Removed more auto-generated minified files.

Ylian Saint-Hilaire committed Dec 23, 2019 at 14:41 UTC 43d80bc9d133681756126783f6e7f17c272fe3aa
14 files changed +2 -9090
.gitignore
+2
@@ -11,6 +11,8 @@
11 [Aa]gents/meshcore.min.js
12 [Pp]ublic/translations/
13 [Vv]iews/translations/
14 +[Pp]ublic/*-min.htm
15 +[Vv]iews/*-min.handlebars
16 meshcentral.db
17 meshcentral.db.json
18 mesherrors.txt
public/player-min.htm deleted
-1
@@ -1 +0,0 @@
1 -<!doctypehtml><html dir=ltr xmlns=http://www.w3.org/1999/xhtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html;charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link type=text/css href=styles/style.css media=screen rel=stylesheet title=CSS><script src=scripts/common-0.0.1.js></script><script src=scripts/agent-desktop-0.0.2.js></script><script src=scripts/amt-desktop-0.0.2.js></script><script src=scripts/amt-terminal-0.0.2.js></script><script src=scripts/zlib.js></script><script src=scripts/zlib-inflate.js></script><script src=scripts/zlib-adler32.js></script><script src=scripts/zlib-crc32.js></script><body style=overflow:hidden;background-color:#000><div id=p11 class=noselect style=overflow:hidden><div id=deskarea0><div id=deskarea1 class=areaHead><div class=toright2><div class=deskareaicon title="Toggle View Mode"onclick=toggleAspectRatio(1)>&#8690;</div></div><div><input id=OpenFileButton type=button value="Open File..."onclick=openfile()> <span id=deskstatus></span></div></div><div id=deskarea2><div class=areaProgress><div id=progressbar></div></div></div><div id=deskarea3x style="max-height:calc(100vh - 54px);height:calc(100vh - 54px)"onclick=togglePause()><div id=bigok style="display:none;left:calc((100vh / 2))"><b>&checkmark;</b></div><div id=bigfail style="display:none;left:calc((100vh / 2))"><b>&#10007;</b></div><div id=metadatadiv style=padding:20px;color:#d3d3d3;text-align:left;display:none></div><div id=DeskParent><canvas id=Desk width=640 height=480></canvas></div><div id=TermParent style=display:none><pre id=Term></pre></div><div id=p11DeskConsoleMsg style=display:none;cursor:pointer;position:absolute;left:30px;top:17px;color:#ff0;background-color:rgba(0,0,0,.6);padding:10px;border-radius:5px onclick=clearConsoleMsg()></div></div><div id=deskarea4 class=areaFoot><div class=toright2><div id=timespan style=padding-top:4px;padding-right:4px>00:00:00</div></div><div>&nbsp; <input id=PlayButton type=button value=Play disabled onclick=play()> <input id=PauseButton type=button value=Pause disabled onclick=pause()> <input id=RestartButton type=button value=Restart disabled onclick=restart()> <select id=PlaySpeed onchange=this.blur()><option value=4>1/4 Speed<option value=2>1/2 Speed<option value=1 selected>Normal Speed<option value=0.5>2x Speed<option value=0.25>4x Speed<option value=0.1>10x Speed</select></div></div></div><div id=dialog class=noselect style=display:none><div id=dialogHeader><div tabindex=0 id=id_dialogclose onclick=setDialogMode() onkeypress='"Enter"==event.key&&setDialogMode()'>&#x2716;</div><div id=id_dialogtitle></div></div><div id=dialogBody><div id=dialog1><div id=id_dialogMessage></div></div><div id=dialog2><div id=id_dialogOptions></div></div></div><div id=idx_dlgButtonBar><input id=idx_dlgCancelButton type=button value=Cancel onclick=dialogclose(0)> <input id=idx_dlgOkButton type=button value=OK onclick=dialogclose(1)><div><input id=idx_dlgDeleteButton type=button value=Delete style=display:none onclick=dialogclose(2)></div></div></div></div><script>var recFile=null,recFilePtr=0,recFileStartTime=0,recFileLastTime=0,recFileEndTime=0,recFileMetadata=null,recFileProtocol=0,agentDesktop=null,amtDesktop=null,playing=!1,readState=0,waitTimer=null,waitTimerArgs=null,deskAspectRatio=0,currentDeltaTimeTotalSec=0;function start(){window.onresize=deskAdjust,document.ondrop=ondrop,document.ondragover=ondragover,document.ondragleave=ondragleave,document.onkeypress=onkeypress,Q("PlaySpeed").value=1,cleanup()}function readNextBlock(l){if(recFilePtr+16>recFile.size)QS("progressbar").width="100%",l(-1);else{var e=new FileReader;e.onload=function(){var e=ReadShort(this.result,0),t=ReadShort(this.result,2),a=ReadInt(this.result,4),r=(ReadInt(this.result,8)<<32)+ReadInt(this.result,12);if(recFilePtr+16+a>recFile.size)QS("progressbar").width="100%",l(-1);else{var i=new FileReader;i.onload=function(){recFilePtr+=16+a,QS("progressbar").width=0==recFileEndTime?Math.floor(recFilePtr/recFile.size*100)+"%":Math.floor((recFileLastTime-recFileStartTime)/(recFileEndTime-recFileStartTime)*100)+"%",l(e,t,r,this.result)},i.readAsBinaryString(recFile.slice(recFilePtr+16,recFilePtr+16+a))}},e.readAsBinaryString(recFile.slice(recFilePtr,recFilePtr+16))}}function readLastBlock(i){if(recFile.size<32)i(-1);else{var e=new FileReader;e.onload=function(){var e=ReadShort(this.result,0),t=ReadShort(this.result,2),a=ReadInt(this.result,4),r=(ReadInt(this.result,8)<<32)+ReadInt(this.result,12);3==e&&16==a&&"MeshCentralMCREC"==this.result.substring(16,32)?i(e,t,r):i(-1)},e.readAsBinaryString(recFile.slice(recFile.size-32,recFile.size))}}function addInfo(e,t){return null==t?"":addInfoNoEsc(e,EscapeHtml(t))}function addInfoNoEsc(e,t){return null==t?"":"<span style=color:gray>"+EscapeHtml(e)+"</span>:&nbsp;<span style=font-size:20px>"+t+"</span><br/>"}function processFirstBlock(e,t,a,r){if(recFileProtocol=0,1==e&&0==t){try{recFileMetadata=JSON.parse(r)}catch(e){return void cleanup()}if(null!=recFileMetadata&&"MeshCentralRelaySession"==recFileMetadata.magic&&1==recFileMetadata.ver){var i="";if(i+=addInfo("Time",recFileMetadata.time),0!=recFileEndTime){var l=Math.floor((recFileEndTime-a)/1e3);i+=addInfo("Duration",format("{0} second{1}",l,1<l?"s":""))}if(i+=addInfo("Username",recFileMetadata.username),i+=addInfo("UserID",recFileMetadata.userid),i+=addInfo("SessionID",recFileMetadata.sessionid),recFileMetadata.ipaddr1&&recFileMetadata.ipaddr2&&(i+=addInfo("Addresses",format("{0} to {1}",recFileMetadata.ipaddr1,recFileMetadata.ipaddr2))),recFileMetadata.devicename&&(i+=addInfo("Device Name",recFileMetadata.devicename)),i+=addInfo("NodeID",recFileMetadata.nodeid),recFileMetadata.protocol){var n=recFileMetadata.protocol;1==n?n="MeshCentral Terminal":2==n?n="MeshCentral Desktop":100==n?n="Intel&reg; AMT WSMAN":101==n&&(n="Intel&reg; AMT Redirection"),i+=addInfoNoEsc("Protocol",n)}QV("DeskParent",!0),QV("TermParent",!1),1==recFileMetadata.protocol?(recFileProtocol=1,i+="<br /><br /><span style=color:gray>Press [space] to play/pause.</span>",QE("PlayButton",!0),QE("PauseButton",!1),QE("RestartButton",!1),recFileStartTime=recFileLastTime=a):2==recFileMetadata.protocol?(recFileProtocol=2,i+="<br /><br /><span style=color:gray>Press [space] to play/pause.</span>",QE("PlayButton",!0),QE("PauseButton",!1),QE("RestartButton",!1),recFileStartTime=recFileLastTime=a,(agentDesktop=CreateAgentRemoteDesktop("Desk")).onScreenSizeChange=deskAdjust,agentDesktop.State=3,deskAdjust()):101==recFileMetadata.protocol&&(recFileProtocol=101,i+="<br /><br /><span style=color:gray>Press [space] to play/pause.</span>",QE("PlayButton",!0),QE("PauseButton",!1),QE("RestartButton",!1),recFileStartTime=recFileLastTime=a,(amtDesktop=CreateAmtRemoteDesktop("Desk")).onScreenSizeChange=deskAdjust,amtDesktop.State=3,amtDesktop.Start(),deskAdjust()),QV("metadatadiv",!0),QH("metadatadiv",i),QH("deskstatus",recFile.name)}else cleanup()}else cleanup()}function processBlock(e,t,a,r){if(e<0)pause();else{var i=Math.round((a-recFileLastTime)*parseFloat(Q("PlaySpeed").value));i<5?processBlockEx(e,t,a,r):(waitTimerArgs=[e,t,a,r],waitTimer=setTimeout(function(){waitTimer=null,processBlockEx(waitTimerArgs[0],waitTimerArgs[1],waitTimerArgs[2],waitTimerArgs[3])},i))}}function processBlockEx(e,t,a,r){if(0!=playing){var i=0!=(1&t),l=0!=(2&t),n=Math.floor((a-recFileStartTime)/1e3);if(currentDeltaTimeTotalSec!=n){currentDeltaTimeTotalSec=n;var o=Math.floor(n/3600);n-=3600*o;var s=Math.floor(n/60);n-=60*o;var c=Math.floor(n);QH("timespan",pad2(o)+":"+pad2(s)+":"+pad2(c))}2==e&&i&&!l?1==recFileProtocol?agentTerminal.ProcessData(r):2==recFileProtocol?agentDesktop.ProcessData(r):101==recFileProtocol&&(0==readState&&"4100000000000000"==rstr2hex(r)?(readState=1,8<r.length&&amtDesktop.ProcessData(r.substring(8))):1==readState&&amtDesktop.ProcessData(r)):2==e&&i&&l&&101==recFileProtocol&&"0000000008080001000700070003050200000000"==rstr2hex(r)&&(amtDesktop.bpp=1),recFileLastTime=a,playing&&readNextBlock(processBlock)}}function cleanup(){recFilePtr=0,playing=!1,(recFileMetadata=recFile=null)!=agentDesktop&&(agentDesktop.Canvas.clearRect(0,0,agentDesktop.CanvasId.width,agentDesktop.CanvasId.height),agentDesktop=null),null!=amtDesktop&&(amtDesktop.canvas.clearRect(0,0,amtDesktop.CanvasId.width,amtDesktop.CanvasId.height),amtDesktop=null),recFileEndTime=currentDeltaTimeTotalSec=readState=0,(agentTerminal=waitTimerArgs=null)!=waitTimer&&(clearTimeout(waitTimer),waitTimer=null),QH("deskstatus",""),QE("PlayButton",!1),QE("PauseButton",!1),QE("RestartButton",!1),QS("progressbar").width="0px",QH("timespan","00:00:00"),QV("metadatadiv",!0),QH("metadatadiv",'<span style="font-family:Arial,Helvetica Neue,Helvetica,sans-serif;font-size:28px">MeshCentral Session Player</span><br /><br /><span style=color:gray>Drag & drop a .mcrec file or click "Open File..."</span>'),QV("DeskParent",!0),QV("TermParent",!1)}function ondrop(e){if(haltEvent(e),QV("bigfail",!1),QV("bigok",!1),null!=e.dataTransfer){var t=[];for(var a in e.dataTransfer.files)null!=e.dataTransfer.files[a].type&&null!=e.dataTransfer.files[a].size&&0!=e.dataTransfer.files[a].size&&e.dataTransfer.files[a].name.endsWith(".mcrec")&&t.push(e.dataTransfer.files[a]);0!=t.length&&(cleanup(),recFile=t[0],recFilePtr=0,readNextBlock(processFirstBlock),readLastBlock(function(e,t,a){recFileEndTime=3==e?a:0}))}}var xxdialogMode,xxdialogFunc,xxdialogButtons,xxdialogTag,dragtimer=null;function ondragover(e){haltEvent(e),null!=dragtimer&&(clearTimeout(dragtimer),dragtimer=null);QV("bigok",!0),QV("bigfail",!1)}function ondragleave(e){haltEvent(e),dragtimer=setTimeout(function(){QV("bigfail",!1),QV("bigok",!1),dragtimer=null},10)}function onkeypress(e){xxdialogMode||(" "==e.key&&(togglePause(),haltEvent(e)),"1"==e.key&&(Q("PlaySpeed").value=4,haltEvent(e)),"2"==e.key&&(Q("PlaySpeed").value=2,haltEvent(e)),"3"==e.key&&(Q("PlaySpeed").value=1,haltEvent(e)),"4"==e.key&&(Q("PlaySpeed").value=.5,haltEvent(e)),"5"==e.key&&(Q("PlaySpeed").value=.25,haltEvent(e)),"6"==e.key&&(Q("PlaySpeed").value=.1,haltEvent(e)),"0"==e.key&&(pause(),restart(),haltEvent(e)))}function openfile(){setDialogMode(2,"Open File...",3,openfileEx,'<input type=file name=files id=p2fileinput style=width:100% accept=".mcrec" onchange="openfileChanged()" />'),QE("idx_dlgOkButton",!1)}function openfileEx(){var e=Q("p2fileinput").files;if(null!=e){var t=[];for(var a in e)null!=e[a].type&&null!=e[a].size&&0!=e[a].size&&e[a].name.endsWith(".mcrec")&&t.push(e[a])}0!=t.length&&(cleanup(),recFile=t[0],recFilePtr=0,readNextBlock(processFirstBlock),readLastBlock(function(e,t,a){recFileEndTime=3==e?a:0}),Q("OpenFileButton").blur())}function openfileChanged(){var e=Q("p2fileinput").files;if(null!=e){var t=[];for(var a in e)null!=e[a].type&&null!=e[a].size&&0!=e[a].size&&e[a].name.endsWith(".mcrec")&&t.push(e[a])}QE("idx_dlgOkButton",1==t.length)}function togglePause(){return null!=recFile&&(1==playing?pause():recFilePtr!=recFile.size&&play()),!1}function play(){Q("PlayButton").blur(),1!=playing&&0!=recFileProtocol&&(playing=!0,QV("metadatadiv",!1),QE("PlayButton",!1),QE("PauseButton",!0),QE("RestartButton",!1),1==recFileProtocol&&null==agentTerminal&&(QV("DeskParent",!1),QV("TermParent",!0),agentTerminal=CreateAmtRemoteTerminal("Term",{}),agentTerminal.State=3),readNextBlock(processBlock))}function pause(){Q("PauseButton").blur(),0!=playing&&(playing=!1,QE("PlayButton",recFilePtr!=recFile.size),QE("PauseButton",!1),QE("RestartButton",0!=recFilePtr),null!=waitTimer&&(clearTimeout(waitTimer),waitTimer=null,processBlockEx(waitTimerArgs[0],waitTimerArgs[1],waitTimerArgs[2],waitTimerArgs[3]),waitTimerArgs=null))}function restart(){Q("RestartButton").blur(),1!=playing&&(currentDeltaTimeTotalSec=readState=recFilePtr=0,QV("metadatadiv",!0),QE("PlayButton",!0),QE("PauseButton",!1),QE("RestartButton",!1),QS("progressbar").width="0px",QH("timespan","00:00:00"),QV("DeskParent",!0),QV("TermParent",!1),agentDesktop?agentDesktop.Canvas.clearRect(0,0,agentDesktop.CanvasId.width,agentDesktop.CanvasId.height):amtDesktop?(amtDesktop.canvas.clearRect(0,0,amtDesktop.CanvasId.width,amtDesktop.CanvasId.height),(amtDesktop=CreateAmtRemoteDesktop("Desk")).onScreenSizeChange=deskAdjust,amtDesktop.State=3,amtDesktop.Start()):agentTerminal=agentTerminal&&null)}function clearConsoleMsg(){QH("p11DeskConsoleMsg","")}function toggleAspectRatio(e){1===e&&(deskAspectRatio=(deskAspectRatio+1)%3),deskAdjust()}function deskAdjust(){var e=Q("DeskParent").clientHeight,t=Q("DeskParent").clientWidth,a=Q("Desk").height,r=Q("Desk").width;if(2==deskAspectRatio)QS("Desk")["margin-top"]=null,QS("Desk").height="100%",QS("Desk").width="100%",QS("DeskParent").overflow="hidden";else if(1==deskAspectRatio)QS("Desk")["margin-top"]="0px",QS("Desk").height=a+"px",QS("Desk").width=r+"px",QS("DeskParent").overflow="scroll";else{if(a/r<e/t){var i=a*t/r+"px";QS("Desk").height=i,QS("Desk").width="100%"}else{var l=r*e/a+"px";QS("Desk").height="100%",QS("Desk").width=l}QS("Desk")["margin-top"]=null,QS("DeskParent").overflow="hidden"}}var xxcurrentView=-1;function setDialogMode(e,t,a,r,i,l){xxdialogMode=e,xxdialogFunc=r,xxdialogButtons=a,xxdialogTag=l,QE("idx_dlgOkButton",!0),QV("idx_dlgOkButton",1&a),QV("idx_dlgCancelButton",2&a),QV("id_dialogclose",2&a||8&a),QV("idx_dlgDeleteButton",4&a),QV("idx_dlgButtonBar",7&a),t&&QH("id_dialogtitle",t);for(var n=1;n<3;n++)QV("dialog"+n,n==e);QV("dialog",e),i&&(2==e?QH("id_dialogOptions",i):QH("id_dialogMessage",i))}function dialogclose(e){var t=xxdialogFunc,a=xxdialogButtons,r=xxdialogTag;setDialogMode(),(8&a||e)&&t&&t(e,r)}function messagebox(e,t){setSessionActivity(),QH("id_dialogMessage",t),setDialogMode(1,e,1)}function statusbox(e,t){setSessionActivity(),QH("id_dialogMessage",t),setDialogMode(1,e)}function haltEvent(e){return e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation(),!1}function pad2(e){var t="00"+e;return t.substr(t.length-2)}function format(e){var a=Array.prototype.slice.call(arguments,1);return e.replace(/{(\d+)}/g,function(e,t){return void 0!==a[t]?a[t]:e})}start()</script>
\ No newline at end of file
views/agentinvite-min.handlebars deleted
-1
@@ -1 +0,0 @@
1 -<!doctypehtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html; charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link type=text/css href=styles/style.css media=screen rel=stylesheet title=CSS><script src=scripts/common-0.0.1.js></script><title>{{{title}}} - Agent Installation</title><style>.tab{overflow:hidden;border:1px solid #ccc;background-color:#f1f1f1}.tab button{background-color:inherit;float:left;border:none;outline:0;cursor:pointer;padding:14px 16px;transition:.3s}.tab button:hover{background-color:#ddd}.tab button.active{background-color:#8f8}.tabcontent{display:none;padding:6px 12px;border:1px solid #ccc;border-top:none}</style><body id=body onload='"undefined"!=typeof startup&&startup()'style=display:none;overflow:hidden><div id=container><div id=masthead class=noselect style="background:url(logo.png) 0 0;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden"><div style=float:left>{{{titlehtml}}}</div><div style=float:left;height:66px;color:#c8c8c8;padding-left:14px;padding-top:7px><strong><font style=font-size:46px;font-family:Arial,Helvetica,sans-serif>{{{title1}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px><strong><font style=font-size:14px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div><p id=logoutControl style="color:#fff;font-size:11px;margin:10px 10px 0">{{{logoutControl}}}</div><div id=page_leftbar><div style=height:16px></div></div><div id=topbar class="noselect style3"style=height:24px;position:relative><div id=uiMenuButton title="User interface selection"onclick=showUserInterfaceSelectMenu()>&diams;<div id=uiMenu style=display:none><div id=uiViewButton1 class=uiSelector onclick=userInterfaceSelectMenu(1) title="Left bar interface"><div class=uiSelector1></div></div><div id=uiViewButton2 class=uiSelector onclick=userInterfaceSelectMenu(2) title="Top bar interface"><div class=uiSelector2></div></div><div id=uiViewButton3 class=uiSelector onclick=userInterfaceSelectMenu(3) title="Fixed width interface"><div class=uiSelector3></div></div><div id=uiViewButton4 class=uiSelector onclick=toggleNightMode() title="Toggle night mode"><div class=uiSelector4></div></div></div></div></div><div id=column_l style="max-height:calc(100vh - 135px);overflow-y:auto"><h1>Remote Agent Installation<span id=groupname></span></h1><p>You have been invited to install a software that will allow a remote operator to fully access your computer remotely including the desktop and files. Only follow the instructions below if this invitation was expected and you know who will be accessing your computer. Selecting your operation system and follow the instructions below.<div><div class=tab><button id=twintab64 class=tablinks onclick='openTab(event,"wintab64")'>Windows 64bit</button> <button id=twintab32 class=tablinks onclick='openTab(event,"wintab32")'>Windows 32bit</button> <button id=tlinuxtab class=tablinks onclick='openTab(event,"linuxtab")'>Linux</button> <button id=tmacostab class=tablinks onclick='openTab(event,"macostab")'>MacOS</button></div><div id=wintab64 class=tabcontent style=background-color:#fff;color:#000><h3>Microsoft&trade; Windows 64bit</h3><p><a id=win64url>Download the software here</a>, run it and press "Install" or "Connect".<div style=text-align:center><img class=winagent-img src=images/winagent.png></div></div><div id=wintab32 class=tabcontent style=background-color:#fff;color:#000><h3>Microsoft&trade; Windows 32bit</h3><p><a id=win32url>Download the software here</a>, run it and press "Install" or "Connect".<div style=text-align:center><img class=winagent-img src=images/winagent.png></div></div><div id=linuxtab class=tabcontent style=background-color:#fff;color:#000><h3>Linux</h3><p>To install, cut and paste the following command in a root terminal.<div id=linuxinstall style="font-family:courier,'courier new',monospace;margin-left:30px"></div><input type=button value="Copy to clipboard"style=margin-left:30px;margin-top:4px onclick=copyToClipLinuxInstall()><p>To uninstall, cut and paste the following command as root.<div id=unlinuxinstall style="font-family:courier,'courier new',monospace;margin-left:30px"></div><input type=button value="Copy to clipboard"style=margin-left:30px;margin-top:4px onclick=copyToClipLinuxUnInstall()><br><br></div><div id=macostab class=tabcontent style=background-color:#fff;color:#000><h3>Apple&trade; MacOS</h3><p><a id=macosurl>Download the installer here</a>, right click on it or press "control" and click on the file. Then select "Open" and follow the instructions.<div style=text-align:center><img src=images/macosagent.png></div></div></div></div><div id=footer><table cellpadding=0 cellspacing=10 style=width:100%><tr><td style=text-align:left><td style=text-align:right></table></div></div><script>"use strict";var linuxInstall,linuxUnInstall,uiMode=parseInt(getstore("uiMode",1)),webPageStackMenu=!1,webPageFullScreen=!0,nightMode="1"==getstore("_nightMode","0"),domain="{{{domain}}}",domainUrl="{{{domainurl}}}",meshid="{{{meshid}}}",serverPort="{{{serverport}}}",serverHttps="{{{serverhttps}}}",serverNoProxy="{{{servernoproxy}}}",installFlags="{{{installflags}}}",groupName=decodeURIComponent("{{{meshname}}}");function showUserInterfaceSelectMenu(){Q("uiViewButton1").classList.remove("uiSelectorSel"),Q("uiViewButton2").classList.remove("uiSelectorSel"),Q("uiViewButton3").classList.remove("uiSelectorSel"),Q("uiViewButton4").classList.remove("uiSelectorSel");try{Q("uiViewButton"+uiMode).classList.add("uiSelectorSel")}catch(e){}QV("uiMenu","none"==QS("uiMenu").display),nightMode&&Q("uiViewButton4").classList.add("uiSelectorSel")}function userInterfaceSelectMenu(e){e&&putstore("uiMode",uiMode=e),webPageFullScreen=uiMode<3,webPageStackMenu=!0,toggleFullScreen(0),toggleStackMenu(0),QC("column_l").add("room4submenu")}function toggleNightMode(){(nightMode=!nightMode)?QC("body").add("night"):QC("body").remove("night"),putstore("_nightMode",nightMode?"1":"0")}function toggleFullScreen(e){1===e&&putstore("webPageFullScreen",webPageFullScreen=!webPageFullScreen);0==webPageFullScreen?(QC("body").remove("menu_stack"),QC("body").remove("fullscreen"),QC("body").remove("arg_hide")):QC("body").add("fullscreen"),QV("body",!0)}function toggleStackMenu(e){1==webPageFullScreen&&(1===e&&putstore("webPageStackMenu",webPageStackMenu=!webPageStackMenu),0==webPageStackMenu?QC("body").remove("menu_stack"):QC("body").add("menu_stack"))}function putstore(e,t){try{if("undefined"==typeof localStorage)return;localStorage.setItem(e,t)}catch(e){}}function getstore(e,t){try{if("undefined"==typeof localStorage)return t;var n=localStorage.getItem(e);return null==n||null==n?t:n}catch(e){return t}}function openTab(e,t){var n,s,l;for(s=document.getElementsByClassName("tabcontent"),n=0;n<s.length;n++)s[n].style.display="none";for(l=document.getElementsByClassName("tablinks"),n=0;n<l.length;n++)l[n].className=l[n].className.replace(" active","");document.getElementById(t).style.display="block",null!=e?e.currentTarget.className+=" active":document.getElementById("t"+t).className+=" active"}function setup(){var e=window.location.hostname,t=domainUrl.substring(0,domainUrl.length-1),n="meshagents?id=4&meshid="+meshid;if(0!=installFlags&&(n+="&installflags="+installFlags),Q("win64url").href=n,n="meshagents?id=3&meshid="+meshid,0!=installFlags&&(n+="&installflags="+installFlags),Q("win32url").href=n,n="meshosxagent?id=16&meshid="+meshid,Q("macosurl").href=n,1==serverHttps){var s=443==serverPort?"":":"+serverPort;linuxUnInstall=0==serverNoProxy?(linuxInstall="(wget https://"+e+s+domainUrl+'meshagents?script=1 --no-check-certificate -O ./meshinstall.sh || wget https://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh https://'+e+s+t+" '"+meshid+"'\r\n","(wget https://"+e+s+domainUrl+'meshagents?script=1 --no-check-certificate -O ./meshinstall.sh || wget https://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n'):(linuxInstall="wget https://"+e+s+domainUrl+"meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh https://"+e+s+t+" '"+meshid+"'\r\n","wget https://"+e+s+domainUrl+"meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n")}else{s=80==serverPort?"":":"+serverPort;linuxUnInstall=0==serverNoProxy?(linuxInstall="(wget http://"+e+s+domainUrl+'meshagents?script=1 -O ./meshinstall.sh || wget http://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh http://'+e+s+t+" '"+meshid+"'\r\n","(wget http://"+e+s+domainUrl+'meshagents?script=1 -O ./meshinstall.sh || wget http://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n'):(linuxInstall="wget http://"+e+s+domainUrl+"meshagents?script=1 --no-proxy -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh http://"+e+s+t+" '"+meshid+"'\r\n","wget http://"+e+s+domainUrl+"meshagents?script=1 --no-proxy -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n")}QH("linuxinstall",linuxInstall),QH("unlinuxinstall",linuxUnInstall),0<=navigator.userAgent.indexOf("Win64")?openTab(null,"wintab64"):0<=navigator.userAgent.indexOf("Windows")?openTab(null,"wintab32"):0<=navigator.userAgent.indexOf("Linux")?openTab(null,"linuxtab"):0<=navigator.userAgent.indexOf("Macintosh")?openTab(null,"macostab"):openTab(null,"wintab64")}function copyToClipLinuxInstall(){copyTextToClip(linuxInstall)}function copyToClipLinuxUnInstall(){copyTextToClip(linuxUnInstall)}function copyTextToClip(e){var t=document.createElement("DIV");t.textContent=e,document.body.appendChild(t),function(e){if(document.selection)(t=document.body.createTextRange()).moveToElementText(e),t.select();else if(window.getSelection){var t;(t=document.createRange()).selectNode(e),window.getSelection().removeAllRanges(),window.getSelection().addRange(t)}}(t),document.execCommand("copy"),t.remove()}""!=groupName&&QH("groupname"," for "+groupName),userInterfaceSelectMenu(),setup()</script>
\ No newline at end of file
views/default-min.handlebars deleted
-8995
@@ -1,8995 +0,0 @@
1 -<!doctypehtml><html dir=ltr xmlns=http://www.w3.org/1999/xhtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html;charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link rel="shortcut icon"type=image/x-icon href={{{domainurl}}}favicon.ico><link keeplink=1 type=text/css href=styles/style.css media=screen rel=stylesheet title=CSS><link type=text/css href=styles/ol.css media=screen rel=stylesheet title=CSS><link type=text/css href=styles/ol3-contextmenu.min.css media=screen rel=stylesheet title=CSS><script src=scripts/common-0.0.1.js></script><script src=scripts/meshcentral.js></script><script src=scripts/amt-0.2.0.js></script><script src=scripts/amt-wsman-0.2.0.js></script><script src=scripts/amt-desktop-0.0.2.js></script><script src=scripts/amt-terminal-0.0.2.js></script><script src=scripts/zlib.js></script><script src=scripts/zlib-inflate.js></script><script src=scripts/zlib-adler32.js></script><script src=scripts/zlib-crc32.js></script><script src=scripts/amt-redir-ws-0.1.0.js></script><script src=scripts/amt-wsman-ws-0.2.0.js></script><script src=scripts/agent-redir-ws-0.1.1.js></script><script src=scripts/agent-redir-rtc-0.1.0.js></script><script src=scripts/agent-desktop-0.0.2.js></script><script src=scripts/qrcode.min.js></script><script keeplink=1 src=scripts/u2f-api.js></script><script keeplink=1 src=scripts/charts.js></script><script keeplink=1 src=scripts/filesaver.js></script>{{{StartGeoLocation}}}<script keeplink=1 src=scripts/ol.js></script><script keeplink=1 src=scripts/ol3-contextmenu.js></script>{{{EndGeoLocation}}}<title>{{{title}}}</title><body id=body onload='"undefined"!=typeof startup&&startup()'oncontextmenu=handleContextMenu(event) style=display:none;min-width:495px><div id=contextMenu class="contextMenu noselect"style=display:none><div id=cxinfo class=cmtext onclick=cmaction(1,event)><b>Information</b></div><div id=cxdesktop class=cmtext onclick=cmaction(3,event)>Desktop</div><div id=cxterminal class=cmtext onclick=cmaction(2,event)>Terminal</div><div id=cxfiles class=cmtext onclick=cmaction(4,event)>Files</div><div id=cxevents class=cmtext onclick=cmaction(5,event)>Events</div><div id=cxconsole class=cmtext onclick=cmaction(6,event)>Console</div><hr id=cxmgroupsplit><div id=cxmdesktop class=cmtext onclick=cmaction(7,event) style=display:none>Multi-Desktop</div></div><div id=meshContextMenu class="contextMenu noselect"style=display:none;min-width:0><div id=cxselectall class=cmtext onclick=cmmeshaction(1,event)>Select All</div><div id=cxselectnone class=cmtext onclick=cmmeshaction(2,event)>Select None</div></div><div id=termShellContextMenu class="contextMenu noselect"style=display:none;min-width:0><div id=cxtermnorm class=cmtext onclick=cmtermaction(1,event)><b>Admin Shell</b></div><div id=cxtermps class=cmtext onclick=cmtermaction(6,event)>Admin PowerShell</div><div id=cxtermunorm class=cmtext onclick=cmtermaction(8,event)>User Shell</div><div id=cxtermups class=cmtext onclick=cmtermaction(9,event)>User PowerShell</div></div><div id=termShellContextMenuLinux class="contextMenu noselect"style=display:none;min-width:0><div id=cxtermnorm class=cmtext onclick=cmtermaction(1,event)><b>Root Shell</b></div><div id=cxtermps class=cmtext onclick=cmtermaction(8,event)>User Shell</div></div><div id=container><div id=notifiyBox class=notifiyBox style=display:none></div><div id=masthead class=noselect><div style=float:left>{{{titlehtml}}}</div><div class=title>{{{title1}}}</div><div class=title2>{{{title2}}}</div><div style=float:right><div id=notificationCount onclick=clickNotificationIcon() class=unselectable style=display:none title="Click to view current notifications">0</div></div><p id=logoutControl><span id=logoutControlSpan style=color:#fff></span><span id=idleTimeoutNotify style=color:#ff0></span></div><div id=page_leftbar><div style=height:16px></div><div id=LeftMenuMyDevices tabindex=0 class="lbbutton lbbuttonsel"title="My Devices"onclick=go(1,event) onkeypress='"Enter"==event.key&&go(1)'><div class=lb2></div></div><div id=LeftMenuMyAccount tabindex=0 class=lbbutton title="My Account"onclick=go(2,event) onkeypress='"Enter"==event.key&&go(2)'><div class=lb1></div></div><div id=LeftMenuMyEvents tabindex=0 class=lbbutton title="My Events"onclick=go(3,event) onkeypress='"Enter"==event.key&&go(3)'><div class=lb3></div></div><div id=LeftMenuMyFiles tabindex=0 class=lbbutton style=display:none title="My Files"onclick=go(5,event) onkeypress='"Enter"==event.key&&go(5)'><div class=lb4></div></div><div id=LeftMenuMyUsers tabindex=0 class=lbbutton style=display:none title="My Users"onclick=go(4,event) onkeypress='"Enter"==event.key&&go(4)'><div class=lb5></div></div><div id=LeftMenuMyServer tabindex=0 class=lbbutton style=display:none title="My Server"onclick=go(6,event) onkeypress='"Enter"==event.key&&go(6)'><div class=lb6></div></div></div><div id=topbar class=noselect><div><div style=position:relative><span id=logoutControlSpan2 style=color:#fff></span><div tabindex=0 id=uiMenuButton title="User interface selection"onclick=showUserInterfaceSelectMenu() onkeypress='"Enter"==event.key&&showUserInterfaceSelectMenu()'>&diams;<div id=uiMenu style=display:none><div tabindex=0 id=uiViewButton1 class=uiSelector onclick=userInterfaceSelectMenu(1) title="Left bar interface"onkeypress='"Enter"==event.key&&userInterfaceSelectMenu(1)'><div class=uiSelector1></div></div><div tabindex=0 id=uiViewButton2 class=uiSelector onclick=userInterfaceSelectMenu(2) title="Top bar interface"onkeypress='"Enter"==event.key&&userInterfaceSelectMenu(2)'><div class=uiSelector2></div></div><div tabindex=0 id=uiViewButton3 class=uiSelector onclick=userInterfaceSelectMenu(3) title="Fixed width interface"onkeypress='"Enter"==event.key&&userInterfaceSelectMenu(3)'><div class=uiSelector3></div></div><div tabindex=0 id=uiViewButton4 class=uiSelector onclick=toggleNightMode() title="Toggle night mode"onkeypress='"Enter"==event.key&&toggleNightMode()'><div class=uiSelector4></div></div><div tabindex=0 id=uiViewButton5 class=uiSelector onclick=toggleFooterBarMode() title="Toggle footer bar"onkeypress='"Enter"==event.key&&toggleFooterBarMode()'><div class=uiSelector5></div></div></div></div><table id=MainMenuSpan cellpadding=0 cellspacing=0 class=style1><tr><td tabindex=0 id=MainMenuMyDevices class="topbar_td style3x"onclick=go(1,event) onkeypress='"Enter"==event.key&&go(1)'>My Devices<td tabindex=0 id=MainMenuMyAccount class="topbar_td style3x"onclick=go(2,event) onkeypress='"Enter"==event.key&&go(2)'>My Account<td tabindex=0 id=MainMenuMyEvents class="topbar_td style3x"onclick=go(3,event) onkeypress='"Enter"==event.key&&go(3)'>My Events<td tabindex=0 id=MainMenuMyFiles class="topbar_td style3x"onclick=go(5,event) onkeypress='"Enter"==event.key&&go(5)'>My Files<td tabindex=0 id=MainMenuMyUsers class="topbar_td style3x"onclick=go(4,event) onkeypress='"Enter"==event.key&&go(4)'>My Users<td tabindex=0 id=MainMenuMyServer class="topbar_td style3x"onclick=go(6,event) onkeypress='"Enter"==event.key&&go(6)'>My Server<td class="topbar_td_end style3">&nbsp;</table><div id=MainSubMenuSpan style=display:none><table id=MainSubMenu cellpadding=0 cellspacing=0 class=style1><tr><td tabindex=0 id=MainDev class="topbar_td style3x"onclick=go(10,event) onkeypress='"Enter"==event.key&&go(10)'>General<td tabindex=0 id=MainDevDesktop class="topbar_td style3x"onclick=go(11,event) onkeypress='"Enter"==event.key&&go(11)'>Desktop<td tabindex=0 id=MainDevTerminal class="topbar_td style3x"onclick=go(12,event) onkeypress='"Enter"==event.key&&go(12)'>Terminal<td tabindex=0 id=MainDevFiles class="topbar_td style3x"onclick=go(13,event) onkeypress='"Enter"==event.key&&go(13)'>Files<td tabindex=0 id=MainDevEvents class="topbar_td style3x"onclick=go(16,event) onkeypress='"Enter"==event.key&&go(16)'>Events<td tabindex=0 id=MainDevInfo class="topbar_td style3x"onclick=go(17,event) onkeypress='"Enter"==event.key&&go(17)'>Details<td tabindex=0 id=MainDevAmt class="topbar_td style3x"onclick=go(14,event) onkeypress='"Enter"==event.key&&go(14)'>Intel&reg; AMT<td tabindex=0 id=MainDevConsole class="topbar_td style3x"onclick=go(15,event) onkeypress='"Enter"==event.key&&go(15)'>Console<td tabindex=0 id=MainDevPlugins class="topbar_td style3x"onclick=go(19,event) onkeypress='"Enter"==event.key&&go(19)'>Plugins<td class="topbar_td_end style3">&nbsp;</table></div><div id=MeshSubMenuSpan style=display:none><table id=MeshSubMenu cellpadding=0 cellspacing=0 class=style1><tr><td tabindex=0 id=MeshGeneral class="topbar_td style3x"onclick=go(20,event) onkeypress='"Enter"==event.key&&go(20)'>General<td tabindex=0 id=MeshSummary class="topbar_td style3x"onclick=go(21,event) onkeypress='"Enter"==event.key&&go(21)'>Summary<td class="topbar_td_end style3">&nbsp;</table></div><div id=UserSubMenuSpan style=display:none><table id=UserSubMenu cellpadding=0 cellspacing=0 class=style1><tr><td tabindex=0 id=UserGeneral class="topbar_td style3x"onclick=go(30,event) onkeypress='"Enter"==event.key&&go(30)'>General<td tabindex=0 id=UserEvents class="topbar_td style3x"onclick=go(31,event) onkeypress='"Enter"==event.key&&go(31)'>Events<td class="topbar_td_end style3">&nbsp;</table></div><div id=ServerSubMenuSpan style=display:none><table id=ServerSubMenu cellpadding=0 cellspacing=0 class=style1><tr><td tabindex=0 id=ServerGeneral class="topbar_td style3x"onclick=go(6,event) onkeypress='"Enter"==event.key&&go(6)'>General<td tabindex=0 id=ServerStats class="topbar_td style3x"onclick=go(40,event) onkeypress='"Enter"==event.key&&go(40)'>Stats<td tabindex=0 id=ServerConsole class="topbar_td style3x"onclick=go(115,event) onkeypress='"Enter"==event.key&&go(115)'>Console<td tabindex=0 id=ServerTrace class="topbar_td style3x"onclick=go(41,event) onkeypress='"Enter"==event.key&&go(41)'>Trace<td tabindex=0 id=ServerPlugins class="topbar_td style3x"onclick=go(42,event) onkeypress='"Enter"==event.key&&go(42)'>Plugins<td class="topbar_td_end style3">&nbsp;</table></div><div id=UserDummyMenuSpan><table id=UserDummyMenu cellpadding=0 cellspacing=0 class=style1><tr><td class=style3>&nbsp;</table></div></div></div></div><div id=column_l><div id=p0 style=display:none><div id=p0message><span id=p0span>Server disconnected</span>,<href onclick=reload() style=cursor:pointer><u>click to reconnect</u></href>.</div></div><div id=p1 style=display:none><div id=p1title><div style=display:none id=devListToolbarViewIcons><div tabindex=0 id=devViewButton1 class=viewSelector onclick=onDeviceViewChange(1) onkeypress='"Enter"==event.key&&onDeviceViewChange(1)'title=Columns><div class=viewSelector2></div></div><div tabindex=0 id=devViewButton2 class=viewSelector onclick=onDeviceViewChange(2) onkeypress='"Enter"==event.key&&onDeviceViewChange(2)'title=List><div class=viewSelector1></div></div><div tabindex=0 id=devViewButton3 class=viewSelector onclick=onDeviceViewChange(3) onkeypress='"Enter"==event.key&&onDeviceViewChange(3)'title=Desktops><div class=viewSelector3></div></div><div tabindex=0 id=devViewButton4 class=viewSelector onclick=onDeviceViewChange(4) onkeypress='"Enter"==event.key&&onDeviceViewChange(4)'title=Map style=display:none><div class=viewSelector4></div></div></div><div><h1>My Devices</h1></div></div><table id=devListToolbarSpan class=noselect><tr><td class=h1><td id=devListToolbar class=style14 style=display:none>&nbsp;&nbsp;<input type=button id=SelectAllButton onclick=selectallButtonFunction() value="Select All">&nbsp; <input type=button id=GroupActionButton disabled value="Group Action"onclick=groupActionFunction()>&nbsp; <input id=SearchInput placeholder=Filter onchange=masterUpdate(5) onkeyup=masterUpdate(5) autocomplete=off onfocus=onSearchFocus(1) onblur=onSearchFocus(0)>&nbsp; <label><input type=checkbox id=RealNameCheckBox onclick=onRealNameCheckBox()><span title="Show devices operating system name">OS Name</span></label><td id=kvmListToolbar class=style14 style=display:none>&nbsp;&nbsp;<input type=button onclick=connectAllKvmFunction() value="Connect All">&nbsp; <input type=button onclick=disconnectAllKvmFunction() value="Disconnect All">&nbsp; <label><input type=checkbox id=autoConnectDesktopCheckbox onclick=autoConnectDesktops(event) title="Automatic connect">Auto&nbsp;</label> <input type=button onclick=showMultiDesktopSettings() value=Settings>&nbsp;<td id=devMapToolbar class=style14 style=display:none>&nbsp;&nbsp;<input id=mapSearchLocation placeholder="Search Location"onfocus=onMapSearchFocus(1) onblur=onMapSearchFocus(0)> <input type=button value=Search title="Search for location"onclick=getSearchLocation()> <input type=button id=refreshmap title="Reset map view"value=Reset onclick=refreshMap(!1,!0)><td class=auto-style1 style=height:100%><div style=display:none id=devListToolbarView>View <select id=viewselect onchange=onDeviceViewChange()><option value=1>Columns<option value=2>List<option value=3>Desktops<option id=viewselectmapoption value=4 style=display:none>Map</select></div><div style=display:none id=devListToolbarSort>Sort <select id=sortselect onchange=masterUpdate(6)><option>Group<option>Power<option>Device<option>Tags</select> &nbsp;</div><div style=display:none id=devListToolbarSize>Size <select id=sizeselect onchange=onDeviceViewChange()><option value=0>Small<option value=1>Medium<option value=2>Large</select> &nbsp;</div><td class=h2></table><div id=NoMeshesPanel style=display:none><table><tr><td valign=top style=width:50px><img src=images/info.png><td><div id=getStarted1>To get started, <a href=# onclick="return account_createMesh()"><strong>click here to create a device group</strong></a>.</div><div id=getStarted2>No device groups.</div></table></div><div id=xdevices class=noselect style=display:none></div><div id=xdevicesmap style=display:none><div id=xmapSearchResultsDlg style=display:none><div id=xmapSearchResultsBck><div id=xmapSearchClose onclick=mapCloseSearchWindow()><b>X</b></div><div style=padding:5px>Location Results</div><div style=width:100%;margin:6px></div></div><div id=xmapSearchResults style=margin:6px></div></div></div><div id=xmap-info-window></div></div><div id=p2 style=display:none><div id=p2title><h1>My Account</h1></div><img id=p2AccountImage alt=""src=images/clipboard-128.png><div id=p2AccountSecurity style=display:none><p><strong>Account security</strong><div style=margin-left:25px><div id=manageAuthApp><div class=p2AccountActions><span id=authAppSetupCheck><strong>&#x2713;</strong></span></div><span><a href=# onclick="return account_manageAuthApp()">Manage authenticator app</a><br></span></div><div id=manageHardwareOtp><div class=p2AccountActions><span id=authKeySetupCheck><strong>&#x2713;</strong></span></div><span><a href=# onclick="return account_manageHardwareOtp(0)">Manage security keys</a><br></span></div><div id=manageOtp><div class=p2AccountActions><span id=authCodesSetupCheck><strong>&#x2713;</strong></span></div><span><a href=# onclick="return account_manageOtp(0)">Manage backup codes</a><br></span></div></div></div><div id=p2AccountActions><p><strong>Account actions</strong><p class=mL><span id=verifyEmailId style=display:none><a href=# onclick="return account_showVerifyEmail()">Verify email</a><br></span><span id=accountEnableNotificationsSpan style=display:none><a href=# onclick="return account_enableNotifications()">Enable web notifications</a><br></span><a href=# onclick="return account_showLocalizationSettings()">Localization Settings</a><br><a href=# onclick="return account_showAccountNotifySettings()">Notification Settings</a><br><span id=p2AccountPassActions><span id=accountChangeEmailAddressSpan style=display:none><a href=# onclick="return account_showChangeEmail()">Change email address</a><br></span><a href=# onclick="return account_showChangePassword()">Change password</a><span id=p2nextPasswordUpdateTime></span><br><a href=# onclick="return account_showDeleteAccount()">Delete account</a><br></span></p><br style=clear:both></div><strong>Device Groups</strong> <span id=p2createMeshLink1>( <a href=# onclick="return account_createMesh()"class=newMeshBtn>New</a> )</span><br><br><div id=p2meshes></div><div id=p2noMeshFound style=display:none>No device groups.<span id=p2createMeshLink2> <a href=# onclick="return account_createMesh()"><strong>Get started here!</strong></a></span></div><br style=clear:both></div><div id=p3 style=display:none><div id=p3title><h1>My Events</h1></div><table class=pTable><tr><td class=h1><td class=auto-style1>Show <select id=p3limitdropdown onchange=refreshEvents()><option value=60>Last 60<option value=120>Last 120<option value=250>Last 250<option value=500>Last 500<option value=1000>Last 1000</select>&nbsp; <a href=# onclick=p3showDownloadEventsDialog(2)><img src=images/link4.png height=10 width=10 title="Download Events"style=cursor:pointer></a>&nbsp;<td class=h2></table><div id=p3events></div></div><div id=p4 style=display:none><div id=p4title><h1>My Users</h1></div><table class=pTable><tr><td class=h1><td class=style14><div style=float:right><input type=button onclick=showUserBroadcastDialog() style=margin-right:6px value=Broadcast> <a href=# onclick=p4downloadUserInfo()><img style=cursor:pointer title="Download user information"src=images/link4.png></a><a href=# onclick=p4batchAccountCreate()><img id=p4UserBatchCreate style=cursor:pointer;display:none title="Batch create many user accounts"src=images/link6.png></a></div><div><input id=UserNewAccountButton type=button style=margin-left:6px onclick=showCreateNewAccountDialog() value="New Account..."> <input id=UserSearchInput style=width:120px;margin-left:6px placeholder=Filter onchange=onUserSearchInputChanged() onkeyup=onUserSearchInputChanged() autocomplete=off onfocus=onUserSearchFocus(1) onblur=onUserSearchFocus(0)></div><td class=h2></table><div id=p3users></div></div><div id=p5 style=display:none><div id=p5title><h1>My Files</h1></div><table id=p5toolbar cellpadding=0 cellspacing=0><tr><td id=p5filehead valign=bottom><div id=p5rightOfButtons></div><div><input type=button id=p5FolderUp disabled onclick="return p5folderup()"value=Up>&nbsp; <input type=button id=p5SelectAllButton disabled onclick=p5selectallfile() value="Select All">&nbsp; <input type=button id=p5RenameFileButton disabled value=Rename onclick=p5renamefile()>&nbsp; <input type=button id=p5DeleteFileButton disabled value=Delete onclick=p5deletefile()>&nbsp; <input type=button id=p5NewFolderButton disabled value="New Folder"onclick=p5createfolder()>&nbsp; <input type=button id=p5UploadButton disabled value=Upload onclick=p5uploadFile()>&nbsp; <input type=button id=p5CutButton disabled value=Cut onclick=p5copyFile(1)>&nbsp; <input type=button id=p5CopyButton disabled value=Copy onclick=p5copyFile(0)>&nbsp; <input type=button id=p5PasteButton disabled value=Paste onclick=p5pasteFile()>&nbsp;</div><tr><td id=p5filesubhead><div style=float:right><select id=p5sortdropdown onchange=updateFiles()><option value=1 selected>Sort by name<option value=2>Sort by size<option value=3>Sort by date<option value=4>Descend by name<option value=5>Descend by size<option value=6>Descend by date</select></div><div>&nbsp;&nbsp;<span id=p5currentpath></span></div></table><div id=p5filetable><div id=p5PublicShare><div>These files are shared publicly, click "link" to get public url.</div></div><div id=bigok style=display:none><b>&checkmark;</b></div><div id=bigfail style=display:none><b>&#10007;</b></div><span id=p5files></span></div><table id=p5toolbarBottom style=width:100% cellpadding=0 cellspacing=0><tr><td class=style6>&nbsp;<span id=p5bottomstatus></span></table></div><div id=p6 style=display:none><div id=p6title><img id=MainMeshImage src=serverpic.ashx><h1>My Server</h1></div><div id=p2ServerActions><p><strong>Server actions</strong><div class=mL><div id=p2ServerActionsBackup><a href={{{domainurl}}}backup.zip rel="noreferrer noopener"target=_blank>Download server backup</a></div><div id=p2ServerActionsRestore><a href=# onclick="return server_showRestoreDlg()">Restore server with backup</a></div><div id=p2ServerActionsVersion><a href=# onclick="return server_showVersionDlg()">Check server version</a></div><div id=p2ServerActionsErrors><a href=# onclick="return server_showErrorsDlg()">Show server error log</a></div></div></div><br><strong>Server Statistics</strong><br><br><div id=serverStats><div id=serverCpuChartView style=display:none><div class=chartViewCanvas><canvas id=serverCpuChart></canvas></div><div class=chartViewText id=serverCpuChartText></div></div><div id=serverMemoryChartView style=display:none><div class=chartViewCanvas><canvas id=serverMemoryChart></canvas></div><div class=chartViewText id=serverMemoryChartText></div></div><br><br><div id=serverStatsTable></div></div><div id=serverWarningsDiv style=display:none><br><strong>Server Warnings</strong><br><br><div id=serverWarnings></div></div></div><div id=p10 style=display:none><table style=width:100% cellpadding=0 cellspacing=0><tr><td style=width:auto valign=top><div id=p10title><div id=p10BackButton><div class=backButton tabindex=0 onclick=goBack() title=Back onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>General - <span id=p10deviceName></span></h1></div><div id=p10html></div><td style=width:20px><td style=width:200px><a href=# onclick=p10showiconselector()><img id=MainComputerImage></a><div id=MainComputerState></div></table><br><div id=p10html2></div><div id=p10html3></div></div><div id=p11 class=noselect style=display:none><div id=p11title><div id=p11deviceNameHeader><div id=p11BackButton><div class=backButton tabindex=0 onclick=goBack() title=Back onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><div id=devListToolbarViewIcons><div class=viewSelector onclick=deskToggleFull(event) title="Full Screen. Hold shift to browser full screen."><div class=viewSelector5></div></div></div><h1>Desktop - <span id=p11deviceName></span></h1></div></div><div id=p11warning onclick=showFeaturesDlg()><div class=icon2></div><div class=warningbox>Intel&reg; AMT Redirection port or KVM feature is disabled<span id=p11warninga>, click here to enable it.</span></div></div><div id=p11warning2 onclick=showPowerActionDlg()><div class=icon2></div><div class=warningbox>Remote computer is not powered on, click here to issue a power command.</div></div><div id=deskarea0 cellpadding=0 cellspacing=0><div id=deskarea1 class=areaHead><div class=toright2><span id=p11power></span>&nbsp;<div class=deskareaicon title="Toggle View Mode"onclick=toggleAspectRatio(1)>&#8690;</div><div class=deskareaicon title="Rotate Left"onclick=drotate(-1)>&olarr;</div><div class=deskareaicon title="Rotate Right"onclick=drotate(1)>&orarr;</div><div id=deskRecordIcon class=deskareaicon title="Server is recording this session"style=display:none;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px></div><input id=deskFocusBtn type=button title="Toggle focus mode, when active only the region around the mouse is updated"onkeypress=return!1 onkeydown=return!1 value="Focus All"onclick=deskToggleFocus() style=margin-right:3px;display:none> <input id=deskSaveBtn type=button title="Save a screenshot of the remote desktop"onkeypress=return!1 onkeydown=return!1 value=Save... onclick=deskSaveImage() class=mR> <input id=deskActionsBtn type=button title="Perform power actions on the device"onkeypress=return!1 onkeydown=return!1 value=Actions onclick=deviceActionFunction() class=mR> <input id=deskActionsSettings type=button value=Settings... title="Edit remote desktop settings"onkeypress=return!1 onkeydown=return!1 onclick=showDesktopSettings() class=mR> <input type=button title="Change the power state of the remote machine"onkeypress=return!1 onkeydown=return!1 value="Power Actions..."onclick=showPowerActionDlg() style=display:none></div><div><div id=idx_deskFullBtn2 onclick=deskToggleFull(event)>&nbsp;&#x2716;</div><input type=button id=autoconnectbutton1 value=AutoConnect onclick=autoConnectDesktop(event) onkeypress=return!1 onkeydown=return!1 style=display:none> <span id=connectbutton1span><input type=button id=connectbutton1 value=Connect onclick=connectDesktop(event,3) onkeypress=return!1 onkeydown=return!1 disabled></span><span id=connectbutton1hspan>&nbsp;<input type=button id=connectbutton1h value="HW Connect"title="Connect using Intel AMT hardware KVM"onclick=connectDesktop(event,2) onkeypress=return!1 onkeydown=return!1 disabled></span><span id=disconnectbutton1span>&nbsp;<input type=button id=disconnectbutton1 value=Disconnect onclick=connectDesktop(event,0) onkeypress=return!1 onkeydown=return!1></span>&nbsp;<span id=deskstatus>Disconnected</span></div></div><div id=deskarea2><div class=areaProgress><div id=progressbar></div></div></div><div id=deskarea3x><div id=DeskFocus oncontextmenu=return!1 onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></div><div id=DeskParent><canvas id=Desk width=640 height=480 oncontextmenu=return!1 onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event) onmousewheel=dmousewheel(event)></canvas></div><div id=DeskTools><div id=deskToolsAreaTop><a id=DeskToolsRefreshButton style=right:2px onclick=refreshDeskTools()>Refresh</a><div id=deskToolsTopTabProcess class=deskToolsTopTab onclick=changeDeskToolTab(0) style=left:0;bottom:0>Processes</div><div id=deskToolsTopTabService class=deskToolsTopTab onclick=changeDeskToolTab(1) style=display:none;left:90px;color:gray>Services</div></div><div id=deskToolsArea><div id=DeskToolsProcessTab><div id=deskToolsHeader><a class=colmn1 title="Sort by process id"onclick=sortProcess(0)>PID</a> <a class=colmn2 title="Sort by name"onclick=sortProcess(1)>Name</a></div><div id=DeskToolsProcesses></div></div><div id=DeskToolsServiceTab style=display:none><div id=deskToolsServiceHeader><a class=colmn1 style=width:70px title="Sort by state"onclick=sortService(0)>State</a> <a class=colmn2 title="Sort by name"onclick=sortService(1)>Name</a></div><div id=DeskToolsServices></div></div></div></div><div id=p11DeskConsoleMsg style=display:none;cursor:pointer;position:absolute;left:30px;top:17px;color:#ff0;background-color:rgba(0,0,0,.6);padding:10px;border-radius:5px onclick=p11clearConsoleMsg()></div><div id=p11DeskSessionSelector style=display:none;position:absolute;left:30px;top:17px;right:30px></div></div><div id=deskarea4 class=areaFoot><div class=toright2><span id=DeskTimer title="Session time"></span>&nbsp; <select id=termdisplays style=display:none onchange=deskSetDisplay(event) onkeypress=return!1 onkeydown=return!1></select>&nbsp; <input id=DeskToolsButton type=button value=Tools title="Toggle tools view"onkeypress=return!1 onkeydown=return!1 onclick=toggleDeskTools()>&nbsp; <span id=DeskChatButton class=deskarea title="Open chat window to this computer"><img src=images/icon-chat.png onclick=deviceChat(event) height=16 width=16 style=padding-top:2px></span><span id=DeskNotifyButton 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><span id=DeskOpenWebButton title="Open a web address on the remote computer"><img src=images/icon-url2.png onclick=deviceUrlFunction() height=16 width=16 style=padding-top:2px></span><span id=DeskBackgroundButton title="Toggle remote desktop background"><img src=images/icon-background.png onclick=deviceToggleBackground(event) height=16 width=16 style=padding-top:2px></span></div><div><select id=deskkeys><option value=10>Ctrl+Alt+Del<option value=5>Win<option value=0>Win+Down<option value=1>Win+Up<option value=2>Win+L<option value=3>Win+M<option value=4>Shift+Win+M<option value=6>Win+R<option value=7>Alt-F4<option value=8>Ctrl-W<option value=9>Alt-Tab<option value=11>Win+Left<option value=12>Win+Right</select> <input id=DeskWD type=button value=Send onkeypress=return!1 onkeydown=return!1 onclick=deskSendKeys()> <input id=DeskClip type=button value=Clipboard onkeypress=return!1 onkeydown=return!1 onclick=showDeskClip()> <input id=DeskType type=button value=Type onkeypress=return!1 onkeydown=return!1 onclick=showDeskType()> <label><span id=DeskControlSpan title="Toggle mouse and keyboard input"><input id=DeskControl type=checkbox onkeypress=return!1 onkeydown=return!1 onclick=toggleKvmControl()>Input</span></label>&nbsp;</div></div></div></div><div id=p12 style=display:none><div id=p12title><div id=p12BackButton><div class=backButton tabindex=0 onclick=goBack() title=Back onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>Terminal - <span id=p12deviceName></span></h1></div><div id=p12warning onclick=showFeaturesDlg()><div class=icon2></div><div class=warningbox>Intel&reg; AMT Redirection port or KVM feature is disabled<span id=p12warninga>, click here to enable it.</span></div></div><div id=p12warning2 onclick=showPowerActionDlg()><div class=icon2></div><div class=warningbox>Remote computer is not powered on, click here to issue a power command.</div></div><div id=termTable style=position:relative><table style=width:100% cellpadding=0 cellspacing=0><tr><td class=areaHead><div class=toright2><div id=termRecordIcon class=deskareaicon title="Server is recording this session"style=display:none;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px;margin-left:5px></div><input id=termActionsBtn type=button title="Perform power actions on the device"onkeypress=return!1 onkeydown=return!1 value=Actions onclick=deviceActionFunction()></div><div><input type=button id=autoconnectbutton2 value=AutoConnect onclick=autoConnectTerminal(event) onkeypress=return!1 onkeydown=return!1 style=display:none> <span id=connectbutton2span><input type=button id=connectbutton2 value=Connect onclick=connectTerminal(event,1) onkeypress=return!1 onkeydown=return!1 disabled></span><span id=connectbutton2hspan>&nbsp;<input type=button id=connectbutton2h value="HW Connect"title="Connect using Intel AMT hardware KVM"onclick=connectTerminal(event,2) onkeypress=return!1 onkeydown=return!1 disabled></span><span id=disconnectbutton2span>&nbsp;<input type=button id=disconnectbutton2 value=Disconnect onclick=connectTerminal(event,0) onkeypress=return!1 onkeydown=return!1></span>&nbsp;<span id=termstatus>Disconnected</span><span id=termtitle></span></div><tr><td><div class=areaProgress><div id=termprogressbar></div></div><tr><td id=termarea3x><pre id=Term></pre><tr><td class=areaFoot><div class=toright2><span id=TermTimer title="Session time"></span>&nbsp; <span id=terminalSettingsButtons style=display:none><input id=id_tcrbutton type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton value=CR+LF title="Toggle what the return key will send"onclick=termToggleCr()> <input id=id_tfxkeysbutton type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton value="Intel (F10 = ESC+[OM)"title="Toggle F1 to F10 keys emulation type"onclick=termToggleFx()> <input id=id_ttypebutton type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton value="Extended Ascii"title="Toggle terminal emulation type"onclick=termToggleType()> </span><span id=terminalSizeDropDown><select id=termSizeList onkeypress=return!1><option value=1>80x25<option value=2>100x30<option value=3 selected>Auto</select> </span><select id=specialkeylist onkeypress=return!1></select> <input id=specialkeylistinput type=button onkeypress=return!1 class=bottombutton value=Send title="Send the selected special key"onclick=sendSpecialKey()></div><div>&nbsp; <input type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton id=ctrlcbutton value=Ctl-C onclick='termSendKey(3,"ctrlcbutton")'> <input type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton id=ctrlxbutton value=Ctl-X onclick='termSendKey(24,"ctrlxbutton")'> <input type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton id=escbutton value=ESC onclick='termSendKey(27,"escbutton")'> <input type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton id=bsbutton value=Backspace onclick='termSendKey(8,"bsbutton")'> <input type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton id=pastebutton value=Paste title="Paste text into the terminal"onclick=showTermPasteDialog()></div></table><div id=p12TermConsoleMsg style=display:none;cursor:pointer;position:absolute;left:30px;top:45px;color:#ff0;background-color:rgba(0,0,0,.6);padding:10px;border-radius:5px onclick=p12clearConsoleMsg()></div></div></div><div id=p13 style=display:none><div id=p13title><div id=p13BackButton style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Back onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>Files - <span id=p13deviceName></span></h1></div><table id=p13toolbar cellpadding=0 cellspacing=0><tr><td class=areaHead><div class=toright2><input id=filesActionsBtn type=button title="Perform power actions on the device"value=Actions onclick=deviceActionFunction()><div id=filesRecordIcon class=deskareaicon title="Server is recording this session"style=display:none;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px;margin-left:5px></div></div><div><input id=p13AutoConnect value=AutoConnect onclick=autoConnectFiles(event) type=button style=display:none> <input id=p13Connect value=Connect onclick=connectFiles(event) type=button> <span id=p13Status>Disconnected</span></div><tr><td class=areaHead2 valign=bottom><div id=p13rightOfButtons class=toright2></div><div><input type=button id=p13FolderUp disabled onclick=p13folderup() value=Up>&nbsp; <input type=button id=p13SelectAllButton disabled onclick=p13selectallfile() value="Select All">&nbsp; <input type=button id=p13RenameFileButton disabled value=Rename onclick=p13renamefile()>&nbsp; <input type=button id=p13DeleteFileButton disabled value=Delete onclick=p13deletefile()>&nbsp; <input type=button id=p13ViewFileButton disabled value=Edit onclick=p13viewfile()>&nbsp; <input type=button id=p13NewFolderButton disabled value="New Folder"onclick=p13createfolder()>&nbsp; <input type=button id=p13UploadButton disabled value=Upload onclick=p13uploadFile()>&nbsp; <input type=button id=p13CutButton disabled value=Cut onclick=p13copyFile(1)>&nbsp; <input type=button id=p13CopyButton disabled value=Copy onclick=p13copyFile(0)>&nbsp; <input type=button id=p13PasteButton disabled value=Paste onclick=p13pasteFile()>&nbsp; <input type=button id=p13RefreshButton disabled value=Refresh onclick=p13folderup(9999)>&nbsp;</div><tr><td class=areaHead3><div class=toright2><select id=p13sortdropdown onchange=p13updateFiles()><option value=1 selected>Sort by name<option value=2>Sort by size<option value=3>Sort by date<option value=4>Descend by name<option value=5>Descend by size<option value=6>Descend by date</select></div><div>&nbsp;&nbsp;<span id=p13currentpath></span></div></table><div id=p13FilesConsoleMsg style=display:none;cursor:pointer;position:absolute;left:30px;top:165px;color:#ff0;background-color:rgba(0,0,0,.6);padding:10px;border-radius:5px onclick=p13clearConsoleMsg()></div><div id=p13filetable><div id=p13bigok style=display:none><b>&checkmark;</b></div><div id=p13bigfail style=display:none><b>&#10007;</b></div><span id=p13files></span></div><table id=p13toolbarBottom cellpadding=0 cellspacing=0><tr><td class=style6>&nbsp;<span id=p13bottomstatus></span></table></div><div id=p14 style=display:none><div id=p14title><div id=p14BackButton style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Back onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><div id=devListToolbarViewIcons><div class=viewSelector onclick=deskToggleFull(event) title="Full Screen. Hold shift to browser full screen."><div class=viewSelector5></div></div></div><h1>Intel&reg; AMT - <span id=p14deviceName></span></h1></div><iframe id=p14iframe src={{{domainurl}}}commander.htm></iframe></div><div id=p15 style=display:none><div id=p15title><div id=p15BackButton style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Back onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1><span id=p15deviceName></span></h1></div><table id=consoleTable cellpadding=0 cellspacing=0><tr><td class=areaHead><div class=toright2><div id=p15coreName title="Information about current core running on this agent"></div><input type=button id=p15uploadCore value="Agent Action"onclick=p15uploadCore(event) title="Change the agent Java Script code module"> <img onclick=p15downloadConsoleText() style=cursor:pointer;margin-top:6px title="Download console text"src=images/link4.png></div><div id=p15statetext></div><tr><td><div class=areaProgress><div id=consoleprogressbar></div></div><tr><td id=p15agentConsole><pre id=p15agentConsoleText></pre><tr><td class=areaFoot><table style=width:100%><tr><td style=width:99%><input id=p15consoleText style=width:100% onkeyup=p15consoleSend(event) onfocus=onConsoleFocus(1) onblur=onConsoleFocus(0)><td>&nbsp;<td id=p15outputselecttd><select id=p15outputselect><option value=1>Agent<option value=2>MQTT</select><td style=width:1%><input id=id_p15consoleClear type=button class=bottombutton value=Clear onclick=p15consoleClear()></table></table></div><div id=p16 style=display:none><div id=p16title><div id=p16BackButton style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Back onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>Events - <span id=p16deviceName></span></h1></div><table class=pTable><tr><td class=h1><td class=auto-style1>Show <select id=p16limitdropdown onchange=refreshDeviceEvents()><option value=60>Last 60<option value=120>Last 120<option value=250>Last 250<option value=500>Last 500<option value=1000>Last 1000</select> <a href=# onclick=p3showDownloadEventsDialog(1)><img src=images/link4.png height=10 width=10 title="Download Events"style=cursor:pointer></a>&nbsp;<td class=h2></table><div id=p16events></div></div><div id=p17 style=display:none><div id=p17title><div id=p17BackButton style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Back onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>Details - <span id=p17deviceName></span></h1></div><div id=p17info></div></div><div id=p20 style=display:none><div id=p20title><picture id=MainMeshImage style=border-width:0;height:200px;width:200px;float:right><source type=image/webp width=200 height=200 srcset=images/webp/mesh-256.webp><img alt=""width=200 height=200 src=images/mesh-256.png></picture><div style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Back onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>General - <span id=p20meshName></span></h1></div><p id=p20info></div><div id=p21 style=display:none><div id=p21title><div style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Back onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>Summary - <span id=p21meshName></span></h1></div><div style=width:100%><div style=display:table;width:93%><div id=meshPowerChartDiv style=width:31%;display:inline-block;text-align:center;max-width:250px><div style=margin:10px;font-size:16px>Power States</div><canvas id=meshPowerChart style=width:250px;height:250px></canvas></div><div id=meshOsChartDiv style=width:31%;display:inline-block;text-align:center;max-width:250px><div style=margin:10px;font-size:16px>Agent Types</div><canvas id=meshOsChart style=width:250px;height:250px></canvas></div><div id=meshConnChartDiv style=width:31%;display:inline-block;text-align:center;max-width:250px><div style=margin:10px;font-size:16px>Connectivity</div><canvas id=meshConnChart style=width:250px;height:250px></canvas></div></div></div><p id=p21info></div><div id=p30 style=display:none><table style=width:100% cellpadding=0 cellspacing=0><tr><td style=width:auto valign=top><div id=p30title><div style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Back onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>General - <span id=p30userName></span></h1></div><div id=p30html></div><td style=width:20px><td style=width:200px><picture id=MainUserImage style=border-width:0;height:200px;width:200px;float:right><source type=image/webp width=200 height=200 srcset=images/webp/user-256.webp><img alt=""width=200 height=200 src=images/user-256.png></picture><div style=width:100%;text-align:center><strong><span id=MainUserState></span></strong></div></table><br><div id=p30html2></div><div id=p30html3></div></div><div id=p31 style=display:none><div id=p31title><div style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Back onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>Events - <span id=p31userName></span></h1></div><table class=pTable><tr><td class=h1><td class=auto-style1>Show <select id=p31limitdropdown onchange=refreshUsersEvents()><option value=60>Last 60<option value=120>Last 120<option value=250>Last 250<option value=500>Last 500<option value=1000>Last 1000</select> <a href=# onclick=p3showDownloadEventsDialog(3)><img src=images/link4.png height=10 width=10 title="Download Events"style=cursor:pointer></a>&nbsp;<td class=h2></table><div id=p31events></div></div><div id=p40 style=display:none><div id=p40title><h1>My Server Stats</h1></div><div class=areaHead><div class=toright2><select id=p40type onchange=updateServerTimelineStats()><option value=0>Connections<option value=1>Memory</select>&nbsp; <select id=p40time onchange=updateServerTimelineHours()><option value=3>Last 3 hours<option value=8>Last 8 hours<option value=24>Last day<option value=168>Last week<option value=720>Last 30 days</select>&nbsp; <img src=images/link4.png height=10 width=10 title="Download data points (.csv)"style=cursor:pointer onclick=p40downloadEvents()>&nbsp;</div><div><input value=Refresh type=button onclick=refreshServerTimelineStats()> &nbsp;<label><input id=p40log type=checkbox onclick=updateServerTimelineHours()>Log-X</label></div></div><canvas id=serverMainStats></canvas></div><div id=p41 style=display:none><div id=p41title><h1>My Server Tracing</h1></div><div class=areaHead><div class=toright2>Show <select id=p41limitdropdown onchange=displayServerTrace()><option value=100>Last 100<option value=250>Last 250<option value=500>Last 500<option value=1000>Last 1000</select> <input value=Clear type=button onclick=clearServerTracing()> <img src=images/link4.png height=10 width=10 title="Download trace (.csv)"style=cursor:pointer onclick=p41downloadServerTrace()>&nbsp;</div><div><input value=Tracing type=button onclick=setServerTracing()> <span id=p41traceStatus>None</span></div></div><div id=p41events></div></div><div id=p42 style=display:none><h1>My Server Plugins</h1><div class=areaHead><div class=toright2></div><div><input value="Download Plugin"type=button onclick="return pluginHandler.addPluginDlg()"></div></div><div id=pluginRestartNotice class=areaHead style=background-color:gold;display:none><div class=toright2><input value="Refresh Agent Cores"type=button onclick="return distributeCore(),!1"></div><div style=padding:2px><div style=padding:2px><b>Notice:</b> Plugins have been altered, this may require agent core update.</div></div></div><table id=p42tbl><tr class=DevSt><th style=width:26px><th style=width:10px><th class=chName>Name<th class=chDescription>Description<th class=chSite style=text-align:center>Link<th class=chVersion style=text-align:center>Version<th class=chUpgradeAvail style=text-align:center>Latest<th class=chStatus style=text-align:center>Status<th class=chAction style=text-align:center>Action<th style=width:10px></table><div id=pluginNoneNotice style=width:100%;text-align:center;padding-top:10px;display:none><i>No plugins on server.</i></div></div><div id=p43 style=display:none><div id=p43BackButton><div class=backButton tabindex=0 onclick=go(42) title=Back onkeypress='"Enter"==event.key&&go(42)'><div class=backButtonEx></div></div></div><h1>My Server Plugins - <span id=p43title></span></h1><iframe id=p43iframe frameborder=0 style="width:100%;height:calc(100vh - 245px);max-height:calc(100vh - 245px)"></iframe></div><div id=p19 style=display:none><h1>Plugins - <span id=p19deviceName></span></h1><div id=p19headers></div><div id=p19pages></div></div><br id=column_l_bottomgap></div><div id=footer><div class=footer1>{{{footer}}}</div><div class=footer2><a id=verifyEmailId2 style=display:none href=# onclick=account_showVerifyEmail()>Verify Email</a> &nbsp;<a href=terms>Terms &amp; Privacy</a></div></div><div id=dialog class=noselect style=display:none><div id=dialogHeader><div tabindex=0 id=id_dialogclose onclick=setDialogMode() onkeypress='"Enter"==event.key&&setDialogMode()'>&#x2716;</div><div id=id_dialogtitle></div></div><div id=dialogBody><div id=dialog1><div id=id_dialogMessage></div></div><div id=dialog2><div id=id_dialogOptions></div></div><div id=dialog3><div id=d3upload><div>File Selection</div><select id=d3uploadMode onchange=d3modechange()><option value=1>Local file upload<option value=2>Server file selection</select></div><div id=d3localmode style=display:none><div>Upload File</div><form id=d3localmodeform method=post enctype=multipart/form-data action=uploadfile.ashx target=fileUploadFrame><input id=d3auth name=auth style=display:none> <input id=d3attrib name=attrib style=display:none> <input type=file id=d3localFile name=files onchange=d3setActions()> <input type=submit id=d3submit style=display:none></form></div><div id=d3servermode><div id=d3serveraction valign=bottom><input type=button id=p3FolderUp disabled onclick=d3folderup() value=Up>&nbsp;</div><div id=d3serverfiles></div></div></div><div id=dialog4><input id=d4WrapButton type=button value="Wrap On"onclick=d4ToggleWrap()> <input id=d4SizeButton type=button value=Small onclick=d4ToggleSize()> <textarea id=d4editorarea style="height:calc(100vh - 286px);width:100%;overflow:scroll;resize:none;white-space:pre"></textarea></div><div id=dialog7><div id=d7meshkvm><h4>Agent Remote Desktop</h4><div><div>Quality</div><select id=d7bitmapquality dir=rtl></select></div><div><div>Scaling</div><select id=d7bitmapscaling dir=rtl><option selected value=1024>100%<option value=896>87.5%<option value=768>75%<option value=640>62.5%<option value=512>50%<option value=384>37.5%<option value=256>25%<option value=128>12.5%</select></div><div><div>Frame rate</div><select id=d7framelimiter dir=rtl><option selected value=50>Fast<option value=100>Medium<option value=400>Slow<option value=1000>Very slow</select></div></div><div id=d7amtkvm><h4>Intel&reg; AMT Hardware KVM</h4><div><div>Image Encoding</div><select id=d7desktopmode><option value=1>RLE8, Fastest<option value=2>RLE16, Recommended<option value=3>RAW8, Slow<option value=4>RAW16, Very Slow</select></div><div><div>Other Settings</div><div id=d7otherset style=display:block><label style=display:block><input type=checkbox id=d7showfocus>Show Focus Tool</label> <label style=display:block><input type=checkbox id=d7showcursor>Show Local Mouse Cursor</label> <label style=display:block><input type=checkbox id=d7localKeyMap>Local Keyboard Map</label></div></div></div></div></div><div id=idx_dlgButtonBar><input id=idx_dlgCancelButton type=button value=Cancel onclick=dialogclose(0)> <input id=idx_dlgOkButton type=button value=OK onclick=dialogclose(1)><div><input id=idx_dlgDeleteButton type=button value=Delete style=display:none onclick=dialogclose(2)></div></div></div><iframe name=fileUploadFrame style=display:none></iframe><form style=display:none method=post action=uploadfile.ashx enctype=multipart/form-data target=fileUploadFrame><input id=p5fileDragName name=name><input id=p5fileDragAuthCookie name=auth><input id=p5fileDragSize name=size><input id=p5fileDragType name=type><input id=p5fileDragData name=data><input id=p5fileDragLink name=link><input type=submit id=p5loginSubmit2 style=display:none></form><form style=display:none method=post action=uploadnodefile.ashx enctype=multipart/form-data target=fileUploadFrame><input id=p13fileDragName name=name><input id=p13fileDragSize name=size><input id=p13fileDragType name=type><input id=p13fileDragData name=data><input id=p13fileDragLink name=link><input type=submit id=p13loginSubmit2 style=display:none></form><audio id=chimes><source src=sounds/chimes.mp3 type=audio/mp3></audio></div><script>'use strict';
2 -
3 - // Process server-side web state
4 - var webState = '{{{webstate}}}';
5 - if (webState != '') { webState = JSON.parse(decodeURIComponent(webState)); }
6 - for (var i in webState) { localStorage.setItem(i, webState[i]); }
7 - if (!webState.loctag) { delete localStorage.removeItem('loctag'); }
8 -
9 - var args;
10 - var autoReconnect = true;
11 - var powerStatetable = ['', "Powered", "Sleep", "Sleep", "Sleep", "Hibernating", "Power off", "Present"];
12 - var StatusStrs = ["Disconnected", "Connecting...", "Setup...", "Connected", "Intel&reg; AMT Connected"];
13 - var agentsStr = ["Unknown", "Windows 32bit console", "Windows 64bit console", "Windows 32bit service", "Windows 64bit service", "Linux 32bit", "Linux 64bit", "MIPS", "XENx86", "Android ARM", "Linux ARM", "MacOS 32bit", "Android x86", "PogoPlug ARM", "Android APK", "Linux Poky x86-32bit", "MacOS 64bit", "ChromeOS", "Linux Poky x86-64bit", "Linux NoKVM x86-32bit", "Linux NoKVM x86-64bit", "Windows MinCore console", "Windows MinCore service", "NodeJS", "ARM-Linaro", "ARMv6l / ARMv7l", "ARMv8 64bit", "ARMv6l / ARMv7l / NoKVM", "Unknown", "Unknown", "FreeBSD x86-64"];
14 - var sort = 0;
15 - var searchFocus = 0;
16 - var mapSearchFocus = 0;
17 - var userSearchFocus = 0;
18 - var consoleFocus = 0;
19 - var showRealNames = false;
20 - var meshserver = null;
21 - var meshes = {};
22 - var meshcount = 0;
23 - var nodes = null;
24 - var filetree = {};
25 - var userinfo = null;
26 - var serverinfo = null;
27 - var events = [];
28 - var users = null;
29 - var wssessions = null;
30 - var nodeShortIdent = 0;
31 - var desktop;
32 - var desktopsettings = { encoding: 2, showfocus: false, showmouse: true, showcad: true, quality: 40, scaling: 1024, framerate: 50, localkeymap: false };
33 - var multidesktopsettings = { quality: 20, scaling: 128, framerate: 1000 };
34 - var terminal;
35 - var files;
36 - var debugLevel = parseInt('{{{debuglevel}}}');
37 - var features = parseInt('{{{features}}}');
38 - var sessionTime = parseInt('{{{sessiontime}}}');
39 - var domain = '{{{domain}}}';
40 - var domainUrl = '{{{domainurl}}}';
41 - var authCookie = '{{{authCookie}}}';
42 - var authRelayCookie = '{{{authRelayCookie}}}';
43 - var logoutControls = {{{logoutControls}}};
44 - var authCookieRenewTimer = null;
45 - var multiDesktop = {};
46 - var multiDesktopFilter = null;
47 - var serverPublicNamePort = '{{{serverDnsName}}}:{{{serverPublicPort}}}';
48 - var amtScanResults = null;
49 - var debugmode = 0;
50 - var clickOnce = (((features & 256) != 0) && detectClickOnce());
51 - var attemptWebRTC = ((features & 128) != 0);
52 - var passRequirements = '{{{passRequirements}}}';
53 - if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); }
54 - var deskAspectRatio = 0;
55 - try { deskAspectRatio = parseInt(getstore('deskAspectRatio', '0')); } catch (ex) { }
56 - var uiMode = parseInt(getstore('uiMode', 1));
57 - var webPageStackMenu = false;
58 - var webPageFullScreen = true;
59 - var nightMode = (getstore('_nightMode', '0') == '1');
60 - var footerBar = (getstore('_footerBar', '1') == '1');
61 - var sessionActivity = Date.now();
62 - var updateSessionTimer = null;
63 - var pluginHandlerBuilder = {{{pluginHandler}}};
64 - var pluginHandler = null;
65 - if (pluginHandlerBuilder != null) { pluginHandler = new pluginHandlerBuilder(); }
66 - var installedPluginList = null;
67 - var goBackStack = [];
68 -
69 - // Console Message Display Timers
70 - var p11DeskConsoleMsgTimer = null;
71 - var p12TermConsoleMsgTimer = null;
72 - var p13FilesConsoleMsgTimer = null;
73 -
74 - function startup() {
75 - if ((features & 32) == 0) {
76 - // Guard against other site's top frames (web bugs).
77 - var loc = null;
78 - try { loc = top.location.toString().toLowerCase(); } catch (e) { }
79 - if (top != self && (loc == null || top.active == false)) { top.location = self.location; return; }
80 - }
81 -
82 - // Check if we are in debug mode
83 - args = parseUriArgs();
84 - if (!args.locale) { var x = getstore('loctag', 0); if ((x != null) && (x != '*')) { args.locale = x; } }
85 - debugmode = args.debug;
86 - if (args.webrtc != null) { attemptWebRTC = (args.webrtc == 1); }
87 - QV('p13AutoConnect', debugmode); // Files
88 - QV('autoconnectbutton2', debugmode); // Terminal
89 - QV('autoconnectbutton1', debugmode); // Desktop
90 - //QV('DeskClip', debugmode); // Clipboard feature, not completed so show in in debug mode only.
91 -
92 - if (nightMode) { QC('body').add('night'); QS('body')['background-color'] = '#000'; }
93 - toggleFullScreen();
94 -
95 - // Setup page visuals
96 - var hide = 0;
97 - var globalHide = parseInt('{{{hide}}}');
98 - if (globalHide || args.hide) {
99 - if (args.hide) { hide = parseInt(args.hide); }
100 - if (globalHide) { hide = (hide | globalHide); }
101 - }
102 - args.hide = hide;
103 - QV('uiViewButton5', !(args.hide & 4)); // Hide the footer toggle button if footer is hidden anyway.
104 - adjustPanels();
105 -
106 - // Setup logout control
107 - var logoutControl = '';
108 - if (logoutControls.name != null) { logoutControl = format("Welcome {0}.", logoutControls.name); }
109 - if (logoutControls.logoutUrl != null) { logoutControl += format(' <a href=\"' + logoutControls.logoutUrl + '\" style="color:white">' + "Logout" + '</a>'); }
110 - if (args.hide & 1) { QH('logoutControlSpan2', logoutControl); } else { QH('logoutControlSpan', logoutControl); }
111 -
112 - // Setup the context menu
113 - document.onclick = function (e) { hideContextMenu(); }
114 - document.onkeypress = ondockeypress;
115 - document.onkeydown = ondockeydown;
116 - document.onkeyup = ondockeyup;
117 - //window.addEventListener('focus', ondocfocus, false);
118 - window.addEventListener('blur', ondocblur, false);
119 - window.onresize = function () { masterUpdate(512); }
120 - setTimeout(function() { masterUpdate(512); }, 200);
121 -
122 - // Connect to the mesh server
123 - meshserver = MeshServerCreateControl(domainUrl, authCookie);
124 - meshserver.onStateChanged = onStateChanged;
125 - meshserver.onMessage = onMessage;
126 - meshserver.trace = (args.trace == 1);
127 - meshserver.Start();
128 -
129 - // Setup page controls
130 - Q('sortselect').selectedIndex = sort = getstore('sort', 0);
131 - Q('sizeselect').selectedIndex = getstore('_viewsize', 1);
132 - Q('SearchInput').value = getstore('_search', '');
133 - showRealNames = (getstore('showRealNames', 0) == 1);
134 - Q('RealNameCheckBox').checked = showRealNames;
135 - Q('viewselect').value = getstore('_deviceView', 1);
136 - Q('DeskControl').checked = (getstore('DeskControl', 1) == 1);
137 - QV('accountChangeEmailAddressSpan', (features & 0x200000) == 0);
138 -
139 - // Display the page devices
140 - masterUpdate(3)
141 - for (var j = 1; j < 5; j++) { Q('devViewButton' + j).classList.remove('viewSelectorSel'); }
142 - Q('devViewButton' + Q('viewselect').value).classList.add('viewSelectorSel');
143 -
144 - // Setup upload drag & drop
145 - Q('p5filetable').addEventListener('drop', p5fileDragDrop, false);
146 - Q('p5filetable').addEventListener('dragover', p5fileDragOver, false);
147 - Q('p5filetable').addEventListener('dragleave', p5fileDragLeave, false);
148 - //Q('p5fileCatchAllInput').addEventListener('drop', p5fileDragDrop, false);
149 - //Q('p5fileCatchAllInput').addEventListener('dragover', p5fileDragOver, false);
150 - //Q('p5fileCatchAllInput').addEventListener('dragleave', p5fileDragLeave, false);
151 -
152 - // Setup upload drag & drop
153 - Q('p13filetable').addEventListener('drop', p13fileDragDrop, false);
154 - Q('p13filetable').addEventListener('dragover', p13fileDragOver, false);
155 - Q('p13filetable').addEventListener('dragleave', p13fileDragLeave, false);
156 -
157 - // Timeline update interval
158 - setInterval(updateDeviceTimeline, 120000); // Check every 2 minutes
159 -
160 - // Load desktop settings
161 - var t = localStorage.getItem('desktopsettings');
162 - if (t != null) { desktopsettings = JSON.parse(t); }
163 - t = localStorage.getItem('multidesktopsettings');
164 - if (t != null) { multidesktopsettings = JSON.parse(t); }
165 - applyDesktopSettings();
166 -
167 - // Terminal special keys
168 - var x = '';
169 - for (var c = 1; c < 27; c++) x += '<option value=\'' + c + '\'>' + "Ctrl" + '-' + String.fromCharCode(64 + c) + ' (' + c + ')</option>';
170 - QH('specialkeylist', x);
171 -
172 - // Setup server stats panels
173 - setupGeneralServerStats();
174 - setupServerTimelineStats();
175 -
176 - // Setup the user interface in the right mode
177 - userInterfaceSelectMenu();
178 -
179 - // Setup Mesh summary panel
180 - setupMeshSummaryStats();
181 -
182 - // If SSPI or LDAP authentication not used, allow batch account creation.
183 - QV('p4UserBatchCreate', (features & 0x00080000) == 0);
184 -
185 - // Set the file editor
186 - d4EditWrapVal = getstore('editorWrap', 0);
187 - d4EditSizeVal = getstore('editorSize', 0);
188 - d4ToggleWrap(true);
189 - d4ToggleSize(true);
190 - }
191 -
192 - function adjustPanels() {
193 - var hide = args.hide;
194 - if (footerBar == false) { hide |= 4; }
195 - QV('masthead', !(hide & 1));
196 - QV('topbar', !(hide & 2));
197 - QV('footer', !(hide & 4));
198 - QV('p1title', !(hide & 8));
199 - QV('p2title', !(hide & 8));
200 - QV('p3title', !(hide & 8));
201 - QV('p4title', !(hide & 8));
202 - QV('p5title', !(hide & 8));
203 - QV('p6title', !(hide & 8));
204 - QV('p10title', !(hide & 8));
205 - QV('p11title', !(hide & 8));
206 - QV('p12title', !(hide & 8));
207 - QV('p13title', !(hide & 8));
208 - QV('p14title', !(hide & 8));
209 - QV('p15title', !(hide & 8));
210 - QV('p16title', !(hide & 8));
211 - QV('p17title', !(hide & 8));
212 - QV('p20title', !(hide & 8));
213 - QV('p21title', !(hide & 8));
214 - QV('p30title', !(hide & 8));
215 - QV('p31title', !(hide & 8));
216 - QV('p40title', !(hide & 8));
217 - QV('p41title', !(hide & 8));
218 - //if (hide & 16) { QV('page_leftbar', false); QS('page_content').left = '0px'; }
219 -
220 - if (hide != 0) {
221 - // Fix the main grid to zero-height elements we want to hide.
222 - if (uiMode == 2) {
223 - QS('container')['grid-template-rows'] = ((hide & 1) ? '0' : '66') + 'px fit-content(48px) auto ' + ((hide & 4) ? '0' : '45') + 'px';
224 - QS('container')['-ms-grid-rows'] = ((hide & 1) ? '0' : '66') + 'px fit-content(48px) auto ' + ((hide & 4) ? '0' : '45') + 'px';
225 - } else {
226 - QS('container')['grid-template-rows'] = ((hide & 1) ? '0' : '66') + 'px ' + ((hide & 2) ? '0' : '24') + 'px auto ' + ((hide & 4) ? '0' : '45') + 'px';
227 - QS('container')['-ms-grid-rows'] = ((hide & 1) ? '0' : '66') + 'px ' + ((hide & 2) ? '0' : '24') + 'px auto ' + ((hide & 4) ? '0' : '45') + 'px';
228 - }
229 - }
230 -
231 - // Adjust height of remote desktop, files and Intel AMT
232 - // 1 = Top bar, 2 = Tool Bar, 4 = Bottom Bar, 8 = Tab Title
233 - var xh = (((hide & 1) ? 0 : 66) + ((hide & 2) ? 0 : 24) + ((hide & 4) ? 0 : 45) + ((hide & 8) ? 0 : 60)); // 0 to 195
234 - var xh2 = (uiMode > 1)?24:0;
235 - QS('p3users')['max-height'] = 'calc(100vh - ' + (50 + xh) + 'px)'; // 124
236 - QS('p3events')['height'] = 'calc(100vh - ' + (50 + xh) + 'px)'; // 124
237 - QS('p5filetable')['height'] = 'calc(100vh - ' + (99 + xh) + 'px)'; // 160
238 - QS('p13filetable')['height'] = 'calc(100vh - ' + (127 + xh + xh2) + 'px)'; // 124
239 - QS('serverMainStats')['height'] = 'calc(100vh - ' + (50 + xh + xh2) + 'px)'; // 110
240 - QS('serverMainStats')['max-height'] = 'calc(100vh - ' + (50 + xh + xh2) + 'px)'; // 110
241 - QS('xdevices')['max-height'] = 'calc(100vh - ' + (46 + xh) + 'px)'; // 124
242 - QS('xdevicesmap')['max-height'] = 'calc(100vh - ' + (46 + xh) + 'px)'; // 124
243 - QS('p15agentConsole')['height'] = 'calc(100vh - ' + (84 + xh + xh2) + 'px)';
244 - QS('p15agentConsole')['max-height'] = 'calc(100vh - ' + (84 + xh + xh2) + 'px)';
245 - QS('p15agentConsoleText')['height'] = 'calc(100vh - ' + (81 + xh + xh2) + 'px)';
246 - QS('p15agentConsoleText')['max-height'] = 'calc(100vh - ' + (81 + xh + xh2) + 'px)';
247 - if (fullscreen) {
248 - QS('deskarea3x')['height'] = null;
249 - QS('deskarea3x')['max-height'] = null;
250 - QS('p14iframe')['height'] = null;
251 - QS('p14iframe')['max-height'] = null;
252 - } else {
253 - QS('deskarea3x')['height'] = 'calc(100vh - ' + (74 + xh + xh2) + 'px)';
254 - QS('deskarea3x')['max-height'] = 'calc(100vh - ' + (74 + xh + xh2) + 'px)';
255 - QS('p14iframe')['height'] = 'calc(100vh - ' + (23 + xh + xh2) + 'px)';
256 - QS('p14iframe')['max-height'] = 'calc(100vh - ' + (23 + xh + xh2) + 'px)';
257 - }
258 - QS('p43iframe')['height'] = 'calc(100vh - ' + (84 + xh) + 'px)';
259 - QS('p43iframe')['max-height'] = 'calc(100vh - ' + (84 + xh) + 'px)';
260 - QS('p16events')['height'] = 'calc(100vh - ' + (50 + xh + xh2) + 'px)';
261 - QS('p16events')['max-height'] = 'calc(100vh - ' + (50 + xh + xh2) + 'px)';
262 - QS('p41events')['height'] = 'calc(100vh - ' + (48 + xh + xh2) + 'px)';
263 - QS('p41events')['max-height'] = 'calc(100vh - ' + (48 + xh + xh2) + 'px)';
264 -
265 - // We are looking at a single device, remove all the back buttons
266 - if ('{{currentNode}}' != '') {
267 - QV('p10BackButton', false);
268 - QV('p11BackButton', false);
269 - QV('p12BackButton', false);
270 - QV('p13BackButton', false);
271 - QV('p14BackButton', false);
272 - QV('p15BackButton', false);
273 - QV('p16BackButton', false);
274 - }
275 - p1updateInfo();
276 - }
277 -
278 - // Toggle the web page to full screen
279 - function toggleAspectRatio(toggle) {
280 - if (toggle === 1) { deskAspectRatio = ((deskAspectRatio + 1) % 3); putstore('deskAspectRatio', deskAspectRatio); }
281 - deskAdjust();
282 - }
283 -
284 - // If FullScreen, toggle menu to be horizontal or vertical
285 - function toggleStackMenu(toggle) {
286 - if (webPageFullScreen == true) {
287 - if (toggle === 1) {
288 - webPageStackMenu = !webPageStackMenu;
289 - putstore('webPageStackMenu', webPageStackMenu);
290 - }
291 - if (webPageStackMenu == false) {
292 - QC('body').remove('menu_stack');
293 - } else {
294 - QC('body').add('menu_stack');
295 - if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
296 - }
297 - deskAdjust();
298 - }
299 - }
300 -
301 - // Toggle user interface menu
302 - function showUserInterfaceSelectMenu() {
303 - Q('uiViewButton1').classList.remove('uiSelectorSel');
304 - Q('uiViewButton2').classList.remove('uiSelectorSel');
305 - Q('uiViewButton3').classList.remove('uiSelectorSel');
306 - Q('uiViewButton4').classList.remove('uiSelectorSel');
307 - Q('uiViewButton5').classList.remove('uiSelectorSel');
308 - try { Q('uiViewButton' + uiMode).classList.add('uiSelectorSel'); } catch (ex) { }
309 - QV('uiMenu', (QS('uiMenu').display == 'none'));
310 - //Q('uiViewButton1').focus();
311 - if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
312 - if (footerBar) { Q('uiViewButton5').classList.add('uiSelectorSel'); }
313 - }
314 -
315 - function userInterfaceSelectMenu(s) {
316 - if (s) { uiMode = s; putstore('uiMode', uiMode); }
317 - webPageFullScreen = (uiMode < 3);
318 - webPageStackMenu = (uiMode > 1);
319 - toggleFullScreen(0);
320 - toggleStackMenu(0);
321 - if (webPageStackMenu && (xxcurrentView >= 10)) { QC('column_l').add('room4submenu'); } else { QC('column_l').remove('room4submenu'); }
322 - adjustPanels();
323 - }
324 -
325 - function toggleNightMode() {
326 - nightMode = !nightMode;
327 - if (nightMode) { QC('body').add('night'); QS('body')['background-color'] = '#000'; } else { QC('body').remove('night'); QS('body')['background-color'] = '#d3d9d6'; }
328 - putstore('_nightMode', nightMode?'1':'0');
329 - }
330 -
331 - function toggleFooterBarMode() {
332 - footerBar = !footerBar;
333 - putstore('_footerBar', footerBar?'1':'0');
334 - QS('container')['grid-template-rows'] = null;
335 - QS('container')['-ms-grid-rows'] = null;
336 - adjustPanels();
337 - }
338 -
339 - // Toggle the web page to full screen
340 - function toggleFullScreen(toggle) {
341 - if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
342 - if (webPageFullScreen == false) {
343 - QC('body').remove('menu_stack');
344 - QC('body').remove('fullscreen');
345 - QC('body').remove('arg_hide');
346 - if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
347 - QV('UserDummyMenuSpan', false);
348 - //QV('page_leftbar', false);
349 - } else {
350 - QC('body').add('fullscreen');
351 - if (args.hide & 16) QC('body').add('arg_hide'); // This is replacement for QV('page_leftbar', !(args.hide & 16));
352 - QV('page_leftbar', !(args.hide & 16));
353 - QV('MainMenuSpan', !(args.hide & 16));
354 - if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
355 - QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
356 - }
357 - masterUpdate(512);
358 - QV('body', true);
359 - }
360 -
361 - function getNodeFromId(id) { if (nodes != null) { for (var i in nodes) { if (nodes[i]._id == id) return nodes[i]; } } return null; }
362 - function reload() {
363 - var x = window.location.href;
364 - if (x.endsWith('/#')) { x = x.substring(0, x.length - 2); }
365 - window.location.href = x;
366 - }
367 -
368 - function onStateChanged(server, state, prevState, errorCode) {
369 - if (state == 0) {
370 - // Control web socket disconnected
371 - setDialogMode(0); // Close any dialog boxes if present
372 - go(0); // Go to disconnection panel
373 -
374 - // Clean up
375 - powerTimeline = null;
376 - powerTimelineReq = null;
377 - powerTimelineNode = null;
378 - powerTimelineUpdate = null;
379 - deleteAllNotifications(); // Close and clear notifications if present
380 - hideContextMenu(); // Hide the context menu if present
381 - QV('verifyEmailId2', false);
382 - QV('logoutControl', false);
383 - if (errorCode == 'noauth') { QH('p0span', "Unable to perform authentication"); return; }
384 - if (prevState == 2) { if (autoReconnect) { setTimeout(serverPoll, 5000); } } else { QH('p0span', "Unable to connect web socket"); }
385 - if (authCookieRenewTimer != null) { clearInterval(authCookieRenewTimer); authCookieRenewTimer = null; }
386 - } else if (state == 2) {
387 - // Fetch list of meshes, nodes, files
388 - meshserver.send({ action: 'meshes' });
389 - meshserver.send({ action: 'nodes', id: '{{currentNode}}' });
390 - if (pluginHandler != null) { meshserver.send({ action: 'plugins' }); }
391 - if ('{{currentNode}}' == '') { meshserver.send({ action: 'files' }); }
392 - if ('{{viewmode}}' == '') { go(1); }
393 - authCookieRenewTimer = setInterval(function () { meshserver.send({ action: 'authcookie' }); }, 1800000); // Request a cookie refresh every 30 minutes.
394 - }
395 - }
396 -
397 - // Poll the server, if it responds, refresh the page.
398 - function serverPoll() {
399 - var xdr = null;
400 - try { xdr = new XDomainRequest(); } catch (e) { }
401 - if (!xdr) xdr = new XMLHttpRequest();
402 - xdr.open('HEAD', window.location.href);
403 - xdr.timeout = 15000;
404 - xdr.onload = function () { reload(); };
405 - xdr.onerror = xdr.ontimeout = function () { setTimeout(serverPoll, 10000); };
406 - xdr.send();
407 - }
408 -
409 - // Return true if this browser supports clickonce
410 - function detectClickOnce() {
411 - for (var i in window.navigator.mimeTypes) { if (window.navigator.mimeTypes[i].type == 'application/x-ms-application') { return true; } }
412 - var userAgent = window.navigator.userAgent.toUpperCase();
413 - return (userAgent.indexOf('.NET CLR 3.5') >= 0) || (userAgent.indexOf('(WINDOWS NT ') >= 0);
414 - }
415 -
416 - function updateSiteAdmin() {
417 - var noServerBackup = '{{{noServerBackup}}}';
418 - var siteRights = userinfo.siteadmin;
419 - if (noServerBackup == 1) { siteRights &= 0xFFFFFFFA; } // If not server backups allowed, remove server backup and restore permissions
420 -
421 - // Update account actions
422 - QV('p2AccountSecurity', ((features & 4) == 0) && (serverinfo.domainauth == false) && ((features & 4096) != 0)); // Hide Account Security if in single user mode, domain authentication to 2 factor auth not supported.
423 - QV('p2AccountPassActions', ((features & 4) == 0) && (serverinfo.domainauth == false)); // Hide Account Actions if in single user mode or domain authentication
424 - //QV('p2AccountImage', ((features & 4) == 0) && (serverinfo.domainauth == false)); // If account actions are not visible, also remove the image on that panel
425 - QV('p2ServerActions', siteRights & 21);
426 - QV('LeftMenuMyServer', siteRights & 21); // 16 + 4 + 1
427 - QV('MainMenuMyServer', siteRights & 21);
428 - QV('p2ServerActionsBackup', siteRights & 1);
429 - QV('p2ServerActionsRestore', siteRights & 4);
430 - QV('p2ServerActionsVersion', siteRights & 16);
431 - QV('MainMenuMyFiles', siteRights & 8);
432 - QV('LeftMenuMyFiles', siteRights & 8);
433 - if (((siteRights & 8) == 0) && (xxcurrentView == 5)) { setDialogMode(0); go(1); }
434 - if (currentNode != null) { gotoDevice(currentNode._id, xxcurrentView, true); }
435 -
436 - // Update user management state
437 - if ((userinfo.siteadmin & 2) != 0)
438 - {
439 - // We are user administrator
440 - if (users == null) { meshserver.send({ action: 'users' }); }
441 - if (wssessions == null) { meshserver.send({ action: 'wssessioncount' }); }
442 - } else {
443 - // We are not user administrator
444 - users = null;
445 - wssessions = null;
446 - updateUsers();
447 - if (xxcurrentView == 4 || ((xxcurrentView >= 30) && (xxcurrentView < 40))) { setDialogMode(0); go(1); currentUser = null; }
448 - }
449 - meshserver.send({ action: 'events', limit: parseInt(p3limitdropdown.value) });
450 - QV('ServerConsole', userinfo.siteadmin === 0xFFFFFFFF);
451 - QV('ServerTrace', userinfo.siteadmin === 0xFFFFFFFF);
452 - if ((xxcurrentView == 115) && (userinfo.siteadmin != 0xFFFFFFFF)) { go(6); }
453 - if ((xxcurrentView == 6) && ((userinfo.siteadmin & 21) == 0)) { go(1); }
454 -
455 - // If we are site administrator, register to get server statistics
456 - if ((siteRights & 21) != 0) { meshserver.send({ action: 'serverstats', interval: 10000 }); }
457 - }
458 -
459 - // To boost the speed of the web page when even floods occur, this method perform a delayed update on the web page.
460 - var updateNaggleTimer = null;
461 - var updateNaggleFlags = 0;
462 - function masterUpdate(flags) {
463 - updateNaggleFlags |= flags;
464 - if (updateNaggleTimer == null) {
465 - updateNaggleTimer = setTimeout(function () {
466 - if (updateNaggleFlags & 512) { center(); }
467 - if (updateNaggleFlags & 1) { onSearchInputChanged(); }
468 - if (updateNaggleFlags & 2) { onSortSelectChange(false); }
469 - if (updateNaggleFlags & 128) { updateMeshes(); }
470 - if (updateNaggleFlags & 4) { updateDevices(); if (xxcurrentView == 21) { p21updateMesh(); } }
471 - if (updateNaggleFlags & 8) { drawNotifications(); }
472 - {{{StartGeoLocationJS}}}if (updateNaggleFlags & 16) { updateMapMarkers(); }{{{EndGeoLocationJS}}}
473 - if (updateNaggleFlags & 32) { eventsUpdate(); }
474 - {{{StartGeoLocationJS}}}if (updateNaggleFlags & 64) { refreshMap(false, true); }{{{EndGeoLocationJS}}}
475 - if (updateNaggleFlags & 256) { drawDeviceTimeline(); }
476 - if (updateNaggleFlags & 1024) { deviceEventsUpdate(); }
477 - if (updateNaggleFlags & 2048) { userEventsUpdate(); }
478 - if (updateNaggleFlags & 4096) { p20updateMesh(); }
479 - updateNaggleTimer = null;
480 - updateNaggleFlags = 0;
481 - }, 150);
482 - }
483 - }
484 -
485 - var backupCodesWarningDone = false;
486 - function updateSelf() {
487 - QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
488 - QV('verifyEmailId2', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
489 - QV('manageOtp', (userinfo.otpsecret == 1) || (userinfo.otphkeys > 0));
490 - QV('authAppSetupCheck', userinfo.otpsecret == 1);
491 - QV('authKeySetupCheck', userinfo.otphkeys > 0);
492 - QV('authCodesSetupCheck', userinfo.otpkeys > 0);
493 - masterUpdate(4 + 128 + 4096);
494 -
495 - // Check if backup codes should really be enabled
496 - if ((backupCodesWarningDone == false) && !(userinfo.otpkeys > 0) && (((userinfo.otpsecret == 1) && !(userinfo.otphkeys > 0)) || ((userinfo.otpsecret != 1) && (userinfo.otphkeys == 1)))) {
497 - var n = { text: "Please add two-factor backup codes. If the current factor is lost, there is not way to recover this account.", title: "Two factor authentication" };
498 - addNotification(n);
499 - backupCodesWarningDone = true;
500 - }
501 -
502 - // If we can't create new groups, hide all links that can do that.
503 - var newGroupsAllowed = ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 64) == 0));
504 - QV('p2createMeshLink1', newGroupsAllowed);
505 - QV('p2createMeshLink2', newGroupsAllowed);
506 - QV('getStarted1', newGroupsAllowed);
507 - QV('getStarted2', !newGroupsAllowed);
508 -
509 - if (typeof userinfo.passchange == 'number') {
510 - if (userinfo.passchange == -1) { QH('p2nextPasswordUpdateTime', " - Reset on next login."); }
511 - else if ((passRequirements != null) && (typeof passRequirements.reset == 'number')) {
512 - var seconds = (userinfo.passchange) + (passRequirements.reset * 86400) - Math.floor(Date.now() / 1000);
513 - if (seconds < 0) { QH('p2nextPasswordUpdateTime', " - Reset on next login."); }
514 - else if (seconds < 3600) { QH('p2nextPasswordUpdateTime', format(" - Reset in {0} minute{1}.", Math.floor(seconds / 60), addLetterS(Math.floor(seconds / 60)))); }
515 - else if (seconds < 86400) { QH('p2nextPasswordUpdateTime', format(" - Reset in {0} hour{1}.", Math.floor(seconds / 3600), addLetterS(Math.floor(seconds / 3600)))); }
516 - else { QH('p2nextPasswordUpdateTime', format(" - Reset in {0} day{1}."), Math.floor(seconds / 86400), addLetterS(Math.floor(seconds / 86400))); }
517 - }
518 - }
519 - }
520 -
521 - function addLetterS(x) { return (x > 1) ? 's' : ''; }
522 - function setSessionActivity() { sessionActivity = Date.now(); QH('idleTimeoutNotify', ''); }
523 - function checkIdleSessionTimeout() {
524 - var delta = (Date.now() - sessionActivity);
525 - if (delta > serverinfo.timeout) { window.location.href = 'logout'; } else {
526 - var ds = Math.round((serverinfo.timeout - delta) / 1000);
527 - if (ds <= 60) {
528 - QH('idleTimeoutNotify', '<br />' + format("{0} second{1} until disconnect", ds, addLetterS(ds)));
529 - } else {
530 - ds = Math.round(ds / 60);
531 - if (ds <= 5) { QH('idleTimeoutNotify', '<br />' + format("{0} minute{1} until disconnect", ds, addLetterS(ds))); }
532 - }
533 - }
534 - }
535 -
536 - function onMessage(server, message) {
537 - switch (message.action) {
538 - case 'trace': {
539 - serverTrace.unshift(message);
540 - displayServerTrace();
541 - break;
542 - }
543 - case 'traceinfo': {
544 - if (typeof message.traceSources == 'object') {
545 - if ((message.traceSources != null) && (message.traceSources.length > 0)) {
546 - serverTraceSources = message.traceSources;
547 - QH('p41traceStatus', EscapeHtml(message.traceSources.join(', ')));
548 - } else {
549 - serverTraceSources = [];
550 - QH('p41traceStatus', "None");
551 - }
552 - }
553 - break;
554 - }
555 - case 'serverstats': {
556 - updateGeneralServerStats(message);
557 - break;
558 - }
559 - case 'serverwarnings': {
560 - if ((message.warnings != null) && (message.warnings.length > 0)) {
561 - var x = '';
562 - for (var i in message.warnings) { x += '<div style=color:red;padding-bottom:6px><b>' + "WARNING: " + message.warnings[i] + '</b></div>'; }
563 - QH('serverWarnings', x);
564 - QV('serverWarningsDiv', true);
565 - }
566 - break;
567 - }
568 - case 'servertimelinestats': {
569 - setServerTimelineStats(message.events);
570 - break;
571 - }
572 - case 'authcookie': {
573 - // Got an authentication cookie refresh
574 - authCookie = message.cookie;
575 - authRelayCookie = message.rcookie;
576 - break;
577 - }
578 - case 'serverinfo': {
579 - serverinfo = message.serverinfo;
580 - if (serverinfo.timeout) { setInterval(checkIdleSessionTimeout, 10000); checkIdleSessionTimeout(); }
581 - if (debugmode == 1) { console.log('Server time: ', printDateTime(new Date(serverinfo.serverTime))); }
582 - break;
583 - }
584 - case 'userinfo': {
585 - userinfo = message.userinfo;
586 - updateSiteAdmin();
587 - updateSelf();
588 - break;
589 - }
590 - case 'users': {
591 - users = {};
592 - for (var m in message.users) { users[message.users[m]._id] = message.users[m]; }
593 - updateUsers();
594 - break;
595 - }
596 - case 'wssessioncount': {
597 - wssessions = message.wssessions;
598 - updateUsers();
599 - break;
600 - }
601 - case 'meshes': {
602 - meshes = {};
603 - for (var m in message.meshes) { meshes[message.meshes[m]._id] = message.meshes[m]; }
604 - masterUpdate(4 + 128);
605 - break;
606 - }
607 - case 'files': {
608 - filetree = setupBackPointers(message.filetree);
609 - updateFiles();
610 - d3updatefiles();
611 - break;
612 - }
613 - case 'nodes': {
614 - nodes = [];
615 - for (var m in message.nodes) {
616 - if (!meshes[m]) { console.log('Invalid mesh (1): ' + m); continue; }
617 - for (var n in message.nodes[m]) {
618 - if (message.nodes[m][n]._id == null) { console.log('Invalid node (' + n + '): ' + JSON.stringify(message.nodes)); continue; }
619 - message.nodes[m][n].namel = message.nodes[m][n].name.toLowerCase();
620 - if (message.nodes[m][n].rname) { message.nodes[m][n].rnamel = message.nodes[m][n].rname.toLowerCase(); } else { message.nodes[m][n].rnamel = message.nodes[m][n].namel; }
621 - message.nodes[m][n].meshnamel = meshes[m].name.toLowerCase();
622 - message.nodes[m][n].meshid = m;
623 - message.nodes[m][n].state = (message.nodes[m][n].state)?(message.nodes[m][n].state):0;
624 - message.nodes[m][n].desc = message.nodes[m][n].desc;
625 - message.nodes[m][n].ip = message.nodes[m][n].ip;
626 - if (!message.nodes[m][n].icon) message.nodes[m][n].icon = 1;
627 - message.nodes[m][n].ident = ++nodeShortIdent;
628 - nodes.push(message.nodes[m][n]);
629 - }
630 - }
631 - masterUpdate(1 | 2 | 4 | 64);
632 -
633 - if (xxcurrentView == -1) { if ('{{viewmode}}' != '') { go(parseInt('{{viewmode}}')); } else { setDialogMode(0); go(1); } }
634 - if ('{{currentNode}}' != '') { gotoDevice('{{currentNode}}',parseInt('{{viewmode}}'));}
635 - break;
636 - }
637 - case 'powertimeline': {
638 - if (message.nodeid != powerTimelineReq) break;
639 - powerTimelineNode = message.nodeid;
640 - powerTimeline = message.timeline;
641 - powerTimelineUpdate = Date.now() + 300000; // Update every 5 minutes
642 - for (var i in powerTimeline) { if (i % 2 == 1) { powerTimeline[i] = powerTimeline[i] * 1000; } } // Decompress time
643 - if (currentNode._id == message.nodeid) { masterUpdate(256); }
644 - break;
645 - }
646 - case 'getsysinfo': {
647 - if (message.nodeid != powerTimelineReq) break;
648 - //console.log('getsysinfo', message); // ***********************
649 - if (message.noinfo === true) {
650 - QH('p17info', "No information for this device.");
651 - } else {
652 - var x = '', s = {};
653 - if (message.hardware) {
654 - if (message.hardware.identifiers) {
655 - var ident = message.hardware.identifiers;
656 - // BIOS
657 - x += '<div class=DevSt style=margin-bottom:3px><b>' + "BIOS" + '</b></div>';
658 - if (ident.bios_vendor) { x += addDetailItem("Vendor", ident.bios_vendor, s); }
659 - if (ident.bios_version) { x += addDetailItem("Version", ident.bios_version, s); }
660 - x += '<br />';
661 -
662 - // Motherboard
663 - x += '<div class=DevSt style=margin-bottom:3px><b>' + "Motherboard" + '</b></div>';
664 - if (ident.board_vendor) { x += addDetailItem("Vendor", ident.board_vendor, s); }
665 - if (ident.board_name) { x += addDetailItem("Name", ident.board_name, s); }
666 - if (ident.board_serial && (ident.board_serial != '')) { x += addDetailItem("Serial", ident.board_serial, s); }
667 - if (ident.board_version) { x += addDetailItem("Version", ident.board_version, s); }
668 - if (ident.product_uuid) { x += addDetailItem("Identifier", ident.product_uuid, s); }
669 - x += '<br />';
670 - }
671 -
672 - if (message.hardware.windows) {
673 - if (message.hardware.windows.memory) {
674 - // Memory
675 - x += '<div class=DevSt style=margin-bottom:3px><b>' + "Memory" + '</b></div>';
676 -
677 - // Sort Memory
678 - function memorySort(a, b) { if (a.BankLabel > b.BankLabel) return 1; if (a.BankLabel < b.BankLabel) return -1; return 0; }
679 - message.hardware.windows.memory.sort(memorySort);
680 -
681 - x += '<table style=width:100%>';
682 - for (var i in message.hardware.windows.memory) {
683 - var m = message.hardware.windows.memory[i];
684 - x += '<tr><td VALIGN=Top style=width:38px><img src="images/ram2.png" />'
685 - x += '<td><div style=background-color:lightgray;border-radius:5px;padding:8px>';
686 - x += '<div><b>' + m.BankLabel + '</b></div>';
687 - if (m.Capacity) { x += addDetailItem("Capacity / Speed", format("{0} Mb, {1} Mhz", (m.Capacity / 1024 / 1024), m.Speed), s); }
688 - if (m.PartNumber) { x += addDetailItem("Part Number", ((m.Manufacturer && m.Manufacturer != 'Undefined')?(m.Manufacturer + ', '):'') + m.PartNumber, s); }
689 - x += '</div>';
690 - }
691 - x += '</table><br />';
692 - }
693 -
694 - if (message.hardware.windows.osinfo) {
695 - // Operating System
696 - var m = message.hardware.windows.osinfo;
697 - x += '<div class=DevSt style=margin-bottom:3px><b>' + "Operating System" + '</b></div>';
698 - if (m.Caption) { x += addDetailItem("Name", m.Caption, s); }
699 - if (m.Version) { x += addDetailItem("Version", m.Version, s); }
700 - if (m.OSArchitecture) { x += addDetailItem("Architecture", m.OSArchitecture, s); }
701 - x += '<br />';
702 - }
703 -
704 - // Disks
705 - //x += '<div class=DevSt style=margin-bottom:3px><b>Disks</b></div>';
706 - //x += '<br />';
707 - }
708 - }
709 -
710 - QH('p17info', x);
711 - }
712 - break;
713 - }
714 - case 'lastconnect': {
715 - var node = getNodeFromId(message.nodeid);
716 - if (node != null) {
717 - node.lastconnect = message.time;
718 - node.lastaddr = message.addr;
719 - if ((currentNode._id == node._id) && (Q('MainComputerState').innerHTML == '')) {
720 - QH('MainComputerState', '<span>' + "Last seen:" + '<br />' + printDateTime(new Date(node.lastconnect)) + '</span>');
721 - }
722 - }
723 - break;
724 - }
725 - case 'msg': {
726 - // Check if this is a message from a node
727 - if (message.nodeid != null) {
728 - var index = -1;
729 - if (nodes != null) { for (var i in nodes) { if (nodes[i]._id == message.nodeid) { index = i; break; } } }
730 - if (index != -1) {
731 - // Node was found, dispatch the message
732 - if (message.type == 'console') { p15consoleReceive(nodes[index], message.value, message.source); } // This is a console message.
733 - else if (message.type == 'notify') { // This is a notification message.
734 - var n = getstore('notifications', 0);
735 - if (((n & 8) == 0) && (message.amtMessage != null)) { break; } // Intel AMT desktop & terminal messages should be ignored.
736 - var n = { text: message.value, title: message.title, icon: message.icon };
737 - if (message.nodeid != null) { n.nodeid = message.nodeid; }
738 - if (message.tag != null) { n.tag = message.tag; }
739 - if (message.username != null) { n.username = message.username; }
740 - addNotification(n);
741 - } else if (message.type == 'ps') {
742 - showDeskToolsProcesses(message);
743 - } else if (message.type == 'services') {
744 - showDeskToolsServices(message);
745 - } else if ((message.type == 'getclip') && (xxdialogTag == 'clipboard') && (currentNode != null) && (currentNode._id == message.nodeid)) {
746 - Q('d2clipText').value = message.data;
747 - } else if ((message.type == 'setclip') && (xxdialogTag == 'clipboard') && (currentNode != null) && (currentNode._id == message.nodeid)) {
748 - // Display success/fail on the clipboard dialog box.
749 - QH('dlgClipStatus', message.success ? '<span style=color:green>' + "Success" + '</span>' : '<span style=color:red>' + "Failed" + '</span>')
750 - setTimeout(function () { try { QH('dlgClipStatus', ''); } catch (ex) { } }, 2000);
751 - } else if ((message.type == 'userSessions') && (currentNode != null) && (currentNode._id == message.nodeid) && (desktop == null)) {
752 - // Got list of user sessions
753 - var userSessions = [];
754 - if (message.data != null) { for (var i in message.data) { if ((message.data[i].State == 'Active') || (message.data[i].StationName == 'Console') || (debugmode == 3)) { userSessions.push(message.data[i]); } } }
755 - if (userSessions.length == 0) { connectDesktop(null, 1); } // No active sessions, do a normal connection.
756 - else if (userSessions.length == 1) { connectDesktop(null, 1, userSessions[0].SessionId); } // One active session, connect to it
757 - else {
758 - var x = '';
759 - for (var i in userSessions) {
760 - x += '<div style="text-align:left;cursor:pointer;background-color:gray;margin:5px;padding:5px;border-radius:5px" onclick=connectDesktop(event,1,' + userSessions[i].SessionId + ')>' + userSessions[i].State + ', ' + userSessions[i].StationName;
761 - if (userSessions[i].Username) { if (userSessions[i].Domain) { x += ' - ' + userSessions[i].Domain + '/' + userSessions[i].Username; } else { x += ' - ' + userSessions[i].Username; } }
762 - x += '</div>';
763 - }
764 - QH('p11DeskSessionSelector', x);
765 - QV('p11DeskSessionSelector', true);
766 - }
767 - }
768 - }
769 - } else {
770 - if (message.type == 'notify') { // This is a notification message.
771 - var n = { text: message.value, title: message.title, icon: message.icon };
772 - if (message.tag != null) { n.tag = message.tag; }
773 - if (message.username != null) { n.username = message.username; }
774 - addNotification(n);
775 - }
776 - }
777 - break;
778 - }
779 - case 'getnetworkinfo': {
780 - if ((currentNode._id == message.nodeid) && (xxdialogMode == 2) && (xxdialogTag == 'if' + message.nodeid)) {
781 - if (message.netif == null) {
782 - QH('d2netinfo', "No network interface information available for this device.");
783 - } else {
784 - var x = '<div class=dialogText>';
785 -
786 - if (currentNode.lastconnect) { x += addHtmlValue2("Last agent connection", printDateTime(new Date(currentNode.lastconnect))); }
787 - if (currentNode.lastaddr) {
788 - var splitip = currentNode.lastaddr.split(':');
789 - if (splitip.length > 2) {
790 - // IPv6
791 - x += addHtmlValue2("Last agent address", currentNode.lastaddr + ' <img src="images/link4.png" title="Copy address to clipboard" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(currentNode.lastaddr) + '\") width=10 height=10>');
792 - } else {
793 - // IPv4
794 - if (isPrivateIP(currentNode.lastaddr)) {
795 - x += addHtmlValue2("Last agent address", splitip[0] + ' <img src="images/link4.png" title="' + "Copy address to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(splitip[0]) + '\") width=10 height=10>');
796 - } else {
797 - x += addHtmlValue2("Last agent address", '<a href="https://iplocation.com/?ip=' + splitip[0] + '" rel="noreferrer noopener" target="MeshIPLoopup">' + splitip[0] + '</a> <img src="images/link4.png" title="' + "Copy address to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(splitip[0]) + '\") width=10 height=10>');
798 - }
799 - }
800 - }
801 -
802 - x += addHtmlValue2("Last interfaces update", printDateTime(new Date(message.updateTime)));
803 - for (var i in message.netif) {
804 - var net = message.netif[i];
805 - x += '<hr />'
806 - if (net.name) { x += addHtmlValue2("Name", '<b>' + EscapeHtml(net.name) + '</b>'); }
807 - if (net.desc) { x += addHtmlValue2("Description", EscapeHtml(net.desc).replace('(R)', '&reg;').replace('(r)', '&reg;')); }
808 - if (net.dnssuffix) { x += addHtmlValue2("DNS suffix", EscapeHtml(net.dnssuffix) + ' <img src="images/link4.png" title="' + "Copy name to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.dnssuffix) + '\") width=10 height=10>'); }
809 - if (net.mac) { x += addHtmlValue2("MAC address", '<a href="https://dnslytics.com/mac-address-lookup/' + net.mac.substring(0, 6) + '" rel="noreferrer noopener" target="MeshMACLoopup">' + EscapeHtml(net.mac.toLowerCase()) + '</a> <img src="images/link4.png" title="' + "Copy MAC address to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.mac.toLowerCase()) + '\") width=10 height=10>'); }
810 - if (net.v4addr) { x += addHtmlValue2("IPv4 address", EscapeHtml(net.v4addr) + ' <img src="images/link4.png" title="' + "Copy address to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4addr) + '\") width=10 height=10>'); }
811 - if (net.v4mask) { x += addHtmlValue2("IPv4 mask", EscapeHtml(net.v4mask) + ' <img src="images/link4.png" title="' + "Copy address to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4mask) + '\") width=10 height=10>'); }
812 - if (net.v4gateway) { x += addHtmlValue2("IPv4 gateway", EscapeHtml(net.v4gateway) + ' <img src="images/link4.png" title="' + "Copy address to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4gateway) + '\") width=10 height=10>'); }
813 - if (net.gatewaymac) { x += addHtmlValue2("Gateway MAC", '<a href="https://dnslytics.com/mac-address-lookup/' + net.gatewaymac.substring(0, 6) + '" rel="noreferrer noopener" target="MeshMACLoopup">' + EscapeHtml(net.gatewaymac.toLowerCase()) + '</a> <img src="images/link4.png" title="' + "Copy MAC address to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.gatewaymac.toLowerCase()) + '\") width=10 height=10>'); }
814 - }
815 - x += '</div>';
816 - QH('d2netinfo', x);
817 - }
818 - }
819 - break;
820 - }
821 - case 'serverversion': {
822 - if ((xxdialogMode == 2) && (xxdialogTag == 'MeshCentralServerUpdate')) {
823 - var x = '<div class=dialogText>';
824 - if (!message.current) { message.current = "Unknown"; }
825 - if (!message.latest) { message.latest = "Unknown"; }
826 - x += addHtmlValue2("Current Version", '<b>' + EscapeHtml(message.current) + '</b>');
827 - x += addHtmlValue2("Latest Version", '<b>' + EscapeHtml(message.latest) + '</b>');
828 - x += '</div>';
829 - if ((message.latest.indexOf('.') == -1) || (message.current == message.latest) || ((features & 2048) == 0)) {
830 - setDialogMode(2, "MeshCentral Version", 1, null, x);
831 - } else {
832 - setDialogMode(2, "MeshCentral Version", 3, server_showVersionDlgEx, x + '<br /><label><input id=d2updateCheck type=checkbox onclick=server_showVersionDlgUpdate() /> ' + "Check and click OK to start server self-update." + '</label>');
833 - server_showVersionDlgUpdate();
834 - }
835 - }
836 - break;
837 - }
838 - case 'servererrors': {
839 - if ((xxdialogMode == 2) && (xxdialogTag == 'MeshCentralServerErrors')) {
840 - if (message.data == null) {
841 - setDialogMode(2, "MeshCentral Server Errors", 1, null, "Server has no error log.");
842 - } else {
843 - var x = '<div class="dialogText dialogTextLog"><pre id=d2ServerErrorsLogPre>' + message.data + '<pre></div>';
844 - setDialogMode(2, "MeshCentral Server Errors", 3, server_showErrorsDlgEx, x + '<br /><div style=float:right><img src=images/link4.png height=10 width=10 title="' + "Download error log" + '" style=cursor:pointer onclick=d2CopyServerErrorsToClip()></div><div><label><input id=d2updateCheck type=checkbox onclick=server_showVersionDlgUpdate() /> ' + "Check and click OK to clear error log." + '</label></div>');
845 - server_showVersionDlgUpdate();
846 - }
847 - }
848 - break;
849 - }
850 - case 'serverconsole': {
851 - p15consoleReceive('serverconsole', message.value);
852 - break;
853 - }
854 - case 'events': {
855 - if ((message.nodeid != null) && (message.nodeid == currentNode._id)) {
856 - currentDeviceEvents = message.events;
857 - masterUpdate(1024);
858 - } else if ((message.user != null) && (message.user == currentUser.name)) {
859 - currentUserEvents = message.events;
860 - masterUpdate(2048);
861 - } else {
862 - events = message.events;
863 - masterUpdate(32);
864 - }
865 - break;
866 - }
867 - case 'getcookie': {
868 - if (message.tag == 'clickonce') {
869 - var basicPort = '{{{serverRedirPort}}}' == '' ? '{{{serverPublicPort}}}' : '{{{serverRedirPort}}}';
870 - var rdpurl = 'http://' + window.location.hostname + ':' + basicPort + '/clickonce/minirouter/MeshMiniRouter.application?WS=wss%3A%2F%2F' + window.location.hostname + '%2Fmeshrelay.ashx%3Fauth=' + message.cookie + '&CH={{{webcerthash}}}&AP=' + message.protocol + ((debugmode == 1) ? '' : '&HOL=1');
871 - var newWindow = window.open(rdpurl, '_blank');
872 - newWindow.opener = null;
873 - }
874 - break;
875 - }
876 - case 'getNotes': {
877 - var n = Q('d2devNotes');
878 - if (n && (message.id == decodeURIComponent(n.attributes['noteid'].value))) {
879 - if (message.notes) { QH('d2devNotes', decodeURIComponent(message.notes)); } else { QH('d2devNotes', ''); }
880 - var ro = (n.attributes['ro'].value == 'true');
881 - if (ro == false) { // If we have permissions, set read/write on this note.
882 - n.removeAttribute('readonly');
883 - QE('idx_dlgOkButton', true);
884 - QV('idx_dlgOkButton', true);
885 - focusTextBox('d2devNotes');
886 - }
887 - }
888 - break;
889 - }
890 - case 'otpauth-request': {
891 - if ((xxdialogMode == 2) && (xxdialogTag == 'otpauth-request')) {
892 - var secret = message.secret;
893 - if (secret.length == 52) { secret = secret.split(/(.............)/).filter(Boolean).join(' '); }
894 - else if (secret.length == 32) { secret = secret.split(/(....)/).filter(Boolean).join(' '); secret = secret.substring(0, 20) + '<br/>' + secret.substring(20) }
895 - QH('d2optinfo', '<table style=width:380px><tr><td style=vertical-align:top>' + "Install <a href=\"https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2\" rel=\"noreferrer noopener\" target=_blank>Google Authenticator</a> or a compatible application and scan the barcode, use <a href=\"' + message.url + '\" rel=\"noreferrer noopener\" target=_blank> this link</a> or enter the secret. Then, enter the current 6 digit token below to activate 2-Step login." + '<br /><br />Secret<br /><tt id=d2optsecret secret=\"' + message.secret + '\" style=font-size:12px>' + secret + '</tt><br /><br /></td><td style=width:1px;vertical-align:top><a href=\"' + message.url + '\" rel=\"noreferrer noopener\" target=_blank><div id="qrcode"></div></a></td><tr><td colspan=2 style="text-align:center;border-top:1px solid black"><br />' + "Enter the token here for 2-step login:" + ' <input type=text onkeypress=\"return (event.keyCode == 8) || (event.charCode >= 48 && event.charCode <= 57)\" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text></td></table>');
896 - new QRCode(Q('qrcode'), { text: message.url, width: 128, height: 128, colorDark: '#000000', colorLight: '#EEE', correctLevel: QRCode.CorrectLevel.H });
897 - QV('idx_dlgOkButton', true);
898 - QE('idx_dlgOkButton', false);
899 - Q('d2otpauthinput').focus();
900 - }
901 - break;
902 - }
903 - case 'otpauth-setup': {
904 - if (xxdialogMode) return;
905 - setDialogMode(2, "Authenticator App", 1, null, message.success ? ('<b style=color:green>' + "Authenticator app activation successful." + '</b> ' + "You will now need a valid token to login again.") : ('<b style=color:red>' + "2-step login activation failed." + '</b> ' + "Clear the secret from the application and try again. You only have a few minutes to enter the proper code."));
906 - break;
907 - }
908 - case 'otpauth-clear': {
909 - if (xxdialogMode) return;
910 - setDialogMode(2, "Authenticator App", 1, null, message.success ? ('<b>' + "Authenticator application removed." + '</b> ' + "You can reactivate this feature at any time.") : ('<b style=color:red>' + "2-step login activation removal failed." + '</b> ' + "Try again."));
911 - break;
912 - }
913 - case 'otpauth-getpasswords': {
914 - if (xxdialogMode) return;
915 - var x = "One time tokens can be used as secondary authentication. Generate a set, print them and keep them in a safe place.";
916 - x += '<div style="border-radius:6px;border: 2px dashed #888;width:100%;margin-top:8px"><div style="padding:8px;font-family:Arial, Helvetica, sans-serif;font-size:20px;font-weight:bold"><table class=selecttext style=width:100%;text-align:center>';
917 - if (message.passwords) {
918 - var j = 0, clipb = '';
919 - for (var i in message.passwords) {
920 - if (++j % 2) { x += '<tr>'; }
921 - var p = '' + message.passwords[i].p;
922 - while (p.length < 8) { p = '0' + p; }
923 - if (message.passwords[i].u === true) {
924 - x += '<td>' + p.substring(0, 4) + '&nbsp;' + p.substring(4);
925 - if (clipb != '') { clipb += ' '; }
926 - clipb += p;
927 - } else {
928 - x += '<td><strike style=color:#BBB>' + p.substring(0, 4) + '&nbsp;' + p.substring(4); + '</strike>';
929 - }
930 - }
931 - } else {
932 - x += '<tr><td>' + "No Active Tokens";
933 - }
934 - x += '</table></div></div><br />';
935 - x += '<div><input type=button value=' + "Close" + ' onclick=setDialogMode(0) style=float:right></input>';
936 - x += '<input type=button value="' + "Generate New Tokens" + '" onclick="account_manageOtp(1);"></input>';
937 - if (message.passwords != null) {
938 - x += '<input type=button value="' + "Clear Tokens" + '" onclick="account_manageOtp(2);"></input>';
939 - x += '&nbsp;<img src=images/link4.png height=10 width=10 title="' + "Copy valid codes to clipboard" + '" style=cursor:pointer onclick=copyTextToClip2("' + encodeURIComponent(clipb) + '")>';
940 - }
941 - x += '</div><br />';
942 - setDialogMode(2, "Manage Backup Codes", 8, null, x, 'otpauth-manage');
943 - break;
944 - }
945 - case 'otp-hkey-get': {
946 - if (xxdialogMode && (xxdialogTag != 'otpauth-hardware-manage')) return;
947 - var start = '<div style="border-radius:6px;border:2px solid #CCC;background-color:#BBB;width:100%;box-sizing:border-box;margin-bottom:6px"><div style="margin:3px;font-family:Arial, Helvetica, sans-serif;font-size:16px;font-weight:bold"><table style=width:100%;text-align:left>';
948 - var end = '</table></div></div>';
949 - var x = "<a href=\"https://www.yubico.com/\" rel=\"noreferrer noopener\" target=\"_blank\">Hardware keys</a> are used as secondary login authentication.";
950 - x += '<div style="max-height:150px;overflow-y:auto;overflow-x:hidden;margin-top:6px;margin-bottom:6px">';
951 - if (message.keys && message.keys.length > 0) {
952 - for (var i in message.keys) {
953 - var key = message.keys[i], type = (key.type == 2)?'OTP':'WebAuthn';
954 - x += start + '<tr style=margin:5px><td style=width:30px><img width=24 height=18 src="images/hardware-key-' + type + '-24.png" style=margin-top:4px><td style=width:250px>' + key.name + '<td><input type=button value="' + "Remove" + '" onclick=account_removehkey(' + key.i + ')></input>' + end;
955 - }
956 - } else {
957 - x += start + '<tr style=text-align:center><td>' + "No Keys Configured" + end;
958 - }
959 - x += '</div>';
960 - x += '<div><input type=button value="' + "Close" + '" onclick=setDialogMode(0) style=float:right></input>';
961 - if ((features & 0x00020000) != 0) { x += '<input id=d2addkey3 type=button value="' + "Add Key" + '" onclick="account_addhkey(3);"></input>'; }
962 - if ((features & 0x00004000) != 0) { x += '<input id=d2addkey2 type=button value="' + "Add YubiKey&reg; OTP" + '" onclick="account_addhkey(2);"></input>'; }
963 - x += '</div><br />';
964 - setDialogMode(2, "Manage Security Keys", 8, null, x, 'otpauth-hardware-manage');
965 - if (u2fSupported() == false) { QE('d2addkey1', false); }
966 - break;
967 - }
968 - case 'otp-hkey-yubikey-add': {
969 - if (message.result) {
970 - meshserver.send({ action: 'otp-hkey-get' }); // Success, ask for the full list of keys.
971 - } else {
972 - setDialogMode(2, "Add Security Key", 1, null, '<br />' + "Error, Unable to add key." + '<br /><br />');
973 - }
974 - break;
975 - }
976 - case 'otp-hkey-setup-response': {
977 - if (xxdialogMode && (xxdialogTag != 'otpauth-hardware-manage')) return;
978 - if (message.result == true) {
979 - meshserver.send({ action: 'otp-hkey-get' }); // Success, ask for the full list of keys.
980 - } else {
981 - setDialogMode(2, "Add Security Key", 1, null, '<br />' + "ERROR: Unable to add key." + '<br /><br />', 'otpauth-hardware-manage');
982 - }
983 - break;
984 - }
985 - case 'webauthn-startregister': {
986 - if (xxdialogMode && (xxdialogTag != 'otpauth-hardware-manage')) return;
987 - var x = "Press the key button now." + '<br /><br /><div style=width:100%;text-align:center><img width=120 height=117 src="images/hardware-keypress-120.png" /></div><input id=dp1keyname style=display:none value=' + message.name + ' />';
988 - setDialogMode(2, "Add Security Key", 2, null, x);
989 -
990 - var publicKey = message.request;
991 - message.request.challenge = Uint8Array.from(atob(message.request.challenge), function (c) { return c.charCodeAt(0) })
992 - message.request.user.id = Uint8Array.from(atob(message.request.user.id), function (c) { return c.charCodeAt(0) })
993 - navigator.credentials.create({ publicKey: publicKey })
994 - .then(function(newCredentialInfo) {
995 - // Public key credential
996 - var r = { rawId: btoa(String.fromCharCode.apply(null, new Uint8Array(newCredentialInfo.rawId))), response: { attestationObject: btoa(String.fromCharCode.apply(null, new Uint8Array(newCredentialInfo.response.attestationObject))), clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(newCredentialInfo.response.clientDataJSON))) }, type: newCredentialInfo.type };
997 - meshserver.send({ action: 'webauthn-endregister', response: r });
998 - setDialogMode(0);
999 - }, function(error) {
1000 - // Error
1001 - setDialogMode(2, "Add Security Key", 1, null, "ERROR: " + error);
1002 - });
1003 - break;
1004 - }
1005 - case 'event': {
1006 - if (!message.event.nolog) {
1007 - if (currentNode && (message.event.nodeid == currentNode._id)) {
1008 - // If this event has a nodeid and we are looking at this node, update the log in real time.
1009 - currentDeviceEvents.unshift(message.event);
1010 - var eventLimit = parseInt(p16limitdropdown.value);
1011 - while (currentDeviceEvents.length > eventLimit) { currentDeviceEvents.pop(); } // Remove element(s) at the end
1012 - masterUpdate(1024);
1013 - }
1014 -
1015 - if (currentUser && (message.event.userid == currentUser._id)) {
1016 - // If this event has a userid and we are looking at this user, update the log in real time.
1017 - currentUserEvents.unshift(message.event);
1018 - var eventLimit = parseInt(p31limitdropdown.value);
1019 - while (currentUserEvents.length > eventLimit) { currentUserEvents.pop(); } // Remove element(s) at the end
1020 - masterUpdate(2048);
1021 - }
1022 -
1023 - // Add this event to the master events log.
1024 - events.unshift(message.event);
1025 - var eventLimit = parseInt(p3limitdropdown.value);
1026 - while (events.length > eventLimit) { events.pop(); } // Remove element(s) at the end
1027 - masterUpdate(32);
1028 - }
1029 - if (message.event.noact) break; // Take no action on this event
1030 - switch (message.event.action) {
1031 - case 'userWebState': {
1032 - // New user web state, update the web page as needed
1033 - if (localStorage != null) {
1034 - var oldShowRealNames = localStorage.getItem('showRealNames');
1035 - var oldUiMode = localStorage.getItem('uiMode');
1036 - var oldSort = localStorage.getItem('sort');
1037 - var oldLoctag = localStorage.getItem('loctag');
1038 -
1039 - var webstate = JSON.parse(message.event.state);
1040 - for (var i in webstate) { localStorage.setItem(i, webstate[i]); }
1041 -
1042 - // Update the web page
1043 - if ((webstate.deskAspectRatio != null) && (webstate.deskAspectRatio != deskAspectRatio)) { deskAspectRatio = webstate.deskAspectRatio; deskAdjust(); }
1044 - if ((webstate.showRealNames != null) && (webstate.showRealNames != oldShowRealNames)) { showRealNames = Q('RealNameCheckBox').checked = (webstate.showRealNames == '1'); masterUpdate(6); }
1045 - if ((webstate.uiMode != null) && (webstate.uiMode != oldUiMode)) { userInterfaceSelectMenu(parseInt(webstate.uiMode)); }
1046 - if ((webstate.sort != null) && (webstate.sort != oldSort)) { document.getElementById('sortselect').selectedIndex = sort = parseInt(webstate.sort); masterUpdate(6); }
1047 - if ((webstate.loctag != null) && (webstate.loctag != oldLoctag)) { if (webstate.loctag != null) { args.locale = webstate.loctag; } else { delete args.locale; } masterUpdate(0xFFFFFFFF); }
1048 - }
1049 - break;
1050 - }
1051 - case 'servertimelinestats': { addServerTimelineStats(message.event.data); break; }
1052 - case 'accountcreate':
1053 - case 'accountchange': {
1054 - // An account was created or changed
1055 - if (userinfo.name == message.event.account.name) {
1056 - var newsiteadmin = message.event.account.siteadmin?message.event.account.siteadmin:0;
1057 - var oldsiteadmin = userinfo.siteadmin?userinfo.siteadmin:0;
1058 - if ((message.event.account.quota != userinfo.quota) || (((userinfo.siteadmin & 8) == 0) && ((message.event.account.siteadmin & 8) != 0))) { meshserver.send({ action: 'files' }); }
1059 - var oldgroups = userinfo.groups;
1060 - userinfo = message.event.account;
1061 - if (oldsiteadmin != newsiteadmin) updateSiteAdmin();
1062 - updateSelf();
1063 -
1064 - if ((userinfo.siteadmin & 2) != 0) {
1065 - // Compare our groups
1066 - var og = oldgroups ? oldgroups : [];
1067 - var ng = userinfo.groups ? userinfo.groups : [];
1068 - if (og.join(',') != ng.join(',')) {
1069 - // Our groups have changed, re-ask for a list of users.
1070 - users = wssessions = null;
1071 - meshserver.send({ action: 'users' });
1072 - meshserver.send({ action: 'wssessioncount' });
1073 - }
1074 - }
1075 - }
1076 - if (users == null) break;
1077 -
1078 - // Check if the account is part of our user group
1079 - if ((userinfo.groups == null) || (userinfo.groups.length == 0) || (findOne(message.event.account.groups, userinfo.groups) == true)) {
1080 - users[message.event.account._id] = message.event.account; // Part of our groups, update this user.
1081 - } else {
1082 - delete users[message.event.account._id]; // No longer part of our groups, remove this user.
1083 - }
1084 -
1085 - updateUsers();
1086 - break;
1087 - }
1088 - case 'accountremove': {
1089 - // An account was removed
1090 - if (users == null) break;
1091 - delete users['user/' + domain + '/' + message.event.username.toLowerCase()];
1092 - updateUsers();
1093 - break;
1094 - }
1095 - case 'createmesh': {
1096 - // A new mesh was created
1097 - if ((meshes[message.event.meshid] == null) && (message.event.links[userinfo._id] != null)) { // Check if this is a mesh create for a mesh we own. If site administrator, we get all messages so need to ignore some.
1098 - meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links };
1099 - masterUpdate(4 + 128);
1100 - meshserver.send({ action: 'files' });
1101 - }
1102 - break;
1103 - }
1104 - case 'meshchange': {
1105 - // Update mesh information
1106 - if (meshes[message.event.meshid] == null) {
1107 - // This is a new mesh for us
1108 - meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links };
1109 - meshserver.send({ action: 'nodes' }); // Request a refresh of all nodes (TODO: We could optimize this to only request nodes for the new mesh).
1110 - } else {
1111 - // This is an existing mesh
1112 - if (message.event.name != null) {
1113 - meshes[message.event.meshid].name = message.event.name;
1114 - for (var i in nodes) { if (nodes[i].meshid == message.event.meshid) { nodes[i].meshnamel = message.event.name.toLowerCase(); } }
1115 - }
1116 - if (message.event.desc != null) { meshes[message.event.meshid].desc = message.event.desc; }
1117 - if (message.event.flags != null) { meshes[message.event.meshid].flags = message.event.flags; }
1118 - if (message.event.consent != null) { meshes[message.event.meshid].consent = message.event.consent; }
1119 - if (message.event.links) { meshes[message.event.meshid].links = message.event.links; }
1120 - if (message.event.amt) { meshes[message.event.meshid].amt = message.event.amt; }
1121 -
1122 - // Check if we lost rights to this mesh in this change.
1123 - if (meshes[message.event.meshid].links[userinfo._id] == null) {
1124 - if ((xxcurrentView == 20) && (currentMesh == meshes[message.event.meshid])) go(2);
1125 - delete meshes[message.event.meshid];
1126 -
1127 - // Delete all nodes in that mesh
1128 - var newnodes = [];
1129 - for (var i in nodes) { if (nodes[i].meshid != message.event.meshid) { newnodes.push(nodes[i]); } }
1130 - nodes = newnodes;
1131 -
1132 - // If we are looking at a node in the deleted mesh, move back to "My Devices"
1133 - if (xxcurrentView >= 10 && xxcurrentView < 20 && currentNode && currentNode.meshid == message.event.meshid) { setDialogMode(0); go(1); }
1134 - }
1135 - }
1136 - masterUpdate(4 + 128);
1137 - if (currentNode && (currentNode.meshid == message.event.meshid)) { currentNode = null; if ((xxcurrentView >= 10) && (xxcurrentView < 20)) { go(1); } }
1138 - //meshserver.send({ action: 'files' }); // TODO: Why do we need to do this??
1139 -
1140 - // If we are looking at a mesh that is now deleted, move back to "My Account"
1141 - if (xxcurrentView == 20 && currentMesh._id == message.event.meshid) { masterUpdate(4096); }
1142 - break;
1143 - }
1144 - case 'deletemesh': {
1145 - // Delete the mesh
1146 - if (meshes[message.event.meshid]) {
1147 - delete meshes[message.event.meshid];
1148 - masterUpdate(128);
1149 - meshserver.send({ action: 'files' });
1150 - }
1151 -
1152 - // Delete all nodes in that mesh
1153 - var newnodes = [];
1154 - if (nodes != null) { for (var i in nodes) { if (nodes[i].meshid != message.event.meshid) { newnodes.push(nodes[i]); } } }
1155 - nodes = newnodes;
1156 - masterUpdate(4);
1157 -
1158 - // If we are looking at a mesh that is now deleted, move back to "My Account"
1159 - if (xxcurrentView >= 20 && xxcurrentView < 30 && currentMesh._id == message.event.meshid) { setDialogMode(0); go(2); }
1160 - // If we are looking at a node in the deleted mesh, move back to "My Devices"
1161 - if (xxcurrentView >= 10 && xxcurrentView < 20 && currentNode && currentNode.meshid == message.event.meshid) { setDialogMode(0); go(1); }
1162 -
1163 - break;
1164 - }
1165 - case 'addnode': {
1166 - var node = message.event.node;
1167 - if (!meshes[node.meshid]) break; // This is a node for a mesh we don't know. Happens when we are site administrator, we get all messages.
1168 - if (getNodeFromId(node._id) != null) break; // This node is already known.
1169 - node.namel = node.name.toLowerCase();
1170 - if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
1171 - node.meshnamel = meshes[node.meshid].name.toLowerCase();
1172 - node.state = 0;
1173 - if (!node.icon) node.icon = 1;
1174 - node.ident = ++nodeShortIdent;
1175 - if (nodes == null) { }
1176 - nodes.push(node);
1177 -
1178 - // Web page update
1179 - masterUpdate(1 | 2 | 4 | 16);
1180 -
1181 - break;
1182 - }
1183 - case 'removenode': {
1184 - var index = -1;
1185 - for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
1186 - if (index != -1) {
1187 - var node = nodes[index];
1188 - if (currentNode == node) {
1189 - if (xxcurrentView >= 10 && xxcurrentView < 20) { setDialogMode(0); go(1); }
1190 - currentNode = null;
1191 - // TODO: Correctly disconnect from this node (Desktop/Terminal/Files...)
1192 - }
1193 - nodes.splice(index, 1);
1194 -
1195 - // Web page update
1196 - masterUpdate(4 | 16);
1197 - }
1198 - break;
1199 - }
1200 - case 'changenode': {
1201 - var index = -1;
1202 - for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
1203 - if (index != -1) {
1204 - var node = nodes[index];
1205 -
1206 - // Change the node
1207 - node.name = message.event.node.name;
1208 - node.rname = message.event.node.rname;
1209 - node.users = message.event.node.users;
1210 - node.host = message.event.node.host;
1211 - node.desc = message.event.node.desc;
1212 - node.ip = message.event.node.ip;
1213 - node.osdesc = message.event.node.osdesc;
1214 - node.publicip = message.event.node.publicip;
1215 - node.iploc = message.event.node.iploc;
1216 - node.wifiloc = message.event.node.wifiloc;
1217 - node.gpsloc = message.event.node.gpsloc;
1218 - node.tags = message.event.node.tags;
1219 - node.userloc = message.event.node.userloc;
1220 - if (message.event.node.agent != null) {
1221 - if (node.agent == null) node.agent = {};
1222 - if (message.event.node.agent.ver != null) { node.agent.ver = message.event.node.agent.ver; }
1223 - if (message.event.node.agent.id != null) { node.agent.id = message.event.node.agent.id; }
1224 - if (message.event.node.agent.caps != null) { node.agent.caps = message.event.node.agent.caps; }
1225 - if (message.event.node.agent.core != null) { node.agent.core = message.event.node.agent.core; } else { if (node.agent.core) { delete node.agent.core; } }
1226 - node.agent.tag = message.event.node.agent.tag;
1227 - }
1228 - if (message.event.node.intelamt != null) {
1229 - if (node.intelamt == null) node.intelamt = {};
1230 - if (message.event.node.intelamt.state != null) { node.intelamt.state = message.event.node.intelamt.state; }
1231 - if (message.event.node.intelamt.host != null) { node.intelamt.user = message.event.node.intelamt.host; }
1232 - if (message.event.node.intelamt.user != null) { node.intelamt.user = message.event.node.intelamt.user; }
1233 - if (message.event.node.intelamt.tls != null) { node.intelamt.tls = message.event.node.intelamt.tls; }
1234 - if (message.event.node.intelamt.ver != null) { node.intelamt.ver = message.event.node.intelamt.ver; }
1235 - if (message.event.node.intelamt.tag != null) { node.intelamt.tag = message.event.node.intelamt.tag; }
1236 - if (message.event.node.intelamt.uuid != null) { node.intelamt.uuid = message.event.node.intelamt.uuid; }
1237 - if (message.event.node.intelamt.realm != null) { node.intelamt.realm = message.event.node.intelamt.realm; }
1238 - }
1239 - if (message.event.node.av != null) { node.av = message.event.node.av; }
1240 - node.namel = node.name.toLowerCase();
1241 - if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
1242 - if (message.event.node.icon) { node.icon = message.event.node.icon; }
1243 -
1244 - // Web page update
1245 - masterUpdate(2 | 4 | 8 | 16);
1246 - refreshDevice(node._id);
1247 -
1248 - if ((currentNode == node) && (xxdialogMode != null) && (xxdialogTag == '@xxmap')) { p10showNodeLocationDialog(); }
1249 - }
1250 - break;
1251 - }
1252 - case 'nodemeshchange': {
1253 - var index = -1;
1254 - for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
1255 - if (index != -1) {
1256 - var node = nodes[index];
1257 - if (meshes[message.event.newMeshId] == null) {
1258 - // We don't see the new mesh, remove this device
1259 -
1260 - // TODO: Correctly disconnect from this node (Desktop/Terminal/Files...)
1261 - if (currentNode == node) { if (xxcurrentView >= 10 && xxcurrentView < 20) { setDialogMode(0); go(1); } currentNode = null; }
1262 - nodes.splice(index, 1);
1263 - masterUpdate(4 | 16);
1264 - } else {
1265 - // We see the new mesh, move this device
1266 - node.meshid = message.event.newMeshId;
1267 - node.meshnamel = meshes[message.event.newMeshId].name.toLowerCase();
1268 - masterUpdate(1 | 2 | 4);
1269 - }
1270 - refreshDevice(message.event.nodeid);
1271 - } else {
1272 - // This is a new device, add it.
1273 - var node = message.event.node;
1274 - if (!meshes[node.meshid]) break; // This is a node for a mesh we don't know. Happens when we are site administrator, we get all messages.
1275 - node.namel = node.name.toLowerCase();
1276 - if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
1277 - node.meshnamel = meshes[node.meshid].name.toLowerCase();
1278 - node.state = 0;
1279 - if (!node.icon) node.icon = 1;
1280 - node.ident = ++nodeShortIdent;
1281 - if (nodes == null) { }
1282 - nodes.push(node);
1283 -
1284 - // Web page update
1285 - masterUpdate(1 | 2 | 4 | 16);
1286 - }
1287 - break;
1288 - }
1289 - case 'nodeconnect': {
1290 - // Indicated a node has changed connectivity state
1291 - var index = -1;
1292 - for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
1293 - if (index != -1) {
1294 - var node = nodes[index];
1295 -
1296 - // Event the connection change if needed
1297 - var n = getstore('notifications', 0); // Account notification settings
1298 -
1299 - // Per-group notification settings
1300 - if (message.event.meshid && userinfo.links && userinfo.links[message.event.meshid] && userinfo.links[message.event.meshid].notify) {
1301 - n &= userinfo.links[message.event.meshid].notify;
1302 - } else {
1303 - n = 0;
1304 - }
1305 -
1306 - // Show the notification
1307 - if (n & 2) {
1308 - if (((node.conn & 1) == 0) && ((message.event.conn & 1) != 0)) { addNotification({ text: "Agent connected", title: node.name, icon: node.icon, nodeid: node._id }); }
1309 - if (((node.conn & 2) == 0) && ((message.event.conn & 2) != 0)) { addNotification({ text: "Intel AMT detected", title: node.name, icon: node.icon, nodeid: node._id }); }
1310 - if (((node.conn & 4) == 0) && ((message.event.conn & 4) != 0)) { addNotification({ text: "Intel AMT CIRA connected", title: node.name, icon: node.icon, nodeid: node._id }); }
1311 - if (((node.conn & 16) == 0) && ((message.event.conn & 16) != 0)) { addNotification({ text: "MQTT connected", title: node.name, icon: node.icon, nodeid: node._id }); }
1312 - }
1313 - if (n & 4) {
1314 - if (((node.conn & 1) != 0) && ((message.event.conn & 1) == 0)) { addNotification({ text: "Agent disconnected", title: node.name, icon: node.icon, nodeid: node._id }); }
1315 - if (((node.conn & 2) != 0) && ((message.event.conn & 2) == 0)) { addNotification({ text: "Intel AMT not detected", title: node.name, icon: node.icon, nodeid: node._id }); }
1316 - if (((node.conn & 4) != 0) && ((message.event.conn & 4) == 0)) { addNotification({ text: "Intel AMT CIRA disconnected", title: node.name, icon: node.icon, nodeid: node._id }); }
1317 - if (((node.conn & 16) != 0) && ((message.event.conn & 16) == 0)) { addNotification({ text: "MQTT disconnected", title: node.name, icon: node.icon, nodeid: node._id }); }
1318 - }
1319 -
1320 - // Change the node connection state
1321 - node.conn = message.event.conn;
1322 - node.pwr = message.event.pwr;
1323 -
1324 - // Web page update
1325 - masterUpdate(4 | 16);
1326 - refreshDevice(node._id);
1327 - }
1328 - break;
1329 - }
1330 - case 'wssessioncount': {
1331 - // Update the active web socket session count for a user
1332 - if (wssessions != null) {
1333 - if (message.event.count == 0 && wssessions['user/' + domain + '/' + message.event.username.toLowerCase()]) {
1334 - delete wssessions['user/' + domain + '/' + message.event.username.toLowerCase()];
1335 - } else {
1336 - wssessions['user/' + domain + '/' + message.event.username.toLowerCase()] = message.event.count;
1337 - }
1338 - updateUsers();
1339 - }
1340 - break;
1341 - }
1342 - case 'login': {
1343 - // Update the last login time
1344 - if (users != null && users['user/' + domain + '/' + message.event.username.toLowerCase()]) {
1345 - users['user/' + domain + '/' + message.event.username.toLowerCase()].login = Math.floor(new Date(message.event.time).getTime() / 1000);
1346 - }
1347 - break;
1348 - }
1349 - case 'scanamtdevice': {
1350 - // Populate the Intel AMT scan dialog box with the result of the RMCP scan
1351 - if ((xxdialogMode == null) || (!Q('dp1range')) || (Q('dp1range').value != message.event.range)) return;
1352 - var x = '';
1353 - if (message.event.results == null) {
1354 - // The scan could not occur because of an error. Likely the user range was invalid.
1355 - x = '<div style=width:100%;text-align:center;margin-top:12px>' + "Unable to scan this address range." + '</div><div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>' + "Sample IP range values<br />192.168.0.100<br />192.168.1.0/24<br />192.167.0.1-192.168.0.100" + '</div>';
1356 - } else {
1357 - // Go thru all the results and populate the dialog box
1358 - amtScanResults = message.event.results;
1359 - for (var i in message.event.results) {
1360 - var r = message.event.results[i], shortname = r.hostname;
1361 - if (shortname.length > 20) { shortname = shortname.substring(0, 20) + '...'; }
1362 - var str = '<b title="' + EscapeHtml(r.hostname) + '">' + EscapeHtml(shortname) + '</b> - v' + r.ver;
1363 - if (r.state == 2) { if (r.tls == 1) { str += " with TLS."; } else { str += " without TLS."; } } else { str += ' not activated.'; }
1364 - x += '<div style=width:100%;margin-bottom:2px;background-color:lightgray><div style=padding:4px><div style=display:inline-block;margin-right:5px><input class=DevScanCheckbox name=dp1checkbox tag="' + EscapeHtml(i) + '" type=checkbox onclick=addAmtScanToMeshCheckbox() /></div><div class=j1 style=display:inline-block></div><div style=display:inline-block;margin-left:5px;overflow-x:auto;white-space:nowrap>' + str + '</div></div></div>';
1365 - }
1366 - // If no results where found, display a nice message
1367 - if (x == '') { x = '<div style=width:100%;text-align:center;margin-top:12px>Scan returned no results.</div><div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>Sample IP range values<br />192.168.0.100<br />192.168.1.0/24<br />192.167.0.1-192.168.0.100</div>'; }
1368 - }
1369 - // Set the html in the dialog box and re-enable the scan button
1370 - QH('dp1results', x);
1371 - QE('dp1range', true);
1372 - QE('dp1rangebutton', true);
1373 - break;
1374 - }
1375 - case 'notify': {
1376 - var n = { text: message.event.value, title: message.event.title, icon: message.event.icon };
1377 - if (message.event.tag != null) { n.tag = message.event.tag; }
1378 - addNotification(n);
1379 - break;
1380 - }
1381 - case 'traceinfo': {
1382 - if (typeof message.event.traceSources == 'object') {
1383 - if ((message.event.traceSources != null) && (message.event.traceSources.length > 0)) {
1384 - serverTraceSources = message.event.traceSources;
1385 - QH('p41traceStatus', EscapeHtml(message.event.traceSources.join(', ')));
1386 - } else {
1387 - serverTraceSources = [];
1388 - QH('p41traceStatus', "None");
1389 - }
1390 - }
1391 - break;
1392 - }
1393 - case 'sysinfohash': {
1394 - // If the sysinfo document has changed and we are looking at it, request an update.
1395 - if ((currentNode != null) && (message.event.nodeid == powerTimelineReq)) {
1396 - meshserver.send({ action: 'getsysinfo', nodeid: message.event.nodeid });
1397 - }
1398 - break;
1399 - }
1400 - case 'stopped': { // Server is stopping.
1401 - // Disconnect
1402 - //console.log(message.msg);
1403 - break;
1404 - }
1405 - case 'updatePluginList': {
1406 - installedPluginList = message.event.list;
1407 - updatePluginList();
1408 - break;
1409 - }
1410 - case 'pluginStateChange': {
1411 - if (pluginHandler == null) break;
1412 - pluginHandler.refreshPluginHandler();
1413 - break;
1414 - }
1415 - case 'plugin': {
1416 - if (pluginHandler == null) break;
1417 - try { pluginHandler[message.event.plugin][message.event.pluginaction](message); } catch (e) { console.log("PluginHandler could not event message: ", e); }
1418 - break;
1419 - }
1420 - default:
1421 - //console.log('Unknown message.event.action', message.event.action);
1422 - break;
1423 - }
1424 - break;
1425 - }
1426 - case 'createInviteLink': { // Agent installation invitation link
1427 - if (xxdialogTag != message.meshid) break;
1428 - var servername = serverinfo.name;
1429 - if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
1430 - var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
1431 - var url;
1432 - if (serverinfo.https == true) {
1433 - var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
1434 - url = 'https://' + servername + portStr + domainUrl + 'agentinvite?c=' + message.cookie;
1435 - } else {
1436 - var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
1437 - url = 'http://' + servername + portStr + domainUrl + 'agentinvite?c=' + message.cookie;
1438 - }
1439 - Q('agentInvitationLink').href = url;
1440 - var t = format("{0} hour{1}", message.expire, addLetterS(message.expire));
1441 - if (message.expire == 24) { t = "1 day"; }
1442 - if (message.expire == 168) { t = "1 week"; }
1443 - if (message.expire == 5040) { t = "1 month"; }
1444 - if (message.expire == 0) { t = "Unlimited"; }
1445 - QH('agentInvitationLink', format("Invitation Link ({0})", t));
1446 - QV('agentInvitationLinkDiv', true);
1447 - break;
1448 - }
1449 - case 'getmqttlogin': {
1450 - if ((currentNode == null) || (currentNode._id != message.nodeid) || (xxdialogMode != null)) return;
1451 - var x = "These settings can be used to connect MQTT for this device." + '<br /><br />';
1452 - delete message.action;
1453 - delete message.nodeid;
1454 - x += '<textarea readonly=readonly style=width:100%;resize:none;height:100px;overflow:auto;font-size:12px readonly>' + JSON.stringify(message) + '</textarea>';
1455 - /*
1456 - x += addHtmlValue('Username', '<input style=width:230px readonly value="' + message.user + '" />');
1457 - x += addHtmlValue('Password', '<input style=width:230px readonly value="' + message.pass + '" />');
1458 - x += addHtmlValue('WS URL', '<input style=width:230px readonly value="' + message.wsUrl + '" />');
1459 - if (message.mpsUrl && message.mpsCertHash) {
1460 - x += addHtmlValue('MPS URL', '<input style=width:230px readonly value="' + message.mpsUrl + '" />');
1461 - x += addHtmlValue('MPS Cert Hash', '<input style=width:230px readonly value="' + message.mpsCertHash + '" />');
1462 - }
1463 - */
1464 - setDialogMode(2, "MQTT Credentials", 1, null, x);
1465 - break;
1466 - }
1467 - case 'stopped': { // Server is stopping.
1468 - // Disconnect
1469 - autoReconnect = false;
1470 - QH('p0span', message.msg);
1471 - break;
1472 - }
1473 - case 'updatePluginList': {
1474 - installedPluginList = message.list;
1475 - updatePluginList();
1476 - break;
1477 - }
1478 - case 'pluginVersionsAvailable': {
1479 - if (pluginHandler == null) break;
1480 - updatePluginList(message.list);
1481 - break;
1482 - }
1483 - case 'downgradePluginVersions': {
1484 - var vSelect = '<select id="lastPluginVersion">';
1485 - message.info.versionList.forEach(function(v) { vSelect += '<option value="' + v.zipball_url + '">' + v.name + '</option>'; });
1486 - vSelect += '</select>';
1487 - setDialogMode(2, "Plugin Action", 3, pluginActionEx, format('Select the version to downgrade the plugin: {0}', message.info.name) + '<hr />' + vSelect + '<hr />' + "Please be aware that downgrading is not recommended. Please only do so in the event that a recent upgrade has broken something." + + '<input id="lastPluginAct" type="hidden" value="downgrade" /><input id="lastPluginId" type="hidden" value="' + message.info.id + '" />');
1488 - break;
1489 - }
1490 - case 'pluginError': {
1491 - setDialogMode(2, "Plugin Error", 1, null, message.msg);
1492 - break;
1493 - }
1494 - case 'plugin': {
1495 - if ((pluginHandler == null) || (typeof message.plugin != 'string')) break;
1496 - try { pluginHandler[message.plugin][message.method](server, message); } catch (e) { console.log('Error loading plugin handler ('+ e + ')'); }
1497 - break;
1498 - }
1499 - default:
1500 - //console.log('Unknown message.action', message.action);
1501 - break;
1502 - }
1503 - }
1504 -
1505 - //
1506 - // MY DEVICES
1507 - //
1508 -
1509 - function onRealNameCheckBox() {
1510 - showRealNames = Q('RealNameCheckBox').checked;
1511 - putstore('showRealNames', showRealNames ? 1 : 0);
1512 - masterUpdate(6);
1513 - return;
1514 - }
1515 -
1516 - function onDeviceViewChange(i) {
1517 - if (i != null) { Q('viewselect').value = i; }
1518 - for (var j = 1; j < 5; j++) { Q('devViewButton' + j).classList.remove('viewSelectorSel'); }
1519 - Q('devViewButton' + Q('viewselect').value).classList.add('viewSelectorSel');
1520 - putstore('_deviceView', Q('viewselect').value);
1521 - putstore('_viewsize', Q('sizeselect').value);
1522 - masterUpdate(4);
1523 - setTimeout(function () { masterUpdate(512); }, 200);
1524 - }
1525 -
1526 - function ondockeypress(e) {
1527 - setSessionActivity();
1528 - if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
1529 - // Check what keys we are allows to send
1530 - if (currentNode != null) {
1531 - var mesh = meshes[currentNode.meshid];
1532 - var meshrights = mesh.links[userinfo._id].rights;
1533 - var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
1534 - if (inputAllowed == false) return false;
1535 - var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
1536 - if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
1537 - }
1538 - return desktop.m.handleKeys(e);
1539 - }
1540 - if (!xxdialogMode && xxcurrentView == 12 && terminal && terminal.State == 3) { return terminal.m.TermHandleKeys(e); }
1541 - if (!xxdialogMode && ((xxcurrentView == 15) || (xxcurrentView == 115))) return agentConsoleHandleKeys(e);
1542 - if (!xxdialogMode && xxcurrentView == 4) {
1543 - if (e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
1544 - var processed = 0;
1545 - if (e.key) {
1546 - if (e.key.length === 1 && userSearchFocus == 0) { Q('UserSearchInput').value = ((Q('UserSearchInput').value + e.key)); processed = 1; }
1547 - if (e.keyCode == 8 && userSearchFocus == 0) { var x = Q('UserSearchInput').value; Q('UserSearchInput').value = x.substring(0, x.length - 1); processed = 1; }
1548 - if (e.keyCode == 27) { Q('UserSearchInput').value = ''; processed = 1; }
1549 - } else {
1550 - if (e.charCode != 0 && userSearchFocus == 0) { Q('UserSearchInput').value = ((Q('UserSearchInput').value + String.fromCharCode(e.charCode))); processed = 1; }
1551 - }
1552 - if (processed > 0) { if (processed == 1) { onUserSearchInputChanged(); } return haltEvent(e); }
1553 - }
1554 - if (xxdialogMode || xxcurrentView != 1) return;
1555 - if (e.ctrlKey == true && e.charCode == 96) {
1556 - showRealNames = !showRealNames;
1557 - Q('RealNameCheckBox').value = showRealNames;
1558 - putstore('showRealNames', showRealNames ? 1 : 0);
1559 - masterUpdate(6)
1560 - return;
1561 - }
1562 - if (e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
1563 - if (Q('viewselect').value < 3) {
1564 - var processed = 0;
1565 - if (e.key) {
1566 - if (e.key.length === 1 && searchFocus == 0) { Q('SearchInput').value = ((Q('SearchInput').value + e.key)); processed = 1; }
1567 - if (e.keyCode == 8 && searchFocus == 0) { var x = Q('SearchInput').value; Q('SearchInput').value = x.substring(0, x.length - 1); processed = 1; }
1568 - if (e.keyCode == 27) { Q('SearchInput').value = ''; processed = 1; }
1569 - } else {
1570 - if (e.charCode != 0 && searchFocus == 0) { Q('SearchInput').value = ((Q('SearchInput').value + String.fromCharCode(e.charCode))); processed = 1; }
1571 - }
1572 - if (processed > 0) { if (processed == 1) { masterUpdate(5); } return haltEvent(e); }
1573 - }
1574 - if (Q('viewselect').value == 3) {
1575 - if (e.key) {
1576 - if (e.key.length === 1 && mapSearchFocus == 0) { Q('mapSearchLocation').value = ((Q('mapSearchLocation').value + e.key)); processed = 1; }
1577 - //if (e.keyCode == 8 && mapSearchFocus == 0) { var x = Q('mapSearchLocation').value; Q('mapSearchLocation').value = x.substring(0, x.length - 1); processed = 1; }
1578 - if (e.keyCode == 27) { Q('mapSearchLocation').value = ''; mapCloseSearchWindow(); processed = 1; }
1579 - if (e.keyCode == 13) { getSearchLocation(); }
1580 - } else {
1581 - if (e.charCode != 0 && mapSearchFocus == 0) { Q('mapSearchLocation').value = ((Q('mapSearchLocation').value + String.fromCharCode(e.charCode))); processed = 1; }
1582 - }
1583 - }
1584 - }
1585 -
1586 - function ondockeydown(e) {
1587 - setSessionActivity();
1588 - if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
1589 - // Check what keys we are allows to send
1590 - if (currentNode != null) {
1591 - var mesh = meshes[currentNode.meshid];
1592 - var meshrights = mesh.links[userinfo._id].rights;
1593 - var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
1594 - if (inputAllowed == false) return false;
1595 - var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
1596 - if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
1597 - }
1598 - return desktop.m.handleKeyDown(e);
1599 - }
1600 - if (!xxdialogMode && xxcurrentView == 12 && terminal && terminal.State == 3) { terminal.m.TermHandleKeyDown(e); if ((e.keyCode >= 37) && (e.keyCode <= 40)) { haltEvent(e); } }
1601 - if (!xxdialogMode && xxcurrentView == 13 && e.keyCode == 116 && p13filetree != null) { haltEvent(e); return false; } // F5 Refresh on files
1602 - if (!xxdialogMode && ((xxcurrentView == 15) || (xxcurrentView == 115))) { return agentConsoleHandleKeys(e); }
1603 - if (!xxdialogMode && xxcurrentView == 4) {
1604 - if (e.keyCode === 8 && userSearchFocus == 0) { var x = Q('UserSearchInput').value; Q('UserSearchInput').value = (x.substring(0, x.length - 1)); processed = 1; }
1605 - if (e.keyCode === 27) { Q('UserSearchInput').value = ''; processed = 1; }
1606 - if (processed > 0) { if (processed == 1) { masterUpdate(5); } return haltEvent(e); }
1607 - }
1608 - if (xxdialogMode || xxcurrentView != 1 || e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
1609 - var processed = 0;
1610 - if (Q('viewselect').value < 3) {
1611 - if (e.keyCode === 8 && searchFocus == 0) { var x = Q('SearchInput').value; Q('SearchInput').value = (x.substring(0, x.length - 1)); processed = 1; }
1612 - if (e.keyCode === 27) { Q('SearchInput').value = ''; processed = 1; }
1613 - if (processed > 0) { if (processed == 1) { masterUpdate(5); } return haltEvent(e); }
1614 - }
1615 - if (Q('viewselect').value == 3) {
1616 - if (e.keyCode === 8 && mapSearchFocus == 0) { var x = Q('mapSearchLocation').value; Q('mapSearchLocation').value = (x.substring(0, x.length - 1)); processed = 1; }
1617 - if (e.keyCode === 27) { Q('mapSearchLocation').value = ''; mapCloseSearchWindow(); processed = 1; }
1618 - }
1619 - }
1620 -
1621 - function ondockeyup(e) {
1622 - setSessionActivity();
1623 - if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
1624 - // Check what keys we are allows to send
1625 - if (currentNode != null) {
1626 - var mesh = meshes[currentNode.meshid];
1627 - var meshrights = mesh.links[userinfo._id].rights;
1628 - var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
1629 - if (inputAllowed == false) return false;
1630 - var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
1631 - if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
1632 - }
1633 - return desktop.m.handleKeyUp(e);
1634 - }
1635 - if (!xxdialogMode && xxcurrentView == 12 && terminal && terminal.State == 3) { return terminal.m.TermHandleKeyUp(e); }
1636 - if (!xxdialogMode && xxcurrentView == 13 && e.keyCode == 116 && p13filetree != null) { p13folderup(9999); haltEvent(e); return false; } // F5 Refresh on files
1637 - if (!xxdialogMode && xxcurrentView == 4) { if ((e.keyCode === 8 && searchFocus == 0) || e.keyCode === 27) { return haltEvent(e); } }
1638 - if (xxdialogMode && e.keyCode == 27) { dialogclose(0); }
1639 - if (xxdialogMode || xxcurrentView != 0 || e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
1640 - if (Q('viewselect').value < 3) { if ((e.keyCode === 8 && searchFocus == 0) || e.keyCode === 27) { return haltEvent(e); } }
1641 - if (Q('viewselect').value == 3) { if ((e.keyCode === 8 && mapSearchFocus == 0) || e.keyCode === 27) { return haltEvent(e); } }
1642 - }
1643 -
1644 - //function ondocfocus() { }
1645 - // TODO: Add handleReleaseKeys() for Intel AMT.
1646 - function ondocblur() { if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked && desktop.m.handleReleaseKeys) { return desktop.m.handleReleaseKeys(); } }
1647 -
1648 - // Highlights the device being hovered
1649 - function devMouseHover(element, over) {
1650 - setSessionActivity();
1651 - var view = Q('viewselect').value;
1652 - if (view == 1) {
1653 - var e = element.children[1].children[1];
1654 - e.children[0].classList.remove('g1s');
1655 - e.children[1].classList.remove('e2s');
1656 - e.children[2].classList.remove('g2s');
1657 - if (over == 1) {
1658 - e.children[0].classList.add('g1s');
1659 - e.children[1].classList.add('e2s');
1660 - e.children[2].classList.add('g2s');
1661 - }
1662 - } else if (view == 2) {
1663 - var e = element;
1664 - e.children[2].classList.remove('g1s');
1665 - e.children[4].classList.remove('e2s');
1666 - e.children[3].classList.remove('g2s');
1667 - if (over == 1) {
1668 - e.children[2].classList.add('g1s');
1669 - e.children[4].classList.add('e2s');
1670 - e.children[3].classList.add('g2s');
1671 - }
1672 - }
1673 - }
1674 -
1675 - var deviceHeaderId = 0;
1676 - var deviceHeaderTotal = 0;
1677 - var deviceHeadersTitles = {};
1678 - var deviceHeaderCount;
1679 - var deviceHeaders = {};
1680 - var oldviewmode = 0;
1681 - function updateDevices() {
1682 - if (nodes == null) { return; }
1683 - var r = '', c = 0, current = null, count = 0, scount = 0, displayedMeshes = {}, view = Q('viewselect').value, groups = {}, groupCount = {};
1684 - QV('xdevices', view < 4);
1685 - QV('xdevicesmap', view == 4);
1686 - QV('devListToolbar', view < 3);
1687 - QV('kvmListToolbar', view == 3);
1688 - QV('devMapToolbar', view == 4);
1689 - QV('devListToolbarSize', view == 3);
1690 - QV('NoMeshesPanel', meshcount == 0);
1691 - //QV('devListToolbarView', (meshcount != 0) && (nodes.length > 0));
1692 - QV('devListToolbarViewIcons', (meshcount != 0) && (nodes.length > 0));
1693 - QV('devListToolbarSort', (meshcount != 0) && (nodes.length > 0) && (view < 4));
1694 - if ((meshcount == 0) || (nodes.length == 0)) { view = 1; sort = 0; }
1695 - if (view == 4) {
1696 - setTimeout( function() { if (xxmap.map != null) { xxmap.map.updateSize(); } }, 200);
1697 - // TODO
1698 - } else {
1699 - // 3 wide, list view or desktop view
1700 - deviceHeaderId = 0;
1701 - deviceHeaderCount = {};
1702 - deviceHeaderTotal = 0;
1703 - deviceHeaders = {};
1704 - deviceHeadersTitles = {};
1705 - var kvmDivs = [];
1706 -
1707 - // Perform node sort
1708 - if (sort == 0) { nodes.sort(meshSort); }
1709 - else if (sort == 1) { nodes.sort(powerSort); }
1710 - else if (sort == 2) { if (showRealNames == true) { nodes.sort(deviceHostSort); } else { nodes.sort(deviceSort); } }
1711 -
1712 - // Save the list of currently checked nodeid's
1713 - var checkedNodeids = [], elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
1714 - for (var i=0;i<elements.length;i++) { if (elements[i].checked) { checkedNodeids.push(elements[i].value); } }
1715 - if ((oldviewmode < 3) && (view == 3)) { multiDesktopFilter = checkedNodeids; }
1716 - else if ((oldviewmode == 3) && (view < 3)) { checkedNodeids = multiDesktopFilter; }
1717 -
1718 - // Compute the width of the device view.
1719 - var totalDeviceViewWidth = Q('column_l').clientWidth - 60;
1720 - var deviceBoxWidth = Math.floor(totalDeviceViewWidth / 301);
1721 - deviceBoxWidth = 301 + Math.floor((totalDeviceViewWidth - (deviceBoxWidth * 301)) / deviceBoxWidth);
1722 -
1723 - // Go thru the list of nodes and display them
1724 - for (var i in nodes) {
1725 - var node = nodes[i];
1726 - if (node.v == false) continue;
1727 - var mesh2 = meshes[node.meshid], meshlinks = mesh2.links[userinfo._id];
1728 - if (meshlinks == null) continue;
1729 - var meshrights = meshlinks.rights;
1730 - if ((view == 3) && (mesh2.mtype == 1)) continue;
1731 - if (sort == 0) {
1732 - // Mesh header
1733 - if (node.meshid != current) {
1734 - deviceHeaderSet();
1735 - var extra = '';
1736 - if (view == 2) { r += '<tr><td colspan=5>'; }
1737 - if (meshes[node.meshid].mtype == 1) { extra = '<span class=devHeaderx>' + ", Intel&reg; AMT only" + '</span>'; }
1738 - if ((view == 1) && (current != null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
1739 - if (view == 2) { r += '<div>'; }
1740 - r += '<div class=DevSt style=width:100%;padding-top:4px><span style=float:right>';
1741 - r += '<span id=DevxHeader' + deviceHeaderId + ' class=devHeaderx></span>' + extra;
1742 - r += '</span><span id=MxMESH tabindex=0 style=cursor:pointer onclick=gotoMesh("' + node.meshid + '") onkeypress="if (event.key==\'Enter\') gotoMesh(\'' + node.meshid + '\')">' + EscapeHtml(meshes[node.meshid].name) + '</span>' + getMeshActions(mesh2, meshrights) + '</div>';
1743 - if (view == 2) { r += '</div>'; }
1744 - current = node.meshid;
1745 - displayedMeshes[current] = 1;
1746 - c = 0;
1747 - }
1748 - } else if (sort == 1) {
1749 - // Power header
1750 - var pwr = node.pwr?node.pwr:0;
1751 - if (pwr !== current) {
1752 - deviceHeaderSet();
1753 - if ((view == 1) && (current !== null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
1754 -
1755 - if (view == 2) { r += '<tr><td>'; }
1756 - r += '<div class=DevSt style=width:100%;padding-top:4px><span id=DevxHeader' + deviceHeaderId + ' class=devHeaderx style=float:right></span><span>' + PowerStateStr2(node.pwr) + '</span></div>';
1757 -
1758 - current = pwr;
1759 - c = 0;
1760 - }
1761 - } else if (sort == 2) {
1762 - // Device header
1763 - if (current == null) { current = '1'; }
1764 - }
1765 -
1766 - count++;
1767 - var title = EscapeHtml(node.name);
1768 - if (title.length == 0) { title = '<i>' + "None" + '</i>'; }
1769 - if ((node.rname != null) && (node.rname.length > 0)) { title += ' / ' + EscapeHtml(node.rname); }
1770 - var name = EscapeHtml(node.name);
1771 - if (showRealNames == true && node.rname != null) name = EscapeHtml(node.rname);
1772 - if (name.length == 0) { name = '<i>' + "None" + '</i>'; }
1773 -
1774 - // Node
1775 - var icon = node.icon;
1776 - if ((!node.conn) || (node.conn == 0)) { icon += ' gray'; }
1777 - if (view == 1) {
1778 - r += '<div id=devs onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=display:inline-block;width:' + deviceBoxWidth + 'px;height:50px;padding-top:1px;padding-bottom:1px><div style=width:22px;height:50%;float:left;padding-top:12px><input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox></div><div style=height:100%;cursor:pointer tabindex=0 onclick=gotoDevice(\'' + node._id + '\',null,null,event) onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',null,null,event)"><div class="i' + icon + '" style=width:50px;float:left></div><div style=height:100%><div class=g1></div><div class=e2><div class=e1 style=width:' + (deviceBoxWidth - 100) + 'px title="' + title + '">' + name + '</div><div>' + NodeStateStr(node) + '</div></div><div class=g2></div></div></div></div>';
1779 - } else if (view == 2) {
1780 - var states = [];
1781 - 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." + '\">' + "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>'); }
1787 - }
1788 - r += '<tr><td><div id=devs class=bar18 tabindex=0 onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=height:18px;width:100%;font-size:medium onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',null,null,event)">';
1789 - r += '<div class=deviceBarCheckbox><input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox></div>';
1790 - r += '<div class=deviceBarIcon onclick=gotoDevice(\'' + node._id + '\',null,null,event)><div class=\"j' + icon + '\" style=width:16px;margin-top:1px;margin-left:2px;height:16px></div></div>';
1791 - r += '<div class=g1 style=height:18px;float:left></div><div class=g2 style=height:18px;float:right></div>';
1792 - r += '<div style=cursor:pointer;font-size:14px title="' + title + '" onclick=gotoDevice(\'' + node._id + '\',null,null,event)><span style=width:300px>' + name + '</span></div></div></td>';
1793 - r += '<td style=text-align:center>' + getUserShortStr(node);
1794 - r += '<td style=text-align:center>' + (node.ip != null ? node.ip : '');
1795 - r += '<td style=text-align:center>' + states.join('&nbsp;+&nbsp;');
1796 - //r += '<td style=text-align:center>' + (node.pwr != null ? powerStateStrings[node.pwr] : '');
1797 - r += '</tr>';
1798 - } else if ((view == 3) && (node.conn & 1) && (((meshrights & 8) || (meshrights & 256)) != 0) && ((node.agent.caps & 1) != 0)) { // Check if we have rights and agent is capable of KVM.
1799 - if ((multiDesktopFilter) && ((multiDesktopFilter.length == 0) || (multiDesktopFilter.indexOf('devid_' + node._id) >= 0))) {
1800 - r += '<div id=devs style=display:inline-block;margin:1px;background-color:lightgray;border-radius:5px;position:relative><div tabindex=0 style=padding:3px;cursor:pointer onclick=gotoDevice(\'' + node._id + '\',11,null,event) onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',11,null,event)">';
1801 - //r += '<input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox style=float:left>';
1802 - r += '<div class="j' + icon + '" style=width:16px;float:left></div>&nbsp;' + name + '</div>';
1803 - r += '<span onclick=gotoDevice(\'' + node._id + '\',null,null,event)></span><div id=xkvmid_' + node._id.split('/')[2] + '><div id=skvmid_' + node._id.split('/')[2] + ' tabindex=0 style="position:absolute;color:white;left:5px;top:27px;text-shadow:0px 0px 5px #000;z-index:1000;cursor:default" onclick=toggleKvmDevice(\'' + node._id + '\') onkeypress="if (event.key==\'Enter\') toggleKvmDevice(\'' + node._id + '\')">' + "Disconnected" + '</div></div>';
1804 - r += '</div>';
1805 - kvmDivs.push(node._id);
1806 - }
1807 - }
1808 -
1809 - // If we are displaying devices by group, put the device in the right group.
1810 - if ((sort == 3) && (r != '')) {
1811 - if (node.tags) {
1812 - for (var j in node.tags) {
1813 - var tag = node.tags[j];
1814 - if (groups[tag] == null) { groups[tag] = r; groupCount[tag] = 1; } else { groups[tag] += r; groupCount[tag] += 1; }
1815 - if (view == 3) break;
1816 - }
1817 - }
1818 - r = '';
1819 - }
1820 -
1821 - deviceHeaderTotal++;
1822 - if (typeof deviceHeaderCount[node.state] == 'undefined') { deviceHeaderCount[node.state] = 1; } else { deviceHeaderCount[node.state]++; }
1823 - }
1824 -
1825 - // Above 32 devices, gray out the auto connect feature.
1826 - if (kvmDivs.length >= 32) { Q('autoConnectDesktopCheckbox').checked = false; }
1827 - QE('autoConnectDesktopCheckbox', kvmDivs.length < 32);
1828 -
1829 - // If displaying devices by groups, sort the group names and display the devices.
1830 - if (sort == 3) {
1831 - var groupNames = [];
1832 - for (var i in groups) { groupNames.push(i); }
1833 - groupNames.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); });
1834 - for (var j in groupNames) {
1835 - var i = groupNames[j];
1836 - if (view == 2) {
1837 - r += '<tr><td colspan=4><div class=DevSt style=width:100%;padding-top:4px><span class=devHeaderx style=float:right>' + groupCount[i] + ' node' + ((groupCount[i] > 1) ? 's' : '') + '</span><span>' + i + '</span></div>' + groups[i];
1838 - } else {
1839 - r += '<div class=DevSt style=width:100%;padding-top:4px><span class=devHeaderx style=float:right>' + groupCount[i] + ' node' + ((groupCount[i] > 1) ? 's' : '') + '</span><span>' + i + '</span></div>' + groups[i];
1840 - }
1841 - }
1842 - }
1843 -
1844 - // If there is nothing to display, explain the problem
1845 - if ((r == '') && (meshcount > 0) && (Q('SearchInput').value != '')) {
1846 - if (sort == 3) {
1847 - r = '<div style="margin:30px">' + "No devices are included in any groups, click on a device\'s \"Groups\" to add to a group." + '</div>';
1848 - } else {
1849 - r = '<div style="margin:30px">' + "No devices matching this search." + '</div>';
1850 - }
1851 - }
1852 -
1853 - if ((view == 1) && (c == 2)) r += '<td><div style=width:301px></div></td>'; // Adds device padding
1854 -
1855 - // Display all empty device groups, we need to do this because users can add devices to these at any time.
1856 - if ((sort == 0) && (Q('SearchInput').value == '') && (view < 3)) {
1857 - for (var i in meshes) {
1858 - var mesh = meshes[i], meshlink = mesh.links[userinfo._id];
1859 - if (meshlink != null) {
1860 - var meshrights = meshlink.rights;
1861 - if (displayedMeshes[mesh._id] == null) {
1862 - if ((current != '') && (r != '')) { r += '</tr></table>'; }
1863 - r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr><td colspan=3 class=DevSt><span id=MxMESH style=cursor:pointer onclick=gotoMesh("' + mesh._id + '")>' + EscapeHtml(mesh.name) + '</span><span>';
1864 - r += getMeshActions(mesh, meshrights);
1865 - r += '</span></td></tr><tr>';
1866 - if (mesh.mtype == 1) {
1867 - r += '<td><div style=padding:10px><i>' + "No Intel&reg; AMT devices in this mesh";
1868 - if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addDeviceToMesh(\"' + mesh._id + '\")\'>' + "add one" + '</a>'; }
1869 - }
1870 - if (mesh.mtype == 2) {
1871 - r += '<td><div style=padding:10px><i>' + "No devices in this group";
1872 - if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addAgentToMesh(\"' + mesh._id + '\")\'>' + "add one" + '</a>'; }
1873 - }
1874 - r += '.</i></div></td>';
1875 - current = mesh._id;
1876 - count++;
1877 - }
1878 - }
1879 - }
1880 - }
1881 -
1882 - if (r != '') {
1883 - r += '</table>';
1884 - if (view == 2) {
1885 - // This height of 1 div at the end to fix a problem in Linux firefox browsers
1886 - r = '<table style=width:100%;margin-top:4px cellpadding=0 cellspacing=0><th style=color:gray><th style=color:gray;width:120px>' + "User" + '<th style=color:gray;width:120px>' + "Address" + '<th style=color:gray;width:100px>' + "Connectivity" + r + '</tr></table><div style=height:1px></div>'; //<th style=color:gray;width:100px>State';
1887 - }
1888 - } else {
1889 - r += '</table>';
1890 - if (sort == 3) { r = '<div style="margin:10px"><i>' + "No devices with tags found." + '</i></div>'; }
1891 - }
1892 -
1893 - // Add a "Add Device Group" option
1894 - r += '<div style=border-top-style:solid;border-top-width:1px;border-top-color:#DDDDDD;cursor:pointer;font-size:10px>';
1895 - if ((view < 3) && (sort == 0) && (meshcount > 0) && ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 64) == 0))) {
1896 - r += '<a href=# onclick="return account_createMesh()" title=\"' + "Create a new group of devices." + '\" style=cursor:pointer>' + "Add Device Group" + '</a>&nbsp';
1897 - }
1898 - if ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 128) == 0)) {
1899 - r += '<a href=# onclick=\'return p10showMeshCmdDialog(0)\' style=cursor:pointer title=\"' + "Download MeshCmd, a command line tool that performs many functions." + '\">' + "MeshCmd" + '</a>&nbsp';
1900 - if (navigator.platform.toLowerCase() == 'win32') { r += '<a href=# onclick=\'return p10showMeshRouterDialog()\' style=cursor:pointer title=\"' + "Download MeshCentral Router, a TCP port mapping tool." + '\">' + "Router" + '</a>&nbsp'; }
1901 - }
1902 - r += '</div><br/>';
1903 -
1904 - QH('xdevices', r);
1905 - deviceHeaderSet();
1906 -
1907 - // Re-check nodeid's
1908 - var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
1909 - if (checkedNodeids) { for (var i=0;i<elements.length;i++) { elements[i].checked = (checkedNodeids.indexOf(elements[i].value) >= 0); } }
1910 -
1911 - for (var i in deviceHeaders) { QH(i, deviceHeaders[i]); }
1912 - for (var i in deviceHeadersTitles) { Q(i).title = deviceHeadersTitles[i]; }
1913 - p1updateInfo();
1914 -
1915 - // Take care of KVM surfaces in desktop view mode
1916 - if (view == 3) {
1917 - // Figure out and adjust the size to fill the width of the div
1918 - var vsize = [{ x: 180, y: 101 }, { x: 302, y: 169 }, { x: 454, y: 255 }][Q('sizeselect').selectedIndex];
1919 - //var realw = vsize.x + 2, tw = Q('xdevices').clientWidth - 30, xw = Math.floor(tw / realw);
1920 - var realw = vsize.x + 2, tw = totalDeviceViewWidth - 5, xw = Math.floor(tw / realw);
1921 - xw = realw + Math.floor((tw - (xw * realw)) / xw);
1922 - vsize.y = vsize.y * (xw / vsize.x);
1923 - vsize.x = xw;
1924 -
1925 - for (var i in multiDesktop) { multiDesktop[i].xxdelete = true; }
1926 - for (var i in kvmDivs) {
1927 - var id = kvmDivs[i], shortid = id.split('/')[2], desk = multiDesktop[id];
1928 - if (desk != null) {
1929 - // This device already has a canvas, use it.
1930 - desk.m.CanvasId.setAttribute('style', 'background-color:black;width:' + vsize.x + 'px;height:' + vsize.y + 'px');
1931 - Q('xkvmid_' + shortid).appendChild(desk.m.CanvasId);
1932 - delete desk.xxdelete;
1933 - QH('skvmid_' + shortid, ["Disconnected", "Connecting...", "Setup...", '', ''][((desk.m.State == null)?desk.m.state:desk.m.State)]);
1934 - } else {
1935 - var node = getNodeFromId(id);
1936 - if ((desktopNode == node) && (desktop != null)) { // Check if the main desktop is this device, if it is, use that.
1937 - // This device already has a canvas, use it.
1938 - var c = desktop.m.CanvasId;
1939 - c.setAttribute('id', 'kvmid_' + shortid);
1940 - c.setAttribute('style', 'background-color:black;width:' + vsize.x + 'px;height:' + vsize.y + 'px');
1941 - c.setAttribute('onclick', 'toggleKvmDevice(\'' + id + '\')');
1942 - c.removeAttribute('onmousedown');
1943 - c.removeAttribute('onmouseup');
1944 - c.removeAttribute('onmousemove');
1945 - Q('xkvmid_' + shortid).appendChild(c);
1946 - QH('skvmid_' + shortid, ["Disconnected", "Connecting...", "Setup...", '', ''][((desktop.m.State == null)?desktop.m.state:desktop.m.State)]);
1947 - if (desktop.m.SendCompressionLevel) { desktop.m.SendCompressionLevel(1, multidesktopsettings.quality, multidesktopsettings.scaling, multidesktopsettings.framerate); }
1948 - desktop.shortid = shortid;
1949 - desktop.onStateChanged = onMultiDesktopStateChange;
1950 - multiDesktop[id] = desktop;
1951 - desktop = desktopNode = currentNode = null;
1952 - // Setup a replacement desktop
1953 - QH('DeskParent', '<canvas id="Desk" oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></canvas>');
1954 - } else {
1955 - // This is a new device, create a canvas for it.
1956 - var c = document.createElement('canvas');
1957 - c.setAttribute('id', 'kvmid_' + shortid);
1958 - c.setAttribute('width', 640);
1959 - c.setAttribute('height', 480);
1960 - c.setAttribute('oncontextmenu', 'return false');
1961 - c.setAttribute('style', 'background-color:black;width:' + vsize.x + 'px;height:' + vsize.y + 'px');
1962 - c.setAttribute('onclick', 'toggleKvmDevice(\'' + id + '\')');
1963 - try { Q('xkvmid_' + shortid).appendChild(c); } catch (ex) {}
1964 - // Check if we need to auto-connect
1965 - if (Q('autoConnectDesktopCheckbox').checked == true) { setTimeout(function() { connectMultiDesktop(node, 1); }, 100); }
1966 - }
1967 - }
1968 - }
1969 - for (var i in multiDesktop) {
1970 - // If a device is no longer viewed, disconnect it.
1971 - if (multiDesktop[i].xxdelete == true) { multiDesktop[i].Stop(); delete multiDesktop[i]; }
1972 - else if (debugmode && multiDesktop[i].m && multiDesktop[i].m.onScreenSizeChange) {
1973 - mdeskAdjust(multiDesktop[i].m, multiDesktop[i].m.ScreenWidth, multiDesktop[i].m.ScreenHeight, multiDesktop[i].m.CanvasId); // Adjust screen size change
1974 - }
1975 - }
1976 - deskAdjust();
1977 - } else {
1978 - disconnectAllKvmFunction();
1979 - Q('autoConnectDesktopCheckbox').checked = false;
1980 - }
1981 - }
1982 - oldviewmode = view;
1983 - }
1984 -
1985 - function toggleKvmDevice(node) {
1986 - if (typeof node == 'string') { node = getNodeFromId(node); } // Convert nodeid to node if needed
1987 - var mesh = meshes[node.meshid], meshrights = mesh.links[userinfo._id].rights;
1988 - if ((meshrights & 8) || (meshrights & 256)) { // Requires remote control rights or desktop view only rights
1989 - //var conn = 0;
1990 - //if ((node.conn & 1) != 0) { conn = 1; } else if ((node.conn & 6) != 0) { conn = 2; } // Check what type of connect we can do (Agent vs AMT)
1991 - if (node.conn & 1) { connectMultiDesktop(node, 1); }
1992 - }
1993 - }
1994 -
1995 - function getUserShortStr(node) {
1996 - if (node == null || node.users == null || node.users.length == 0) return '';
1997 - if (node.users.length > 1) { return '<span title="' + EscapeHtml(node.users.join(', ')) + '">' + nobreak(format("{0} users", node.users.length)) + '</span>'; }
1998 - var u = node.users[0], su = u, i = u.indexOf('\\');
1999 - if (i > 0) { su = u.substring(i + 1); }
2000 - su = EscapeHtml(su);
2001 - if (su.length > 15) { su = su.substring(0, 14) + '&#8230;'; }
2002 - return '<span title="' + EscapeHtml(u) + '">' + su + '</span>';
2003 - }
2004 -
2005 - function autoConnectDesktops() { if (Q('autoConnectDesktopCheckbox').checked == true) { connectAllKvmFunction(); } }
2006 - function connectAllKvmFunction(force) {
2007 - if (xxdialogMode) return false;
2008 - if (force !== true) { // We need to count how many devices will need to be connected, if it's a lot, prompt first.
2009 - var count = 0;
2010 - for (var i in nodes) {
2011 - var node = nodes[i], nodeid = nodes[i]._id;
2012 - if ((multiDesktop[nodeid] == null) && ((multiDesktopFilter.length == 0) || (multiDesktopFilter.indexOf('devid_' + nodeid) >= 0))) {
2013 - var mesh = meshes[node.meshid], meshrights = mesh.links[userinfo._id].rights;
2014 - if ((meshrights & 8) || (meshrights & 256)) { // Requires remote control rights or desktop view only rights
2015 - //var conn = 0;
2016 - //if ((node.conn & 1) != 0) { conn = 1; } else if ((node.conn & 6) != 0) { conn = 2; } // Check what type of connect we can do (Agent vs AMT)
2017 - if (node.conn & 1) { count++; }
2018 - }
2019 - }
2020 - }
2021 - if (count > 8) { setDialogMode(2, "Connect All", 3, function() { connectAllKvmFunction(true); }, format("Are you sure you want to connect to {0} devices?", count)); return; }
2022 - }
2023 -
2024 - // Perform connect all
2025 - for (var i in nodes) {
2026 - if ((multiDesktop[nodes[i]._id] == null) && ((multiDesktopFilter.length == 0) || (multiDesktopFilter.indexOf('devid_' + nodes[i]._id) >= 0))) {
2027 - toggleKvmDevice(nodes[i]._id);
2028 - }
2029 - }
2030 - }
2031 - function disconnectAllKvmFunction() { if (xxdialogMode) return false; for (var nodeid in multiDesktop) { multiDesktop[nodeid].Stop(); } multiDesktop = {}; }
2032 - function onMultiDesktopStateChange(desk, state) { try { QH('skvmid_' + desk.shortid, ["Disconnected", "Connecting...", "Setup...", '', ''][state]); } catch (ex) {} }
2033 -
2034 - function showMultiDesktopSettings() {
2035 - QV('d7amtkvm', false);
2036 - QV('d7meshkvm', true);
2037 - d7bitmapquality.value = multidesktopsettings.quality;
2038 - d7bitmapscaling.value = multidesktopsettings.scaling;
2039 - if (multidesktopsettings.framerate) { d7framelimiter.value = multidesktopsettings.framerate; } else { d7framelimiter.value = 1000; }
2040 - setDialogMode(7, "Remote Desktop Settings", 3, showMultiDesktopSettingsChanged);
2041 - }
2042 -
2043 - function showMultiDesktopSettingsChanged() {
2044 - multidesktopsettings.quality = d7bitmapquality.value;
2045 - multidesktopsettings.scaling = d7bitmapscaling.value;
2046 - multidesktopsettings.framerate = d7framelimiter.value;
2047 - localStorage.setItem('multidesktopsettings', JSON.stringify(multidesktopsettings));
2048 - // Make changes to all current connections
2049 - for (var i in multiDesktop) { multiDesktop[i].m.SendCompressionLevel(1, multidesktopsettings.quality, multidesktopsettings.scaling, multidesktopsettings.framerate); }
2050 - }
2051 -
2052 - function connectMultiDesktop(node, contype) {
2053 - var nodeid = node._id, shortid = nodeid.split('/')[2];
2054 - var desk = multiDesktop[nodeid];
2055 - if (desk == null) {
2056 - if (Q('kvmid_' + shortid) == null) return; // Check if this device is being displayed, if not, exit now.
2057 - if (contype == 2) {
2058 - // Setup the Intel AMT remote desktop
2059 - if ((node.intelamt.user == null) || (node.intelamt.user == '')) { return; }
2060 - desk = CreateAmtRedirect(CreateAmtRemoteDesktop('kvmid_' + shortid), authCookie);
2061 - desk.shortid = shortid;
2062 - //desk.debugmode = debugmode;
2063 - desk.onStateChanged = onMultiDesktopStateChange;
2064 - desk.m.bpp = 1;
2065 - desk.m.useZRLE = true;
2066 - desk.m.showmouse = true;
2067 - desk.m.onKvmData = function (data) { console.log('KVM Data received in multi-desktop mode, this is not supported.'); }; // KVM Data Channel not supported in multi-desktop right now.
2068 - //desk.m.onScreenSizeChange = deskAdjust;
2069 - if (debugmode > 0) { desk.m.onScreenSizeChange = mdeskAdjust; } // Multi-Desktop Adjust
2070 - desk.Start(nodeid, 16994, '*', '*', 0);
2071 - desk.contype = 2;
2072 - multiDesktop[nodeid] = desk;
2073 - } else if (contype == 1) {
2074 - // Setup the Mesh Agent remote desktop
2075 - desk = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('kvmid_' + shortid), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
2076 - desk.shortid = shortid;
2077 - desk.attemptWebRTC = attemptWebRTC;
2078 - desk.onStateChanged = onMultiDesktopStateChange;
2079 - //desk.onConsoleMessageChange = function () { console.log('CONSOLEMSG:', desk.consoleMessage); }
2080 - desk.m.CompressionLevel = multidesktopsettings.quality;
2081 - desk.m.ScalingLevel = multidesktopsettings.scaling;
2082 - desk.m.FrameRateTimer = multidesktopsettings.framerate;
2083 - //desk.m.onDisplayinfo = deskDisplayInfo;
2084 - //desk.m.onScreenSizeChange = deskAdjust;
2085 - if (debugmode > 0) { desk.m.onScreenSizeChange = mdeskAdjust; } // Multi-Desktop Adjust
2086 - desk.Start(nodeid);
2087 - desk.contype = 1;
2088 - multiDesktop[nodeid] = desk;
2089 - }
2090 - } else {
2091 - // Disconnect and clean up the remote desktop
2092 - desk.Stop();
2093 - delete multiDesktop[nodeid];
2094 - }
2095 - }
2096 -
2097 - function getMeshActions(mesh, meshrights) {
2098 - if ((meshrights & 4) == 0) return '';
2099 - var r = '';
2100 - if ((features & 1024) == 0) { // If CIRA is allowed
2101 - r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Add a new Intel&reg; AMT computer that is located on the internet." + '\" onclick=\'return addCiraDeviceToMesh(\"' + mesh._id + '\")\'>' + "Add CIRA" + '</a>';
2102 - }
2103 - if (mesh.mtype == 1) {
2104 - if ((features & 1) == 0) { // If not WAN-Only
2105 - r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Add a new Intel&reg; AMT computer that is located on the local network." + '\" onclick=\'return addDeviceToMesh(\"' + mesh._id + '\")\'>' + "Add Local" + '</a>';
2106 - r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Add a new Intel&reg; AMT computer by scanning the local network." + '\" onclick=\'return addAmtScanToMesh(\"' + mesh._id + '\")\'>' + "Scan Network" + '</a>';
2107 - }
2108 - if (mesh.amt && (mesh.amt.type == 2)) { // CCM activation
2109 - r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Perform Intel AMT client control mode (CCM) activation." + '\" onclick=\'return showCcmActivation(\"' + mesh._id + '\")\'>' + "Activation" + '</a>';
2110 - } else if (mesh.amt && (mesh.amt.type == 3) && ((features & 0x00100000) != 0)) { // ACM activation
2111 - r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Perform Intel AMT admin control mode (ACM) activation." + '\" onclick=\'return showAcmActivation(\"' + mesh._id + '\")\'>' + "Activation" + '</a>';
2112 - }
2113 - }
2114 - if (mesh.mtype == 2) {
2115 - r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Add a new computer to this mesh by installing the mesh agent." + '\" onclick=\'return addAgentToMesh(\"' + mesh._id + '\")\'>' + "Add Agent" + '</a>';
2116 - if ((features & 2) == 0) { r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Invite someone to install the mesh agent on this mesh." + '\" onclick=\'return inviteAgentToMesh(\"' + mesh._id + '\")\'>' + "Invite" + '</a>'; }
2117 - }
2118 - return r;
2119 - }
2120 -
2121 - function addDeviceToMesh(meshid) {
2122 - if (xxdialogMode) return false;
2123 - var mesh = meshes[meshid];
2124 - var x = format("Add a new Intel&reg; AMT device to device group \"{0}\".", EscapeHtml(mesh.name)) + '<br /><br />';
2125 - x += addHtmlValue("Device Name", '<input id=dp1devicename style=width:230px maxlength=32 autocomplete=off onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
2126 - x += addHtmlValue("Hostname", '<input id=dp1hostname style=width:230px maxlength=32 autocomplete=off placeholder=\"' + "Same as device name" + '\" onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
2127 - x += addHtmlValue("Username", '<input id=dp1username style=width:230px maxlength=32 autocomplete=off placeholder=\"' + "admin" + '\" onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
2128 - x += addHtmlValue("Password", '<input id=dp1password type=password style=width:230px autocomplete=off maxlength=32 onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
2129 - x += addHtmlValue("Security", '<select id=dp1tls style=width:236px><option value=0>' + "No TLS security" + '</option><option value=1>' + "TLS security required" + '</option></select>');
2130 - setDialogMode(2, "Add Intel&reg; AMT device", 3, addDeviceToMeshEx, x, meshid);
2131 - validateDeviceToMesh();
2132 - Q('dp1devicename').focus();
2133 - return false;
2134 - }
2135 -
2136 - // Intel AMT CCM Activation
2137 - function showCcmActivation(meshid) {
2138 - if (xxdialogMode) return false;
2139 - var servername = serverinfo.name, mesh = meshes[meshid];
2140 - if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
2141 - var url, domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
2142 - if (serverinfo.https == true) {
2143 - var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
2144 - url = 'wss://' + servername + portStr + domainUrl;
2145 - } else {
2146 - var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
2147 - url = 'ws://' + servername + portStr + domainUrl;
2148 - }
2149 - var x = format("Perform Intel AMT client control mode (CCM) activation to group \"{0}\" by downloading the MeshCMD tool and running it like this:", EscapeHtml(mesh.name)) + '<br /><br />';
2150 - x += '<textarea readonly=readonly style=width:100%;resize:none;height:100px;overflow:auto;font-size:12px readonly>meshcmd amtccm --url ' + url + 'amtactivate?id=' + meshid.split('/')[2] + ' --serverhttpshash ' + serverinfo.tlshash + '</textarea>';
2151 - setDialogMode(2, "Intel&reg; AMT activation", 9, null, x);
2152 - Q('idx_dlgOkButton').focus();
2153 - return false;
2154 - }
2155 -
2156 - // Intel AMT ACM Activation
2157 - function showAcmActivation(meshid) {
2158 - if (xxdialogMode) return false;
2159 - var servername = serverinfo.name, mesh = meshes[meshid];
2160 - if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
2161 - var url, domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
2162 - if (serverinfo.https == true) {
2163 - var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
2164 - url = 'wss://' + servername + portStr + domainUrl;
2165 - } else {
2166 - var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
2167 - url = 'ws://' + servername + portStr + domainUrl;
2168 - }
2169 - var x = format("Perform Intel AMT admin control mode (ACM) activation to group \"{0}\" by downloading the MeshCMD tool and running it like this:", EscapeHtml(mesh.name)) + '<br /><br />';
2170 - x += '<textarea readonly=readonly style=width:100%;resize:none;height:100px;overflow:auto;font-size:12px readonly>meshcmd amtacm --url ' + url + 'amtactivate?id=' + meshid.split('/')[2] + ' --serverhttpshash ' + serverinfo.tlshash + '</textarea>';
2171 - if (serverinfo.amtAcmFqdn != null) {
2172 - x += ('<div style=margin-top:8px>' + "Intel AMT will need to be set with a Trusted FQDN in MEBx or have a wired LAN on the network:" + ' <b>' + serverinfo.amtAcmFqdn.join(', ') + '</b></div>');
2173 - }
2174 - setDialogMode(2, "Intel&reg; AMT activation", 9, null, x);
2175 - Q('idx_dlgOkButton').focus();
2176 - return false;
2177 - }
2178 -
2179 - // Display the Intel AMT scanning dialog box
2180 - function addAmtScanToMesh(meshid) {
2181 - if (xxdialogMode) return false;
2182 - var x = "Enter a range of IP addresses to scan for Intel AMT devices." + '<br /><br />';
2183 - x += addHtmlValue("IP Range", '<input id=dp1range style=width:184px value="192.168.1.0/24" onkeyup=addAmtScanToMeshKeyUp(event) /><input id=dp1rangebutton type=button value=\"' + "Scan" + '\" onclick=addAmtScanToMeshButton()></input>');
2184 - x += '<div id=dp1results style="width:100%;height:200px;background-color:white;border:1px gray solid;overflow-y:scroll"></div>';
2185 - setDialogMode(2, "Scan for Intel&reg; AMT devices", 3, addAmtScanToMeshEx, x, meshid);
2186 - QE('idx_dlgOkButton', false);
2187 - QH('dp1results', '<div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>Sample IP range values<br />192.168.0.100<br />192.168.1.0/24<br />192.167.0.1-192.168.0.100</div>');
2188 - focusTextBox('dp1range');
2189 - return false;
2190 - }
2191 -
2192 - function addAmtScanToMeshKeyUp(e) {
2193 - if (e.keyCode == 13) { haltEvent(e); addAmtScanToMeshButton(); }
2194 - }
2195 -
2196 - // Called when OK is pressed on the Intel AMT scanning box
2197 - function addAmtScanToMeshEx(button, meshid) {
2198 - var elements = document.getElementsByClassName('DevScanCheckbox'), checkcount = 0;
2199 - for (var i=0;i<elements.length;i++) {
2200 - if (elements[i].checked) {
2201 - var ipaddr = elements[i].getAttribute('tag');
2202 - var amtinfo = amtScanResults[ipaddr];
2203 - meshserver.send({ action: 'addamtdevice', meshid: meshid, devicename: ipaddr, hostname: amtinfo.hostname, amtusername: '', amtpassword: '', amttls: amtinfo.tls });
2204 - }
2205 - }
2206 - }
2207 -
2208 - // If the user presses the "Scan" button on the Intel AMT scanning dialog box, start a scan.
2209 - function addAmtScanToMeshButton() {
2210 - QE('dp1range', false);
2211 - QE('dp1rangebutton', false);
2212 - QH('dp1results', '<div style=width:100%;text-align:center;margin-top:12px>' + "Scanning..." + '</div>');
2213 - meshserver.send({ action: 'scanamtdevice', range: Q('dp1range').value });
2214 - }
2215 -
2216 - // Called when a scanned computer is checked or unchecked.
2217 - function addAmtScanToMeshCheckbox() {
2218 - var elements = document.getElementsByClassName('DevScanCheckbox'), checkcount = 0;
2219 - for (var i=0;i<elements.length;i++) { if (elements[i].checked) checkcount++; }
2220 - QE('idx_dlgOkButton', checkcount > 0);
2221 - }
2222 -
2223 - function addCiraDeviceToMesh(meshid) {
2224 - if (xxdialogMode) return false;
2225 - var mesh = meshes[meshid];
2226 -
2227 - // Replace non alphabetic characters (@ and $) with 'X' because MPS username cannot accept it.
2228 - var meshidx = meshid.split('/')[2].replace(/\@/g, 'X').replace(/\$/g, 'X');
2229 -
2230 - var y = '<select id=dlgAddCiraSel onclick=dlgAddCiraSelClick() style=width:230px><option value=0>' + "MeshCommander Script" + '</option><option value=1>' + "Manual Username/Password" + '</option>';
2231 - if ((features & 16) == 0) { y += ('<option value=2>' + "Manual Certificate" + '</option></select>'); } // Only display this option if Intel AMT CIRA with Mutual-Auth is allowed.
2232 -
2233 - var x = '';
2234 - x += addHtmlValue("Setup Method", y);
2235 - x += '<hr>';
2236 -
2237 - // Setup CIRA using a MeshCommander script (Pretty Simple)
2238 - x += '<div id=dlgAddCira0>' + format("To add a new Intel&reg; AMT device to device group \"{0}\" with CIRA, download the following script files and use <a href='http://meshcommander.com' rel='noreferrer noopener' target='_blank'>MeshCommander</a> to run the script to configure computers.", EscapeHtml(mesh.name)) + '<br /><br />';
2239 - //x += addHtmlValue('Setup CIRA', '<a href="mescript.ashx?type=1&meshid=' + meshidx.substring(0, 16) + '" download>cira_setup.mescript</a>');
2240 - x += addHtmlValue("Setup CIRA", '<a href="mescript.ashx?type=1&meshid=' + meshid + '" download>cira_setup.mescript</a>');
2241 - x += addHtmlValue("Cleanup CIRA", '<a href="mescript.ashx?type=2" download>cira_clean.mescript</a>');
2242 - x += '</div>';
2243 -
2244 - // Setup CIRA with user/pass authentication (Somewhat difficult)
2245 - x += '<div id=dlgAddCira1 style=display:none>' + format("To add a new Intel&reg; AMT device to device group \"{0}\" with CIRA, load the following certificate as trusted root within Intel AMT", EscapeHtml(mesh.name));
2246 - if (serverinfo.mpspass) { x += (" and authenticate to the server using this username and password." + '<br /><br />'); } else { x += (" and authenticate to the server using this username and any password." + '<br /><br />'); }
2247 - x += addHtmlValue("Root Certificate", '<a href=\"' + "MeshServerRootCert.cer" + '\" download>' + "Root Certificate File" + '</a>');
2248 - x += addHtmlValue("Username", '<input style=width:230px readonly value="' + meshidx.substring(0, 16) + '" />');
2249 - if (serverinfo.mpspass) { x += addHtmlValue("Password", '<input style=width:230px readonly value="' + EscapeHtml(serverinfo.mpspass) + '" />'); }
2250 - if (serverinfo != null) { x += addHtmlValue("MPS Server", '<input style=width:230px readonly value="' + EscapeHtml(serverinfo.mpsname) + ':' + serverinfo.mpsport + '" />'); }
2251 - x += '</div>';
2252 -
2253 - // Setup CIRA with certificate authentication (Really difficult, only if TLS offload is not used)
2254 - if ((features & 16) == 0) {
2255 - x += '<div id=dlgAddCira2 style=display:none>' + format("To add a new Intel&reg; AMT device to device group \"{0}\" with CIRA, load the following certificate as trusted root within Intel AMT, authenticate using a client certificate with the following common name and connect to the following server.", EscapeHtml(mesh.name)) + '<br /><br />';
2256 - x += addHtmlValue("Root Certificate", '<a href="MeshServerRootCert.cer" download>' + "Root Certificate File" + '</a>');
2257 - x += addHtmlValue("Organization", '<input style=width:230px readonly value="' + meshidx + '" />');
2258 - if (serverinfo != null) { x += addHtmlValue("MPS Server", '<input style=width:230px readonly value="' + EscapeHtml(serverinfo.mpsname) + ':' + serverinfo.mpsport + '" />'); }
2259 - x += '</div>';
2260 - }
2261 -
2262 - setDialogMode(2, "Add Intel&reg; AMT CIRA device", 2, null, x, 'fileDownload');
2263 - Q('dlgAddCiraSel').focus();
2264 - return false;
2265 - }
2266 -
2267 - function dlgAddCiraSelClick() {
2268 - var val = Q('dlgAddCiraSel').value;
2269 - QV('dlgAddCira0', val == 0);
2270 - QV('dlgAddCira1', val == 1);
2271 - QV('dlgAddCira2', val == 2);
2272 - }
2273 -
2274 - // Return true is the input string looks like an email address
2275 - function checkEmail(str) {
2276 - var x = str.split('@');
2277 - var ok = ((x.length == 2) && (x[0].length > 0) && (x[1].split('.').length > 1) && (x[1].length > 2));
2278 - if (ok == true) { var y = x[1].split('.'); for (var i in y) { if (y[i].length == 0) { ok = false; } } }
2279 - return ok;
2280 - }
2281 -
2282 - function inviteAgentToMesh(meshid) {
2283 - if (xxdialogMode) return false;
2284 - var x = '', mesh = meshes[meshid];
2285 - if (features & 64) {
2286 - x += addHtmlValue("Invitation Type", '<select id=d2InviteType onchange=d2ChangedInviteType() style=width:236px><option value=0>Link invitation</option><option value=1>Email invitation</option></select>') + '<hr />';
2287 - x += '<div id=emailInviteDiv style=display:none>' + format("Invite someone to install the mesh agent. An email with be sent with the link to the mesh agent installation for the \"{0}\" device group.", EscapeHtml(mesh.name)) + '<br /><br />';
2288 - x += addHtmlValue("Name (optional)", '<input id=agentInviteName value="" style=width:230px maxlength=64 />');
2289 - x += addHtmlValue("Email", '<input id=agentInviteEmail style=width:230px placeholder=\"' + "example@email.com" + '\" onkeyup=validateAgentInvite()></input>');
2290 - x += addHtmlValue("Operating System", '<select id=agentInviteNameOs onchange=d2ChangedInviteType() style=width:236px><option value=4>' + "Send installation link" + '</option><option value=0 selected>' + "Any supported" + '</option><option value=1>' + "Windows only" + '</option><option value=3>' + "Apple MacOS only" + '</option><option value=2>' + "Linux only" + '</option></select>');
2291 - x += '<div id=d2agentexpirediv>';
2292 - x += addHtmlValue("Link Expiration", '<select id=agentInviteExpire style=width:236px><option value=1>' + "1 hour" + '</option><option value=8>' + "8 hours" + '</option><option value=24>' + "1 day" + '</option><option value=168>' + "1 week" + '</option><option value=5040>' + "1 month" + '</option><option value=0>' + "Unlimited" + '</option></select>');
2293 - x += '</div>';
2294 - x += addHtmlValue("Installation Type", '<select id=agentInviteType style=width:236px><option value=0>' + "Background and interactive" + '</option><option value=2>' + "Background only" + '</option><option value=1>' + "Interactive only" + '</option></select>');
2295 - x += addHtmlValue("Message" + '<br />' + "(optional)", '<textarea id=agentInviteMessage value="" style=width:230px;height:100px;resize:none maxlength=1024 /></textarea>');
2296 - x += '</div>';
2297 - }
2298 - x += '<div id=urlInviteDiv>' + format("Invite someone to install the mesh agent by sharing an invitation link. This link points the user to installation instructions for the \"{0}\" device group. The link is public and no account for this server is needed.", EscapeHtml(mesh.name)) + '<br /><br />';
2299 - x += addHtmlValue("Link Expiration", '<select id=d2inviteExpire style=width:236px onchange=d2RequestInvitationLink()><option value=1>' + "1 hour" + '</option><option value=8>' + "8 hours" + '</option><option value=24>' + "1 day" + '</option><option value=168>' + "1 week" + '</option><option value=5040>' + "1 month" + '</option><option value=0>' + "Unlimited" + '</option></select>');
2300 - x += '<div id=agentInvitationLinkDiv style="text-align:center;font-size:large;margin:16px;display:none"><a href=# id=agentInvitationLink target="_blank" style=cursor:pointer></a> <img src=images/link4.png height=10 width=10 title=\"' + "Copy link to clipboard" + '\" style=cursor:pointer onclick=d2CopyInviteToClip()></div></div>';
2301 - setDialogMode(2, "Invite", 3, performAgentInvite, x, meshid);
2302 - if (features & 64) { Q('d2InviteType').focus(); d2ChangedInviteType(); } else { Q('d2inviteExpire').focus(); validateAgentInvite(); }
2303 - d2RequestInvitationLink();
2304 - return false;
2305 - }
2306 -
2307 - function d2RequestInvitationLink() {
2308 - meshserver.send({ action: 'createInviteLink', meshid: xxdialogTag, expire: parseInt(Q('d2inviteExpire').value), flags: 0 });
2309 - }
2310 -
2311 - function d2ChangedInviteType() {
2312 - QV('urlInviteDiv', Q('d2InviteType').value == 0);
2313 - QV('d2agentexpirediv', Q('agentInviteNameOs').value == 4);
2314 - QV('emailInviteDiv', Q('d2InviteType').value == 1);
2315 - validateAgentInvite();
2316 - }
2317 -
2318 - function d2CopyInviteToClip() { copyTextToClip(Q('agentInvitationLink').href); }
2319 -
2320 - function validateAgentInvite() {
2321 - if ((features & 64) && (Q('d2InviteType').value == 1)) {
2322 - QE('idx_dlgOkButton', checkEmail(Q('agentInviteEmail').value));
2323 - QV('idx_dlgCancelButton', true);
2324 - } else {
2325 - QE('idx_dlgOkButton', true);
2326 - QV('idx_dlgCancelButton', false);
2327 - }
2328 - }
2329 -
2330 - function performAgentInvite(button, meshid) {
2331 - if ((features & 64) && (Q('d2InviteType').value == 1)) {
2332 - meshserver.send({ action: 'inviteAgent', meshid: meshid, email: Q('agentInviteEmail').value, name: Q('agentInviteName').value, os: Q('agentInviteNameOs').value, flags: Q('agentInviteType').value, msg: Q('agentInviteMessage').value, expire: parseInt(Q('agentInviteExpire').value) });
2333 - }
2334 - }
2335 -
2336 - function addAgentToMesh(meshid) {
2337 - if (xxdialogMode) return false;
2338 - var mesh = meshes[meshid], x = '', installType = 0;
2339 - x += addHtmlValue("Operating System", '<select id=aginsSelect onchange=addAgentToMeshClick() style=width:236px><option value=0>' + "Windows" + '</option><option value=1>' + "Linux / BSD" + '</option><option value=2>' + "Apple MacOS" + '</option><option value=3>' + "Windows (UnInstall)" + '</option><option value=4>' + "Linux / BSD (UnInstall)" + '</option></select>');
2340 - x += '<div id=aginsTypeDiv>';
2341 - x += addHtmlValue("Installation Type", '<select id=aginsType onchange=addAgentToMeshClick() style=width:236px><option value=0>' + "Background & interactive" + '</option><option value=2>' + "Background only" + '</option><option value=1>' + "Interactive only" + '</option></select>');
2342 - x += '</div><hr>';
2343 -
2344 - // \/:*?"<>|
2345 - var meshfilename = mesh.name
2346 - meshfilename = meshfilename.split('\\').join('').split('/').join('').split(':').join('').split('*').join('').split('?').join('').split('"').join('').split('<').join('').split('>').join('').split('|').join('').split(' ').join('').split('\'').join('');
2347 -
2348 - // Windows agent install
2349 - //x += "<div id=agins_windows>To add a new computer to device group \"" + EscapeHtml(mesh.name) + "\", download the mesh agent and configuration file and install the agent on the computer to manage.<br /><br />";
2350 - x += '<div id=agins_windows>' + format("To add a new computer to device group \"{0}\", download the mesh agent and install it the computer to manage. This agent has server and device group information embedded within it.", EscapeHtml(mesh.name)) + '<br /><br />';
2351 - x += addHtmlValue("Mesh Agent", '<a id=aginsw32lnk href="meshagents?id=3&meshid=' + meshid.split('/')[2] + '&installflags=0" download onclick="setDialogMode(0)" title=\"' + "32bit version of the MeshAgent" + '\">' + "Windows (.exe)" + '</a> <img src=images/link4.png height=10 width=10 title="Copy Windows 32bit agent URL to clipboard" style=cursor:pointer onclick=copyAgentUrl("meshagents?id=3&meshid=' + meshid.split('/')[2] + '&installflags=",1)>');
2352 - x += addHtmlValue("Mesh Agent", '<a id=aginsw64lnk href="meshagents?id=4&meshid=' + meshid.split('/')[2] + '&installflags=0" download onclick="setDialogMode(0)" title=\"' + "64bit version of the MeshAgent" + '\">' + "Windows x64 (.exe)" + '</a> <img src=images/link4.png height=10 width=10 title="Copy Windows 64bit agent URL to clipboard" style=cursor:pointer onclick=copyAgentUrl("meshagents?id=4&meshid=' + meshid.split('/')[2] + '&installflags=",1)>');
2353 - if (debugmode > 0) { x += addHtmlValue("Settings File", '<a id=aginswmshlnk href="meshsettings?id=' + meshid.split('/')[2] + '&installflags=0" rel="noreferrer noopener" target="_blank">' + format("{0} settings (.msh)", EscapeHtml(mesh.name)) + '</a>'); }
2354 - x += '</div>';
2355 -
2356 - // Linux agent install
2357 - x += '<div id=agins_linux style=display:none>' + format("To add a computer to {0} run the following command. Root credentials will be needed.", EscapeHtml(mesh.name)) + '<br />';
2358 - x += '<textarea id=agins_linux_area rows=2 cols=20 readonly=readonly style=width:100%;resize:none;height:120px;overflow:scroll;font-size:12px readonly></textarea>';
2359 - x += '<div style=\'font-size:x-small\'>' + "* For BSD, run \"pkg install wget sudo bash\" first." + '</div></div>';
2360 -
2361 - // MacOS agent install
2362 - x += '<div id=agins_osx style=display:none>' + format("To add a new computer to device group \"{0}\", download the mesh agent and install it the computer to manage. This agent installer has server and device group information embedded within it.", EscapeHtml(mesh.name)) + '<br /><br />';
2363 - x += addHtmlValue("Mesh Agent", '<a href="meshosxagent?id=16&meshid=' + meshid.split('/')[2] + '" rel="noreferrer noopener" target="_blank" title="64bit version of MacOS Mesh Agent">MacOS Agent (64bit)</a> <img src=images/link4.png height=10 width=10 title="' + "Copy MacOS agent URL to clipboard" + '" style=cursor:pointer onclick=copyAgentUrl("meshosxagent?id=16&meshid=' + meshid.split('/')[2] + '",0)>');
2364 - x += '</div>';
2365 -
2366 - // Windows agent uninstall
2367 - x += '<div id=agins_windows_un style=display:none>' + "To remove a mesh agent, download the file below, run it and click \"uninstall\"." + '<br /><br />';
2368 - x += addHtmlValue("Mesh Agent", '<a href="meshagents?id=3" download onclick="setDialogMode(0)" title="' + "32bit version of the MeshAgent" + '">' + "Windows (.exe)" + '</a>');
2369 - x += addHtmlValue("Mesh Agent", '<a href="meshagents?id=4" download onclick="setDialogMode(0)" title="' + "64bit version of the MeshAgent" + '">' + "Windows x64 (.exe)" + '</a>');
2370 - x += '</div>';
2371 -
2372 - // Linux agent uninstall
2373 - x += '<div id=agins_linux_un style=display:none>' + "To remove a mesh agent, run the following command. Root credentials will be needed." + '<br />';
2374 - x += '<textarea id=agins_linux_area_un rows=2 cols=20 readonly=readonly style=width:100%;resize:none;height:120px;overflow:scroll;font-size:12px readonly></textarea>';
2375 - x += '</div>';
2376 -
2377 - setDialogMode(2, "Add Mesh Agent", 2, null, x, 'fileDownload');
2378 - var servername = serverinfo.name;
2379 - if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
2380 - var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
2381 -
2382 - if (serverinfo.https == true)
2383 - {
2384 - var portStr = (serverinfo.port == 443)?'':(':' + serverinfo.port);
2385 - if ((features & 0x2000) == 0)
2386 - {
2387 - Q('agins_linux_area').value = '(wget https://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-check-certificate -O ./meshinstall.sh || wget https://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo -E ./meshinstall.sh https://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid.split('/')[2] + '\' || ./meshinstall.sh https://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid.split('/')[2] + '\'\r\n';
2388 - Q('agins_linux_area_un').value = '(wget https://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-check-certificate -O ./meshinstall.sh || wget https://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n';
2389 - }
2390 - else
2391 - {
2392 - // Server asked that agent be installed to preferably not use a HTTP proxy.
2393 - Q('agins_linux_area').value = 'wget https://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh https://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid.split('/')[2] + '\' || ./meshinstall.sh https://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid.split('/')[2] + '\'\r\n';
2394 - Q('agins_linux_area_un').value = 'wget https://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n';
2395 - }
2396 - }
2397 - else
2398 - {
2399 - var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
2400 - if ((features & 0x2000) == 0)
2401 - {
2402 - Q('agins_linux_area').value = '(wget http://' + servername + portStr + domainUrl + 'meshagents?script=1 -O ./meshinstall.sh || wget http://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-proxy -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo -E ./meshinstall.sh http://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid.split('/')[2] + '\'\r\n';
2403 - Q('agins_linux_area_un').value = '(wget http://' + servername + portStr + domainUrl + 'meshagents?script=1 -O ./meshinstall.sh || wget http://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-proxy -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n';
2404 - }
2405 - else
2406 - {
2407 - // Server asked that agent be installed to preferably not use a HTTP proxy.
2408 - Q('agins_linux_area').value = 'wget http://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-proxy -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh http://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid.split('/')[2] + '\'\r\n';
2409 - Q('agins_linux_area_un').value = 'wget http://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-proxy -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n';
2410 - }
2411 - }
2412 - Q('aginsSelect').focus();
2413 - addAgentToMeshClick();
2414 - return false;
2415 - }
2416 -
2417 - function copyAgentUrl(url,addflag) {
2418 - var servername = serverinfo.name;
2419 - if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
2420 - var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
2421 - var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
2422 - var c = 'https://' + servername + portStr + domainUrl + url;
2423 - if (addflag == 1) c += Q('aginsType').value;
2424 - copyTextToClip(c);
2425 - }
2426 -
2427 - function addAgentToMeshClick() {
2428 - var v = Q('aginsSelect').value;
2429 - QV('agins_windows', v == 0);
2430 - QV('agins_linux', v == 1);
2431 - QV('agins_osx', v == 2);
2432 - QV('agins_windows_un', v == 3);
2433 - QV('agins_linux_un', v == 4);
2434 - QV('aginsTypeDiv', v == 0);
2435 -
2436 - // Fix the links if needed
2437 - Q('aginsw32lnk').href = (Q('aginsw32lnk').href.split('installflags=')[0]) + 'installflags=' + Q('aginsType').value;
2438 - Q('aginsw64lnk').href = (Q('aginsw64lnk').href.split('installflags=')[0]) + 'installflags=' + Q('aginsType').value;
2439 - if (debugmode > 0) { Q('aginswmshlnk').href = (Q('aginswmshlnk').href.split('installflags=')[0]) + 'installflags=' + Q('aginsType').value; }
2440 - }
2441 -
2442 - function validateDeviceToMesh() {
2443 - QE('idx_dlgOkButton', (Q('dp1devicename').value.length > 0) && (passwordcheck(Q('dp1password').value)));
2444 - }
2445 -
2446 - function addDeviceToMeshEx(button, meshid) {
2447 - var amtuser = Q('dp1username').value;
2448 - if (amtuser == '') amtuser = 'admin';
2449 - var host = Q('dp1hostname').value;
2450 - if (host == '') host = Q('dp1devicename').value;
2451 - meshserver.send({ action: 'addamtdevice', meshid: meshid, devicename: Q('dp1devicename').value, hostname: host, amtusername: amtuser, amtpassword: Q('dp1password').value, amttls: Q('dp1tls').value });
2452 - }
2453 -
2454 - function deviceHeaderSet() {
2455 - if (deviceHeaderId == 0) { deviceHeaderId = 1; return; }
2456 - deviceHeaders['DevxHeader' + deviceHeaderId] = ((deviceHeaderTotal == 1) ? "1 node" : format("{0} nodes", deviceHeaderTotal));
2457 - //var title = '';
2458 - //for (x in deviceHeaderCount) { if (title.length > 0) title += ', '; title += deviceHeaderCount[x] + ' ' + PowerStateStr2(x); }
2459 - //deviceHeadersTitles["DevxHeader" + deviceHeaderId] = title;
2460 - deviceHeaderId++;
2461 - deviceHeaderCount = {};
2462 - deviceHeaderTotal = 0;
2463 - }
2464 -
2465 - 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>'];
2466 - 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"];
2467 - var powerColorTable = ['pwsTransparent', 'pwsBlack', 'pwsBlue', 'pwsBlue2', 'pwsLightblue', 'pwsBlueviolet', 'pwsDarkgreen', 'pwsLightseagreen', 'pwsLightseagreen2'];
2468 - function NodeStateStr(node) {
2469 - var states = [];
2470 - if (node.state > 0 && node.state < powerStatetable.length) state.push(powerStatetable[node.state]);
2471 - if (node.conn) {
2472 - if ((node.conn & 1) != 0) { states.push('<span title=\"' + "Mesh agent is connected and ready for use." + '\">' + "Agent" + '</span>'); }
2473 - if ((node.conn & 2) != 0) { states.push('<span title=\"' + "Intel&reg; AMT CIRA is connected and ready for use." + '\">' + "CIRA" + '</span>'); }
2474 - else if ((node.conn & 4) != 0) { states.push('<span title=\"' + "Intel&reg; AMT is routable." + '\">' + "AMT" + '</span>'); }
2475 - if ((node.conn & 8) != 0) { states.push('<span title=\"' + "Mesh agent is reachable using another agent as relay." + '\">' + "Relay" + '</span>'); }
2476 - if ((node.conn & 16) != 0) { states.push('<span title=\"' + "MQTT connection to the device is active." + '\">' + "MQTT" + '</span>'); }
2477 - }
2478 - if ((node.pwr != null) && (node.pwr != 0)) { states.push(powerStateStrings[node.pwr]); }
2479 - return states.join(', ');
2480 - }
2481 -
2482 - function PowerStateStr(x) {
2483 - if (x < powerStatetable.length) return powerStatetable[x];
2484 - return '';
2485 - }
2486 -
2487 - function PowerStateStr2(x) {
2488 - if ((x != 0) && (x < powerStatetable.length)) return powerStatetable[x];
2489 - return "Unknown";
2490 - }
2491 -
2492 - function selectallButtonFunction() {
2493 - var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
2494 - for (var i=0;i<elements.length;i++) { if (elements[i].checked === true) checkcount++; }
2495 - for (var i=0;i<elements.length;i++) { elements[i].checked = (checkcount == 0); }
2496 - p1updateInfo();
2497 - }
2498 -
2499 - function p1updateInfo() {
2500 - var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
2501 - for (var i=0;i<elements.length;i++) { if (elements[i].checked === true) { checkcount++; } }
2502 - if (checkcount > 0) {
2503 - QE('GroupActionButton', true);
2504 - Q('SelectAllButton').value = "Select None";
2505 - QV('cxmgroupsplit', true);
2506 - QV('cxmdesktop', true);
2507 - } else {
2508 - QE('GroupActionButton', false);
2509 - Q('SelectAllButton').value = "Select All";
2510 - QV('cxmgroupsplit', false);
2511 - QV('cxmdesktop', false);
2512 - }
2513 - }
2514 -
2515 - function groupActionFunction() {
2516 - var addedOptions = '', nodeids = getCheckedDevices();
2517 -
2518 - // Check if any of the selected devices have a MQTT connection active
2519 - if (features & 0x00400000) {
2520 - for (var i in nodeids) { if ((getNodeFromId(nodeids[i]).conn & 16) != 0) { addedOptions += '<option value=103>' + "Send MQTT Message" + '</option>'; break; } }
2521 - }
2522 -
2523 - // Display the "Uninstall Agent" option if allowed and we selected connected devices.
2524 - for (var i in nodeids) {
2525 - var node = getNodeFromId(nodeids[i]);
2526 - var mesh = meshes[node.meshid];
2527 - var meshrights = mesh.links[userinfo._id].rights;
2528 - if (((node.conn & 1) != 0) && ((meshrights & 32768) != 0)) { addedOptions += '<option value=104>' + "Uninstall Agent" + '</option>'; break; }
2529 - }
2530 -
2531 - var x = "Select an operation to perform on all selected devices. Actions will be performed only with proper rights." + '<br /><br />';
2532 - x += addHtmlValue("Operation", '<select id=d2groupop><option value=100>' + "Wake-up devices" + '</option><option value=4>' + "Sleep devices" + '</option><option value=3>' + "Reset devices" + '</option><option value=2>' + "Power off devices" + '</option><option value=102>' + "Move to device group" + '</option>' + addedOptions + '<option value=101>' + "Delete devices" + '</option></select>');
2533 - setDialogMode(2, "Group Action", 3, groupActionFunctionEx, x);
2534 - }
2535 -
2536 - // Get the list of checked devices, removes any duplicates.
2537 - function getCheckedDevices() {
2538 - var nodeids = [], elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
2539 - for (var i=0;i<elements.length;i++) { if (elements[i].checked) { if (elements[i].value) { var nid = elements[i].value.substring(6); if (nodeids.indexOf(nid) == -1) { nodeids.push(nid); } } } }
2540 - return nodeids;
2541 - }
2542 -
2543 - function groupActionFunctionEx() {
2544 - var op = Q('d2groupop').value;
2545 - if (op == 100) {
2546 - // Group wake
2547 - meshserver.send({ action: 'wakedevices', nodeids: getCheckedDevices() });
2548 - } else if (op == 101) {
2549 - // Group delete, ask for confirmation
2550 - var x = "Confirm delete selected devices(s)?" + '<br /><br />';
2551 - x += '<label><input id=d2check type=checkbox onchange=d2groupActionFunctionDelEx() />' + "Confirm" + '</label>';
2552 - setDialogMode(2, "Delete Nodes", 3, groupActionFunctionDelEx, x);
2553 - QE('idx_dlgOkButton', false);
2554 - } else if (op == 102) {
2555 - // Move computers to a different group
2556 - p10showChangeGroupDialog(getCheckedDevices());
2557 - } else if (op == 103) {
2558 - // Send MQTT Message
2559 - p10showSendMqttMsgDialog(getCheckedDevices());
2560 - } else if (op == 104) {
2561 - // Uninstall agent
2562 - p10showSendUninstallAgentDialog(getCheckedDevices());
2563 - } else {
2564 - // Power operation
2565 - meshserver.send({ action: 'poweraction', nodeids: getCheckedDevices(), actiontype: parseInt(op) });
2566 - }
2567 - }
2568 -
2569 - function d2groupActionFunctionDelEx() { QE('idx_dlgOkButton', Q('d2check').checked); }
2570 - function groupActionFunctionDelEx() { meshserver.send({ action: 'removedevices', nodeids: getCheckedDevices() }); }
2571 -
2572 - function onSortSelectChange(skipsave) {
2573 - sort = document.getElementById('sortselect').selectedIndex;
2574 - if (!skipsave) { putstore('sort', sort); }
2575 - }
2576 -
2577 - function meshSort(a, b) { if (a.meshnamel > b.meshnamel) return 1; if (a.meshnamel < b.meshnamel) return -1; if (a.meshid == b.meshid) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } return 0; }
2578 - function powerSort(a, b) { var ap = a.pwr?a.pwr:0; var bp = b.pwr?b.pwr:0; if (ap > bp) return -1; if (ap < bp) return 1; if (ap == bp) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } return 0; }
2579 - function deviceSort(a, b) { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; }
2580 - function deviceHostSort(a, b) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; }
2581 - function onSearchFocus(x) { searchFocus = x; }
2582 - function onMapSearchFocus(x) { mapSearchFocus = x; }
2583 - function onUserSearchFocus(x) { userSearchFocus = x; }
2584 - function onConsoleFocus(x) { consoleFocus = x; }
2585 -
2586 - function onSearchInputChanged() {
2587 - var x = Q('SearchInput').value.toLowerCase().trim(); putstore('_search', x);
2588 - var userSearch = null, ipSearch = null, groupSearch = null;
2589 - if (x.startsWith("user:")) { userSearch = x.substring(5); }
2590 - else if (x.startsWith("u:")) { userSearch = x.substring(2); }
2591 - else if (x.startsWith("ip:")) { ipSearch = x.substring(3); }
2592 - else if (x.startsWith("group:")) { groupSearch = x.substring(6); }
2593 - else if (x.startsWith("g:")) { groupSearch = x.substring(2); }
2594 -
2595 - if (x == '') {
2596 - // No search
2597 - for (var d in nodes) { nodes[d].v = true; }
2598 - } else if (ipSearch != null) {
2599 - // IP address search
2600 - for (var d in nodes) { nodes[d].v = ((nodes[d].ip != null) && (nodes[d].ip.indexOf(ipSearch) >= 0)); }
2601 - } else if (groupSearch != null) {
2602 - // Group filter
2603 - for (var d in nodes) { nodes[d].v = (meshes[nodes[d].meshid].name.toLowerCase().indexOf(groupSearch) >= 0); }
2604 - } else if (userSearch != null) {
2605 - // User search
2606 - for (var d in nodes) {
2607 - nodes[d].v = false;
2608 - if (nodes[d].users && nodes[d].users.length > 0) { for (var i in nodes[d].users) { if (nodes[d].users[i].toLowerCase().indexOf(userSearch) >= 0) { nodes[d].v = true; } } }
2609 - }
2610 - } else {
2611 - // Device name search
2612 - try {
2613 - var rs = x.split(/\s+/).join('|'), rx = new RegExp(rs); // In some cases (like +), this can throw an exception.
2614 - for (var d in nodes) {
2615 - nodes[d].v = (rx.test(nodes[d].name.toLowerCase())) || (nodes[d].rnamel != null && rx.test(nodes[d].rnamel.toLowerCase()));
2616 - if ((nodes[d].v == false) && nodes[d].tags) {
2617 - for (var s in nodes[d].tags) {
2618 - if (rx.test(nodes[d].tags[s].toLowerCase())) {
2619 - nodes[d].v = true;
2620 - break;
2621 - } else {
2622 - nodes[d].v = false;
2623 - }
2624 - }
2625 - }
2626 - }
2627 - } catch (ex) { for (var d in nodes) { nodes[d].v = true; } }
2628 - }
2629 - }
2630 -
2631 - var contextelement = null;
2632 - function handleContextMenu(event) {
2633 - hideContextMenu();
2634 - var scrollLeft = (window.pageXOffset !== null) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft;
2635 - var scrollTop = (window.pageYOffset !== null) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
2636 - var elem = document.elementFromPoint(event.pageX - scrollLeft, event.pageY - scrollTop);
2637 - if (elem && elem != null && elem.id == 'connectbutton2' && currentNode && currentNode.agent && (currentNode.agent.id > 0) && (currentNode.agent.id < 5)) {
2638 - contextelement = elem;
2639 - var contextmenudiv = document.getElementById('termShellContextMenu');
2640 - contextmenudiv.style.left = event.pageX + 'px';
2641 - contextmenudiv.style.top = event.pageY + 'px';
2642 - contextmenudiv.style.display = 'block';
2643 - } else if (elem && elem != null && elem.id == 'connectbutton2' && currentNode && currentNode.agent && (currentNode.agent.id > 4)) {
2644 - contextelement = elem;
2645 - var contextmenudiv = document.getElementById('termShellContextMenuLinux');
2646 - contextmenudiv.style.left = event.pageX + 'px';
2647 - contextmenudiv.style.top = event.pageY + 'px';
2648 - contextmenudiv.style.display = 'block';
2649 - } else if (elem && elem != null && elem.id == 'MxMESH') {
2650 - contextelement = elem;
2651 - var contextmenudiv = document.getElementById('meshContextMenu');
2652 - contextmenudiv.style.left = event.pageX + 'px';
2653 - contextmenudiv.style.top = event.pageY + 'px';
2654 - contextmenudiv.style.display = 'block';
2655 - /*} else if (elem && elem != null && elem.classList.contains('pluginTab')) {
2656 - contextelement = elem;
2657 - var contextmenudiv = document.getElementById('pluginTabContextMenu');
2658 - contextmenudiv.style.left = event.pageX + 'px';
2659 - contextmenudiv.style.top = event.pageY + 'px';
2660 - contextmenudiv.style.display = 'block';*/
2661 - } else {
2662 - while (elem && elem != null && elem.id != 'devs') { elem = elem.parentElement; }
2663 - if (!elem || elem == null) return true;
2664 - contextelement = elem;
2665 - var contextmenudiv = document.getElementById('contextMenu');
2666 - contextmenudiv.style.left = event.pageX + 'px';
2667 - contextmenudiv.style.top = event.pageY + 'px';
2668 - contextmenudiv.style.display = 'block';
2669 -
2670 - // Get the node and set the menu options
2671 - var nodeid = contextelement.children[1].attributes.onclick.value;
2672 - var node = getNodeFromId(nodeid.substring(12, nodeid.length - 18));
2673 - var mesh = meshes[node.meshid];
2674 - var meshlinks = mesh.links[userinfo._id];
2675 - var meshrights = meshlinks.rights;
2676 - var consoleRights = ((meshrights & 16) != 0);
2677 -
2678 - // Check if we have terminal and file access
2679 - var terminalAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 512) == 0));
2680 - var fileAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 1024) == 0));
2681 -
2682 - QV('cxdesktop', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0) || (node.intelamt && (node.intelamt.state == 2))) && ((meshrights & 8) || (meshrights & 256)));
2683 - QV('cxterminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0) || (node.intelamt && (node.intelamt.state == 2))) && (meshrights & 8) && terminalAccess);
2684 - QV('cxfiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8) && fileAccess);
2685 - QV('cxevents', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8));
2686 - QV('cxconsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8));
2687 - }
2688 -
2689 - return haltEvent(event);
2690 - }
2691 -
2692 - function cmaction(action,event) {
2693 - var nodeid = contextelement.children[1].attributes.onclick.value;
2694 - nodeid = nodeid.substring(12, nodeid.length - 18);
2695 - if (action == 7) { Q('viewselect').value = 3; Q('viewselect').onchange(); Q('autoConnectDesktopCheckbox').checked = true; Q('autoConnectDesktopCheckbox').onclick(); } // Multi-Desktop
2696 - if ((action > 0) && (action < 7)) {
2697 - var panel = [0, 10, 12, 11, 13, 16, 15][action]; // (invalid), General, Desktop, Terminal, Files, Events, Console
2698 - if (event && (event.shiftKey == true)) {
2699 - // Open the device in a different tab
2700 - window.open(window.location.origin + '?node=' + nodeid.split('/')[2] + '&viewmode=' + panel + '&hide=16', 'meshcentral:' + nodeid);
2701 - } else {
2702 - // Go to the right panel
2703 - gotoDevice(nodeid, panel);
2704 -
2705 - // If possible, connect...
2706 - var mesh = meshes[currentNode.meshid];
2707 - if ((currentNode.conn & 1) && (mesh.mtype == 2)) {
2708 - if ((panel == 11) && (desktop == null) && (currentNode.agent.caps & 1)) { connectDesktop(null, 3); } // Desktop
2709 - if ((panel == 12) && (terminal == null) && (currentNode.agent.caps & 2)) { connectTerminal(null, 1); } // Terminal
2710 - if ((panel == 13) && (files == null)) { connectFiles(null); } // files
2711 - }
2712 - }
2713 - }
2714 - }
2715 -
2716 - function cmmeshaction(action) {
2717 - var meshid = contextelement.attributes.onclick.value.substring(10, contextelement.attributes.onclick.value.length - 2);
2718 - var elements = document.getElementsByClassName('DeviceCheckbox');
2719 - if ((action == 1) || (action == 2)) {
2720 - for (var i = 0; i < elements.length; i++) {
2721 - if ((elements[i].attributes) && (elements[i].attributes['class']['value'].split(' ')[0] == meshid)) { elements[i].checked = (action == 1); }
2722 - }
2723 - }
2724 - //if (action == 3) { window.location = "multidesktop.aspx?mesh=" + meshid + "&auto=1"; }
2725 - p1updateInfo();
2726 - }
2727 -
2728 - function cmtermaction(action) {
2729 - connectTerminal(null, 1, { protocol: action });
2730 - }
2731 -
2732 - /*
2733 - function pluginTabClose() {
2734 - var pluginTab = contextelement;
2735 - var pname = pluginTab.getAttribute('x-data-plugin-sname');
2736 - var pdiv = Q('plugin-'+pname);
2737 - pdiv.parentNode.removeChild(pdiv);
2738 - pluginTab.parentNode.removeChild(pluginTab);
2739 - QV('p42', true);
2740 - goPlugin(-1);
2741 - }
2742 - */
2743 -
2744 - function hideContextMenu() {
2745 - QV('contextMenu', false);
2746 - QV('meshContextMenu', false);
2747 - QV('termShellContextMenu', false);
2748 - QV('termShellContextMenuLinux', false);
2749 - //QV('pluginTabContextMenu', false);
2750 - contextelement = null;
2751 - }
2752 -
2753 - //
2754 - // DEVICES MAP
2755 - //
2756 -
2757 - // Maps code starts from here. Initialize all the variables
2758 - var xxmap = {
2759 - map: null,
2760 - contextmenu: null,
2761 - activeInteractions: [], // Save Modified features in this list
2762 - showindex: 0,
2763 - markersSource: null, // Initialize a Source Vector
2764 - markersLayer: null,
2765 - mapLayer: null, // Create a tile and use OSM source
2766 - mapView: null, // Sets the initial view
2767 - }
2768 -
2769 - {{{StartGeoLocationJS}}}
2770 -
2771 - // Add a feature for every Node and change style if connection status changes
2772 - function updateMapMarkers(selectedMesh) {
2773 - if ((xxmap != null) && (xxmap.map == null)) { try { loadmap(); } catch (ex) { console.error('loadmap() exception', ex); } }
2774 - if (xxmap == null) return;
2775 - var boundingBox = null;
2776 - for (var i in nodes) {
2777 - try {
2778 - var loc = map_parseNodeLoc(nodes[i]), feature = xxmap.markersSource.getFeatureById(nodes[i]._id);
2779 - if ((loc != null) && ((nodes[i].meshid == selectedMesh) || (selectedMesh == null))) { // Draw markers for devices with locations
2780 - var lat = loc[0], lon = loc[1], type = loc[2];
2781 - if (boundingBox == null) { boundingBox = [ lat, lon, lat, lon, 0 ]; } else { if (lat < boundingBox[0]) { boundingBox[0] = lat; } if (lon < boundingBox[1]) { boundingBox[1] = lon; } if (lat > boundingBox[2]) { boundingBox[2] = lat; } if (lon > boundingBox[3]) { boundingBox[3] = lon; } }
2782 - if (feature == null) { addFeature(nodes[i]); boundingBox[4] = 1; } else { updateFeature(nodes[i], feature); feature.setStyle(markerStyle(nodes[i], loc[2])); } // Update Feature
2783 - } else {
2784 - if (feature) { xxmap.markersSource.removeFeature(feature); }
2785 - }
2786 - } catch (ex) { console.error('updateMapMarkers() exception', ex, JSON.stringify(nodes[i])); }
2787 - }
2788 - return boundingBox;
2789 - }
2790 -
2791 - // Show node details on hovering over a feature
2792 - var map_cm_popup = new ol.Overlay({ element: Q('xmap-info-window'), positioning: 'bottom-center', stopEvent: false });
2793 -
2794 - // Edit Marker item
2795 - var map_cm_editMarker = { text: "Modify node location", callback: function (obj) { modifyMarkerloc(obj.data); } };
2796 -
2797 - // Clear Marker item
2798 - var map_cm_clearMarker = { text: "Remove node location", callback: function (obj) {
2799 - meshserver.send({ action: 'changedevice', nodeid: obj.data.a, userloc: [] }); // Clear the user position marker
2800 - }};
2801 -
2802 - // Save Marker item
2803 - var map_cm_saveMarker = { text: "Save node location", callback: function (obj) { saveMarkerloc(obj.data); } };
2804 -
2805 - // Build a context menu for a feature
2806 - var map_cm_nodemenu_items = [
2807 - { text: "General information", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 10); } } },
2808 - { text: "Desktop", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 11); } } },
2809 - { text: "Terminal", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 12); } } },
2810 - { text: "Intel&reg; AMT", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 14); } } },
2811 - '-',
2812 - { text: "Zoom-in to extent", callback: function(obj) { var coords = obj.data.getGeometry().getCoordinates(); zoomToLocation(coords, 19); } },
2813 - { text: "Zoom-out to extent", callback: function(obj) { var coords = obj.data.getGeometry().getCoordinates(); zoomToLocation(coords, 2); } }
2814 - ];
2815 -
2816 - // Context menu for clicks other than on feature
2817 - var contextmenu_items = [
2818 - { text: "Refresh", callback: function () { refreshMap(true, true); } },
2819 - { text: "Zoom to fit extent", callback: function () { zoomToFitExtent(); } },
2820 - { text: "Center map here", callback: function(obj) { xxmap.mapView.animate({ center: obj.coordinate } ); } },
2821 - { text: "Place node here", callback: function(obj) { placeNode(obj.coordinate); } }
2822 - ];
2823 -
2824 - function stringToIntHash(str) {
2825 - var hash = 0, i;
2826 - for (i = 0; i < str.length; i++) { hash = ((hash << 5) - hash) + str.charCodeAt(i); hash |= 0; }
2827 - return hash;
2828 - };
2829 -
2830 - // Get the lat/lon from a node
2831 - function map_parseNodeLoc(node) {
2832 - var loc = null, t = 0;
2833 - if (node.iploc) { loc = node.iploc; t = 1; }
2834 - if (node.wifiloc) { loc = node.wifiloc; t = 2; }
2835 - if (node.gpsloc) { loc = node.gpsloc; t = 3; }
2836 - if (node.userloc) { loc = node.userloc; t = 4; }
2837 - if ((loc == null) || (typeof loc != 'string')) return null;
2838 - loc = loc.split(',');
2839 - if (t == 1) {
2840 - // If this is IP location, randomize the position a little.
2841 - return [ parseFloat(loc[0]) + (stringToIntHash(node._id.substring(0, 20)) / 100000000000), parseFloat(loc[1]) + (stringToIntHash(node._id.substring(20)) / 100000000000), t ];
2842 - } else {
2843 - // Return the real position
2844 - return [ parseFloat(loc[0]), parseFloat(loc[1]), t ];
2845 - }
2846 - }
2847 -
2848 - // Load the entire map
2849 - function loadmap() {
2850 - if (xxmap == null) return;
2851 - if ((features & 0x8000) == 0) { xxmap = null; return; } // Geolocation not supported
2852 - QV('viewselectmapoption', true);
2853 - QV('devViewButton4', true);
2854 - try {
2855 - // Initialize a Source Vector
2856 - xxmap.markersSource = new ol.source.Vector();
2857 -
2858 - xxmap.markersLayer = new ol.layer.Vector({
2859 - source: xxmap.markersSource
2860 - });
2861 -
2862 - // Create a tile and use OSM source
2863 - xxmap.mapLayer = new ol.layer.Tile({ source: new ol.source.OSM() });
2864 -
2865 - xxmap.mapView = new ol.View({ // Set the initial view
2866 - center: ol.proj.transform([0, 0], 'EPSG:4326', 'EPSG:3857'),
2867 - zoom: 2,
2868 - minZoom: 2,
2869 - maxZoom: 20,
2870 - extent: ol.proj.transformExtent([-100000, -69.55, 100000, 69.55], 'EPSG:4326', 'EPSG:3857')
2871 - });
2872 -
2873 - xxmap.map = new ol.Map({
2874 - target: 'xdevicesmap',
2875 - layers: [xxmap.mapLayer, xxmap.markersLayer],
2876 - view: xxmap.mapView
2877 - });
2878 -
2879 - xxmap.map.addOverlay(map_cm_popup);
2880 -
2881 - // Goto information tab if a user clicks on a feature
2882 - xxmap.map.on('click', function(evt) {
2883 - var feature = xxmap.map.forEachFeatureAtPixel(evt.pixel, function(feat, layer) { return feat; });
2884 - if (feature) {
2885 - var nodeid = feature.getId();
2886 - if (nodeid != null) { gotoDevice(nodeid, 10); } // Goto general info tab
2887 - else { // For pointer
2888 - var nodeFeatgoto = getCorrespondingFeature(feature); gotoDevice(nodeFeatgoto.getId(), 10);
2889 - }
2890 - }
2891 - });
2892 -
2893 - // On hover feature show the name of the node. Also add pointer style
2894 - xxmap.map.on('pointermove', function(evt) {
2895 - var feature = xxmap.map.forEachFeatureAtPixel(evt.pixel, function(feat, layer) { return feat; });
2896 - if (feature) {
2897 - xxmap.map.getTargetElement().style.cursor = 'pointer';
2898 - var coord = feature.getGeometry().getCoordinates();
2899 - // map_cm_popup.setPosition(evt.coordinate);
2900 - map_cm_popup.setPosition(coord);
2901 - var featid = feature.getId();
2902 - if (featid) {
2903 - QH('xmap-info-window', feature.get('name'));
2904 - } else {
2905 - var nodeFeat = getCorrespondingFeature(feature); // Return the node feature associated to pointer.
2906 - QH('xmap-info-window', nodeFeat.get('name'));
2907 - }
2908 - } else {
2909 - xxmap.map.getTargetElement().style.cursor = '';
2910 - QH('xmap-info-window', '');
2911 - }
2912 - });
2913 -
2914 - // Initialize context menu for openlayers
2915 - var contextmenu = new ContextMenu({
2916 - width: 160,
2917 - defaultItems: false, // defaultItems are Zoom In/Zoom Out
2918 - items: contextmenu_items
2919 - });
2920 -
2921 - // On right click open the context menu
2922 - contextmenu.on('open', function (evt) {
2923 - var feature = xxmap.map.forEachFeatureAtPixel(evt.pixel, function(ft, l){ return ft; });
2924 - xxmap.contextmenu.clear(); //Clear the context menu
2925 - if (feature) {
2926 - var featId = feature.getId();
2927 - if (featId) { addContextMenuItems(feature); } // Node feature will have an id
2928 - else { // If the feature is a pointer, Get its corresponding Node feature
2929 - var nodeFeature = getCorrespondingFeature(feature); //return the node feature associated to pointer.
2930 - if (nodeFeature) { addContextMenuItems(nodeFeature); }
2931 - else{ xxmap.contextmenu.extend(contextmenu_items); }
2932 - }
2933 - }
2934 - else { xxmap.contextmenu.extend(contextmenu_items); }
2935 - });
2936 - if (xxmap.contextmenu == null) { xxmap.contextmenu = contextmenu; }
2937 - xxmap.map.addControl(xxmap.contextmenu);
2938 - //addMeshOptions(); // Adds Mesh names to mesh dropdown
2939 - } catch (ex) {
2940 - console.log(ex);
2941 - QV('viewselectmapoption', false);
2942 - QV('devViewButton4', false);
2943 - xxmap = null;
2944 - }
2945 - }
2946 -
2947 - // Add feature on to Map for a Node
2948 - function addFeature(node, lat, lon) {
2949 - var existingfeature = getModifiedFeature(node._id); // Check if Corresponding feature was Modified ( Modifed feature are in active interactions list)
2950 - if (existingfeature) { xxmap.markersSource.addFeature(existingfeature); } // Add that existing feature
2951 - else { // Add new feature for this node
2952 - if (!lat && !lon) { var loc = map_parseNodeLoc(node); lat = loc[0]; lon = loc[1]; }
2953 -
2954 - // Fix the longiture and send an event to patch the db to correct coordinate format. It will cause second unnecessary updateFeature on this node to the map.
2955 - if (lon > 180) { lon = 180 - lon; meshserver.send({ action: 'changedevice', nodeid: node._id, userloc: [ lat, lon ] }); }
2956 -
2957 - if ((lat < 90) && (lat > -90) && (lon < 180) && (lon > -180)) { // Check valid lat/lon
2958 - var feature = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.transform([lon, lat], 'EPSG:4326','EPSG:3857')), name: node.name, status: node.conn, lat: lat, lon: lon });
2959 - feature.setId(node._id); // Set id for the device as nodeid
2960 - feature.setStyle(markerStyle(node));
2961 - xxmap.markersSource.addFeature(feature); // Add the feature to Marker Source
2962 - }
2963 - }
2964 - }
2965 -
2966 - // Removing any feature from map
2967 - function removeFeature(node) {
2968 - var feature = xxmap.markersSource.getFeatureById(node._id);
2969 - if (feature) { xxmap.markersSource.removeFeature(feature); }
2970 - }
2971 -
2972 - // Update feature
2973 - function updateFeature(node, feature) {
2974 - if (node.conn != feature.get('status') ) { // Update status if changed
2975 - feature.set('status',node.conn)
2976 - feature.setStyle(markerStyle(node));
2977 - }
2978 -
2979 - // Since this is IP address location, add some fixed randomness to the location. Avoid pin pile-up.
2980 - var loc = map_parseNodeLoc(node);
2981 - if (loc != null) {
2982 - var lat = loc[0], lon = loc[1];
2983 - if ((lat != feature.get('lat')) || (lon != feature.get('lon'))) { // Update lat and lon if changed
2984 - feature.set('lat', lat); feature.set('lon', lon);
2985 - var modifiedCoordinates = ol.proj.transform([parseFloat(lon), parseFloat(lat)], 'EPSG:4326', 'EPSG:3857');
2986 - feature.getGeometry().setCoordinates(modifiedCoordinates);
2987 - }
2988 - }
2989 -
2990 - if (node.name != feature.get('name') ) { feature.set('name', node.name); } // Update name
2991 - }
2992 -
2993 - // Enable dragging of a marker after edit option is clicked in context menu
2994 - function modifyMarkerloc(ft){
2995 - var featid = ft.getId();
2996 - if (featid) {
2997 - ft.setStyle(markerStyle(getNodeFromId(ft.a), 4)); // Switch to a user marker
2998 - if ( !getActiveInteractions(ft)) {
2999 - var dragInteration = new ol.interaction.Modify({
3000 - features: new ol.Collection([ft]),
3001 - pixelTolerance: 10
3002 - });
3003 - xxmap.activeInteractions.push({ featureid: featid, feature:ft, interaction: dragInteration }); // Also keep track of Interactions
3004 - xxmap.map.addInteraction(dragInteration);
3005 - }
3006 - }
3007 - }
3008 -
3009 - // This will be called when save location option is clicked in context menu
3010 - function saveMarkerloc(ft){
3011 - var featid = ft.getId()
3012 - if (featid) {
3013 - var actInteraction = getActiveInteractions(ft);
3014 - if (actInteraction) { // Check if the interaction exists
3015 - xxmap.map.removeInteraction(actInteraction); //Clear Interaction for that node
3016 - removeInteraction(featid);
3017 - var coord = ft.getGeometry().getCoordinates();
3018 - var v = ol.proj.transform(coord, 'EPSG:3857', 'EPSG:4326');
3019 - if (v[0] > 180) { v[0] = 180 - v[0]; }
3020 - var vx = [ v[1], v[0] ]; // Flip the coordinates around, lat/long
3021 - meshserver.send({ action: 'changedevice', nodeid: featid, userloc: vx }); // Send them to server to save changes
3022 - }
3023 - }
3024 - }
3025 -
3026 - // Style the Markers
3027 - function markerStyle(node, type) {
3028 - if (type == null) {
3029 - type = 0;
3030 - if (node.iploc) { type = 1; }
3031 - if (node.wifiloc) { type = 2; }
3032 - if (node.gpsloc) { type = 3; }
3033 - if (node.userloc) { type = 4; }
3034 - }
3035 - var types = ['', '-ip','-wifi','-gps','-user'];
3036 - var color = connStateColor(node);
3037 - var style = new ol.style.Style({
3038 - image: new ol.style.Icon({ color: color, anchor: [0.5, 1], src: 'images/mapmarker' + types[type] + '.png' })
3039 - //stroke: new ol.style.Stroke({ color: '#000', width: 20 })
3040 - //text: new ol.style.Text({ text: 'bob!', textAlign: 'right', offsetX: -10, fill: new ol.style.Fill({ color: '#000' }), stroke: new ol.style.Stroke({ color: '#fff', width: 2 }) })
3041 - });
3042 -
3043 - //deviceMark.setStyle(new ol.style.Style({
3044 - // text: new ol.style.Text({
3045 - // //font: '12px helvetica,sans-serif',
3046 - // text: currentNode.name,
3047 - // textAlign: 'right',
3048 - // offsetX: -10,
3049 - // fill: new ol.style.Fill({ color: '#000' }),
3050 - // stroke: new ol.style.Stroke({ color: '#fff', width: 2 })
3051 - // }),
3052 - // image: new ol.style.Icon(({ color: [113, 140, 0], src: 'images/dot.png' })) }));
3053 -
3054 - return [ style ];
3055 - }
3056 -
3057 - // TODO: Add more connection status types. Currently we only change color if connection status changes
3058 - function connStateColor(nodeConn){
3059 - if (nodeConn.conn == 1 || nodeConn.conn == 3 || nodeConn.conn == 5) { return '#00ffdd'; } // Green for connected devices
3060 - return '#C70039'; // Red if the Agent is not connected
3061 - }
3062 -
3063 - // Add save/edit option to context menu
3064 - function addContextMenuItems(feature) {
3065 - if (getActiveInteractions(feature)) { // If this feature is modified then display save option in contextmenu
3066 - map_cm_saveMarker.data = feature;
3067 - xxmap.contextmenu.push(map_cm_saveMarker);
3068 - } else {
3069 - map_cm_editMarker.data = feature;
3070 - xxmap.contextmenu.push(map_cm_editMarker);
3071 - var node = getNodeFromId(feature.a);
3072 - if (node.userloc) {
3073 - map_cm_clearMarker.data = feature;
3074 - xxmap.contextmenu.push(map_cm_clearMarker);
3075 - }
3076 - }
3077 - map_cm_nodemenu_items.forEach(function (item){
3078 - if (item.text == "Zoom-in to extent" || item.text == "Zoom-out to extent") { item.data = feature; }
3079 - else { if (item != '-') { item.data = feature.getId(); } }
3080 - });
3081 - xxmap.contextmenu.extend(map_cm_nodemenu_items);
3082 - }
3083 -
3084 - // Return a active Interaction if it exists in activeInteractions list
3085 - function getActiveInteractions(feature) {
3086 - var featid = feature.getId();
3087 - for (var i = 0; i < xxmap.activeInteractions.length; i++) {
3088 - if (xxmap.activeInteractions[i].featureid == featid) { return xxmap.activeInteractions[i].interaction; }
3089 - }
3090 - return false;
3091 - }
3092 -
3093 - // Return Modified feature based on Id
3094 - function getModifiedFeature(featid) {
3095 - if (featid) {
3096 - for (var i = 0; i < xxmap.activeInteractions.length; i++) {
3097 - if (xxmap.activeInteractions[i].featureid == featid) { return xxmap.activeInteractions[i].feature; }
3098 - }
3099 - }
3100 - return null;
3101 - }
3102 -
3103 - // Remove Interaction
3104 - function removeInteraction(ftid) {
3105 - var index = -1;
3106 - for (var i = 0; i < xxmap.activeInteractions.length; i++) {
3107 - if (xxmap.activeInteractions[i].featureid === ftid) { index = i; break; }
3108 - }
3109 - if (index >= 0) { xxmap.activeInteractions.splice(index, 1); }
3110 - }
3111 -
3112 - // Check if pointer coordinates are equal to features and return node feature
3113 - function getCorrespondingFeature(pointerFeat) {
3114 - var pointerCoord = pointerFeat.getGeometry().getCoordinates();
3115 - for (var i = 0; i < xxmap.activeInteractions.length ; i++) {
3116 - var modifiedFeatures = xxmap.activeInteractions[i].feature;
3117 - var fearCoord = modifiedFeatures.getGeometry().getCoordinates();
3118 - if (fearCoord[0].toFixed(5) == pointerCoord[0].toFixed(5) && fearCoord[1].toFixed(5) == pointerCoord[1].toFixed(5) ) { return modifiedFeatures; }
3119 - }
3120 - return null;
3121 - }
3122 -
3123 - // Refresh the map and clear list
3124 - function refreshMap(reset, rebound){
3125 - if (reset) {
3126 - xxmap.map.setTarget(null);
3127 - xxmap.map = null;
3128 - xxmap.markersSource = null;
3129 - xxmap.mapView = null;
3130 - xxmap.mapLayer = null;
3131 - xxmap.activeInteractions = []; // Clear Active Interaction list
3132 - }
3133 - //clearMeshOptions();
3134 - //onSelectMeshChange();
3135 - var box = updateMapMarkers();
3136 - if ((box != null) && (rebound || (box[4] == 1))) {
3137 - var clat = (box[0] + box[2]) / 2;
3138 - var clon = (box[1] + box[3]) / 2;
3139 - var cscale = Math.max(Math.abs(box[0] - box[2]), Math.abs(box[1] - box[3]));
3140 - var view = xxmap.map.getView();
3141 - view.setCenter(ol.proj.transform([clon, clat], 'EPSG:4326', 'EPSG:3857'));
3142 - var i = 360, j = -2;
3143 - while (i > cscale) { j++; i = i / 2; }
3144 - view.setZoom(j);
3145 - }
3146 - }
3147 -
3148 - // Called When Place a node option is clicked from context menu
3149 - function placeNode(coords) {
3150 - if (xxdialogMode) return;
3151 - var x = '<div style=margin-bottom:6px><label for=selectnode-search>' + "Search" + '</label>&nbsp&nbsp<input type=text placeholder="' + "Device name" + '" id="selectnode-search" onchange=onPlaceNodeInputChange() onkeyup=onPlaceNodeInputChange() autocomplete=off style=width:120px></div><div id=placenode style="height:254px;overflow-y:auto;width:100%;margin:12px 1px 4px 1px;"><div id=noNodesMapPlace style=text-align:center;width:100%;display:none>' + "No devices found." + '</div>';
3152 - for (var i in nodes) {
3153 - x += '<div class=noselect id=' + nodes[i]._id + '-rowid onclick=selectNodeToPlace(event,\''+ nodes[i]._id +'\') style=background-color:lightgray;margin-bottom:4px;border-radius:2px><input name=PlaceMapDeviceCheckbox id=' + nodes[i]._id + '-checkid type=checkbox style=width:16px;display:inline />';
3154 - x += '<div class=j' + nodes[i].icon + ' style=width:16px;height:16px;margin-top:2px;margin-right:4px;display:inline-block></div><div style=width:16px;display:inline>' + nodes[i].name + '</div></div>';
3155 - }
3156 - setDialogMode(2, "Select a node to place", 3, placeNodeEx, x + '</div>', coords);
3157 - onPlaceNodeInputChange();
3158 - }
3159 -
3160 - function placeNodeEx(button, coords) {
3161 - var elements = document.getElementsByName('PlaceMapDeviceCheckbox');
3162 - for (var i in elements) {
3163 - if (elements[i].checked) {
3164 - var node = getNodeFromId(elements[i].id.substring(0, elements[i].id.length - 8));
3165 - if (node) {
3166 - var feature = xxmap.markersSource.getFeatureById(i);
3167 - var v = ol.proj.transform(coords, 'EPSG:3857', 'EPSG:4326');
3168 - var vx = [ v[1], v[0] ]; // Flip the coordinates around, lat/long
3169 - if (feature) {
3170 - feature.getGeometry().setCoordinates(coords);
3171 - var activeInteraction = getActiveInteractions(feature);
3172 - if (activeInteraction) {
3173 - saveMarkerloc(feature);
3174 - } else { // If this feature is not saved after its location is changed, then send updated coords to server.
3175 - meshserver.send({ action: 'changedevice', nodeid: node._id, userloc: vx }); // Send them to server to save changes
3176 - }
3177 - } else {
3178 - meshserver.send({ action: 'changedevice', nodeid: node._id, userloc: vx }); // This Node is not yet added to maps.
3179 - }
3180 - }
3181 - }
3182 - }
3183 - }
3184 -
3185 - // Called when the user changes the search box
3186 - function onPlaceNodeInputChange() {
3187 - updatePlaceNodeTable(Q('selectnode-search').value.trim().toLowerCase());
3188 - }
3189 -
3190 - // Update the list of devices in the "place on map" table
3191 - function updatePlaceNodeTable(inputSearch) {
3192 - var elements = document.getElementsByName('PlaceMapDeviceCheckbox'), count = 0;
3193 - for (var i in nodes) {
3194 - var visible = ((nodes[i].namel.indexOf(inputSearch) >= 0 || inputSearch == '') || (nodes[i].rnamel != null && nodes[i].rnamel.indexOf(inputSearch) >= 0));
3195 - if (visible) { count++; }
3196 - QV(nodes[i]._id + '-rowid', visible);
3197 - }
3198 - QV('noNodesMapPlace', count == 0);
3199 - //console.log(selected);
3200 - //for (var i in nodes) {
3201 - // if ((nodes[i].name.toLowerCase().indexOf(inputSearch) >= 0 || inputSearch == '') || (nodes[i].rnamel != null && nodes[i].rnamel.toLowerCase().indexOf(inputSearch) >= 0)) {
3202 - // console.log(selected.indexOf(nodes[i]._id));
3203 - // x += '<div class=noselect id=' + nodes[i]._id + '-rowid onclick=selectNodeToPlace(event,\''+ nodes[i]._id +'\') style=background-color:lightgray;margin-bottom:4px;border-radius:2px><input name=PlaceMapDeviceCheckbox id=' + nodes[i]._id + '-checkid type=checkbox style=width:16px;display:inline ' + ((selected.indexOf(nodes[i]._id) >= 0)?'checked':'') + ' />';
3204 - // x += '<div class=j' + nodes[i].icon + ' style=width:16px;height:16px;margin-top:2px;margin-right:4px;display:inline-block></div><div style=width:16px;display:inline>' + nodes[i].name + '</div></div>';
3205 - // }
3206 - //}
3207 - //if (x == '') { x = '<div style=text-align:center;width:100%>No devices found.</div>'; }
3208 - //QH('placenode', '');
3209 - }
3210 -
3211 - // Called when a user clicks on a device to toggle selection for placement on map.
3212 - function selectNodeToPlace(e, id) {
3213 - // Toggle checkbox if needed
3214 - if (e.target.name != 'PlaceMapDeviceCheckbox') { var inputElement = Q(id + '-checkid'); inputElement.checked = !inputElement.checked; }
3215 -
3216 - // Check button state
3217 - var elements = document.getElementsByName('PlaceMapDeviceCheckbox'), checkcount = 0;
3218 - for (var i in elements) { if (elements[i].checked) checkcount++; }
3219 - QE('idx_dlgOkButton', checkcount > 0);
3220 - }
3221 -
3222 - // Add option for available meshes in mesh Dropdown
3223 - function addMeshOptions(addMeshid, meshName) {
3224 - //var meshOptions = Q('select-mesh');
3225 - //if (addMeshid && meshName) {
3226 - // var option = document.createElement('option');
3227 - // option.value =addMeshid;
3228 - // option.text = meshName;
3229 - // meshOptions.add(option); // Add specific option
3230 - //}
3231 - //else {
3232 - // for (var i in meshes) { // Add all options
3233 - // var option = document.createElement('option');
3234 - // option.value = i;
3235 - // option.text = meshes[i].name;
3236 - // meshOptions.add(option);
3237 - // }
3238 - //}
3239 - }
3240 -
3241 - // Remove/Modify options in Mesh dropdown (if modMeshname is defined then Modify else Remove)
3242 - function meshOptionRmvMod(delMeshid, modMeshname){
3243 - //var meshOptions = Q('select-mesh');
3244 - //if (delMeshid) {
3245 - // var index=-1;
3246 - // for (var i = 1; i < meshOptions.options.length; i++) {
3247 - // if (meshOptions[i].value === delMeshid) { index=i; }
3248 - // }
3249 - // if (index > 0) {
3250 - // if (modMeshname) {
3251 - // meshOptions[index].innerHTML=modMeshname; // If Mesh name is Modified
3252 - // }
3253 - // else { meshOptions.remove(index); }
3254 - // }
3255 - //}
3256 - }
3257 -
3258 - //Check if there is any mesh created
3259 - function meshExists() {
3260 - for (var i in meshes) { if (meshes[i]) { return true; } }
3261 - return false;
3262 - }
3263 -
3264 - // Reset Mesh dropdown option to 'All' when a current view mesh is deleted.
3265 - function setMeshView(emeshid) {
3266 - var selectMeshElement=Q('select-mesh');
3267 - var selectedIndex = selectMeshElement.selectedIndex;
3268 - if (selectMeshElement[selectedIndex].value == emeshid) { selectMeshElement[0].selected = true; onSelectMeshChange(); }
3269 - }
3270 -
3271 - // Clear all mesh options except 'All'
3272 - function clearMeshOptions() {
3273 - //var meshOptions=Q('select-mesh');
3274 - //for(var i = meshOptions.options.length - 1 ; i > 0 ; i--) { meshOptions.remove(i); }
3275 - }
3276 -
3277 - // Make a http get call- Replace this with AJAX get if jquery is used
3278 - function getSearchLocation() {
3279 - try {
3280 - var searchdata = Q('mapSearchLocation').value.trim();
3281 - if (searchdata.length > 0) {
3282 - var xmlhttp = new XMLHttpRequest(); // Compatible with Chrome, Opera, Safari, IE7+, Firefox.
3283 - xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { formatSearchData(xmlhttp.responseText); } }
3284 - xmlhttp.open('GET', 'https://nominatim.openstreetmap.org/search?q=' + searchdata + '&format=json', true); // Get request
3285 - xmlhttp.send();
3286 - }
3287 - } catch (e) {}
3288 - }
3289 -
3290 - // Format data recieved from nominatim API and display it on content window
3291 - function formatSearchData(data) {
3292 - try {
3293 - QH('xmapSearchResults','');
3294 - var dataInfo = JSON.parse(data), count = 0, x = '<div class="xmapItem">';
3295 - for (var i = 0; i < dataInfo.length; i++) {
3296 - if (dataInfo[i].display_name && dataInfo[i].boundingbox[0] && dataInfo[i].boundingbox[1] && dataInfo[i].boundingbox[2] && dataInfo[i].boundingbox[3]) {
3297 - count++;
3298 - var itemclass = (i % 2 == 0)?'xmapItemSel1':'xmapItemSel1';
3299 - x += '<div class="' + itemclass + '" onclick=mapGotoSelectedLocation(this)><div>' + dataInfo[i].display_name + '</div><div style=display:none>' + dataInfo[i].boundingbox[0] + '!#!' + dataInfo[i].boundingbox[1] + '!#!' + dataInfo[i].boundingbox[2] + '!#!' + dataInfo[i].boundingbox[3] + '</div></div>';
3300 - }
3301 - }
3302 - x += '</div>';
3303 - if (count == 1) {
3304 - // If only one result is returned then zoom to that location
3305 - var extent = [ parseFloat(dataInfo[0].boundingbox[2]), parseFloat(dataInfo[0].boundingbox[0]), parseFloat(dataInfo[0].boundingbox[3]), parseFloat(dataInfo[0].boundingbox[1]) ];
3306 - zoomToExtent(extent);
3307 - } else {
3308 - if (count == 0) { x = '<div style=width:200px>' + "No location found." + '<div>'; }
3309 - QV('xmapSearchResultsDlg', true);
3310 - }
3311 - QH('xmapSearchResults', x);
3312 - }
3313 - catch (e) {}
3314 - }
3315 -
3316 - // Zoom into the bounding box
3317 - function mapGotoSelectedLocation(obj) {
3318 - var objchildren = obj.children;
3319 - var boundingBox = objchildren[1].innerHTML.split('!#!');
3320 - var extent = [parseFloat(boundingBox[2]), parseFloat(boundingBox[0]), parseFloat(boundingBox[3]), parseFloat(boundingBox[1])];
3321 - //Q('search-location').value = objchildren[0].innerHTML;
3322 - zoomToExtent(extent);
3323 - mapCloseSearchWindow();
3324 - }
3325 -
3326 - // Close the search window
3327 - function mapCloseSearchWindow() {
3328 - QH('xmapSearchResults', '');
3329 - QV('xmapSearchResultsDlg', false);
3330 - }
3331 -
3332 - // Zoom to specific cordinates
3333 - function zoomToLocation(coordinates, zoomVal) {
3334 - var view = xxmap.map.getView();
3335 - view.setCenter(coordinates);
3336 - view.setZoom(zoomVal);
3337 - }
3338 -
3339 - function zoomToFitExtent() {
3340 - var features = xxmap.markersSource.getFeatures();
3341 - if (features.length > 0) {
3342 - var extent = xxmap.markersSource.getExtent();
3343 - xxmap.map.getView().fit(extent, xxmap.map.getSize());
3344 - }
3345 - }
3346 -
3347 - function zoomToExtent(extent){
3348 - var boundingExtent = ol.proj.transformExtent(extent, ol.proj.get('EPSG:4326'), ol.proj.get('EPSG:3857'));
3349 - xxmap.map.getView().fit(boundingExtent, xxmap.map.getSize());
3350 - }
3351 -
3352 - {{{EndGeoLocationJS}}}
3353 -
3354 - //
3355 - // MY DEVICE
3356 - //
3357 - function refreshDevice(nodeid) {
3358 - if (!currentNode || currentNode._id != nodeid) return;
3359 - gotoDevice(nodeid, xxcurrentView, true);
3360 - }
3361 -
3362 - function getNodeRights(nodeid) {
3363 - var node = getNodeFromId(nodeid), mesh = meshes[node.meshid];
3364 - return mesh.links[userinfo._id].rights;
3365 - }
3366 -
3367 - var currentNode;
3368 - var powerTimelineNode = null;
3369 - var powerTimelineReq = null;
3370 - var powerTimelineUpdate = null;
3371 - var powerTimeline = null;
3372 - function getCurrentNode() { return currentNode; };
3373 - function gotoDevice(nodeid, panel, refresh, event) {
3374 - // Remind the user to verify the email address
3375 - if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until a email address is verified. This is required for password recovery. Go to the \"My Account\" tab to change and verify an email address."); return; }
3376 -
3377 - // Remind the user to add two factor authentication
3378 - if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0))) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" tab and look at the \"Account Security\" section."); return; }
3379 -
3380 - if (event && (event.shiftKey == true)) {
3381 - // Open the device in a different tab
3382 - window.open(window.location.origin + '?node=' + nodeid.split('/')[2] + '&viewmode=10&hide=16', 'meshcentral:' + nodeid);
3383 - return;
3384 - }
3385 -
3386 - //disconnectAllKvmFunction();
3387 - var node = getNodeFromId(nodeid);
3388 - var mesh = meshes[node.meshid];
3389 - var meshrights = mesh.links[userinfo._id].rights;
3390 - if (!currentNode || currentNode._id != node._id || refresh == true) {
3391 - currentNode = node;
3392 -
3393 - // Add node name
3394 - var nname = EscapeHtml(node.name);
3395 - if (nname.length == 0) { nname = '<i>' + "None" + '</i>'; }
3396 - if (((meshrights & 4) != 0) && ((!mesh.flags) || ((mesh.flags & 2) == 0))) { nname = '<span tabindex=0 title=\"' + "Click here to edit the server-side device name" + '\" onclick=showEditNodeValueDialog(0) onkeyup="if (event.key == \'Enter\') showEditNodeValueDialog(0)" style=cursor:pointer>' + nname + ' <img class=hoverButton src="images/link5.png" /></span>'; }
3397 - nname += '<span style=color:#AAA;font-size:small> - ' + EscapeHtml(mesh.name) + '</span>';
3398 - QH('p10deviceName', nname);
3399 - QH('p11deviceName', nname);
3400 - QH('p12deviceName', nname);
3401 - QH('p13deviceName', nname);
3402 - QH('p14deviceName', nname);
3403 - QH('p15deviceName', "Console - " + nname);
3404 - QH('p16deviceName', nname);
3405 - QH('p17deviceName', nname);
3406 - QH('p19deviceName', nname);
3407 -
3408 - // Node attributes
3409 - var x = '<table style=width:100%>';
3410 -
3411 - // Attribute: Mesh
3412 - x += addDeviceAttribute('<span title=\"' + "The name of the device group this computer belong to." + '\">' + "Group" + '</span>', '<a href=# title=\"' + "The name of the device group this computer belong to" + '\" onclick=gotoMesh("' + node.meshid + '") style=cursor:pointer>' + EscapeHtml(meshes[node.meshid].name) + '</a>');
3413 -
3414 - // Attribute: Name
3415 - if ((node.rname != null) && (node.name != node.rname)) { 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>'); }
3416 -
3417 - // Attribute: Host
3418 - if ((features & 1) == 0) { // If not WAN-only, local hostname is in use
3419 - if ((meshrights & 4) != 0) {
3420 - if (node.host) {
3421 - x += addDeviceAttribute("Hostname", '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer>' + EscapeHtml(node.host) + '</span>');
3422 - } else {
3423 - x += addDeviceAttribute("Hostname", '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer><i>' + "None" + '</i></span>');
3424 - }
3425 - } else {
3426 - x += addDeviceAttribute("Hostname", EscapeHtml(node.host));
3427 - }
3428 - }
3429 -
3430 - // Attribute: Description
3431 - var description = node.desc?EscapeHtml(node.desc):('<i>' + "None" + '</i>');
3432 - if ((meshrights & 4) != 0) {
3433 - x += addDeviceAttribute("Description", '<span onclick=showEditNodeValueDialog(2) style=cursor:pointer>' + description + ' <img class=hoverButton src="images/link5.png" /></span>');
3434 - } else {
3435 - x += addDeviceAttribute("Description", description);
3436 - }
3437 -
3438 - // Attribute: Mesh Agent
3439 - if ((node.agent != null) && (node.agent.id != null) && (node.agent.ver != null)) {
3440 - var str = '';
3441 - if (node.agent.id <= agentsStr.length) { str = agentsStr[node.agent.id]; } else { str = agentsStr[0]; }
3442 - if (node.agent.ver != 0) { str += ' v' + node.agent.ver; }
3443 - x += addDeviceAttribute("Mesh Agent", str);
3444 - }
3445 -
3446 - // Attribute: Intel AMT
3447 - if (node.intelamt != null) {
3448 - var str = '';
3449 - var provisioningStates = { 0: nobreak("Not Activated (Pre)"), 1: nobreak("Not Activated (In)"), 2: nobreak("Activated") };
3450 - if (node.intelamt.ver != null && node.intelamt.state == null) { str += '<i>' + "Unknown State" + '</i>, v' + node.intelamt.ver; } else
3451 -
3452 - if ((node.intelamt.ver == null) && (node.intelamt.state == 2)) { str += '<i>' + "Activated" + '</i>'; }
3453 - else if ((node.intelamt.ver == null) || (node.intelamt.state == null)) { str += '<i>' + "Unknown Version & State" + '</i>'; }
3454 - else {
3455 - str += provisioningStates[node.intelamt.state];
3456 - if ((node.intelamt.state == 2) && 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>'; } }
3457 - str += (', v' + node.intelamt.ver);
3458 - }
3459 -
3460 - if (node.intelamt.tls == 1) { str += ', <span title=\"' + "Intel AMT is setup with TLS network security" + '\">' + "TLS" + '</span>'; }
3461 - if (node.intelamt.state == 2) {
3462 - if (node.intelamt.user == null || node.intelamt.user == '') {
3463 - if ((meshrights & 4) != 0) {
3464 - str += ', <i style=color:#FF0000;cursor:pointer title=\"' + "Edit Intel&reg; AMT credentials" + '\" onclick=editDeviceAmtSettings("' + node._id + '")>' + "No Credentials" + '</i>';
3465 - } else {
3466 - str += ', <i style=color:#FF0000>' + "No Credentials" + '</i>';
3467 - }
3468 - }
3469 - str += ' ';
3470 - if ((meshrights & 4) != 0) {
3471 - str += '<img src=images/link4.png height=10 width=10 title=\"' + "Edit Intel&reg; AMT credentials" + '\" style=cursor:pointer onclick=editDeviceAmtSettings("' + node._id + '")>';
3472 - }
3473 - }
3474 -
3475 - var meName = '<span title=\"Intel&reg; Manageability Engine\">' + "Intel&reg; ME" + '<span>';
3476 - if (typeof node.intelamt.sku == 'number') {
3477 - if ((node.intelamt.sku & 8) != 0) { meName = '<span title=\"' + "Intel&reg; Active Management Technology" + '\">' + "Intel&reg; AMT" + '<span>'; }
3478 - else if ((node.intelamt.sku & 16) != 0) { meName = '<span title=\"' + "Intel&reg; Standard Manageability" + '\">' + "Intel&reg; SM" + '<span>'; }
3479 - }
3480 - x += addDeviceAttribute(meName, str);
3481 - }
3482 -
3483 - if (mesh.mtype == 2) {
3484 - // Attribute: Mesh Agent Tag
3485 - if ((node.agent != null) && (node.agent.tag != null)) {
3486 - var tag = EscapeHtml(node.agent.tag);
3487 - if (tag.startsWith('mailto:')) { tag = '<a href="' + tag + '">' + tag.substring(7) + '</a>'; }
3488 - x += addDeviceAttribute("Agent Tag", tag);
3489 - }
3490 - } else {
3491 - // Attribute: Intel AMT Tag
3492 - if ((node.intelamt != null) && (node.intelamt.tag != null)) {
3493 - var tag = EscapeHtml(node.intelamt.tag);
3494 - if (tag.startsWith('mailto:')) { tag = '<a href="' + tag + '">' + tag.substring(7) + '</a>'; }
3495 - x += addDeviceAttribute("Intel&reg; AMT Tag", tag);
3496 - }
3497 - }
3498 -
3499 - // Attribute: Intel AMT
3500 - //if (node.intelamt && node.intelamt.user) { x += addDeviceAttribute('Intel&reg; AMT', node.intelamt.user); }
3501 -
3502 - // Operating system description
3503 - if (node.osdesc) { x += addDeviceAttribute("Operating System", node.osdesc); }
3504 -
3505 - // Antivirus
3506 - if (node.av && node.av.length > 0) {
3507 - var y = [];
3508 - for (var i in node.av) {
3509 - if (node.av[i].product) {
3510 - var avx = EscapeHtml(node.av[i].product);
3511 - if (node.av[i].enabled !== true) { avx += ' - <span style=color:red>' + "Disabled" + '</span>'; }
3512 - if (node.av[i].updated !== true) { avx += ' - <span style=color:red>' + "Out of date" + '</span>'; }
3513 - if ((node.av[i].enabled == true) && (node.av[i].updated == true)) { avx += ' - <span style=color:green>' + "OK" + '</span>'; }
3514 - y.push(avx);
3515 - }
3516 - }
3517 - x += addDeviceAttribute("Antivirus", y.join('<br />'));
3518 - }
3519 -
3520 - // Active Users
3521 - if (node.users && node.conn && (node.users.length > 0) && (node.conn & 1)) { x += addDeviceAttribute(format("Active User{0}", ((node.users.length > 1)?'s':'')), node.users.join(', ')); }
3522 -
3523 - // Attribute: Connectivity (Only show this if more than just the agent is connected).
3524 - var connectivity = node.conn;
3525 - if (connectivity && connectivity > 1) {
3526 - var cstate = [];
3527 - if ((node.conn & 1) != 0) cstate.push('<span title=\"' + "Mesh agent is connected and ready for use." + '\">' + "Mesh Agent" + '</span>');
3528 - if ((node.conn & 2) != 0) cstate.push('<span title=\"' + "Intel&reg; AMT CIRA is connected and ready for use." + '\">' + "Intel&reg; AMT CIRA" + '</span>');
3529 - else if ((node.conn & 4) != 0) cstate.push('<span title=\"' + "Intel&reg; AMT is routable and ready for use." + '\">' + "Intel&reg; AMT" + '</span>');
3530 - if ((node.conn & 8) != 0) cstate.push('<span title=\"' + "Mesh agent is reachable using another agent as relay." + '\">' + "Mesh Relay" + '</span>');
3531 - if ((node.conn & 16) != 0) { cstate.push('<span title=\"' + "MQTT connection to the device is active." + '\">' + "MQTT" + '</span>'); }
3532 - x += addDeviceAttribute("Connectivity", cstate.join(', '));
3533 - }
3534 -
3535 - // Node grouping tags
3536 - var groupingTags = '<i>' + "None" + '</i>';
3537 - if (node.tags != null) { groupingTags = ''; for (var i in node.tags) { groupingTags += '<span class="tagSpan">' + node.tags[i] + '</span>'; } }
3538 - if ((meshrights & 4) != 0) {
3539 - x += addDeviceAttribute('Tags', '<span onclick=showEditNodeValueDialog(3) style=cursor:pointer>' + groupingTags + ' <img class=hoverButton src="images/link5.png" /></span>');
3540 - } else {
3541 - x += addDeviceAttribute('Tags', groupingTags);
3542 - }
3543 -
3544 - x += '</table><br />';
3545 - // Show action button, only show if we have permissions 4, 8, 64
3546 - if ((meshrights & 76) != 0) { x += '<input type=button value=\"' + "Actions" + '\" title=\"' + "Perform power actions on the device" + '\" onclick=deviceActionFunction() />'; }
3547 - x += '<input type=button value=\"' + "Notes" + '\" title=\"' + "View notes about this device" + '\" onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponent(node._id) + '") />';
3548 - x += '<input type=button value=\"' + "Log Event" + '\" title=\"' + "Write an event for this device" + '\" onclick=writeDeviceEvent("' + encodeURIComponent(node._id) + '") />';
3549 - //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() />'; }
3550 - QH('p10html', x);
3551 -
3552 - // Show node last 7 days timeline
3553 - masterUpdate(256);
3554 -
3555 - // Show bottom buttons
3556 - x = '<div class="p10html3right">';
3557 - if ((meshrights & 4) != 0) {
3558 - // TODO: Show change group only if there is another mesh of the same type.
3559 - x += '&nbsp;<a href=# onclick=p10showChangeGroupDialog(["' + node._id + '"]) title=\"' + "Move this device to a different device group" + '\">' + "Change Group" + '</a>';
3560 - x += '&nbsp;<a href=# onclick=p10showDeleteNodeDialog("' + node._id + '") title=\"' + "Remove this device" + '\">' + "Delete Device" + '</a>';
3561 - }
3562 - x += '</div><div class="p10html3left">';
3563 - if (mesh.mtype == 2) x += '<a href=# onclick=p10showNodeNetInfoDialog("' + node._id + '") title=\"' + "Show device network interface information" + '\">' + "Interfaces" + '</a>&nbsp;';
3564 - if (xxmap != null) x += '<a href=# onclick=p10showNodeLocationDialog("' + node._id + '") title=\"' + "Show device locations information" + '\">' + "Location" + '</a>&nbsp;';
3565 - if (((meshrights & 8) != 0) && (mesh.mtype == 2)) x += '<a href=# onclick=p10showMeshCmdDialog(1,"' + node._id + '") title=\"' + "Traffic router used to connect to a device thru this server" + '.\">' + "Router" + '</a>&nbsp;';
3566 -
3567 - // RDP link, show this link only of the remote machine is Windows.
3568 - if (((connectivity & 1) != 0) && (clickOnce == true) && (mesh.mtype == 2) && ((meshrights & 8) != 0)) {
3569 - if ((node.agent.id > 0) && (node.agent.id < 5)) { x += '<a href=# onclick=p10clickOnce("' + node._id + '","RDP2",3389) title=\"' + "Requires Microsoft ClickOnce support in your browser" + '.\">' + "RDP" + '</a>&nbsp;'; }
3570 - if (node.agent.id > 4) {
3571 - x += '<a href=# onclick=p10clickOnce("' + node._id + '","PSSH",22) title=\"' + "Requires Microsoft ClickOnce support in your browser." + '\">' + "Putty" + '</a>&nbsp;';
3572 - x += '<a href=# onclick=p10clickOnce("' + node._id + '","WSCP",22) title=\"' + "Requires Microsoft ClickOnce support in your browser." + '\">' + "WinSCP" + '</a>&nbsp;';
3573 - }
3574 - }
3575 -
3576 - // MQTT options
3577 - if ((meshrights == 0xFFFFFFFF) && (features & 0x00400000)) { x += '<a href=# onclick=p10showMqttLoginDialog("' + node._id + '") title=\"' + "Get MQTT login credentials for this device." + '\">' + "MQTT Login" + '</a>&nbsp;'; }
3578 - x += '</div><br>'
3579 -
3580 - QH('p10html3', x);
3581 -
3582 - // Set the node power state
3583 - var powerstate = PowerStateStr(node.state);
3584 - //if (node.state == 0) { powerstate = 'Unknown State'; }
3585 - if ((connectivity & 1) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "Agent connected" + '\">' + "Agent connected" + '</span>'; }
3586 - if ((connectivity & 2) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "Intel&reg; AMT connected" + '\">' + "Intel&reg; AMT connected" + '</span>'; }
3587 - else if ((connectivity & 4) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "Intel&reg; AMT detected" + '\">' + "Intel&reg; AMT detected" + '</span>'; }
3588 - if ((connectivity & 16) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "MQTT connected" + '\">' + "MQTT channel connected" + '</span>'; }
3589 - if ((powerstate == '') && node.lastconnect) { powerstate = '<span style=font-size:12px>' + "Last seen:" + '<br />' + printDateTime(new Date(node.lastconnect)) + '</span>'; }
3590 - QH('MainComputerState', powerstate);
3591 -
3592 - // Set the node icon
3593 - Q('MainComputerImage').setAttribute('src', 'images/icons256-' + node.icon + '-1.png');
3594 - Q('MainComputerImage').className = ((!node.conn) || (node.conn == 0)?'gray':'');
3595 -
3596 - // Check if we have terminal and file access
3597 - var terminalAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 512) == 0));
3598 - var fileAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 1024) == 0));
3599 - var amtAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 2048) == 0));
3600 -
3601 - // Setup/Refresh the desktop tab
3602 - if (terminalAccess) { setupTerminal(); }
3603 - if (fileAccess) { setupFiles(); }
3604 - var consoleRights = ((meshrights & 16) != 0);
3605 - if (consoleRights) { setupConsole(); } else { if (panel == 15) { panel = 10; } }
3606 -
3607 - // Show or hide the tabs
3608 - // mesh.mtype: 1 = Intel AMT only, 2 = Mesh Agent
3609 - // node.agent.caps (bitmask): 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console
3610 - QV('MainDevDesktop', (((mesh.mtype == 1) && ((typeof node.intelamt.sku !== 'number') || ((node.intelamt.sku & 8) != 0)))
3611 - || ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0) || (node.intelamt && (node.intelamt.state == 2)))))
3612 - && ((meshrights & 8) || (meshrights & 256))
3613 - );
3614 - QV('MainDevTerminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0) || (node.intelamt && (node.intelamt.state == 2))) && (meshrights & 8) && terminalAccess);
3615 - QV('MainDevFiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8) && fileAccess);
3616 - QV('MainDevAmt', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8) && amtAccess);
3617 - QV('MainDevConsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8));
3618 - QV('MainDevPlugins', false);
3619 - QV('p15uploadCore', (node.agent != null) && (node.agent.caps != null) && ((node.agent.caps & 16) != 0));
3620 - QH('p15coreName', ((node.agent != null) && (node.agent.core != null))?node.agent.core:'');
3621 -
3622 - // Setup/Refresh Intel AMT tab
3623 - var amtFrameNode = Q('p14iframe').contentWindow.getCurrentMeshNode();
3624 - if ((amtFrameNode != null) && (amtFrameNode._id != currentNode._id)) { Q('p14iframe').contentWindow.disconnect(); }
3625 - var online = ((node.conn & 6) != 0)?true:false; // If CIRA (2) or AMT (4) connected, enable Commander
3626 - Q('p14iframe').contentWindow.setConnectionState(online);
3627 - Q('p14iframe').contentWindow.setFrameHeight('650px');
3628 - Q('p14iframe').contentWindow.setAuthCallback(updateAmtCredentials);
3629 -
3630 - // Display "action" button on desktop/terminal/files
3631 - QV('deskActionsBtn', (meshrights & 72) != 0); // 72 = Wake-up + Remote Control permissions
3632 - QV('termActionsBtn', (meshrights & 72) != 0);
3633 - QV('filesActionsBtn', (meshrights & 72) != 0);
3634 -
3635 - // Request the power timeline
3636 - if ((powerTimelineNode != currentNode._id) && (powerTimelineReq != currentNode._id)) {
3637 - QH('p10html2', '');
3638 - powerTimelineReq = currentNode._id;
3639 - meshserver.send({ action: 'powertimeline', nodeid: currentNode._id });
3640 - meshserver.send({ action: 'lastconnect', nodeid: currentNode._id });
3641 - meshserver.send({ action: 'getsysinfo', nodeid: currentNode._id });
3642 - QH('p17info', '');
3643 - }
3644 -
3645 - // Reset the desktop tools
3646 - QV('DeskTools', false);
3647 - showDeskToolsProcesses();
3648 -
3649 - // Ask for device events
3650 - refreshDeviceEvents();
3651 -
3652 - // Update the web page title
3653 - if ((currentNode) && (xxcurrentView >= 10) && (xxcurrentView < 20)) {
3654 - document.title = decodeURIComponent('{{{extitle}}}') + ' - ' + currentNode.name + ' - ' + mesh.name;
3655 - } else {
3656 - document.title = decodeURIComponent('{{{extitle}}}');
3657 - }
3658 -
3659 - // Clear user consent status if present
3660 - p11clearConsoleMsg();
3661 - p12clearConsoleMsg();
3662 - p13clearConsoleMsg();
3663 -
3664 - // Device refresh plugin handler
3665 - if (pluginHandler != null) {
3666 - QH('p19headers', ''); QH('p19pages', '');
3667 - pluginHandler.callHook('onDeviceRefreshEnd', nodeid, panel, refresh, event);
3668 - var lastTab = getstore('_curPluginPage', null);
3669 - if (lastTab != null && Q('p19ph-' + lastTab) != null) pluginHandler.callPluginPage(lastTab, Q('p19ph-' + lastTab));
3670 - }
3671 - }
3672 - setupDesktop(); // Always refresh the desktop, even if we are on the same device, we need to do some canvas switching.
3673 - if (!panel) panel = 10;
3674 - go(panel);
3675 - }
3676 -
3677 - function writeDeviceEvent(nodeid) {
3678 - if (xxdialogMode) return;
3679 - setDialogMode(2, "Add Device Event", 3, writeDeviceEventEx, '<textarea id=d2devEvent style=background-color:#fcf3cf;width:100%;height:200px;resize:none;overflow-y:scroll></textarea><span style=font-size:10px>' + "This will add an entry to this device\'s event log." + '<span>', nodeid);
3680 - }
3681 -
3682 - function writeDeviceEventEx(buttons, tag) { meshserver.send({ action: 'setDeviceEvent', nodeid: decodeURIComponent(tag), msg: encodeURIComponent(Q('d2devEvent').value) }); }
3683 -
3684 - function showNotes(readonly, noteid) {
3685 - if (xxdialogMode) return;
3686 - setDialogMode(2, "Notes", 2, showNotesEx, '<textarea id=d2devNotes ro=' + readonly + ' noteid=' + noteid + ' readonly style=background-color:#fcf3cf;width:100%;height:200px;resize:none;overflow-y:scroll></textarea><span style=font-size:10px>' + "Device group notes can be viewed and changed by other device group administrators." + '<span>', noteid);
3687 - meshserver.send({ action: 'getNotes', id: decodeURIComponent(noteid) });
3688 - }
3689 -
3690 - function showNotesEx(buttons, tag) { meshserver.send({ action: 'setNotes', id: decodeURIComponent(tag), notes: encodeURIComponent(Q('d2devNotes').value) }); }
3691 -
3692 - function deviceChat(e) {
3693 - if (xxdialogMode) return;
3694 - var url = '/messenger?id=meshmessenger/' + encodeURIComponent(currentNode._id) + '/' + encodeURIComponent(userinfo._id) + '&title=' + currentNode.name;
3695 - if ((authCookie != null) && (authCookie != '')) { url += '&auth=' + authCookie; }
3696 - if (e && (e.shiftKey == true)) {
3697 - window.open(url, 'meshmessenger:' + currentNode._id);
3698 - } else {
3699 - window.open(url, 'meshmessenger:' + currentNode._id, 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,width=400,height=560');
3700 - }
3701 - meshserver.send({ action: 'meshmessenger', nodeid: decodeURIComponent(currentNode._id) });
3702 - }
3703 -
3704 - function deviceToggleBackground() {
3705 - if (xxdialogMode) return;
3706 - meshserver.send({ action: 'msg', type: 'deskBackground', nodeid: currentNode._id, op: 1 }); // Toggle desktop background image
3707 - }
3708 -
3709 - function deviceUrlFunction() {
3710 - if (xxdialogMode) return;
3711 - setDialogMode(2, "Open Page on Device", 3, deviceUrlFunctionEx, '<input id=d2devurl placeholder="http://server.com" style=width:100%;overflow-y:scroll></input>');
3712 - Q('d2devurl').focus();
3713 - }
3714 -
3715 - function deviceUrlFunctionEx() {
3716 - meshserver.send({ action: 'msg', type: 'openUrl', nodeid: currentNode._id, url: Q('d2devurl').value });
3717 - }
3718 -
3719 - function deviceToastFunction() {
3720 - if (xxdialogMode) return;
3721 - setDialogMode(2, "Device Notification", 3, deviceToastFunctionEx, '<textarea id=d2devToast style=width:100%;height:80px;resize:none;overflow-y:scroll></textarea>');
3722 - Q('d2devToast').focus();
3723 - }
3724 -
3725 - function deviceToastFunctionEx() {
3726 - meshserver.send({ action: 'toast', nodeids: [ currentNode._id ], title: 'MeshCentral', msg: Q('d2devToast').value });
3727 - }
3728 -
3729 - function deviceActionFunction() {
3730 - if (xxdialogMode) return;
3731 - var meshrights = meshes[currentNode.meshid].links[userinfo._id].rights;
3732 - var x = "Select an operation to perform on this device." + '<br /><br />';
3733 - var y = '<select id=d2deviceop style=float:right;width:250px>';
3734 - if ((meshrights & 64) != 0) { y += '<option value=100>' + "Wake-up" + '</option>'; } // Wake-up permission
3735 - if ((meshrights & 8) != 0) { y += '<option value=4>' + "Sleep" + '</option><option value=3>' + "Reset" + '</option><option value=2>' + "Power off" + '</option>'; } // Remote control permission
3736 - if ((currentNode.conn & 16) != 0) { y += '<option value=103>' + "Send MQTT Message" + '</option>'; }
3737 - if (((currentNode.conn & 1) != 0) && ((meshrights & 32768) != 0)) { y += '<option value=104>' + "Uninstall Agent" + '</option>'; }
3738 - y += '</select>';
3739 - x += addHtmlValue("Operation", y);
3740 - setDialogMode(2, "Device Action", 3, deviceActionFunctionEx, x);
3741 - }
3742 -
3743 - function deviceActionFunctionEx() {
3744 - var op = Q('d2deviceop').value;
3745 - if (op == 100) {
3746 - // Device wake
3747 - meshserver.send({ action: 'wakedevices', nodeids: [currentNode._id] });
3748 - } else if (op == 103) {
3749 - // Send MQTT Message
3750 - p10showSendMqttMsgDialog([currentNode._id]);
3751 - } else if (op == 104) {
3752 - // Uninstall agent
3753 - p10showSendUninstallAgentDialog([currentNode._id]);
3754 - } else {
3755 - // Power operation
3756 - meshserver.send({ action: 'poweraction', nodeids: [ currentNode._id ], actiontype: parseInt(op) });
3757 - }
3758 - }
3759 -
3760 - // Called when MeshCommander needs new credentials or updated credentials.
3761 - function updateAmtCredentials(forceDialog) {
3762 - var node = getNodeFromId(currentNode._id);
3763 - if ((forceDialog == true) || (node.intelamt.user == null) || (node.intelamt.user == '')) {
3764 - editDeviceAmtSettings(currentNode._id, updateAmtCredentialsEx);
3765 - } else {
3766 - Q('p14iframe').contentWindow.connectButtonfunctionEx();
3767 - }
3768 - }
3769 -
3770 - function updateAmtCredentialsEx(button, tag) {
3771 - Q('p14iframe').contentWindow.connectButtonfunctionEx();
3772 - }
3773 -
3774 - // Look to see if we need to update the device timeline
3775 - function updateDeviceTimeline() {
3776 - if ((meshserver.State != 2) || (powerTimelineNode == null) || (powerTimelineUpdate == null) || (currentNode == null)) return;
3777 - if ((powerTimelineNode == powerTimelineReq) && (currentNode._id == powerTimelineNode) && (powerTimelineUpdate < Date.now())) {
3778 - powerTimelineUpdate = null;
3779 - meshserver.send({ action: 'powertimeline', nodeid: currentNode._id });
3780 - meshserver.send({ action: 'lastconnect', nodeid: currentNode._id });
3781 - }
3782 - }
3783 -
3784 - // Draw device power bars. The bars are 766px wide.
3785 - function drawDeviceTimeline() {
3786 - if ((currentNode == null) || (xxcurrentView < 10) || (xxcurrentView > 19)) return;
3787 - var timeline = null, now = Date.now();
3788 - if (currentNode._id == powerTimelineNode) { timeline = powerTimeline; }
3789 -
3790 - // Calculate when the timeline starts
3791 - var d = new Date();
3792 - d.setHours(0, 0, 0, 0);
3793 - d = new Date(d.getTime() - (1000 * 60 * 60 * 24 * 6));
3794 - var timelineStart = d.getTime();
3795 -
3796 - // De-compact the timeline
3797 - var timeline2 = [];
3798 - if (timeline != null && timeline.length > 1) {
3799 - timeline2.push([ 0, timeline[1], timeline[0] ]); // Start, End, Power
3800 - var ct = timeline[1];
3801 - for (var i = 2; i < timeline.length; i += 2) {
3802 - var power = timeline[i], dt = now;
3803 - if (timeline.length > (i + 1)) { dt = timeline[i + 1]; }
3804 - timeline2.push([ ct, ct + dt, power ]); // Start, End, Power
3805 - ct = ct + dt;
3806 - }
3807 - }
3808 -
3809 - // Draw the timeline
3810 - var x = '', count = 1, date = new Date();
3811 - var totalWidth = Q('masthead').offsetWidth - (160 + 9 + 9 + 14); // Compute the total width of the power bar
3812 - date.setHours(0, 0, 0, 0);
3813 - for (var i = 0; i < 7; i++) {
3814 - var datavalue = '', start = date.getTime(), end = start + (1000 * 60 * 60 * 24);
3815 - for (var j in timeline2) {
3816 - var block = timeline2[j];
3817 - if (isTimeBlockInside(start, end, block[0], block[1]) == true) {
3818 - var ts = Math.max(start, block[0]);
3819 - var te = Math.min(Math.min(end, block[1]), now);
3820 - var width = Math.round(((te - ts) * totalWidth) / 86400000);
3821 - if (width > 0) {
3822 - var title = format('{0} from {1} to {2}.', powerStateStrings2[block[2]], printTime(new Date(ts)), printTime(new Date(te)));
3823 - datavalue += '<div class="pwState ' + powerColor(block[2]) + '" title="' + title + '" style="width:' + width + 'px;"></div>';
3824 - }
3825 - }
3826 - }
3827 - x += '<tr class=' + (((count % 2) == 0)?'altBack':'') + '><td><div>&nbsp;' + printDate(date) + '<div></div></div></td><td><div>' + datavalue + '</div></td></tr>';
3828 - ++count;
3829 - date = new Date(date.getTime() - (1000 * 60 * 60 * 24)); // Substract one day
3830 - }
3831 - QH('p10html2', '<table cellpadding=2 cellspacing=0><thead><tr style=><th scope=col style=text-align:center;width:150px>' + "Day" + '</th><th scope=col style=text-align:center><a download href="devicepowerevents.ashx?id=' + currentNode._id + '" onclick="setDialogMode(0)"><img title=\"' + "Download power events" + '\" src="images/link4.png" /></a>' + "7 Day Power State" + '</th></tr></thead><tbody>' + x + '</tbody></table>');
3832 - }
3833 -
3834 - // Return a color for the given power state
3835 - function powerColor(x) { if (x < powerColorTable.length) { return powerColorTable[x]; } return 'pwsYellow'; }
3836 -
3837 - // Return true if the time block is visible within the start/end period
3838 - function isTimeBlockInside(start, end, blockStart, blockEnd) {
3839 - if ((blockStart < start) && (blockEnd > end)) return true; // Block is wider than timespan
3840 - if ((blockStart > start) && (blockStart < end)) return true;
3841 - if ((blockEnd > start) && (blockEnd < end)) return true;
3842 - return false;
3843 - }
3844 -
3845 - function addDeviceAttribute(name, value) { return '<tr><td class=style7>' + name + '</td><td class=style9>' + value + '</td></tr>'; }
3846 -
3847 - function editDeviceAmtSettings(nodeid, func, arg) {
3848 - if (xxdialogMode) return;
3849 - var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid);
3850 - if ((meshrights & 4) == 0) return;
3851 - x += addHtmlValue("Username", '<input id=dp10username style=width:230px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
3852 - x += addHtmlValue("Password", '<input id=dp10password type=password style=width:230px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
3853 - x += addHtmlValue("Security", '<select id=dp10tls style=width:236px><option value=0>' + "No TLS security" + '</option><option value=1>' + "TLS security required" + '</option></select>');
3854 - if ((node.intelamt.user != null) && (node.intelamt.user != '')) { buttons = 7; }
3855 - setDialogMode(2, "Edit Intel&reg; AMT credentials", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func, arg: arg });
3856 - if ((node.intelamt.user != null) && (node.intelamt.user != '')) { Q('dp10username').value = node.intelamt.user; } else { Q('dp10username').value = 'admin'; }
3857 - Q('dp10tls').value = node.intelamt.tls;
3858 - validateDeviceAmtSettings();
3859 - }
3860 -
3861 - function validateDeviceAmtSettings() {
3862 - QE('idx_dlgOkButton', passwordcheck(Q('dp10password').value));
3863 - }
3864 -
3865 - function editDeviceAmtSettingsEx(button, tag) {
3866 - if (button == 2) {
3867 - // Delete button pressed, remove credentials
3868 - meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: '', pass: '' } });
3869 - } else {
3870 - // Change Intel AMT credentials
3871 - var amtuser = Q('dp10username').value;
3872 - if (amtuser == '') amtuser = 'admin';
3873 - var amtpass = Q('dp10password').value;
3874 - if (amtpass == '') amtuser = '';
3875 - meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: amtuser, pass: amtpass, tls: Q('dp10tls').value } });
3876 - tag.node.intelamt.user = amtuser;
3877 - tag.node.intelamt.tls = Q('dp10tls').value;
3878 - if (tag.func) { setTimeout(function () { tag.func(null, tag.arg); }, 300); }
3879 - }
3880 - }
3881 -
3882 - function p10showSendMqttMsgDialog(nodeids) {
3883 - if (xxdialogMode) return false;
3884 - var x = addHtmlValue("Topic", '<input id=dp2topic style=width:230px maxlength=64 onchange=p10validateSendMqttMsgDialog() onkeyup=p10validateSendMqttMsgDialog(event,1) />');
3885 - x += addHtmlValue("Message", '<div style=width:230px;margin:0;padding:0><textarea id=dp2msg maxlength=4096 style=width:100%;height:150px;resize:none onchange=p10validateSendMqttMsgDialog() onkeyup=p10validateSendMqttMsgDialog(event,1)></textarea></div>');
3886 - setDialogMode(2, "Send MQTT message", 3, p10showSendMqttMsgDialogEx, x, nodeids);
3887 - p10validateSendMqttMsgDialog();
3888 - Q('dp2topic').focus();
3889 - return false;
3890 - }
3891 -
3892 - function p10validateSendMqttMsgDialog() {
3893 - QE('idx_dlgOkButton', (Q('dp2topic').value.length > 0) && (Q('dp2msg').value.length > 0));
3894 - }
3895 -
3896 - function p10showSendMqttMsgDialogEx(b, nodeids) {
3897 - meshserver.send({ action: 'sendmqttmsg', nodeids: nodeids, topic: Q('dp2topic').value, msg: Q('dp2msg').value });
3898 - }
3899 -
3900 - function p10showSendUninstallAgentDialog(nodeids) {
3901 - if (xxdialogMode) return false;
3902 - var x = '';
3903 - if (nodeids.length > 1) { x = format("Are you sure you want to uninstall the selected {0} agents?", nodeids.length); } else { x = "Are you sure you want to uninstall selected agent?"; }
3904 - x += '<br /><br />';
3905 - if (nodeids.length > 1) { x += "This will not remove the devices from the server, but the devices will not longer be able to connect to the server. All remote access to the devices will be lost. The devices must be connected for this command to work."; } else { x += "This will not remove this device from the server, but the device will not longer be able to connect to the server. All remote access to the device will be lost. The device must be connect for this command to work."; }
3906 - x += '<br /><br /><label style=color:red><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "Confirm" + '</label>';
3907 - setDialogMode(2, "Uninstall agent", 3, p10showSendUninstallAgentDialogEx, x, nodeids);
3908 - p10validateSendUninstallAgentDialog();
3909 - return false;
3910 - }
3911 -
3912 - function p10validateSendUninstallAgentDialog() { QE('idx_dlgOkButton', Q('p10check').checked); }
3913 - function p10showSendUninstallAgentDialogEx(b, nodeids) { meshserver.send({ action: 'uninstallagent', nodeids: nodeids }); }
3914 -
3915 - function p10showChangeGroupDialog(nodeids) {
3916 - if (xxdialogMode) return false;
3917 - var targetMeshId = null;
3918 - if (nodeids.length == 1) { try { targetMeshId = meshes[getNodeFromId(nodeids[0])]._id; } catch (ex) { } }
3919 -
3920 - // List all available alternative groups
3921 - var y = '<select id=p10newGroup style=width:236px>', count = 0;
3922 - for (var i in meshes) {
3923 - var meshrights = meshes[i].links[userinfo._id].rights;
3924 - if ((meshes[i]._id != targetMeshId) && (meshrights & 4)) { count++; y += '<option value=\'' + meshes[i]._id + '\'>' + meshes[i].name + '</option>'; }
3925 - }
3926 - y += '</select>';
3927 -
3928 - if (count > 0) {
3929 - var x = (nodeids.length == 1) ? ("Select a new group for this device" + '<br /><br />') : ("Select a new group for selected devices" + '<br /><br />');
3930 - x += addHtmlValue("New Device Group", y);
3931 - setDialogMode(2, "Change Group", 3, p10showChangeGroupDialogEx, x, nodeids);
3932 - } else {
3933 - setDialogMode(2, "Change Group", 1, null, "No other device group of same type exists.");
3934 - }
3935 - return false;
3936 - }
3937 -
3938 - function p10showChangeGroupDialogEx(b, nodeids) {
3939 - meshserver.send({ action: 'changeDeviceMesh', nodeids: nodeids, meshid: Q('p10newGroup').value });
3940 - }
3941 -
3942 - function p10showDeleteNodeDialog(nodeid) {
3943 - if (xxdialogMode) return false;
3944 - 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>';
3945 - setDialogMode(2, "Delete Node", 3, p10showDeleteNodeDialogEx, x, nodeid);
3946 - p10validateDeleteNodeDialog();
3947 - return false;
3948 - }
3949 -
3950 - function p10validateDeleteNodeDialog() {
3951 - QE('idx_dlgOkButton', Q('p10check').checked);
3952 - }
3953 -
3954 - function p10showDeleteNodeDialogEx(buttons, nodeid) {
3955 - meshserver.send({ action: 'removedevices', nodeids: [ nodeid ] });
3956 - }
3957 -
3958 - function p10clickOnce(nodeid, protocol, port) {
3959 - meshserver.send({ action: 'getcookie', nodeid: nodeid, tcpport: port, tag: 'clickonce', protocol: protocol });
3960 - return false;
3961 - }
3962 -
3963 - // Show current location
3964 - var d2map = null;
3965 - function p10showNodeLocationDialog() {
3966 - if ((xxdialogMode != null) && (xxdialogTag == '@xxmap')) { setDialogMode(0); } else { if (xxdialogMode) return false; }
3967 - var markers = [], types = ['iploc', 'wifiloc', 'gpsloc', 'userloc'], boundingBox = null;
3968 -
3969 - for (var loctype in types) {
3970 - if (currentNode[types[loctype]] != null) {
3971 - var loc = currentNode[types[loctype]].split(','), lat = parseFloat(loc[0]), lon = parseFloat(loc[1]);
3972 - if ((lat < 90) && (lat > -90) && (lon < 180) && (lon > -180)) { // Check valid lat/lon
3973 - var deviceMark = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.fromLonLat([lon, lat])) });
3974 - deviceMark.setStyle(markerStyle(currentNode, parseInt(loctype) + 1));
3975 - markers.push(deviceMark);
3976 -
3977 - if (boundingBox == null) { boundingBox = [ lat, lon, lat, lon, 0 ]; } else { if (lat < boundingBox[0]) { boundingBox[0] = lat; } if (lon < boundingBox[1]) { boundingBox[1] = lon; } if (lat > boundingBox[2]) { boundingBox[2] = lat; } if (lon > boundingBox[3]) { boundingBox[3] = lon; } }
3978 - }
3979 - }
3980 - }
3981 -
3982 - // Setup the device mark layer
3983 - var vectorSource = new ol.source.Vector({ features: markers });
3984 - var vectorLayer = new ol.layer.Vector({ source: vectorSource });
3985 -
3986 - //var x = '<div><a href="https://www.google.com/maps/preview/@' + lat + ',' + lng + ',12z" rel="noreferrer noopener" target=_blank>Open in Google maps</a></div>';
3987 - var x = '<div id=d2map style=width:100%;height:300px></div>';
3988 - setDialogMode(2, "Device Location", 1, null, x, '@xxmap');
3989 -
3990 - var clng = 0, clat = 0, zoom = 8;
3991 - if (boundingBox != null) {
3992 - var clat = (boundingBox[0] + boundingBox[2]) / 2;
3993 - var clng = (boundingBox[1] + boundingBox[3]) / 2;
3994 - var cscale = Math.max(Math.abs(boundingBox[0] - boundingBox[2]), Math.abs(boundingBox[1] - boundingBox[3]));
3995 - var i = 360, zoom = -2;
3996 - while (i > cscale) { zoom++; i = i / 2; }
3997 - }
3998 -
3999 - if (markers.length == 1) { zoom = 8; }
4000 -
4001 - // Setup the map
4002 - d2map = new ol.Map({
4003 - target: 'd2map',
4004 - interactions: ol.interaction.defaults({dragPan:false, mouseWheelZoom:false}),
4005 - layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), vectorLayer ],
4006 - view: new ol.View({ center: ol.proj.fromLonLat([clng, clat]), zoom: zoom })
4007 - });
4008 - return false;
4009 - }
4010 -
4011 - // Show network interfaces
4012 - function p10showNodeNetInfoDialog() {
4013 - if (xxdialogMode) return false;
4014 - setDialogMode(2, "Network Interfaces", 1, null, '<div id=d2netinfo>' + "Loading..." + '</div>', 'if' + currentNode._id );
4015 - meshserver.send({ action: 'getnetworkinfo', nodeid: currentNode._id });
4016 - return false;
4017 - }
4018 -
4019 - // Show MeshCentral Router dialog
4020 - function p10showMeshRouterDialog() {
4021 - if (xxdialogMode) return;
4022 - var x = '<div>' + "MeshCentral Router is a Windows tool for TCP port mapping. You can, for example, RDP into a remote device thru this server." + '</div><br />';
4023 - x += addHtmlValue('Win32 Executable', '<a style=cursor:pointer download href="meshagents?meshaction=winrouter" onclick="setDialogMode(0)">MeshCentralRouter.exe</a>');
4024 - setDialogMode(2, "MeshCentral Router", 1, null, x, 'fileDownload');
4025 - }
4026 -
4027 - // Request MQTT login credentials
4028 - function p10showMqttLoginDialog(nodeid) { meshserver.send({ action: 'getmqttlogin', nodeid: nodeid }); }
4029 -
4030 - // Show MeshCmd dialog
4031 - function p10showMeshCmdDialog(mode, nodeid) {
4032 - if (xxdialogMode) return;
4033 - var y = '<select id=aginsSelect onclick=meshCmdOsClick() style=width:236px>';
4034 - y += '<option value=3>' + "Windows (32bit)" + '</option>';
4035 - y += '<option value=4>' + "Windows (64bit)" + '</option>';
4036 - y += '<option value=5>' + "Linux x86 (32bit)" + '</option>';
4037 - y += '<option value=6>' + "Linux x86 (64bit)" + '</option>';
4038 - y += '<option value=16>' + "MacOS (64bit)" + '</option>';
4039 - y += '<option value=25>' + "Linux ARM, Raspberry Pi (32bit)" + '</option>';
4040 - y += '</select>';
4041 -
4042 - var x = '';
4043 - if (mode == 0) { x += '<div>MeshCmd is a command line tool that performs lots of different operations. The action file can optionally be downloaded and edited to provide server information and credentials.<br /><br />'; }
4044 - if (mode == 1) { x += '<div>Download "meshcmd" with an action file to route traffic thru this server to this device. Make sure to edit meshaction.txt and add your account password or make any changes needed.<br /><br />'; }
4045 - x += addHtmlValue('Operating System', y);
4046 - x += addHtmlValue('MeshCmd', '<a id=meshcmddownloadid href="meshagents?meshcmd=3" download></a>');
4047 - if (mode == 0) { x += addHtmlValue('Action File', '<a href="meshagents?meshaction=generic" download>MeshAction (.txt)</a>'); }
4048 - if (mode == 1) { x += addHtmlValue('Action File', '<a href="meshagents?meshaction=route&nodeid=' + nodeid + '" download>MeshAction (.txt)</a>'); }
4049 - x += '</div>';
4050 - setDialogMode(2, [ "Download MeshCmd", "Network Router" ][mode], 9, null, x, 'fileDownload');
4051 - meshCmdOsClick();
4052 - }
4053 -
4054 - function meshCmdOsClick() {
4055 - var os = Q('aginsSelect').value, osn = '', osurl = '';
4056 - //Q('meshcmddownloadid').href = 'meshagents?meshcmd=' + os;
4057 - if (os == 3) { osn = 'MeshCmd (Win32 executable)'; }
4058 - if (os == 4) { osn = 'MeshCmd (Win64 executable)'; }
4059 - if (os == 5) { osn = 'MeshCmd (Linux x86, 32bit)'; }
4060 - if (os == 6) { osn = 'MeshCmd (Linux x86, 64bit)'; }
4061 - if (os == 16) { osn = 'MeshCmd (MacOS, 64bit)'; }
4062 - if (os == 25) { osn = 'MeshCmd (Linux ARM, 32bit)'; }
4063 - QH('meshcmddownloadid', osn);
4064 - Q('meshcmddownloadid').setAttribute('href', 'meshagents?meshcmd=' + os);
4065 - }
4066 -
4067 - function p10showiconselector() {
4068 - if (xxdialogMode) return;
4069 - var mesh = meshes[currentNode.meshid];
4070 - var meshrights = mesh.links[userinfo._id].rights;
4071 - if ((meshrights & 4) == 0) return;
4072 -
4073 - var x = '<br><div style=display:inline-block;width:40px></div>';
4074 - x += '<div tabindex=0 style=display:inline-block class=i1 onclick=p10setIcon(1) onkeypress="if (event.key==\'Enter\') p10setIcon(1)"></div>';
4075 - x += '<div tabindex=0 style=display:inline-block class=i2 onclick=p10setIcon(2) onkeypress="if (event.key==\'Enter\') p10setIcon(2)"></div>';
4076 - x += '<div tabindex=0 style=display:inline-block class=i3 onclick=p10setIcon(3) onkeypress="if (event.key==\'Enter\') p10setIcon(3)"></div>';
4077 - x += '<div tabindex=0 style=display:inline-block class=i4 onclick=p10setIcon(4) onkeypress="if (event.key==\'Enter\') p10setIcon(4)"></div>';
4078 - x += '<div tabindex=0 style=display:inline-block class=i5 onclick=p10setIcon(5) onkeypress="if (event.key==\'Enter\') p10setIcon(5)"></div>';
4079 - x += '<div tabindex=0 style=display:inline-block class=i6 onclick=p10setIcon(6) onkeypress="if (event.key==\'Enter\') p10setIcon(6)"></div><br><br>';
4080 - setDialogMode(2, "Icon Selection", 0, null, x);
4081 - QV('id_dialogclose', true);
4082 - }
4083 -
4084 - function p10setIcon(icon) {
4085 - setDialogMode(0);
4086 - meshserver.send({ action: 'changedevice', nodeid: currentNode._id, icon: icon });
4087 - }
4088 -
4089 - var showEditNodeValueDialog_modes = ["Device Name", "Hostname", "Description", "Tags"];
4090 - var showEditNodeValueDialog_modes2 = ['name', 'host', 'desc', 'tags'];
4091 - var showEditNodeValueDialog_modes3 = ['', '', '', "Tag1, Tag2, Tag3"];
4092 - function showEditNodeValueDialog(mode) {
4093 - if (xxdialogMode) return;
4094 - var x = addHtmlValue(showEditNodeValueDialog_modes[mode], '<input id=dp10devicevalue maxlength=64 placeholder="' + showEditNodeValueDialog_modes3[mode] + '" onchange=p10editdevicevalueValidate(' + mode + ',event) onkeyup=p10editdevicevalueValidate(' + mode + ',event) />');
4095 - setDialogMode(2, "Edit Device", 3, showEditNodeValueDialogEx, x, mode);
4096 - var v = currentNode[showEditNodeValueDialog_modes2[mode]];
4097 - if (v == null) v = '';
4098 - if (Array.isArray(v)) { v = v.join(', '); }
4099 - Q('dp10devicevalue').value = v;
4100 - p10editdevicevalueValidate();
4101 - Q('dp10devicevalue').focus();
4102 - }
4103 -
4104 - function showEditNodeValueDialogEx(button, mode) {
4105 - var x = { action: 'changedevice', nodeid: currentNode._id };
4106 - x[showEditNodeValueDialog_modes2[mode]] = Q('dp10devicevalue').value;
4107 - meshserver.send(x);
4108 - }
4109 -
4110 - function p10editdevicevalueValidate(mode, e) {
4111 - var x = ((mode > 1) || (Q('dp10devicevalue').value.length > 0));
4112 - QE('idx_dlgOkButton', x);
4113 - if ((e != null) && (x == true) && (e.keyCode == 13)) { dialogclose(1); }
4114 - }
4115 -
4116 - //
4117 - // DESKTOP
4118 - //
4119 -
4120 - var desktopNode;
4121 - function setupDesktop() {
4122 - // Setup the remote desktop
4123 - if ((desktopNode != currentNode) && (desktop != null)) { desktop.Stop(); desktopNode = null; desktop = null; }
4124 -
4125 - // If the device desktop is already connected in multi-desktop, use that.
4126 - if ((desktopNode != currentNode) || (desktop == null)) {
4127 - var xdesk = multiDesktop[currentNode._id];
4128 - if (xdesk != null) {
4129 - // This device already has a canvas, use it.
4130 - QH('DeskParent', '');
4131 - var c = xdesk.m.CanvasId;
4132 - c.setAttribute('id', 'Desk');
4133 - c.setAttribute('onmousedown', 'dmousedown(event)');
4134 - c.setAttribute('onmouseup', 'dmouseup(event)');
4135 - c.setAttribute('onmousemove', 'dmousemove(event)');
4136 - c.removeAttribute('onclick');
4137 - Q('DeskParent').appendChild(c);
4138 - desktop = xdesk;
4139 - if (desktop.m.SendCompressionLevel) { desktop.m.SendCompressionLevel(1, desktopsettings.quality, desktopsettings.scaling, desktopsettings.framerate); }
4140 - desktop.onStateChanged = onDesktopStateChange;
4141 - desktopNode = currentNode;
4142 - onDesktopStateChange(desktop, desktop.State);
4143 - delete multiDesktop[currentNode._id];
4144 - } else {
4145 - // Device is not already connected, just setup a blank canvas
4146 - QH('DeskParent', '<canvas id=Desk oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></canvas>');
4147 - desktopNode = currentNode;
4148 - }
4149 - // Setup the mouse wheel
4150 - Q('Desk').addEventListener('DOMMouseScroll', function (e) { return dmousewheel(e); });
4151 - Q('Desk').addEventListener('mousewheel', function (e) { return dmousewheel(e); });
4152 - }
4153 - desktopNode = currentNode;
4154 - updateDesktopButtons();
4155 - deskAdjust();
4156 -
4157 - // On some browsers like IE, we can't save screen shots. Hide the scheenshot/capture buttons.
4158 - if (!Q('Desk')['toBlob']) { QV('deskSaveBtn', false); }
4159 - }
4160 -
4161 - // Show and enable the right buttons
4162 - function updateDesktopButtons() {
4163 - var mesh = meshes[currentNode.meshid];
4164 - var deskState = 0;
4165 - if (desktop != null) { deskState = desktop.State; }
4166 - var meshrights = mesh.links[userinfo._id].rights;
4167 -
4168 - // Show the right buttons
4169 - QV('disconnectbutton1span', (deskState != 0));
4170 - QV('connectbutton1span', (deskState == 0) && ((meshrights & 8) || (meshrights & 256)) && (mesh.mtype == 2) && (currentNode.agent.caps & 1));
4171 - QV('connectbutton1hspan',
4172 - (deskState == 0) &&
4173 - (meshrights & 8) &&
4174 - ((mesh.mtype == 1) ||
4175 - ((currentNode.intelamt != null) &&
4176 - (currentNode.intelamt.state == 2) &&
4177 - (currentNode.intelamt.ver != null) &&
4178 - (typeof currentNode.intelamt.sku == 'number') &&
4179 - ((currentNode.intelamt.sku & 8) != 0))
4180 - )
4181 - );
4182 -
4183 - // Show the right settings
4184 - QV('d7amtkvm', (currentNode.intelamt != null && ((currentNode.intelamt.ver != null) || (mesh.mtype == 1))) && ((deskState == 0) || (desktop.contype == 2)));
4185 - QV('d7meshkvm', (webRtcDesktop) || ((mesh.mtype == 2) && (currentNode.agent.caps & 1) && ((deskState == false) || (desktop.contype == 1))));
4186 -
4187 - // Enable buttons
4188 - var inputAllowed = (meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) == 0));
4189 - var online = ((currentNode.conn & 1) != 0); // If Agent (1) connected, enable remote desktop
4190 - QE('connectbutton1', online);
4191 - var hwonline = ((currentNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal
4192 - QE('connectbutton1h', hwonline);
4193 - QE('deskSaveBtn', deskState == 3);
4194 - QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (deskState != 0) && (desktopsettings.showfocus));
4195 - QV('DeskClip', (currentNode.agent) && (currentNode.agent.id != 11) && (currentNode.agent.id != 16) && ((desktop == null) || (desktop.contype != 2))); // Clipboard not supported on MacOS
4196 - QE('DeskClip', deskState == 3);
4197 - QE('DeskType', deskState == 3);
4198 - QV('DeskWD', inputAllowed);
4199 - QE('DeskWD', deskState == 3);
4200 - QV('deskkeys', inputAllowed);
4201 - QE('deskkeys', deskState == 3);
4202 -
4203 - // Display this only if we have Chat & Notify permissions
4204 - QV('DeskChatButton', ((meshrights & 16384) != 0) && (browserfullscreen == false) && (inputAllowed) && (mesh.mtype == 2) && online);
4205 - QV('DeskNotifyButton', ((meshrights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && (currentNode.agent.id < 5) && (inputAllowed) && (mesh.mtype == 2) && online);
4206 -
4207 - QV('DeskToolsButton', (inputAllowed) && (mesh.mtype == 2) && online);
4208 - QV('DeskOpenWebButton', (browserfullscreen == false) && (inputAllowed) && (mesh.mtype == 2) && online);
4209 - QV('DeskBackgroundButton', (deskState == 3) && (desktop.contype == 1) && (mesh.mtype == 2) && (currentNode.agent.id != 11) && (currentNode.agent.id != 16) && online);
4210 - QV('DeskControlSpan', inputAllowed)
4211 - QV('deskActionsBtn', (browserfullscreen == false));
4212 - QV('deskActionsSettings', (browserfullscreen == false));
4213 - if (meshrights & 8) { Q('DeskControl').checked = (getstore('DeskControl', 1) == 1); } else { Q('DeskControl').checked = false; }
4214 - if (online == false) QV('DeskTools', false);
4215 - }
4216 -
4217 - // Debug
4218 - var autoConnectDesktopTimer = null;
4219 - function autoConnectDesktop(e) { if (autoConnectDesktopTimer == null) { autoConnectDesktopTimer = setInterval(function() { connectDesktop(null, 1) }, 1000); } else { clearInterval(autoConnectDesktopTimer); autoConnectDesktopTimer = null; } }
4220 -
4221 - function connectDesktop(e, contype, tsid) {
4222 - if (xxdialogMode) return;
4223 - if ((e != null) && (e.shiftKey == false) && (contype == 3)) { contype = 1; } // If the shift key is not pressed, don't try to ask for session list.
4224 - QV('p11DeskSessionSelector', false);
4225 - p11clearConsoleMsg();
4226 - if (desktop == null) {
4227 - desktopNode = currentNode;
4228 - if (contype == 2) {
4229 - // Setup the Intel AMT remote desktop
4230 - if ((desktopNode.intelamt.user == null) || (desktopNode.intelamt.user == '')) { editDeviceAmtSettings(desktopNode._id, connectDesktop, 2); return; }
4231 - desktop = CreateAmtRedirect(CreateAmtRemoteDesktop('Desk'), authCookie);
4232 - desktop.debugmode = debugmode;
4233 - desktop.onStateChanged = onDesktopStateChange;
4234 - desktop.m.bpp = (desktopsettings.encoding == 1 || desktopsettings.encoding == 3) ? 1 : 2;
4235 - desktop.m.useZRLE = (desktopsettings.encoding < 3);
4236 - desktop.m.localKeyMap = desktopsettings.localkeymap;
4237 - desktop.m.showmouse = desktopsettings.showmouse;
4238 - desktop.m.onScreenSizeChange = deskAdjust;
4239 - desktop.m.onKvmData = function (x) {
4240 - //console.log('onKvmData (' + x.length + '): ' + x);
4241 - // Send the presense probe only once if needed.
4242 - if (x.length == 0) { if (!desktop.m._sentPresence) { desktop.m._sentPresence = true; desktop.m.sendKvmData(JSON.stringify({ action: 'present', ver: 1 })); } return; }
4243 - var data = null;
4244 - try { data = JSON.parse(x); } catch (e) { }
4245 - if ((data != null) && (data.action != null)) {
4246 - if (data.action == 'restart') {
4247 - // Clear WebRTC channel
4248 - webRtcDesktopReset();
4249 - desktop.m.sendKvmData(JSON.stringify({ action: 'present', ver: 1 }));
4250 - } else if ((data.action == 'present') && (webRtcDesktop == null)) {
4251 - // Setup WebRTC channel
4252 - webRtcDesktop = { platform: data.platform };
4253 - var configuration = null; //{ "iceServers": [ { 'urls': 'stun:stun.services.mozilla.com' }, { 'urls': 'stun:stun.l.google.com:19302' } ] };
4254 - if (typeof RTCPeerConnection !== 'undefined') { webRtcDesktop.webrtc = new RTCPeerConnection(configuration); }
4255 - else if (typeof webkitRTCPeerConnection !== 'undefined') { webRtcDesktop.webrtc = new webkitRTCPeerConnection(configuration); }
4256 -
4257 - webRtcDesktop.webchannel = webRtcDesktop.webrtc.createDataChannel("DataChannel", {}); // { ordered: false, maxRetransmits: 2 }
4258 - webRtcDesktop.webchannel.onopen = function () {
4259 - // Switch to software KVM
4260 - //if (urlvars && urlvars['kvmdatatrace']) { console.log('WebRTC Data Channel Open'); }
4261 - console.log('WebRTC Data Channel Open');
4262 - Q('deskstatus').textContent = StatusStrs[desktop.State] + ", Soft-KVM";
4263 - desktop.m.hold(true);
4264 - webRtcDesktop.webRtcActive = true;
4265 - webRtcDesktop.softdesktop = CreateKvmDataChannel(webRtcDesktop.webchannel, CreateAgentRemoteDesktop('Desk', Q('id_mainarea')), desktop.m);
4266 - webRtcDesktop.softdesktop.m.setRotation(desktop.m.rotation);
4267 - webRtcDesktop.softdesktop.m.onScreenSizeChange = deskAdjust;
4268 - if (desktopsettings.quality) { webRtcDesktop.softdesktop.m.CompressionLevel = desktopsettings.quality; } // Number from 1 to 100. 50 or less is best.
4269 - if (desktopsettings.scaling) { webRtcDesktop.softdesktop.m.ScalingLevel = desktopsettings.scaling; }
4270 - webRtcDesktop.softdesktop.Start();
4271 -
4272 - // Check if we can get remote file access
4273 - // ###BEGIN###{DesktopInbandFiles}
4274 - /*
4275 - QV('go24', true); // Files
4276 - downloadFile = null;
4277 - p24files = webRtcDesktop.softdesktop;
4278 - p24targetpath = '';
4279 - webRtcDesktop.softdesktop.onControlMsg = onFilesControlData;
4280 - webRtcDesktop.softdesktop.sendCtrlMsg(JSON.stringify({ action: 'ls', reqid: 1, path: '' })); // Ask for the root folder
4281 - */
4282 - // ###END###{DesktopInbandFiles}
4283 - }
4284 - webRtcDesktop.webchannel.onclose = function (event) {
4285 - //if (urlvars['kvmdatatrace']) { console.log('WebRTC Data Channel Closed'); }
4286 - console.log('WebRTC Data Channel Closed');
4287 - webRtcDesktopReset();
4288 - }
4289 - webRtcDesktop.webrtc.onicecandidate = function (e) {
4290 - if (e.candidate == null) {
4291 - desktop.m.sendKvmData(JSON.stringify({ action: 'offer', ver: 1, sdp: webRtcDesktop.webrtcoffer.sdp }));
4292 - } else {
4293 - webRtcDesktop.webrtcoffer.sdp += ('a=' + e.candidate.candidate + '\r\n'); // New candidate, add it to the SDP
4294 - }
4295 - }
4296 - webRtcDesktop.webrtc.oniceconnectionstatechange = function () {
4297 - if ((webRtcDesktop != null) && (webRtcDesktop.webrtc != null) && ((webRtcDesktop.webrtc.iceConnectionState == 'disconnected') || (webRtcDesktop.webrtc.iceConnectionState == 'failed'))) { /*console.log('WebRTC ICE Failed');*/ webRtcDesktopReset(); }
4298 - }
4299 - webRtcDesktop.webrtc.createOffer(function (offer) {
4300 - // Got the offer
4301 - webRtcDesktop.webrtcoffer = offer;
4302 - webRtcDesktop.webrtc.setLocalDescription(offer, function () { }, webRtcDesktopReset);
4303 - }, webRtcDesktopReset, { mandatory: { OfferToReceiveAudio: false, OfferToReceiveVideo: false } });
4304 - } else if ((data.action == 'answer') && (webRtcDesktop != null)) {
4305 - // Complete the WebRTC channel
4306 - webRtcDesktop.webrtc.setRemoteDescription(new RTCSessionDescription({ type: 'answer', sdp: data.sdp }), function () { }, webRtcDesktopReset);
4307 - }
4308 - }
4309 - };
4310 - desktop.Start(desktopNode._id, 16994, '*', '*', 0);
4311 - desktop.contype = 2;
4312 - } else if ((contype == null) || (contype == 1) || ((contype == 3) && (currentNode.agent.id > 4))) {
4313 - // Setup the Mesh Agent remote desktop
4314 - desktop = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('Desk'), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
4315 - desktop.debugmode = debugmode;
4316 - desktop.m.debugmode = debugmode;
4317 - desktop.attemptWebRTC = attemptWebRTC;
4318 - if (tsid != null) { desktop.options = { tsid: tsid }; }
4319 - desktop.onStateChanged = onDesktopStateChange;
4320 - desktop.onConsoleMessageChange = function () {
4321 - p11clearConsoleMsg();
4322 - if (desktop.consoleMessage) {
4323 - QH('p11DeskConsoleMsg', EscapeHtml(desktop.consoleMessage).split('\n').join('<br />'));
4324 - QV('p11DeskConsoleMsg', true);
4325 - p11DeskConsoleMsgTimer = setTimeout(p11clearConsoleMsg, 8000);
4326 - }
4327 - }
4328 - desktop.m.CompressionLevel = desktopsettings.quality; // Number from 1 to 100. 50 or less is best.
4329 - desktop.m.ScalingLevel = desktopsettings.scaling;
4330 - desktop.m.FrameRateTimer = desktopsettings.framerate;
4331 - desktop.m.onDisplayinfo = deskDisplayInfo;
4332 - desktop.m.onScreenSizeChange = deskAdjust;
4333 - desktop.Start(desktopNode._id);
4334 - desktop.contype = 1;
4335 - } else if (contype == 3) {
4336 - // Ask for user sessions
4337 - meshserver.send({ action: 'msg', type: 'userSessions', nodeid: currentNode._id });
4338 - }
4339 - } else {
4340 - // Disconnect and clean up the remote desktop
4341 - desktop.Stop();
4342 - webRtcDesktopReset();
4343 - desktopNode = desktop = null;
4344 - if (pluginHandler != null) { pluginHandler.callHook('onDesktopDisconnect'); }
4345 - }
4346 - }
4347 -
4348 - function p11clearConsoleMsg() { QV('p11DeskConsoleMsg', false); if (p11DeskConsoleMsgTimer) { clearTimeout(p11DeskConsoleMsgTimer); p11DeskConsoleMsgTimer = null; } }
4349 - function p12clearConsoleMsg() { QV('p12TermConsoleMsg', false); if (p12TermConsoleMsgTimer) { clearTimeout(p12TermConsoleMsgTimer); p12TermConsoleMsgTimer = null; } }
4350 - function p13clearConsoleMsg() { QV('p13FilesConsoleMsg', false); if (p13FilesConsoleMsgTimer) { clearTimeout(p13FilesConsoleMsgTimer); p13FilesConsoleMsgTimer = null; } }
4351 -
4352 - var webRtcDesktop = null;
4353 - function webRtcDesktopReset() {
4354 - if (webRtcDesktop == null) return;
4355 - if (webRtcDesktop.softdesktop != null) { webRtcDesktop.softdesktop.Stop(); webRtcDesktop.softdesktop = null; }
4356 - if (webRtcDesktop.webchannel != null) { try { webRtcDesktop.webchannel.close(); } catch (e) { } webRtcDesktop.webchannel = null; }
4357 - if (webRtcDesktop.webrtc != null) { try { webRtcDesktop.webrtc.close(); } catch (e) { } webRtcDesktop.webrtc = null; }
4358 - webRtcDesktop = null;
4359 - // Switch back to hardware KVM
4360 - if (desktop && desktop.m) {
4361 - desktop.m.hold(false);
4362 - Q('deskstatus').textContent = StatusStrs[desktop.State];
4363 - }
4364 - // ###BEGIN###{DesktopInbandFiles}
4365 - /*
4366 - p24files = null;
4367 - p24downloadFileCancel() // If any downloads are in process, cancel them.
4368 - p24uploadFileCancel(); // If any uploads are in process, cancel them.
4369 - QV('go24', false); // Files
4370 - if (currentView == 24) { go(14); }
4371 - */
4372 - // ###END###{DesktopInbandFiles}
4373 - }
4374 -
4375 - function onDesktopStateChange(xdesktop, state) {
4376 - var xstate = state;
4377 - if ((xstate == 3) && (xdesktop.contype == 2)) { xstate++; }
4378 - var str = StatusStrs[xstate];
4379 - if ((desktop != null) && (desktop.webRtcActive == true)) { str += ", WebRTC"; }
4380 - //if (desktop.m.stopInput == true) { str += ', Loopback'; }
4381 - QH('deskstatus', str);
4382 - switch (state) {
4383 - case 0:
4384 - // Disconnect and clean up the remote desktop
4385 - desktop.Stop();
4386 - desktopNode = desktop = null;
4387 - QV('DeskFocus', false);
4388 - QV('termdisplays', false);
4389 - QV('deskRecordIcon', false);
4390 - deskFocusBtn.value = "All Focus";
4391 - if (fullscreen == true) { deskToggleFull(); }
4392 - webRtcDesktopReset();
4393 - deskPreferedStickyDisplay = 0;
4394 - break;
4395 - case 2:
4396 - break;
4397 - case 3:
4398 - if (desktop && (desktop.serverIsRecording == true)) { QV('deskRecordIcon', true); }
4399 - desktop.startTime = new Date();
4400 - if (updateSessionTimer == null) { updateSessionTimer = setInterval(updateSessionTime, 1000); }
4401 - break;
4402 - default:
4403 - //console.log('Unknown onDesktopStateChange state', state);
4404 - break;
4405 - }
4406 - updateDesktopButtons();
4407 - deskAdjust();
4408 - setTimeout(deskAdjust, 50);
4409 - }
4410 -
4411 - function updateSessionTime() {
4412 - // Desktop
4413 - var seconds = 0;
4414 - if (desktop && desktop.startTime) {
4415 - seconds = Math.floor((new Date() - desktop.startTime) / 1000);
4416 - QH('DeskTimer', zeroPad(Math.floor(seconds / 3600), 2) + ':' + zeroPad((Math.floor(seconds / 60) % 60), 2) + ':' + zeroPad((seconds % 60), 2));
4417 - } else {
4418 - QH('DeskTimer', '');
4419 - }
4420 -
4421 - // Terminal
4422 - seconds = 0;
4423 - if (terminal && terminal.startTime) {
4424 - seconds = Math.floor((new Date() - terminal.startTime) / 1000);
4425 - QH('TermTimer', zeroPad(Math.floor(seconds / 3600), 2) + ':' + zeroPad((Math.floor(seconds / 60) % 60), 2) + ':' + zeroPad((seconds % 60), 2));
4426 - } else {
4427 - QH('TermTimer', '');
4428 - }
4429 -
4430 - if ((desktop == null) && (terminal == null)) { clearInterval(updateSessionTimer); updateSessionTimer = null; }
4431 - }
4432 -
4433 - function showDesktopSettings() {
4434 - if (xxdialogMode) return;
4435 - applyDesktopSettings();
4436 - updateDesktopButtons();
4437 - setDialogMode(7, "Remote Desktop Settings", 3, showDesktopSettingsChanged);
4438 - }
4439 -
4440 - function showDesktopSettingsChanged() {
4441 - desktopsettings.encoding = d7desktopmode.value;
4442 - desktopsettings.showfocus = d7showfocus.checked;
4443 - desktopsettings.showmouse = d7showcursor.checked;
4444 - desktopsettings.quality = d7bitmapquality.value;
4445 - desktopsettings.scaling = d7bitmapscaling.value;
4446 - desktopsettings.framerate = d7framelimiter.value;
4447 - desktopsettings.localkeymap = d7localKeyMap.checked;
4448 - localStorage.setItem('desktopsettings', JSON.stringify(desktopsettings));
4449 - applyDesktopSettings();
4450 - if (desktop) {
4451 - if (desktop.contype == 1) {
4452 - if (desktop.State != 0) {
4453 - desktop.m.SendCompressionLevel(1, desktopsettings.quality, desktopsettings.scaling, desktopsettings.framerate);
4454 - }
4455 - }
4456 - if (desktop.contype == 2) {
4457 - if (desktopsettings.showfocus == false) { desktop.m.focusmode = 0; deskFocusBtn.value = "All Focus"; }
4458 - if (desktop.State != 0) { desktop.Stop(); setTimeout(function () { connectDesktop(null, 2); }, 50); }
4459 - }
4460 - }
4461 - }
4462 -
4463 - function applyDesktopSettings() {
4464 - var r = '', ops = (features & 512)?[90,80,70,60,50,40,30,20,10,5,1]:[60,50,40,30,20,10,5,1];
4465 - for (var i in ops) { r += '<option value=' + ops[i] + '>' + ops[i] + '%</option>'; }
4466 - QH('d7bitmapquality', r);
4467 - d7desktopmode.value = desktopsettings.encoding;
4468 - d7showfocus.checked = desktopsettings.showfocus;
4469 - d7showcursor.checked = desktopsettings.showmouse;
4470 - d7bitmapquality.value = 40; // Default value
4471 - if (ops.indexOf(parseInt(desktopsettings.quality)) >= 0) { d7bitmapquality.value = desktopsettings.quality; }
4472 - d7bitmapscaling.value = desktopsettings.scaling;
4473 - if (desktopsettings.framerate) { d7framelimiter.value = desktopsettings.framerate; }
4474 - if (desktopsettings.localkeymap) { d7localKeyMap.checked = desktopsettings.localkeymap; }
4475 - QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (desktop.state != 0) && (desktopsettings.showfocus));
4476 - }
4477 -
4478 - // Enter browser fullscreen
4479 - function enterBrowserFullscreen(elem) {
4480 - if (elem.requestFullscreen) { elem.requestFullscreen(); }
4481 - else if (elem.msRequestFullscreen) { elem.msRequestFullscreen(); }
4482 - else if (elem.mozRequestFullScreen) { elem.mozRequestFullScreen(); }
4483 - else if (elem.webkitRequestFullscreen) { elem.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); }
4484 - }
4485 -
4486 - // Exit browser fullscreen
4487 - function exitBrowserFullscreen() {
4488 - if (document.exitFullscreen) { document.exitFullscreen(); }
4489 - else if (document.msExitFullscreen) { document.msExitFullscreen(); }
4490 - else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); }
4491 - else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); }
4492 - }
4493 -
4494 - // Return true if the browser is fullscreen. This is a delayed method that will return true/false late. Not very useful.
4495 - function isBrowserFullscreen() {
4496 - if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) { return false; } else { return true; }
4497 - }
4498 -
4499 - var fullscreen = false;
4500 - var browserfullscreen = false;
4501 - function deskToggleFull(e) {
4502 - fullscreen = !fullscreen;
4503 - if (fullscreen) {
4504 - QC('body').add('fulldesk');
4505 - QS('deskarea3x')['height'] = '100%';
4506 - QS('deskarea3x')['max-height'] = '100%';
4507 - // If shift is pressed, enter browser full screen.
4508 - if (e.shiftKey == true) { enterBrowserFullscreen(Q('deskarea0')); browserfullscreen = true; }
4509 - } else {
4510 - QC('body').remove('fulldesk');
4511 - var hide = args.hide;
4512 - if (footerBar == false) { hide |= 4; }
4513 - var xh = (((hide & 1) ? 0 : 66) + ((hide & 2) ? 0 : 24) + ((hide & 4) ? 0 : 45) + ((hide & 8) ? 0 : 60)); // 0 to 195
4514 - QS('deskarea3x')['height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
4515 - QS('deskarea3x')['max-height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
4516 - if (browserfullscreen == true) { exitBrowserFullscreen(); browserfullscreen = false; }
4517 - }
4518 - deskAdjust();
4519 - updateDesktopButtons();
4520 - adjustPanels();
4521 - }
4522 -
4523 - function deskToggleFocus() {
4524 - desktop.m.focusmode = (desktop.m.focusmode + 64) % 192;
4525 - Q('deskFocusBtn').value = ["All Focus", "Small Focus", "Large Focus"][desktop.m.focusmode / 64];
4526 - }
4527 -
4528 - function deskAdjust() {
4529 - var parentH = Q('DeskParent').clientHeight, parentW = Q('DeskParent').clientWidth;
4530 - var deskH = Q('Desk').height, deskW = Q('Desk').width;
4531 -
4532 - if (deskAspectRatio == 2) {
4533 - // Scale mode
4534 - QS('Desk')['margin-top'] = null;
4535 - QS('Desk').height = '100%';
4536 - QS('Desk').width = '100%';
4537 - //QS('deskarea3x').height = null;
4538 - QS('DeskParent').overflow = 'hidden';
4539 - } else if (deskAspectRatio == 1) {
4540 - // Zoomed mode
4541 - QS('Desk')['margin-top'] = '0px';
4542 - QS('Desk').height = deskH + 'px';
4543 - QS('Desk').width = deskW + 'px';
4544 - QS('DeskParent').overflow = 'scroll';
4545 - } else {
4546 - // Fixed aspect ratio
4547 - if ((parentH / parentW) > (deskH / deskW)) {
4548 - var hNew = ((deskH * parentW) / deskW) + 'px';
4549 - //if (webPageFullScreen || fullscreen) {
4550 - //QS('deskarea3x').height = null;
4551 - //} else {
4552 - // QS('deskarea3x').height = hNew;
4553 - //QS('deskarea3x').height = null;
4554 - //}
4555 - QS('Desk').height = hNew;
4556 - QS('Desk').width = '100%';
4557 - } else {
4558 - var wNew = ((deskW * parentH) / deskH) + 'px';
4559 - if (webPageFullScreen || fullscreen) {
4560 - QS('Desk').height = null;
4561 - } else {
4562 - QS('Desk').height = '100%';
4563 - }
4564 - QS('Desk').width = wNew;
4565 - }
4566 - QS('Desk')['margin-top'] = null;
4567 - QS('DeskParent').overflow = 'hidden';
4568 - }
4569 - }
4570 -
4571 - function mdeskAdjust(mod, sw, sh, cv) {
4572 - if (!mod || !sw || !sh || !cv) return;
4573 -
4574 - // Check if we are in single desktop mode
4575 - if (cv.id == 'Desk') { deskAdjust(); return; }
4576 -
4577 - // Figure out and adjust the size to fill the width of the div
4578 - var vsize = [{ x: 180, y: 101 }, { x: 302, y: 169 }, { x: 454, y: 255 }][Q('sizeselect').selectedIndex];
4579 - var realw = vsize.x + 2, tw = Q('xdevices').clientWidth - 30, xw = Math.floor(tw / realw);
4580 - xw = realw + Math.floor((tw - (xw * realw)) / xw);
4581 - vsize.y = vsize.y * (xw / vsize.x);
4582 - vsize.x = xw;
4583 - var mh = vsize.y, mw = vsize.x;
4584 - if (mod.State != 0) { mh = vsize.y; mw = (sw / sh) * vsize.y; }
4585 - QS(cv.id)['max-height'] = mh + 'px';
4586 - QS(cv.id)['max-width'] = mw + 'px';
4587 - QS(cv.id)['margin-top'] = '0';
4588 - QS(cv.id)['margin-bottom'] = '0';
4589 - }
4590 -
4591 - // Remote desktop special key combos for Windows
4592 - function deskSendKeys() {
4593 - if (xxdialogMode || desktop == null || desktop.State != 3) return;
4594 - var ks = Q('deskkeys').value;
4595 - if (ks == 0) { // WIN+Down arrow
4596 - if (desktop.contype == 2) {
4597 - desktop.m.sendkey([[0xffe7,1],[0xff54,1],[0xff54,0],[0xffe7,0]]); // Intel AMT: Meta-left down, Down arrow press, Down arrow release, Meta-left release
4598 - } else {
4599 - desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,40],[desktop.m.KeyAction.UP,40],[desktop.m.KeyAction.EXUP,0x5B]]); // Agent: L-Winkey press, Down arrow press, Down arrow release, L-Winkey release
4600 - }
4601 - } else if (ks == 1) { // WIN+Up arrow
4602 - if (desktop.contype == 2) {
4603 - desktop.m.sendkey([[0xffe7,1],[0xff52,1],[0xff52,0],[0xffe7,0]]); // Intel AMT: Meta-left down, Up arrow press, Up arrow release, Meta-left release
4604 - } else {
4605 - desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,38],[desktop.m.KeyAction.UP,38],[desktop.m.KeyAction.EXUP,0x5B]]); // MeshAgent: L-Winkey press, Up arrow press, Up arrow release, L-Winkey release
4606 - }
4607 - } else if (ks == 2) { // WIN+L arrow
4608 - if (desktop.contype == 2) {
4609 - desktop.m.sendkey([[0xffe7,1],[0x6c,1],[0x6c,0],[0xffe7,0]]); // Intel AMT: Meta-left down, 'l' press, 'l' release, Meta-left release
4610 - } else {
4611 - desktop.sendCtrlMsg('{"action":"lock"}');
4612 - //desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,76],[desktop.m.KeyAction.UP,76],[desktop.m.KeyAction.EXUP,0x5B]]); // MeshAgent: L-Winkey press, 'L' press, 'L' release, L-Winkey release
4613 - //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.EXDOWN, 0x5B);
4614 - //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.DOWN, 76);
4615 - //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.UP, 76);
4616 - //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.EXUP, 0x5B);
4617 - }
4618 - } else if (ks == 3) { // WIN+M arrow
4619 - if (desktop.contype == 2) {
4620 - desktop.m.sendkey([[0xffe7,1],[0x6d,1],[0x6d,0],[0xffe7,0]]); // Intel AMT: Meta-left down, 'm' press, 'm' release, Meta-left release
4621 - } else {
4622 - desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,77],[desktop.m.KeyAction.UP,77],[desktop.m.KeyAction.EXUP,0x5B]]); // MeshAgent: L-Winkey press, 'M' press, 'M' release, L-Winkey release
4623 - }
4624 - } else if (ks == 4) { // Shift+WIN+M arrow
4625 - if (desktop.contype == 2) {
4626 - desktop.m.sendkey([[0xffe1,1],[0xffe7,1],[0x6d,1],[0x6d,0],[0xffe7,0],[0xffe1,0]]); // Intel AMT: Shift-left down, Meta-left down, 'm' press, 'm' release, Meta-left release, Shift-left release
4627 - } else {
4628 - desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.DOWN,16],[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,77],[desktop.m.KeyAction.UP,77],[desktop.m.KeyAction.EXUP,0x5B],[desktop.m.KeyAction.UP, 16]]); // MeshAgent: L-shift press, L-Winkey press, 'M' press, 'M' release, L-Winkey release, L-shift release
4629 - }
4630 - } else if (ks == 5) { // WIN
4631 - if (desktop.contype == 2) {
4632 - desktop.m.sendkey([[0xffe7,1],[0xffe7,0]]); // Intel AMT: Meta-left down, Meta-left release
4633 - } else {
4634 - desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B], [desktop.m.KeyAction.EXUP,0x5B]]); // MeshAgent: L-Winkey press, L-Winkey release
4635 - }
4636 - } else if (ks == 6) { // WIN+R
4637 - if (desktop.contype == 2) {
4638 - desktop.m.sendkey([[0xffe7,1],[0x72,1],[0x72,0],[0xffe7,0]]); // Intel AMT: Meta-left down, 'r' press, 'r' release, Meta-left release
4639 - } else {
4640 - desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 82], [desktop.m.KeyAction.UP, 82], [desktop.m.KeyAction.EXUP, 0x5B]]); // MeshAgent: L-Winkey press, 'R' press, 'R' release, L-Winkey release
4641 - }
4642 - } else if (ks == 7) { // ALT-F4
4643 - if (desktop.contype == 2) {
4644 - desktop.m.sendkey([[0xffe9,1],[0xffc1,1],[0xffc1,0],[0xffe9,0]]); // Intel AMT: Alt down, 'F4' press, 'F4' release, Alt release
4645 - } else {
4646 - desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 18], [desktop.m.KeyAction.DOWN, 115], [desktop.m.KeyAction.UP, 115], [desktop.m.KeyAction.EXUP, 18]]); // MeshAgent: Alt press, 'F4' press, 'F4' release, Alt release
4647 - }
4648 - } else if (ks == 8) { // CTRL-W
4649 - if (desktop.contype == 2) {
4650 - desktop.m.sendkey([[0xffe3,1],[0x77,1],[0x77,0],[0xffe3,0]]); // Intel AMT: Ctrl down, 'w' press, 'w' release, Ctrl release
4651 - } else {
4652 - desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 17], [desktop.m.KeyAction.DOWN, 87], [desktop.m.KeyAction.UP, 87], [desktop.m.KeyAction.EXUP, 17]]); // MeshAgent: Ctrl press, 'W' press, 'W' release, Ctrl release
4653 - }
4654 - } else if (ks == 9) { // ALT-TAB
4655 - if (desktop.contype == 2) {
4656 - desktop.m.sendkey([[0xffe9, 1], [0xff09, 1], [0xff09, 0], [0xffe9, 0]]); // Intel AMT: Alt down, 'TAB' press, 'TAB' release, Alt release
4657 - } else {
4658 - desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 18], [desktop.m.KeyAction.DOWN, 9], [desktop.m.KeyAction.UP, 9], [desktop.m.KeyAction.EXUP, 18]]); // MeshAgent: Alt press, 'TAB' press, 'TAB' release, Alt release
4659 - }
4660 - } else if (ks == 10) { // CTRL-ALT-DEL
4661 - desktop.m.sendcad();
4662 - } else if (ks == 11) { // WIN-LEFT
4663 - if (desktop.contype == 2) {
4664 - desktop.m.sendkey([[0xffe7, 1], [0xff51, 1], [0xff51, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Left arrow press, Left arrow release, Meta-left release
4665 - } else {
4666 - desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 37], [desktop.m.KeyAction.UP, 37], [desktop.m.KeyAction.EXUP, 0x5B]]);
4667 - }
4668 - } else if (ks == 12) { // WIN-RIGHT
4669 - if (desktop.contype == 2) {
4670 - desktop.m.sendkey([[0xffe7, 1], [0xff53, 1], [0xff53, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Right arrow press, Right arrow release, Meta-left release
4671 - } else {
4672 - desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 39], [desktop.m.KeyAction.UP, 39], [desktop.m.KeyAction.EXUP, 0x5B]]);
4673 - }
4674 - }
4675 - }
4676 -
4677 - // Remote desktop typing
4678 - function showDeskType() {
4679 - if (xxdialogMode || desktop == null || desktop.State != 3) return;
4680 - Q('DeskType').blur();
4681 - var x = '<div>' + "Enter text and click OK to remotely type it using a US english keyboard. Make sure to place the remote cursor at the correct position before proceeding." + '<div>';
4682 - x += '<textarea id=d2typeText style="margin-top:5px;width:100%;height:184px;resize:none" maxlength=2000></textarea>';
4683 - setDialogMode(2, "Remote Keyboard Entry", 3, showDeskTypeEx, x);
4684 - Q('d2typeText').focus();
4685 - }
4686 -
4687 - var AmtDeskTypeTimer = null;
4688 - var AmtDeskTypeContent = null;
4689 - var DeskTypeTranslate = { 39: 222, 42: 106, 43: 107, 44: 188, 45: 189, 46: 190, 47: 191, 59: 186, 61: 187, 91: 219, 92: 220, 93: 221, 96: 192, 191: 111 };
4690 - var DeskTypeShiftTranslate = { 33: 49, 34: 222, 35: 51, 36: 52, 37: 53, 38: 55, 40: 57, 41: 48, 58: 186, 60: 188, 62: 190, 63: 191, 64: 50, 94: 54, 95: 189, 106: 56, 107: 187, 123: 219, 124: 220, 125: 221, 126: 192 };
4691 - function showDeskTypeEx() {
4692 - var txt = Q('d2typeText').value, ltxt = Q('d2typeText').value.toUpperCase(), x = [], shift = false;
4693 - if (desktop.contype == 2) {
4694 - // Intel AMT
4695 - for (var i in txt) { var a = txt.charCodeAt(i); x.push([a, 1], [a, 0]); }
4696 - AmtDeskTypeContent = x;
4697 - AmtDeskTypeTimer = setInterval(function () {
4698 - var key = AmtDeskTypeContent.shift();
4699 - if (desktop) { desktop.m.sendkey(key[0], key[1]); }
4700 - if ((desktop == null) || (AmtDeskTypeContent.length == 0)) { clearInterval(AmtDeskTypeTimer); AmtDeskTypeContent = null; }
4701 - }, 10);
4702 - } else {
4703 - // MeshAgent
4704 - for (var i in txt) {
4705 - var a = txt.charCodeAt(i), b = ltxt.charCodeAt(i);
4706 - if (((a >= 65) && (a <= 90)) || ((a >= 97) && (a <= 122))) {
4707 - if ((a == b) && (shift == false)) { x.push([desktop.m.KeyAction.DOWN, 16]); shift = true; } // LShift down
4708 - if ((a != b) && (shift == true)) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // LShift up
4709 - } else if ((a >= 48) && (a <= 57)) {
4710 - if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
4711 - } else if (DeskTypeTranslate[a]) {
4712 - if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
4713 - b = DeskTypeTranslate[a];
4714 - } else if (DeskTypeShiftTranslate[a]) {
4715 - if (shift == false) { x.push([desktop.m.KeyAction.DOWN, 16]); shift = true; } // LShift down
4716 - b = DeskTypeShiftTranslate[a];
4717 - }
4718 - x.push([desktop.m.KeyAction.DOWN, b], [desktop.m.KeyAction.UP, b]);
4719 - }
4720 - if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
4721 - desktop.m.SendKeyMsgKC(x);
4722 - }
4723 - }
4724 -
4725 - // Show clipboard dialog
4726 - function showDeskClip() {
4727 - if (xxdialogMode || desktop == null || desktop.State != 3) return;
4728 - Q('DeskClip').blur();
4729 - var x = '';
4730 - x += '<input id=dlgClipGet type=button value="Get Clipboard" style=width:120px onclick=showDeskClipGet()>';
4731 - x += '<input id=dlgClipSet type=button value="Set Clipboard" style=width:120px onclick=showDeskClipSet()>';
4732 - x += '<div id=dlgClipStatus style="display:inline-block;margin-left:8px" ></div>';
4733 - x += '<textarea id=d2clipText style="width:100%;height:184px;resize:none" maxlength=65535></textarea>';
4734 - x += '<input type=button value="Close" style=width:80px;float:right onclick=dialogclose(0)><div style=height:26px;margin-top:3px><span id=linuxClipWarn style=display:none>' + "Remote clipboard is valid for 60 seconds." + '</span>&nbsp;</div><div></div>';
4735 - setDialogMode(2, "Remote Clipboard", 8, null, x, 'clipboard');
4736 - Q('d2clipText').focus();
4737 - }
4738 -
4739 - function showDeskClipGet() {
4740 - if (desktop == null || desktop.State != 3) return;
4741 - meshserver.send({ action: 'msg', type: 'getclip', nodeid: currentNode._id });
4742 - }
4743 -
4744 - function showDeskClipSet() {
4745 - if (desktop == null || desktop.State != 3) return;
4746 - meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: Q('d2clipText').value });
4747 - QV('linuxClipWarn', currentNode && currentNode.agent && (currentNode.agent.id > 4) && (currentNode.agent.id != 21) && (currentNode.agent.id != 22));
4748 - }
4749 -
4750 - // Send CTRL-ALT-DEL
4751 - function sendCAD() {
4752 - if (xxdialogMode || desktop == null || desktop.State != 3) return;
4753 - desktop.m.sendcad();
4754 - }
4755 -
4756 - // Show process dialogs
4757 - function toggleDeskTools() {
4758 - if (xxdialogMode) return;
4759 - if (QS('DeskTools').display == 'none') {
4760 - QV('DeskTools', true);
4761 - Q('DeskTools').nodeid = currentNode._id;
4762 - QH('DeskToolsProcesses', '');
4763 - QH('DeskToolsServices', '');
4764 - QV('deskToolsTopTabService', false);
4765 - changeDeskToolTab(0)
4766 - refreshDeskTools(0);
4767 - refreshDeskTools(1);
4768 - } else {
4769 - QV('DeskTools', false);
4770 - }
4771 - }
4772 -
4773 - var deskToolTabSelection = 0;
4774 - function changeDeskToolTab(tabnum) {
4775 - deskToolTabSelection = tabnum;
4776 - QV('DeskToolsProcessTab', tabnum == 0);
4777 - QV('DeskToolsServiceTab', tabnum == 1);
4778 - QS('deskToolsTopTabProcess')['bottom'] = (tabnum == 0) ? '0px' : '3px';
4779 - QS('deskToolsTopTabService')['bottom'] = (tabnum == 1) ? '0px' : '3px';
4780 - QS('deskToolsTopTabProcess')['color'] = (tabnum == 0) ? 'black' : 'gray';
4781 - QS('deskToolsTopTabService')['color'] = (tabnum == 1) ? 'black' : 'gray';
4782 - }
4783 -
4784 - // Refresh all of the desktop tool panels
4785 - function refreshDeskTools(x) {
4786 - var sel = (x == null) ? deskToolTabSelection : x;
4787 - QV('DeskToolsRefreshButton', false);
4788 - setTimeout(refreshDeskToolsEx, 500);
4789 - if (sel == 0) meshserver.send({ action: 'msg', type: 'ps', nodeid: currentNode._id });
4790 - if (sel == 1) meshserver.send({ action: 'msg', type: 'services', nodeid: currentNode._id });
4791 - }
4792 - function refreshDeskToolsEx() { QV('DeskToolsRefreshButton', true); }
4793 - var deskTools = { sort: 1, ssort: 1, msg: null, smsg: null };
4794 - function sortProcess(sort) { deskTools.sort = sort; showDeskToolsProcesses(deskTools.msg); }
4795 - function sortService(sort) { deskTools.ssort = sort; showDeskToolsServices(deskTools.smsg); }
4796 - function sortProcessPid(a, b) { if (a.p > b.p) return 1; if (a.p < b.p) return (-1); return sortProcessName(a, b); }
4797 - function sortProcessName(a, b) { if (a.d > b.d) return 1; if (a.d < b.d) return (-1); return 0; }
4798 - function showDeskToolsProcesses(message) {
4799 - deskTools.msg = message;
4800 - if (message == null) { QH('DeskToolsProcesses', ''); return; }
4801 - if (Q('DeskTools').nodeid != message.nodeid) return;
4802 - var p = [], processes = null;
4803 - try { processes = JSON.parse(message.value); } catch (e) { }
4804 - if (processes != null) {
4805 - for (var pid in processes) { p.push( { p:parseInt(pid), c:processes[pid].cmd, d:processes[pid].cmd.toLowerCase(), u: processes[pid].user } ); }
4806 - if (deskTools.sort == 0) { p.sort(sortProcessPid); } else if (deskTools.sort == 1) { p.sort(sortProcessName); }
4807 - var x = '';
4808 - for (var i in p) {
4809 - if (p[i].p != 0) {
4810 - var c = p[i].c;
4811 - if (c.length > 30) { c = '<span title="' + c + '">' + c.substring(0,30) + '...</span>' }
4812 - x += '<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>' + p[i].p + '</div><a href=# style=float:right;padding-right:5px;cursor:pointer title="Stop process" onclick=\'return 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>' + c + '</div></div>';
4813 - }
4814 - }
4815 - QH('DeskToolsProcesses', x);
4816 - }
4817 - }
4818 - function showDeskToolsServices(message) {
4819 - deskTools.smsg = message;
4820 - if (message == null) { QH('DeskToolsProcesses', ''); return; }
4821 - if (Q('DeskTools').nodeid != message.nodeid) return;
4822 - QV('deskToolsTopTabService', true);
4823 - var s = [], services = null;
4824 - try { services = JSON.parse(message.value); } catch (e) { }
4825 - deskTools.services = services;
4826 - if (services != null) {
4827 - for (var i in services) {
4828 - if (services[i].status) {
4829 - // Windows
4830 - s.push({ p: capitalizeFirstLetter(services[i].status.state.toLowerCase()), d: services[i].displayName, i: i });
4831 - } else if (services[i].serviceType) {
4832 - // Linux (TODO: This the service status is not displayed, not sure start/stop/restart will work).
4833 - s.push({ p: services[i].serviceType, d: services[i].name, i: i });
4834 - }
4835 - }
4836 - if (deskTools.ssort == 0) { s.sort(sortProcessPid); } else if (deskTools.ssort == 1) { s.sort(sortProcessName); }
4837 - var x = '';
4838 - for (var i in s) {
4839 - if (s[i].p != 0) {
4840 - var c = s[i].d;
4841 - if (c.length > 30) { c = '<span title="' + c + '">' + c.substring(0, 30) + '...</span>' }
4842 - x += '<div onclick=showServiceDetailsDialog(' + s[i].i + ') class=deskToolsBar><div style=width:70px;float:left;padding-right:5px>' + s[i].p + '</div><div>' + c + '</div></div>';
4843 - }
4844 - }
4845 - QH('DeskToolsServices', x);
4846 - }
4847 - }
4848 -
4849 - function showServiceDetailsDialog(index) {
4850 - if (xxdialogMode) return;
4851 - var service = deskTools.services[index];
4852 - if (service != null) {
4853 - var x = '';
4854 - if (service.name) { x += addHtmlValue("Name", service.name); }
4855 - if (service.displayName) { x += addHtmlValue("Display name", service.displayName); }
4856 - if (service.status) {
4857 - if (service.status.state) { x += addHtmlValue("State", capitalizeFirstLetter(service.status.state.toLowerCase())); }
4858 - if (service.status.pid) { x += addHtmlValue("PID", service.status.pid); }
4859 - var serviceTypes = [];
4860 - if (service.status.isFileSystemDriver === true) { serviceTypes.push("FileSystemDriver"); }
4861 - if (service.status.isInteractive === true) { serviceTypes.push("Interactive"); }
4862 - if (service.status.isKernelDriver === true) { serviceTypes.push("KernelDriver"); }
4863 - if (service.status.isOwnProcess === true) { serviceTypes.push("OwnProcess"); }
4864 - if (service.status.isSharedProcess === true) { serviceTypes.push("SharedProcess"); }
4865 - if (serviceTypes.length > 0) { x += addHtmlValue("Type", serviceTypes.join(', ')); }
4866 - }
4867 - x += '<br/><div style=float:right;margin-bottom:12px><input type=button value=\"' + "Close" + '\" onclick=showServiceDetailsDialogEx(0,' + index + ')></div><div style=margin-bottom:12px><input type=button value=\"' + "Start" + '\" onclick=showServiceDetailsDialogEx(1,' + index + ')><input type=button value=\"' + "Stop" + '\" onclick=showServiceDetailsDialogEx(2,' + index + ')><input type=button value=\"' + "Restart" + '\" onclick=showServiceDetailsDialogEx(3,' + index + ')></div>';
4868 - setDialogMode(2, "Service Details", 8, null, x, name);
4869 - }
4870 - }
4871 -
4872 - function showServiceDetailsDialogEx(action, index) {
4873 - setDialogMode(0);
4874 - if (action == 0) return;
4875 - var service = deskTools.services[index];
4876 - if (service != null) {
4877 - if (action == 1) { meshserver.send({ action: 'msg', type: 'serviceStart', nodeid: currentNode._id, serviceName: service.name }); }
4878 - if (action == 2) { meshserver.send({ action: 'msg', type: 'serviceStop', nodeid: currentNode._id, serviceName: service.name }); }
4879 - if (action == 3) { meshserver.send({ action: 'msg', type: 'serviceRestart', nodeid: currentNode._id, serviceName: service.name }); }
4880 - setTimeout(function () { refreshDeskTools(1) }, 1000);
4881 - }
4882 - }
4883 -
4884 - // Toggle mouse and keyboard input
4885 - function toggleKvmControl() { putstore('DeskControl', (Q("DeskControl").checked?1:0)); }
4886 -
4887 - // Save the desktop image to file
4888 - function deskSaveImage() {
4889 - if (xxdialogMode || desktop == null || desktop.State != 3) return;
4890 - 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);
4891 - Q('Desk')['toBlob'](function (blob) { saveAs(blob, n + '.jpg'); });
4892 - }
4893 -
4894 - function deskDisplayInfo(sender, displays, selDisplay) {
4895 - var displayCount = 0, displaySelector = '';
4896 - for (var i in displays) {
4897 - displayCount++;
4898 - displaySelector += '<option' + ((selDisplay == i) ? ' selected' : '') + ' value=' + i + '>' + displays[i] + '</option>';
4899 - if ((deskPreferedStickyDisplay == i) && (selDisplay != deskPreferedStickyDisplay)) { desktop.m.SetDisplay(i); }
4900 - }
4901 - QH('termdisplays', displaySelector);
4902 - QV('termdisplays', displayCount > 1);
4903 - }
4904 -
4905 - function deskGetDisplayNumbers(e) { desktop.m.GetDisplayNumbers(); }
4906 - var deskPreferedStickyDisplay = 0;
4907 - function deskSetDisplay(e) { desktop.m.SetDisplay(deskPreferedStickyDisplay = parseInt(Q('termdisplays').value)); Q('termdisplays').blur(); }
4908 -
4909 - // Double click detection. This is important for MacOS.
4910 - var dblClickDetectArgs = { t:0, x:0, y:0 };
4911 - function dblClickDetect(e) {
4912 - if (e.buttons != 1) return;
4913 - var t = Date.now();
4914 - if (((t - dblClickDetectArgs.t) < 250) && (Math.abs(e.clientX - dblClickDetectArgs.x) < 2) && (Math.abs(e.clientY - dblClickDetectArgs.y) < 2)) {
4915 - if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousedblclick(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousedblclick(e); } }
4916 - }
4917 - dblClickDetectArgs.t = t;
4918 - dblClickDetectArgs.x = e.clientX;
4919 - dblClickDetectArgs.y = e.clientY;
4920 - }
4921 -
4922 - function dmousedown(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousedown(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousedown(e); } } dblClickDetect(e); }
4923 - function dmouseup(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mouseup(e); desktop.m.sendKeepAlive(); } else { desktop.m.mouseup(e); } }
4924 - function dmousemove(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousemove(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousemove(e); } } }
4925 - function dmousewheel(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousewheel(e); desktop.m.sendKeepAlive(); } else { if (desktop.m.mousewheel) { desktop.m.mousewheel(e); } } haltEvent(e); return true; } return false; }
4926 - function drotate(x) { if (!xxdialogMode && desktop != null) { desktop.m.setRotation(desktop.m.rotation + x); deskAdjust(); deskAdjust(); } }
4927 - function stopProcess(id, name) { setDialogMode(2, "Process Control", 3, stopProcessEx, format("Stop process #{0} \"{1}\"?", id, name), id); return false; }
4928 - function stopProcessEx(buttons, tag) { meshserver.send({ action: 'msg', type: 'pskill', nodeid: currentNode._id, value: tag }); setTimeout(refreshDeskTools, 300); }
4929 -
4930 - //
4931 - // TERMINAL
4932 - //
4933 -
4934 - var terminalNode;
4935 - function setupTerminal() {
4936 - // Setup the terminal
4937 - if ((terminalNode != currentNode) && (terminal != null)) { terminal.Stop(); terminal = null; }
4938 - terminalNode = currentNode;
4939 - updateTerminalButtons();
4940 - }
4941 -
4942 - // Show and enable the right buttons
4943 - function updateTerminalButtons() {
4944 - var mesh = meshes[terminalNode.meshid];
4945 - var termState = ((terminal != null) && (terminal.state != 0));
4946 -
4947 - // Show the right buttons
4948 - QV('disconnectbutton2span', (termState == true));
4949 - QV('connectbutton2span', (termState == false) && (mesh.mtype == 2) && (currentNode.agent.caps & 2));
4950 - QV('connectbutton2hspan', (termState == false) && ((terminalNode.intelamt != null) && (mesh.mtype == 1 || terminalNode.intelamt.state == 2) && ((terminalNode.intelamt.ver != null) || (mesh.mtype == 1))));
4951 -
4952 - // Enable buttons
4953 - var online = ((terminalNode.conn & 1) != 0); // If Agent (1) connected, enable Terminal
4954 - QE('connectbutton2', online);
4955 - var hwonline = ((terminalNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal
4956 - QE('connectbutton2h', hwonline);
4957 -
4958 - // Key buttons
4959 - QE('ctrlcbutton', termState);
4960 - QE('ctrlxbutton', termState);
4961 - QE('escbutton', termState);
4962 - QE('bsbutton', termState);
4963 - QE('pastebutton', termState);
4964 - QE('specialkeylist', termState);
4965 - QE('specialkeylistinput', termState);
4966 -
4967 - // Terminal settings
4968 - QV('terminalSettingsButtons', (terminal) && (terminal.contype == 2));
4969 - if (terminal) {
4970 - Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
4971 - Q('id_tfxkeysbutton').value = fxEmulations[terminal.m.fxEmulation];
4972 - Q('id_tcrbutton').value = (terminal.m.lineFeed == '\r\n')?"CR+LF":"LF";
4973 - }
4974 - }
4975 -
4976 - // Called when the terminal state changes
4977 - function onTerminalStateChange(xterminal, state) {
4978 - var xstate = state;
4979 - if ((xstate == 3) && (xterminal.contype == 2)) { xstate++; }
4980 - var str = StatusStrs[xstate];
4981 - if (terminal.webRtcActive == true) { str += ", WebRTC"; }
4982 - QH('termstatus', str);
4983 - switch (state) {
4984 - case 0:
4985 - // Disconnected, clear the terminal
4986 - QE('termSizeList', true);
4987 - QH('termtitle', '');
4988 - QV('termRecordIcon', false);
4989 - xterminal.m.TermResetScreen();
4990 - xterminal.m.TermDraw();
4991 - if (terminal != null) { terminal.Stop(); terminal = null; }
4992 - break;
4993 - case 3:
4994 - QE('termSizeList', false);
4995 - if (xterminal && (xterminal.serverIsRecording == true)) { QV('termRecordIcon', true); }
4996 - terminal.startTime = new Date();
4997 - if (updateSessionTimer == null) { updateSessionTimer = setInterval(updateSessionTime, 1000); }
4998 - break;
4999 - default:

This file is too large to show in full.

views/default-mobile-min.handlebars deleted
-1
@@ -1 +0,0 @@
1 -<!doctypehtml><html dir=ltr xmlns=http://www.w3.org/1999/xhtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html; charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link rel="shortcut icon"type=image/x-icon href={{{domainurl}}}favicon.ico><script src=scripts/common-0.0.1.js></script><script src=scripts/meshcentral.js></script><script src=scripts/agent-redir-ws-0.1.1.js></script><script src=scripts/agent-desktop-0.0.2.js></script><script src=scripts/amt-0.2.0.js></script><script src=scripts/amt-redir-ws-0.1.0.js></script><script src=scripts/amt-desktop-0.0.2.js></script><script src=scripts/zlib.js></script><script src=scripts/zlib-inflate.js></script><script src=scripts/zlib-adler32.js></script><script src=scripts/zlib-crc32.js></script><script keeplink=1 src=scripts/filesaver.js></script><title>{{{title}}}</title><style>a{color:#036;text-decoration:underline}#footer a{color:#fff;text-decoration:underline}#footer a:hover{color:#fff;text-decoration:none}.i1{background:url(../images/icons50.png) 0 0;height:50px;width:50px;border:none}.i2{background:url(../images/icons50.png) -50px 0;height:50px;width:50px;border:none}.i3{background:url(../images/icons50.png) -100px 0;height:50px;width:50px;border:none}.i4{background:url(../images/icons50.png) -150px 0;height:50px;width:50px;border:none}.i5{background:url(../images/icons50.png) -200px 0;height:50px;width:50px;border:none}.i6{background:url(../images/icons50.png) -250px 0;height:50px;width:50px;border:none}.m0{background:url(../images/images16.png) -32px 0;height:16px;width:16px;border:none;float:left}.m1{background:url(../images/images16.png) -16px 0;height:16px;width:16px;border:none;float:left}.m2{background:url(../images/images16.png) -96px 0;height:16px;width:16px;border:none;float:left}.m3{background:url(../images/images16.png) -112px 0;height:16px;width:16px;border:none;float:left}.gray{filter:gray;-webkit-filter:grayscale(100%) opacity(60%)}.DevSt{padding-left:5px;border-bottom-style:solid;border-bottom-width:1px;border-bottom-color:#ddd}.noselect{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fileIcon1{background:url(data:image/gif;base64,R0lGODlhEAAQAJEDAPb49Y2Sj9LT2f///yH5BAEAAAMALAAAAAAQABAAAAImnI+py+1vhJwyUYAzHTL4D3qdlJWaIFJqmKod607sDKIiDUP63hQAOw==);height:16px;width:16px;cursor:pointer;border:none;float:left;margin-top:1px}.fileIcon2{background:url(data:image/gif;base64,R0lGODlhEAAQAJEDAM2xV/Xur+XPgP///yH5BAEAAAMALAAAAAAQABAAAAJD3ISZIGHWUGihznesYDYATFVM+D2hJ4lgN1olxALAtAlmPCJvuMmJd6PJckDYwicrHhTD5o7plJmg0Uc0asNMkphHAQA7);height:16px;width:16px;cursor:pointer;border:none;float:left;margin-top:1px}.fileIcon3{background:url(data:image/gif;base64,R0lGODlhEAAQAJEDAPb19IGBgbq6uv///yH5BAEAAAMALAAAAAAQABAAAAIy3ISpxgcPH2ouQgFEw1YmxnUXKEaaEZZnVWZk66JwzKpvuwZzwOgwb/C1gIOA8Yg8DgoAOw==);height:16px;width:16px;cursor:pointer;border:none;float:left;margin-top:1px}.fileIcon4{background:url(../images/meshicon16.png);height:16px;width:16px;cursor:pointer;border:none;float:left;margin-top:1px}.filelist{-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-o-user-select:none;cursor:default;-khtml-user-drag:element;background-color:#fff;clear:both}</style><body onload='"undefined"!=typeof startup&&startup()'style="overflow-y:hidden;margin:0;padding:0;border:0;color:#000;font-size:13px;font-family:\'Trebuchet MS\',Arial,Helvetica,sans-serif"><div id=container><div id=mastheadx></div><div id=masthead style="background:url(logo.png) 0 0;background-size:341px 50px;background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden"><div style="width:calc(100% - 50px);overflow:hidden"><div style=float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:6px><strong><font style=font-size:36px;font-family:Arial,Helvetica,sans-serif>{{{title}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:10px><strong><font style=font-size:12px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div></div><img id=topMenuIcon class=noselect style=position:absolute;right:0;top:10px;bottom:50px;color:#c8c8c8;font-size:44px;margin-right:8px;cursor:pointer;display:none onclick=topMenu() src=/images/3bars-30.png width=30 height=30></div><div id=page_content style=overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%><div id=column_l style=width:100%;padding:0;position:absolute;bottom:0;top:0><div id=p0 style=display:none;width:100%;height:100%><div style=display:flex;align-items:center;width:100%;height:100%><div id=p0message style=text-align:center;width:100%><span id=p0span>Server disconnected</span>,<href onclick=reload() style=cursor:pointer><u>click to reconnect</u></href>.</div></div></div><div id=p1 style=display:none;width:100%;height:100%><div style=display:flex;align-items:center;width:100%;height:100%><div id=p1message style=text-align:center;width:100%></div></div></div><div id=p2 style=display:none><div id=xdevices></div></div><div id=p3 style=display:none;position:absolute;bottom:0;top:0;width:100%><table cellspacing=0 style=margin:0;padding:0;border-spacing:0;border:0><tr style=padding:0><td style=padding:0;color:#c8c8c8;text-align:center;cursor:pointer width=60px valign=top onclick=goBack()><div style=padding:0;background-color:#036;width:10px;height:10px;float:right;border:0><div style="background-color:#fff;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid #fff;border-bottom:1px solid #fff"></div></div><div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">&#9664;</div><td><img src=/images/user-50.png width=50 height=50><td><div style=margin-left:5px><strong style=font-size:large><span id=p3userName></span></strong><br></div></table><div id=p3info style=overflow-y:scroll;position:absolute;top:55px;bottom:0;width:100%><div style=margin-left:8px><div id=p3AccountActions><p><strong>Account Security</strong><div style=margin-left:9px;margin-bottom:8px><div id=manageAuthApp style=margin-top:5px;display:none><a onclick=account_manageAuthApp() style=cursor:pointer>Manage authenticator app</a></div><div id=manageOtp style=margin-top:5px;display:none><a onclick=account_manageOtp(0) style=cursor:pointer>Manage backup codes</a></div></div><p><strong>Account Actions</strong><div style=margin-left:9px;margin-bottom:8px><div style=margin-top:5px><span id=verifyEmailId style=display:none><a onclick=account_showVerifyEmail() style=cursor:pointer>Verify email</a></span></div><div style=margin-top:5px><span id=changeEmailId style=display:none><a onclick=account_showChangeEmail() style=cursor:pointer>Change email address</a></span></div><div style=margin-top:5px><a onclick=account_showChangePassword() style=cursor:pointer>Change password</a><span id=p2nextPasswordUpdateTime></span></div><div style=margin-top:5px><a onclick=account_showDeleteAccount() style=cursor:pointer>Delete account</a></div></div><br style=clear:both></div><strong>Device Groups</strong> <span id=p3createMeshLink1>( <a onclick=account_createMesh() style=cursor:pointer><img src=images/icon-addnew.png width=12 height=12 border=0> New</a> )</span><br><br><div id=p3meshes></div><div id=p3noMeshFound style=margin-left:9px;display:none>No device groups.<span id=p3createMeshLink2> <a onclick=account_createMesh() style=cursor:pointer><strong>Get started here!</strong></a></span></div><br style=clear:both></div></div></div><div id=p5 style=display:none><table cellspacing=0 style=margin:0;padding:0;border-spacing:0;border:0><tr style=padding:0><td style=padding:0;color:#c8c8c8;text-align:center;cursor:pointer width=60px valign=top onclick=goBack()><div style=padding:0;background-color:#036;width:10px;height:10px;float:right;border:0><div style="background-color:#fff;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid #fff;border-bottom:1px solid #fff"></div></div><div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">&#9664;</div><td><img src=/images/user-50.png width=50 height=50><td><div style=margin-left:5px><strong style=font-size:large>My Files</strong><br></div></table><div id=p5myfiles style=overflow-y:scroll;position:absolute;top:55px;bottom:0;width:100%><table id=p5toolbar style=width:100%;height:78px cellpadding=0 cellspacing=0><tr><td style=width:100%;background-color:#d3d9d6;text-align:left;padding:4px valign=bottom><div style=width:100%;text-align:center><input type=button style="width:calc(100%/5 - 5px)"id=p5FolderUp disabled onclick=p5folderup() value=Up> <input type=button style="width:calc(100%/5 - 5px)"id=p5SelectAllButton disabled onclick=p5selectallfile() value=SelectAll onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p5RenameFileButton disabled value=Rename onclick=p5renamefile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p5DeleteFileButton disabled value=Delete onclick=p5deletefile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p5NewFolderButton disabled value=Folder onclick=p5createfolder() onkeypress=return!1 onkeydown=return!1></div><div style=width:100%;text-align:center><input type=button style="width:calc(100%/5 - 5px)"id=p5UploadButton disabled value=Upload onclick=p5uploadFile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p5CutButton disabled value=Cut onclick=p5copyFile(1) onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p5CopyButton disabled value=Copy onclick=p5copyFile(0) onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p5PasteButton disabled value=Paste onclick=p5pasteFile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p5RefreshButton value=Refresh onclick=p5refreshFiles() onkeypress=return!1 onkeydown=return!1></div><tr><td style=background-color:#e4e9e7;height:28px><table style=width:100%><tr><td id=p5currentpath style=overflow:hidden;padding-left:4px;padding-top:2px><td style=text-align:right;padding-right:4px><select id=p5sortdropdown onchange=updateFiles()><option value=1 selected>Sort by name<option value=2>Sort by size<option value=3>Sort by date<option value=4>Descend by name<option value=5>Descend by size<option value=6>Descend by date</select></table></table><div id=p5filetable style="width:100%;height:calc(100% - 133px);overflow:auto;-webkit-user-select:none"><span id=p5files></span></div><table id=p5toolbarBottom style=width:100%;height:22px;position:absolute;bottom:0;background-color:#d3d9d6 cellpadding=0 cellspacing=0><tr><td style=text-align:left;padding:3px>&nbsp;<span id=p5bottomstatus></span><td id=p5rightOfButtons style=text-align:right;padding:3px></table></div></div><div id=p10 style=display:none;position:absolute;bottom:0;top:0;width:100%;overflow:hidden><table cellspacing=0 style=margin:0;padding:0;border-spacing:0;border:0;position:absolute;top:0><tr style=padding:0><td style=padding:0;color:#c8c8c8;text-align:center;cursor:pointer width=60px valign=top onclick=goBack()><div style=padding:0;background-color:#036;width:10px;height:10px;float:right;border:0><div style="background-color:#fff;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid #fff;border-bottom:1px solid #fff"></div></div><div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">&#9664;</div><td><a id=MainComputerImage style=cursor:pointer onclick=p10showiconselector()></a><td><div style=margin-left:5px><strong><span id=p10deviceName></span></strong><br><span id=MainComputerState></span></div></table><div id=p10general style=overflow-y:scroll;position:absolute;top:55px;bottom:0;width:100%><div id=p10html style=margin-left:8px;margin-right:8px></div><div id=p10html2></div><div id=p10html3></div></div><div id=p10desktop style=overflow:hidden;position:absolute;top:55px;bottom:0;width:100%;display:none><div id=deskarea1 style=position:absolute;top:0;width:100%;height:25px><div style=padding-top:2px;padding-bottom:2px;background:silver><div style=float:right;text-align:right><span id=p14power></span>&nbsp; <input id=DeskSoftInput style=width:25px;display:none;opacity:.2 onblur=toggleSoftKeys(0) onkeypress="return ondeskkeypress(event)"onkeydown="return ondeskkeydown(event)"onkeyup="return ondeskkeyup(event)"></div><div style=margin-left:3px><input type=button id=connectbutton1 value=Connect onclick=connectDesktop(event,1) onkeypress=return!1 onkeydown=return!1 disabled> <input type=button id=connectbutton1h value="HW Connect"onclick=connectDesktop(event,2) onkeypress=return!1 onkeydown=return!1 disabled> <input type=button id=disconnectbutton1 value=Disconnect onclick=connectDesktop(event,0) onkeypress=return!1 onkeydown=return!1> <span id=deskstatus>Disconnected</span></div></div></div><div id=deskarea3 style="position:absolute;top:25px;width:100%;height:calc(100% - 50px)"><div id=deskarea3x style=background:#000;text-align:center;height:100%;position:relative><div id=DeskParent style=height:100%><canvas id=Desk width=640 height=200 style=width:100%;-ms-touch-action:none;margin-left:0 oncontextmenu=return!1 onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event) onmousewheel=dmousewheel(event)></canvas></div><div id=DeskTools style="position:absolute;width:400px;height:100%;background-color:gray;top:0;right:0;border-left:2px solid #d3d3d3;display:none"><a id=DeskToolsRefreshButton style=float:right;padding:3px;cursor:pointer onclick=refreshDeskTools()>Refresh</a><div id=DeskToolsBar style="position:absolute;padding:3px;border-radius:3px 3px 0 0;top:5px;left:4px;bottom:26px;background-color:#d3d3d3;cursor:pointer">Processes</div><div style=position:absolute;top:26px;left:4px;right:4px;bottom:4px;background-color:#d3d3d3;text-align:left><div style="border-bottom:1px solid #a9a9a9;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><div id=DeskToolsProcesses style=overflow-y:scroll;position:absolute;top:24px;bottom:0;width:100%></div></div></div></div></div><div id=deskarea4 style=position:absolute;bottom:0;width:100%;height:25px><div style=padding-top:2px;padding-bottom:2px;background:silver><div style=float:right;text-align:right><select id=termdisplays style=display:none onchange=deskSetDisplay(event) onclick=deskGetDisplayNumbers(event)></select>&nbsp; <span id=DeskToastButton><img src=images/icon-notify.png onclick=deviceToastFunction() height=16 width=16 style=padding-top:2px></span>&nbsp;</div><div><input id=deskActionsBtn type=button style=margin-left:3px onkeypress=return!1 onkeydown=return!1 value=Actions onclick=deviceActionFunction()> <input type=button value=Settings onkeypress=return!1 onkeydown=return!1 onclick=showDesktopSettings()> <input type=button onkeypress=return!1 onkeydown=return!1 value="Power Actions..."onclick=showPowerActionDlg() style=display:none> <input id=DeskSpecialKeys type=button value="Special Keys"onkeypress=return!1 onkeydown=return!1 onclick=sendSpecialKeys()> <input id=DeskSoftKeys type=button value=Keyboard onkeypress=return!1 onkeydown=return!1 onclick=toggleSoftKeys(1)> <label><span id=DeskControlSpan style=display:none><input id=DeskControl type=checkbox onkeypress=return!1 onkeydown=return!1>Input</span></label></div></div></div></div><div id=p10files style=overflow-y:scroll;position:absolute;top:55px;bottom:0;width:100%;display:none><table id=p13toolbar style=width:100%;height:111px cellpadding=0 cellspacing=0><tr><td style="background-color:silver;border-bottom:2px solid #000;padding:2px"><div style=float:right;text-align:right><input id=filesActionsBtn type=button onkeypress=return!1 onkeydown=return!1 value=Actions onclick=deviceActionFunction() style=margin-right:2px></div><div style=margin-left:2px><input id=p13AutoConnect value=AutoConnect onclick=autoConnectFiles(event) onkeypress=return!1 onkeydown=return!1 type=button style=display:none> <input id=p13Connect value=Connect onclick=connectFiles(event) onkeypress=return!1 onkeydown=return!1 type=button> <span id=p13Status>Disconnected</span></div><tr><td style=width:100%;background-color:#d3d9d6;text-align:left;padding:4px valign=bottom><div style=width:100%;text-align:center><input type=button style="width:calc(100%/5 - 5px)"id=p13FolderUp disabled onclick=p13folderup() value=Up> <input type=button style="width:calc(100%/5 - 5px)"id=p13SelectAllButton disabled onclick=p13selectallfile() value=SelectAll onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p13RenameFileButton disabled value=Rename onclick=p13renamefile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p13DeleteFileButton disabled value=Delete onclick=p13deletefile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p13NewFolderButton disabled value=Folder onclick=p13createfolder() onkeypress=return!1 onkeydown=return!1></div><div style=width:100%;text-align:center><input type=button style="width:calc(100%/5 - 5px)"id=p13UploadButton disabled value=Upload onclick=p13uploadFile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p13CutButton disabled value=Cut onclick=p13copyFile(1) onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p13CopyButton disabled value=Copy onclick=p13copyFile(0) onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p13PasteButton disabled value=Paste onclick=p13pasteFile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p13RefreshButton disabled value=Refresh onclick=p13folderup(9999) onkeypress=return!1 onkeydown=return!1></div><tr><td style=background-color:#e4e9e7;height:28px><table style=width:100%><tr><td id=p13currentpath style=overflow:hidden;padding-left:4px;padding-top:2px><td style=text-align:right;padding-right:4px><select id=p13sortdropdown onchange=p13updateFiles()><option value=1 selected>Sort by name<option value=2>Sort by size<option value=3>Sort by date<option value=4>Descend by name<option value=5>Descend by size<option value=6>Descend by date</select></table></table><div id=p13filetable style="width:100%;height:calc(100% - 133px);overflow:auto;-webkit-user-select:none"><span id=p13files></span></div><table id=p13toolbarBottom style=width:100%;height:22px;position:absolute;bottom:0 cellpadding=0 cellspacing=0><tr><td style=text-align:left;padding:3px;text-align:center;background-color:#d3d9d6>&nbsp;<span id=p13bottomstatus></span></table></div></div><div id=p20 style=display:none;position:absolute;bottom:0;top:0;width:100%><table cellspacing=0 style=margin:0;padding:0;border-spacing:0;border:0><tr style=padding:0><td style=padding:0;color:#c8c8c8;text-align:center;cursor:pointer width=60px valign=top onclick=goBack()><div style=padding:0;background-color:#036;width:10px;height:10px;float:right;border:0><div style="background-color:#fff;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid #fff;border-bottom:1px solid #fff"></div></div><div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">&#9664;</div><td onclick=p20editmesh(1)><img src=/images/meshicon50.png width=50 height=50><td onclick=p20editmesh(1)><div style=margin-left:5px><strong style=font-size:large><span id=p20meshName></span></strong><br></div></table><div id=p20info style=margin-left:8px;margin-right:8px></div></div></div></div><div id=footer style=height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0><table id=footerMenu cellpadding=0 cellspacing=0 style=height:32px;width:100%;color:#fff;cursor:pointer;table-layout:fixed></table></div></div><div id=dialog style="z-index:1000;background-color:#eee;box-shadow:0 0 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:5px;position:fixed;top:90px;width:300px;display:none"><div style="width:100%;background-color:#036;color:#fff;border-radius:5px 5px 0 0"><div id=id_dialogclose style=float:right;padding:5px;cursor:pointer onclick=setDialogMode()><b>X</b></div><div id=id_dialogtitle style=padding:5px></div><div style=width:100%;margin:6px></div></div><div style=margin-right:16px;margin-left:8px><div id=dialog1 style=margin:auto;text-align:center;margin:3px><div id=id_dialogMessage style=padding:10px></div></div><div id=dialog2 style=margin:auto;margin:3px><div id=id_dialogOptions></div></div><div id=dialog3 style=margin:auto;margin:3px><select id=deskkeys style=width:100%><option value=10>Ctrl+Alt+Del<option value=11>Tab<option value=5>Win<option value=0>Win+Down<option value=1>Win+Up<option value=2>Win+L<option value=3>Win+M<option value=4>Shift+Win+M<option value=6>Win+R<option value=7>Alt-F4<option value=8>Ctrl-W<option value=9>Alt-Tab</select></div><div id=dialog7 style=margin:auto;margin:3px><div id=d7meshkvm><h4 style="width:100%;border-bottom:1px solid gray">Agent Remote Desktop</h4><div style="margin:3px 0 3px 0"><select id=d7bitmapquality style=float:right;width:200px;height:20px dir=rtl></select><div style=height:20px>Quality</div></div><div style="margin:3px 0 3px 0"><select id=d7bitmapscaling style=float:right;width:200px;height:20px dir=rtl><option selected value=1024>100%<option value=896>87.5%<option value=768>75%<option value=640>62.5%<option value=512>50%<option value=384>37.5%<option value=256>25%<option value=128>12.5%</select><div style=height:20px>Scaling</div></div><div style="margin:3px 0 3px 0"><select id=d7framelimiter style=float:right;width:200px;height:20px dir=rtl><option selected value=50>Fast<option value=100>Medium<option value=400>Slow<option value=1000>Very slow</select><div style=height:20px>Rate</div></div></div><div id=d7amtkvm><h4 style="width:100%;border-bottom:1px solid gray">Intel&reg; AMT Hardware KVM</h4><div style=height:26px><select id=d7desktopmode style=float:right;width:200px><option value=1>RLE8, Fastest<option value=2>RLE16, Recommended<option value=3>RAW8, Slow<option value=4>RAW16, Very Slow</select><div>Encoding</div></div><div style=height:60px><div style="float:right;border:1px solid #666;width:200px;height:60px;overflow-y:scroll;background-color:#fff"><label><input type=checkbox id=d7showfocus>Show Focus Tool</label><br><label><input type=checkbox id=d7showcursor>Show Local Mouse Cursor</label><br></div><div>Other</div></div></div></div></div><div id=idx_dlgButtonBar style=padding:10px;margin-bottom:20px><input id=idx_dlgCancelButton type=button value=Cancel style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)> <input id=idx_dlgOkButton type=button value=OK style=float:right;width:80px onclick=dialogclose(1)></div></div><div id=topMenu style="z-index:1000;background-color:#eee;box-shadow:0 0 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:0 0 5px 5px;position:fixed;top:50px;right:5px;width:170px;display:none"><div style="padding:12px;border-top:1px solid gray;color:#000;cursor:pointer"onclick=topMenu(2)>My Files</div><div style="padding:12px;border-top:1px solid gray;color:#000;cursor:pointer"onclick=topMenu(1)>My Account</div><div id=logoutMenuOption><a href=/logout><div style="padding:12px;border-top:1px solid gray;color:#000;cursor:pointer">Logout</div></a></div></div><iframe name=fileUploadFrame style=display:none></iframe><script>"use strict";var webState="{{{webstate}}}";for(var i in""!=webState&&(webState=JSON.parse(decodeURIComponent(webState))),webState)localStorage.setItem(i,webState[i]);webState.loctag||localStorage.removeItem("loctag");var files,args=parseUriArgs(),debugLevel=parseInt("{{{debuglevel}}}"),features=parseInt("{{{features}}}"),sessionTime=parseInt("{{{sessiontime}}}"),domain="{{{domain}}}",domainUrl="{{{domainurl}}}",authCookie="{{{authCookie}}}",authRelayCookie="{{{authRelayCookie}}}",authCookieRenewTimer=null,meshserver=null,xdr=null,serverinfo=null,nodes=[],meshes={},filetree={},userinfo=null,users=(serverinfo=null,null),nodeShortIdent=0,serverPublicNamePort="{{{serverDnsName}}}:{{{serverPublicPort}}}",debugmode=!1,attemptWebRTC=0!=(128&features),StatusStrs=["Disconnected","Connecting...","Setup...","Connected","Intel&reg; AMT Connected"],passRequirements="{{{passRequirements}}}";""!=passRequirements&&(passRequirements=JSON.parse(decodeURIComponent(passRequirements)));var sessionActivity=Date.now();function startup(){if(0==(32&features)){var e=null;try{e=top.location.toString().toLowerCase()}catch(e){}if(top!=self&&(null==e||0==top.active))return void(top.location=self.location)}if(!args.locale){var t=getstore("loctag",0);null!=t&&"*"!=t&&(args.locale=t)}(window.onresize=center)(),QV("changeEmailId",0==(2097152&features)),QH("p1message","Connecting..."),go(1),(meshserver=MeshServerCreateControl(domainUrl,authCookie)).onStateChanged=onStateChanged,meshserver.onMessage=onMessage,meshserver.Start();var o=localStorage.getItem("desktopsettings");null!=o&&(desktopsettings=JSON.parse(o)),applyDesktopSettings()}function onStateChanged(e,t,o,n){if(0==t){if(setDialogMode(0),go(0),"noauth"==n)return void QH("p0span","Unable to perform authentication");2==o?setTimeout(serverPoll,5e3):QH("p0span","Unable to connect web socket"),null!=authCookieRenewTimer&&(clearInterval(authCookieRenewTimer),authCookieRenewTimer=null)}else 2==t&&(meshserver.send({action:"meshes"}),meshserver.send({action:"nodes"}),meshserver.send({action:"files"}),xxcurrentView<2&&go(2),authCookieRenewTimer=setInterval(function(){meshserver.send({action:"authcookie"})},18e5));QV("topMenuIcon",2==t)}function serverPoll(){xdr=null;try{xdr=new XDomainRequest}catch(e){}(xdr=xdr||new XMLHttpRequest).open("HEAD",window.location.href),xdr.timeout=15e3,xdr.onload=function(){reload()},xdr.onerror=xdr.ontimeout=function(){setTimeout(serverPoll,1e4)},xdr.send()}function updateSelf(){if(QV("verifyEmailId",!0!==userinfo.emailVerified&&null!=userinfo.email&&1==serverinfo.emailcheck),QV("manageAuthApp",4096&features),QV("manageOtp",0!=(4096&features)&&(1==userinfo.otpsecret||0<userinfo.otphkeys)),QV("p3createMeshLink1",!1),QV("p3createMeshLink2",!1),"number"==typeof userinfo.passchange)if(-1==userinfo.passchange)QH("p2nextPasswordUpdateTime"," - Reset on next login.");else if(null!=passRequirements&&"number"==typeof passRequirements.reset){var e=userinfo.passchange+86400*passRequirements.reset-Math.floor(Date.now()/1e3);e<0?QH("p2nextPasswordUpdateTime"," - Reset on next login."):e<3600?QH("p2nextPasswordUpdateTime",format(" - Reset in {0} minute{1}.",Math.floor(e/60),addLetterS(Math.floor(e/60)))):e<86400?QH("p2nextPasswordUpdateTime",format(" - Reset in {0} hour{1}.",Math.floor(e/3600),addLetterS(Math.floor(e/3600)))):QH("p2nextPasswordUpdateTime",format(" - Reset in {0} day{1}."),Math.floor(e/86400),addLetterS(Math.floor(e/86400)))}}function addLetterS(e){return 1<e?"s":""}function setSessionActivity(){sessionActivity=Date.now()}function checkIdleSessionTimeout(){Date.now()-sessionActivity>serverinfo.timeout&&(window.location.href="logout")}function onMessage(e,t){switch(t.action){case"serverinfo":(serverinfo=t.serverinfo).timeout&&(setInterval(checkIdleSessionTimeout,1e4),checkIdleSessionTimeout()),QV("p3AccountActions",0==(4&features)&&0==serverinfo.domainauth),QV("logoutMenuOption",0==(4&features)&&0==serverinfo.domainauth);break;case"authcookie":authCookie=t.cookie,authRelayCookie=t.rcookie;break;case"userinfo":userinfo=t.userinfo,QH("p3userName",userinfo.name),updateSelf();break;case"users":for(var o in users={},t.users)users[t.users[o]._id]=t.users[o];updateUsers();break;case"wssessioncount":wssessions=t.wssessions,updateUsers();break;case"meshes":for(var o in meshes={},t.meshes)meshes[t.meshes[o]._id]=t.meshes[o];updateMeshes(),updateDevices();break;case"files":filetree=setupBackPointers(t.filetree),updateFiles();break;case"nodes":for(var o in nodes=[],t.nodes)for(var n in t.nodes[o])meshes[o]?(t.nodes[o][n].namel=t.nodes[o][n].name.toLowerCase(),t.nodes[o][n].rname?t.nodes[o][n].rnamel=t.nodes[o][n].rname.toLowerCase():t.nodes[o][n].rnamel=t.nodes[o][n].namel,t.nodes[o][n].meshnamel=meshes[o].name.toLowerCase(),t.nodes[o][n].meshid=o,t.nodes[o][n].state=t.nodes[o][n].state?t.nodes[o][n].state:0,t.nodes[o][n].desc=t.nodes[o][n].desc,t.nodes[o][n].icon||(t.nodes[o][n].icon=1),t.nodes[o][n].ident=++nodeShortIdent,nodes.push(t.nodes[o][n])):console.log("Invalid mesh (1): "+o);updateDevices(),0==xxcurrentView&&go(parseInt("{{viewmode}}")),gotoDevice("{{currentNode}}",parseInt("{{viewmode}}"));break;case"powertimeline":if(t.nodeid!=powerTimelineReq)break;powerTimelineNode=t.nodeid,powerTimeline=t.timeline,powerTimelineUpdate=Date.now()+3e5,currentNode._id==t.nodeid&&drawDeviceTimeline();break;case"otpauth-request":if(2==xxdialogMode&&"otpauth-request"==xxdialogTag){var i=t.secret;52==i.length?i=i.split(/(.............)/).filter(Boolean).join(" "):32==i.length&&(i=(i=i.split(/(....)/).filter(Boolean).join(" ")).substring(0,20)+"<br/>"+i.substring(20)),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="'+t.secret+'" style=font-size:15px>'+i+'</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>'),QV("idx_dlgOkButton",!0),QE("idx_dlgOkButton",!1),Q("d2otpauthinput").focus()}break;case"otpauth-setup":if(xxdialogMode)return;setDialogMode(2,"Authenticator App",1,null,t.success?"<b style=color:green>2-step login activation successful</b>. You will now need a valid token to login again.":"<b style=color:red>2-step login activation failed</b>. Clear the secret from the application and try again. You only have a few minutes to enter the proper code.");break;case"otpauth-clear":if(xxdialogMode)return;setDialogMode(2,"Authenticator App",1,null,t.success?"<b style=color:green>2-step login activation removed</b>. You can reactivate this feature at any time.":"<b style=color:red>2-step login activation removal failed</b>. Try again.");break;case"otpauth-getpasswords":if(xxdialogMode)return;var a="One time tokens can be used as secondary authentication. Generate a set, print them and keep them in a safe place.";if(a+="<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>",t.passwords){var s=0;for(var l in t.passwords){++s%2&&(a+="<tr>");for(var r=""+t.passwords[l].p;r.length<8;)r="0"+r;!0===t.passwords[l].u?a+="<td>"+r.substring(0,4)+"&nbsp;"+r.substring(4):a+="<td><strike style=color:#BBB>"+r.substring(0,4)+"&nbsp;"+r.substring(4)}}else a+="<tr><td>No Active Tokens";a+="</table></div></div><br />",a+="<div><input type=button value='Close' onclick=setDialogMode(0) style=float:right></input>",a+="<input type=button value='New Tokens' onclick='account_manageOtp(1);'></input>",null!=t.passwords&&(a+="<input type=button value='Clear' onclick='account_manageOtp(2);'></input>"),setDialogMode(2,"Manage Backup Codes",8,null,a+="</div><br />","otpauth-manage");break;case"event":if(t.event.noact)break;switch(t.event.action){case"userWebState":if(null!=localStorage){var d=JSON.parse(t.event.state);for(var l in d)localStorage.setItem(l,d[l]);null!=d.loctag&&d.loctag!=oldLoctag&&(null!=d.loctag?args.locale=d.loctag:delete args.locale,updateDevices(),updateMeshes())}break;case"accountchange":if(userinfo.name==t.event.account.name){var p=t.event.account.siteadmin?t.event.account.siteadmin:0,c=userinfo.siteadmin?userinfo.siteadmin:0;(t.event.account.quota!=userinfo.quota||0==(8&userinfo.siteadmin)&&0!=(8&t.event.account.siteadmin))&&meshserver.send({action:"files"}),userinfo=t.event.account,c!=p&&updateSiteAdmin(),updateSelf()}break;case"createmesh":null!=t.event.links[userinfo._id]&&(meshes[t.event.meshid]={_id:t.event.meshid,name:t.event.name,mtype:t.event.mtype,desc:t.event.desc,links:t.event.links},updateMeshes(),updateDevices(),meshserver.send({action:"files"}));break;case"meshchange":if(null==meshes[t.event.meshid])meshes[t.event.meshid]={_id:t.event.meshid,name:t.event.name,mtype:t.event.mtype,desc:t.event.desc,links:t.event.links},meshserver.send({action:"nodes"});else{if(meshes[t.event.meshid].name!=t.event.name)for(var l in meshes[t.event.meshid].name=t.event.name,nodes)nodes[l].meshid==t.event.meshid&&(nodes[l].meshnamel=t.event.name.toLowerCase());if(meshes[t.event.meshid].desc=t.event.desc,meshes[t.event.meshid].links=t.event.links,null==meshes[t.event.meshid].links[userinfo._id]){20==xxcurrentView&&currentMesh==meshes[t.event.meshid]&&go(2),delete meshes[t.event.meshid];var u=[];for(var l in nodes)nodes[l].meshid!=t.event.meshid&&u.push(nodes[l]);nodes=u,10<=xxcurrentView&&xxcurrentView<20&&currentNode&&currentNode.meshid==t.event.meshid&&(setDialogMode(0),go(2))}}updateMeshes(),updateDevices(),meshserver.send({action:"files"}),20==xxcurrentView&&currentMesh._id==t.event.meshid&&p20updateMesh();break;case"deletemesh":meshes[t.event.meshid]&&(delete meshes[t.event.meshid],updateMeshes(),meshserver.send({action:"files"}));u=[];for(var l in nodes)nodes[l].meshid!=t.event.meshid&&u.push(nodes[l]);nodes=u,updateDevices(),20<=xxcurrentView&&xxcurrentView<30&&currentMesh._id==t.event.meshid&&(setDialogMode(0),go(2)),10<=xxcurrentView&&xxcurrentView<20&&currentNode&&currentNode.meshid==t.event.meshid&&(setDialogMode(0),go(2));break;case"addnode":var m=t.event.node;if(!meshes[m.meshid])break;if(null!=getNodeFromId(m._id))break;m.namel=m.name.toLowerCase(),m.rname?m.rnamel=m.rname.toLowerCase():m.rnamel=m.namel,m.meshnamel=meshes[m.meshid].name.toLowerCase(),m.state=0,m.icon||(m.icon=1),m.ident=++nodeShortIdent,nodes.push(m),updateDevices();break;case"removenode":var h=-1;for(var l in nodes)if(nodes[l]._id==t.event.nodeid){h=l;break}if(-1!=h){m=nodes[h];currentNode==m&&(10<=xxcurrentView&&xxcurrentView<20&&(setDialogMode(0),go(2)),currentNode=null),nodes.splice(h,1),updateDevices()}break;case"changenode":h=-1;for(var l in nodes)if(nodes[l]._id==t.event.nodeid){h=l;break}if(-1!=h)(m=nodes[h]).name=t.event.node.name,m.rname=t.event.node.rname,m.host=t.event.node.host,m.desc=t.event.node.desc,m.publicip=t.event.node.publicip,m.iploc=t.event.node.iploc,m.wifiloc=t.event.node.wifiloc,m.gpsloc=t.event.node.gpsloc,m.tags=t.event.node.tags,m.userloc=t.event.node.userloc,null!=t.event.node.agent&&(null==m.agent&&(m.agent={}),null!=t.event.node.agent.ver&&(m.agent.ver=t.event.node.agent.ver),null!=t.event.node.agent.id&&(m.agent.id=t.event.node.agent.id),null!=t.event.node.agent.caps&&(m.agent.caps=t.event.node.agent.caps),null!=t.event.node.agent.core?m.agent.core=t.event.node.agent.core:m.agent.core&&delete m.agent.core,m.agent.tag=t.event.node.agent.tag),null!=t.event.node.intelamt&&(null==m.intelamt&&(m.intelamt={}),null!=t.event.node.intelamt.state&&(m.intelamt.state=t.event.node.intelamt.state),null!=t.event.node.intelamt.host&&(m.intelamt.user=t.event.node.intelamt.host),null!=t.event.node.intelamt.user&&(m.intelamt.user=t.event.node.intelamt.user),null!=t.event.node.intelamt.tls&&(m.intelamt.tls=t.event.node.intelamt.tls),null!=t.event.node.intelamt.ver&&(m.intelamt.ver=t.event.node.intelamt.ver),null!=t.event.node.intelamt.tag&&(m.intelamt.tag=t.event.node.intelamt.tag),null!=t.event.node.intelamt.uuid&&(m.intelamt.uuid=t.event.node.intelamt.uuid),null!=t.event.node.intelamt.realm&&(m.intelamt.realm=t.event.node.intelamt.realm)),m.namel=m.name.toLowerCase(),m.rname?m.rnamel=m.rname.toLowerCase():m.rnamel=m.namel,t.event.node.icon&&(m.icon=t.event.node.icon),refreshDevice(m._id),updateDevices();break;case"nodemeshchange":h=-1;for(var l in nodes)if(nodes[l]._id==t.event.nodeid){h=l;break}if(-1!=h){m=nodes[h];null==meshes[t.event.newMeshId]?(currentNode==m&&(10<=xxcurrentView&&xxcurrentView<20&&(setDialogMode(0),go(2)),currentNode=null),nodes.splice(h,1)):(m.meshid=t.event.newMeshId,m.meshnamel=meshes[t.event.newMeshId].name.toLowerCase()),updateDevices(),refreshDevice(t.event.nodeid)}else{m=t.event.node;if(!meshes[m.meshid])break;m.namel=m.name.toLowerCase(),m.rname?m.rnamel=m.rname.toLowerCase():m.rnamel=m.namel,m.meshnamel=meshes[m.meshid].name.toLowerCase(),m.state=0,m.icon||(m.icon=1),m.ident=++nodeShortIdent,nodes.push(m),updateDevices()}break;case"nodeconnect":h=-1;for(var l in nodes)if(nodes[l]._id==t.event.nodeid){h=l;break}if(-1!=h)(m=nodes[h]).conn=t.event.conn,m.pwr=t.event.pwr,updateDevices();break;case"login":null!=users&&users["user/"+domain+"/"+t.event.username.toLowerCase()]&&(users["user/"+domain+"/"+t.event.username.toLowerCase()].login=t.event.time)}}}function topMenu(e){null!=xxdialogMode&&0!=xxdialogMode&&999!=xxdialogMode||(void 0===e?1==("none"==QS("topMenu").display)?0!=xxdialogMode&&null!=xxdialogMode||(QV("topMenu",!0),xxdialogMode=999):(QV("topMenu",!1),xxdialogMode=0):(QV("topMenu",!1),xxdialogMode=0,1==e&&3!=xxcurrentView&&goForward("account"),2==e&&5!=xxcurrentView&&goForward("files")))}var filetreelinkpath,backStack=[];function goBack(){xxdialogMode||(0<backStack.length&&backStack.pop(),goStack())}function goForward(e){xxdialogMode||(backStack.push(e),goStack())}function goStack(){if(0!=backStack.length){var e=backStack[backStack.length-1],t=e.split("/")[0];"node"==t&&(setupDeviceMenu(0),gotoDevice(e)),"mesh"==t&&gotoMesh(e),"account"==t&&go(3),"devices"==t&&go(2),"files"==t&&go(5)}else go(2)}function updateFooterMenu(e){for(;null!=e&&e.length<3;)e.push({n:""});var t="",o="";if(null!=e)for(var n in e)t+='<td style="cursor:pointer'+(""==o?"":";border-left:solid 1px white")+'" onclick="'+e[n].f+'">'+e[n].n,o=e[n].n;QH("footerMenu","<tr>"+t)}function account_manageAuthApp(){xxdialogMode||0==(4096&features)||(1==userinfo.otpsecret?account_removeOtp():account_addOtp())}function account_addOtp(){xxdialogMode||1==userinfo.otpsecret||0==(4096&features)||(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"),meshserver.send({action:"otpauth-request"}))}function account_addOtpCheck(e){var t=6==Q("d2otpauthinput").value.length;QE("idx_dlgOkButton",t),e&&13==e.keyCode&&t&&dialogclose(1)}function account_removeOtp(){xxdialogMode||1!=userinfo.otpsecret||0==(4096&features)||setDialogMode(2,"Authenticator App",3,function(){meshserver.send({action:"otpauth-clear"})},"Confirm removal of authenticator application 2-step login?")}function account_manageOtp(e){2==xxdialogMode&&"otpauth-manage"==xxdialogTag&&dialogclose(0),xxdialogMode||1!=userinfo.otpsecret||0==(4096&features)||meshserver.send({action:"otpauth-getpasswords",subaction:e})}function account_showVerifyEmail(){xxdialogMode||1==userinfo.emailVerified||1!=serverinfo.emailcheck||setDialogMode(2,"Email Verification",3,account_showVerifyEmailEx,"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.")}function account_showVerifyEmailEx(){meshserver.send({action:"verifyemail",email:userinfo.email})}function account_showChangeEmail(){xxdialogMode||(setDialogMode(2,"Email Address Change",3,account_changeEmail,addHtmlValue("Email","<input id=dp3email style=width:170px maxlength=256 onchange=account_validateEmail() onkeyup=account_validateEmail(event) />")),null!=userinfo.email&&(Q("dp3email").value=userinfo.email),account_validateEmail(),Q("dp3email").focus())}function account_validateEmail(e,t){QE("idx_dlgOkButton",validateEmail(Q("dp3email").value)&&Q("dp3email").value!=userinfo.email),null!=e&&13==e.keyCode&&dialogclose(1)}function account_changeEmail(){meshserver.send({action:"changeemail",email:Q("dp3email").value})}function account_showDeleteAccount(){if(!xxdialogMode){var e="<form method=post><table style=margin-left:10px><input type=hidden name=action value=deleteaccount /><input type=hidden name=authcookie value="+authCookie+" /><tr>";e+="<td align=right>Password:</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>",e+="</tr><tr><td align=right>Password:</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>",e+="</tr></table><div style=padding:10px;margin-bottom:4px>",e+='<input id=account_dlgCancelButton type=button value="Cancel" style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>',e+='<input id=account_dlgOkButton type=submit value="OK" style="float:right;width:80px" onclick=dialogclose(1)>',setDialogMode(2,"Delete Account",0,null,e+="</div><br /></form>"),account_validateDeleteAccount(),Q("apassword1").focus()}}function account_showChangePassword(){if(xxdialogMode)return!1;var e="<table style=margin-left:10px>";if(e+="<tr><td align=right>"+nobreak("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>",e+="<tr><td align=right>"+nobreak("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>",e+="<tr><td align=right>"+nobreak("New password:")+"</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /></td></tr>",65536&features&&(e+="<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>"),e+="</table>",passRequirements){var t=[],o=0;for(var n in passRequirements)"reset"!=n&&"hint"!=n&&(t.push(n+":"+passRequirements[n]),o++);0<o&&(e+="<br /><span style=font-size:x-small>"+format("Requirements: {0}.",t.join(", "))+"</span>")}return setDialogMode(2,"Change Password",3,account_showChangePasswordEx,e+="<br />"),Q("apassword0").focus(),account_validateNewPassword(),!1}function account_showChangePasswordEx(){if(Q("apassword1").value==Q("apassword2").value){var e={action:"changepassword",oldpass:Q("apassword0").value,newpass:Q("apassword1").value};65536&features&&(e.hint=Q("apasswordhint").value),meshserver.send(e)}}function account_createMesh(){if(!xxdialogMode)if(4294967295==userinfo.siteadmin||0==(64&userinfo.siteadmin))if(!0===userinfo.emailVerified||1!=serverinfo.emailcheck||4294967295==userinfo.siteadmin)if(!(262144&features)||1==userinfo.otpsecret||0<userinfo.otphkeys||0<userinfo.otpkeys){var e=addHtmlValue("Name","<input id=dp3meshname style=width:170px maxlength=64 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate() />");e+=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>"),setDialogMode(2,"Create Device Group",3,account_createMeshEx,e+=addHtmlValue("Description","<div style=width:170px;margin:0;padding:0><textarea id=dp3meshdesc maxlength=1024 style=width:100%;resize:none></textarea></div>")),account_validateMeshCreate(),Q("dp3meshname").focus()}else 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.');else setDialogMode(2,"Account Security",1,null,'Unable to access a device until a email address is verified. This is required for password recovery. Go to the "My Account" to change and verify an email address.');else setDialogMode(2,"New Device Group",1,null,"This account does not have the rights to create a new device group.")}function account_validateMeshCreate(){QE("idx_dlgOkButton",0<Q("dp3meshname").value.length)}function account_createMeshEx(e,t){meshserver.send({action:"createmesh",meshname:Q("dp3meshname").value,meshtype:Q("dp3meshtype").value,desc:Q("dp3meshdesc").value})}function account_validateDeleteAccount(){QE("account_dlgOkButton",0<Q("apassword1").value.length&&Q("apassword1").value==Q("apassword2").value)}function account_validateNewPassword(){var e="",t=0<Q("apassword0").value.length&&0<Q("apassword1").value.length&&Q("apassword1").value==Q("apassword2").value&&Q("apassword0").value!=Q("apassword1").value;if(65536&features&&Q("apasswordhint").value==Q("apassword1").value&&(t=!1),""!=Q("apassword1").value)if(null==passRequirements||""==passRequirements){var o=checkPasswordStrength(Q("apassword1").value);e=80<=o?"<span style=color:green>Strong<span>":60<=o?"<span style=color:blue>&#9679;<span>":"<span style=color:red>&#9679;<span>"}else{0==checkPasswordRequirements(Q("apassword1").value,passRequirements)&&(t=!1,e="<span style=color:red>Policy<span>")}QH("dxPassWarn",e),QE("idx_dlgOkButton",t)}function checkPasswordStrength(e){var t=0,o={},n=0,i={digits:/\d/.test(e),lower:/[a-z]/.test(e),upper:/[A-Z]/.test(e),nonWords:/\W/.test(e)};if(!e)return 0;for(var a=0;a<e.length;a++)o[e[a]]=(o[e[a]]||0)+1,t+=5/o[e[a]];for(var s in i)n+=1==i[s]?1:0;return parseInt(t+10*(n-1))}function checkPasswordRequirements(e,t){if(null==t||""==t||"object"!=typeof t)return!0;if(t.min&&e.length<t.min)return!1;if(t.max&&e.length>t.max)return!1;for(var o=0,n=0,i=0,a=0,s=0;s<e.length;s++)/\d/.test(e[s])&&o++,/[a-z]/.test(e[s])&&n++,/[A-Z]/.test(e[s])&&i++,/\W/.test(e[s])&&a++;return!(t.num&&o<t.num)&&(!(t.lower&&n<t.lower)&&(!(t.upper&&i<t.upper)&&!(t.nonalpha&&a<t.nonalpha)))}function updateMeshes(){var e="",t=0;for(i in meshes){t++;var o=meshes[i].links[userinfo._id].rights,n="Partial Rights";4294967295==o?n="Full Administrator":0==o&&(n="No Rights"),e+="<div style=cursor:pointer onclick=goForward('"+i+"')>",e+='<div style="float:left;margin-left:4px"><img src="/images/meshicon50.png" width=50 height=50 /></div>',e+='<div style="width:auto;height:40px;background-color:lightgray;margin-top:5px;margin-bottom:5px;margin-left:60px;padding-top:5px;padding-bottom:5px;border-radius:8px 0px 0px 8px">',e+="<div><div style=padding-left:12px;padding-top:2px><b>"+EscapeHtml(meshes[i].name)+"</b></div><div style=padding-left:12px;padding-top:3px;color:gray>"+n+"</div></div>",e+="</div></div>"}QH("p3meshes",e),QV("p3noMeshFound",0==t)}function gotoMesh(e){null==(currentMesh=meshes[e])&&goBack(),p20updateMesh(),go(20)}var sortorder,filetreelocation=[];function p5refreshFiles(){meshserver.send({action:"files"})}function updateFiles(){if(QV("MainMenuMyFiles",0==(8&features)),0==(8&features)){for(var e,t="",o="",n="<a style=cursor:pointer onclick=p5folderup(0)>Root</a>",i="Root",a=filetree,s=1,l=[],r=filetreelinkpath,d=[],p=document.getElementsByName("fc"),c=0;c<p.length;c++)p[c].checked&&d.push(p[c].value);for(var c in filetreelinkpath="",filetreelocation){if(null==a.f||null==a.f[filetreelocation[c]])break;if(l.push(filetreelocation[c]),i+=" / "+filetreelocation[c],1==s){var u=filetreelocation[c].split("/");e=window.location+u[0]+"files/"+u[2],filetreelinkpath+=filetreelocation[c]}else""!=filetreelinkpath&&(filetreelinkpath+="/"+filetreelocation[c],2<s&&(e+="/"+filetreelocation[c]));n+=" / <a style=cursor:pointer onclick=p5folderup("+s+")>"+(null!=(a=a.f[filetreelocation[c]]).n?a.n:filetreelocation[c])+"</a>",s++}filetreelocation=l;var m=i.toLowerCase().startsWith("root / "+userinfo._id+" / public"),h=p5sort_files(a.f);for(var c in h){var f,g=h[c],v=g.n;f=40<(f=v).length?EscapeHtml(v.substring(0,40))+"...":EscapeHtml(v),v=EscapeHtml(v);var k="";null!=g.s&&(k=getFileSizeStr(g.s));var y="";if(g.t<3||4==g.t){y="<div class=filelist file=999><input file=999 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value='"+v+"'>&nbsp;<span style=float:right;padding-right:4px>"+(1==g.t||4==g.t?p5getQuotabar(g):"")+"</span><span><div class=fileIcon"+g.t+'></div><a style=cursor:pointer onclick=p5folderset("'+encodeURIComponent(g.nx)+'")>'+f+"</a></span></div>"}else{var w=f,b="";m&&(b=" (<a style=cursor:pointer onclick='p5showPublicLink(\""+e+"/"+g.nx+"\")'>Link</a>)"),0<g.s&&(w='<a rel="noreferrer noopener" target="_blank" href="downloadfile.ashx?link='+encodeURIComponent(filetreelinkpath+"/"+g.nx)+'">'+f+"</a>"+b),y="<div class=filelist file=3><input file=3 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value='"+g.nx+"'>&nbsp;<span style=float:right;padding-right:4px>"+k+"</span><span><div class=fileIcon"+g.t+"></div>"+w+"</span></div>"}g.t<3?t+=y:o+=y}if(QH("p5rightOfButtons",p5getQuotabar(a)),QH("p5files",t+o),QH("p5currentpath",n),QE("p5FolderUp",0!=filetreelocation.length),QV("p5PublicShare",m),r==filetreelinkpath){p=document.getElementsByName("fc");for(c=0;c<p.length;c++)p[c].checked=0<=d.indexOf(p[c].value)}p5setActions()}}function getNiceSize(e){return e<=0?"Storage exceed":e<2048?format("{0}b left",e):e<2097152?format("{0}k left",Math.round(e/1024)):e<2147483648?format("{0}m left",Math.round(e/1024/1024)):format("{0}g left",Math.round(e/1024/1024/1024))}function p5getQuotabar(e){for(;1<e.t&&4!=e.t;)e=e.parent;return 1!=e.t&&4!=e.t||null==e.maxbytes?"":getNiceSize(e.maxbytes-e.s)+" <progress style=height:10px;width:100px value="+e.s+" max="+e.maxbytes+" />"}function p5showPublicLink(e){setDialogMode(2,"Public Link",1,null,'<input type=text style=width:100% value="'+e+'" readonly />')}function p5sort_filename(e,t){return e.ln>t.ln?1*sortorder:e.ln<t.ln?-1*sortorder:0}function p5sort_timestamp(e,t){return e.d>t.d?1*sortorder:e.d<t.d?-1*sortorder:0}function p5sort_bysize(e,t){return e.s==t.s?p5sort_filename(e,t):(e.s-t.s)*sortorder}function p5sort_files(e){var t=[],o=Q("p5sortdropdown").value;for(var n in e)e[n].nx=n,null==e[n].n&&(e[n].n=n),e[n].ln=e[n].n.toLowerCase(),t.push(e[n]);return sortorder=1,3<o&&(sortorder=-1,o-=3),1==o?t.sort(p5sort_filename):2==o?t.sort(p5sort_bysize):3==o&&t.sort(p5sort_timestamp),t}function p5setActions(){var e=getFileSelCount(),t=getFileCount(),o=getFileSelCount(!1);QE("p5DeleteFileButton",0<e&&0<filetreelocation.length),QE("p5NewFolderButton",0<filetreelocation.length),QE("p5UploadButton",0<filetreelocation.length),QE("p5RenameFileButton",1==e&&0<filetreelocation.length),QE("p5SelectAllButton",0<t),Q("p5SelectAllButton").value=0<e?"None":"All",QE("p5CutButton",0<o&&e==o),QE("p5CopyButton",0<o&&e==o),QE("p5PasteButton",null!=p5clipboard&&0<p5clipboard.length&&0<filetreelocation.length)}function getFileSelCount(e){for(var t=0,o=document.getElementsByName("fc"),n=0;n<o.length;n++)!o[n].checked||0==e&&"3"!=o[n].attributes.file.value||t++;return t}function getFileSelDirCount(){for(var e=0,t=document.getElementsByName("fc"),o=0;o<t.length;o++)t[o].checked&&"999"==t[o].attributes.file.value&&e++;return e}function getFileCount(){return document.getElementsByName("fc").length}function p5selectallfile(){for(var e=0==getFileSelCount(),t=document.getElementsByName("fc"),o=0;o<t.length;o++)t[o].checked=e;p5setActions()}function setupBackPointers(e){if(null!=e.f){var t=0,o=0;for(var n in e.f)setupBackPointers(e.f[n]),(e.f[n].parent=e).f[n].s&&(t+=e.f[n].s),e.f[n].c&&(o+=e.f[n].c),3==e.f[n].t&&o++;e.s=t,e.c=o}return e}function getFileSizeStr(e){return 1==e?"1 byte":format("{0} bytes",e)}function p5folderup(e){if(null==e)filetreelocation.pop();else for(;filetreelocation.length>e;)filetreelocation.pop();return updateFiles(),!1}function p5folderset(e){return filetreelocation.push(decodeURIComponent(e)),updateFiles(),!1}function p5createfolder(){setDialogMode(2,"New Folder",3,p5createfolderEx,"<input type=text id=p5renameinput maxlength=64 onkeyup=p5fileNameCheck(event) style=width:100% />"),focusTextBox("p5renameinput"),p5fileNameCheck()}function p5createfolderEx(){meshserver.send({action:"fileoperation",fileop:"createfolder",path:filetreelocation,newfolder:Q("p5renameinput").value})}function p5deletefile(){var e=getFileSelCount(),t=0<getFileSelDirCount()?"<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,1<e?format("Delete {0} selected items?",e)+t:"Delete selected item?"+t)}function p5deletefileEx(){for(var e=[],t=document.getElementsByName("fc"),o=0;o<t.length;o++)t[o].checked&&e.push(t[o].value);meshserver.send({action:"fileoperation",fileop:"delete",path:filetreelocation,delfiles:e,rec:Q("p5recdeleteinput").checked})}function p5renamefile(){for(var e,t=document.getElementsByName("fc"),o=0;o<t.length;o++)t[o].checked&&(e=t[o].value);setDialogMode(2,"Rename",3,p5renamefileEx,'<input type=text id=p5renameinput maxlength=64 onkeyup=p5fileNameCheck(event) style=width:100% value="'+e+'" />',{action:"fileoperation",fileop:"rename",path:filetreelocation,oldname:e}),focusTextBox("p5renameinput"),p5fileNameCheck()}function p5renamefileEx(e,t){t.newname=Q("p5renameinput").value,meshserver.send(t)}function p5fileNameCheck(e){var t=isFilenameValid(Q("p5renameinput").value);QE("idx_dlgOkButton",t),1==t&&e&&13==e.keyCode&&dialogclose(1)}var isFilenameValid=function(){var t=/^[^\\/:\*\?"<>\|]+$/,o=/^\./,n=/^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i;return function(e){return t.test(e)&&!o.test(e)&&!n.test(e)&&"."!=e[0]}}();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")}function p5uploadFileEx(){Q("p5loginSubmit").click()}function updateUploadDialogOk(e){QE("idx_dlgOkButton",""!=Q(e).value)}var p5clipboard=null,p5clipboardFolder=null,p5clipboardCut=0;function p5copyFile(e){var t=document.getElementsByName("fc");p5clipboard=[],p5clipboardCut=e,p5clipboardFolder=Clone(filetreelocation);for(var o=0;o<t.length;o++)t[o].checked&&"3"==t[o].attributes.file.value&&p5clipboard.push(t[o].value);p5updateClipview()}function p5pasteFile(){var e="";null!=p5clipboard&&0<p5clipboard.length&&(e=format("Confim {0} of {1} entrie{2} to this location?",0==p5clipboardCut?"copy":"move",p5clipboard.length,1<p5clipboard.length?"s":"")),setDialogMode(2,"Paste",3,p5pasteFileEx,e)}function p5pasteFileEx(){meshserver.send({action:"fileoperation",fileop:0==p5clipboardCut?"copy":"move",scpath:p5clipboardFolder,path:filetreelocation,names:p5clipboard}),p5folderup(999),1==p5clipboardCut&&(p5clipboardFolder=p5clipboard=null,p5clipboardCut=0,p5updateClipview())}function p5updateClipview(){var e="";null!=p5clipboard&&0<p5clipboard.length&&(e=format("Holding {0} entrie{1} for {2}",p5clipboard.length,1<p5clipboard.length?"s":"",0==p5clipboardCut?"copy":"move")+', <a href=# onclick="return p5clearClip()" style=cursor:pointer>Clear</a>.'),QH("p5bottomstatus",e),p5setActions()}function p5clearClip(){return p5clipboardFolder=p5clipboard=null,p5clipboardCut=0,p5updateClipview(),!1}function p5fileDragDrop(e){if(haltEvent(e),QV("bigfail",!1),QV("bigok",!1),null!=e.dataTransfer&&0!=e.dataTransfer.files.length&&0!=filetreelocation.length)for(var t=[],o=[],n=[],i=[],a=e.dataTransfer.files.length,s=0;s<e.dataTransfer.files.length;s++){var l=new FileReader,r=e.dataTransfer.files[s];t.push(r.name),o.push(r.size),n.push(r.type),l.onload=function(e){i.push(e.target.result),0==--a&&(Q("p5fileDragName").value=t.join("*"),Q("p5fileDragSize").value=o.join("*"),Q("p5fileDragType").value=n.join("*"),Q("p5fileDragData").value=i.join("*"),Q("p5fileDragLink").value=encodeURIComponent(filetreelinkpath),Q("p5loginSubmit2").click())},l.readAsDataURL(r)}}var p5dragtimer=null;function p5fileDragOver(e){haltEvent(e),null!=p5dragtimer&&(clearTimeout(p5dragtimer),p5dragtimer=null);var t=!0;0==filetreelocation.length&&(t=!1),QV("bigok",t),QV("bigfail",!t)}function p5fileDragLeave(e){haltEvent(e),"p5filetable"!=e.target.id?(QV("bigfail",!1),QV("bigok",!1)):p5dragtimer=setTimeout("QV('bigfail',false);QV('bigok',false);p5dragtimer=null;",200)}function ondeskkeypress(e){if(toggleSoftKeys(0),Q("DeskSoftInput").value="",setSessionActivity(),desktop&&!xxdialogMode&&10==xxcurrentView){if(null!=currentNode){var t=meshes[currentNode.meshid].links[userinfo._id].rights;if(0==(4294967295==t||0!=(8&t)&&0==(256&t)))return!1;if(1==(4294967295!=t&&0!=(8&t)&&0==(256&t)&&0!=(4096&t))&&(1==e.altKey||1==e.ctrlKey||e.keyCode<32&&8!=e.keyCode&&13!=e.keyCode||90<e.keyCode))return!1}return desktop.m.handleKeys(e)}}function ondeskkeydown(e){if(toggleSoftKeys(0),Q("DeskSoftInput").value="",setSessionActivity(),desktop&&!xxdialogMode&&10==xxcurrentView){if(null!=currentNode){var t=meshes[currentNode.meshid].links[userinfo._id].rights;if(0==(4294967295==t||0!=(8&t)&&0==(256&t)))return!1;if(1==(4294967295!=t&&0!=(8&t)&&0==(256&t)&&0!=(4096&t))&&(1==e.altKey||1==e.ctrlKey||e.keyCode<32&&8!=e.keyCode&&13!=e.keyCode||90<e.keyCode))return!1}return desktop.m.handleKeyDown(e)}}function ondeskkeyup(e){if(toggleSoftKeys(0),Q("DeskSoftInput").value="",setSessionActivity(),desktop&&!xxdialogMode&&10==xxcurrentView){if(null!=currentNode){var t=meshes[currentNode.meshid].links[userinfo._id].rights;if(0==(4294967295==t||0!=(8&t)&&0==(256&t)))return!1;if(1==(4294967295!=t&&0!=(8&t)&&0==(256&t)&&0!=(4096&t))&&(1==e.altKey||1==e.ctrlKey||e.keyCode<32&&8!=e.keyCode&&13!=e.keyCode||90<e.keyCode))return!1}return desktop.m.handleKeyUp(e)}}var updateDevicesTimer=null;function updateDevices(){null==updateDevicesTimer&&(updateDevicesTimer=setTimeout(updateDevicesEx,200))}var deviceHeaderCount,sort=0,deviceHeaderId=0,deviceHeaders={},showRealNames=!1,deviceHeaderTotal=0,deviceHeadersTitles=(deviceHeaders={},{});function updateDevicesEx(){null!=updateDevicesTimer&&(clearTimeout(updateDevicesTimer),updateDevicesTimer=null);var e="",t=0,o=null,n=0,i={};for(var a in deviceHeaderCount={},deviceHeaders={},deviceHeadersTitles={},(deviceHeaderTotal=deviceHeaderId=0)==sort?nodes.sort(meshSort):1==sort?nodes.sort(powerSort):2==sort&&(1==showRealNames?nodes.sort(deviceHostSort):nodes.sort(deviceSort)),nodes)if(0!=nodes[a].v){var s=meshes[nodes[a].meshid].links[userinfo._id];if(null!=s){s.rights;if(0==sort){if(nodes.sort(meshSort),nodes[a].meshid!=o){deviceHeaderSet();var l="";1==meshes[nodes[a].meshid].mtype&&(l="<span style=color:lightgray>, Intel&reg; AMT only</span>"),null!=o&&(2==t&&(e+="<td><div style=width:301px></div></td>"),""!=e&&(e+="</tr></table>")),e+="<div class=DevSt style=padding-top:4px><span style=float:right>",e+='</span><span id=MxMESH style=cursor:pointer onclick=goForward("'+nodes[a].meshid+'")>'+EscapeHtml(meshes[nodes[a].meshid].name)+"</span>"+l+"<span id=DevxHeader"+deviceHeaderId+" style=color:lightgray></span></div>",i[o=nodes[a].meshid]=1,t=0}}else 1==sort?nodes[a].pwr!==o&&(deviceHeaderSet(),null!==o&&(2==t&&(e+="<td><div style=width:301px></div></td>"),""!=e&&(e+="</tr></table>")),e+="<div class=DevSt style=width:100%;padding-top:4px><span>"+PowerStateStr2(nodes[a].pwr)+"</span><span id=DevxHeader"+deviceHeaderId+" style=color:lightgray></span></div>",o=nodes[a].pwr,t=0):2==sort&&null==o&&(o="1");n++;var r=EscapeHtml(nodes[a].name);0==r.length&&(r="<i>None</i>"),null!=nodes[a].rname&&0<nodes[a].rname.length&&(r+=" / "+EscapeHtml(nodes[a].rname));var d=EscapeHtml(nodes[a].name);1==showRealNames&&null!=nodes[a].rname&&(d=EscapeHtml(nodes[a].rname)),0==d.length&&(d="<i>None</i>");var p=nodes[a].icon,c=NodeStateStr(nodes[a]);nodes[a].conn&&0!=nodes[a].conn||(p+=" gray"),e+="<div style=cursor:pointer onclick=goForward('"+nodes[a]._id+"')>",e+='<div class="i'+p+'" style="float:left;margin-left:4px"></div>',e+='<div style="width:auto;height:40px;background-color:lightgray;margin-top:5px;margin-bottom:5px;margin-left:60px;padding-top:5px;padding-bottom:5px;border-radius:8px 0px 0px 8px">',e+="<div><div style=padding-left:12px;padding-top:2px><b>"+d+"</b></div><div style=padding-left:12px;padding-top:3px;color:gray>"+c+"</div></div>",e+="</div></div>",deviceHeaderTotal++,void 0===deviceHeaderCount[nodes[a].state]?deviceHeaderCount[nodes[a].state]=1:deviceHeaderCount[nodes[a].state]++}}if(0==sort)for(var a in meshes){var u=meshes[a],m=u.links[userinfo._id];if(null!=m){m.rights;null==i[u._id]&&(""!=o&&""!=e&&(e+="</tr></table>"),e+="<div><div colspan=3 class=DevSt><span style=float:right>",e+='</span><span id=MxMESH style=cursor:pointer onclick=goForward("'+u._id+'")>'+EscapeHtml(u.name)+"</span></div>",1==u.mtype&&(e+="<div style=padding:10px><i>No Intel&reg; AMT devices in this group"),2==u.mtype&&(e+="<div style=padding:10px><i>No devices in this group"),e+=".</i></div></div>",o=u._id,n++)}}for(var a in 0==n?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>'):QH("xdevices",e),deviceHeaderSet(),deviceHeaders)QH(a,deviceHeaders[a]);for(var a in deviceHeadersTitles)Q(a).title=deviceHeadersTitles[a]}var powerStatetable=["","Powered","Sleep","Sleep","Sleep","Hibernating","Power off","Present"],powerStateStrings=["","Powered","Sleeping","Sleeping","Deep Sleep","Hibernating","Soft-Off","Present"],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"],powerColorTable=["#00000000","black","blue","blue","lightblue","blueviolet","darkgreen","lightseagreen","lightseagreen"];function NodeStateStr(e){var t=[];return 0<e.state&&e.state<powerStatetable.length&&state.push(powerStatetable[e.state]),e.conn&&(0!=(1&e.conn)&&t.push("<span>Agent</span>"),0!=(2&e.conn)?t.push("<span>CIRA</span>"):0!=(4&e.conn)&&t.push("<span>Intel&reg; AMT</span>"),0!=(8&e.conn)&&t.push("<span>Relay</span>"),0!=(16&e.conn)&&t.push("<span>MQTT</span>")),null!=e.pwr&&0!=e.pwr&&t.push(powerStateStrings[e.pwr]),t.join(", ")}function PowerStateStr(e){return e<powerStatetable.length?powerStatetable[e]:""}function PowerStateStr2(e){return 0!=e&&e<powerStatetable.length?powerStatetable[e]:"Unknown"}function onSortSelectChange(e){sort=document.getElementById("sortselect").selectedIndex,e||putstore("sort",sort),updateDevicesEx()}function deviceHeaderSet(){if(0!=deviceHeaderId){deviceHeaders["DevxHeader"+deviceHeaderId]=", "+deviceHeaderTotal+(1==deviceHeaderTotal?" node":" nodes");var e="";for(var t in deviceHeaderCount)0<e.length&&(e+=", "),e+=deviceHeaderCount[t]+" "+PowerStateStr2(t);deviceHeadersTitles["DevxHeader"+deviceHeaderId]=e,deviceHeaderId++,deviceHeaderCount={},deviceHeaderTotal=0}else deviceHeaderId=1}function meshSort(e,t){return e.meshnamel>t.meshnamel?1:e.meshnamel<t.meshnamel?-1:e.meshid==t.meshid?1==showRealNames?e.rnamel>t.rnamel?1:e.rnamel<t.rnamel?-1:0:e.namel>t.namel?1:e.namel<t.namel?-1:0:0}function powerSort(e,t){var o=e.pwr?e.pwr:0,n=t.pwr?t.pwr:0;return o==n?1==showRealNames?e.rnamel>t.rnamel?1:e.rnamel<t.rnamel?-1:0:e.namel>t.namel?1:e.namel<t.namel?-1:0:n<o?1:o<n?-1:0}function deviceSort(e,t){return e.namel>t.namel?1:e.namel<t.namel?-1:0}function deviceHostSort(e,t){return e.rnamel>t.rnamel?1:e.rnamel<t.rnamel?-1:0}function refreshDevice(e){currentNode&&currentNode._id==e&&gotoDevice(e,xxcurrentView,!0)}function getNodeRights(e){var t=getNodeFromId(e);return meshes[t.meshid].links[userinfo._id].rights}var currentNode,currentDevicePanel=0,powerTimelineNode=null,powerTimelineReq=null,powerTimelineUpdate=null,powerTimeline=null;function getCurrentNode(){return currentNode}function gotoDevice(e,t,o){if(!0===userinfo.emailVerified||1!=serverinfo.emailcheck||4294967295==userinfo.siteadmin)if(!(262144&features)||1==userinfo.otpsecret||0<userinfo.otphkeys||0<userinfo.otpkeys){var n=getNodeFromId(e);if(null!=n){var i=meshes[n.meshid];if(null!=i){var a=i.links[userinfo._id].rights;if(!currentNode||currentNode._id!=n._id||1==o){currentNode=n;var s=EscapeHtml(n.name);0==s.length&&(s="<i>None</i>"),0!=(4&a)&&(s="<span onclick=showEditNodeValueDialog(0) style=cursor:pointer>"+s+"</span>"),QH("p10deviceName",s);var l="<table style=width:100%>";l+=addDeviceAttribute("<span>Group</span>",'<a onclick=goForward("'+n.meshid+'") style=cursor:pointer>'+EscapeHtml(meshes[n.meshid].name)+"</a>"),null!=n.rname&&(l+=addDeviceAttribute("<span>Name</span>","<span>"+EscapeHtml(n.rname)+"</span>")),1!=i.mtype&&n.name==n.host||(0!=(4&a)?n.host?l+=addDeviceAttribute("Hostname","<span onclick=showEditNodeValueDialog(1) style=cursor:pointer>"+EscapeHtml(n.host)+"</span>"):l+=addDeviceAttribute("Hostname","<span onclick=showEditNodeValueDialog(1) style=cursor:pointer><i>None</i></span>"):l+=addDeviceAttribute("Hostname",EscapeHtml(n.host)));var r=n.desc?EscapeHtml(n.desc):"<i>None</i>";l+=addDeviceAttribute("Description",0!=(4&a)?"<span onclick=showEditNodeValueDialog(2) style=cursor:pointer>"+r+"</span>":r);var d=["Unknown","Windows 32bit console","Windows 64bit console","Windows 32bit service","Windows 64bit service","Linux 32bit","Linux 64bit","MIPS","XENx86","Android ARM","Linux ARM","MacOS 32bit","Android x86","PogoPlug ARM","Android APK","Linux Poky x86-32bit","MacOS 64bit","ChromeOS","Linux Poky x86-64bit","Linux NoKVM x86-32bit","Linux NoKVM x86-64bit","Windows MinCore console","Windows MinCore service","NodeJS","ARM-Linaro","ARMv6l / ARMv7l","ARMv8 64bit","ARMv6l / ARMv7l / NoKVM","Unknown","Unknown","FreeBSD x86-64"];if(null!=n.agent&&null!=n.agent.id&&null!=n.agent.ver){var p="";p=n.agent.id<=d.length?d[n.agent.id]:d[0],0!=n.agent.ver&&(p+=" v"+n.agent.ver),l+=addDeviceAttribute("Agent",p)}if(null!=n.intelamt){p="";var c={0:nobreak("Not Activated (Pre)"),1:nobreak("Not Activated (In)"),2:nobreak("Activated")};null!=n.intelamt.ver&&null==n.intelamt.state?p+="<i>"+nobreak("Unknown State")+"</i>, v"+n.intelamt.ver:null==n.intelamt.ver&&2==n.intelamt.state?p+="<i>Activated</i>":null==n.intelamt.ver||null==n.intelamt.state?p+="<i>Unknown Version & State</i>":(p+=c[n.intelamt.state],n.intelamt.flags&&(2&n.intelamt.flags?p=" <span>CCM</span>":4&n.intelamt.flags&&(p=" <span>ACM</span>")),p+=", v"+n.intelamt.ver),1==n.intelamt.tls&&(p+=", <span>TLS</span>"),2==n.intelamt.state&&(null!=n.intelamt.user&&""!=n.intelamt.user||(p+=0!=(4&a)?', <i style=color:#FF0000;cursor:pointer onclick=editDeviceAmtSettings("'+n._id+'")>'+nobreak("No Credentials")+"</i>":", <i style=color:#FF0000>No Credentials</i>"),p+=" ",0!=(4&a)&&(p+='<img src=images/link4.png height=10 width=10 style=cursor:pointer onclick=editDeviceAmtSettings("'+n._id+'")>'));var u="Intel&reg; ME";"number"==typeof n.intelamt.sku&&(0!=(8&n.intelamt.sku)?u="Intel&reg; AMT":0!=(16&n.intelamt.sku)&&(u="Intel&reg; SM")),l+=addDeviceAttribute(u,p)}if(null!=n.agent&&null!=n.agent.tag&&"mailto:"!=n.agent.tag){var m=EscapeHtml(n.agent.tag);m.startsWith("mailto:")&&(m='<a href="'+m+'">'+m.substring(7)+"</a>"),l+=addDeviceAttribute("Agent Tag",m)}var h=n.conn;if(h&&1<h){var f=[];0!=(1&n.conn)&&f.push("<span>Agent</span>"),0!=(2&n.conn)?f.push("<span>Intel&reg; AMT CIRA</span>"):0!=(4&n.conn)&&f.push("<span>Intel&reg; AMT</span>"),0!=(8&n.conn)&&f.push("<span>Agent Relay</span>"),0!=(16&n.conn)&&f.push("<span>MQTT</span>"),l+=addDeviceAttribute("Connectivity",f.join(", "))}var g="<i>None</i>";if(null!=n.tags)for(var v in g="",n.tags)g+='<span style="background-color:lightgray;padding:3px;margin-right:4px;border-radius:5px">'+n.tags[v]+"</span>";l+=addDeviceAttribute("Tags",0!=(4&a)?"<span onclick=showEditNodeValueDialog(3) style=cursor:pointer>"+g+"</span>":g),l+="</table><br />",0!=(76&a)&&(l+="<input type=button value=Actions onclick=deviceActionFunction() />"),QH("p10html",l),setupFiles(),l="<div style=float:right;font-size:x-small;margin-right:10px>",0!=(4&a)&&(l+='<a style=cursor:pointer onclick=p10showDeleteNodeDialog("'+n._id+'")>Delete Device</a>'),l+="</div><div style=font-size:x-small>",l+="</div><br>",QH("p10html3",l);var k=PowerStateStr(n.state);0!=(1&h)&&(0<k.length&&(k+=", "),k+="<span style=font-size:10px>Mesh Agent</span>"),0!=(2&h)?(0<k.length&&(k+=", "),k+="<span style=font-size:10px>Intel&reg; AMT connected</span>"):0!=(4&h)&&(0<k.length&&(k+=", "),k+="<span style=font-size:10px>Intel&reg; AMT detected</span>"),0!=(16&h)&&(0<k.length&&(k+="<br/>"),k+="<span style=font-size:12px>MQTT channel connected</span>"),QH("MainComputerState",k),QH("MainComputerImage",'<div class="i'+n.icon+'"></div>'),powerTimelineNode!=currentNode._id&&powerTimelineReq!=currentNode._id&&(QH("p10html2",""),powerTimelineReq=currentNode._id,meshserver.send({action:"powertimeline",nodeid:currentNode._id}))}setupDesktop(),go(t=t||10),setupDeviceMenu()}else goBack()}else goBack()}else 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.');else setDialogMode(2,"Account Security",1,null,'Unable to access a device until a email address is verified. This is required for password recovery. Go to the "My Account" to change and verify an email address.')}function deviceToastFunction(){xxdialogMode||setDialogMode(2,"Device Toast",3,deviceToastFunctionEx,"<textarea id=d2devToast style=width:100%;height:80px;resize:none;overflow-y:scroll></textarea>")}function deviceToastFunctionEx(){meshserver.send({action:"toast",nodeids:[currentNode._id],title:"MeshCentral",msg:Q("d2devToast").value})}function setupDeviceMenu(e,t){var o=0;currentNode&&(o=meshes[currentNode.meshid].links[userinfo._id].rights),null!=e&&(currentDevicePanel=e),QV("p10general",0==currentDevicePanel),QV("p10desktop",1==currentDevicePanel),QV("p10files",2==currentDevicePanel);var n=[];0!=currentDevicePanel&&n.push({n:"General",f:"setupDeviceMenu(0)"}),1!=currentDevicePanel&&null!=currentNode&&(8&o||256&o)&&(1==meshes[currentNode.meshid].mtype&&("number"!=typeof currentNode.intelamt.sku||0!=(8&currentNode.intelamt.sku))||currentNode.agent&&1&currentNode.agent.caps)&&n.push({n:"Desktop",f:"setupDeviceMenu(1)"}),2!=currentDevicePanel&&null!=currentNode&&8&o&&(4294967295==o||0==(1024&o))&&2==currentNode.mtype&&4&currentNode.agent.caps&&n.push({n:"Files",f:"setupDeviceMenu(2)"}),updateFooterMenu(n)}function deviceActionFunction(){if(!xxdialogMode){var e=meshes[currentNode.meshid].links[userinfo._id].rights,t="Select an operation to perform on this device.<br /><br />",o="<select id=d2deviceop style=float:right;width:170px>";0!=(64&e)&&(o+="<option value=100>Wake-up</option>"),0!=(8&e)&&(o+="<option value=4>Sleep</option><option value=3>Reset</option><option value=2>Power off</option>"),setDialogMode(2,"Device Action",3,deviceActionFunctionEx,t+=addHtmlValue("Operation",o+="</select>"))}}function deviceActionFunctionEx(){var e=Q("d2deviceop").value;100==e?meshserver.send({action:"wakedevices",nodeids:[currentNode._id]}):meshserver.send({action:"poweraction",nodeids:[currentNode._id],actiontype:e})}function updateDeviceTimeline(){2==meshserver.State&&null!=powerTimelineNode&&null!=powerTimelineUpdate&&null!=currentNode&&powerTimelineNode==powerTimelineReq&&currentNode._id==powerTimelineNode&&powerTimelineUpdate<Date.now()&&(powerTimelineUpdate=null,meshserver.send({action:"powertimeline",nodeid:currentNode._id}))}function drawDeviceTimeline(){var e=null,t=Date.now();currentNode._id==powerTimelineNode&&(e=powerTimeline);var o=new Date;o.setHours(0,0,0,0);(o=new Date(o.getTime()-5184e5)).getTime();var n=[];if(null!=e&&1<e.length){n.push([0,e[1],e[0]]);for(var i=e[1],a=2;a<e.length;a+=2){var s=e[a],l=t;e.length>a+1&&(l=e[a+1]),n.push([i,i+l,s]),i+=l}}var r="",d=1,p=new Date,c=Q("masthead").offsetWidth-122;p.setHours(0,0,0,0);for(a=0;a<7;a++){var u="",m=p.getTime(),h=m+864e5;for(var f in n){var g=n[f];if(1==isTimeBlockInside(m,h,g[0],g[1])){var v=Math.max(m,g[0]),k=Math.min(Math.min(h,g[1]),t),y=Math.round((k-v)*c/864e5);0<y&&(u+="<div style=display:table-cell;width:"+y+"px;background-color:"+powerColor(g[2])+";height:16px></div>")}}r+="<tr style="+(d%2==0?"background-color:#DDD":"")+"><td><div>&nbsp;"+printDate(p)+"<div></div></div></td><td><div>"+u+"</div></td></tr>",++d,p=new Date(p.getTime()-864e5)}QH("p10html2",'<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse;width:calc(100% - 18px);margin:9px" border=0 cellpadding=2 cellspacing=0><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:center;width:90px>Day</th><th scope=col style=text-align:center>Power State</th></tr>'+r+"</tbody></table>")}function powerColor(e){return e<powerColorTable.length?powerColorTable[e]:"yellow"}function isTimeBlockInside(e,t,o,n){return o<e&&t<n||(e<o&&o<t||e<n&&n<t)}function addDeviceAttribute(e,t){return"<tr><td style=width:100px;color:gray>"+e+"</td><td style=overflow:hidden>"+t+"</td></tr>"}function editDeviceAmtSettings(e,t){if(!xxdialogMode){var o="",n=getNodeFromId(e),i=3;0!=(4&getNodeRights(e))&&(o+=addHtmlValue("Username",'<input id=dp10username style=width:170px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />'),o+=addHtmlValue("Password","<input id=dp10password type=password style=width:170px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />"),o+=addHtmlValue("Security","<select id=dp10tls style=width:176px><option value=0>No TLS security</option><option value=1>TLS security required</option></select>"),null!=n.intelamt.user&&""!=n.intelamt.user&&(i=7),setDialogMode(2,"Edit Intel&reg; AMT credentials",i,editDeviceAmtSettingsEx,o,{node:n,func:t}),null!=n.intelamt.user&&""!=n.intelamt.user?Q("dp10username").value=n.intelamt.user:Q("dp10username").value="admin",Q("dp10tls").value=n.intelamt.tls,validateDeviceAmtSettings())}}function validateDeviceAmtSettings(){QE("idx_dlgOkButton",passwordcheck(Q("dp10password").value))}function editDeviceAmtSettingsEx(e,t){if(2==e)meshserver.send({action:"changedevice",nodeid:t.node._id,intelamt:{user:"",pass:""}});else{var o=Q("dp10username").value;""==o&&(o="admin");var n=Q("dp10password").value;""==n&&(o=""),meshserver.send({action:"changedevice",nodeid:t.node._id,intelamt:{user:o,pass:n,tls:Q("dp10tls").value}}),t.node.intelamt.user=o,t.node.intelamt.tls=Q("dp10tls").value,t.func&&setTimeout(t.func,300)}}function p10showDeleteNodeDialog(e){xxdialogMode||(setDialogMode(2,"Delete Node",3,p10showDeleteNodeDialogEx,format("Delete {0}?",EscapeHtml(currentNode.name))+"<br /><br /><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />Confirm",e),p10validateDeleteNodeDialog())}function p10validateDeleteNodeDialog(){QE("idx_dlgOkButton",Q("p10check").checked)}function p10showDeleteNodeDialogEx(e,t){meshserver.send({action:"removedevices",nodeids:[t]})}function p10showiconselector(){if(!xxdialogMode&&0!=(4&meshes[currentNode.meshid].links[userinfo._id].rights)){"<div style=display:inline-block class=i1 onclick=p10setIcon(1)></div>","<div style=display:inline-block class=i2 onclick=p10setIcon(2)></div>","<div style=display:inline-block class=i3 onclick=p10setIcon(3)></div><br>","<div style=display:inline-block class=i4 onclick=p10setIcon(4)></div>","<div style=display:inline-block class=i5 onclick=p10setIcon(5)></div>","<div style=display:inline-block class=i6 onclick=p10setIcon(6)></div></table>",setDialogMode(2,"Icon Selection",0,null,"<table align=center><td><div style=display:inline-block class=i1 onclick=p10setIcon(1)></div><div style=display:inline-block class=i2 onclick=p10setIcon(2)></div><div style=display:inline-block class=i3 onclick=p10setIcon(3)></div><br><div style=display:inline-block class=i4 onclick=p10setIcon(4)></div><div style=display:inline-block class=i5 onclick=p10setIcon(5)></div><div style=display:inline-block class=i6 onclick=p10setIcon(6)></div></table>"),QV("id_dialogclose",!0)}}function p10setIcon(e){setDialogMode(0),meshserver.send({action:"changedevice",nodeid:currentNode._id,icon:e})}var desktop,desktopNode,showEditNodeValueDialog_modes=["Device Name","Hostname","Description","Tags"],showEditNodeValueDialog_modes2=["name","host","desc","tags"],showEditNodeValueDialog_modes3=["","","","Group1, Group2, Group3"];function showEditNodeValueDialog(e){if(!xxdialogMode){setDialogMode(2,"Edit Device",3,showEditNodeValueDialogEx,addHtmlValue(showEditNodeValueDialog_modes[e],'<input id=dp10devicevalue style=width:170px maxlength=64 placeholder="'+showEditNodeValueDialog_modes3[e]+'" onchange=p10editdevicevalueValidate('+e+",event) onkeyup=p10editdevicevalueValidate("+e+",event) />"),e);var t=currentNode[showEditNodeValueDialog_modes2[e]];null==t&&(t=""),Array.isArray(t)&&(t=t.join(", ")),Q("dp10devicevalue").value=t,p10editdevicevalueValidate(),Q("dp10devicevalue").focus()}}function showEditNodeValueDialogEx(e,t){var o={action:"changedevice",nodeid:currentNode._id};o[showEditNodeValueDialog_modes2[t]]=Q("dp10devicevalue").value,meshserver.send(o)}function p10editdevicevalueValidate(e,t){var o=1<e||0<Q("dp10devicevalue").value.length;QE("idx_dlgOkButton",o),null!=t&&1==o&&13==t.keyCode&&dialogclose(1)}var desktopsettings={encoding:2,showfocus:!1,showmouse:!0,showcad:!0,quality:40,scaling:1024,framerate:50};function setupDesktop(){desktopNode!=currentNode&&null!=desktop&&(desktop.Stop(),desktop=desktopNode=null),desktopNode==currentNode&&null!=desktop||(QH("DeskParent",'<canvas id=Desk width=640 height=200 style="width:100%;-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></canvas>'),desktopNode=currentNode,Q("Desk").addEventListener("DOMMouseScroll",function(e){return dmousewheel(e)}),Q("Desk").addEventListener("mousewheel",function(e){return dmousewheel(e)})),desktopNode=currentNode,updateDesktopButtons(),Q("Desk").toBlob||QV("deskSaveBtn",!1)}function updateDesktopButtons(){var e=meshes[currentNode.meshid],t=0;null!=desktop&&(t=desktop.State);var o=e.links[userinfo._id].rights;QV("disconnectbutton1",0!=t),QV("connectbutton1",0==t&&2==e.mtype&&(8&o||256&o)),QV("connectbutton1h",0==t&&8&o&&(1==e.mtype||null!=currentNode.intelamt&&2==currentNode.intelamt.state&&null!=currentNode.intelamt.ver&&"number"==typeof currentNode.intelamt.sku&&0!=(8&currentNode.intelamt.sku))),QV("d7amtkvm",!(null==currentNode.intelamt||null==currentNode.intelamt.ver&&1!=e.mtype||0!=t&&2!=desktop.contype)),QV("d7meshkvm",2==e.mtype&&(0==t||1==desktop.contype));var n=0!=(1&currentNode.conn);QE("connectbutton1",n);var i=0!=(6&currentNode.conn);QE("connectbutton1h",i),QV("DeskToastButton",0!=(16384&o)&&currentNode.agent&&currentNode.agent.id<5&&8&o),QV("deskActionsBtn",8&o),Q("DeskControl").checked=0!=(8&o),0==n&&QV("DeskTools",!1)}function connectDesktop(e,t){if(setSessionActivity(),null==desktop)if(desktopNode=currentNode,2==t){if(null==desktopNode.intelamt.user||""==desktopNode.intelamt.user)return void editDeviceAmtSettings(desktopNode._id,connectDesktop);(desktop=CreateAmtRedirect(CreateAmtRemoteDesktop("Desk"),authCookie)).debugmode=debugmode,desktop.onStateChanged=onDesktopStateChange,desktop.m.bpp=1==desktopsettings.encoding||3==desktopsettings.encoding?1:2,desktop.m.useZRLE=desktopsettings.encoding<3,desktop.m.showmouse=desktopsettings.showmouse,desktop.m.onScreenSizeChange=deskAdjust,desktop.Start(desktopNode._id,16994,"*","*",0),desktop.contype=2}else(desktop=CreateAgentRedirect(meshserver,CreateAgentRemoteDesktop("Desk"),serverPublicNamePort,authCookie,authRelayCookie,domainUrl)).debugmode=debugmode,desktop.m.debugmode=debugmode,desktop.attemptWebRTC=attemptWebRTC,desktop.onStateChanged=onDesktopStateChange,desktop.m.CompressionLevel=desktopsettings.quality,desktop.m.ScalingLevel=desktopsettings.scaling,desktop.m.FrameRateTimer=desktopsettings.framerate,desktop.m.onDisplayinfo=deskDisplayInfo,desktop.m.onScreenSizeChange=deskAdjust,desktop.Start(desktopNode._id),desktop.contype=1;else desktop.Stop(),desktopNode=desktop=null}function onDesktopStateChange(e,t){var o=t;3==o&&2==e.contype&&o++;var n=StatusStrs[o];switch(null!=desktop&&1==desktop.webRtcActive&&(n+=", WebRTC"),QH("deskstatus",n),t){case 0:desktop.Stop(),desktopNode=desktop=null,QV("termdisplays",!1),1==fullscreen&&deskToggleFull()}updateDesktopButtons(),deskAdjust(),setTimeout(deskAdjust,50)}function showDesktopSettings(){xxdialogMode||(applyDesktopSettings(),updateDesktopButtons(),setDialogMode(7,"Remote Desktop Settings",3,showDesktopSettingsChanged))}function showDesktopSettingsChanged(){desktopsettings.encoding=d7desktopmode.value,desktopsettings.showfocus=d7showfocus.checked,desktopsettings.showmouse=d7showcursor.checked,desktopsettings.quality=d7bitmapquality.value,desktopsettings.scaling=d7bitmapscaling.value,desktopsettings.framerate=d7framelimiter.value,localStorage.setItem("desktopsettings",JSON.stringify(desktopsettings)),applyDesktopSettings(),desktop&&(1==desktop.contype&&0!=desktop.State&&desktop.m.SendCompressionLevel(1,desktopsettings.quality,desktopsettings.scaling,desktopsettings.framerate),2==desktop.contype&&0!=desktop.State&&(desktop.Stop(),setTimeout(function(){connectDesktop(null,2)},50)))}function applyDesktopSettings(){var e="",t=512&features?[90,70,50,40,30,20,10,5,1]:[50,40,30,20,10,5,1];for(var o in t)e+="<option value="+t[o]+">"+t[o]+"%</option>";QH("d7bitmapquality",e),d7desktopmode.value=desktopsettings.encoding,d7showfocus.checked=desktopsettings.showfocus,d7showcursor.checked=desktopsettings.showmouse,d7bitmapquality.value=40,0<=t.indexOf(parseInt(desktopsettings.quality))&&(d7bitmapquality.value=desktopsettings.quality),d7bitmapscaling.value=desktopsettings.scaling,desktopsettings.framerate&&(d7framelimiter.value=desktopsettings.framerate)}var fullscreen=!1;function deskAdjust(){var e=(Q("DeskParent").clientHeight-Q("Desk").clientHeight)/2;if(e<0){var t=Q("DeskParent").clientHeight,o=9999;desktop&&(o=desktop.m.width/desktop.m.height*t),QS("Desk")["max-height"]=t+"px",QS("Desk")["max-width"]=o+"px",e=0}else QS("Desk")["max-height"]=null,QS("Desk")["max-width"]=null;QS("Desk")["margin-top"]=e+"px",QS("Desk")["margin-bottom"]=e+"px"}function deskSendKeys(){if(!xxdialogMode&&null!=desktop&&3==desktop.State){var e=Q("deskkeys").value;0==e?2==desktop.contype?desktop.m.sendkey([[65511,1],[65364,1],[65364,0],[65511,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,91],[desktop.m.KeyAction.DOWN,40],[desktop.m.KeyAction.UP,40],[desktop.m.KeyAction.EXUP,91]]):1==e?2==desktop.contype?desktop.m.sendkey([[65511,1],[65362,1],[65362,0],[65511,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,91],[desktop.m.KeyAction.DOWN,38],[desktop.m.KeyAction.UP,38],[desktop.m.KeyAction.EXUP,91]]):2==e?2==desktop.contype?desktop.m.sendkey([[65511,1],[108,1],[108,0],[65511,0]]):desktop.sendCtrlMsg('{"action":"lock"}'):3==e?2==desktop.contype?desktop.m.sendkey([[65511,1],[109,1],[109,0],[65511,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,91],[desktop.m.KeyAction.DOWN,77],[desktop.m.KeyAction.UP,77],[desktop.m.KeyAction.EXUP,91]]):4==e?2==desktop.contype?desktop.m.sendkey([[65505,1],[65511,1],[109,1],[109,0],[65511,0],[65505,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.DOWN,16],[desktop.m.KeyAction.EXDOWN,91],[desktop.m.KeyAction.DOWN,77],[desktop.m.KeyAction.UP,77],[desktop.m.KeyAction.EXUP,91],[desktop.m.KeyAction.UP,16]]):5==e?2==desktop.contype?desktop.m.sendkey([[65511,1],[65511,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,91],[desktop.m.KeyAction.EXUP,91]]):6==e?2==desktop.contype?desktop.m.sendkey([[65511,1],[114,1],[114,0],[65511,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,91],[desktop.m.KeyAction.DOWN,82],[desktop.m.KeyAction.UP,82],[desktop.m.KeyAction.EXUP,91]]):7==e?2==desktop.contype?desktop.m.sendkey([[65513,1],[65473,1],[65473,0],[65513,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,18],[desktop.m.KeyAction.DOWN,115],[desktop.m.KeyAction.UP,115],[desktop.m.KeyAction.EXUP,18]]):8==e?2==desktop.contype?desktop.m.sendkey([[65507,1],[119,1],[119,0],[65507,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,17],[desktop.m.KeyAction.DOWN,87],[desktop.m.KeyAction.UP,87],[desktop.m.KeyAction.EXUP,17]]):9==e?2==desktop.contype?desktop.m.sendkey([[65513,1],[65289,1],[65289,0],[65513,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,18],[desktop.m.KeyAction.DOWN,9],[desktop.m.KeyAction.UP,9],[desktop.m.KeyAction.EXUP,18]]):10==e?desktop.m.sendcad():11==e&&(2==desktop.contype?desktop.m.sendkey([[65289,1],[65289,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.DOWN,9],[desktop.m.KeyAction.UP,9]]))}}function sendSpecialKeys(){xxdialogMode||null==desktop||3!=desktop.State||setDialogMode(3,"Special Keys",3,deskSendKeys)}function toggleSoftKeys(e){QV("DeskSoftInput",1==e),1==e&&Q("DeskSoftInput").focus()}function toggleDeskTools(){setSessionActivity(),xxdialogMode||("none"==QS("DeskTools").display?(QV("DeskTools",!0),Q("DeskTools").nodeid=currentNode._id,refreshDeskTools()):QV("DeskTools",!1))}function refreshDeskTools(){setSessionActivity(),QV("DeskToolsRefreshButton",!1),setTimeout(refreshDeskToolsEx,500),meshserver.send({action:"msg",type:"ps",nodeid:currentNode._id})}function refreshDeskToolsEx(){QV("DeskToolsRefreshButton",!0)}var filesNode,deskTools={sort:1,msg:null};function sortProcess(e){deskTools.sort=e,showDeskToolsProcesses(deskTools.msg)}function sortProcessPid(e,t){return e.p>t.p?1:e.p<t.p?-1:0}function sortProcessName(e,t){return e.d>t.d?1:e.d<t.d?-1:0}function showDeskToolsProcesses(e){if(null!=(deskTools.msg=e)){if(Q("DeskTools").nodeid==e.nodeid){var t=[],o=null;try{o=JSON.parse(e.value)}catch(e){}if(console.log(o),null!=o){for(var n in o)t.push({p:parseInt(n),c:o[n].cmd,d:o[n].cmd.toLowerCase(),u:o[n].user});0==deskTools.sort?t.sort(sortProcessPid):1==deskTools.sort&&t.sort(sortProcessName);var i="";for(var a in t)0!=t[a].p&&(i+="<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>"+t[a].p+"</div><a style=float:right;padding-right:5px;cursor:pointer onclick=stopProcess("+t[a].p+',"'+t[a].c+'")><img width=10 height=10 src="images/trash.png"></a><div style=float:right;padding-right:5px>'+(t[a].u?t[a].u:"")+"</div><div>"+t[a].c+"</div></div>");QH("DeskToolsProcesses",i)}}}else QH("DeskToolsProcesses","")}function deskSaveImage(){if(setSessionActivity(),!xxdialogMode&&null!=desktop&&3==desktop.State){var e=new Date,t="Desktop-"+currentNode.name+"-"+e.getFullYear()+"-"+("0"+(e.getMonth()+1)).slice(-2)+"-"+("0"+e.getDate()).slice(-2)+"-"+("0"+e.getHours()).slice(-2)+"-"+("0"+e.getMinutes()).slice(-2);Q("Desk").toBlob(function(e){saveAs(e,t+".jpg")})}}function deskDisplayInfo(e,t,o,n){var i=Q("termdisplays").value;if(0<t.length){var a="";for(var s in t)a+="<option"+(i==t[s]?" selected":"")+">"+t[s]+"</option>";QH("termdisplays",a)}QV("termdisplays",0<t.length)}function deskGetDisplayNumbers(e){desktop.m.GetDisplayNumbers()}function deskSetDisplay(e){setSessionActivity();var t=0,o=Q("termdisplays").value;t="All Displays"==o?65535:parseInt(o.substring(8)),desktop.m.SetDisplay(t)}function dmousedown(e){setSessionActivity(),xxdialogMode||null==desktop||desktop.m.mousedown(e)}function dmouseup(e){setSessionActivity(),xxdialogMode||null==desktop||desktop.m.mouseup(e)}function dmousemove(e){setSessionActivity(),xxdialogMode||null==desktop||desktop.m.mousemove(e)}function dmousewheel(e){return setSessionActivity(),!(xxdialogMode||null==desktop||!desktop.m.mousewheel)&&(desktop.m.mousewheel(e),haltEvent(e),!0)}function drotate(e){xxdialogMode||null==desktop||(desktop.m.setRotation(desktop.m.rotation+e),deskAdjust(),deskAdjust())}function stopProcess(e,t){return setDialogMode(2,"Process Control",3,stopProcessEx,format('Stop process #{0} "{1}"?',e,t),e),!1}function stopProcessEx(e,t){meshserver.send({action:"msg",type:"pskill",nodeid:currentNode._id,value:t}),setTimeout(refreshDeskTools,300)}function setupFiles(){var e=filesNode==currentNode,t=0!=(1&(filesNode=currentNode).conn);QE("p13Connect",t),0!=e&&0!=t||!files||(files.Stop(),files=null)}function onFilesStateChange(e,t){setSessionActivity(),p13Connect.value=0==t?"Connect":"Disconnect";var o=StatusStrs[t];switch(1==files.webRtcActive&&(o+=", WebRTC"),Q("p13Status").textContent=o,t){case 0:QH("p13files",""),p13filetree=null,p13filetreelocation=[],QH("p13currentpath",""),QE("p13FolderUp",!1),p13setActions(),null!=files&&(files.Stop(),files=null);break;case 3:p13targetpath="",files.sendText({action:"ls",reqid:1,path:""})}}function CreateRemoteFiles(e){var t={protocol:5};return t.onFileUpdate=e,t.xxStateChange=function(e){},t.ProcessData=function(e){t.onFileUpdate(e)},t}var autoConnectFilesTimer=null;function autoConnectFiles(e){autoConnectFilesTimer=null==autoConnectFilesTimer?setInterval(connectFiles,100):(clearInterval(autoConnectFilesTimer),null)}function connectFiles(e){files?(files.Stop(),files=null):((files=CreateAgentRedirect(meshserver,CreateRemoteFiles(p13gotFiles),serverPublicNamePort,authCookie,authRelayCookie,domainUrl)).attemptWebRTC=attemptWebRTC,files.onStateChanged=onFilesStateChange,files.Start(filesNode._id)),p13clipboard=p13clipboardFolder=null,p13clipboardCut=0,p13updateClipview()}var p13sortorder,p13filetree=null,p13targetpath=null,p13filetreelocation=[];function p13gotFiles(e){if(setSessionActivity(),0<e.length&&123!=e.charCodeAt(0))p13gotDownloadBinaryData(e);else if("download"!=(e=JSON.parse(decode_utf8(e))).action)if(e.path=e.path.replace(/\//g,"\\"),null!=p13filetree&&e.path==p13filetree.path){var t=p13getCheckedNames();p13filetree=e,p13updateFiles(t)}else{for(var o=e.path.replace(/\//g,"\\"),n=p13targetpath.replace(/\//g,"\\");0<o.length&&"\\"==o[0];)o=o.substring(1);for(;0<n.length&&"\\"==n[0];)n=n.substring(1);(o==n||"\\"==e.path&&""==p13targetpath)&&(p13filetree=e,p13updateFiles())}else p13gotDownloadCommand(e)}function p13getCheckedNames(){for(var e=[],t=document.getElementsByName("fd"),o=0;o<t.length;o++)t[o].checked&&e.push(p13filetree.dir[t[o].value].n);return e}function p13updateFiles(e){var t="",o="",n="<a style=cursor:pointer onclick=p13folderup(0)>Root</a>",i=p13filetree.path.split("\\");for(var a in p13filetreelocation=[],i)""!=i[a]&&p13filetreelocation.push(i[a]);for(var a in p13filetreelocation)n+=" / <a style=cursor:pointer onclick=p13folderup("+(parseInt(a)+1)+")>"+p13filetreelocation[a]+"</a>";var s=p13filetreelocation.join("/"),l=p13sort_files(p13filetree.dir);for(var a in l){var r,d=l[a],p=d.n;r=70<(r=p).length?EscapeHtml(p.substring(0,70))+"...":EscapeHtml(p),p=EscapeHtml(p);var c="";null!=d.s&&(c=getFileSizeStr(d.s));var u="";if(d.t<3){u="<div class=filelist file=999><input file=999 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value='"+d.nx+"'>&nbsp;<span style=float:right></span><span><div class=fileIcon"+d.t+'></div><a style=cursor:pointer onclick=p13folderset("'+encodeURIComponent(d.nx)+'")>'+r+"</a></span></div>"}else{var m=r;0<d.s&&(m='<a rel="noreferrer noopener" target="_blank" style=cursor:pointer onclick="p13downloadfile(\''+encodeURIComponent(s+"/"+p)+"','"+encodeURIComponent(p)+"',"+d.s+')">'+r+"</a>"),u="<div class=filelist file=3><input file=3 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value='"+d.nx+"'>&nbsp;<span style=float:right;padding-right:4px>"+c+"</span><span><div class=fileIcon"+d.t+"></div>"+m+"</span></div>"}d.t<3?t+=u:o+=u}if(QH("p13files",t+o),QH("p13currentpath",n),QE("p13FolderUp",0!=p13filetreelocation.length),null!=e){var h=document.getElementsByName("fd");for(a=0;a<h.length;a++)0<=e.indexOf(p13filetree.dir[h[a].value].n)&&(h[a].checked=!0)}p13setActions()}function p13folderset(e){p13targetpath=joinPaths(p13filetree.path,p13filetree.dir[e].n).split("\\").join("/"),files.sendText({action:"ls",reqid:1,path:p13targetpath})}function p13folderup(e){if(null==e)p13filetreelocation.pop();else for(;p13filetreelocation.length>e;)p13filetreelocation.pop();p13targetpath=p13filetreelocation.join("/"),files.sendText({action:"ls",reqid:1,path:p13targetpath})}function p13sort_filename(e,t){return e.ln>t.ln?1*p13sortorder:e.ln<t.ln?-1*p13sortorder:0}function p13sort_timestamp(e,t){return e.d>t.d?1*p13sortorder:e.d<t.d?-1*p13sortorder:0}function p13sort_bysize(e,t){return e.s==t.s?p13sort_filename(e,t):(e.s-t.s)*p13sortorder}function p13sort_files(e){var t=[],o=Q("p13sortdropdown").value;for(var n in e)e[n].nx=n,null==e[n].s&&(e[n].s=0),null==e[n].n&&(e[n].n=n),e[n].ln=e[n].n.toLowerCase(),t.push(e[n]);return p13sortorder=1,3<o&&(p13sortorder=-1,o-=3),1==o?t.sort(p13sort_filename):2==o?t.sort(p13sort_bysize):3==o&&t.sort(p13sort_timestamp),t}function p13setActions(){if(null==p13filetree)QE("p13DeleteFileButton",!1),QE("p13NewFolderButton",!1),QE("p13UploadButton",!1),QE("p13RenameFileButton",!1),QE("p13SelectAllButton",!1),Q("p13SelectAllButton").value="All",QE("p13RefreshButton",!1),QE("p13CutButton",!1),QE("p13CopyButton",!1),QE("p13PasteButton",!1);else{var e=p13getFileSelCount(),t=p13getFileCount(),o=p13getFileSelCount(!1),n=0<currentNode.agent.id&&currentNode.agent.id<5;QE("p13DeleteFileButton",0<e&&(0<p13filetreelocation.length||0==n)),QE("p13NewFolderButton",0<p13filetreelocation.length||0==n),QE("p13UploadButton",0<p13filetreelocation.length||0==n),QE("p13RenameFileButton",1==e&&(0<p13filetreelocation.length||0==n)),QE("p13SelectAllButton",0<t),Q("p13SelectAllButton").value=0<e?"None":"All",QE("p13RefreshButton",!0),QE("p13CutButton",0<e&&e==o&&(0<p13filetreelocation.length||0==n)),QE("p13CopyButton",0<e&&e==o&&(0<p13filetreelocation.length||0==n)),QE("p13PasteButton",(0<p13filetreelocation.length||0==n)&&null!=p13clipboard&&0<p13clipboard.length)}}function p13getFileSelCount(e){for(var t=0,o=document.getElementsByName("fd"),n=0;n<o.length;n++)!o[n].checked||0==e&&"3"!=o[n].attributes.file.value||t++;return t}function p13getFileSelDirCount(){for(var e=0,t=document.getElementsByName("fd"),o=0;o<t.length;o++)t[o].checked&&"999"==t[o].attributes.file.value&&e++;return e}function p13getFileCount(){return document.getElementsByName("fd").length}function p13selectallfile(){for(var e=0==p13getFileSelCount(),t=document.getElementsByName("fd"),o=0;o<t.length;o++)t[o].checked=e;p13setActions()}function p13createfolder(){setDialogMode(2,"New Folder",3,p13createfolderEx,"<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% />"),focusTextBox("p13renameinput"),p13fileNameCheck()}function p13createfolderEx(){files.sendText({action:"mkdir",reqid:1,path:p13filetreelocation.join("/")+"/"+Q("p13renameinput").value}),p13folderup(999)}function p13deletefile(){var e=p13getFileSelCount(),t=0<p13getFileSelDirCount()?"<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,1<e?format("Delete {0} selected items?",e)+t:"Delete selected item?"+t)}function p13deletefileEx(){for(var e=[],t=document.getElementsByName("fd"),o=0;o<t.length;o++)t[o].checked&&e.push(p13filetree.dir[t[o].value].n);files.sendText({action:"rm",reqid:1,path:p13filetreelocation.join("/"),delfiles:e,rec:Q("p13recdeleteinput").checked}),p13folderup(999)}function p13renamefile(){for(var e,t=document.getElementsByName("fd"),o=0;o<t.length;o++)t[o].checked&&(e=p13filetree.dir[t[o].value].n);setDialogMode(2,"Rename",3,p13renamefileEx,'<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% value="'+e+'" />',{action:"rename",path:p13filetreelocation.join("/"),oldname:e}),focusTextBox("p13renameinput"),p13fileNameCheck()}function p13renamefileEx(e,t){t.newname=Q("p13renameinput").value,files.sendText(t),p13folderup(999)}function p13fileNameCheck(e){var t=isFilenameValid(Q("p13renameinput").value);QE("idx_dlgOkButton",t),1==t&&null!=e&&13==e.keyCode&&dialogclose(1)}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")}function p13uploadFileEx(){p13doUploadFiles(Q("p13uploadinput").files)}function p13viewfile(){for(var e=document.getElementsByName("fd"),t=0;t<e.length;t++)if(e[t].checked){p13filetree.dir[e[t].value].s<=204800?p13downloadfile(encodeURIComponent(p13filetreelocation.join("/")+"/"+p13filetree.dir[e[t].value].n),encodeURIComponent(p13filetree.dir[e[t].value].n),p13filetree.dir[e[t].value].s,"viewer"):messagebox("File Editor","Only files less than 200k can be edited.");break}}var downloadFile,uploadFile,currentMesh,p13clipboard=null,p13clipboardFolder=null,p13clipboardCut=0;function p13copyFile(e){var t=document.getElementsByName("fd");p13clipboard=[],p13clipboardCut=e,p13clipboardFolder=p13targetpath;for(var o=0;o<t.length;o++)t[o].checked&&"3"==t[o].attributes.file.value&&p13clipboard.push(p13filetree.dir[t[o].value].n);p13updateClipview()}function p13pasteFile(){var e="";null!=p13clipboard&&0<p13clipboard.length&&(e=0==p13clipboardCut?1<p13clipboard.length?format("Confirm copy of {0} entries's to this location?",p13clipboard.length):format("Confirm copy of 1 entrie to this location?"):1<p13clipboard.length?format("Confirm move of {0} entries's to this location?",p13clipboard.length):format("Confirm move of 1 entrie to this location?")),setDialogMode(2,"Paste",3,p13pasteFileEx,e)}function p13pasteFileEx(){files.sendText({action:0==p13clipboardCut?"copy":"move",reqid:1,scpath:p13clipboardFolder,dspath:p13targetpath,names:p13clipboard}),p13folderup(999),1==p13clipboardCut&&(p13clipboardFolder=p13clipboard=null,p13clipboardCut=0,p13updateClipview())}function p13updateClipview(){var e="";null!=p13clipboard&&0<p13clipboard.length&&(e=0==p13clipboardCut?1<p13clipboard.length?format('Holding {0} entries for copy, <a href=# onclick="return p13clearClip()" style=cursor:pointer>Clear</a>.',p13clipboard.length):format('Holding 1 entrie for copy, <a href=# onclick="return p13clearClip()" style=cursor:pointer>Clear</a>.'):1<p13clipboard.length?format('Holding {0} entries for move, <a href=# onclick="return p13clearClip()" style=cursor:pointer>Clear</a>.',p13clipboard.length):format('Holding 1 entrie for move, <a href=# onclick="return p13clearClip()" style=cursor:pointer>Clear</a>.')),QH("p13bottomstatus",e),p13setActions()}function p13clearClip(){return p13clipboardFolder=p13clipboard=null,p13clipboardCut=0,p13updateClipview(),!1}function updateUploadDialogOk(e){QE("idx_dlgOkButton",""!=Q(e).value)}function getFileSelCount(e){for(var t=0,o=document.getElementsByName("fc"),n=0;n<o.length;n++)!o[n].checked||0==e&&"3"!=o[n].attributes.file.value||t++;return t}function getFileCount(){return document.getElementsByName("fc").length}function p13downloadfile(e,t,o){xxdialogMode||downloadFile||!files||(downloadFile={path:decodeURIComponent(e),file:decodeURIComponent(t),size:o,tsize:0,data:"",state:0,id:Math.random()},files.sendText({action:"download",sub:"start",id:downloadFile.id,path:downloadFile.path}),setDialogMode(2,"Download File",10,p13downloadFileCancel,"<div>"+downloadFile.file+"</div><br /><progress id=d2progressBar style=width:100% value=0 max="+o+" />"))}function p13downloadFileCancel(){setDialogMode(0),files.sendText({action:"download",sub:"cancel",id:downloadFile.id}),downloadFile=null}function p13gotDownloadCommand(e){null!=downloadFile&&e.id==downloadFile.id&&("start"==e.sub?(downloadFile.state=1,files.sendText({action:"download",sub:"startack",id:downloadFile.id})):"cancel"==e.sub&&(downloadFile=null,setDialogMode(0)))}function p13gotDownloadBinaryData(e){downloadFile&&0!=downloadFile.state&&(4<e.length&&(downloadFile.tsize+=e.length-4,downloadFile.data+=e.substring(4),Q("d2progressBar").value=downloadFile.tsize),0!=(1&ReadInt(e,0))?(saveAs(data2blob(downloadFile.data),downloadFile.file),downloadFile=null,setDialogMode(0)):files.sendText({action:"download",sub:"ack",id:downloadFile.id}))}function p13doUploadFiles(e){xxdialogMode||((uploadFile={}).xpath=p13filetreelocation.join("/"),uploadFile.xfiles=e,uploadFile.xfilePtr=-1,setDialogMode(2,"Upload File",10,p13uploadFileCancel,"<div id=p13dfileName>Connecting...</div><br /><progress id=d2progressBar style=width:100% value=0 max=0 />"),p13uploadReconnect())}function onFileUploadStateChange(e,t){switch(t){case 0:p13folderup(9999);break;case 3:p13uploadNextFile();break;default:console.log("Unknown onFileUploadStateChange state",t)}}function p13uploadReconnect(){uploadFile.ws=CreateAgentRedirect(meshserver,CreateRemoteFiles(p13gotUploadData),serverPublicNamePort,authCookie,authRelayCookie,domainUrl),uploadFile.ws.attemptWebRTC=!1,uploadFile.ws.ctrlMsgAllowed=!1,uploadFile.ws.onStateChanged=onFileUploadStateChange,uploadFile.ws.Start(filesNode._id)}function p13uploadNextFile(){if(uploadFile.xfilePtr++,uploadFile.xfiles.length>uploadFile.xfilePtr){uploadFile.xptr=0;var e=uploadFile.xfiles[uploadFile.xfilePtr];QH("p13dfileName",e.name),Q("d2progressBar").max=e.size,Q("d2progressBar").value=0,uploadFile.xreader=new FileReader,uploadFile.xreader.onload=function(){uploadFile.xdata=uploadFile.xreader.result,uploadFile.ws.sendText({action:"upload",reqid:uploadFile.xfilePtr,path:uploadFile.xpath,name:e.name,size:uploadFile.xdata.byteLength})},uploadFile.xreader.readAsArrayBuffer(e)}else p13uploadFileCancel()}function p13uploadFileCancel(e,t){null!=uploadFile&&(null!=uploadFile.ws&&(uploadFile.ws.Stop(),uploadFile.ws=null),uploadFile=null),setDialogMode(0)}function p13gotUploadData(e){var t=JSON.parse(e);if(null!=uploadFile&&parseInt(uploadFile.xfilePtr)==parseInt(t.reqid))if("uploadstart"==t.action){p13uploadNextPart(!1);for(var o=0;o<8;o++)p13uploadNextPart(!0)}else"uploadack"==t.action?p13uploadNextPart(!1):"uploaderror"==t.action&&p13uploadFileCancel()}function p13uploadNextPart(e){var t=uploadFile.xdata,o=uploadFile.xptr,n=uploadFile.xptr+4096;if(n>t.byteLength){if(1==e)return;n=t.byteLength}if(o==t.byteLength)null!=uploadFile.ws&&(uploadFile.ws.Stop(),uploadFile.ws=null),uploadFile.xfiles.length>uploadFile.xfilePtr+1?p13uploadReconnect():p13uploadFileCancel();else{var i=t.slice(o,n);uploadFile.ws.send(i),uploadFile.xptr=n,Q("d2progressBar").value=n}}function p20updateMesh(){if(null!=currentMesh){QH("p20meshName",EscapeHtml(currentMesh.name));var e=format("Unknown #{0}",currentMesh.mtype),t=currentMesh.links[userinfo._id].rights;1==currentMesh.mtype&&(e="Intel&reg; AMT only, no agent"),2==currentMesh.mtype&&(e="Managed using a software agent");var o="";o+=addHtmlValue("Name",addLinkConditional(EscapeHtml(currentMesh.name),"p20editmesh(1)",0!=(1&t))),o+=addHtmlValue("Description",addLinkConditional(currentMesh.desc&&""!=currentMesh.desc?EscapeHtml(currentMesh.desc):"<i>None</i>","p20editmesh(2)",0!=(1&t))),o+=addHtmlValue("Type",e),o+="<br style=clear:both><br>";var n=currentMesh.links[userinfo._id];n&&0!=(2&n.rights)&&(o+="<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>"),o+='<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>';var i=1,a=[];for(var s in currentMesh.links)a.push({id:s,name:s.split("/")[2],rights:currentMesh.links[s].rights});for(var s in a.sort(function(e,t){return e.name>t.name?1:e.name<t.name?-1:0}),a){var l="",r="Partial Rights",d=a[s].rights;4294967295==d?r="Full Administrator":0==d&&(r="No Rights"),s==userinfo._id||4294967295!=t&&0==(2&t)||(l='<a onclick=p20deleteUser(event,"'+encodeURIComponent(a[s].id)+'") style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'),o+='<tr onclick=p20viewuser("'+encodeURIComponent(a[s].id)+'") style=height:32px;cursor:pointer'+(i%2==0?";background-color:#DDD":"")+"><td>",o+="<div style=float:right>"+l+"</div><div style=float:right;padding-right:4px>"+r+"</div><div class=m2></div><div>&nbsp;"+EscapeHtml(decodeURIComponent(a[s].name))+"<div></div></div>",o+="</td></tr>",++i}o+="</tbody></table>",4294967295==t&&(o+="<div style=font-size:small;text-align:right;margin-top:6px><span><a onclick=p20showDeleteMeshDialog() style=cursor:pointer>Delete Group</a></span></div>"),QH("p20info",o)}}function p20showDeleteMeshDialog(){if(xxdialogMode)return!1;var e=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 />";return setDialogMode(2,"Delete Group",3,p20showDeleteMeshDialogEx,e+="<label><input id=p20check type=checkbox onchange=p20validateDeleteMeshDialog() />Confirm</label>"),p20validateDeleteMeshDialog(),!1}function p20validateDeleteMeshDialog(){QE("idx_dlgOkButton",Q("p20check").checked)}function p20showDeleteMeshDialogEx(e,t){meshserver.send({action:"deletemesh",meshid:currentMesh._id,meshname:currentMesh.name})}function p20editmesh(e){if(!xxdialogMode){var t=addHtmlValue("Name","<input id=dp20meshname style=width:170px maxlength=32 onchange=p20editmeshValidate() onkeyup=p20editmeshValidate() />");setDialogMode(2,"Edit Device Group",3,p20editmeshEx,t+=addHtmlValue("Description","<input id=dp20meshdesc style=width:170px maxlength=1024 onkeyup=p20editmeshValidate() />")),Q("dp20meshname").value=currentMesh.name,currentMesh.desc&&(Q("dp20meshdesc").value=currentMesh.desc),p20editmeshValidate(),2==e?Q("dp20meshdesc").focus():Q("dp20meshname").focus()}}function p20editmeshEx(){meshserver.send({action:"editmesh",meshid:currentMesh._id,meshname:Q("dp20meshname").value,desc:Q("dp20meshdesc").value})}function p20editmeshValidate(){QE("idx_dlgOkButton",0<Q("dp20meshname").value.length)}function p20showAddMeshUserDialog(){if(!xxdialogMode){var e=addHtmlValue("User","<input id=dp20username style=width:170px maxlength=32 onchange=p20validateAddMeshUserDialog() onkeyup=p20validateAddMeshUserDialog() />");e+='<div style="border:2px groove gray;background-color:white;max-height:120px;overflow-y:scroll">',e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20fulladmin>Full Administrator</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editmesh>Edit Device Group</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20manageusers>Manage Device Group Users</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20managecomputers>Manage Device Group Computers</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotecontrol>Remote Control</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remoteview style=margin-left:12px>Remote View Only</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotelimitedinput style=margin-left:12px>Limited Input Only</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noterminal style=margin-left:12px>No Terminal Access</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20nofiles style=margin-left:12px>No File Access</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noamt style=margin-left:12px>No Intel&reg; AMT</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshagentconsole>Mesh Agent Console</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshserverfiles>Server Files</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20wakedevices>Wake Devices</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>Edit Device Notes</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20limitevents>Show Only Own Events</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20chatnotify>Chat & Notify</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20uninstall>Uninstall Agent</label><br>",setDialogMode(2,"Add User to Mesh",3,p20showAddMeshUserDialogEx,e+="</div>"),p20validateAddMeshUserDialog(),Q("dp20username").focus()}}function p20validateAddMeshUserDialog(){var e=currentMesh.links[userinfo._id].rights,t=!Q("p20fulladmin").checked;QE("p20fulladmin",4294967295==e),QE("p20editmesh",t&&4294967295==e),QE("p20manageusers",t),QE("p20managecomputers",t),QE("p20remotecontrol",t),QE("p20meshagentconsole",t),QE("p20meshserverfiles",t),QE("p20wakedevices",t),QE("p20editnotes",t),QE("p20limitevents",t),QE("p20remoteview",t&&Q("p20remotecontrol").checked),QE("p20remotelimitedinput",t&&Q("p20remotecontrol").checked&&!Q("p20remoteview").checked),QE("p20noterminal",t&&Q("p20remotecontrol").checked),QE("p20nofiles",t&&Q("p20remotecontrol").checked),QE("p20noamt",t&&Q("p20remotecontrol").checked),QE("p20chatnotify",t),QE("p20uninstall",t)}function p20showAddMeshUserDialogEx(){var e=0;1==Q("p20fulladmin").checked?e=4294967295:(1==Q("p20editmesh").checked&&(e+=1),1==Q("p20manageusers").checked&&(e+=2),1==Q("p20managecomputers").checked&&(e+=4),1==Q("p20remotecontrol").checked&&(e+=8),1==Q("p20meshagentconsole").checked&&(e+=16),1==Q("p20meshserverfiles").checked&&(e+=32),1==Q("p20wakedevices").checked&&(e+=64),1==Q("p20editnotes").checked&&(e+=128),1==Q("p20remoteview").checked&&(e+=256),1==Q("p20noterminal").checked&&(e+=512),1==Q("p20nofiles").checked&&(e+=1024),1==Q("p20noamt").checked&&(e+=2048),1==Q("p20remotelimitedinput").checked&&(e+=4096),1==Q("p20limitevents").checked&&(e+=8192),1==Q("p20chatnotify").checked&&(e+=16384),1==Q("p20uninstall").checked&&(e+=32768));var t=Q("dp20username").value.split(","),o=[];for(var n in t)o.push(t[n].trim());meshserver.send({action:"addmeshuser",meshid:currentMesh._id,meshname:currentMesh.name,usernames:o,meshadmin:e})}function p20viewuser(e){if(!xxdialogMode){e=decodeURIComponent(e);var t=[],o=currentMesh.links[userinfo._id].rights,n=currentMesh.links[e].rights;4294967295==n?t.push("Full Administrator"):(0!=(1&n)&&t.push("Edit Device Group"),0!=(2&n)&&t.push("Manage Device Group Users"),0!=(4&n)&&t.push("Manage Device Group Computers"),0!=(8&n)&&t.push("Remote Control"),0!=(16&n)&&t.push("Agent Console"),0!=(32&n)&&t.push("Server Files"),0!=(64&n)&&t.push("Wake Devices"),0!=(128&n)&&t.push("Edit Notes"),0!=(256&n)&&t.push("Remote View Only"),0!=(512&n)&&t.push("No Terminal"),0!=(1024&n)&&t.push("No Files"),0!=(2048&n)&&t.push("No Intel&reg; AMT"),0!=(8&n)&&0!=(4096&n)&&0==(256&n)&&t.push("Limited Input"),0!=(8192&n)&&t.push("Self Events Only"),0!=(16384&n)&&t.push("Chat & Notify"),0!=(32768&n)&&t.push("Uninstall")),0==t.length&&t.push("No Rights");var i=1,a=addHtmlValue("User",EscapeHtml(decodeURIComponent(e.split("/")[2])));a+=addHtmlValue("Permissions",t.join(", ")),userinfo._id!=e&&(4294967295==o||0!=(2&o)&&4294967295!=n)&&(i+=4),setDialogMode(2,"Device Group User",i,p20viewuserEx,a,e)}}function p20viewuserEx(e,t){2==e&&setDialogMode(2,"Remote Mesh User",3,p20viewuserEx2,format("Confirm removal of user {0}?",t.split("/")[2]),t)}function p20deleteUser(e,t){haltEvent(e),p20viewuserEx(2,decodeURIComponent(t))}function p20viewuserEx2(e,t){meshserver.send({action:"removemeshuser",meshid:currentMesh._id,meshname:currentMesh.name,userid:t})}var xxdialogMode,xxdialogFunc,xxdialogButtons,xxdialogTag,xxcurrentView=-1;function go(e){if(setSessionActivity(),!xxdialogMode&&xxcurrentView!=e){updateFooterMenu(),setDialogMode(0);for(var t=0;t<32;t++)QV("p"+t,t==e);xxcurrentView=e}}function setDialogMode(e,t,o,n,i,a){setSessionActivity(),xxdialogMode=e,xxdialogFunc=n,xxdialogButtons=o,xxdialogTag=a,QE("idx_dlgOkButton",!0),QV("idx_dlgOkButton",1&o),QV("idx_dlgCancelButton",2&o),QV("id_dialogclose",2&o||8&o),QV("idx_dlgButtonBar",7&o),t&&QH("id_dialogtitle",t);for(var s=1;s<24;s++)QV("dialog"+s,s==e);QV("dialog",e),i&&(2==e?QH("id_dialogOptions",i):QH("id_dialogMessage",i))}function dialogclose(e){setSessionActivity();var t=xxdialogFunc,o=xxdialogButtons,n=xxdialogTag;setDialogMode(),(8&o||e)&&t&&t(e,n)}function putstore(e,t){try{if("undefined"==typeof localStorage||localStorage.getItem(e)==t)return;null==t?localStorage.removeItem(e):localStorage.setItem(e,t)}catch(e){}if("_"!=e[0]){for(var o={},n=0,i=localStorage.length;n<i;++n){var a=localStorage.key(n);"_"!=a[0]&&(o[a]=localStorage.getItem(a))}meshserver.send({action:"userWebState",state:JSON.stringify(o)})}}function getstore(e,t){try{if("undefined"==typeof localStorage)return t;var o=localStorage.getItem(e);return null==o||null==o?t:o}catch(e){return t}}function center(){QS("dialog").left=(getDocWidth()-300)/2+"px",deskAdjust(),deskAdjust()}function messagebox(e,t){QH("id_dialogMessage",t),setDialogMode(1,e,1)}function statusbox(e,t){QH("id_dialogMessage",t),setDialogMode(1,e)}function getDocWidth(){return window.innerWidth?window.innerWidth:document.documentElement&&document.documentElement.clientWidth&&0!=document.documentElement.clientWidth?document.documentElement.clientWidth:document.getElementsByTagName("body")[0].clientWidth}function haltEvent(e){return e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation(),!1}function haltReturn(e){13==e.keyCode&&haltEvent(e)}function validateEmail(e){return/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(e)}function reload(){window.location.href=window.location.href}function getNodeFromId(e){for(var t in nodes)if(nodes[t]._id==e)return nodes[t];return null}function addHtmlValue(e,t){return"<table><td style=width:120px>"+e+"<td><b>"+t+"</b></table>"}function addHtmlValue2(e,t){return"<div><div style=display:inline-block;float:right>"+t+"</div><div style=display:inline-block>"+e+"</div></div>"}function addLink(e,t){return"<a style=cursor:pointer;color:darkblue;text-decoration:none onclick='"+t+"'>&diams; "+e+"</a>"}function addLinkConditional(e,t,o){return o?addLink(e,t):e}function passwordcheck(e){return/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()]).{8,}/.test(e)}function getFileSizeStr(e){return 1==e?"1 byte":format("{0} bytes",e)}function joinPaths(){var e=[];for(var t in arguments){var o=arguments[t];if(null!=o&&""!=o){for(;o.endsWith("/")||o.endsWith("\\");)o=o.substring(0,o.length-1);for(;o.startsWith("/")||o.startsWith("\\");)o=o.substring(1);e.push(o)}}return e.join("/")}function focusTextBox(e){setTimeout(function(){Q(e).selectionStart=Q(e).selectionEnd=65535,Q(e).focus()},0)}isFilenameValid=function(){var t=/^[^\\/:\*\?"<>\|]+$/,o=/^\./,n=/^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i;return function(e){return t.test(e)&&!o.test(e)&&!n.test(e)&&"."!=e[0]}}();function parseUriArgs(){var e,t={},o=window.document.location.href.split(/[\?&|\=]/);for(n in o.splice(0,1),o)switch(n%2){case 0:e=decodeURIComponent(o[n]);break;case 1:t[e]=decodeURIComponent(o[n]);var n=parseInt(t[e]);n==t[e]&&(t[e]=n)}return t}function printDate(e){return e.toLocaleDateString(args.locale)}function printTime(e){return e.toLocaleTimeString(args.locale)}function printDateTime(e){return e.toLocaleString(args.locale)}function format(e){var o=Array.prototype.slice.call(arguments,1);return e.replace(/{(\d+)}/g,function(e,t){return void 0!==o[t]?o[t]:e})}function nobreak(e){return e.split(" ").join("&nbsp;")}</script>
\ No newline at end of file
views/download-min.handlebars deleted
-1
@@ -1 +0,0 @@
1 -<!doctypehtml><html dir=ltr xmlns=http://www.w3.org/1999/xhtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html;charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link type=text/css href=/styles/style.css media=screen rel=stylesheet title=CSS><title>{{{title1}}} - Download</title><div id=container style=max-height:100vh><div id=mastheadx></div><div id=masthead style="background:url(logo.png) 0 0;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden"><div style=float:left>{{{titlehtml}}}</div><div style=float:left;height:66px;color:#c8c8c8;padding-left:14px;padding-top:7px><strong><font style=font-size:46px;font-family:Arial,Helvetica,sans-serif>{{{title1}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px><strong><font style=font-size:14px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div></div><div id=page_content style=max-height:calc(100vh-138px)><div id=column_l><h1>Download</h1><p style=margin-left:20px>{{{message}}}</p><br></div><div id=footer><table cellpadding=0 cellspacing=10 style=width:100%><tr><td style=text-align:left><td style=text-align:right>{{{rootCertLink}}} &nbsp;<a href=terms>Terms &amp; Privacy</a></table></div></div></div>
\ No newline at end of file
views/error404-min.handlebars deleted
-1
@@ -1 +0,0 @@
1 -<!doctypehtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html; charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link type=text/css href=styles/style.css media=screen rel=stylesheet title=CSS><script src=scripts/common-0.0.1.js></script><title>{{{title}}}</title><body id=body onload='"undefined"!=typeof startup&&startup()'style=display:none;overflow:hidden><div id=container><div id=masthead class=noselect style="background:url(logo.png) 0 0;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden"><div style=float:left>{{{titlehtml}}}</div><div style=float:left;height:66px;color:#c8c8c8;padding-left:16px;padding-top:7px><strong><font style=font-size:46px;font-family:Arial,Helvetica,sans-serif>{{{title1}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px><strong><font style=font-size:14px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div></div><div id=page_leftbar><div style=height:16px></div></div><div id=topbar class="noselect style3"style=height:24px;position:relative><div id=uiMenuButton title="User interface selection"onclick=showUserInterfaceSelectMenu()>&diams;<div id=uiMenu style=display:none><div id=uiViewButton1 class=uiSelector onclick=userInterfaceSelectMenu(1) title="Left bar interface"><div class=uiSelector1></div></div><div id=uiViewButton2 class=uiSelector onclick=userInterfaceSelectMenu(2) title="Top bar interface"><div class=uiSelector2></div></div><div id=uiViewButton3 class=uiSelector onclick=userInterfaceSelectMenu(3) title="Fixed width interface"><div class=uiSelector3></div></div><div id=uiViewButton4 class=uiSelector onclick=toggleNightMode() title="Toggle night mode"><div class=uiSelector4></div></div></div></div></div><div id=column_l style="max-height:calc(100vh - 135px);overflow-y:auto"><div style=text-align:center;padding-top:30px;font-size:200px;font-family:Arial;color:#bbb><b>404</b></div><div style=text-align:center;font-size:20px;font-family:Arial;color:#999>This page does not exist</div><div style=text-align:center;padding-top:20px;font-size:20px;font-family:Arial;color:#999><a href=/ style=text-decoration:none><b>Go to main site</b></a></div></div><div id=footer><table cellpadding=0 cellspacing=10 style=width:100%><tr><td style=text-align:left><td style=text-align:right><a href=/ >Back</a></table></div></div><script>"use strict";var uiMode=parseInt(getstore("uiMode",1)),webPageStackMenu=!1,webPageFullScreen=!0,nightMode="1"==getstore("_nightMode","0"),terms="{{{terms}}}";function showUserInterfaceSelectMenu(){Q("uiViewButton1").classList.remove("uiSelectorSel"),Q("uiViewButton2").classList.remove("uiSelectorSel"),Q("uiViewButton3").classList.remove("uiSelectorSel"),Q("uiViewButton4").classList.remove("uiSelectorSel");try{Q("uiViewButton"+uiMode).classList.add("uiSelectorSel")}catch(e){}QV("uiMenu","none"==QS("uiMenu").display),nightMode&&Q("uiViewButton4").classList.add("uiSelectorSel")}function userInterfaceSelectMenu(e){e&&putstore("uiMode",uiMode=e),webPageFullScreen=uiMode<3,webPageStackMenu=!0,toggleFullScreen(0),toggleStackMenu(0),QC("column_l").add("room4submenu")}function toggleNightMode(){(nightMode=!nightMode)?QC("body").add("night"):QC("body").remove("night"),putstore("_nightMode",nightMode?"1":"0")}function toggleFullScreen(e){1===e&&putstore("webPageFullScreen",webPageFullScreen=!webPageFullScreen);0==webPageFullScreen?(QC("body").remove("menu_stack"),QC("body").remove("fullscreen"),QC("body").remove("arg_hide")):QC("body").add("fullscreen"),QV("body",!0)}function toggleStackMenu(e){1==webPageFullScreen&&(1===e&&putstore("webPageStackMenu",webPageStackMenu=!webPageStackMenu),0==webPageStackMenu?QC("body").remove("menu_stack"):QC("body").add("menu_stack"))}function putstore(e,t){try{if("undefined"==typeof localStorage)return;localStorage.setItem(e,t)}catch(e){}}function getstore(e,t){try{if("undefined"==typeof localStorage)return t;var o=localStorage.getItem(e);return null==o||null==o?t:o}catch(e){return t}}""!=terms&&QH("column_l",decodeURIComponent(terms)),QV("column_l",!0),userInterfaceSelectMenu()</script>
\ No newline at end of file
views/error404-mobile-min.handlebars deleted
-1
@@ -1 +0,0 @@
1 -<!doctypehtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html; charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><title>{{{title}}}</title><style type=text/css>a{color:#036;text-decoration:underline}#footer a{color:#fff;text-decoration:underline}#footer a:hover{color:#fff;text-decoration:none}</style><body onload='"undefined"!=typeof startup&&startup()'style="overflow-y:hidden;max-width:100%;margin:0;padding:0;border:0;color:#000;font-size:13px;font-family:\'Trebuchet MS\',Arial,Helvetica,sans-serif"><div id=container><div id=masthead style="background:url(logo.png) 0 0;background-size:341px 50px;background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden"><div style=float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:4px><strong><font style=font-size:36px;font-family:Arial,Helvetica,sans-serif>{{{title}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:7px><strong><font style=font-size:12px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div></div><div id=page_content style=overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%><div id=column_l style=padding-left:10px;padding-right:10px><div style=text-align:center;padding-top:30px;font-size:100px;font-family:Arial;color:#bbb><b>404</b></div><div style=text-align:center;font-size:16px;font-family:Arial;color:#999>This page does not exist</div><div style=text-align:center;padding-top:16px;font-size:20px;font-family:Arial;color:#999><a href=/ style=text-decoration:none><b>Go to main site</b></a></div></div></div><div id=footer style=height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0><table cellpadding=0 cellspacing=6 style=width:100%><tr><td style=text-align:left;color:#fff>{{{footer}}}<td style=text-align:right>{{{rootCertLink}}}&nbsp;<a href=/ >Back</a></table></div></div>
\ No newline at end of file
views/login-min.handlebars deleted
-1
@@ -1 +0,0 @@
1 -<!doctypehtml><html dir=ltr xmlns=http://www.w3.org/1999/xhtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html; charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link rel="shortcut icon"type=image/x-icon href={{{domainurl}}}favicon.ico><link keeplink=1 type=text/css href=styles/style.css media=screen rel=stylesheet title=CSS><script src=scripts/common-0.0.1.js></script><script keeplink=1 src=scripts/u2f-api.js></script><title>{{{title}}} - Login</title><body id=body onload='"undefined"!=typeof startup&&startup()'class="arg_hide login"><div id=container><div id=masthead><div style=float:left>{{{titlehtml}}}</div><div class=title>{{{title1}}}</div><div class=title2>{{{title2}}}</div></div><div id=topbar class="noselect style3"style=height:24px><div id=uiMenuButton title="User interface selection"onclick=showUserInterfaceSelectMenu()>&diams;<div id=uiMenu style=display:none><div id=uiViewButton1 class=uiSelector onclick=userInterfaceSelectMenu(1) title="Left bar interface"><div class=uiSelector1></div></div><div id=uiViewButton2 class=uiSelector onclick=userInterfaceSelectMenu(2) title="Top bar interface"><div class=uiSelector2></div></div><div id=uiViewButton3 class=uiSelector onclick=userInterfaceSelectMenu(3) title="Fixed width interface"><div class=uiSelector3></div></div><div id=uiViewButton4 class=uiSelector onclick=toggleNightMode() title="Toggle night mode"><div class=uiSelector4></div></div></div></div></div><div id=column_l><h1>Welcome</h1><div id=welcomeText style=display:none>Connect to your home or office devices from anywhere in the world using MeshCentral, the real time, open source remote monitoring and management web site. You will need to download and install a management agent on your computers. Once installed, computers will show up in the &quot;My Devices&quot; section of this web site and you will be able to monitor them and take control of them.</div><table id=centralTable><tr><td id=welcomeimage><picture><img alt=""src=welcome.jpg style=border-radius:20px></picture><td id=logincell><div id=loginpanel style=display:none><form method=post><input type=hidden name=action value=login><div id=message1></div><div><b>Log In</b></div><table><tr><td id=loginusername align=right width=100>Username:<td><input id=username maxlength=64 name=username onchange=validateLogin(1) onkeyup=validateLogin(1,event)><tr><td align=right>Password:<td><input id=password type=password maxlength=256 name=password autocomplete=off onchange=validateLogin(2) onkeyup=validateLogin(2,event)><tr><td><div id=showPassHintLink style=display:none><a onclick="return showPassHint(event)"href=# style=cursor:pointer>Show Hint</a></div><td align=right><input id=loginButton type=submit value="Log In"disabled></table><div id=hrAccountDiv style=display:none><hr></div><div id=resetAccountDiv style=display:none;padding:2px><span id=resetAccountSpan>Forgot username/password?</span> <a onclick="return xgo(3,event)"href=# style=cursor:pointer>Reset account</a>.</div><div id=newAccountDiv style=display:none;padding:2px>Don&#39;t have an account? <a onclick="return xgo(2,event)"href=# style=cursor:pointer>Create one</a>.</div><input id=loginformargs name=urlargs type=hidden></form></div><div id=createpanel style=display:none;position:relative><form method=post><input type=hidden name=action value=createaccount><div id=message2></div><div><b>Account Creation</b></div><div id=passwordPolicyCallout style=display:none></div><table><tr id=nuUserRow><td id=nuUser align=right width=100>Username:<td><input id=ausername name=username onchange=validateCreate(1) maxlength=64 onkeydown=haltReturn(event) onkeyup=validateCreate(1,event)><tr><td id=nuEmail align=right width=100>Email:<td><input id=aemail name=email onchange=validateCreate(2) maxlength=256 onkeydown=haltReturn(event) onkeyup=validateCreate(2,event)><tr><td id=nuPass1 align=right>Password:<td><input id=apassword1 type=password name=password1 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(3,event) onkeyup=validateCreate(3,event)><tr><td id=nuPass2 align=right>Password:<td><input id=apassword2 type=password name=password2 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(4,event) onkeyup=validateCreate(4,event)><tr id=createPanelHint style=display:none><td id=nuHint align=right>Password Hint:<td><input id=apasswordhint name=apasswordhint autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(5,event) onkeyup=validateCreate(5,event)><tr id=newAccountPass title="Enter the account creation token"><td id=nuToken align=right>Creation Token:<td><input id=anewaccountpass type=password name=anewaccountpass autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(6,event) onkeyup=validateCreate(6,event)><tr><td colspan=2><div style=float:right><input id=createButton type=submit value="Create Account"disabled></div><div id=passWarning style=padding-top:6px></div></table><hr><a onclick="return xgo(1,event)"href=# style=cursor:pointer>Back to login</a> <input id=createformargs name=urlargs type=hidden></form></div><div id=resetpanel style=display:none><form method=post><input type=hidden name=action value=resetaccount><div id=message3></div><div><b>Account Reset</b></div><table><tr><td align=right width=100>Email:<td><input id=remail name=email maxlength=256 onchange=validateReset() onkeyup=validateReset(event)><tr><td colspan=2><div style=float:right><input id=eresetButton type=submit value="Reset Account"disabled></div><div id=passWarning style=padding-top:6px></div></table><hr><a onclick="return xgo(1,event)"href=# style=cursor:pointer>Back to login</a> <input id=resetformargs name=urlargs type=hidden></form></div><div id=tokenpanel style=display:none><form method=post autocomplete=off><input type=hidden name=action value=tokenlogin> <input type=hidden name=hwstate value={{{hwstate}}}><div id=message4></div><table><tr><td align=right width=100>Login token:<td><input id=tokenInput name=token maxlength=50 onchange=checkToken(event) onpaste=resetCheckToken(event) onkeyup=checkToken(event) onkeydown=checkToken(event)><br><input id=hwtokenInput name=hwtoken style=display:none><tr><td colspan=2 style=align-content:center><label><input id=tokenInputRemember name=remembertoken type=checkbox>Remember this device for 30 days.</label><tr><td colspan=2><div style=float:right><input id=tokenOkButton type=submit value=Login disabled></div><div style=float:right><input style=display:none;float:right id=securityKeyButton type=button value="Use Security Key"onclick=useSecurityKey()></div></table><hr><a onclick="return xgo(1,event)"href=# style=cursor:pointer>Back to login</a> <input id=tokenformargs name=urlargs type=hidden></form></div><div id=resettokenpanel style=display:none><form method=post><input type=hidden name=action value=resetaccount><div id=message5></div><table><tr><td align=right width=100>Login token:<td><input id=resetTokenInput name=token maxlength=50 onchange=resetCheckToken(event) onkeyup=resetCheckToken(event) onkeydown=resetCheckToken(event)> <input id=resetHwtokenInput name=hwtoken style=display:none><tr><td colspan=2><div style=float:right><input id=resetTokenOkButton type=submit value=Login disabled></div></table><hr><a onclick="return xgo(1,event)"href=# style=cursor:pointer>Back to login</a> <input id=resettokenformargs name=urlargs type=hidden></form></div><div id=resetpasswordpanel style=display:none;position:relative><form method=post><input type=hidden name=action value=resetpassword><div id=message6></div><div id=rpasswordPolicyCallout style=display:none></div><table><tr><td id=rnuPass1 width=100 align=right>Password:<td><input id=rapassword1 type=password name=rpassword1 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validatePassReset(3,event) onkeyup=validatePassReset(3,event)><tr><td id=rnuPass2 align=right>Password:<td><input id=rapassword2 type=password name=rpassword2 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validatePassReset(4,event) onkeyup=validatePassReset(4,event)><tr id=resetpasswordpanelHint style=display:none><td id=rnuHint align=right>Password Hint:<td><input id=rapasswordhint name=rpasswordhint autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validatePassReset(5,event) onkeyup=validatePassReset(5,event)><tr><td colspan=2><div style=float:right><input id=resetPassButton type=submit value="Reset Password"disabled></div><div id=rpassWarning style=padding-top:6px></div></table><hr><a onclick="return xgo(1,event)"href=# style=cursor:pointer>Back to login</a> <input id=resetpasswordformargs name=urlargs type=hidden></form></div></table><br></div><div id=footer><div class=footer1>{{{footer}}}</div><div class=footer2>{{{rootCertLink}}} &nbsp;<a href=terms>Terms &amp; Privacy</a></div></div></div><div id=dialog style=display:none><div id=dialogHeader><div id=id_dialogclose style=float:right;padding:5px;cursor:pointer onclick=setDialogMode()><b>X</b></div><div id=id_dialogtitle style=padding:5px></div><div style=width:100%;margin:6px></div></div><div id=dialogBody><div id=dialog1><div id=id_dialogMessage></div></div><div id=dialog2><div id=id_dialogOptions></div></div></div><div id=idx_dlgButtonBar><input id=idx_dlgCancelButton type=button value=Cancel onclick=dialogclose(0)> <input id=idx_dlgOkButton type=button value=OK onclick=dialogclose(1)></div></div><script>"use strict";var xxdialogMode,xxdialogFunc,xxdialogButtons,xxdialogTag,passhint="{{{passhint}}}",loginMode="{{{loginmode}}}",newAccount="{{{newAccount}}}",newAccountPass=parseInt("{{{newAccountPass}}}"),emailCheck=!1,passRequirements="{{{passRequirements}}}",hardwareKeyChallenge=decodeURIComponent("{{{hkey}}}"),passRequirementsEx=null!=(passRequirements=""!=passRequirements?JSON.parse(decodeURIComponent(passRequirements)):{}).min||null!=passRequirements.max||null!=passRequirements.upper||null!=passRequirements.lower||null!=passRequirements.numeric||null!=passRequirements.nonalpha,features=parseInt("{{{features}}}"),welcomeText=decodeURIComponent("{{{welcometext}}}"),currentpanel=0,uiMode=parseInt(getstore("uiMode","1")),webPageFullScreen=!0,nightMode="1"==getstore("_nightMode","0"),publicKeyCredentialRequestOptions=null,messageid=parseInt("{{{messageid}}}"),okmessages=["","Hold on, reset mail sent."],failmessages=["Unable to create account.","Account limit reached.","Existing account with this email address.","Invalid account creation token.","Username already exists.","Password rejected, use a different one.","Invalid email.","Account not found.","Invalid token, try again.","Unable to sent email.","Account locked.","Access denied.","Login failed, check username and password.","Password change requested.","IP address blocked, try again later."];if(0<messageid){var msg="";if(messageid<100&&messageid<okmessages.length?msg=okmessages[messageid]:100<=messageid&&messageid-100<failmessages.length&&(msg=failmessages[messageid-100]),""!=msg){msg=100<=messageid?'<span class="msg error"><b style=color:#8C001A>'+msg+"<b></span><br /><br />":'<span class="msg success"><b>'+msg+"</b></span><br /><br />";for(var i=1;i<7;i++)QH("message"+i,msg)}}if(0<window.location.href.indexOf("?")){var urlargs=window.location.href.substring(window.location.href.indexOf("?"));Q("loginformargs").value=urlargs,Q("createformargs").value=urlargs,Q("resetformargs").value=urlargs,Q("tokenformargs").value=urlargs,Q("resettokenformargs").value=urlargs,Q("resetpasswordformargs").value=urlargs}function startup(){if(0==(32&features)){var e=null;try{e=top.location.toString().toLowerCase()}catch(e){}if(top!=self&&(null==e||0==top.active))return void(top.location=self.location)}if(2097152&features&&(QH("loginusername","Email:"),QH("resetAccountSpan","Forgot password?"),QV("nuUserRow",!1)),nightMode&&QC("body").add("night"),QV("createPanelHint",!0===passRequirements.hint),QV("resetpasswordpanelHint",!0===passRequirements.hint),welcomeText&&QH("welcomeText",welcomeText),QH("welcomeText",addTextLink("MeshCentral",Q("welcomeText").innerHTML,"http://www.meshcommander.com/meshcentral2")),QV("welcomeText",!0),(window.onresize=center)(),validateLogin(),validateCreate(),0!=loginMode.length?go(parseInt(loginMode)):go(1),QV("newAccountDiv","1"===newAccount||"true"===newAccount),null!=passhint&&0<passhint.length&&QV("showPassHintLink",!0),QV("newAccountPass",1==newAccountPass),QV("resetAccountDiv",1==emailCheck),QV("hrAccountDiv",1==emailCheck||1==newAccountPass),"4"==loginMode){try{hardwareKeyChallenge=0<hardwareKeyChallenge.length?JSON.parse(hardwareKeyChallenge):null}catch(e){hardwareKeyChallenge=null}QV("securityKeyButton",null!=hardwareKeyChallenge&&"webAuthn"==hardwareKeyChallenge.type)}if("5"==loginMode){try{hardwareKeyChallenge=0<hardwareKeyChallenge.length?JSON.parse(hardwareKeyChallenge):null}catch(e){hardwareKeyChallenge=null}if(null!=hardwareKeyChallenge&&"webAuthn"==hardwareKeyChallenge.type){"string"==typeof hardwareKeyChallenge.challenge&&(hardwareKeyChallenge.challenge=Uint8Array.from(atob(hardwareKeyChallenge.challenge),function(e){return e.charCodeAt(0)}).buffer),publicKeyCredentialRequestOptions={challenge:hardwareKeyChallenge.challenge,allowCredentials:[],timeout:hardwareKeyChallenge.timeout};for(var a=0;a<hardwareKeyChallenge.keyIds.length;a++)publicKeyCredentialRequestOptions.allowCredentials.push({id:Uint8Array.from(atob(hardwareKeyChallenge.keyIds[a]),function(e){return e.charCodeAt(0)}),type:"public-key",transports:["usb","ble","nfc"]});navigator.credentials.get({publicKey:publicKeyCredentialRequestOptions}).then(function(e){var a={id:btoa(String.fromCharCode.apply(null,new Uint8Array(e.rawId))),clientDataJSON:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.clientDataJSON))),userHandle:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.userHandle))),signature:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.signature))),authenticatorData:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.authenticatorData)))};Q("resetHwtokenInput").value=JSON.stringify(a),QE("resetTokenOkButton",!0),Q("resetTokenOkButton").click()},function(e){console.log("credentials-get error",e)})}}userInterfaceSelectMenu()}function useSecurityKey(){if(null!=hardwareKeyChallenge&&"webAuthn"==hardwareKeyChallenge.type){"string"==typeof hardwareKeyChallenge.challenge&&(hardwareKeyChallenge.challenge=Uint8Array.from(atob(hardwareKeyChallenge.challenge),function(e){return e.charCodeAt(0)}).buffer),publicKeyCredentialRequestOptions={challenge:hardwareKeyChallenge.challenge,allowCredentials:[],timeout:hardwareKeyChallenge.timeout};for(var e=0;e<hardwareKeyChallenge.keyIds.length;e++)publicKeyCredentialRequestOptions.allowCredentials.push({id:Uint8Array.from(atob(hardwareKeyChallenge.keyIds[e]),function(e){return e.charCodeAt(0)}),type:"public-key",transports:["usb","ble","nfc"]});navigator.credentials.get({publicKey:publicKeyCredentialRequestOptions}).then(function(e){var a={id:btoa(String.fromCharCode.apply(null,new Uint8Array(e.rawId))),clientDataJSON:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.clientDataJSON))),userHandle:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.userHandle))),signature:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.signature))),authenticatorData:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.authenticatorData)))};Q("hwtokenInput").value=JSON.stringify(a),QE("tokenOkButton",!0),Q("tokenOkButton").click()},function(e){console.log("credentials-get error",e)})}}function showPassHint(e){return messagebox("Password Hint",passhint),haltEvent(e),!1}function xgo(e,a){return QV("message1",!1),QV("message2",!1),QV("message3",!1),QV("message4",!1),QV("message5",!1),QV("message6",!1),go(e),haltEvent(a),!1}function go(e){currentpanel=e,setDialogMode(0),QV("showPassHintLink",!1),QV("loginpanel",1==e),QV("createpanel",2==e),QV("resetpanel",3==e),QV("tokenpanel",4==e),QV("resettokenpanel",5==e),QV("resetpasswordpanel",6==e),1==e&&Q("username").focus(),2==e&&(2097152&features?Q("aemail").focus():Q("ausername").focus()),3==e&&Q("remail").focus(),4==e&&Q("tokenInput").focus(),5==e&&Q("resetTokenInput").focus(),6==e&&Q("rapassword1").focus()}function validateLogin(e,a){var n=0<Q("username").value.length&&-1==Q("username").value.indexOf(" ")&&0<Q("password").value.length;QE("loginButton",n),setDialogMode(0),null!=a&&13==a.keyCode&&(1==e&&""!=Q("username").value?Q("password").focus():2==e&&""!=Q("password").value&&Q("loginButton").click()),null!=a&&haltEvent(a)}function validateCreate(e,a){setDialogMode(0);var n=!1;n=!!(2097152&features)||0<Q("ausername").value.length&&-1==Q("ausername").value.indexOf(" ")&&-1==Q("ausername").value.indexOf('"')&&-1==Q("ausername").value.indexOf(",");var t=1==validateEmail(Q("aemail").value),r=0<Q("apassword1").value.length,s=0<Q("apassword2").value.length&&Q("apassword2").value==Q("apassword1").value,o=0==newAccountPass||0<Q("anewaccountpass").value.length,l=n&&t&&r&&s&&o;if(QS("nuUser").color=n?"black":"#7b241c",QS("nuEmail").color=t?"black":"#7b241c",QS("nuPass1").color=r?"black":"#7b241c",QS("nuPass2").color=s?"black":"#7b241c",QS("nuToken").color=o?"black":"#7b241c",""==Q("apassword1").value)QH("passWarning",""),QV("passwordPolicyCallout",!1);else if(passRequirementsEx){0==checkPasswordRequirements(Q("apassword1").value,passRequirements)?(l=!1,QS("nuPass1").color="#7b241c",QS("nuPass2").color="#7b241c",QH("passWarning","<div style=color:red;cursor:pointer onclick=showPasswordPolicy()><b>Password Policy</b><div>"),QV("passwordPolicyCallout",!0),QH("passwordPolicyCallout",passwordPolicyText(Q("apassword1").value))):(QH("passWarning",""),QV("passwordPolicyCallout",!1))}else{var i=checkPasswordStrength(Q("apassword1").value);80<=i?QH("passWarning","<span style=color:green><b>Strong Password</b><span>"):60<=i?QH("passWarning","<span style=color:blue><b>Good Password</b><span>"):QH("passWarning","<span style=color:red><b>Weak Password</b><span>")}null!=a&&13==a.keyCode&&(1==e&&n&&Q("aemail").focus(),2==e&&t&&Q("apassword1").focus(),3==e&&r&&Q("apassword2").focus(),4==e&&s&&(!0===passRequirements.hint?Q("apasswordhint").focus():e=5),5==e&&(1==newAccountPass?Q("anewaccountpass").focus():e=6),6==e&&Q("createButton").click()),null!=a&&haltEvent(a),QE("createButton",l)}function validatePassReset(e,a){setDialogMode(0);var n=0<Q("rapassword1").value.length,t=0<Q("rapassword2").value.length&&Q("rapassword2").value==Q("rapassword1").value,r=n&&t;if(QS("rnuPass1").color=n?"black":"#7b241c",QS("rnuPass2").color=t?"black":"#7b241c",""==Q("rapassword1").value)QH("rpassWarning",""),QV("rpasswordPolicyCallout",!1);else if(passRequirementsEx){0==checkPasswordRequirements(Q("rapassword1").value,passRequirements)?(r=!1,QS("rnuPass1").color="#7b241c",QS("rnuPass2").color="#7b241c",QH("rpassWarning","<div style=color:red;cursor:pointer onclick=showPasswordPolicy()><b>Password Policy</b><div>"),QV("rpasswordPolicyCallout",!0),QH("rpasswordPolicyCallout",passwordPolicyText(Q("rapassword1").value))):(QH("rpassWarning",""),QV("rpasswordPolicyCallout",!1))}else{var s=checkPasswordStrength(Q("rapassword1").value);80<=s?QH("rpassWarning","<span style=color:green><b>Strong Password</b><span>"):60<=s?QH("rpassWarning","<span style=color:blue><b>Good Password</b><span>"):QH("rpassWarning","<span style=color:red><b>Weak Password</b><span>")}null!=a&&13==a.keyCode&&(2==e&&Q("rapassword1").focus(),3==e&&Q("rapassword2").focus(),4==e&&Q("rapasswordhint").focus(),6==e&&Q("resetPassButton").click()),null!=a&&haltEvent(a),QE("resetPassButton",r)}function passwordPolicyText(e){var a="<div style=text-align:left>",n=strCount(e);return passRequirements.min&&(null==e||e.length<passRequirements.min)&&(a+=format("Minimum length of {0}",passRequirements.min)+"<br />"),passRequirements.max&&(null==e||e.length>passRequirements.max)&&(a+=format("Maximum length of {0}",passRequirements.max)+"<br />"),passRequirements.upper&&(null==e||n.upper<passRequirements.upper)&&(a+=format("{0} upper case",passRequirements.upper)+"<br />"),passRequirements.lower&&(null==e||n.lower<passRequirements.lower)&&(a+=format("{0} lower case",passRequirements.lower)+"<br />"),passRequirements.numeric&&(null==e||n.numeric<passRequirements.numeric)&&(a+=format("{0} numeric",passRequirements.numeric)+"<br />"),passRequirements.nonalpha&&(null==e||n.nonalpha<passRequirements.nonalpha)&&(a+=format("{0} non-alphanumeric",passRequirements.nonalpha)+"<br />"),a+="</div>"}function showPasswordPolicy(){messagebox("Password Policy",passwordPolicyText())}function validateReset(e){setDialogMode(0);var a=validateEmail(Q("remail").value);QE("eresetButton",a),null!=e&&13==e.keyCode&&1==a&&Q("eresetButton").click(),null!=e&&haltEvent(e)}function checkPasswordStrength(e){var a=0,n={},t=0,r={digits:/\d/.test(e),lower:/[a-z]/.test(e),upper:/[A-Z]/.test(e),nonWords:/\W/.test(e)};if(!e)return 0;for(var s=0;s<e.length;s++)n[e[s]]=(n[e[s]]||0)+1,a+=5/n[e[s]];for(var o in r)t+=1==r[o]?1:0;return parseInt(a+10*(t-1))}function checkPasswordRequirements(e,a){if(null==a||""==a||"object"!=typeof a)return!0;if(a.min&&e.length<a.min)return!1;if(a.max&&e.length>a.max)return!1;var n=strCount(e);return!(a.numeric&&n.numeric<a.numeric)&&(!(a.lower&&n.lower<a.lower)&&(!(a.upper&&n.upper<a.upper)&&!(a.nonalpha&&n.nonalpha<a.nonalpha)))}function strCount(e){var a={numeric:0,lower:0,upper:0,nonalpha:0};if("string"!=typeof e)return a;for(var n=0;n<e.length;n++)/\d/.test(e[n])&&a.numeric++,/[a-z]/.test(e[n])&&a.lower++,/[A-Z]/.test(e[n])&&a.upper++,/\W/.test(e[n])&&a.nonalpha++;return a}function checkToken(){var e=Q("tokenInput").value,a=e.split(" ").join("");e!=a&&(Q("tokenInput").value=a),QE("tokenOkButton",6==Q("tokenInput").value.length||8==Q("tokenInput").value.length||44==Q("tokenInput").value.length)}function resetCheckToken(){var e=Q("resetTokenInput").value,a=e.split(" ").join("");e!=a&&(Q("resetTokenInput").value=a),QE("resetTokenOkButton",6==Q("resetTokenInput").value.length||8==Q("resetTokenInput").value.length||44==Q("resetTokenInput").value.length)}var xxcurrentView=0;function setDialogMode(e,a,n,t,r,s){xxdialogMode=e,xxdialogFunc=t,xxdialogButtons=n,xxdialogTag=s,QE("idx_dlgOkButton",!0),QV("idx_dlgOkButton",1&n),QV("idx_dlgCancelButton",2&n),QV("id_dialogclose",2&n||8&n),QV("idx_dlgButtonBar",7&n),a&&QH("id_dialogtitle",a);for(var o=1;o<24;o++)QV("dialog"+o,o==e);QV("dialog",e),r&&(2==e?QH("id_dialogOptions",r):QH("id_dialogMessage",r))}function dialogclose(e){var a=xxdialogFunc,n=xxdialogButtons,t=xxdialogTag;setDialogMode(),(8&n||e)&&a&&a(e,t)}function toggleFullScreen(e){0==webPageFullScreen?QC("body").remove("fullscreen"):QC("body").add("fullscreen"),QV("body",!0),center()}function showUserInterfaceSelectMenu(){Q("uiViewButton1").classList.remove("uiSelectorSel"),Q("uiViewButton2").classList.remove("uiSelectorSel"),Q("uiViewButton3").classList.remove("uiSelectorSel");try{Q("uiViewButton"+uiMode).classList.add("uiSelectorSel")}catch(e){}QV("uiMenu","none"==QS("uiMenu").display),nightMode&&Q("uiViewButton4").classList.add("uiSelectorSel")}function userInterfaceSelectMenu(e){e&&putstore("uiMode",uiMode=e),webPageFullScreen=uiMode<3,toggleFullScreen(0)}function toggleNightMode(){(nightMode=!nightMode)?QC("body").add("night"):QC("body").remove("night"),putstore("_nightMode",nightMode?"1":"0")}function center(){if(0==webPageFullScreen)QS("centralTable")["margin-top"]="";else{var e=Q("column_l").clientHeight/2-220;e<0&&(e=0),QS("centralTable")["margin-top"]=e+"px"}}function messagebox(e,a){QH("id_dialogMessage",a),setDialogMode(1,e,1)}function statusbox(e,a){QH("id_dialogMessage",a),setDialogMode(1,e)}function getDocWidth(){return window.innerWidth?window.innerWidth:document.documentElement&&document.documentElement.clientWidth&&0!=document.documentElement.clientWidth?document.documentElement.clientWidth:document.getElementsByTagName("body")[0].clientWidth}function haltEvent(e){return e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation(),!1}function haltReturn(e){13==e.keyCode&&haltEvent(e)}function validateEmail(e){return/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(e)}function putstore(e,a){try{if("undefined"==typeof localStorage)return;localStorage.setItem(e,a)}catch(e){}}function getstore(e,a){try{if("undefined"==typeof localStorage)return a;var n=localStorage.getItem(e);return null==n||null==n?a:n}catch(e){return a}}function format(e){var n=Array.prototype.slice.call(arguments,1);return e.replace(/{(\d+)}/g,function(e,a){return void 0!==n[a]?n[a]:e})}function addTextLink(e,a,n){var t=a.toLowerCase().indexOf(e.toLowerCase());return-1==t?a:a.substring(0,t)+'<a href="'+n+'">'+e+"</a>"+a.substring(t+e.length)}</script>
\ No newline at end of file
views/login-mobile-min.handlebars deleted
-1
@@ -1 +0,0 @@
1 -<!doctypehtml><html dir=ltr xmlns=http://www.w3.org/1999/xhtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html; charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link rel="shortcut icon"type=image/x-icon href={{{domainurl}}}favicon.ico><script src=scripts/common-0.0.1.js></script><script src=scripts/u2f-api.js></script><title>{{{title}}} - Login</title><style>a{color:#036;text-decoration:underline}#footer a{color:#fff;text-decoration:underline}#footer a:hover{color:#fff;text-decoration:none}</style><body onload='"undefined"!=typeof startup&&startup()'style="overflow-y:hidden;margin:0;padding:0;border:0;color:#000;font-size:13px;font-family:\'Trebuchet MS\',Arial,Helvetica,sans-serif"><div id=container><div id=mastheadx></div><div id=masthead style="background:url(logo.png) 0 0;background-size:341px 50px;background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden"><div style=float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:6px><strong><font style=font-size:36px;font-family:Arial,Helvetica,sans-serif>{{{title}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:10px><strong><font style=font-size:12px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div></div><div id=page_content style=overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%;display:flex;align-items:center><div id=column_l style=padding:10px;width:100%><table style=width:100%><tr><td align=center><div id=loginpanel style=background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;clear:both;display:none><form method=post><input type=hidden name=action value=login><div id=message1></div><div><b>Log In</b></div><table><tr><td id=loginusername align=right width=100>Username:<td><input id=username maxlength=64 name=username onchange=validateLogin(1) onkeyup=validateLogin(1,event)><tr><td align=right>Password:<td><input id=password type=password maxlength=256 name=password autocomplete=off onchange=validateLogin(2) onkeyup=validateLogin(2,event)><tr><td><div id=showPassHintLink style=display:none><a onclick=showPassHint() style=cursor:pointer>Show Hint</a></div><td align=right><input id=loginButton type=submit value="Log In"disabled></table><div id=hrAccountDiv style=display:none><hr></div><div id=resetAccountDiv style=display:none;padding:2px><span id=resetAccountSpan>Forgot user/password?</span> <a onclick=xgo(3) style=cursor:pointer>Reset account</a>.</div><div id=newAccountDiv style=display:none;padding:2px>Don&#39;t have an account? <a onclick=xgo(2) style=cursor:pointer>Create one</a>.</div><input id=loginformargs name=urlargs type=hidden></form></div><div id=createpanel style=display:none><div style=background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;clear:both;position:relative><form method=post><input type=hidden name=action value=createaccount><div id=message2></div><div><b>Account Creation</b></div><div id=passwordPolicyCallout style="left:-5px;top:10px;width:100px;position:absolute;background-color:#ffc;border-radius:5px;padding:5px;box-shadow:0 0 15px #666;font-size:10px"></div><table><tr id=nuUserRow><td align=right width=100>Username:<td><input id=ausername name=username onchange=validateCreate(1) maxlength=64 onkeydown=haltReturn(event) onkeyup=validateCreate(1,event)><tr><td align=right width=100>Email:<td><input id=aemail name=email onchange=validateCreate(2) maxlength=256 onkeydown=haltReturn(event) onkeyup=validateCreate(2,event)><tr><td align=right>Password:<td><input id=apassword1 type=password name=password1 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(3) onkeyup=validateCreate(3,event)><tr><td align=right>Password:<td><input id=apassword2 type=password name=password2 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(4) onkeyup=validateCreate(4,event)><tr id=createPanelHint style=display:none><td align=right>Pass Hint:<td><input id=apasswordhint name=apasswordhint autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(5) onkeyup=validateCreate(5,event)><tr id=newAccountPass title="Enter the account creation token"><td align=right>Creation Token:<td><input id=anewaccountpass type=password name=anewaccountpass autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(6) onkeyup=validateCreate(6,event)><tr><td colspan=2><div style=float:right><input id=createButton type=submit value="Create Account"disabled></div><div id=passWarning style=padding-top:6px></div></table><hr><a onclick=xgo(1) style=cursor:pointer>Back to login</a> <input id=createformargs name=urlargs type=hidden></form></div></div><div id=resetpanel style=background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none;clear:both><form method=post><input type=hidden name=action value=resetaccount><div id=message3></div><div><b>Account Reset</b></div><table><tr><td align=right width=100>Email:<td><input id=remail name=email maxlength=256 onchange=validateReset() onkeyup=validateReset(event)><tr><td colspan=2><div style=float:right><input id=eresetButton type=submit value="Reset Account"disabled></div><div id=passWarning style=padding-top:6px></div></table><hr><a onclick=xgo(1) style=cursor:pointer>Back to login</a> <input id=resetformargs name=urlargs type=hidden></form></div><div id=tokenpanel style=background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none;clear:both><form method=post autocomplete=off><input type=hidden name=action value=tokenlogin> <input type=hidden name=hwstate value={{{hwstate}}}><div id=message4></div><table><tr><td align=right width=100>Login token:<td><input id=tokenInput name=token maxlength=50 onchange=checkToken(event) onkeyup=checkToken(event) onkeydown=checkToken(event) onfocus=checkTokenTimer(1) onblur=checkTokenTimer(0)> <input id=hwtokenInput name=hwtoken style=display:none><tr><td colspan=2 style=align-content:center><label><input id=tokenInputRemember name=remembertoken type=checkbox>Remember this device for 30 days.</label><tr><td colspan=2><div style=float:right><input id=tokenOkButton type=submit value=Login disabled></div><div style=float:right><input style=display:none;float:right id=securityKeyButton type=button value="Use Security Key"onclick=useSecurityKey()></div></table><hr><a onclick=xgo(1) style=cursor:pointer>Back to login</a> <input id=tokenformargs name=urlargs type=hidden></form></div><div id=resettokenpanel style=background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none;clear:both><form method=post autocomplete=off><input type=hidden name=action value=resetaccount><div id=message5></div><table><tr><td align=right width=100>Login token:<td><input id=resetTokenInput name=token maxlength=50 onchange=resetCheckToken(event) onpaste=resetCheckToken(event) onkeyup=resetCheckToken(event) onkeydown=resetCheckToken(event)> <input id=resetHwtokenInput name=hwtoken style=display:none><tr><td colspan=2><div style=float:right><input id=resetTokenOkButton type=submit value=Login disabled></div></table><hr><a onclick=xgo(1) style=cursor:pointer>Back to login</a> <input id=resettokenformargs name=urlargs type=hidden></form></div><div id=resetpasswordpanel style=position:relative;background-color:#979797;border-radius:16px;width:300px;padding:16px;text-align:center;display:none><form method=post><input type=hidden name=action value=resetpassword><div id=message6></div><div id=rpasswordPolicyCallout style="left:-10px;width:100px;display:none;position:absolute;background-color:#ffc;border-radius:5px;padding:5px;box-shadow:0 0 15px #666;font-size:10px"></div><table><tr><td id=rnuPass1 width=100 align=right>Password:<td><input id=rapassword1 type=password name=rpassword1 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validatePassReset(3,event) onkeyup=validatePassReset(3,event)><tr><td id=rnuPass2 align=right>Password:<td><input id=rapassword2 type=password name=rpassword2 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validatePassReset(4,event) onkeyup=validatePassReset(4,event)><tr id=resetpasswordpanelHint style=display:none><td id=rnuHint align=right>Password Hint:<td><input id=rapasswordhint name=rpasswordhint autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validatePassReset(5,event) onkeyup=validatePassReset(5,event)><tr><td colspan=2><div style=float:right><input id=resetPassButton type=submit value="Reset Password"disabled></div><div id=rpassWarning style=padding-top:6px></div></table><hr><a onclick=xgo(1) style=cursor:pointer>Back to login</a> <input id=resetpasswordformargs name=urlargs type=hidden></form></div></table></div></div><div id=footer style=height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0><table cellpadding=0 cellspacing=6 style=width:100%><tr><td style=text-align:left;color:#fff>{{{footer}}}<td style=text-align:right>{{{rootCertLink}}}&nbsp;<a href=terms>Terms &amp; Privacy</a></table></div></div><div id=dialog style="z-index:1000;background-color:#eee;box-shadow:0 0 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:5px;position:fixed;top:180px;width:400px;display:none"><div style="width:100%;background-color:#036;color:#fff;border-radius:5px 5px 0 0"><div id=id_dialogclose style=float:right;padding:5px;cursor:pointer onclick=setDialogMode()><b>X</b></div><div id=id_dialogtitle style=padding:5px></div><div style=width:100%;margin:6px></div></div><div style=margin-right:16px;margin-left:8px><div id=dialog1 style=margin:auto;text-align:center;margin:3px><div id=id_dialogMessage style=padding:10px></div></div><div id=dialog2 style=margin:auto;margin:3px><div id=id_dialogOptions></div></div></div><div id=idx_dlgButtonBar style=padding:10px;margin-bottom:20px><input id=idx_dlgCancelButton type=button value=Cancel style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)> <input id=idx_dlgOkButton type=button value=OK style=float:right;width:80px onclick=dialogclose(1)></div></div><script>"use strict";var loginMode="{{{loginmode}}}",newAccount="{{{newAccount}}}",passhint="{{{passhint}}}",newAccountPass=parseInt("{{{newAccountPass}}}"),emailCheck=!1,features=parseInt("{{{features}}}"),passRequirements="{{{passRequirements}}}",passRequirementsEx=null!=(passRequirements=""!=passRequirements?JSON.parse(decodeURIComponent(passRequirements)):{}).min||null!=passRequirements.max||null!=passRequirements.upper||null!=passRequirements.lower||null!=passRequirements.numeric||null!=passRequirements.nonalpha,hardwareKeyChallenge=decodeURIComponent("{{{hkey}}}"),publicKeyCredentialRequestOptions=null,currentpanel=0,messageid=parseInt("{{{messageid}}}"),okmessages=["","Hold on, reset mail sent."],failmessages=["Unable to create account.","Account limit reached.","Existing account with this email address.","Invalid account creation token.","Username already exists.","Password rejected, use a different one.","Invalid email.","Account not found.","Invalid token, try again.","Unable to sent email.","Account locked.","Access denied.","Login failed, check username and password.","Password change requested.","IP address blocked, try again later."];if(0<messageid){var msg="";if(messageid<100&&messageid<okmessages.length?msg=okmessages[messageid]:100<=messageid&&messageid-100<failmessages.length&&(msg=failmessages[messageid-100]),""!=msg){msg=100<=messageid?'<span class="msg error"><b style=color:#8C001A>'+msg+"<b></span><br /><br />":'<span class="msg success"><b>'+msg+"</b></span><br /><br />";for(var i=1;i<7;i++)QH("message"+i,msg)}}if(0<window.location.href.indexOf("?")){var urlargs=window.location.href.substring(window.location.href.indexOf("?"));Q("loginformargs").value=urlargs,Q("createformargs").value=urlargs,Q("resetformargs").value=urlargs,Q("tokenformargs").value=urlargs,Q("resettokenformargs").value=urlargs,Q("resetpasswordformargs").value=urlargs}function startup(){if(0==(32&features)){var e=null;try{e=top.location.toString().toLowerCase()}catch(e){}if(top!=self&&(null==e||0==top.active))return void(top.location=self.location)}if(2097152&features&&(QH("loginusername","Email:"),QH("resetAccountSpan","Forgot password?"),QV("nuUserRow",!1)),QV("createPanelHint",!0===passRequirements.hint),QV("resetpasswordpanelHint",!0===passRequirements.hint),(window.onresize=center)(),validateLogin(),validateCreate(),0!=loginMode.length?go(parseInt(loginMode)):go(1),QV("newAccountDiv","1"===newAccount||"true"===newAccount),!0===passRequirements.hint&&null!=passhint&&0<passhint.length&&QV("showPassHintLink",!0),QV("newAccountPass",1==newAccountPass),QV("resetAccountDiv",1==emailCheck),QV("hrAccountDiv",1==emailCheck||1==newAccountPass),"4"==loginMode){try{hardwareKeyChallenge=0<hardwareKeyChallenge.length?JSON.parse(hardwareKeyChallenge):null}catch(e){hardwareKeyChallenge=null}QV("securityKeyButton",null!=hardwareKeyChallenge&&"webAuthn"==hardwareKeyChallenge.type)}if("5"==loginMode){try{hardwareKeyChallenge=0<hardwareKeyChallenge.length?JSON.parse(hardwareKeyChallenge):null}catch(e){hardwareKeyChallenge=null}if(null!=hardwareKeyChallenge&&"webAuthn"==hardwareKeyChallenge.type){"string"==typeof hardwareKeyChallenge.challenge&&(hardwareKeyChallenge.challenge=Uint8Array.from(atob(hardwareKeyChallenge.challenge),function(e){return e.charCodeAt(0)}).buffer),publicKeyCredentialRequestOptions={challenge:hardwareKeyChallenge.challenge,allowCredentials:[],timeout:hardwareKeyChallenge.timeout};for(var a=0;a<hardwareKeyChallenge.keyIds.length;a++)publicKeyCredentialRequestOptions.allowCredentials.push({id:Uint8Array.from(atob(hardwareKeyChallenge.keyIds[a]),function(e){return e.charCodeAt(0)}),type:"public-key",transports:["usb","ble","nfc"]});navigator.credentials.get({publicKey:publicKeyCredentialRequestOptions}).then(function(e){var a={id:btoa(String.fromCharCode.apply(null,new Uint8Array(e.rawId))),clientDataJSON:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.clientDataJSON))),userHandle:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.userHandle))),signature:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.signature))),authenticatorData:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.authenticatorData)))};Q("resetHwtokenInput").value=JSON.stringify(a),QE("resetTokenOkButton",!0),Q("resetTokenOkButton").click()},function(e){console.log("credentials-get error",e)})}}}function useSecurityKey(){if(null!=hardwareKeyChallenge&&"webAuthn"==hardwareKeyChallenge.type){"string"==typeof hardwareKeyChallenge.challenge&&(hardwareKeyChallenge.challenge=Uint8Array.from(atob(hardwareKeyChallenge.challenge),function(e){return e.charCodeAt(0)}).buffer),publicKeyCredentialRequestOptions={challenge:hardwareKeyChallenge.challenge,allowCredentials:[],timeout:hardwareKeyChallenge.timeout};for(var e=0;e<hardwareKeyChallenge.keyIds.length;e++)publicKeyCredentialRequestOptions.allowCredentials.push({id:Uint8Array.from(atob(hardwareKeyChallenge.keyIds[e]),function(e){return e.charCodeAt(0)}),type:"public-key",transports:["usb","ble","nfc"]});navigator.credentials.get({publicKey:publicKeyCredentialRequestOptions}).then(function(e){var a={id:btoa(String.fromCharCode.apply(null,new Uint8Array(e.rawId))),clientDataJSON:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.clientDataJSON))),userHandle:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.userHandle))),signature:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.signature))),authenticatorData:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.authenticatorData)))};Q("hwtokenInput").value=JSON.stringify(a),QE("tokenOkButton",!0),Q("tokenOkButton").click()},function(e){console.log("credentials-get error",e)})}}function showPassHint(){!0===passRequirements.hint&&messagebox("Password Hint",passhint)}function xgo(e){QV("message1",!1),QV("message2",!1),QV("message3",!1),QV("message4",!1),QV("message5",!1),QV("message6",!1),go(e)}function go(e){currentpanel=e,setDialogMode(0),QV("showPassHintLink",!1),QV("loginpanel",1==e),QV("createpanel",2==e),QV("resetpanel",3==e),QV("tokenpanel",4==e),QV("resettokenpanel",5==e),QV("resetpasswordpanel",6==e),1==e&&Q("username").focus(),2==e&&(2097152&features?Q("aemail").focus():Q("ausername").focus()),3==e&&Q("remail").focus(),4==e&&Q("tokenInput").focus(),5==e&&Q("resetTokenInput").focus(),6==e&&Q("rapassword1").focus()}function validateLogin(e,a){var n=0<Q("username").value.length&&-1==Q("username").value.indexOf(" ")&&0<Q("password").value.length;QE("loginButton",n),setDialogMode(0),null!=a&&13==a.keyCode&&(1==e?Q("password").focus():2==e&&Q("loginButton").click()),null!=a&&haltEvent(a)}function validateCreate(e,a){setDialogMode(0);var n=!1;if(n=!!(2097152&features)||0<Q("ausername").value.length&&-1==Q("ausername").value.indexOf(" ")&&-1==Q("ausername").value.indexOf('"')&&-1==Q("ausername").value.indexOf(","),n&=1==validateEmail(Q("aemail").value)&&0<Q("apassword1").value.length&&Q("apassword2").value==Q("apassword1").value,1==newAccountPass&&0==Q("anewaccountpass").value.length&&(n=!1),""==Q("apassword1").value)QH("passWarning",""),QV("passwordPolicyCallout",!1);else if(passRequirementsEx){0==checkPasswordRequirements(Q("apassword1").value,passRequirements)?(n=!1,QH("passWarning","<span style=color:red><b>Password Policy</b><span>"),QV("passwordPolicyCallout",!0),QH("passwordPolicyCallout",passwordPolicyText(Q("apassword1").value))):(QH("passWarning",""),QV("passwordPolicyCallout",!1))}else{var s=checkPasswordStrength(Q("apassword1").value);80<=s?QH("passWarning","<span style=color:green><b>Strong Password</b><span>"):60<=s?QH("passWarning","<span style=color:blue><b>Good Password</b><span>"):QH("passWarning","<span style=color:red><b>Weak Password</b><span>")}QE("createButton",n),null!=a&&13==a.keyCode&&(1==e&&Q("aemail").focus(),2==e&&Q("apassword1").focus(),3==e&&Q("apassword2").focus(),4==e&&Q("apasswordhint").focus(),5==e&&(1==newAccountPass?Q("anewaccountpass").focus():Q("createButton").click()),6==e&&Q("createButton").click()),null!=a&&haltEvent(a)}function validatePassReset(e,a){setDialogMode(0);var n=0<Q("rapassword1").value.length,s=0<Q("rapassword2").value.length&&Q("rapassword2").value==Q("rapassword1").value,t=n&&s;if(QS("rnuPass1").color=n?"black":"#7b241c",QS("rnuPass2").color=s?"black":"#7b241c",""==Q("rapassword1").value)QH("rpassWarning",""),QV("rpasswordPolicyCallout",!1);else if(passRequirementsEx){0==checkPasswordRequirements(Q("rapassword1").value,passRequirements)?(t=!1,QS("rnuPass1").color="#7b241c",QS("rnuPass2").color="#7b241c",QH("rpassWarning","<div style=color:red;cursor:pointer onclick=showPasswordPolicy()><b>Password Policy</b><div>"),QV("rpasswordPolicyCallout",!0),QH("rpasswordPolicyCallout",passwordPolicyText(Q("rapassword1").value))):(QH("rpassWarning",""),QV("rpasswordPolicyCallout",!1))}else{var r=checkPasswordStrength(Q("rapassword1").value);80<=r?QH("rpassWarning","<span style=color:green><b>Strong Password</b><span>"):60<=r?QH("rpassWarning","<span style=color:blue><b>Good Password</b><span>"):QH("rpassWarning","<span style=color:red><b>Weak Password</b><span>")}null!=a&&13==a.keyCode&&(2==e&&Q("rapassword1").focus(),3==e&&Q("rapassword2").focus(),4==e&&Q("rapasswordhint").focus(),6==e&&Q("resetPassButton").click()),null!=a&&haltEvent(a),QE("resetPassButton",t)}function validateReset(e){setDialogMode(0);var a=validateEmail(Q("remail").value);QE("eresetButton",a),null!=e&&13==e.keyCode&&1==a&&Q("eresetButton").click(),null!=e&&haltEvent(e)}function passwordPolicyText(e){var a="<div style=text-align:left>",n=strCount(e);return passRequirements.min&&(null==e||e.length<passRequirements.min)&&(a+=format("Minimum length of {0}",passRequirements.min)+"<br />"),passRequirements.max&&(null==e||e.length>passRequirements.max)&&(a+=format("Maximum length of {0}",passRequirements.max)+"<br />"),passRequirements.upper&&(null==e||n.upper<passRequirements.upper)&&(a+=format("{0} upper case",passRequirements.upper)+"<br />"),passRequirements.lower&&(null==e||n.lower<passRequirements.lower)&&(a+=format("{0} lower case",passRequirements.lower)+"<br />"),passRequirements.numeric&&(null==e||n.numeric<passRequirements.numeric)&&(a+=format("{0} numeric",passRequirements.numeric)+"<br />"),passRequirements.nonalpha&&(null==e||n.nonalpha<passRequirements.nonalpha)&&(a+=format("{0} non-alphanumeric",passRequirements.nonalpha)+"<br />"),a+="</div>"}function checkPasswordStrength(e){var a=0,n={},s=0,t={digits:/\d/.test(e),lower:/[a-z]/.test(e),upper:/[A-Z]/.test(e),nonWords:/\W/.test(e)};if(!e)return 0;for(var r=0;r<e.length;r++)n[e[r]]=(n[e[r]]||0)+1,a+=5/n[e[r]];for(var l in t)s+=1==t[l]?1:0;return parseInt(a+10*(s-1))}function checkPasswordRequirements(e,a){if(null==a||""==a||"object"!=typeof a)return!0;if(a.min&&e.length<a.min)return!1;if(a.max&&e.length>a.max)return!1;var n=strCount(e);return!(a.numeric&&n.numeric<a.numeric)&&(!(a.lower&&n.lower<a.lower)&&(!(a.upper&&n.upper<a.upper)&&!(a.nonalpha&&n.nonalpha<a.nonalpha)))}function strCount(e){var a={numeric:0,lower:0,upper:0,nonalpha:0};if("string"!=typeof e)return a;for(var n=0;n<e.length;n++)/\d/.test(e[n])&&a.numeric++,/[a-z]/.test(e[n])&&a.lower++,/[A-Z]/.test(e[n])&&a.upper++,/\W/.test(e[n])&&a.nonalpha++;return a}var xxdialogMode,xxdialogFunc,xxdialogButtons,xxdialogTag,xcheckTokenTimer=null;function checkTokenTimer(e){0==e&&null!=xcheckTokenTimer&&(clearInterval(xcheckTokenTimer),xcheckTokenTimer=null),1==e&&null==xcheckTokenTimer&&(xcheckTokenTimer=setInterval(checkToken,200))}function checkToken(){var e=Q("tokenInput").value,a=e.split(" ").join("");e!=a&&(Q("tokenInput").value=a),QE("tokenOkButton",6==Q("tokenInput").value.length||8==Q("tokenInput").value.length||44==Q("tokenInput").value.length)}function resetCheckToken(){var e=Q("resetTokenInput").value,a=e.split(" ").join("");e!=a&&(Q("resetTokenInput").value=a),QE("resetTokenOkButton",6==Q("resetTokenInput").value.length||8==Q("resetTokenInput").value.length||44==Q("resetTokenInput").value.length)}var xxcurrentView=0;function setDialogMode(e,a,n,s,t,r){xxdialogMode=e,xxdialogFunc=s,xxdialogButtons=n,xxdialogTag=r,QE("idx_dlgOkButton",!0),QV("idx_dlgOkButton",1&n),QV("idx_dlgCancelButton",2&n),QV("id_dialogclose",2&n||8&n),QV("idx_dlgButtonBar",7&n),a&&QH("id_dialogtitle",a);for(var l=1;l<24;l++)QV("dialog"+l,l==e);QV("dialog",e),t&&(2==e?QH("id_dialogOptions",t):QH("id_dialogMessage",t))}function dialogclose(e){var a=xxdialogFunc,n=xxdialogButtons,s=xxdialogTag;setDialogMode(),(8&n||e)&&a&&a(e,s)}function center(){QS("dialog").left=(getDocWidth()-400)/2+"px"}function messagebox(e,a){QH("id_dialogMessage",a),setDialogMode(1,e,1)}function statusbox(e,a){QH("id_dialogMessage",a),setDialogMode(1,e)}function getDocWidth(){return window.innerWidth?window.innerWidth:document.documentElement&&document.documentElement.clientWidth&&0!=document.documentElement.clientWidth?document.documentElement.clientWidth:document.getElementsByTagName("body")[0].clientWidth}function haltEvent(e){return e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation(),!1}function haltReturn(e){13==e.keyCode&&haltEvent(e)}function validateEmail(e){return/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(e)}function format(e){var n=Array.prototype.slice.call(arguments,1);return e.replace(/{(\d+)}/g,function(e,a){return void 0!==n[a]?n[a]:e})}</script>
\ No newline at end of file
views/message-min.handlebars deleted
-1
@@ -1 +0,0 @@
1 -<!doctypehtml><html dir=ltr xmlns=http://www.w3.org/1999/xhtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html;charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link type=text/css href=/styles/style.css media=screen rel=stylesheet title=CSS><title>{{{title}}} - {{{title3}}}</title><div id=container style=max-height:100vh><div id=mastheadx></div><div id=masthead style="background:url(logo.png) 0 0;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden"><div style=float:left>{{{titlehtml}}}</div><div style=float:left;height:66px;color:#c8c8c8;padding-left:14px;padding-top:7px><strong><font style=font-size:46px;font-family:Arial,Helvetica,sans-serif>{{{title1}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px><strong><font style=font-size:14px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div></div><div id=page_content style=max-height:calc(100vh-138px)><div id=column_l><h1>{{{title3}}}</h1><p style=margin-left:20px>{{{message}}}</p><br></div><div id=footer><table cellpadding=0 cellspacing=10 style=width:100%><tr><td style=text-align:left><td style=text-align:right><a href=terms>Terms &amp; Privacy</a></table></div></div></div>
\ No newline at end of file
views/messenger-min.handlebars deleted
-1
@@ -1 +0,0 @@
1 -<!doctypehtml><html style=height:100%><title>{{{title}}} - Messenger</title><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html;charset=utf-8"http-equiv=Content-Type><meta name=format-detection content="telephone=no"><link type=text/css href=styles/style.css media=screen rel=stylesheet title=CSS><link type=text/css href=styles/messenger.css media=screen rel=stylesheet title=CSS><script src=scripts/common-0.0.1.js></script><script src=scripts/filesaver.js></script><body style=font-family:Arial,Helvetica,sans-serif><div id=xtop style="position:absolute;left:0;right:0;top:0;height:38px;background-color:#036;color:#c8c8c8;box-shadow:3px 3px 10px gray"><div style=position:absolute;background-color:#036;right:0;height:38px><div id=notifyButton class="icon13 topButton"style=margin-right:4px;display:none title="Enable browser notification"onclick=enableNotificationsButtonClick()></div><div id=fileButton class="icon4 topButton"title="Share a file"style=display:none onclick=fileButtonClick()></div><div id=camButton class="icon2 topButton"title="Activate camera & microphone"style=display:none onclick=camButtonClick()></div><div id=micButton class="icon6 topButton"title="Activate microphone"style=display:none onclick=micButtonClick()></div><div id=hangupButton class="icon11 topRedButton"title="Hang up"style=display:none onclick=hangUpButtonClick(1)></div></div><div style=padding-top:9px;padding-left:6px;font-size:20px;display:inline-block><b><span id=xtitle>MeshMessenger</span></b></div></div><div id=xmiddle style=position:absolute;left:0;right:0;top:38px;bottom:30px><div style=position:absolute;left:0;right:0;top:0;bottom:0;overflow-y:scroll><div id=xmsg style=position:absolute;left:0;right:0;bottom:0;padding:5px></div></div></div><div id=xbottom style=position:absolute;left:0;right:0;bottom:0;height:30px;background-color:#036><div style=position:absolute;left:5px;right:215px;bottom:4px;top:4px;background-color:#f0f8ff><input id=xouttext style="width:calc(100% - 5px)"onfocus=onUserInputFocus(1) onblur=onUserInputFocus(0)></div><input type=button id=sendButton value=Send style=position:absolute;right:110px;width:100px;top:4px onclick=xsend(event)> <input type=button id=clearButton value=Clear style=position:absolute;right:5px;width:100px;top:4px onclick=displayClear()></div><div id=remoteVideo style="position:absolute;right:24px;top:45px;width:320px;height:calc(240px + 30px);background-color:gray;border-radius:12px 12px 12px 12px;box-shadow:3px 3px 10px gray;display:none"><div style=position:absolute;right:0;left:0;top:2.5px;text-align:center>Remote</div><video id=remoteVideoCanvas autoplay style="position:absolute;top:20px;left:0;width:100%;height:calc(100% - 30px);background-color:#000"></video></div><div id=localVideo style="position:absolute;right:24px;top:320px;width:160px;height:calc(120px + 30px);background-color:gray;border-radius:12px 12px 12px 12px;box-shadow:3px 3px 10px gray;display:none"><div style=position:absolute;right:0;left:0;top:2.5px;text-align:center>Local</div><video id=localVideoCanvas autoplay muted style="position:absolute;top:20px;left:0;width:100%;height:calc(100% - 30px);background-color:#000"></video></div><input id=uploadFileInput type=file multiple style=display:none><script onunload=onUnLoad()>var userInputFocus=0,args=parseUriArgs(),socket=null,state=0,random=Math.random(),webrtcSessions={},webchannel=null,localStream=null,remoteStream=null,multiWebRtc=!0,userMediaSupport=0,notification=null;getUserMediaSupport(function(e){userMediaSupport=e});var webrtcconfiguration="{{{webrtconfig}}}";if(""==webrtcconfiguration)webrtcconfiguration=null;else try{webrtcconfiguration=JSON.parse(decodeURIComponent(webrtcconfiguration))}catch(e){console.log('Invalid WebRTC config: "'+webrtcconfiguration+'".'),webrtcconfiguration=null}var fileUploads=[],fileDownloads={},currentFileUpload=null,currentFileDownload=null;function onUserInputFocus(e){userInputFocus=e}function displayClear(){QH("xmsg",""),cancelAllFileTransfers(),fileUploads=[],fileDownloads={}}function getUserMediaSupport(i){try{navigator.mediaDevices.enumerateDevices().then(function(e){try{var t=0,n=0;e.forEach(function(e){"audioinput"===e.kind&&(t=1),"videoinput"===e.kind&&(n=1)}),0==t&&i(0),i(t+n)}catch(e){}})}catch(e){}}function displayControl(e){QA("xmsg",'<div style="clear:both"><div style="color:gray;float:left;margin-bottom:2px">'+e+"</div><div></div></div>"),Q("xmsg").scrollTop=Q("xmsg").scrollHeight}function displayLocalVideo(e){QV("localVideo",e),adjustVideoWindows()}function displayRemoteVideo(e){QV("remoteVideo",e),adjustVideoWindows()}function adjustVideoWindows(){var e="none"!=QS("remoteVideo").display;QS("localVideo").top=e?"320px":"45px"}function displayRemote(e){QA("xmsg",'<div style="clear:both"><div class="remoteBubble">'+e+"</div><div></div></div>"),Q("xmsg").scrollTop=Q("xmsg").scrollHeight,Notification&&QV("notifyButton","granted"!=Notification.permission),Notification&&"granted"==Notification.permission&&(null!=notification&&(notification.close(),notification=null),notification=args.title?new Notification("MeshMessenger - "+args.title,{body:e}):new Notification("MeshMessenger",{body:e}))}function xsend(e){null!=notification&&(notification.close(),notification=null),Notification&&QV("notifyButton","granted"!=Notification.permission);var t=Q("xouttext").value;0<t.length&&(Q("xouttext").value="",QA("xmsg",'<div style="clear:both"><div class="localBubble">'+t+"</div><div></div></div>"),Q("xmsg").scrollTop=Q("xmsg").scrollHeight,send({action:"chat",msg:t}))}function haltEvent(e){return e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation(),!1}function parseUriArgs(){var e,t={},n=window.document.location.href.split(/[\?&|\=]/);for(i in n.splice(0,1),n)switch(i%2){case 0:e=decodeURIComponent(n[i]);break;case 1:t[e]=decodeURIComponent(n[i]);var i=parseInt(t[e]);i==t[e]&&(t[e]=i)}return t}function updateControls(){QE("sendButton",2==state),QE("clearButton",2==state),QE("xouttext",2==state),QV("fileButton",2==state),QV("camButton",webchannel&&webchannel.ok&&!localStream&&2==userMediaSupport),QV("micButton",webchannel&&webchannel.ok&&!localStream&&0<userMediaSupport),QV("hangupButton",webchannel&&webchannel.ok&&localStream)}function startWebRTC(t,e){if(null!=webrtcSessions[0]&&0==multiWebRtc)return webrtcSessions[0];var n=null;return"undefined"!=typeof RTCPeerConnection?n=new RTCPeerConnection(webrtcconfiguration):"undefined"!=typeof webkitRTCPeerConnection&&(n=new webkitRTCPeerConnection(webrtcconfiguration)),null==n?null:(n.id=t,n.onicecandidate=function(e){try{null!=e.candidate&&sendws({action:"webRtcIce",ice:e.candidate,id:this.id})}catch(e){}},n.oniceconnectionstatechange=function(){n&&"failed"==n.iceConnectionState&&(n.close(),webrtcSessions[n.id]&&delete webrtcSessions[n.id])},n.ondatachannel=function(e){(webchannel=e.channel).onmessage=function(e){processMessage(e.data,2)},webchannel.onopen=function(){webchannel.ok=!0,updateControls(),sendws({action:"rtcSwitch",v:0})},webchannel.onclose=function(e){webchannel&&webchannel.ok?disconnect():hangUpButtonClick(0)}},n.onnegotiationneeded=function(e){null==n.holdTimer&&(n.holdTimer=setTimeout(function(){n.holdTimer=null,n.createOffer(function(e){n.setLocalDescription(e,function(){sendws({action:"webRtcSdp",sdp:e,id:t})},function(){hangUpButtonClick(t)})},function(){hangUpButtonClick(t)})},20))},n.ontrack=function(e){var t=Q("remoteVideoCanvas");t.srcObject=remoteStream=e.streams[0],t.onloadedmetadata=function(e){t.play()},displayRemoteVideo(!0)},1==e&&((webchannel=n.createDataChannel("DataChannel",{})).onmessage=function(e){processMessage(e.data,2)},webchannel.onopen=function(){webchannel.ok=!0,updateControls(),sendws({action:"rtcSwitch",v:0})},webchannel.onclose=function(e){webchannel&&webchannel.ok?disconnect():hangUpButtonClick(0)}),webrtcSessions[t]=n)}function webRtcHandleOffer(i,e){var t=webrtcSessions[i];t&&t.setRemoteDescription(new RTCSessionDescription(e),function(){"offer"==e.type&&t.createAnswer(function(n){t.setLocalDescription(n,function(e,t){try{sendws({action:"webRtcSdp",sdp:n,id:i})}catch(e){}},function(){hangUpButtonClick(i)})},function(){hangUpButtonClick(i)})},function(){hangUpButtonClick(i)})}function performWebRtcSwitch(){webchannel&&webchannel.ok&&(sendws({action:"rtcSwitch",v:1}),webchannel.xoutBuffer=[])}function disconnect(){0<state&&displayControl("Connection closed."),1<state&&setTimeout(start,500),cancelAllFileTransfers(),hangUpButtonClick(0,!0),hangUpButtonClick(1,!0),hangUpButtonClick(2,!0),null!=socket&&(socket.close(),socket=null),updateControls(),state=0}function send(e){if(2==state)if("object"==typeof e&&(e=JSON.stringify(e)),webchannel&&webchannel.ok)null!=webchannel.xoutBuffer?webchannel.xoutBuffer.push(e):webchannel.send(e);else if(null!=socket)try{socket.send(e)}catch(e){}}function sendws(e){2==state&&("object"==typeof e&&(e=JSON.stringify(e)),null!=socket&&socket.send(e))}function webRtcIdSwitch(e){return 0==e?0:3-e}function processMessage(t,e){if("string"==typeof t){try{t=JSON.parse(t)}catch(e){return void console.log("Unable to parse",t)}switch(t.action){case"chat":displayRemote(t.msg);break;case"random":random>t.random&&startWebRTC(0,!0);break;case"webRtcSdp":webrtcSessions[webRtcIdSwitch(t.id)]||startWebRTC(webRtcIdSwitch(t.id),!1),webRtcHandleOffer(webRtcIdSwitch(t.id),t.sdp);break;case"webRtcIce":var n=webrtcSessions[webRtcIdSwitch(t.id)];if(n)try{n.addIceCandidate(new RTCIceCandidate(t.ice))}catch(e){}break;case"videoStop":hangUpButtonClick(webRtcIdSwitch(t.id),!0);break;case"rtcSwitch":switch(t.v){case 0:performWebRtcSwitch();break;case 1:sendws({action:"rtcSwitch",v:2});break;case 2:for(var i in webchannel.xoutBuffer)webchannel.send(webchannel.xoutBuffer[i]);delete webchannel.xoutBuffer;break;default:console.log("Unknown rtcSwitch value: "+t.action)}break;case"file":startFileDownload(t);break;case"fileUploadCancel":cancelFileTransfer(t.id);break;case"fileUploadStart":fileDownloads[t.id]&&((currentFileDownload=fileDownloads[t.id]).data="",changeFileInfo(t.id,2,0),continueFileDownload(t),send({action:"fileUploadAck",id:t.id}));break;case"fileUploadEnd":currentFileDownload&&currentFileDownload.id==t.id&&(changeFileInfo(t.id,3,200),currentFileDownload.done=1,currentFileDownload=null,send({action:"fileUploadAck",id:t.id})),currentFileDownload=null;break;case"fileUploadAck":continueFileUpload();break;case"fileData":currentFileDownload&&currentFileDownload.id==t.id&&(currentFileDownload.data+=t.data,changeFileInfo(t.id,2,200*currentFileDownload.data.length/currentFileDownload.size),send({action:"fileUploadAck",id:t.id}));break;default:console.log("Unhandled object data",t)}}else console.log("Unhandled data",typeof t,t)}function fileButtonClick(){var e=Q("uploadFileInput");1!=e.getAttribute("eventset")&&(e.setAttribute("eventset","1"),e.addEventListener("change",fileSelect,!1)),e.value=null,e.click()}function fileSelect(){if(2==state){var e=Q("uploadFileInput");if(10<e.files.length)displayControl("Limit of 10 file uploads at the same time.");else for(var t=0;t<e.files.length;t++)if(0<e.files[t].size){var n=new FileReader;n.onload=function(e){this.xfile.data=e.target.result,startFileUpload(this.xfile)},n.xfile=e.files[t],n.readAsBinaryString(e.files[t])}}}function fileDrop(e){if(haltEvent(e),2==state&&null!=e.dataTransfer)if(10<e.dataTransfer.files.length)displayControl("Limit of 10 file uploads at the same time.");else for(var t=0;t<e.dataTransfer.files.length;t++)if(0<e.dataTransfer.files[t].size){var n=new FileReader;n.onload=function(e){this.xfile.data=e.target.result,startFileUpload(this.xfile)},n.xfile=e.dataTransfer.files[t],n.readAsBinaryString(e.dataTransfer.files[t])}}function startFileUpload(e){2==state&&(e.id=Math.random(),fileUploads.push(e),QA("xmsg",'<div style="clear:both"></div><div id="FILEUP-'+e.id+'" class="localBubble" style="width:240px;cursor:pointer" onclick="cancelFileTransfer(\''+e.id+'\')"><div id="FILEUP-ICON-'+e.id+'" class="fileicon" style="float:left;width:32px;height:32px"></div><div><div id="FILEUP-NAME-'+e.id+'" style="height:16px;overflow:hidden;white-space:nowrap;" title="'+e.name+'">'+e.name+'</div><div style="width:200px;background-color:lightgray;margin-left:32px;border-radius:3px;margin-top:3px;height:11px"><div id="FILEUP-PROGRESS-'+e.id+'" style="width:0px;background-color:green;border-radius:3px;height:11px">&nbsp;</div></div></div></div>'),Q("xmsg").scrollTop=Q("xmsg").scrollHeight,send({action:"file",size:e.size,id:e.id,type:e.type,name:e.name}),null==currentFileUpload&&continueFileUpload())}function startFileDownload(e){2==state&&(fileDownloads[e.id]=e,QA("xmsg",'<div style="clear:both"></div><div id="FILEUP-'+e.id+'" class="remoteBubble" style="width:240px;cursor:pointer" onclick="saveFileTransfer(\''+e.id+'\')"><div id="FILEUP-ICON-'+e.id+'" class="fileicon" style="float:left;width:32px;height:32px"></div><div><div id="FILEUP-NAME-'+e.id+'" style="height:16px;overflow:hidden;white-space:nowrap;" title="'+e.name+'">'+e.name+'</div><div style="width:200px;background-color:lightgray;margin-left:32px;border-radius:3px;margin-top:3px;height:11px"><div id="FILEUP-PROGRESS-'+e.id+'" style="width:0px;background-color:green;border-radius:3px;height:11px">&nbsp;</div></div></div></div>'),Q("xmsg").scrollTop=Q("xmsg").scrollHeight)}function changeFileInfo(e,t,n,i){t&&(Q("FILEUP-ICON-"+e).classList.remove("fileicon"),Q("FILEUP-ICON-"+e).classList.remove("fileiconx"),Q("FILEUP-ICON-"+e).classList.remove("fileicontransfer"),Q("FILEUP-ICON-"+e).classList.remove("fileicondone"),Q("FILEUP-ICON-"+e).classList.add(["fileicon","fileiconx","fileicontransfer","fileicondone"][t])),n&&(QS("FILEUP-PROGRESS-"+e).width=n+"px"),i&&(QS("FILEUP-PROGRESS-"+e)["background-color"]=i)}function data2blob(e){for(var t=new Array(e.length),n=0;n<e.length;n++)t[n]=e.charCodeAt(n);return new Blob([new Uint8Array(t)])}function saveFileTransfer(e){var t=fileDownloads[e];t&&1==t.done&&saveAs(data2blob(t.data),t.name)}function cancelFileTransfer(e){null!=currentFileUpload&&currentFileUpload.id==e&&(currentFileUpload=null),null!=currentFileDownload&&currentFileDownload.id==e&&(currentFileDownload=null);var t=!1;if(fileDownloads[e]&&1!=fileDownloads[e].done)delete fileDownloads[e],t=!0;else for(var n in fileUploads)if(fileUploads[n].id==e){send({action:"fileUploadCancel",id:e}),fileUploads.splice(n,1),t=!0;break}t&&changeFileInfo(e,1,200,"gray")}function cancelAllFileTransfers(){for(var e in fileDownloads)cancelFileTransfer(fileDownloads[e].id);for(var e in fileUploads)cancelFileTransfer(fileUploads[e].id)}function continueFileUpload(){if(null==currentFileUpload){if(0==fileUploads.length)return;(currentFileUpload=fileUploads[0]).ptr=0,send({action:"fileUploadStart",size:currentFileUpload.size,id:currentFileUpload.id,type:currentFileUpload.type,name:currentFileUpload.name})}else if(currentFileUpload.size<=currentFileUpload.ptr)send({action:"fileUploadEnd",size:currentFileUpload.size,id:currentFileUpload.id,type:currentFileUpload.type,name:currentFileUpload.name}),changeFileInfo(currentFileUpload.id,3,200),fileUploads.splice(0,1),currentFileUpload=null,continueFileUpload();else{var e=Math.min(4e3,currentFileUpload.data.length-currentFileUpload.ptr),t=currentFileUpload.data.substring(currentFileUpload.ptr,currentFileUpload.ptr+e);send({action:"fileData",id:currentFileUpload.id,data:t}),currentFileUpload.ptr+=e,changeFileInfo(currentFileUpload.id,0,200*currentFileUpload.ptr/currentFileUpload.size)}}function continueFileDownload(e){send({action:"fileUploadAck",id:e.id})}function enableNotificationsButtonClick(){return Notification&&Notification.requestPermission().then(function(e){QV("notifyButton","granted"!=e)}),!1}function camButtonClick(){null==localStream&&startLocalStream({video:!0,audio:!0})}function micButtonClick(){null==localStream&&startLocalStream({video:!1,audio:!0})}function hangUpButtonClick(e,t){var n=Q("localVideoCanvas"),i=Q("remoteVideoCanvas"),o=webrtcSessions[1==multiWebRtc?e:0];if(0==e&&null!=webchannel){try{webchannel.close()}catch(e){}webchannel=null}if(o){if(1!=multiWebRtc&&0!=e||(o.ontrack=null,o.onremovetrack=null,o.onremovestream=null,o.onnicecandidate=null,o.oniceconnectionstatechange=null,o.onsignalingstatechange=null,o.onicegatheringstatechange=null,o.onnotificationneeded=null),1==e&&localStream){var a=localStream.getTracks();for(var l in a)a[l].stop();localStream=null}if(2==e&&remoteStream){a=remoteStream.getTracks();for(var l in a)a[l].stop();remoteStream=null}1!=multiWebRtc&&0!=e||(o.close(),delete webrtcSessions[e])}1==e?(n.removeAttribute("src"),n.removeAttribute("srcObject"),null!=localStream&&(localStream=null),displayLocalVideo(!1)):2==e&&(i.removeAttribute("src"),i.removeAttribute("srcObject"),displayRemoteVideo(!1)),1!=t&&send({action:"videoStop",id:e}),updateControls()}function startLocalStream(a){var l=1==multiWebRtc?1:0;null==localStream&&(1==multiWebRtc&&null!=webrtcSessions[1]||navigator.mediaDevices.getUserMedia&&(localStream=1,updateControls(),navigator.mediaDevices.getUserMedia(a).then(function(e){var t=(localStream=e).getTracks(),n=startWebRTC(l);if(1==a.video){var i=Q("localVideoCanvas");i.srcObject=e,i.onloadedmetadata=function(e){i.play()},displayLocalVideo(!0)}for(var o in t)n.addTrack(t[o],localStream)},function(e){displayControl(e.message+"."),hangUpButtonClick(1)})))}function start(){if(updateControls(),"string"==typeof args.id&&0<args.id.length){var e=window.location.protocol.replace("http","ws")+"//"+window.location.host+window.location.pathname.substring(0,window.location.pathname.lastIndexOf("/"))+"/meshrelay.ashx?id="+args.id;null!=args.auth&&""!=args.auth&&(e+="&auth="+args.auth),(socket=new WebSocket(e)).onopen=function(){state=1,displayControl("Waiting for other user...")},socket.onerror=function(e){},socket.onclose=function(){disconnect()},socket.onmessage=function(e){if(state<2&&"string"==typeof e.data&&("c"==e.data||"cr"==e.data))return hangUpButtonClick(0,!0),hangUpButtonClick(1,!0),hangUpButtonClick(2,!0),displayControl("Connected."),state=2,updateControls(),void sendws({action:"random",random:random});2==state&&processMessage(e.data,1)}}else displayControl("Error: No connection key specified.")}function onUnLoad(){for(var e=0;e<3;e++)webrtcSessions[e]&&(webrtcSessions[e].close(),delete webrtcSessions[e]);if(null!=webchannel){try{webchannel.close()}catch(e){}webchannel=null}if(null!=socket){try{socket.close()}catch(e){}socket=null}}args.title&&(QH("xtitle",args.title.split(" ").join("&nbsp")),document.title=document.title+" - "+args.title),Notification&&QV("notifyButton","granted"!=Notification.permission),document.addEventListener("dragover",haltEvent,!1),document.addEventListener("dragleave",haltEvent,!1),document.addEventListener("drop",fileDrop,!1),document.onclick=function(e){Notification&&QV("notifyButton","granted"!=Notification.permission),null!=notification&&(notification.close(),notification=null)},document.onkeyup=function(e){if(Notification&&QV("notifyButton","granted"!=Notification.permission),null!=notification&&(notification.close(),notification=null),2==state&&8==e.keyCode&&0==userInputFocus){var t=Q("xouttext").value;0<t.length&&(Q("xouttext").value=t.substring(0,t.length-1))}if(0==userInputFocus)return haltEvent(e),!1},document.onkeypress=function(e){if(Notification&&QV("notifyButton","granted"!=Notification.permission),null!=notification&&(notification.close(),notification=null),2==state&&(13==e.keyCode?xsend(e):0==userInputFocus&&1==e.key.length&&(Q("xouttext").value=Q("xouttext").value+e.key)),0==userInputFocus)return haltEvent(e),!1},FileReader.prototype.readAsBinaryString||(FileReader.prototype.readAsBinaryString=function(e){var i="",o=this,a=new FileReader;a.onload=function(e){for(var t=new Uint8Array(a.result),n=0;n<t.byteLength;n++)i+=String.fromCharCode(t[n]);o.onload({target:{result:i}})},a.readAsArrayBuffer(e)}),start()</script>
\ No newline at end of file
views/terms-min.handlebars deleted
-84
@@ -1,84 +0,0 @@
1 -<!doctypehtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html; charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link type=text/css href=styles/style.css media=screen rel=stylesheet title=CSS><script src=scripts/common-0.0.1.js></script><title>{{{title}}} - Terms of use</title><body id=body onload='"undefined"!=typeof startup&&startup()'style=display:none;overflow:hidden><div id=container><div id=masthead class=noselect style="background:url(logo.png) 0 0;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden"><div style=float:left>{{{titlehtml}}}</div><div style=float:left;height:66px;color:#c8c8c8;padding-left:14px;padding-top:7px><strong><font style=font-size:46px;font-family:Arial,Helvetica,sans-serif>{{{title1}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px><strong><font style=font-size:14px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div><p id=logoutControl style="color:#fff;font-size:11px;margin:10px 10px 0"></div><div id=page_leftbar><div style=height:16px></div></div><div id=topbar class="noselect style3"style=height:24px;position:relative><div id=uiMenuButton title="User interface selection"onclick=showUserInterfaceSelectMenu()>&diams;<div id=uiMenu style=display:none><div id=uiViewButton1 class=uiSelector onclick=userInterfaceSelectMenu(1) title="Left bar interface"><div class=uiSelector1></div></div><div id=uiViewButton2 class=uiSelector onclick=userInterfaceSelectMenu(2) title="Top bar interface"><div class=uiSelector2></div></div><div id=uiViewButton3 class=uiSelector onclick=userInterfaceSelectMenu(3) title="Fixed width interface"><div class=uiSelector3></div></div><div id=uiViewButton4 class=uiSelector onclick=toggleNightMode() title="Toggle night mode"><div class=uiSelector4></div></div></div></div></div><div id=column_l style="max-height:calc(100vh - 135px);overflow-y:auto"><h1>Terms of use</h1><p>Please contact the site administrator for terms of use.<hr><p class=MsoNormal>The following are the required disclosures of open source components and software incorporated into this software.<p class=MsoNormal><b><span>1.AJAX Control Toolkit - New BSD License</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span>Copyright (c) 2009, CodePlex Foundation. All rights reserved.<o:p></o:p></span><p class=MsoNormal><span>Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:<o:p></o:p></span><p class=MsoNormal><span>1.Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.<o:p></o:p></span><p class=MsoNormal><span>2.Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.<o:p></o:p></span><p class=MsoNormal><span>3.Neither the name of CodePlex Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.<o:p></o:p></span><p class=MsoNormal><span>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.<o:p></o:p></span><p class=MsoNormal><b><span>2.OpenSSL – OpenSSL and SSLeay License</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span><a href=http://www.openssl.org/source/license.html>http://www.openssl.org/source/license.html</a></span><p class=MsoNormal><span>Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.<o:p></o:p></span><p class=MsoNormal><span>Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:<o:p></o:p></span><p class=MsoNormal><span>1.Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.<o:p></o:p></span><p class=MsoNormal><span>2.Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.<o:p></o:p></span><p class=MsoNormal><span>3.All advertising materials mentioning features or use of this software must display the following acknowledgment: &quot;This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)&quot;<o:p></o:p></span><p class=MsoNormal><span>4.The names &quot;OpenSSL Toolkit&quot; and &quot;OpenSSL Project&quot; must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact openssl-core@openssl.org.<o:p></o:p></span><p class=MsoNormal><span>5.Products derived from this software may not be called &quot;OpenSSL&quot; nor may &quot;OpenSSL&quot; appear in their names without prior written permission of the OpenSSL Project.<o:p></o:p></span><p class=MsoNormal><span>6.Redistributions of any form whatsoever must retain the following acknowledgment: &quot;This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)&quot;.<o:p></o:p></span><p class=MsoNormal><span>THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS&#39;&#39; AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.<o:p></o:p></span><p class=MsoNormal><b><span>3.jQuery Foundation - MIT License</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span>Copyright 2013 jQuery Foundation and other contributors <a href=http://jquery.com/ >http://jquery.com/</a></span><p class=MsoNormal><span>THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</span><p class=MsoNormal><b><span>4.jQuery User Interface - MIT License</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span>Copyright 2013 jQuery Foundation and other contributors, <a href=http://jqueryui.com/ >http://jqueryui.com/</a></span><p class=MsoNormal><span>This software consists of voluntary contributions made by many individuals (AUTHORS.txt, http://jqueryui.com/about ). For exact contribution history,see the revision history and logs, available at http://jquery-ui.googlecode.com/svn/<o:p></o:p></span><p class=MsoNormal><span>THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.<o:p></o:p></span><p class=MsoNormal><b><span>5.noVNC - Mozilla Public License 2.0</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span><a href=https://github.com/kanaka/noVNC/blob/master/LICENSE.txt>https://github.com/kanaka/noVNC/blob/master/LICENSE.txt</a></span><p class=MsoNormal><span>Copyright (C) 2011 Joel Martin This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.<o:p></o:p></span><p class=MsoNormal><b><span>6.Rcarousel - MIT LIcense</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span><a href=https://github.com/ryrych/rcarousel/blob/master/widget/license>https://github.com/ryrych/rcarousel/blob/master/widget/license</a></span><p class=MsoNormal><span>Copyright (c) 2010 Wojciech &#39;RRH&#39; Ryrych<o:p></o:p></span><p class=MsoNormal><span>THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.<o:p></o:p></span><p class=MsoNormal><b><span>7.Webtoolkit Javascript Base 64 – Creative Commons Attribution 2.0 UK License</span></b><span><o:p></o:p></span><p class=MsoNormal><span>This software uses code from <a href=http://www.webtoolkit.info/javascript-base64.html>http://www.webtoolkit.info/javascript-base64.html</a> licensed under the <a href=http://creativecommons.org/licenses/by/2.0/uk/legalcode>http://creativecommons.org/licenses/by/2.0/uk/legalcode</a> and its source can be downloaded from <a href=http://www.webtoolkit.info/javascript-base64.html>http://www.webtoolkit.info/javascript-base64.html</a>.<o:p></o:p></span></p><br></div><div id=footer><table cellpadding=0 cellspacing=10 style=width:100%><tr><td style=text-align:left><td style=text-align:right><a href=/ >Back</a></table></div></div><script>'use strict';
2 - var uiMode = parseInt(getstore('uiMode', 1));
3 - var webPageStackMenu = false;
4 - var webPageFullScreen = true;
5 - var nightMode = (getstore('_nightMode', '0') == '1');
6 - var logoutControls = {{{logoutControls}}};
7 -
8 - var terms = '{{{terms}}}';
9 - if (terms != '') { QH('column_l', decodeURIComponent(terms)); }
10 - QV('column_l', true);
11 - userInterfaceSelectMenu();
12 -
13 - // Setup logout control
14 - var logoutControl = '';
15 - if (logoutControls.name != null) { logoutControl = format("Welcome {0}.", logoutControls.name); }
16 - if (logoutControls.logoutUrl != null) { logoutControl += format(' <a href=\"' + logoutControls.logoutUrl + '\" style="color:white">' + "Logout" + '</a>'); }
17 - QH('logoutControl', logoutControl);
18 -
19 - // Toggle user interface menu
20 - function showUserInterfaceSelectMenu() {
21 - Q('uiViewButton1').classList.remove('uiSelectorSel');
22 - Q('uiViewButton2').classList.remove('uiSelectorSel');
23 - Q('uiViewButton3').classList.remove('uiSelectorSel');
24 - Q('uiViewButton4').classList.remove('uiSelectorSel');
25 - try { Q('uiViewButton' + uiMode).classList.add('uiSelectorSel'); } catch (ex) { }
26 - QV('uiMenu', (QS('uiMenu').display == 'none'));
27 - if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
28 - }
29 -
30 - function userInterfaceSelectMenu(s) {
31 - if (s) { uiMode = s; putstore('uiMode', uiMode); }
32 - webPageFullScreen = (uiMode < 3);
33 - webPageStackMenu = true;//(uiMode > 1);
34 - toggleFullScreen(0);
35 - toggleStackMenu(0);
36 - QC('column_l').add('room4submenu');
37 - }
38 -
39 - function toggleNightMode() {
40 - nightMode = !nightMode;
41 - if (nightMode) { QC('body').add('night'); } else { QC('body').remove('night'); }
42 - putstore('_nightMode', nightMode ? '1' : '0');
43 - }
44 -
45 - // Toggle the web page to full screen
46 - function toggleFullScreen(toggle) {
47 - if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
48 - var hide = 0;
49 - //if (args.hide) { hide = parseInt(args.hide); }
50 - if (webPageFullScreen == false) {
51 - QC('body').remove('menu_stack');
52 - QC('body').remove('fullscreen');
53 - QC('body').remove('arg_hide');
54 - //if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
55 - //QV('UserDummyMenuSpan', false);
56 - //QV('page_leftbar', false);
57 - } else {
58 - QC('body').add('fullscreen');
59 - if (hide & 16) QC('body').add('arg_hide'); // This is replacement for QV('page_leftbar', !(hide & 16));
60 - //QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
61 - //QV('page_leftbar', true);
62 - }
63 - QV('body', true);
64 - }
65 -
66 - // If FullScreen, toggle menu to be horisontal or vertical
67 - function toggleStackMenu(toggle) {
68 - if (webPageFullScreen == true) {
69 - if (toggle === 1) {
70 - webPageStackMenu = !webPageStackMenu;
71 - putstore('webPageStackMenu', webPageStackMenu);
72 - }
73 - if (webPageStackMenu == false) {
74 - QC('body').remove('menu_stack');
75 - } else {
76 - QC('body').add('menu_stack');
77 - //if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
78 - }
79 - }
80 - }
81 -
82 - function putstore(name, val) { try { if (typeof (localStorage) === 'undefined') return; localStorage.setItem(name, val); } catch (e) { } }
83 - 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; } }
84 - 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; }); };</script>
\ No newline at end of file
views/terms-mobile-min.handlebars deleted
-1
@@ -1 +0,0 @@
1 -<!doctypehtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html; charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><title>{{{title}}} - Terms of use</title><style type=text/css>a{color:#036;text-decoration:underline}#footer a{color:#fff;text-decoration:underline}#footer a:hover{color:#fff;text-decoration:none}</style><body onload='"undefined"!=typeof startup&&startup()'style="overflow-y:hidden;max-width:100%;margin:0;padding:0;border:0;color:#000;font-size:13px;font-family:\'Trebuchet MS\',Arial,Helvetica,sans-serif"><div id=container><div id=masthead style="background:url(logo.png) 0 0;background-size:341px 50px;background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden"><div style=float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:4px><strong><font style=font-size:36px;font-family:Arial,Helvetica,sans-serif>{{{title1}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:7px><strong><font style=font-size:12px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div></div><div id=page_content style=overflow-y:scroll;position:absolute;bottom:32px;top:50px><div id=column_l style=padding-left:10px;padding-right:10px><h1>Terms of use</h1><p>Please contact the site administrator for terms of use.<hr><p class=MsoNormal>The following are the required disclosures of open source components and software incorporated into this software.<p class=MsoNormal><b><span>1.AJAX Control Toolkit - New BSD License</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span>Copyright (c) 2009, CodePlex Foundation. All rights reserved.<o:p></o:p></span><p class=MsoNormal><span>Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:<o:p></o:p></span><p class=MsoNormal><span>1.Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.<o:p></o:p></span><p class=MsoNormal><span>2.Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.<o:p></o:p></span><p class=MsoNormal><span>3.Neither the name of CodePlex Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.<o:p></o:p></span><p class=MsoNormal><span>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.<o:p></o:p></span><p class=MsoNormal><b><span>2.OpenSSL – OpenSSL and SSLeay License</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span><a href=http://www.openssl.org/source/license.html>http://www.openssl.org/source/license.html</a></span><p class=MsoNormal><span>Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.<o:p></o:p></span><p class=MsoNormal><span>Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:<o:p></o:p></span><p class=MsoNormal><span>1.Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.<o:p></o:p></span><p class=MsoNormal><span>2.Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.<o:p></o:p></span><p class=MsoNormal><span>3.All advertising materials mentioning features or use of this software must display the following acknowledgment: &quot;This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)&quot;<o:p></o:p></span><p class=MsoNormal><span>4.The names &quot;OpenSSL Toolkit&quot; and &quot;OpenSSL Project&quot; must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact openssl-core@openssl.org.<o:p></o:p></span><p class=MsoNormal><span>5.Products derived from this software may not be called &quot;OpenSSL&quot; nor may &quot;OpenSSL&quot; appear in their names without prior written permission of the OpenSSL Project.<o:p></o:p></span><p class=MsoNormal><span>6.Redistributions of any form whatsoever must retain the following acknowledgment: &quot;This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)&quot;.<o:p></o:p></span><p class=MsoNormal><span>THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS&#39;&#39; AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.<o:p></o:p></span><p class=MsoNormal><b><span>3.jQuery Foundation - MIT License</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span>Copyright 2013 jQuery Foundation and other contributors <a href=http://jquery.com/ >http://jquery.com/</a></span><p class=MsoNormal><span>THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</span><p class=MsoNormal><b><span>4.jQuery User Interface - MIT License</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span>Copyright 2013 jQuery Foundation and other contributors, <a href=http://jqueryui.com/ >http://jqueryui.com/</a></span><p class=MsoNormal><span>This software consists of voluntary contributions made by many individuals (AUTHORS.txt, http://jqueryui.com/about ). For exact contribution history,see the revision history and logs, available at http://jquery-ui.googlecode.com/svn/<o:p></o:p></span><p class=MsoNormal><span>THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.<o:p></o:p></span><p class=MsoNormal><b><span>5.noVNC - Mozilla Public License 2.0</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span><a href=https://github.com/kanaka/noVNC/blob/master/LICENSE.txt>https://github.com/kanaka/noVNC/blob/master/LICENSE.txt</a></span><p class=MsoNormal><span>Copyright (C) 2011 Joel Martin This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.<o:p></o:p></span><p class=MsoNormal><b><span>6.Rcarousel - MIT LIcense</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span><a href=https://github.com/ryrych/rcarousel/blob/master/widget/license>https://github.com/ryrych/rcarousel/blob/master/widget/license</a></span><p class=MsoNormal><span>Copyright (c) 2010 Wojciech &#39;RRH&#39; Ryrych<o:p></o:p></span><p class=MsoNormal><span>THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.<o:p></o:p></span><p class=MsoNormal><b><span>7.Webtoolkit Javascript Base 64 – Creative Commons Attribution 2.0 UK License</span></b><span><o:p></o:p></span><p class=MsoNormal><span>This software uses code from <a href=http://www.webtoolkit.info/javascript-base64.html>http://www.webtoolkit.info/javascript-base64.html</a> licensed under the <a href=http://creativecommons.org/licenses/by/2.0/uk/legalcode>http://creativecommons.org/licenses/by/2.0/uk/legalcode</a> and its source can be downloaded from <a href=http://www.webtoolkit.info/javascript-base64.html>http://www.webtoolkit.info/javascript-base64.html</a>.<o:p></o:p></span></p><br></div></div><div id=footer style=height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0><table cellpadding=0 cellspacing=6 style=width:100%><tr><td style=text-align:left;color:#fff>{{{footer}}}<td style=text-align:right>{{{rootCertLink}}}&nbsp;<a href=/ >Back</a></table></div></div>
\ No newline at end of file