mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-26 23:25:53 -05:00
9719 lines
641 KiB
Handlebars
9719 lines
641 KiB
Handlebars
<!DOCTYPE html><html dir="ltr" xmlns="http://www.w3.org/1999/xhtml"><head>
|
|
<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.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
|
|
<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 type="text/javascript" src="scripts/common-0.0.1.js"></script>
|
|
<script type="text/javascript" src="scripts/meshcentral.js"></script>
|
|
<script type="text/javascript" src="scripts/amt-0.2.0.js"></script>
|
|
<script type="text/javascript" src="scripts/amt-wsman-0.2.0.js"></script>
|
|
<script type="text/javascript" src="scripts/amt-desktop-0.0.2.js"></script>
|
|
<script type="text/javascript" src="scripts/amt-terminal-0.0.2.js"></script>
|
|
<script type="text/javascript" src="scripts/zlib.js"></script>
|
|
<script type="text/javascript" src="scripts/zlib-inflate.js"></script>
|
|
<script type="text/javascript" src="scripts/zlib-adler32.js"></script>
|
|
<script type="text/javascript" src="scripts/zlib-crc32.js"></script>
|
|
<script type="text/javascript" src="scripts/amt-redir-ws-0.1.0.js"></script>
|
|
<script type="text/javascript" src="scripts/amt-wsman-ws-0.2.0.js"></script>
|
|
<script type="text/javascript" src="scripts/agent-redir-ws-0.1.1.js"></script>
|
|
<script type="text/javascript" src="scripts/agent-redir-rtc-0.1.0.js"></script>
|
|
<script type="text/javascript" src="scripts/agent-desktop-0.0.2.js"></script>
|
|
<script type="text/javascript" src="scripts/qrcode.min.js"></script>
|
|
<script keeplink="1" type="text/javascript" src="scripts/u2f-api.js"></script>
|
|
<script keeplink="1" type="text/javascript" src="scripts/charts.js"></script>
|
|
<script keeplink="1" type="text/javascript" src="scripts/filesaver.js"></script>
|
|
</head><body id="body" onload="if (typeof(startup) !== 'undefined') startup();" oncontextmenu="handleContextMenu(event)" style="display:none;min-width:495px">{{{StartGeoLocation}}}
|
|
<script keeplink="1" type="text/javascript" src="scripts/ol.js"></script>
|
|
<script keeplink="1" type="text/javascript" src="scripts/ol3-contextmenu.js"></script>
|
|
{{{EndGeoLocation}}}
|
|
<title>{{{title}}}</title>
|
|
|
|
|
|
<!-- right click menu -->
|
|
<div id="contextMenu" class="contextMenu noselect" style="display:none">
|
|
<div id="cxinfo" class="cmtext" onclick="cmaction(1,event)"><b>Informace</b></div>
|
|
<div id="cxdesktop" class="cmtext" onclick="cmaction(3,event)">Plocha</div>
|
|
<div id="cxterminal" class="cmtext" onclick="cmaction(2,event)">Terminál</div>
|
|
<div id="cxfiles" class="cmtext" onclick="cmaction(4,event)">Soubory</div>
|
|
<div id="cxevents" class="cmtext" onclick="cmaction(5,event)">Události</div>
|
|
<div id="cxconsole" class="cmtext" onclick="cmaction(6,event)">Konzole</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:0px">
|
|
<div id="cxselectall" class="cmtext" onclick="cmmeshaction(1,event)">Vybrat vše</div>
|
|
<div id="cxselectnone" class="cmtext" onclick="cmmeshaction(2,event)">Vybrat nic</div>
|
|
<!--
|
|
<hr id="cxmgroupsplit2" style="display:none" />
|
|
<div id="cxmmdesktop" class="cmtext" style="display:none" onclick="cmmeshaction(3,event)">Multi-Desktop</div>
|
|
-->
|
|
</div>
|
|
<div id="termShellContextMenu" class="contextMenu noselect" style="display:none;min-width:0px">
|
|
<div id="cxtermnorm" class="cmtext" onclick="cmtermaction(1,event)"><b>Administrátorská příkazová řádka</b></div>
|
|
<div id="cxtermps" class="cmtext" onclick="cmtermaction(6,event)">Administrátorský PowerShell</div>
|
|
<div id="cxtermunorm" class="cmtext" onclick="cmtermaction(8,event)">Uživatelská přikazová řádka</div>
|
|
<div id="cxtermups" class="cmtext" onclick="cmtermaction(9,event)">Uživateský PowerShell</div>
|
|
</div>
|
|
<div id="termShellContextMenuLinux" class="contextMenu noselect" style="display:none;min-width:0px">
|
|
<div id="cxtermnorm" class="cmtext" onclick="cmtermaction(1,event)"><b>Root příkazová řádka</b></div>
|
|
<div id="cxtermps" class="cmtext" onclick="cmtermaction(8,event)">Uživatelská přikazová řádka</div>
|
|
</div>
|
|
<!--
|
|
<div id="pluginTabContextMenu" class="contextMenu noselect" style="display:none;min-width:0px">
|
|
<div id="cxclose" class="cmtext" onclick="pluginTabClose(event)">Close Tab</div>
|
|
</div>
|
|
-->
|
|
<!-- main page -->
|
|
<div id="container">
|
|
<div id="notifiyBox" class="notifiyBox" style="display:none"></div>
|
|
<div id="masthead" class="noselect">
|
|
<div class="title">{{{title}}}</div>
|
|
<div class="title2">{{{title2}}}</div>
|
|
<div style="float:right">
|
|
<div id="notificationCount" onclick="clickNotificationIcon()" class="unselectable" style="display: none;" title="Klikni pro zobrazení nastavení notifikací">0</div>
|
|
</div>
|
|
<p id="logoutControl"><span id="logoutControlSpan" style="color:white"></span><span id="idleTimeoutNotify" style="color:yellow"></span></p>
|
|
</div>
|
|
<div id="page_leftbar">
|
|
<div style="height:16px"></div>
|
|
<div id="LeftMenuMyDevices" tabindex="0" class="lbbutton lbbuttonsel" title="Moje zařízení" onclick="go(1,event)" onkeypress="if (event.key=='Enter') { go(1); }">
|
|
<div class="lb2"></div>
|
|
</div>
|
|
<div id="LeftMenuMyAccount" tabindex="0" class="lbbutton" title="Můj účet" onclick="go(2,event)" onkeypress="if (event.key=='Enter') { go(2); }">
|
|
<div class="lb1"></div>
|
|
</div>
|
|
<div id="LeftMenuMyEvents" tabindex="0" class="lbbutton" title="Moje události" onclick="go(3,event)" onkeypress="if (event.key=='Enter') { go(3); }">
|
|
<div class="lb3"></div>
|
|
</div>
|
|
<div id="LeftMenuMyFiles" tabindex="0" class="lbbutton" style="display:none" title="Moje soubory" onclick="go(5,event)" onkeypress="if (event.key=='Enter') { go(5); }">
|
|
<div class="lb4"></div>
|
|
</div>
|
|
<div id="LeftMenuMyUsers" tabindex="0" class="lbbutton" style="display:none" title="Uživatelé" onclick="go(4,event)" onkeypress="if (event.key=='Enter') { go(4); }">
|
|
<div class="lb5"></div>
|
|
</div>
|
|
<div id="LeftMenuMyServer" tabindex="0" class="lbbutton" style="display:none" title="Můj server" onclick="go(6,event)" onkeypress="if (event.key=='Enter') { go(6); }">
|
|
<div class="lb6"></div>
|
|
</div>
|
|
</div>
|
|
<div id="topbar" class="noselect">
|
|
<div>
|
|
<div style="position:relative">
|
|
<div tabindex="0" id="uiMenuButton" title="Výběr rozhraní uživatele" onclick="showUserInterfaceSelectMenu()" onkeypress="if (event.key == 'Enter') showUserInterfaceSelectMenu()">
|
|
♦
|
|
<div id="uiMenu" style="display:none">
|
|
<div tabindex="0" id="uiViewButton1" class="uiSelector" onclick="userInterfaceSelectMenu(1)" title="Rozhraní levé lišty" onkeypress="if (event.key == 'Enter') userInterfaceSelectMenu(1)"><div class="uiSelector1"></div></div>
|
|
<div tabindex="0" id="uiViewButton2" class="uiSelector" onclick="userInterfaceSelectMenu(2)" title="Rozhraní horní lišty" onkeypress="if (event.key == 'Enter') userInterfaceSelectMenu(2)"><div class="uiSelector2"></div></div>
|
|
<div tabindex="0" id="uiViewButton3" class="uiSelector" onclick="userInterfaceSelectMenu(3)" title="Rozhraní s pevnou šířkou" onkeypress="if (event.key == 'Enter') userInterfaceSelectMenu(3)"><div class="uiSelector3"></div></div>
|
|
<div tabindex="0" id="uiViewButton4" class="uiSelector" onclick="toggleNightMode()" title="Přepnout na noční mód" onkeypress="if (event.key == 'Enter') toggleNightMode()"><div class="uiSelector4"></div></div>
|
|
</div>
|
|
</div>
|
|
<table id="MainMenuSpan" cellpadding="0" cellspacing="0" class="style1">
|
|
<tbody><tr>
|
|
<td tabindex="0" id="MainMenuMyDevices" class="topbar_td style3x" onclick="go(1,event)" onkeypress="if (event.key == 'Enter') go(1)">Moje zařízení</td>
|
|
<td tabindex="0" id="MainMenuMyAccount" class="topbar_td style3x" onclick="go(2,event)" onkeypress="if (event.key == 'Enter') go(2)">Můj účet</td>
|
|
<td tabindex="0" id="MainMenuMyEvents" class="topbar_td style3x" onclick="go(3,event)" onkeypress="if (event.key == 'Enter') go(3)">Moje události</td>
|
|
<td tabindex="0" id="MainMenuMyFiles" class="topbar_td style3x" onclick="go(5,event)" onkeypress="if (event.key == 'Enter') go(5)">Moje soubory</td>
|
|
<td tabindex="0" id="MainMenuMyUsers" class="topbar_td style3x" onclick="go(4,event)" onkeypress="if (event.key == 'Enter') go(4)">Uživatelé</td>
|
|
<td tabindex="0" id="MainMenuMyServer" class="topbar_td style3x" onclick="go(6,event)" onkeypress="if (event.key == 'Enter') go(6)">Můj server</td>
|
|
<td class="topbar_td_end style3"> </td>
|
|
</tr>
|
|
</tbody></table>
|
|
<div id="MainSubMenuSpan" style="display:none">
|
|
<table id="MainSubMenu" cellpadding="0" cellspacing="0" class="style1">
|
|
<tbody><tr>
|
|
<td tabindex="0" id="MainDev" class="topbar_td style3x" onclick="go(10,event)" onkeypress="if (event.key == 'Enter') go(10)">Obecné</td>
|
|
<td tabindex="0" id="MainDevDesktop" class="topbar_td style3x" onclick="go(11,event)" onkeypress="if (event.key == 'Enter') go(11)">Plocha</td>
|
|
<td tabindex="0" id="MainDevTerminal" class="topbar_td style3x" onclick="go(12,event)" onkeypress="if (event.key == 'Enter') go(12)">Terminál</td>
|
|
<td tabindex="0" id="MainDevFiles" class="topbar_td style3x" onclick="go(13,event)" onkeypress="if (event.key == 'Enter') go(13)">Soubory</td>
|
|
<td tabindex="0" id="MainDevEvents" class="topbar_td style3x" onclick="go(16,event)" onkeypress="if (event.key == 'Enter') go(16)">Události</td>
|
|
<td tabindex="0" id="MainDevInfo" class="topbar_td style3x" onclick="go(17,event)" onkeypress="if (event.key == 'Enter') go(17)">Detaily</td>
|
|
<td tabindex="0" id="MainDevAmt" class="topbar_td style3x" onclick="go(14,event)" onkeypress="if (event.key == 'Enter') go(14)">Intel® AMT</td>
|
|
<td tabindex="0" id="MainDevConsole" class="topbar_td style3x" onclick="go(15,event)" onkeypress="if (event.key == 'Enter') go(15)">Konzole</td>
|
|
<td tabindex="0" id="MainDevPlugins" class="topbar_td style3x" onclick="go(19,event)" onkeypress="if (event.key == 'Enter') go(19)">Pluginy</td>
|
|
<td class="topbar_td_end style3"> </td>
|
|
</tr>
|
|
</tbody></table>
|
|
</div>
|
|
<div id="MeshSubMenuSpan" style="display:none">
|
|
<table id="MeshSubMenu" cellpadding="0" cellspacing="0" class="style1">
|
|
<tbody><tr>
|
|
<td tabindex="0" id="MeshGeneral" class="topbar_td style3x" onclick="go(20,event)" onkeypress="if (event.key == 'Enter') go(20)">Obecné</td>
|
|
<td class="topbar_td_end style3"> </td>
|
|
</tr>
|
|
</tbody></table>
|
|
</div>
|
|
<div id="UserSubMenuSpan" style="display:none">
|
|
<table id="UserSubMenu" cellpadding="0" cellspacing="0" class="style1">
|
|
<tbody><tr>
|
|
<td tabindex="0" id="UserGeneral" class="topbar_td style3x" onclick="go(30,event)" onkeypress="if (event.key == 'Enter') go(30)">Obecné</td>
|
|
<td tabindex="0" id="UserEvents" class="topbar_td style3x" onclick="go(31,event)" onkeypress="if (event.key == 'Enter') go(31)">Události</td>
|
|
<td class="topbar_td_end style3"> </td>
|
|
</tr>
|
|
</tbody></table>
|
|
</div>
|
|
<div id="ServerSubMenuSpan" style="display:none">
|
|
<table id="ServerSubMenu" cellpadding="0" cellspacing="0" class="style1">
|
|
<tbody><tr>
|
|
<td tabindex="0" id="ServerGeneral" class="topbar_td style3x" onclick="go(6,event)" onkeypress="if (event.key == 'Enter') go(6)">Obecné</td>
|
|
<td tabindex="0" id="ServerStats" class="topbar_td style3x" onclick="go(40,event)" onkeypress="if (event.key == 'Enter') go(40)">Statistiky</td>
|
|
<td tabindex="0" id="ServerConsole" class="topbar_td style3x" onclick="go(115,event)" onkeypress="if (event.key == 'Enter') go(115)">Konzole</td>
|
|
<td tabindex="0" id="ServerTrace" class="topbar_td style3x" onclick="go(41,event)" onkeypress="if (event.key == 'Enter') go(41)">Trasování</td>
|
|
<td tabindex="0" id="ServerPlugins" class="topbar_td style3x" onclick="go(42,event)" onkeypress="if (event.key == 'Enter') go(42)">Pluginy</td>
|
|
<td class="topbar_td_end style3"> </td>
|
|
</tr>
|
|
</tbody></table>
|
|
</div>
|
|
<div id="UserDummyMenuSpan">
|
|
<table id="UserDummyMenu" cellpadding="0" cellspacing="0" class="style1">
|
|
<tbody><tr><td class="style3" style=""> </td></tr>
|
|
</tbody></table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="column_l">
|
|
<div id="p0" style="display:none">
|
|
<div id="p0message"><span id="p0span">Server odpojen</span>, <href onclick="reload()" style="cursor:pointer"><u>klikni pro opětovné připojení</u></href>.</div>
|
|
</div>
|
|
<div id="p1" style="display:none">
|
|
<div style="display:none" id="devListToolbarViewIcons">
|
|
<div tabindex="0" id="devViewButton1" class="viewSelector" onclick="onDeviceViewChange(1)" onkeypress="if (event.key == 'Enter') { onDeviceViewChange(1); }" title="Buňky"><div class="viewSelector2"></div></div>
|
|
<div tabindex="0" id="devViewButton2" class="viewSelector" onclick="onDeviceViewChange(2)" onkeypress="if (event.key == 'Enter') { onDeviceViewChange(2); }" title="Seznam"><div class="viewSelector1"></div></div>
|
|
<div tabindex="0" id="devViewButton3" class="viewSelector" onclick="onDeviceViewChange(3)" onkeypress="if (event.key == 'Enter') { onDeviceViewChange(3); }" title="Desktopy"><div class="viewSelector3"></div></div>
|
|
<div tabindex="0" id="devViewButton4" class="viewSelector" onclick="onDeviceViewChange(4)" onkeypress="if (event.key == 'Enter') { onDeviceViewChange(4); }" title="Mapa" style="display:none"><div class="viewSelector4"></div></div>
|
|
</div><div><h1>Moje zařízení</h1></div>
|
|
<table id="devListToolbarSpan" class="noselect">
|
|
<tbody><tr>
|
|
<td class="h1"></td>
|
|
<td id="devListToolbar" class="style14" style="display:none">
|
|
<input type="button" id="SelectAllButton" onclick="selectallButtonFunction();" value="Vybrat vše">
|
|
<input type="button" id="GroupActionButton" disabled="disabled" value="Akce skupiny" onclick="groupActionFunction()">
|
|
<input id="SearchInput" type="text" placeholder="Filtr" onchange="masterUpdate(5)" onkeyup="masterUpdate(5)" autocomplete="off" onfocus="onSearchFocus(1)" onblur="onSearchFocus(0)">
|
|
<label><input type="checkbox" id="RealNameCheckBox" onclick="onRealNameCheckBox()"><span title="Zobrazit jméno operačního systému">Jméno operačního systému</span></label>
|
|
</td>
|
|
<td id="kvmListToolbar" class="style14" style="display:none">
|
|
<input type="button" onclick="connectAllKvmFunction()" value="Připojit vše">
|
|
<input type="button" onclick="disconnectAllKvmFunction()" value="Odpojit vše">
|
|
<label><input type="checkbox" id="autoConnectDesktopCheckbox" onclick="autoConnectDesktops(event)" title="Automatické připojení">Auto </label>
|
|
<input type="button" onclick="showMultiDesktopSettings()" value="Nastavení">
|
|
</td>
|
|
<td id="devMapToolbar" class="style14" style="display:none">
|
|
<input type="text" id="mapSearchLocation" placeholder="Hledat umístění" onfocus="onMapSearchFocus(1)" onblur="onMapSearchFocus(0)">
|
|
<input type="button" value="Hledat" title="Vyhledat umístění" onclick="getSearchLocation()">
|
|
<input type="button" id="refreshmap" title="Reset pohledu" value="Reset" onclick="refreshMap(false,true)">
|
|
</td>
|
|
<td class="auto-style1" style="height:100%">
|
|
<div style="display:none" id="devListToolbarView">
|
|
Zobrazit
|
|
<select id="viewselect" onchange="onDeviceViewChange()">
|
|
<option value="1">Buňky</option>
|
|
<option value="2">Seznam</option>
|
|
<option value="3">Desktopy</option>
|
|
<option id="viewselectmapoption" value="4" style="display:none">Mapa</option>
|
|
</select>
|
|
</div>
|
|
<div style="display:none" id="devListToolbarSort">
|
|
Třídit
|
|
<select id="sortselect" onchange="masterUpdate(6)">
|
|
<option>Skupina</option>
|
|
<option>Napájení</option>
|
|
<option>Zařízení</option>
|
|
<option>Tagy</option>
|
|
</select>
|
|
|
|
</div>
|
|
<div style="display:none" id="devListToolbarSize">
|
|
Velikost
|
|
<select id="sizeselect" onchange="onDeviceViewChange()">
|
|
<option value="0">Malé</option>
|
|
<option value="1">Středně</option>
|
|
<option value="2">Velký</option>
|
|
</select>
|
|
|
|
</div>
|
|
</td>
|
|
<td class="h2"></td>
|
|
</tr>
|
|
</tbody></table>
|
|
<div id="NoMeshesPanel" style="display:none">
|
|
<table>
|
|
<tbody><tr>
|
|
<td valign="top" style="width: 50px">
|
|
<img src="images/info.png">
|
|
</td>
|
|
<td>
|
|
<div id="getStarted1">Začít, <a href="#" onclick="return account_createMesh()"><strong>klikni zde pro vytvoření skupiny zařízení</strong></a>.</div>
|
|
<div id="getStarted2">Žádná skupina zařízení.</div>
|
|
</td>
|
|
</tr>
|
|
</tbody></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">Výsledky umístění</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">
|
|
<h1>Můj účet</h1>
|
|
<img id="p2AccountImage" alt="" src="images/clipboard-128.png">
|
|
<div id="p2AccountSecurity" style="display:none">
|
|
<p><strong>Nastavení bezpečnosti</strong></p>
|
|
<div style="margin-left:25px">
|
|
<div id="manageAuthApp"><div class="p2AccountActions"><span id="authAppSetupCheck"><strong>✓</strong></span></div><span><a href="#" onclick="return account_manageAuthApp()">Spravovat autentizační aplikace</a><br></span></div>
|
|
<div id="manageHardwareOtp"><div class="p2AccountActions"><span id="authKeySetupCheck"><strong>✓</strong></span></div><span><a href="#" onclick="return account_manageHardwareOtp(0)">Spravovat bezpečnostní klíče</a><br></span></div>
|
|
<div id="manageOtp"><div class="p2AccountActions"><span id="authCodesSetupCheck"><strong>✓</strong></span></div><span><a href="#" onclick="return account_manageOtp(0)">Spravovat záložní kódy</a><br></span></div>
|
|
</div>
|
|
</div>
|
|
<div id="p2AccountActions">
|
|
<p><strong>Akce účtu</strong></p>
|
|
<p class="mL">
|
|
<span id="verifyEmailId" style="display:none"><a href="#" onclick="return account_showVerifyEmail()">Ověřit email</a><br></span>
|
|
<span id="accountEnableNotificationsSpan" style="display:none"><a href="#" onclick="return account_enableNotifications()">Zapnout notifikace prohlížeče</a><br></span>
|
|
<a href="#" onclick="return account_showLocalizationSettings()">Nastavení lokalizace</a><br>
|
|
<a href="#" onclick="return account_showAccountNotifySettings()">Nastavení notifikací</a><br>
|
|
<span id="accountChangeEmailAddressSpan" style="display:none"><a href="#" onclick="return account_showChangeEmail()">Změnit emailovou adresu</a><br></span>
|
|
<a href="#" onclick="return account_showChangePassword()">Změnit heslo</a><span id="p2nextPasswordUpdateTime"></span><br>
|
|
<a href="#" onclick="return account_showDeleteAccount()">Smazat účet</a><br>
|
|
</p>
|
|
<br style="clear:both">
|
|
</div>
|
|
<strong>Skupiny zařízení</strong>
|
|
<span id="p2createMeshLink1">( <a href="#" onclick="return account_createMesh()" class="newMeshBtn"> Vytvořit</a> )</span>
|
|
<br><br>
|
|
<div id="p2meshes"></div>
|
|
<div id="p2noMeshFound" style="display:none">Žádná skupina zařízení.<span id="p2createMeshLink2"> <a href="#" onclick="return account_createMesh()"><strong>Začněte zde!</strong></a></span></div>
|
|
<br style="clear:both">
|
|
</div>
|
|
<div id="p3" style="display:none">
|
|
<h1>Moje události</h1>
|
|
<table class="pTable">
|
|
<tbody><tr>
|
|
<td class="h1"></td>
|
|
<td class="auto-style1">
|
|
Zobrazit
|
|
<select id="p3limitdropdown" onchange="refreshEvents()">
|
|
<option value="60">Posledních 60</option>
|
|
<option value="120">Posledních 120</option>
|
|
<option value="250">Posledních 250</option>
|
|
<option value="500">Posledních 500</option>
|
|
<option value="1000">Posledních 1000</option>
|
|
</select>
|
|
<a href="#" onclick="p3showDownloadEventsDialog(2)"><img src="images/link4.png" height="10" width="10" title="Stáhnout události" style="cursor:pointer"></a>
|
|
</td>
|
|
<td class="h2"></td>
|
|
</tr>
|
|
</tbody></table>
|
|
<div id="p3events" style=""></div>
|
|
</div>
|
|
<div id="p4" style="display:none">
|
|
<h1>Uživatelé</h1>
|
|
<table class="pTable">
|
|
<tbody><tr>
|
|
<td class="h1"></td>
|
|
<td class="style14">
|
|
<div style="float:right">
|
|
<input type="button" onclick="showUserBroadcastDialog()" style="margin-right:6px" value="Hromadná zpráva">
|
|
<a href="#" onclick="p4downloadUserInfo()"><img style="cursor:pointer" title="Stáhnout uživatelské informace" src="images/link4.png"></a>
|
|
<a href="#" onclick="p4batchAccountCreate()"><img id="p4UserBatchCreate" style="cursor:pointer;display:none" title="Dávkově vytvořit více uživatelů" src="images/link6.png"></a>
|
|
</div>
|
|
<div>
|
|
<input id="UserNewAccountButton" type="button" style="margin-left:6px" onclick="showCreateNewAccountDialog()" value="Nový účet...">
|
|
<input id="UserSearchInput" type="text" style="width:120px;margin-left:6px" placeholder="Filtr" onchange="onUserSearchInputChanged()" onkeyup="onUserSearchInputChanged()" autocomplete="off" onfocus="onUserSearchFocus(1)" onblur="onUserSearchFocus(0)">
|
|
</div>
|
|
</td>
|
|
<td class="h2"></td>
|
|
</tr>
|
|
</tbody></table>
|
|
<div id="p3users"></div>
|
|
</div>
|
|
<div id="p5" style="display:none">
|
|
<h1>Moje soubory</h1>
|
|
<table id="p5toolbar" cellpadding="0" cellspacing="0">
|
|
<tbody><tr>
|
|
<td id="p5filehead" valign="bottom">
|
|
<div id="p5rightOfButtons"></div>
|
|
<div>
|
|
<input type="button" id="p5FolderUp" disabled="disabled" onclick="return p5folderup();" value="Nahoru">
|
|
<input type="button" id="p5SelectAllButton" disabled="disabled" onclick="p5selectallfile();" value="Vybrat vše">
|
|
<input type="button" id="p5RenameFileButton" disabled="disabled" value="Přejmenovat" onclick="p5renamefile();">
|
|
<input type="button" id="p5DeleteFileButton" disabled="disabled" value="Smazat" onclick="p5deletefile();">
|
|
<!--<input type=button id=p5ViewFileButton disabled="disabled" value="View" onclick="p5viewfile()" /> -->
|
|
<input type="button" id="p5NewFolderButton" disabled="disabled" value="Nový adresář" onclick="p5createfolder();">
|
|
<input type="button" id="p5UploadButton" disabled="disabled" value="Nahrát" onclick="p5uploadFile()">
|
|
<input type="button" id="p5CutButton" disabled="disabled" value="Vyjmout" onclick="p5copyFile(1)">
|
|
<input type="button" id="p5CopyButton" disabled="disabled" value="Kopírovat" onclick="p5copyFile(0)">
|
|
<input type="button" id="p5PasteButton" disabled="disabled" value="Vložit" onclick="p5pasteFile()">
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td id="p5filesubhead">
|
|
<div style="float:right">
|
|
<select id="p5sortdropdown" onchange="updateFiles()">
|
|
<option value="1" selected="selected">Třídit podle jména</option>
|
|
<option value="2">Třídit podle velikosti</option>
|
|
<option value="3">STřídit podle datumu</option>
|
|
<option value="4">Sestupně podle jména</option>
|
|
<option value="5">Sestupně podle velikosti</option>
|
|
<option value="6">Sestupně podle datumu</option>
|
|
</select>
|
|
</div>
|
|
<div> <span id="p5currentpath"></span></div>
|
|
</td>
|
|
</tr>
|
|
</tbody></table>
|
|
<div id="p5filetable">
|
|
<!--
|
|
<form id=p5fileCatchAll method=post enctype=multipart/form-data action=uploadfile.ashx target=fileUploadFrame>
|
|
<input type=file id=p5fileCatchAllInput name=files style="position:absolute;left:0;width:100%;top:0;bottom:0;opacity:0;display:none" onchange="p5fileCatchAllInputChanged(event)" />
|
|
<input id=p5fileDragLink2 name="link" style="display:none" />
|
|
<input type=submit id=p5fileCatchAllSubmit style="display:none" />
|
|
</form>
|
|
-->
|
|
<div id="p5PublicShare" style=""><div>Tyto soubory jsou veřejné, klikni "link" pro získání veřejného url.</div></div>
|
|
<div id="bigok" style="display:none"><b>✓</b></div>
|
|
<div id="bigfail" style="display:none"><b>✗</b></div>
|
|
<span id="p5files"></span>
|
|
</div>
|
|
<table id="p5toolbarBottom" style="width:100%" cellpadding="0" cellspacing="0">
|
|
<tbody><tr><td class="style6"> <span id="p5bottomstatus"></span></td></tr>
|
|
</tbody></table>
|
|
</div>
|
|
<div id="p6" style="display:none">
|
|
<img id="MainMeshImage" src="serverpic.ashx">
|
|
<h1>Můj server</h1>
|
|
<div id="p2ServerActions">
|
|
<p><strong>Kce serveru</strong></p>
|
|
<div class="mL">
|
|
<div id="p2ServerActionsBackup"><a href="{{{domainurl}}}backup.zip" rel="noreferrer noopener" target="_blank">Stáhnout zálohu serveru</a></div>
|
|
<div id="p2ServerActionsRestore"><a href="#" onclick="return server_showRestoreDlg()">Obnova serveru se zálohou</a></div>
|
|
<div id="p2ServerActionsVersion"><a href="#" onclick="return server_showVersionDlg()">Zkontrolovat verzi serveru</a></div>
|
|
<div id="p2ServerActionsErrors"><a href="#" onclick="return server_showErrorsDlg()">Zobrazit chyby serveru</a></div>
|
|
</div>
|
|
</div>
|
|
<br><strong>Statistiky serveru</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>Varování serveru</strong><br><br>
|
|
<div id="serverWarnings"></div>
|
|
</div>
|
|
</div>
|
|
<div id="p10" style="display:none">
|
|
<table style="width:100%" cellpadding="0" cellspacing="0">
|
|
<tbody><tr>
|
|
<td style="width:auto" valign="top">
|
|
<div id="p10title">
|
|
<div id="p10BackButton"><div class="backButton" tabindex="0" onclick="goBack()" title="Zpět" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
|
|
<h1>Obecné - <span id="p10deviceName"></span></h1>
|
|
</div>
|
|
<div id="p10html"></div>
|
|
</td>
|
|
<td style="width:20px"></td>
|
|
<td style="width:200px">
|
|
<a href="#" onclick="p10showiconselector()"><img id="MainComputerImage"></a>
|
|
<div id="MainComputerState"></div>
|
|
</td>
|
|
</tr>
|
|
</tbody></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="Zpět" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
|
|
<div id="devListToolbarViewIcons"><div class="viewSelector" onclick="deskToggleFull(event)" title="Celá obrazovka. Podržte shift pro zobrazení na celou obrazovku."><div class="viewSelector5"></div></div></div>
|
|
<h1>Plocha - <span id="p11deviceName"></span></h1>
|
|
</div>
|
|
</div>
|
|
<div id="p11warning" onclick="showFeaturesDlg()">
|
|
<div class="icon2"></div>
|
|
<div class="warningbox">Intel® AMT přesměrování portu nebo KVM vlastnost je vypnuta<span id="p11warninga">, zde kliknout pro aktivaci.</span></div>
|
|
</div>
|
|
<div id="p11warning2" onclick="showPowerActionDlg()">
|
|
<div class="icon2"></div>
|
|
<div class="warningbox">Vzdálený počítač není zapnutý, klikněte zde pro zapnutí.</div>
|
|
</div>
|
|
<div id="deskarea0" cellpadding="0" cellspacing="0">
|
|
<div id="deskarea1" class="areaHead">
|
|
<div class="toright2">
|
|
<span id="p11power"></span>
|
|
<div class="deskareaicon" title="Přepnout režim zobrazení" onclick="toggleAspectRatio(1)">⇲</div>
|
|
<div class="deskareaicon" title="Otočit doleva" onclick="drotate(-1)">↺</div>
|
|
<div class="deskareaicon" title="Otočit doprava" onclick="drotate(1)">↻</div>
|
|
<div id="deskRecordIcon" class="deskareaicon" title="Server nahrává toto spojení" style="display:none;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px"></div>
|
|
<input id="deskFocusBtn" type="button" title="Přepnout režim zaměření, pokud je aktivní pouze oblast kolem myši" onkeypress="return false" onkeydown="return false" value="Zaměřit vše" onclick="deskToggleFocus()" style="margin-right:3px;display:none">
|
|
<input id="deskSaveBtn" type="button" title="Uložit screenshot vzdáleného počítače" onkeypress="return false" onkeydown="return false" value="Uložit..." onclick="deskSaveImage()" class="mR">
|
|
<input id="deskActionsBtn" type="button" title="Akce napájení" onkeypress="return false" onkeydown="return false" value="Akce" onclick="deviceActionFunction()" class="mR">
|
|
<input id="deskActionsSettings" type="button" value="Nastavení..." title="Upravit nastavení vzdálené plochy" onkeypress="return false" onkeydown="return false" onclick="showDesktopSettings()" class="mR">
|
|
<input type="button" title="Změnit stav napájení vzdáleného zařízení" onkeypress="return false" onkeydown="return false" value="Akce napájení" onclick="showPowerActionDlg()" style="display:none">
|
|
</div>
|
|
<div>
|
|
<div id="idx_deskFullBtn2" onclick="deskToggleFull(event)"> ✖</div>
|
|
<input type="button" id="autoconnectbutton1" value="Automatické připojení" onclick="autoConnectDesktop(event)" onkeypress="return false" onkeydown="return false" style="display:none">
|
|
<span id="connectbutton1span"><input type="button" id="connectbutton1" value="Připojit" onclick="connectDesktop(event,1)" onkeypress="return false" onkeydown="return false" disabled="disabled"></span>
|
|
<span id="connectbutton1hspan"> <input type="button" id="connectbutton1h" value="HW připojení" title="Připojit pomocí Intel AMT hardware KVM" onclick="connectDesktop(event,2)" onkeypress="return false" onkeydown="return false" disabled="disabled"></span>
|
|
<span id="disconnectbutton1span"> <input type="button" id="disconnectbutton1" value="Odpojit" onclick="connectDesktop(event,0)" onkeypress="return false" onkeydown="return false"></span>
|
|
<span id="deskstatus">Odpojeno</span>
|
|
</div>
|
|
</div>
|
|
<div id="deskarea2" style="">
|
|
<div class="areaProgress"><div id="progressbar" style=""></div></div>
|
|
</div>
|
|
<div id="deskarea3x">
|
|
<div id="DeskFocus" oncontextmenu="return false" onmousedown="dmousedown(event)" onmouseup="dmouseup(event)" onmousemove="dmousemove(event)"></div>
|
|
<div id="DeskParent">
|
|
<canvas id="Desk" width="640" height="480" oncontextmenu="return false" 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()">Obnovit</a>
|
|
<div id="deskToolsTopTabProcess" class="deskToolsTopTab" onclick="changeDeskToolTab(0)" style="left:0px;bottom:0px">Procesy</div>
|
|
<div id="deskToolsTopTabService" class="deskToolsTopTab" onclick="changeDeskToolTab(1)" style="display:none;left:90px;color:gray">Služby</div>
|
|
</div>
|
|
<div id="deskToolsArea">
|
|
<div id="DeskToolsProcessTab">
|
|
<div id="deskToolsHeader">
|
|
<a class="colmn1" title="Třídit podle id procesu" onclick="sortProcess(0)">PID</a>
|
|
<a class="colmn2" title="Třídit podle jména" onclick="sortProcess(1)">Jméno</a>
|
|
</div>
|
|
<div id="DeskToolsProcesses" style=""></div>
|
|
</div>
|
|
<div id="DeskToolsServiceTab" style="display:none">
|
|
<div id="deskToolsServiceHeader">
|
|
<a class="colmn1" style="width:70px" title="Třídit podle stavu" onclick="sortService(0)">Stav</a>
|
|
<a class="colmn2" title="Třídit podle jména" onclick="sortService(1)">Jméno</a>
|
|
</div>
|
|
<div id="DeskToolsServices" style=""></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="p11DeskConsoleMsg" style="display:none;cursor:pointer;position:absolute;left:30px;top:17px;color:yellow;background-color:rgba(0,0,0,0.6);padding:10px;border-radius:5px" onclick="p11clearConsoleMsg()"></div>
|
|
</div>
|
|
<div id="deskarea4" class="areaFoot">
|
|
<div class="toright2">
|
|
<span id="DeskTimer" title="Čas spojení"></span>
|
|
<select id="termdisplays" style="display:none" onchange="deskSetDisplay(event)" onkeypress="return false" onkeydown="return false"></select>
|
|
<input id="DeskToolsButton" type="button" value="Nástroje" title="Přepnout zobrazení nástrojů" onkeypress="return false" onkeydown="return false" onclick="toggleDeskTools()">
|
|
<span id="DeskChatButton" class="deskarea" title="Otevřít chat na tomto počítači"><img src="images/icon-chat.png" onclick="deviceChat(event)" height="16" width="16" style="padding-top:2px"></span>
|
|
<span id="DeskNotifyButton" title="Zobrazit notifikaci na vzdáleném zařízení"><img src="images/icon-notify.png" onclick="deviceToastFunction()" height="16" width="16" style="padding-top:2px"></span>
|
|
<span id="DeskOpenWebButton" title="Otevřít webovou adresu na vzdáleném zařízení"><img src="images/icon-url2.png" onclick="deviceUrlFunction()" height="16" width="16" style="padding-top:2px"></span>
|
|
<span id="DeskBackgroundButton" title="Přepnout pozadí vzdálené plochy"><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>
|
|
<option value="5">Win</option>
|
|
<option value="0">Win+Down</option>
|
|
<option value="1">Win+Up</option>
|
|
<option value="2">Win+L</option>
|
|
<option value="3">Win+M</option>
|
|
<option value="4">Shift+Win+M</option>
|
|
<option value="6">Win+R</option>
|
|
<option value="7">Alt-F4</option>
|
|
<option value="8">Ctrl-W</option>
|
|
<option value="9">Alt-Tab</option>
|
|
<option value="11">Win+Left</option>
|
|
<option value="12">Win+Right</option>
|
|
</select>
|
|
<input id="DeskWD" type="button" value="Odeslat" onkeypress="return false" onkeydown="return false" onclick="deskSendKeys()">
|
|
<input id="DeskClip" style="" type="button" value="Schránka" onkeypress="return false" onkeydown="return false" onclick="showDeskClip()">
|
|
<input id="DeskType" style="" type="button" value="Typ" onkeypress="return false" onkeydown="return false" onclick="showDeskType()">
|
|
<label><span id="DeskControlSpan" title="Přepnutí vstupu myši a klávesnice"><input id="DeskControl" type="checkbox" onkeypress="return false" onkeydown="return false" onclick="toggleKvmControl()">Vstup</span></label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="p12" style="display:none">
|
|
<div id="p12title">
|
|
<div id="p12BackButton"><div class="backButton" tabindex="0" onclick="goBack()" title="Zpět" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
|
|
<h1>Terminál - <span id="p12deviceName"></span></h1>
|
|
</div>
|
|
<div id="p12warning" onclick="showFeaturesDlg()">
|
|
<div class="icon2"></div>
|
|
<div class="warningbox">Intel® AMT přesměrování portu nebo KVM vlastnost je vypnuta<span id="p12warninga">, zde kliknout pro aktivaci.</span></div>
|
|
</div>
|
|
<div id="p12warning2" onclick="showPowerActionDlg()">
|
|
<div class="icon2"></div>
|
|
<div class="warningbox">Vzdálený počítač není zapnutý, klikněte zde pro zapnutí.</div>
|
|
</div>
|
|
<div id="termTable" style="position:relative">
|
|
<table style="width:100%" cellpadding="0" cellspacing="0">
|
|
<tbody><tr>
|
|
<td class="areaHead">
|
|
<div class="toright2">
|
|
<div id="termRecordIcon" class="deskareaicon" title="Server nahrává toto spojení" 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="Akce napájení" onkeypress="return false" onkeydown="return false" value="Akce" onclick="deviceActionFunction()">
|
|
</div>
|
|
<div>
|
|
<input type="button" id="autoconnectbutton2" value="Automatické připojení" onclick="autoConnectTerminal(event)" onkeypress="return false" onkeydown="return false" style="display:none">
|
|
<span id="connectbutton2span"><input type="button" id="connectbutton2" value="Připojit" onclick="connectTerminal(event,1)" onkeypress="return false" onkeydown="return false" disabled="disabled"></span>
|
|
<span id="connectbutton2hspan"> <input type="button" id="connectbutton2h" value="HW připojení" title="Připojit pomocí Intel AMT hardware KVM" onclick="connectTerminal(event,2)" onkeypress="return false" onkeydown="return false" disabled="disabled"></span>
|
|
<span id="disconnectbutton2span"> <input type="button" id="disconnectbutton2" value="Odpojit" onclick="connectTerminal(event,0)" onkeypress="return false" onkeydown="return false"></span>
|
|
<span id="termstatus">Odpojeno</span><span id="termtitle"></span>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<div class="areaProgress"><div id="termprogressbar" style=""></div></div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td id="termarea3x">
|
|
<pre id="Term"></pre>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="areaFoot">
|
|
<div class="toright2">
|
|
<span id="TermTimer" title="Čas spojení"></span>
|
|
<span id="terminalSettingsButtons" style="display:none">
|
|
<input id="id_tcrbutton" type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" value="CR+LF" title="Přepnout, co odešle klávesa return" onclick="termToggleCr()">
|
|
<input id="id_tfxkeysbutton" type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" value="Intel (F10 = ESC+[OM)" title="Přepněte typ emulace kláves F1 na F10" onclick="termToggleFx()">
|
|
<input id="id_ttypebutton" type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" value="Rozšířené Ascii" title="Přepnout typ emulace terminálu" onclick="termToggleType()">
|
|
</span>
|
|
<span id="terminalSizeDropDown">
|
|
<select id="termSizeList" onkeypress="return false"><option value="1">80x25</option><option value="2">100x30</option><option value="3" selected="">Auto</option></select>
|
|
</span>
|
|
<select id="specialkeylist" onkeypress="return false"></select>
|
|
<input id="specialkeylistinput" type="button" onkeypress="return false" class="bottombutton" value="Odeslat" title="Poslat vybraný speciální klíč" onclick="sendSpecialKey()">
|
|
</div>
|
|
<div>
|
|
|
|
<input type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" id="ctrlcbutton" value="Ctl-C" onclick="termSendKey(3,'ctrlcbutton')">
|
|
<input type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" id="ctrlxbutton" value="Ctl-X" onclick="termSendKey(24,'ctrlxbutton')">
|
|
<input type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" id="escbutton" value="ESC" onclick="termSendKey(27,'escbutton')">
|
|
<input type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" id="bsbutton" value="Zpětná klávesa (backspace)" onclick="termSendKey(8,'bsbutton')">
|
|
<input type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" id="pastebutton" value="Vložit" title="Vložit text do terminálu" onclick="showTermPasteDialog()">
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody></table>
|
|
<div id="p12TermConsoleMsg" style="display:none;cursor:pointer;position:absolute;left:30px;top:45px;color:yellow;background-color:rgba(0,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="Zpět" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
|
|
<h1>Soubory - <span id="p13deviceName"></span></h1>
|
|
</div>
|
|
<table id="p13toolbar" cellpadding="0" cellspacing="0">
|
|
<tbody><tr>
|
|
<td class="areaHead">
|
|
<div class="toright2">
|
|
<input id="filesActionsBtn" type="button" title="Akce napájení" value="Akce" onclick="deviceActionFunction()">
|
|
<div id="filesRecordIcon" class="deskareaicon" title="Server nahrává toto spojení" 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="Automatické připojení" onclick="autoConnectFiles(event)" type="button" style="display:none">
|
|
<input id="p13Connect" value="Připojit" onclick="connectFiles(event)" type="button">
|
|
<span id="p13Status">Odpojeno</span>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="areaHead2" valign="bottom">
|
|
<div id="p13rightOfButtons" class="toright2"></div>
|
|
<div>
|
|
<input type="button" id="p13FolderUp" disabled="disabled" onclick="p13folderup()" value="Nahoru">
|
|
<input type="button" id="p13SelectAllButton" disabled="disabled" onclick="p13selectallfile()" value="Vybrat vše">
|
|
<input type="button" id="p13RenameFileButton" disabled="disabled" value="Přejmenovat" onclick="p13renamefile()">
|
|
<input type="button" id="p13DeleteFileButton" disabled="disabled" value="Smazat" onclick="p13deletefile()">
|
|
<input type="button" id="p13ViewFileButton" disabled="disabled" value="Upravit" onclick="p13viewfile()">
|
|
<input type="button" id="p13NewFolderButton" disabled="disabled" value="Nový adresář" onclick="p13createfolder()">
|
|
<input type="button" id="p13UploadButton" disabled="disabled" value="Nahrát" onclick="p13uploadFile()">
|
|
<input type="button" id="p13CutButton" disabled="disabled" value="Vyjmout" onclick="p13copyFile(1)">
|
|
<input type="button" id="p13CopyButton" disabled="disabled" value="Kopírovat" onclick="p13copyFile(0)">
|
|
<input type="button" id="p13PasteButton" disabled="disabled" value="Vložit" onclick="p13pasteFile()">
|
|
<input type="button" id="p13RefreshButton" disabled="disabled" value="Obnovit" onclick="p13folderup(9999)">
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="areaHead3">
|
|
<div class="toright2">
|
|
<select id="p13sortdropdown" onchange="p13updateFiles()">
|
|
<option value="1" selected="selected">Třídit podle jména</option>
|
|
<option value="2">Třídit podle velikosti</option>
|
|
<option value="3">STřídit podle datumu</option>
|
|
<option value="4">Sestupně podle jména</option>
|
|
<option value="5">Sestupně podle velikosti</option>
|
|
<option value="6">Sestupně podle datumu</option>
|
|
</select>
|
|
</div>
|
|
<div> <span id="p13currentpath"></span></div>
|
|
</td>
|
|
</tr>
|
|
</tbody></table>
|
|
<div id="p13FilesConsoleMsg" style="display:none;cursor:pointer;position:absolute;left:30px;top:165px;color:yellow;background-color:rgba(0,0,0,0.6);padding:10px;border-radius:5px" onclick="p13clearConsoleMsg()"></div>
|
|
<div id="p13filetable" style="">
|
|
<div id="p13bigok" style="display:none"><b>✓</b></div>
|
|
<div id="p13bigfail" style="display:none"><b>✗</b></div>
|
|
<span id="p13files"></span>
|
|
</div>
|
|
<table id="p13toolbarBottom" cellpadding="0" cellspacing="0">
|
|
<tbody><tr><td class="style6"> <span id="p13bottomstatus"></span></td></tr>
|
|
</tbody></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="Zpět" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
|
|
<div id="devListToolbarViewIcons"><div class="viewSelector" onclick="deskToggleFull(event)" title="Celá obrazovka. Podržte shift pro zobrazení na celou obrazovku."><div class="viewSelector5"></div></div></div>
|
|
<h1>Intel® 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="Zpět" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
|
|
<h1><span id="p15deviceName"></span></h1>
|
|
</div>
|
|
<table id="consoleTable" cellpadding="0" cellspacing="0">
|
|
<tbody><tr>
|
|
<td class="areaHead">
|
|
<div class="toright2">
|
|
<div id="p15coreName" title="Informace o aktuálním jádru v tomto agentovi"></div>
|
|
<input type="button" id="p15uploadCore" value="Akce agenta" onclick="p15uploadCore(event)" title="Změnit kód modulu agenta Java Script">
|
|
<img onclick="p15downloadConsoleText()" style="cursor:pointer;margin-top:6px" title="Stáhnout text z konzole" src="images/link4.png">
|
|
</div>
|
|
<div id="p15statetext"></div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<div class="areaProgress"><div id="consoleprogressbar" style=""></div></div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td id="p15agentConsole">
|
|
<pre id="p15agentConsoleText"></pre>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="areaFoot">
|
|
<table style="width:100%">
|
|
<tbody><tr>
|
|
<td style="width:99%">
|
|
<input id="p15consoleText" style="width:100%" onkeyup="p15consoleSend(event)" onfocus="onConsoleFocus(1)" onblur="onConsoleFocus(0)">
|
|
</td>
|
|
<td> </td>
|
|
<td id="p15outputselecttd">
|
|
<select id="p15outputselect">
|
|
<option value="1">Agent</option>
|
|
<option value="2">MQTT</option>
|
|
</select>
|
|
</td>
|
|
<td style="width:1%"><input id="id_p15consoleClear" type="button" class="bottombutton" value="Vymazat" onclick="p15consoleClear()"></td>
|
|
</tr>
|
|
</tbody></table>
|
|
</td>
|
|
</tr>
|
|
</tbody></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="Zpět" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
|
|
<h1>Události - <span id="p16deviceName"></span></h1>
|
|
</div>
|
|
<table class="pTable">
|
|
<tbody><tr>
|
|
<td class="h1"></td>
|
|
<!--<td> <input type=button onclick=refreshDeviceEvents() value="Refresh" /></td>-->
|
|
<td class="auto-style1">
|
|
Zobrazit
|
|
<select id="p16limitdropdown" onchange="refreshDeviceEvents()">
|
|
<option value="60">Posledních 60</option>
|
|
<option value="120">Posledních 120</option>
|
|
<option value="250">Posledních 250</option>
|
|
<option value="500">Posledních 500</option>
|
|
<option value="1000">Posledních 1000</option>
|
|
</select>
|
|
<a href="#" onclick="p3showDownloadEventsDialog(1)"><img src="images/link4.png" height="10" width="10" title="Stáhnout události" style="cursor:pointer"></a>
|
|
</td>
|
|
<td class="h2"></td>
|
|
</tr>
|
|
</tbody></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="Zpět" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
|
|
<h1>Detaily - <span id="p17deviceName"></span></h1>
|
|
</div>
|
|
<div id="p17info"></div>
|
|
</div>
|
|
<div id="p20" style="display:none">
|
|
<picture id="MainMeshImage" style="border-width:0px;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="Zpět" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
|
|
<h1>Obecné - <span id="p20meshName"></span></h1>
|
|
<p id="p20info"></p>
|
|
</div>
|
|
<div id="p30" style="display:none">
|
|
<table style="width:100%" cellpadding="0" cellspacing="0">
|
|
<tbody><tr>
|
|
<td style="width:auto" valign="top">
|
|
<div id="p30title">
|
|
<div style="float:left"><div class="backButton" tabindex="0" onclick="goBack()" title="Zpět" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
|
|
<h1>Obecné - <span id="p30userName"></span></h1>
|
|
</div>
|
|
<div id="p30html"></div>
|
|
</td>
|
|
<td style="width:20px"></td>
|
|
<td style="width:200px">
|
|
<picture id="MainUserImage" style="border-width:0px;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>
|
|
</td>
|
|
</tr>
|
|
</tbody></table><br>
|
|
<div id="p30html2"></div>
|
|
<div id="p30html3"></div>
|
|
</div>
|
|
<div id="p31" style="display:none">
|
|
<div style="float:left"><div class="backButton" tabindex="0" onclick="goBack()" title="Zpět" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
|
|
<h1>Události - <span id="p31userName"></span></h1>
|
|
<table class="pTable">
|
|
<tbody><tr>
|
|
<td class="h1"></td>
|
|
<!--<td> <input type=button onclick=refreshUsersEvents() value="Refresh" /></td>-->
|
|
<td class="auto-style1">
|
|
Zobrazit
|
|
<select id="p31limitdropdown" onchange="refreshUsersEvents()">
|
|
<option value="60">Posledních 60</option>
|
|
<option value="120">Posledních 120</option>
|
|
<option value="250">Posledních 250</option>
|
|
<option value="500">Posledních 500</option>
|
|
<option value="1000">Posledních 1000</option>
|
|
</select>
|
|
<a href="#" onclick="p3showDownloadEventsDialog(3)"><img src="images/link4.png" height="10" width="10" title="Stáhnout události" style="cursor:pointer"></a>
|
|
</td>
|
|
<td class="h2"></td>
|
|
</tr>
|
|
</tbody></table>
|
|
<div id="p31events" style=""></div>
|
|
</div>
|
|
<div id="p40" style="display:none">
|
|
<h1>Statistika serveru</h1>
|
|
<div class="areaHead">
|
|
<div class="toright2">
|
|
<select id="p40type" onchange="updateServerTimelineStats()">
|
|
<option value="0">Spojení</option>
|
|
<option value="1">Paměť</option>
|
|
</select>
|
|
<select id="p40time" onchange="updateServerTimelineHours()">
|
|
<option value="3">Poslední 3 hodiny</option>
|
|
<option value="8">Posledních 8 hodin</option>
|
|
<option value="24">Poslední den</option>
|
|
<option value="168">Poslední týden</option>
|
|
<option value="720">Posledních 30 dní</option>
|
|
</select>
|
|
<img src="images/link4.png" height="10" width="10" title="Stáhnout datové body (.csv)" style="cursor:pointer" onclick="p40downloadEvents()">
|
|
</div>
|
|
<div>
|
|
<input value="Obnovit" type="button" onclick="refreshServerTimelineStats()">
|
|
<label><input id="p40log" type="checkbox" onclick="updateServerTimelineHours()">Log-X</label>
|
|
</div>
|
|
</div>
|
|
<canvas id="serverMainStats" style=""></canvas>
|
|
</div>
|
|
<div id="p41" style="display:none">
|
|
<h1>Moje serverové trasování</h1>
|
|
<div class="areaHead">
|
|
<div class="toright2">
|
|
Zobrazit
|
|
<select id="p41limitdropdown" onchange="displayServerTrace()">
|
|
<option value="100">Posledních 100</option>
|
|
<option value="250">Posledních 250</option>
|
|
<option value="500">Posledních 500</option>
|
|
<option value="1000">Posledních 1000</option>
|
|
</select>
|
|
<input value="Vymazat" type="button" onclick="clearServerTracing()">
|
|
<img src="images/link4.png" height="10" width="10" title="Stáhnout trace (.csv)" style="cursor:pointer" onclick="p41downloadServerTrace()">
|
|
</div>
|
|
<div>
|
|
<input value="Trasování" type="button" onclick="setServerTracing()">
|
|
<span id="p41traceStatus">Nic</span>
|
|
</div>
|
|
</div>
|
|
<div id="p41events" style=""></div>
|
|
</div>
|
|
<div id="p42" style="display:none">
|
|
<h1>Moje serverové pluginy</h1>
|
|
<div class="areaHead">
|
|
<div class="toright2">
|
|
</div>
|
|
<div>
|
|
<input value="Stáhnout 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="Obnovit jádra agentů" type="button" onclick="distributeCore();return false">
|
|
</div>
|
|
<div style="padding:2px">
|
|
<div style="padding:2px"><b>Poznámka:</b> Pluginy byly změněny, může to vyžadovat aktualizaci jádra agenta.</div>
|
|
</div>
|
|
</div>
|
|
<table id="p42tbl">
|
|
<tbody><tr class="DevSt"><th style="width:26px"></th><th style="width:10px"></th><th class="chName">Jméno</th><th class="chDescription">Popis</th><th class="chSite" style="text-align:center">Odkaz</th><th class="chVersion" style="text-align:center">Verze</th><th class="chUpgradeAvail" style="text-align:center">Poslední</th><th class="chStatus" style="text-align:center">Status</th><th class="chAction" style="text-align:center">Akce</th><th style="width:10px"></th></tr>
|
|
</tbody></table>
|
|
<div id="pluginNoneNotice" style="width:100%;text-align:center;padding-top:10px;display:none"><i>Žádný plugin na serveru.</i></div>
|
|
</div>
|
|
<div id="p43" style="display:none">
|
|
<div id="p43BackButton"><div class="backButton" tabindex="0" onclick="go(42)" title="Zpět" onkeypress="if (event.key == 'Enter') go(42)"><div class="backButtonEx"></div></div></div>
|
|
<h1>Moje serverové pluginy - <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>Pluginy - <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()">Ověřit email</a>
|
|
<a href="terms">Podmínky & soukromí</a>
|
|
</div>
|
|
</div>
|
|
<div id="dialog" class="noselect" style="display:none">
|
|
<div id="dialogHeader">
|
|
<div tabindex="0" id="id_dialogclose" onclick="setDialogMode()" onkeypress="if (event.key == 'Enter') setDialogMode()">✖</div>
|
|
<div id="id_dialogtitle"></div>
|
|
</div>
|
|
<div id="dialogBody">
|
|
<div id="dialog1">
|
|
<div id="id_dialogMessage" style=""></div>
|
|
</div>
|
|
<div id="dialog2" style="">
|
|
<div id="id_dialogOptions"></div>
|
|
</div>
|
|
<div id="dialog3" style="">
|
|
<div id="d3upload">
|
|
<div>Výběr souboru</div>
|
|
<select id="d3uploadMode" onchange="d3modechange()">
|
|
<option value="1">Nahrání lokálního souboru</option>
|
|
<option value="2">Výběr souboru serveru</option>
|
|
</select>
|
|
</div>
|
|
<div id="d3localmode" style="display:none">
|
|
<div>Nahrát soubor</div>
|
|
<form id="d3localmodeform" method="post" enctype="multipart/form-data" action="uploadfile.ashx" target="fileUploadFrame">
|
|
<input type="text" id="d3auth" name="auth" style="display:none">
|
|
<input type="text" 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="disabled" onclick="d3folderup()" value="Nahoru">
|
|
</div>
|
|
<div id="d3serverfiles"></div>
|
|
</div>
|
|
</div>
|
|
<div id="dialog7" style="">
|
|
<div id="d7meshkvm">
|
|
<h4>Agent vzdálené plochy</h4>
|
|
<div>
|
|
<div>Kvalita</div>
|
|
<select id="d7bitmapquality" dir="rtl"></select>
|
|
</div>
|
|
<div>
|
|
<div>Škálování</div>
|
|
<select id="d7bitmapscaling" style="" dir="rtl">
|
|
<option selected="selected" value="1024">100%</option>
|
|
<option value="896">87.5%</option>
|
|
<option value="768">75%</option>
|
|
<option value="640">62.5%</option>
|
|
<option value="512">50%</option>
|
|
<option value="384">37.5%</option>
|
|
<option value="256">25%</option>
|
|
<option value="128">12.5%</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<div>Obnovování</div>
|
|
<select id="d7framelimiter" dir="rtl">
|
|
<option selected="selected" value="50">Rychle</option>
|
|
<option value="100">Středně</option>
|
|
<option value="400">Pomalu</option>
|
|
<option value="1000">Velmi pomalu</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div id="d7amtkvm">
|
|
<h4>Intel® AMT Hardware KVM</h4>
|
|
<div>
|
|
<div>Kódovaní obrazu</div>
|
|
<select id="d7desktopmode">
|
|
<option value="1">RLE8, Rychlejší</option>
|
|
<option value="2">RLE16, doporučeno</option>
|
|
<option value="3">RAW8, pomalé</option>
|
|
<option value="4">RAW16, hodně pomalé</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<div>Ostatní nastavení</div>
|
|
<div id="d7otherset" style="display:block">
|
|
<label style="display:block"><input type="checkbox" id="d7showfocus">Zobrazit nástroj pro zaměření</label>
|
|
<label style="display:block"><input type="checkbox" id="d7showcursor">Zobrazit lokální kurzor myši</label>
|
|
<label style="display:block"><input type="checkbox" id="d7localKeyMap">Lokální klávesová mapa</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="idx_dlgButtonBar">
|
|
<input id="idx_dlgCancelButton" type="button" value="Zrušit" style="" onclick="dialogclose(0)">
|
|
<input id="idx_dlgOkButton" type="button" value="OK" style="" onclick="dialogclose(1)">
|
|
<div><input id="idx_dlgDeleteButton" type="button" value="Smazat" 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 type="text/javascript">
|
|
'use strict';
|
|
|
|
// Process server-side web state
|
|
var webState = '{{{webstate}}}';
|
|
if (webState != '') { webState = JSON.parse(decodeURIComponent(webState)); }
|
|
for (var i in webState) { localStorage.setItem(i, webState[i]); }
|
|
if (!webState.loctag) { delete localStorage.removeItem('loctag'); }
|
|
|
|
var args;
|
|
var autoReconnect = true;
|
|
var powerStatetable = ['', "Zapnuto", "Spánek", "Spánek", "Spánek", "Hibernuji", "Vypnout", "Současnost"];
|
|
var StatusStrs = ["Odpojeno", "Připojování...", "Nastavení...", "Připojeno", "Intel® AMT připojeno"];
|
|
var sort = 0;
|
|
var searchFocus = 0;
|
|
var mapSearchFocus = 0;
|
|
var userSearchFocus = 0;
|
|
var consoleFocus = 0;
|
|
var showRealNames = false;
|
|
var meshserver = null;
|
|
var meshes = {};
|
|
var meshcount = 0;
|
|
var nodes = null;
|
|
var filetree = {};
|
|
var userinfo = null;
|
|
var serverinfo = null;
|
|
var events = [];
|
|
var users = null;
|
|
var wssessions = null;
|
|
var nodeShortIdent = 0;
|
|
var desktop;
|
|
var desktopsettings = { encoding: 2, showfocus: false, showmouse: true, showcad: true, quality: 40, scaling: 1024, framerate: 50, localkeymap: false };
|
|
var multidesktopsettings = { quality: 20, scaling: 128, framerate: 1000 };
|
|
var terminal;
|
|
var files;
|
|
var debugLevel = parseInt('{{{debuglevel}}}');
|
|
var features = parseInt('{{{features}}}');
|
|
var sessionTime = parseInt('{{{sessiontime}}}');
|
|
var domain = '{{{domain}}}';
|
|
var domainUrl = '{{{domainurl}}}';
|
|
var authCookie = '{{{authCookie}}}';
|
|
var authRelayCookie = '{{{authRelayCookie}}}';
|
|
var logoutControls = {{{logoutControls}}};
|
|
var authCookieRenewTimer = null;
|
|
var multiDesktop = {};
|
|
var multiDesktopFilter = null;
|
|
var serverPublicNamePort = '{{{serverDnsName}}}:{{{serverPublicPort}}}';
|
|
var amtScanResults = null;
|
|
var debugmode = 0;
|
|
var clickOnce = (((features & 256) != 0) && detectClickOnce());
|
|
var attemptWebRTC = ((features & 128) != 0);
|
|
var passRequirements = '{{{passRequirements}}}';
|
|
if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); }
|
|
var deskAspectRatio = 0;
|
|
try { deskAspectRatio = parseInt(getstore('deskAspectRatio', '0')); } catch (ex) { }
|
|
var uiMode = parseInt(getstore('uiMode', 1));
|
|
var webPageStackMenu = false;
|
|
var webPageFullScreen = true;
|
|
var nightMode = (getstore('_nightMode', '0') == '1');
|
|
var sessionActivity = Date.now();
|
|
var updateSessionTimer = null;
|
|
var pluginHandlerBuilder = {{{pluginHandler}}};
|
|
var pluginHandler = null;
|
|
if (pluginHandlerBuilder != null) { pluginHandler = new pluginHandlerBuilder(); }
|
|
var installedPluginList = null;
|
|
|
|
// Console Message Display Timers
|
|
var p11DeskConsoleMsgTimer = null;
|
|
var p12TermConsoleMsgTimer = null;
|
|
var p13FilesConsoleMsgTimer = null;
|
|
|
|
function startup() {
|
|
if ((features & 32) == 0) {
|
|
// Guard against other site's top frames (web bugs).
|
|
var loc = null;
|
|
try { loc = top.location.toString().toLowerCase(); } catch (e) { }
|
|
if (top != self && (loc == null || top.active == false)) { top.location = self.location; return; }
|
|
}
|
|
|
|
// Setup logout control
|
|
var logoutControl = '';
|
|
if (logoutControls.name != null) { logoutControl = format("Vítejte {0}.", logoutControls.name); }
|
|
if (logoutControls.logoutUrl != null) { logoutControl += format(' <a href=\"' + logoutControls.logoutUrl + '\" style="color:white">' + "Odhlásit" + '</a>'); }
|
|
QH('logoutControlSpan', logoutControl);
|
|
|
|
// Check if we are in debug mode
|
|
args = parseUriArgs();
|
|
if (!args.locale) { var x = getstore('loctag', 0); if ((x != null) && (x != '*')) { args.locale = x; } }
|
|
debugmode = args.debug;
|
|
if (args.webrtc != null) { attemptWebRTC = (args.webrtc == 1); }
|
|
QV('p13AutoConnect', debugmode); // Files
|
|
QV('autoconnectbutton2', debugmode); // Terminal
|
|
QV('autoconnectbutton1', debugmode); // Desktop
|
|
//QV('DeskClip', debugmode); // Clipboard feature, not completed so show in in debug mode only.
|
|
|
|
if (nightMode) { QC('body').add('night'); }
|
|
toggleFullScreen();
|
|
|
|
// Setup page visuals
|
|
if (args.hide) {
|
|
var hide = parseInt(args.hide);
|
|
QV('masthead', !(hide & 1));
|
|
QV('topbar', !(hide & 2));
|
|
QV('footer', !(hide & 4));
|
|
QV('p10title', !(hide & 8));
|
|
QV('p11title', !(hide & 8));
|
|
QV('p12title', !(hide & 8));
|
|
QV('p13title', !(hide & 8));
|
|
QV('p14title', !(hide & 8));
|
|
QV('p15title', !(hide & 8));
|
|
QV('p16title', !(hide & 8));
|
|
//if (hide & 16) {
|
|
// QV('page_leftbar', false);
|
|
// QS('page_content').left = '0px';
|
|
//}
|
|
|
|
// Fix the main grid to zero-height elements we want to hide.
|
|
QS('container')['grid-template-rows'] = ((hide & 1) ? '0' : '66') + 'px ' + ((hide & 2) ? '0' : '24') + 'px auto ' + ((hide & 4) ? '0' : '45') + 'px';
|
|
QS('container')['-ms-grid-rows'] = ((hide & 1) ? '0' : '66') + 'px ' + ((hide & 2) ? '0' : '24') + 'px auto ' + ((hide & 4) ? '0' : '45') + 'px';
|
|
|
|
// Adjust height of remote desktop, files and Intel AMT
|
|
var xh = (((hide & 1) ? 0 : 66) + ((hide & 2) ? 0 : 24) + ((hide & 4) ? 0 : 45) + ((hide & 8) ? 0 : 60)); // 0 to 195
|
|
QS('p3users')['max-height'] = 'calc(100vh - ' + (124 + xh) + 'px)';
|
|
QS('p3events')['height'] = 'calc(100vh - ' + (124 + xh) + 'px)';
|
|
QS('deskarea3x')['height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
|
|
QS('deskarea3x')['max-height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
|
|
QS('p5filetable')['height'] = 'calc(100vh - ' + (160 + xh) + 'px)';
|
|
QS('p13filetable')['height'] = 'calc(100vh - ' + (124 + xh) + 'px)';
|
|
QS('serverMainStats')['height'] = 'calc(100vh - ' + (110 + xh) + 'px)';
|
|
QS('serverMainStats')['max-height'] = 'calc(100vh - ' + (110 + xh) + 'px)';
|
|
QS('xdevices')['max-height'] = 'calc(100vh - ' + (124 + xh) + 'px)';
|
|
QS('xdevicesmap')['max-height'] = 'calc(100vh - ' + (124 + xh) + 'px)';
|
|
QS('p15agentConsole')['height'] = 'calc(100vh - ' + (84 + xh) + 'px)';
|
|
QS('p15agentConsole')['max-height'] = 'calc(100vh - ' + (84 + xh) + 'px)';
|
|
QS('p15agentConsoleText')['height'] = 'calc(100vh - ' + (81 + xh) + 'px)';
|
|
QS('p15agentConsoleText')['max-height'] = 'calc(100vh - ' + (81 + xh) + 'px)';
|
|
QS('p43iframe')['height'] = 'calc(100vh - ' + (84 + xh) + 'px)';
|
|
QS('p43iframe')['max-height'] = 'calc(100vh - ' + (84 + xh) + 'px)';
|
|
}
|
|
|
|
// We are looking at a single device, remove all the back buttons
|
|
if ('{{currentNode}}' != '') {
|
|
QV('p10BackButton', false);
|
|
QV('p11BackButton', false);
|
|
QV('p12BackButton', false);
|
|
QV('p13BackButton', false);
|
|
QV('p14BackButton', false);
|
|
QV('p15BackButton', false);
|
|
QV('p16BackButton', false);
|
|
}
|
|
p1updateInfo();
|
|
|
|
// Setup the context menu
|
|
document.onclick = function (e) { hideContextMenu(); }
|
|
document.onkeypress = ondockeypress;
|
|
document.onkeydown = ondockeydown;
|
|
document.onkeyup = ondockeyup;
|
|
//window.addEventListener('focus', ondocfocus, false);
|
|
window.addEventListener('blur', ondocblur, false);
|
|
window.onresize = function () { masterUpdate(512); }
|
|
setTimeout(function() { masterUpdate(512); }, 200);
|
|
|
|
// Connect to the mesh server
|
|
meshserver = MeshServerCreateControl(domainUrl, authCookie);
|
|
meshserver.onStateChanged = onStateChanged;
|
|
meshserver.onMessage = onMessage;
|
|
meshserver.trace = (args.trace == 1);
|
|
meshserver.Start();
|
|
|
|
// Setup page controls
|
|
Q('sortselect').selectedIndex = sort = getstore('sort', 0);
|
|
Q('sizeselect').selectedIndex = getstore('_viewsize', 1);
|
|
Q('SearchInput').value = getstore('_search', '');
|
|
showRealNames = (getstore('showRealNames', 0) == 1);
|
|
Q('RealNameCheckBox').checked = showRealNames;
|
|
Q('viewselect').value = getstore('_deviceView', 1);
|
|
Q('DeskControl').checked = (getstore('DeskControl', 1) == 1);
|
|
QV('accountChangeEmailAddressSpan', (features & 0x200000) == 0);
|
|
|
|
// Display the page devices
|
|
masterUpdate(3)
|
|
for (var j = 1; j < 5; j++) { Q('devViewButton' + j).classList.remove('viewSelectorSel'); }
|
|
Q('devViewButton' + Q('viewselect').value).classList.add('viewSelectorSel');
|
|
|
|
// Setup upload drag & drop
|
|
Q('p5filetable').addEventListener('drop', p5fileDragDrop, false);
|
|
Q('p5filetable').addEventListener('dragover', p5fileDragOver, false);
|
|
Q('p5filetable').addEventListener('dragleave', p5fileDragLeave, false);
|
|
//Q('p5fileCatchAllInput').addEventListener('drop', p5fileDragDrop, false);
|
|
//Q('p5fileCatchAllInput').addEventListener('dragover', p5fileDragOver, false);
|
|
//Q('p5fileCatchAllInput').addEventListener('dragleave', p5fileDragLeave, false);
|
|
|
|
// Setup upload drag & drop
|
|
Q('p13filetable').addEventListener('drop', p13fileDragDrop, false);
|
|
Q('p13filetable').addEventListener('dragover', p13fileDragOver, false);
|
|
Q('p13filetable').addEventListener('dragleave', p13fileDragLeave, false);
|
|
|
|
// Timeline update interval
|
|
setInterval(updateDeviceTimeline, 120000); // Check every 2 minutes
|
|
|
|
// Load desktop settings
|
|
var t = localStorage.getItem('desktopsettings');
|
|
if (t != null) { desktopsettings = JSON.parse(t); }
|
|
t = localStorage.getItem('multidesktopsettings');
|
|
if (t != null) { multidesktopsettings = JSON.parse(t); }
|
|
applyDesktopSettings();
|
|
|
|
// Terminal special keys
|
|
var x = '';
|
|
for (var c = 1; c < 27; c++) x += '<option value=\'' + c + '\'>' + "Ctrl" + '-' + String.fromCharCode(64 + c) + ' (' + c + ')</option>';
|
|
QH('specialkeylist', x);
|
|
|
|
// Setup server stats panels
|
|
setupGeneralServerStats();
|
|
setupServerTimelineStats();
|
|
|
|
// Setup the user interface in the right mode
|
|
userInterfaceSelectMenu();
|
|
|
|
// If SSPI or LDAP authentication not used, allow batch account creation.
|
|
QV('p4UserBatchCreate', (features & 0x00080000) == 0);
|
|
}
|
|
|
|
// Toggle the web page to full screen
|
|
function toggleAspectRatio(toggle) {
|
|
if (toggle === 1) { deskAspectRatio = ((deskAspectRatio + 1) % 3); putstore('deskAspectRatio', deskAspectRatio); }
|
|
deskAdjust();
|
|
}
|
|
|
|
// If FullScreen, toggle menu to be horisontal or vertical
|
|
function toggleStackMenu(toggle) {
|
|
if (webPageFullScreen == true) {
|
|
if (toggle === 1) {
|
|
webPageStackMenu = !webPageStackMenu;
|
|
putstore('webPageStackMenu', webPageStackMenu);
|
|
}
|
|
if (webPageStackMenu == false) {
|
|
QC('body').remove('menu_stack');
|
|
} else {
|
|
QC('body').add('menu_stack');
|
|
if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
|
|
}
|
|
deskAdjust();
|
|
}
|
|
}
|
|
|
|
// Toggle user interface menu
|
|
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 (ex) { }
|
|
QV('uiMenu', (QS('uiMenu').display == 'none'));
|
|
//Q('uiViewButton1').focus();
|
|
if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
|
|
}
|
|
|
|
function userInterfaceSelectMenu(s) {
|
|
if (s) { uiMode = s; putstore('uiMode', uiMode); }
|
|
webPageFullScreen = (uiMode < 3);
|
|
webPageStackMenu = (uiMode > 1);
|
|
toggleFullScreen(0);
|
|
toggleStackMenu(0);
|
|
if (webPageStackMenu && (xxcurrentView >= 10)) { QC('column_l').add('room4submenu'); } else { QC('column_l').remove('room4submenu'); }
|
|
}
|
|
|
|
function toggleNightMode() {
|
|
nightMode = !nightMode;
|
|
if (nightMode) { QC('body').add('night'); } else { QC('body').remove('night'); }
|
|
putstore('_nightMode', nightMode?'1':'0');
|
|
}
|
|
|
|
// Toggle the web page to full screen
|
|
function toggleFullScreen(toggle) {
|
|
if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
|
|
var hide = 0;
|
|
if (args.hide) { hide = parseInt(args.hide); }
|
|
if (webPageFullScreen == false) {
|
|
QC('body').remove('menu_stack');
|
|
QC('body').remove('fullscreen');
|
|
QC('body').remove('arg_hide');
|
|
if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
|
|
QV('UserDummyMenuSpan', false);
|
|
//QV('page_leftbar', false);
|
|
} else {
|
|
QC('body').add('fullscreen');
|
|
if (hide & 16) QC('body').add('arg_hide'); // This is replacement for QV('page_leftbar', !(hide & 16));
|
|
QV('page_leftbar', !(hide & 16));
|
|
QV('MainMenuSpan', !(hide & 16));
|
|
if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
|
|
QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
|
|
}
|
|
masterUpdate(512);
|
|
QV('body', true);
|
|
}
|
|
|
|
function getNodeFromId(id) { if (nodes != null) { for (var i in nodes) { if (nodes[i]._id == id) return nodes[i]; } } return null; }
|
|
function reload() {
|
|
var x = window.location.href;
|
|
if (x.endsWith('/#')) { x = x.substring(0, x.length - 2); }
|
|
window.location.href = x;
|
|
}
|
|
|
|
function onStateChanged(server, state, prevState, errorCode) {
|
|
if (state == 0) {
|
|
// Control web socket disconnected
|
|
setDialogMode(0); // Close any dialog boxes if present
|
|
go(0); // Go to disconnection panel
|
|
|
|
// Clean up
|
|
powerTimeline = null;
|
|
powerTimelineReq = null;
|
|
powerTimelineNode = null;
|
|
powerTimelineUpdate = null;
|
|
deleteAllNotifications(); // Close and clear notifications if present
|
|
hideContextMenu(); // Hide the context menu if present
|
|
QV('verifyEmailId2', false);
|
|
QV('logoutControl', false);
|
|
if (errorCode == 'noauth') { QH('p0span', "Unable to perform authentication"); return; }
|
|
if (prevState == 2) { if (autoReconnect) { setTimeout(serverPoll, 5000); } } else { QH('p0span', "Nelze se připojit k web socketu"); }
|
|
if (authCookieRenewTimer != null) { clearInterval(authCookieRenewTimer); authCookieRenewTimer = null; }
|
|
} else if (state == 2) {
|
|
// Fetch list of meshes, nodes, files
|
|
meshserver.send({ action: 'meshes' });
|
|
meshserver.send({ action: 'nodes', id: '{{currentNode}}' });
|
|
if (pluginHandler != null) { meshserver.send({ action: 'plugins' }); }
|
|
if ('{{currentNode}}' == '') { meshserver.send({ action: 'files' }); }
|
|
if ('{{viewmode}}' == '') { go(1); }
|
|
authCookieRenewTimer = setInterval(function () { meshserver.send({ action: 'authcookie' }); }, 1800000); // Request a cookie refresh every 30 minutes.
|
|
}
|
|
}
|
|
|
|
// Poll the server, if it responds, refresh the page.
|
|
function serverPoll() {
|
|
var xdr = null;
|
|
try { xdr = new XDomainRequest(); } catch (e) { }
|
|
if (!xdr) xdr = new XMLHttpRequest();
|
|
xdr.open('HEAD', window.location.href);
|
|
xdr.timeout = 15000;
|
|
xdr.onload = function () { reload(); };
|
|
xdr.onerror = xdr.ontimeout = function () { setTimeout(serverPoll, 10000); };
|
|
xdr.send();
|
|
}
|
|
|
|
// Return true if this browser supports clickonce
|
|
function detectClickOnce() {
|
|
for (var i in window.navigator.mimeTypes) { if (window.navigator.mimeTypes[i].type == 'application/x-ms-application') { return true; } }
|
|
var userAgent = window.navigator.userAgent.toUpperCase();
|
|
return (userAgent.indexOf('.NET CLR 3.5') >= 0) || (userAgent.indexOf('(WINDOWS NT ') >= 0);
|
|
}
|
|
|
|
function updateSiteAdmin() {
|
|
var noServerBackup = '{{{noServerBackup}}}';
|
|
var siteRights = userinfo.siteadmin;
|
|
if (noServerBackup == 1) { siteRights &= 0xFFFFFFFA; } // If not server backups allowed, remove server backup and restore permissions
|
|
|
|
// Update account actions
|
|
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.
|
|
QV('p2AccountActions', ((features & 4) == 0) && (serverinfo.domainauth == false)); // Hide Account Actions if in single user mode or domain authentication
|
|
QV('p2AccountImage', ((features & 4) == 0) && (serverinfo.domainauth == false)); // If account actions are not visible, also remove the image on that panel
|
|
QV('p2ServerActions', siteRights & 21);
|
|
QV('LeftMenuMyServer', siteRights & 21); // 16 + 4 + 1
|
|
QV('MainMenuMyServer', siteRights & 21);
|
|
QV('p2ServerActionsBackup', siteRights & 1);
|
|
QV('p2ServerActionsRestore', siteRights & 4);
|
|
QV('p2ServerActionsVersion', siteRights & 16);
|
|
QV('MainMenuMyFiles', siteRights & 8);
|
|
QV('LeftMenuMyFiles', siteRights & 8);
|
|
if (((siteRights & 8) == 0) && (xxcurrentView == 5)) { setDialogMode(0); go(1); }
|
|
if (currentNode != null) { gotoDevice(currentNode._id, xxcurrentView, true); }
|
|
|
|
// Update user management state
|
|
if ((userinfo.siteadmin & 2) != 0)
|
|
{
|
|
// We are user administrator
|
|
if (users == null) { meshserver.send({ action: 'users' }); }
|
|
if (wssessions == null) { meshserver.send({ action: 'wssessioncount' }); }
|
|
} else {
|
|
// We are not user administrator
|
|
users = null;
|
|
wssessions = null;
|
|
updateUsers();
|
|
if (xxcurrentView == 4 || ((xxcurrentView >= 30) && (xxcurrentView < 40))) { setDialogMode(0); go(1); currentUser = null; }
|
|
}
|
|
meshserver.send({ action: 'events', limit: parseInt(p3limitdropdown.value) });
|
|
QV('ServerConsole', userinfo.siteadmin === 0xFFFFFFFF);
|
|
QV('ServerTrace', userinfo.siteadmin === 0xFFFFFFFF);
|
|
if ((xxcurrentView == 115) && (userinfo.siteadmin != 0xFFFFFFFF)) { go(6); }
|
|
if ((xxcurrentView == 6) && ((userinfo.siteadmin & 21) == 0)) { go(1); }
|
|
|
|
// If we are site administrator, register to get server statistics
|
|
if ((siteRights & 21) != 0) { meshserver.send({ action: 'serverstats', interval: 10000 }); }
|
|
}
|
|
|
|
// To boost the speed of the web page when even floods occur, this method perform a delayed update on the web page.
|
|
var updateNaggleTimer = null;
|
|
var updateNaggleFlags = 0;
|
|
function masterUpdate(flags) {
|
|
updateNaggleFlags |= flags;
|
|
if (updateNaggleTimer == null) {
|
|
updateNaggleTimer = setTimeout(function () {
|
|
if (updateNaggleFlags & 512) { center(); }
|
|
if (updateNaggleFlags & 1) { onSearchInputChanged(); }
|
|
if (updateNaggleFlags & 2) { onSortSelectChange(false); }
|
|
if (updateNaggleFlags & 128) { updateMeshes(); }
|
|
if (updateNaggleFlags & 4) { updateDevices(); }
|
|
if (updateNaggleFlags & 8) { drawNotifications(); }
|
|
{{{StartGeoLocationJS}}}if (updateNaggleFlags & 16) { updateMapMarkers(); }{{{EndGeoLocationJS}}}
|
|
if (updateNaggleFlags & 32) { eventsUpdate(); }
|
|
{{{StartGeoLocationJS}}}if (updateNaggleFlags & 64) { refreshMap(false, true); }{{{EndGeoLocationJS}}}
|
|
if (updateNaggleFlags & 256) { drawDeviceTimeline(); }
|
|
if (updateNaggleFlags & 1024) { deviceEventsUpdate(); }
|
|
if (updateNaggleFlags & 2048) { userEventsUpdate(); }
|
|
if (updateNaggleFlags & 4096) { p20updateMesh(); }
|
|
updateNaggleTimer = null;
|
|
updateNaggleFlags = 0;
|
|
}, 150);
|
|
}
|
|
}
|
|
|
|
var backupCodesWarningDone = false;
|
|
function updateSelf() {
|
|
QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
|
QV('verifyEmailId2', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
|
QV('manageOtp', (userinfo.otpsecret == 1) || (userinfo.otphkeys > 0));
|
|
QV('authAppSetupCheck', userinfo.otpsecret == 1);
|
|
QV('authKeySetupCheck', userinfo.otphkeys > 0);
|
|
QV('authCodesSetupCheck', userinfo.otpkeys > 0);
|
|
masterUpdate(4 + 128 + 4096);
|
|
|
|
// Check if backup codes should really be enabled
|
|
if ((backupCodesWarningDone == false) && !(userinfo.otpkeys > 0) && (((userinfo.otpsecret == 1) && !(userinfo.otphkeys > 0)) || ((userinfo.otpsecret != 1) && (userinfo.otphkeys == 1)))) {
|
|
var n = { text: "Prosím přidejte 2-faktorové záložní kódy. Pokud dojde ke ztrátě současných faktorů, není možné tento účet obnovit.", title: "2-faktorová autentizace" };
|
|
addNotification(n);
|
|
backupCodesWarningDone = true;
|
|
}
|
|
|
|
// If we can't create new groups, hide all links that can do that.
|
|
var newGroupsAllowed = ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 64) == 0));
|
|
QV('p2createMeshLink1', newGroupsAllowed);
|
|
QV('p2createMeshLink2', newGroupsAllowed);
|
|
QV('getStarted1', newGroupsAllowed);
|
|
QV('getStarted2', !newGroupsAllowed);
|
|
|
|
if (typeof userinfo.passchange == 'number') {
|
|
if (userinfo.passchange == -1) { QH('p2nextPasswordUpdateTime', " - Reset při příštím přihlášení."); }
|
|
else if ((passRequirements != null) && (typeof passRequirements.reset == 'number')) {
|
|
var seconds = (userinfo.passchange) + (passRequirements.reset * 86400) - Math.floor(Date.now() / 1000);
|
|
if (seconds < 0) { QH('p2nextPasswordUpdateTime', " - Reset při příštím přihlášení."); }
|
|
else if (seconds < 3600) { QH('p2nextPasswordUpdateTime', format(" - Reset v {0} minut{1}.", Math.floor(seconds / 60), addLetterS(Math.floor(seconds / 60)))); }
|
|
else if (seconds < 86400) { QH('p2nextPasswordUpdateTime', format(" - Reset v {0} hodin{1}.", Math.floor(seconds / 3600), addLetterS(Math.floor(seconds / 3600)))); }
|
|
else { QH('p2nextPasswordUpdateTime', format(" - Reset v {0} den{1}."), Math.floor(seconds / 86400), addLetterS(Math.floor(seconds / 86400))); }
|
|
}
|
|
}
|
|
}
|
|
|
|
function addLetterS(x) { return (x > 1) ? 's' : ''; }
|
|
function setSessionActivity() { sessionActivity = Date.now(); QH('idleTimeoutNotify', ''); }
|
|
function checkIdleSessionTimeout() {
|
|
var delta = (Date.now() - sessionActivity);
|
|
if (delta > serverinfo.timeout) { window.location.href = 'logout'; } else {
|
|
var ds = Math.round((serverinfo.timeout - delta) / 1000);
|
|
if (ds <= 60) {
|
|
QH('idleTimeoutNotify', '<br />' + format("{0} sekund{1} do odpojení", ds, addLetterS(ds)));
|
|
} else {
|
|
ds = Math.round(ds / 60);
|
|
if (ds <= 5) { QH('idleTimeoutNotify', '<br />' + format("{0} minut{1} do odpojení", ds, addLetterS(ds))); }
|
|
}
|
|
}
|
|
}
|
|
|
|
function onMessage(server, message) {
|
|
switch (message.action) {
|
|
case 'trace': {
|
|
serverTrace.unshift(message);
|
|
displayServerTrace();
|
|
break;
|
|
}
|
|
case 'traceinfo': {
|
|
if (typeof message.traceSources == 'object') {
|
|
if ((message.traceSources != null) && (message.traceSources.length > 0)) {
|
|
serverTraceSources = message.traceSources;
|
|
QH('p41traceStatus', EscapeHtml(message.traceSources.join(', ')));
|
|
} else {
|
|
serverTraceSources = [];
|
|
QH('p41traceStatus', "Nic");
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 'serverstats': {
|
|
updateGeneralServerStats(message);
|
|
break;
|
|
}
|
|
case 'serverwarnings': {
|
|
if ((message.warnings != null) && (message.warnings.length > 0)) {
|
|
var x = '';
|
|
for (var i in message.warnings) { x += '<div style=color:red;padding-bottom:6px><b>' + "UPOZORNĚNÍ: " + message.warnings[i] + '</b></div>'; }
|
|
QH('serverWarnings', x);
|
|
QV('serverWarningsDiv', true);
|
|
}
|
|
break;
|
|
}
|
|
case 'servertimelinestats': {
|
|
setServerTimelineStats(message.events);
|
|
break;
|
|
}
|
|
case 'authcookie': {
|
|
// Got an authentication cookie refresh
|
|
authCookie = message.cookie;
|
|
authRelayCookie = message.rcookie;
|
|
break;
|
|
}
|
|
case 'serverinfo': {
|
|
serverinfo = message.serverinfo;
|
|
if (serverinfo.timeout) { setInterval(checkIdleSessionTimeout, 10000); checkIdleSessionTimeout(); }
|
|
if (debugmode == 1) { console.log('Server time: ', printDateTime(new Date(serverinfo.serverTime))); }
|
|
break;
|
|
}
|
|
case 'userinfo': {
|
|
userinfo = message.userinfo;
|
|
updateSiteAdmin();
|
|
updateSelf();
|
|
break;
|
|
}
|
|
case 'users': {
|
|
users = {};
|
|
for (var m in message.users) { users[message.users[m]._id] = message.users[m]; }
|
|
updateUsers();
|
|
break;
|
|
}
|
|
case 'wssessioncount': {
|
|
wssessions = message.wssessions;
|
|
updateUsers();
|
|
break;
|
|
}
|
|
case 'meshes': {
|
|
meshes = {};
|
|
for (var m in message.meshes) { meshes[message.meshes[m]._id] = message.meshes[m]; }
|
|
masterUpdate(4 + 128);
|
|
break;
|
|
}
|
|
case 'files': {
|
|
filetree = setupBackPointers(message.filetree);
|
|
updateFiles();
|
|
d3updatefiles();
|
|
break;
|
|
}
|
|
case 'nodes': {
|
|
nodes = [];
|
|
for (var m in message.nodes) {
|
|
if (!meshes[m]) { console.log('Invalid mesh (1): ' + m); continue; }
|
|
for (var n in message.nodes[m]) {
|
|
if (message.nodes[m][n]._id == null) { console.log('Invalid node (' + n + '): ' + JSON.stringify(message.nodes)); continue; }
|
|
message.nodes[m][n].namel = message.nodes[m][n].name.toLowerCase();
|
|
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; }
|
|
message.nodes[m][n].meshnamel = meshes[m].name.toLowerCase();
|
|
message.nodes[m][n].meshid = m;
|
|
message.nodes[m][n].state = (message.nodes[m][n].state)?(message.nodes[m][n].state):0;
|
|
message.nodes[m][n].desc = message.nodes[m][n].desc;
|
|
message.nodes[m][n].ip = message.nodes[m][n].ip;
|
|
if (!message.nodes[m][n].icon) message.nodes[m][n].icon = 1;
|
|
message.nodes[m][n].ident = ++nodeShortIdent;
|
|
nodes.push(message.nodes[m][n]);
|
|
}
|
|
}
|
|
masterUpdate(1 | 2 | 4 | 64);
|
|
|
|
if (xxcurrentView == -1) { if ('{{viewmode}}' != '') { go(parseInt('{{viewmode}}')); } else { setDialogMode(0); go(1); } }
|
|
if ('{{currentNode}}' != '') { gotoDevice('{{currentNode}}',parseInt('{{viewmode}}'));}
|
|
break;
|
|
}
|
|
case 'powertimeline': {
|
|
if (message.nodeid != powerTimelineReq) break;
|
|
powerTimelineNode = message.nodeid;
|
|
powerTimeline = message.timeline;
|
|
powerTimelineUpdate = Date.now() + 300000; // Update every 5 minutes
|
|
for (var i in powerTimeline) { if (i % 2 == 1) { powerTimeline[i] = powerTimeline[i] * 1000; } } // Decompress time
|
|
if (currentNode._id == message.nodeid) { masterUpdate(256); }
|
|
break;
|
|
}
|
|
case 'getsysinfo': {
|
|
if (message.nodeid != powerTimelineReq) break;
|
|
//console.log('getsysinfo', message); // ***********************
|
|
if (message.noinfo === true) {
|
|
QH('p17info', "Žádné informace o tomto zařízení.");
|
|
} else {
|
|
var x = '', s = {};
|
|
if (message.hardware) {
|
|
if (message.hardware.identifiers) {
|
|
var ident = message.hardware.identifiers;
|
|
// BIOS
|
|
x += '<div class=DevSt style=margin-bottom:3px><b>' + "BIOS" + '</b></div>';
|
|
if (ident.bios_vendor) { x += addDetailItem("Výrobce", ident.bios_vendor, s); }
|
|
if (ident.bios_version) { x += addDetailItem("Verze", ident.bios_version, s); }
|
|
x += '<br />';
|
|
|
|
// Motherboard
|
|
x += '<div class=DevSt style=margin-bottom:3px><b>' + "Základní deska" + '</b></div>';
|
|
if (ident.board_vendor) { x += addDetailItem("Výrobce", ident.board_vendor, s); }
|
|
if (ident.board_name) { x += addDetailItem("Jméno", ident.board_name, s); }
|
|
if (ident.board_serial && (ident.board_serial != '')) { x += addDetailItem("Sériový", ident.board_serial, s); }
|
|
if (ident.board_version) { x += addDetailItem("Verze", ident.board_version, s); }
|
|
if (ident.product_uuid) { x += addDetailItem("Identifikátor", ident.product_uuid, s); }
|
|
x += '<br />';
|
|
}
|
|
|
|
if (message.hardware.windows) {
|
|
if (message.hardware.windows.memory) {
|
|
// Memory
|
|
x += '<div class=DevSt style=margin-bottom:3px><b>' + "Paměť" + '</b></div>';
|
|
|
|
// Sort Memory
|
|
function memorySort(a, b) { if (a.BankLabel > b.BankLabel) return 1; if (a.BankLabel < b.BankLabel) return -1; return 0; }
|
|
message.hardware.windows.memory.sort(memorySort);
|
|
|
|
x += '<table style=width:100%>';
|
|
for (var i in message.hardware.windows.memory) {
|
|
var m = message.hardware.windows.memory[i];
|
|
x += '<tr><td VALIGN=Top style=width:38px><img src="images/ram2.png" />'
|
|
x += '<td><div style=background-color:lightgray;border-radius:5px;padding:8px>';
|
|
x += '<div><b>' + m.BankLabel + '</b></div>';
|
|
if (m.Capacity) { x += addDetailItem("Kapacita / Rychlost", format("{0} Mb, {1} Mhz", (m.Capacity / 1024 / 1024), m.Speed), s); }
|
|
if (m.PartNumber) { x += addDetailItem("Číslo dílu", ((m.Manufacturer && m.Manufacturer != 'Undefined')?(m.Manufacturer + ', '):'') + m.PartNumber, s); }
|
|
x += '</div>';
|
|
}
|
|
x += '</table><br />';
|
|
}
|
|
|
|
if (message.hardware.windows.osinfo) {
|
|
// Operating System
|
|
var m = message.hardware.windows.osinfo;
|
|
x += '<div class=DevSt style=margin-bottom:3px><b>' + "Operační systém" + '</b></div>';
|
|
if (m.Caption) { x += addDetailItem("Jméno", m.Caption, s); }
|
|
if (m.Version) { x += addDetailItem("Verze", m.Version, s); }
|
|
if (m.OSArchitecture) { x += addDetailItem("Architektura", m.OSArchitecture, s); }
|
|
x += '<br />';
|
|
}
|
|
|
|
// Disks
|
|
//x += '<div class=DevSt style=margin-bottom:3px><b>Disks</b></div>';
|
|
//x += '<br />';
|
|
}
|
|
}
|
|
|
|
QH('p17info', x);
|
|
}
|
|
break;
|
|
}
|
|
case 'lastconnect': {
|
|
var node = getNodeFromId(message.nodeid);
|
|
if (node != null) {
|
|
node.lastconnect = message.time;
|
|
node.lastaddr = message.addr;
|
|
if ((currentNode._id == node._id) && (Q('MainComputerState').innerHTML == '')) {
|
|
QH('MainComputerState', '<span>' + "Naposledy spatřen:" + '<br />' + printDateTime(new Date(node.lastconnect)) + '</span>');
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 'msg': {
|
|
// Check if this is a message from a node
|
|
if (message.nodeid != null) {
|
|
var index = -1;
|
|
if (nodes != null) { for (var i in nodes) { if (nodes[i]._id == message.nodeid) { index = i; break; } } }
|
|
if (index != -1) {
|
|
// Node was found, dispatch the message
|
|
if (message.type == 'console') { p15consoleReceive(nodes[index], message.value, message.source); } // This is a console message.
|
|
else if (message.type == 'notify') { // This is a notification message.
|
|
var n = getstore('notifications', 0);
|
|
if (((n & 8) == 0) && (message.amtMessage != null)) { break; } // Intel AMT desktop & terminal messages should be ignored.
|
|
var n = { text: message.value, title: message.title, icon: message.icon };
|
|
if (message.nodeid != null) { n.nodeid = message.nodeid; }
|
|
if (message.tag != null) { n.tag = message.tag; }
|
|
if (message.username != null) { n.username = message.username; }
|
|
addNotification(n);
|
|
} else if (message.type == 'ps') {
|
|
showDeskToolsProcesses(message);
|
|
} else if (message.type == 'services') {
|
|
showDeskToolsServices(message);
|
|
} else if ((message.type == 'getclip') && (xxdialogTag == 'clipboard') && (currentNode != null) && (currentNode._id == message.nodeid)) {
|
|
Q('d2clipText').value = message.data;
|
|
} else if ((message.type == 'setclip') && (xxdialogTag == 'clipboard') && (currentNode != null) && (currentNode._id == message.nodeid)) {
|
|
// Display success/fail on the clipboard dialog box.
|
|
QH('dlgClipStatus', message.success ? '<span style=color:green>' + "Úspěch" + '</span>' : '<span style=color:red>' + "Selhalo" + '</span>')
|
|
setTimeout(function () { try { QH('dlgClipStatus', ''); } catch (ex) { } }, 2000);
|
|
}
|
|
}
|
|
} else {
|
|
if (message.type == 'notify') { // This is a notification message.
|
|
var n = { text: message.value, title: message.title, icon: message.icon };
|
|
if (message.tag != null) { n.tag = message.tag; }
|
|
if (message.username != null) { n.username = message.username; }
|
|
addNotification(n);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 'getnetworkinfo': {
|
|
if ((currentNode._id == message.nodeid) && (xxdialogMode == 2) && (xxdialogTag == 'if' + message.nodeid)) {
|
|
if (message.netif == null) {
|
|
QH('d2netinfo', "Žádné informace k tomuto síťovému rozhraní.");
|
|
} else {
|
|
var x = '<div class=dialogText>';
|
|
|
|
if (currentNode.lastconnect) { x += addHtmlValue2("Poslední připojení agenta", printDateTime(new Date(currentNode.lastconnect))); }
|
|
if (currentNode.lastaddr) {
|
|
var splitip = currentNode.lastaddr.split(':');
|
|
if (splitip.length > 2) {
|
|
// IPv6
|
|
x += addHtmlValue2("Poslední adresa agenta", currentNode.lastaddr + ' <img src="images/link4.png" title="Copy address to clipboard" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(currentNode.lastaddr) + '\") width=10 height=10>');
|
|
} else {
|
|
// IPv4
|
|
if (isPrivateIP(currentNode.lastaddr)) {
|
|
x += addHtmlValue2("Poslední adresa agenta", splitip[0] + ' <img src="images/link4.png" title="' + "Kopírovat adresu do schránky" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(splitip[0]) + '\") width=10 height=10>');
|
|
} else {
|
|
x += addHtmlValue2("Poslední adresa agenta", '<a href="https://iplocation.com/?ip=' + splitip[0] + '" rel="noreferrer noopener" target="MeshIPLoopup">' + splitip[0] + '</a> <img src="images/link4.png" title="' + "Kopírovat adresu do schránky" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(splitip[0]) + '\") width=10 height=10>');
|
|
}
|
|
}
|
|
}
|
|
|
|
x += addHtmlValue2("Poslední změna rozhraní", printDateTime(new Date(message.updateTime)));
|
|
for (var i in message.netif) {
|
|
var net = message.netif[i];
|
|
x += '<hr />'
|
|
if (net.name) { x += addHtmlValue2("Jméno", '<b>' + EscapeHtml(net.name) + '</b>'); }
|
|
if (net.desc) { x += addHtmlValue2("Popis", EscapeHtml(net.desc).replace('(R)', '®').replace('(r)', '®')); }
|
|
if (net.dnssuffix) { x += addHtmlValue2("DNS suffix", EscapeHtml(net.dnssuffix) + ' <img src="images/link4.png" title="' + "Zkopírovat jméno do schránky" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.dnssuffix) + '\") width=10 height=10>'); }
|
|
if (net.mac) { x += addHtmlValue2("MAC adresa", '<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="' + "Kopírovat MAC adresu do schránky" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.mac.toLowerCase()) + '\") width=10 height=10>'); }
|
|
if (net.v4addr) { x += addHtmlValue2("IPv4 adresa", EscapeHtml(net.v4addr) + ' <img src="images/link4.png" title="' + "Kopírovat adresu do schránky" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4addr) + '\") width=10 height=10>'); }
|
|
if (net.v4mask) { x += addHtmlValue2("IPv4 maska", EscapeHtml(net.v4mask) + ' <img src="images/link4.png" title="' + "Kopírovat adresu do schránky" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4mask) + '\") width=10 height=10>'); }
|
|
if (net.v4gateway) { x += addHtmlValue2("IPv4 brána", EscapeHtml(net.v4gateway) + ' <img src="images/link4.png" title="' + "Kopírovat adresu do schránky" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4gateway) + '\") width=10 height=10>'); }
|
|
if (net.gatewaymac) { x += addHtmlValue2("MAC brány", '<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="' + "Kopírovat MAC adresu do schránky" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.gatewaymac.toLowerCase()) + '\") width=10 height=10>'); }
|
|
}
|
|
x += '</div>';
|
|
QH('d2netinfo', x);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 'serverversion': {
|
|
if ((xxdialogMode == 2) && (xxdialogTag == 'MeshCentralServerUpdate')) {
|
|
var x = '<div class=dialogText>';
|
|
if (!message.current) { message.current = "Neznámý"; }
|
|
if (!message.latest) { message.latest = "Neznámý"; }
|
|
x += addHtmlValue2("Aktuální verze", '<b>' + EscapeHtml(message.current) + '</b>');
|
|
x += addHtmlValue2("Poslední verze", '<b>' + EscapeHtml(message.latest) + '</b>');
|
|
x += '</div>';
|
|
if ((message.latest.indexOf('.') == -1) || (message.current == message.latest) || ((features & 2048) == 0)) {
|
|
setDialogMode(2, "MeshCentral verze", 1, null, x);
|
|
} else {
|
|
setDialogMode(2, "MeshCentral verze", 3, server_showVersionDlgEx, x + '<br /><label><input id=d2updateCheck type=checkbox onclick=server_showVersionDlgUpdate() /> ' + "Zatrhni a klikni na OK pro automatickou aktializaci serveru. " + '</label>');
|
|
server_showVersionDlgUpdate();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 'servererrors': {
|
|
if ((xxdialogMode == 2) && (xxdialogTag == 'MeshCentralServerErrors')) {
|
|
if (message.data == null) {
|
|
setDialogMode(2, "MeshCentral Serverové chyby", 1, null, "Server nemá žádný chybový log.");
|
|
} else {
|
|
var x = '<div class="dialogText dialogTextLog"><pre id=d2ServerErrorsLogPre>' + message.data + '<pre></div>';
|
|
setDialogMode(2, "MeshCentral Serverové chyby", 3, server_showErrorsDlgEx, x + '<br /><div style=float:right><img src=images/link4.png height=10 width=10 title="' + "Stáhnout chybový log" + '" style=cursor:pointer onclick=d2CopyServerErrorsToClip()></div><div><label><input id=d2updateCheck type=checkbox onclick=server_showVersionDlgUpdate() /> ' + "Zatrhni a klikni na OK pro vymazaní chybového logu." + '</label></div>');
|
|
server_showVersionDlgUpdate();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 'serverconsole': {
|
|
p15consoleReceive('serverconsole', message.value);
|
|
break;
|
|
}
|
|
case 'events': {
|
|
if ((message.nodeid != null) && (message.nodeid == currentNode._id)) {
|
|
currentDeviceEvents = message.events;
|
|
masterUpdate(1024);
|
|
} else if ((message.user != null) && (message.user == currentUser.name)) {
|
|
currentUserEvents = message.events;
|
|
masterUpdate(2048);
|
|
} else {
|
|
events = message.events;
|
|
masterUpdate(32);
|
|
}
|
|
break;
|
|
}
|
|
case 'getcookie': {
|
|
if (message.tag == 'clickonce') {
|
|
var basicPort = '{{{serverRedirPort}}}' == '' ? '{{{serverPublicPort}}}' : '{{{serverRedirPort}}}';
|
|
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');
|
|
var newWindow = window.open(rdpurl, '_blank');
|
|
newWindow.opener = null;
|
|
}
|
|
break;
|
|
}
|
|
case 'getNotes': {
|
|
var n = Q('d2devNotes');
|
|
if (n && (message.id == decodeURIComponent(n.attributes['noteid'].value))) {
|
|
if (message.notes) { QH('d2devNotes', decodeURIComponent(message.notes)); } else { QH('d2devNotes', ''); }
|
|
var ro = (n.attributes['ro'].value == 'true');
|
|
if (ro == false) { // If we have permissions, set read/write on this note.
|
|
n.removeAttribute('readonly');
|
|
QE('idx_dlgOkButton', true);
|
|
QV('idx_dlgOkButton', true);
|
|
focusTextBox('d2devNotes');
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 'otpauth-request': {
|
|
if ((xxdialogMode == 2) && (xxdialogTag == 'otpauth-request')) {
|
|
var secret = message.secret;
|
|
if (secret.length == 52) { secret = secret.split(/(.............)/).filter(Boolean).join(' '); }
|
|
else if (secret.length == 32) { secret = secret.split(/(....)/).filter(Boolean).join(' '); secret = secret.substring(0, 20) + '<br/>' + secret.substring(20) }
|
|
QH('d2optinfo', '<table style=width:380px><tr><td style=vertical-align:top>' + "Nainstalujte si <a href=\"https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2\" rel=\"noreferrer noopener\" target=_blank>Google Authenticator</a> nebo kompatibilní aplikaci a naskenujte kód, použijte <a href=\"' + message.url + '\" rel=\"noreferrer noopener\" target=_blank> tento odkaz</a> nebo vložte secret. Pak vložte aktuální 6 číselný token pro aktivaci 2-faktorového přihlašování." + '<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 />' + "Zadejte token pro 2-faktorové přihlášení:" + ' <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>');
|
|
new QRCode(Q('qrcode'), { text: message.url, width: 128, height: 128, colorDark: '#000000', colorLight: '#EEE', correctLevel: QRCode.CorrectLevel.H });
|
|
QV('idx_dlgOkButton', true);
|
|
QE('idx_dlgOkButton', false);
|
|
Q('d2otpauthinput').focus();
|
|
}
|
|
break;
|
|
}
|
|
case 'otpauth-setup': {
|
|
if (xxdialogMode) return;
|
|
setDialogMode(2, "Aplikace pro autentizaci", 1, null, message.success ? ('<b style=color:green>' + "Aktivace autentizační aplikace úspěšná." + '</b> ' + "Budete potřebovat platný token k novému přihlášení.") : ('<b style=color:red>' + "aktivace 2-faktorového přihlašování selhalo." + '</b> ' + "Vymaž tajemství z aplikace a zkus to znovu. Máš na zadání správného kódu jen pár minut."));
|
|
break;
|
|
}
|
|
case 'otpauth-clear': {
|
|
if (xxdialogMode) return;
|
|
setDialogMode(2, "Aplikace pro autentizaci", 1, null, message.success ? ('<b>' + "Autentizační aplikace odstraněna." + '</b> ' + "Tuto funkci můžete kdykoli znovu aktivovat.") : ('<b style=color:red>' + "odstranění 2-faktorového přihlašování selhalo." + '</b> ' + "Zkusit znovu."));
|
|
break;
|
|
}
|
|
case 'otpauth-getpasswords': {
|
|
if (xxdialogMode) return;
|
|
var x = "Jednorázové tokeny lze použít jako sekundární autentizaci. Vytvořte sadu, vytiskněte je a uložte na bezpečném místě.";
|
|
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>';
|
|
if (message.passwords) {
|
|
var j = 0, clipb = '';
|
|
for (var i in message.passwords) {
|
|
if (++j % 2) { x += '<tr>'; }
|
|
var p = '' + message.passwords[i].p;
|
|
while (p.length < 8) { p = '0' + p; }
|
|
if (message.passwords[i].u === true) {
|
|
x += '<td>' + p.substring(0, 4) + ' ' + p.substring(4);
|
|
if (clipb != '') { clipb += ' '; }
|
|
clipb += p;
|
|
} else {
|
|
x += '<td><strike style=color:#BBB>' + p.substring(0, 4) + ' ' + p.substring(4); + '</strike>';
|
|
}
|
|
}
|
|
} else {
|
|
x += '<tr><td>' + "Žádné aktivní tokeny";
|
|
}
|
|
x += '</table></div></div><br />';
|
|
x += '<div><input type=button value=' + "Zavřít" + ' onclick=setDialogMode(0) style=float:right></input>';
|
|
x += '<input type=button value="' + "Generovat nové tokeny" + '" onclick="account_manageOtp(1);"></input>';
|
|
if (message.passwords != null) {
|
|
x += '<input type=button value="' + "Vymazat tokeny" + '" onclick="account_manageOtp(2);"></input>';
|
|
x += ' <img src=images/link4.png height=10 width=10 title="' + "Kopírovat platné kódy do schránky" + '" style=cursor:pointer onclick=copyTextToClip2("' + encodeURIComponent(clipb) + '")>';
|
|
}
|
|
x += '</div><br />';
|
|
setDialogMode(2, "Spravovat záložní kódy", 8, null, x, 'otpauth-manage');
|
|
break;
|
|
}
|
|
case 'otp-hkey-get': {
|
|
if (xxdialogMode && (xxdialogTag != 'otpauth-hardware-manage')) return;
|
|
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>';
|
|
var end = '</table></div></div>';
|
|
var x = "<a href=\"https://www.yubico.com/\" rel=\"noreferrer noopener\" target=\"_blank\">Hardwarové klíče</a> jsou použity jako druhá možnost autentizace.";
|
|
x += '<div style="max-height:150px;overflow-y:auto;overflow-x:hidden;margin-top:6px;margin-bottom:6px">';
|
|
if (message.keys && message.keys.length > 0) {
|
|
for (var i in message.keys) {
|
|
var key = message.keys[i], type = (key.type == 2)?'OTP':'WebAuthn';
|
|
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="' + "Odstranit" + '" onclick=account_removehkey(' + key.i + ')></input>' + end;
|
|
}
|
|
} else {
|
|
x += start + '<tr style=text-align:center><td>' + "Žádný klíč není zkonfigurován" + end;
|
|
}
|
|
x += '</div>';
|
|
x += '<div><input type=button value="' + "Zavřít" + '" onclick=setDialogMode(0) style=float:right></input>';
|
|
if ((features & 0x00020000) != 0) { x += '<input id=d2addkey3 type=button value="' + "Přidat klíč" + '" onclick="account_addhkey(3);"></input>'; }
|
|
if ((features & 0x00004000) != 0) { x += '<input id=d2addkey2 type=button value="' + "Přidat YubiKey® OTP" + '" onclick="account_addhkey(2);"></input>'; }
|
|
x += '</div><br />';
|
|
setDialogMode(2, "Spravovat bezpečnostní klíče", 8, null, x, 'otpauth-hardware-manage');
|
|
if (u2fSupported() == false) { QE('d2addkey1', false); }
|
|
break;
|
|
}
|
|
case 'otp-hkey-yubikey-add': {
|
|
if (message.result) {
|
|
meshserver.send({ action: 'otp-hkey-get' }); // Success, ask for the full list of keys.
|
|
} else {
|
|
setDialogMode(2, "Přidat bezpečnostní klíč", 1, null, '<br />' + "Chyba, nelze přidat klíč." + '<br /><br />');
|
|
}
|
|
break;
|
|
}
|
|
case 'otp-hkey-setup-response': {
|
|
if (xxdialogMode && (xxdialogTag != 'otpauth-hardware-manage')) return;
|
|
if (message.result == true) {
|
|
meshserver.send({ action: 'otp-hkey-get' }); // Success, ask for the full list of keys.
|
|
} else {
|
|
setDialogMode(2, "Přidat bezpečnostní klíč", 1, null, '<br />' + "CHYBA: nelze přidat klíč." + '<br /><br />', 'otpauth-hardware-manage');
|
|
}
|
|
break;
|
|
}
|
|
case 'webauthn-startregister': {
|
|
if (xxdialogMode && (xxdialogTag != 'otpauth-hardware-manage')) return;
|
|
var x = "Stiskni klávesu." + '<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 + ' />';
|
|
setDialogMode(2, "Přidat bezpečnostní klíč", 2, null, x);
|
|
|
|
var publicKey = message.request;
|
|
message.request.challenge = Uint8Array.from(atob(message.request.challenge), function (c) { return c.charCodeAt(0) })
|
|
message.request.user.id = Uint8Array.from(atob(message.request.user.id), function (c) { return c.charCodeAt(0) })
|
|
navigator.credentials.create({ publicKey: publicKey })
|
|
.then(function(newCredentialInfo) {
|
|
// Public key credential
|
|
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 };
|
|
meshserver.send({ action: 'webauthn-endregister', response: r });
|
|
setDialogMode(0);
|
|
}, function(error) {
|
|
// Error
|
|
setDialogMode(2, "Přidat bezpečnostní klíč", 1, null, "CHYBA: " + error);
|
|
});
|
|
break;
|
|
}
|
|
case 'event': {
|
|
if (!message.event.nolog) {
|
|
if (currentNode && (message.event.nodeid == currentNode._id)) {
|
|
// If this event has a nodeid and we are looking at this node, update the log in real time.
|
|
currentDeviceEvents.unshift(message.event);
|
|
var eventLimit = parseInt(p16limitdropdown.value);
|
|
while (currentDeviceEvents.length > eventLimit) { currentDeviceEvents.pop(); } // Remove element(s) at the end
|
|
masterUpdate(1024);
|
|
}
|
|
|
|
if (currentUser && (message.event.userid == currentUser._id)) {
|
|
// If this event has a userid and we are looking at this user, update the log in real time.
|
|
currentUserEvents.unshift(message.event);
|
|
var eventLimit = parseInt(p31limitdropdown.value);
|
|
while (currentUserEvents.length > eventLimit) { currentUserEvents.pop(); } // Remove element(s) at the end
|
|
masterUpdate(2048);
|
|
}
|
|
|
|
// Add this event to the master events log.
|
|
events.unshift(message.event);
|
|
var eventLimit = parseInt(p3limitdropdown.value);
|
|
while (events.length > eventLimit) { events.pop(); } // Remove element(s) at the end
|
|
masterUpdate(32);
|
|
}
|
|
if (message.event.noact) break; // Take no action on this event
|
|
switch (message.event.action) {
|
|
case 'userWebState': {
|
|
// New user web state, update the web page as needed
|
|
if (localStorage != null) {
|
|
var oldShowRealNames = localStorage.getItem('showRealNames');
|
|
var oldUiMode = localStorage.getItem('uiMode');
|
|
var oldSort = localStorage.getItem('sort');
|
|
var oldLoctag = localStorage.getItem('loctag');
|
|
|
|
var webstate = JSON.parse(message.event.state);
|
|
for (var i in webstate) { localStorage.setItem(i, webstate[i]); }
|
|
|
|
// Update the web page
|
|
if ((webstate.deskAspectRatio != null) && (webstate.deskAspectRatio != deskAspectRatio)) { deskAspectRatio = webstate.deskAspectRatio; deskAdjust(); }
|
|
if ((webstate.showRealNames != null) && (webstate.showRealNames != oldShowRealNames)) { showRealNames = Q('RealNameCheckBox').checked = (webstate.showRealNames == '1'); masterUpdate(6); }
|
|
if ((webstate.uiMode != null) && (webstate.uiMode != oldUiMode)) { userInterfaceSelectMenu(parseInt(webstate.uiMode)); }
|
|
if ((webstate.sort != null) && (webstate.sort != oldSort)) { document.getElementById('sortselect').selectedIndex = sort = parseInt(webstate.sort); masterUpdate(6); }
|
|
if ((webstate.loctag != null) && (webstate.loctag != oldLoctag)) { if (webstate.loctag != null) { args.locale = webstate.loctag; } else { delete args.locale; } masterUpdate(0xFFFFFFFF); }
|
|
}
|
|
break;
|
|
}
|
|
case 'servertimelinestats': { addServerTimelineStats(message.event.data); break; }
|
|
case 'accountcreate':
|
|
case 'accountchange': {
|
|
// An account was created or changed
|
|
if (userinfo.name == message.event.account.name) {
|
|
var newsiteadmin = message.event.account.siteadmin?message.event.account.siteadmin:0;
|
|
var oldsiteadmin = userinfo.siteadmin?userinfo.siteadmin:0;
|
|
if ((message.event.account.quota != userinfo.quota) || (((userinfo.siteadmin & 8) == 0) && ((message.event.account.siteadmin & 8) != 0))) { meshserver.send({ action: 'files' }); }
|
|
var oldgroups = userinfo.groups;
|
|
userinfo = message.event.account;
|
|
if (oldsiteadmin != newsiteadmin) updateSiteAdmin();
|
|
updateSelf();
|
|
|
|
if ((userinfo.siteadmin & 2) != 0) {
|
|
// Compare our groups
|
|
var og = oldgroups ? oldgroups : [];
|
|
var ng = userinfo.groups ? userinfo.groups : [];
|
|
if (og.join(',') != ng.join(',')) {
|
|
// Our groups have changed, re-ask for a list of users.
|
|
users = wssessions = null;
|
|
meshserver.send({ action: 'users' });
|
|
meshserver.send({ action: 'wssessioncount' });
|
|
}
|
|
}
|
|
}
|
|
if (users == null) break;
|
|
|
|
// Check if the account is part of our user group
|
|
if ((userinfo.groups == null) || (userinfo.groups.length == 0) || (findOne(message.event.account.groups, userinfo.groups) == true)) {
|
|
users[message.event.account._id] = message.event.account; // Part of our groups, update this user.
|
|
} else {
|
|
delete users[message.event.account._id]; // No longer part of our groups, remove this user.
|
|
}
|
|
|
|
updateUsers();
|
|
break;
|
|
}
|
|
case 'accountremove': {
|
|
// An account was removed
|
|
if (users == null) break;
|
|
delete users['user/' + domain + '/' + message.event.username.toLowerCase()];
|
|
updateUsers();
|
|
break;
|
|
}
|
|
case 'createmesh': {
|
|
// A new mesh was created
|
|
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.
|
|
meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links };
|
|
masterUpdate(4 + 128);
|
|
meshserver.send({ action: 'files' });
|
|
}
|
|
break;
|
|
}
|
|
case 'meshchange': {
|
|
// Update mesh information
|
|
if (meshes[message.event.meshid] == null) {
|
|
// This is a new mesh for us
|
|
meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links };
|
|
meshserver.send({ action: 'nodes' }); // Request a refresh of all nodes (TODO: We could optimize this to only request nodes for the new mesh).
|
|
} else {
|
|
// This is an existing mesh
|
|
if (message.event.name != null) {
|
|
meshes[message.event.meshid].name = message.event.name;
|
|
for (var i in nodes) { if (nodes[i].meshid == message.event.meshid) { nodes[i].meshnamel = message.event.name.toLowerCase(); } }
|
|
}
|
|
if (message.event.desc != null) { meshes[message.event.meshid].desc = message.event.desc; }
|
|
if (message.event.flags != null) { meshes[message.event.meshid].flags = message.event.flags; }
|
|
if (message.event.consent != null) { meshes[message.event.meshid].consent = message.event.consent; }
|
|
if (message.event.links) { meshes[message.event.meshid].links = message.event.links; }
|
|
if (message.event.amt) { meshes[message.event.meshid].amt = message.event.amt; }
|
|
|
|
// Check if we lost rights to this mesh in this change.
|
|
if (meshes[message.event.meshid].links[userinfo._id] == null) {
|
|
if ((xxcurrentView == 20) && (currentMesh == meshes[message.event.meshid])) go(2);
|
|
delete meshes[message.event.meshid];
|
|
|
|
// Delete all nodes in that mesh
|
|
var newnodes = [];
|
|
for (var i in nodes) { if (nodes[i].meshid != message.event.meshid) { newnodes.push(nodes[i]); } }
|
|
nodes = newnodes;
|
|
|
|
// If we are looking at a node in the deleted mesh, move back to "My Devices"
|
|
if (xxcurrentView >= 10 && xxcurrentView < 20 && currentNode && currentNode.meshid == message.event.meshid) { setDialogMode(0); go(1); }
|
|
}
|
|
}
|
|
masterUpdate(4 + 128);
|
|
if (currentNode && (currentNode.meshid == message.event.meshid)) { currentNode = null; if ((xxcurrentView >= 10) && (xxcurrentView < 20)) { go(1); } }
|
|
//meshserver.send({ action: 'files' }); // TODO: Why do we need to do this??
|
|
|
|
// If we are looking at a mesh that is now deleted, move back to "My Account"
|
|
if (xxcurrentView == 20 && currentMesh._id == message.event.meshid) { masterUpdate(4096); }
|
|
break;
|
|
}
|
|
case 'deletemesh': {
|
|
// Delete the mesh
|
|
if (meshes[message.event.meshid]) {
|
|
delete meshes[message.event.meshid];
|
|
masterUpdate(128);
|
|
meshserver.send({ action: 'files' });
|
|
}
|
|
|
|
// Delete all nodes in that mesh
|
|
var newnodes = [];
|
|
if (nodes != null) { for (var i in nodes) { if (nodes[i].meshid != message.event.meshid) { newnodes.push(nodes[i]); } } }
|
|
nodes = newnodes;
|
|
masterUpdate(4);
|
|
|
|
// If we are looking at a mesh that is now deleted, move back to "My Account"
|
|
if (xxcurrentView >= 20 && xxcurrentView < 30 && currentMesh._id == message.event.meshid) { setDialogMode(0); go(2); }
|
|
// If we are looking at a node in the deleted mesh, move back to "My Devices"
|
|
if (xxcurrentView >= 10 && xxcurrentView < 20 && currentNode && currentNode.meshid == message.event.meshid) { setDialogMode(0); go(1); }
|
|
|
|
break;
|
|
}
|
|
case 'addnode': {
|
|
var node = message.event.node;
|
|
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.
|
|
if (getNodeFromId(node._id) != null) break; // This node is already known.
|
|
node.namel = node.name.toLowerCase();
|
|
if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
|
|
node.meshnamel = meshes[node.meshid].name.toLowerCase();
|
|
node.state = 0;
|
|
if (!node.icon) node.icon = 1;
|
|
node.ident = ++nodeShortIdent;
|
|
if (nodes == null) { }
|
|
nodes.push(node);
|
|
|
|
// Web page update
|
|
masterUpdate(1 | 2 | 4 | 16);
|
|
|
|
break;
|
|
}
|
|
case 'removenode': {
|
|
var index = -1;
|
|
for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
|
|
if (index != -1) {
|
|
var node = nodes[index];
|
|
if (currentNode == node) {
|
|
if (xxcurrentView >= 10 && xxcurrentView < 20) { setDialogMode(0); go(1); }
|
|
currentNode = null;
|
|
// TODO: Correctly disconnect from this node (Desktop/Terminal/Files...)
|
|
}
|
|
nodes.splice(index, 1);
|
|
|
|
// Web page update
|
|
masterUpdate(4 | 16);
|
|
}
|
|
break;
|
|
}
|
|
case 'changenode': {
|
|
var index = -1;
|
|
for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
|
|
if (index != -1) {
|
|
var node = nodes[index];
|
|
|
|
// Change the node
|
|
node.name = message.event.node.name;
|
|
node.rname = message.event.node.rname;
|
|
node.users = message.event.node.users;
|
|
node.host = message.event.node.host;
|
|
node.desc = message.event.node.desc;
|
|
node.ip = message.event.node.ip;
|
|
node.osdesc = message.event.node.osdesc;
|
|
node.publicip = message.event.node.publicip;
|
|
node.iploc = message.event.node.iploc;
|
|
node.wifiloc = message.event.node.wifiloc;
|
|
node.gpsloc = message.event.node.gpsloc;
|
|
node.tags = message.event.node.tags;
|
|
node.userloc = message.event.node.userloc;
|
|
if (message.event.node.agent != null) {
|
|
if (node.agent == null) node.agent = {};
|
|
if (message.event.node.agent.ver != null) { node.agent.ver = message.event.node.agent.ver; }
|
|
if (message.event.node.agent.id != null) { node.agent.id = message.event.node.agent.id; }
|
|
if (message.event.node.agent.caps != null) { node.agent.caps = message.event.node.agent.caps; }
|
|
if (message.event.node.agent.core != null) { node.agent.core = message.event.node.agent.core; } else { if (node.agent.core) { delete node.agent.core; } }
|
|
node.agent.tag = message.event.node.agent.tag;
|
|
}
|
|
if (message.event.node.intelamt != null) {
|
|
if (node.intelamt == null) node.intelamt = {};
|
|
if (message.event.node.intelamt.state != null) { node.intelamt.state = message.event.node.intelamt.state; }
|
|
if (message.event.node.intelamt.host != null) { node.intelamt.user = message.event.node.intelamt.host; }
|
|
if (message.event.node.intelamt.user != null) { node.intelamt.user = message.event.node.intelamt.user; }
|
|
if (message.event.node.intelamt.tls != null) { node.intelamt.tls = message.event.node.intelamt.tls; }
|
|
if (message.event.node.intelamt.ver != null) { node.intelamt.ver = message.event.node.intelamt.ver; }
|
|
if (message.event.node.intelamt.tag != null) { node.intelamt.tag = message.event.node.intelamt.tag; }
|
|
if (message.event.node.intelamt.uuid != null) { node.intelamt.uuid = message.event.node.intelamt.uuid; }
|
|
if (message.event.node.intelamt.realm != null) { node.intelamt.realm = message.event.node.intelamt.realm; }
|
|
}
|
|
if (message.event.node.av != null) { node.av = message.event.node.av; }
|
|
node.namel = node.name.toLowerCase();
|
|
if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
|
|
if (message.event.node.icon) { node.icon = message.event.node.icon; }
|
|
|
|
// Web page update
|
|
masterUpdate(2 | 4 | 8 | 16);
|
|
refreshDevice(node._id);
|
|
|
|
if ((currentNode == node) && (xxdialogMode != null) && (xxdialogTag == '@xxmap')) { p10showNodeLocationDialog(); }
|
|
}
|
|
break;
|
|
}
|
|
case 'nodemeshchange': {
|
|
var index = -1;
|
|
for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
|
|
if (index != -1) {
|
|
var node = nodes[index];
|
|
if (meshes[message.event.newMeshId] == null) {
|
|
// We don't see the new mesh, remove this device
|
|
|
|
// TODO: Correctly disconnect from this node (Desktop/Terminal/Files...)
|
|
if (currentNode == node) { if (xxcurrentView >= 10 && xxcurrentView < 20) { setDialogMode(0); go(1); } currentNode = null; }
|
|
nodes.splice(index, 1);
|
|
masterUpdate(4 | 16);
|
|
} else {
|
|
// We see the new mesh, move this device
|
|
node.meshid = message.event.newMeshId;
|
|
node.meshnamel = meshes[message.event.newMeshId].name.toLowerCase();
|
|
masterUpdate(1 | 2 | 4);
|
|
}
|
|
refreshDevice(message.event.nodeid);
|
|
} else {
|
|
// This is a new device, add it.
|
|
var node = message.event.node;
|
|
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.
|
|
node.namel = node.name.toLowerCase();
|
|
if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
|
|
node.meshnamel = meshes[node.meshid].name.toLowerCase();
|
|
node.state = 0;
|
|
if (!node.icon) node.icon = 1;
|
|
node.ident = ++nodeShortIdent;
|
|
if (nodes == null) { }
|
|
nodes.push(node);
|
|
|
|
// Web page update
|
|
masterUpdate(1 | 2 | 4 | 16);
|
|
}
|
|
break;
|
|
}
|
|
case 'nodeconnect': {
|
|
// Indicated a node has changed connectivity state
|
|
var index = -1;
|
|
for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
|
|
if (index != -1) {
|
|
var node = nodes[index];
|
|
|
|
// Event the connection change if needed
|
|
var n = getstore('notifications', 0); // Account notification settings
|
|
|
|
// Per-group notification settings
|
|
if (message.event.meshid && userinfo.links && userinfo.links[message.event.meshid] && userinfo.links[message.event.meshid].notify) {
|
|
n &= userinfo.links[message.event.meshid].notify;
|
|
} else {
|
|
n = 0;
|
|
}
|
|
|
|
// Show the notification
|
|
if (n & 2) {
|
|
if (((node.conn & 1) == 0) && ((message.event.conn & 1) != 0)) { addNotification({ text: "Agent připojen", title: node.name, icon: node.icon, nodeid: node._id }); }
|
|
if (((node.conn & 2) == 0) && ((message.event.conn & 2) != 0)) { addNotification({ text: "Intel AMT detekováno", title: node.name, icon: node.icon, nodeid: node._id }); }
|
|
if (((node.conn & 4) == 0) && ((message.event.conn & 4) != 0)) { addNotification({ text: "Intel AMT CIRA připojeno", title: node.name, icon: node.icon, nodeid: node._id }); }
|
|
if (((node.conn & 16) == 0) && ((message.event.conn & 16) != 0)) { addNotification({ text: "MQTT připojeno", title: node.name, icon: node.icon, nodeid: node._id }); }
|
|
}
|
|
if (n & 4) {
|
|
if (((node.conn & 1) != 0) && ((message.event.conn & 1) == 0)) { addNotification({ text: "Agent odpojen", title: node.name, icon: node.icon, nodeid: node._id }); }
|
|
if (((node.conn & 2) != 0) && ((message.event.conn & 2) == 0)) { addNotification({ text: "Intel AMT není detekováno", title: node.name, icon: node.icon, nodeid: node._id }); }
|
|
if (((node.conn & 4) != 0) && ((message.event.conn & 4) == 0)) { addNotification({ text: "Intel AMT CIRA odpojeno", title: node.name, icon: node.icon, nodeid: node._id }); }
|
|
if (((node.conn & 16) != 0) && ((message.event.conn & 16) == 0)) { addNotification({ text: "MQTT odpojeno", title: node.name, icon: node.icon, nodeid: node._id }); }
|
|
}
|
|
|
|
// Change the node connection state
|
|
node.conn = message.event.conn;
|
|
node.pwr = message.event.pwr;
|
|
|
|
// Web page update
|
|
masterUpdate(4 | 16);
|
|
refreshDevice(node._id);
|
|
}
|
|
break;
|
|
}
|
|
case 'wssessioncount': {
|
|
// Update the active web socket session count for a user
|
|
if (wssessions != null) {
|
|
if (message.event.count == 0 && wssessions['user/' + domain + '/' + message.event.username.toLowerCase()]) {
|
|
delete wssessions['user/' + domain + '/' + message.event.username.toLowerCase()];
|
|
} else {
|
|
wssessions['user/' + domain + '/' + message.event.username.toLowerCase()] = message.event.count;
|
|
}
|
|
updateUsers();
|
|
}
|
|
break;
|
|
}
|
|
case 'login': {
|
|
// Update the last login time
|
|
if (users != null && users['user/' + domain + '/' + message.event.username.toLowerCase()]) {
|
|
users['user/' + domain + '/' + message.event.username.toLowerCase()].login = Math.floor(new Date(message.event.time).getTime() / 1000);
|
|
}
|
|
break;
|
|
}
|
|
case 'scanamtdevice': {
|
|
// Populate the Intel AMT scan dialog box with the result of the RMCP scan
|
|
if ((xxdialogMode == null) || (!Q('dp1range')) || (Q('dp1range').value != message.event.range)) return;
|
|
var x = '';
|
|
if (message.event.results == null) {
|
|
// The scan could not occur because of an error. Likely the user range was invalid.
|
|
x = '<div style=width:100%;text-align:center;margin-top:12px>' + "Nelze skenovat tento rozsah." + '</div><div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>' + "Příklad rozsahu IP adres<br />192.168.0.100<br />192.168.1.0/24<br />192.167.0.1-192.168.0.100" + '</div>';
|
|
} else {
|
|
// Go thru all the results and populate the dialog box
|
|
amtScanResults = message.event.results;
|
|
for (var i in message.event.results) {
|
|
var r = message.event.results[i], shortname = r.hostname;
|
|
if (shortname.length > 20) { shortname = shortname.substring(0, 20) + '...'; }
|
|
var str = '<b title="' + EscapeHtml(r.hostname) + '">' + EscapeHtml(shortname) + '</b> - v' + r.ver;
|
|
if (r.state == 2) { if (r.tls == 1) { str += " s TLS."; } else { str += " bez TLS."; } } else { str += ' not activated.'; }
|
|
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>';
|
|
}
|
|
// If no results where found, display a nice message
|
|
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>'; }
|
|
}
|
|
// Set the html in the dialog box and re-enable the scan button
|
|
QH('dp1results', x);
|
|
QE('dp1range', true);
|
|
QE('dp1rangebutton', true);
|
|
break;
|
|
}
|
|
case 'notify': {
|
|
var n = { text: message.event.value, title: message.event.title, icon: message.event.icon };
|
|
if (message.event.tag != null) { n.tag = message.event.tag; }
|
|
addNotification(n);
|
|
break;
|
|
}
|
|
case 'traceinfo': {
|
|
if (typeof message.event.traceSources == 'object') {
|
|
if ((message.event.traceSources != null) && (message.event.traceSources.length > 0)) {
|
|
serverTraceSources = message.event.traceSources;
|
|
QH('p41traceStatus', EscapeHtml(message.event.traceSources.join(', ')));
|
|
} else {
|
|
serverTraceSources = [];
|
|
QH('p41traceStatus', "Nic");
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 'sysinfohash': {
|
|
// If the sysinfo document has changed and we are looking at it, request an update.
|
|
if ((currentNode != null) && (message.event.nodeid == powerTimelineReq)) {
|
|
meshserver.send({ action: 'getsysinfo', nodeid: message.event.nodeid });
|
|
}
|
|
break;
|
|
}
|
|
case 'stopped': { // Server is stopping.
|
|
// Disconnect
|
|
//console.log(message.msg);
|
|
break;
|
|
}
|
|
case 'updatePluginList': {
|
|
installedPluginList = message.event.list;
|
|
updatePluginList();
|
|
break;
|
|
}
|
|
case 'pluginStateChange': {
|
|
if (pluginHandler == null) break;
|
|
pluginHandler.refreshPluginHandler();
|
|
break;
|
|
}
|
|
default:
|
|
//console.log('Unknown message.event.action', message.event.action);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case 'createInviteLink': { // Agent installation invitation link
|
|
if (xxdialogTag != message.meshid) break;
|
|
var servername = serverinfo.name;
|
|
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.
|
|
var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
|
|
var url;
|
|
if (serverinfo.https == true) {
|
|
var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
|
|
url = 'https://' + servername + portStr + domainUrl + 'agentinvite?c=' + message.cookie;
|
|
} else {
|
|
var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
|
|
url = 'http://' + servername + portStr + domainUrl + 'agentinvite?c=' + message.cookie;
|
|
}
|
|
Q('agentInvitationLink').href = url;
|
|
var t = format("{0} hodina{1}", message.expire, addLetterS(message.expire));
|
|
if (message.expire == 24) { t = "1 den"; }
|
|
if (message.expire == 168) { t = "1 týden"; }
|
|
if (message.expire == 5040) { t = "1 měsíc"; }
|
|
if (message.expire == 0) { t = "Bez limitu"; }
|
|
QH('agentInvitationLink', format("Link pro pozvání ({0})", t));
|
|
QV('agentInvitationLinkDiv', true);
|
|
break;
|
|
}
|
|
case 'getmqttlogin': {
|
|
if ((currentNode == null) || (currentNode._id != message.nodeid) || (xxdialogMode != null)) return;
|
|
var x = "Tyto nastavení mohou být použity pro MQTT tohoto zařízení." + '<br /><br />';
|
|
delete message.action;
|
|
delete message.nodeid;
|
|
x += '<textarea readonly=readonly style=width:100%;resize:none;height:100px;overflow:auto;font-size:12px readonly>' + JSON.stringify(message) + '</textarea>';
|
|
/*
|
|
x += addHtmlValue('Username', '<input style=width:230px readonly value="' + message.user + '" />');
|
|
x += addHtmlValue('Password', '<input style=width:230px readonly value="' + message.pass + '" />');
|
|
x += addHtmlValue('WS URL', '<input style=width:230px readonly value="' + message.wsUrl + '" />');
|
|
if (message.mpsUrl && message.mpsCertHash) {
|
|
x += addHtmlValue('MPS URL', '<input style=width:230px readonly value="' + message.mpsUrl + '" />');
|
|
x += addHtmlValue('MPS Cert Hash', '<input style=width:230px readonly value="' + message.mpsCertHash + '" />');
|
|
}
|
|
*/
|
|
setDialogMode(2, "MQTT pověření", 1, null, x);
|
|
break;
|
|
}
|
|
case 'stopped': { // Server is stopping.
|
|
// Disconnect
|
|
autoReconnect = false;
|
|
QH('p0span', message.msg);
|
|
break;
|
|
}
|
|
case 'updatePluginList': {
|
|
installedPluginList = message.list;
|
|
updatePluginList();
|
|
break;
|
|
}
|
|
case 'pluginVersionsAvailable': {
|
|
if (pluginHandler == null) break;
|
|
updatePluginList(message.list);
|
|
break;
|
|
}
|
|
case 'downgradePluginVersions': {
|
|
var vSelect = '<select id="lastPluginVersion">';
|
|
message.info.versionList.forEach(function(v) { vSelect += '<option value="' + v.zipball_url + '">' + v.name + '</option>'; });
|
|
vSelect += '</select>';
|
|
setDialogMode(2, "Akce pluginu", 3, pluginActionEx, format('Select the version to downgrade the plugin: {0}', message.info.name) + '<hr />' + vSelect + '<hr />' + "Mějte prosím na paměti, že downgrade se nedoporučuje. Učiňte tak pouze v případě, že nedávná aktualizace něco poškodila." + + '<input id="lastPluginAct" type="hidden" value="downgrade" /><input id="lastPluginId" type="hidden" value="' + message.info.id + '" />');
|
|
break;
|
|
}
|
|
case 'pluginError': {
|
|
setDialogMode(2, "Chyba pluginu", 1, null, message.msg);
|
|
break;
|
|
}
|
|
case 'plugin': {
|
|
if ((pluginHandler == null) || (typeof message.plugin != 'string')) break;
|
|
try { pluginHandler[message.plugin][message.method](server, message); } catch (e) { console.log('Error loading plugin handler ('+ e + ')'); }
|
|
break;
|
|
}
|
|
default:
|
|
//console.log('Unknown message.action', message.action);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// MY DEVICES
|
|
//
|
|
|
|
function onRealNameCheckBox() {
|
|
showRealNames = Q('RealNameCheckBox').checked;
|
|
putstore('showRealNames', showRealNames ? 1 : 0);
|
|
masterUpdate(6);
|
|
return;
|
|
}
|
|
|
|
function onDeviceViewChange(i) {
|
|
if (i != null) { Q('viewselect').value = i; }
|
|
for (var j = 1; j < 5; j++) { Q('devViewButton' + j).classList.remove('viewSelectorSel'); }
|
|
Q('devViewButton' + Q('viewselect').value).classList.add('viewSelectorSel');
|
|
putstore('_deviceView', Q('viewselect').value);
|
|
putstore('_viewsize', Q('sizeselect').value);
|
|
masterUpdate(4);
|
|
setTimeout(function () { masterUpdate(512); }, 200);
|
|
}
|
|
|
|
function ondockeypress(e) {
|
|
setSessionActivity();
|
|
if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
|
|
// Check what keys we are allows to send
|
|
if (currentNode != null) {
|
|
var mesh = meshes[currentNode.meshid];
|
|
var meshrights = mesh.links[userinfo._id].rights;
|
|
var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
|
|
if (inputAllowed == false) return false;
|
|
var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
|
|
if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
|
|
}
|
|
return desktop.m.handleKeys(e);
|
|
}
|
|
if (!xxdialogMode && xxcurrentView == 12 && terminal && terminal.State == 3) { return terminal.m.TermHandleKeys(e); }
|
|
if (!xxdialogMode && ((xxcurrentView == 15) || (xxcurrentView == 115))) return agentConsoleHandleKeys(e);
|
|
if (!xxdialogMode && xxcurrentView == 4) {
|
|
if (e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
|
|
var processed = 0;
|
|
if (e.key) {
|
|
if (e.key.length === 1 && userSearchFocus == 0) { Q('UserSearchInput').value = ((Q('UserSearchInput').value + e.key)); processed = 1; }
|
|
if (e.keyCode == 8 && userSearchFocus == 0) { var x = Q('UserSearchInput').value; Q('UserSearchInput').value = x.substring(0, x.length - 1); processed = 1; }
|
|
if (e.keyCode == 27) { Q('UserSearchInput').value = ''; processed = 1; }
|
|
} else {
|
|
if (e.charCode != 0 && userSearchFocus == 0) { Q('UserSearchInput').value = ((Q('UserSearchInput').value + String.fromCharCode(e.charCode))); processed = 1; }
|
|
}
|
|
if (processed > 0) { if (processed == 1) { onUserSearchInputChanged(); } return haltEvent(e); }
|
|
}
|
|
if (xxdialogMode || xxcurrentView != 1) return;
|
|
if (e.ctrlKey == true && e.charCode == 96) {
|
|
showRealNames = !showRealNames;
|
|
Q('RealNameCheckBox').value = showRealNames;
|
|
putstore('showRealNames', showRealNames ? 1 : 0);
|
|
masterUpdate(6)
|
|
return;
|
|
}
|
|
if (e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
|
|
if (Q('viewselect').value < 3) {
|
|
var processed = 0;
|
|
if (e.key) {
|
|
if (e.key.length === 1 && searchFocus == 0) { Q('SearchInput').value = ((Q('SearchInput').value + e.key)); processed = 1; }
|
|
if (e.keyCode == 8 && searchFocus == 0) { var x = Q('SearchInput').value; Q('SearchInput').value = x.substring(0, x.length - 1); processed = 1; }
|
|
if (e.keyCode == 27) { Q('SearchInput').value = ''; processed = 1; }
|
|
} else {
|
|
if (e.charCode != 0 && searchFocus == 0) { Q('SearchInput').value = ((Q('SearchInput').value + String.fromCharCode(e.charCode))); processed = 1; }
|
|
}
|
|
if (processed > 0) { if (processed == 1) { masterUpdate(5); } return haltEvent(e); }
|
|
}
|
|
if (Q('viewselect').value == 3) {
|
|
if (e.key) {
|
|
if (e.key.length === 1 && mapSearchFocus == 0) { Q('mapSearchLocation').value = ((Q('mapSearchLocation').value + e.key)); processed = 1; }
|
|
//if (e.keyCode == 8 && mapSearchFocus == 0) { var x = Q('mapSearchLocation').value; Q('mapSearchLocation').value = x.substring(0, x.length - 1); processed = 1; }
|
|
if (e.keyCode == 27) { Q('mapSearchLocation').value = ''; mapCloseSearchWindow(); processed = 1; }
|
|
if (e.keyCode == 13) { getSearchLocation(); }
|
|
} else {
|
|
if (e.charCode != 0 && mapSearchFocus == 0) { Q('mapSearchLocation').value = ((Q('mapSearchLocation').value + String.fromCharCode(e.charCode))); processed = 1; }
|
|
}
|
|
}
|
|
}
|
|
|
|
function ondockeydown(e) {
|
|
setSessionActivity();
|
|
if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
|
|
// Check what keys we are allows to send
|
|
if (currentNode != null) {
|
|
var mesh = meshes[currentNode.meshid];
|
|
var meshrights = mesh.links[userinfo._id].rights;
|
|
var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
|
|
if (inputAllowed == false) return false;
|
|
var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
|
|
if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
|
|
}
|
|
return desktop.m.handleKeyDown(e);
|
|
}
|
|
if (!xxdialogMode && xxcurrentView == 12 && terminal && terminal.State == 3) { terminal.m.TermHandleKeyDown(e); if ((e.keyCode >= 37) && (e.keyCode <= 40)) { haltEvent(e); } }
|
|
if (!xxdialogMode && xxcurrentView == 13 && e.keyCode == 116 && p13filetree != null) { haltEvent(e); return false; } // F5 Refresh on files
|
|
if (!xxdialogMode && ((xxcurrentView == 15) || (xxcurrentView == 115))) { return agentConsoleHandleKeys(e); }
|
|
if (!xxdialogMode && xxcurrentView == 4) {
|
|
if (e.keyCode === 8 && userSearchFocus == 0) { var x = Q('UserSearchInput').value; Q('UserSearchInput').value = (x.substring(0, x.length - 1)); processed = 1; }
|
|
if (e.keyCode === 27) { Q('UserSearchInput').value = ''; processed = 1; }
|
|
if (processed > 0) { if (processed == 1) { masterUpdate(5); } return haltEvent(e); }
|
|
}
|
|
if (xxdialogMode || xxcurrentView != 1 || e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
|
|
var processed = 0;
|
|
if (Q('viewselect').value < 3) {
|
|
if (e.keyCode === 8 && searchFocus == 0) { var x = Q('SearchInput').value; Q('SearchInput').value = (x.substring(0, x.length - 1)); processed = 1; }
|
|
if (e.keyCode === 27) { Q('SearchInput').value = ''; processed = 1; }
|
|
if (processed > 0) { if (processed == 1) { masterUpdate(5); } return haltEvent(e); }
|
|
}
|
|
if (Q('viewselect').value == 3) {
|
|
if (e.keyCode === 8 && mapSearchFocus == 0) { var x = Q('mapSearchLocation').value; Q('mapSearchLocation').value = (x.substring(0, x.length - 1)); processed = 1; }
|
|
if (e.keyCode === 27) { Q('mapSearchLocation').value = ''; mapCloseSearchWindow(); processed = 1; }
|
|
}
|
|
}
|
|
|
|
function ondockeyup(e) {
|
|
setSessionActivity();
|
|
if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
|
|
// Check what keys we are allows to send
|
|
if (currentNode != null) {
|
|
var mesh = meshes[currentNode.meshid];
|
|
var meshrights = mesh.links[userinfo._id].rights;
|
|
var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
|
|
if (inputAllowed == false) return false;
|
|
var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
|
|
if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
|
|
}
|
|
return desktop.m.handleKeyUp(e);
|
|
}
|
|
if (!xxdialogMode && xxcurrentView == 12 && terminal && terminal.State == 3) { return terminal.m.TermHandleKeyUp(e); }
|
|
if (!xxdialogMode && xxcurrentView == 13 && e.keyCode == 116 && p13filetree != null) { p13folderup(9999); haltEvent(e); return false; } // F5 Refresh on files
|
|
if (!xxdialogMode && xxcurrentView == 4) { if ((e.keyCode === 8 && searchFocus == 0) || e.keyCode === 27) { return haltEvent(e); } }
|
|
if (xxdialogMode && e.keyCode == 27) { dialogclose(0); }
|
|
if (xxdialogMode || xxcurrentView != 0 || e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
|
|
if (Q('viewselect').value < 3) { if ((e.keyCode === 8 && searchFocus == 0) || e.keyCode === 27) { return haltEvent(e); } }
|
|
if (Q('viewselect').value == 3) { if ((e.keyCode === 8 && mapSearchFocus == 0) || e.keyCode === 27) { return haltEvent(e); } }
|
|
}
|
|
|
|
//function ondocfocus() { }
|
|
// TODO: Add handleReleaseKeys() for Intel AMT.
|
|
function ondocblur() { if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked && desktop.m.handleReleaseKeys) { return desktop.m.handleReleaseKeys(); } }
|
|
|
|
// Highlights the device being hovered
|
|
function devMouseHover(element, over) {
|
|
setSessionActivity();
|
|
var view = Q('viewselect').value;
|
|
if (view == 1) {
|
|
var e = element.children[1].children[1];
|
|
e.children[0].classList.remove('g1s');
|
|
e.children[1].classList.remove('e2s');
|
|
e.children[2].classList.remove('g2s');
|
|
if (over == 1) {
|
|
e.children[0].classList.add('g1s');
|
|
e.children[1].classList.add('e2s');
|
|
e.children[2].classList.add('g2s');
|
|
}
|
|
} else if (view == 2) {
|
|
var e = element;
|
|
e.children[2].classList.remove('g1s');
|
|
e.children[4].classList.remove('e2s');
|
|
e.children[3].classList.remove('g2s');
|
|
if (over == 1) {
|
|
e.children[2].classList.add('g1s');
|
|
e.children[4].classList.add('e2s');
|
|
e.children[3].classList.add('g2s');
|
|
}
|
|
}
|
|
}
|
|
|
|
var deviceHeaderId = 0;
|
|
var deviceHeaderTotal = 0;
|
|
var deviceHeadersTitles = {};
|
|
var deviceHeaderCount;
|
|
var deviceHeaders = {};
|
|
var oldviewmode = 0;
|
|
function updateDevices() {
|
|
if (nodes == null) { return; }
|
|
var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, view = Q('viewselect').value, groups = {}, groupCount = {};
|
|
QV('xdevices', view < 4);
|
|
QV('xdevicesmap', view == 4);
|
|
QV('devListToolbar', view < 3);
|
|
QV('kvmListToolbar', view == 3);
|
|
QV('devMapToolbar', view == 4);
|
|
QV('devListToolbarSize', view == 3);
|
|
QV('NoMeshesPanel', meshcount == 0);
|
|
//QV('devListToolbarView', (meshcount != 0) && (nodes.length > 0));
|
|
QV('devListToolbarViewIcons', (meshcount != 0) && (nodes.length > 0));
|
|
QV('devListToolbarSort', (meshcount != 0) && (nodes.length > 0) && (view < 4));
|
|
if ((meshcount == 0) || (nodes.length == 0)) { view = 1; sort = 0; }
|
|
if (view == 4) {
|
|
setTimeout( function() { if (xxmap.map != null) { xxmap.map.updateSize(); } }, 200);
|
|
// TODO
|
|
} else {
|
|
// 3 wide, list view or desktop view
|
|
deviceHeaderId = 0;
|
|
deviceHeaderCount = {};
|
|
deviceHeaderTotal = 0;
|
|
deviceHeaders = {};
|
|
deviceHeadersTitles = {};
|
|
var kvmDivs = [];
|
|
|
|
// Perform node sort
|
|
if (sort == 0) { nodes.sort(meshSort); }
|
|
else if (sort == 1) { nodes.sort(powerSort); }
|
|
else if (sort == 2) { if (showRealNames == true) { nodes.sort(deviceHostSort); } else { nodes.sort(deviceSort); } }
|
|
|
|
// Save the list of currently checked nodeid's
|
|
var checkedNodeids = [], elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
|
|
for (var i=0;i<elements.length;i++) { if (elements[i].checked) { checkedNodeids.push(elements[i].value); } }
|
|
if ((oldviewmode < 3) && (view == 3)) { multiDesktopFilter = checkedNodeids; }
|
|
else if ((oldviewmode == 3) && (view < 3)) { checkedNodeids = multiDesktopFilter; }
|
|
|
|
// Compute the width of the device view.
|
|
var totalDeviceViewWidth = Q('column_l').clientWidth - 60;
|
|
var deviceBoxWidth = Math.floor(totalDeviceViewWidth / 301);
|
|
deviceBoxWidth = 301 + Math.floor((totalDeviceViewWidth - (deviceBoxWidth * 301)) / deviceBoxWidth);
|
|
|
|
if ((view == 2) && (sort != 3)) {
|
|
r += '<table style=width:100%;margin-top:4px cellpadding=0 cellspacing=0><th style=color:gray><th style=color:gray;width:120px>' + "Uživatel" + '<th style=color:gray;width:120px>' + "Adresa" + '<th style=color:gray;width:100px>' + "Konektivita"; //<th style=color:gray;width:100px>State';
|
|
}
|
|
|
|
// Go thru the list of nodes and display them
|
|
for (var i in nodes) {
|
|
var node = nodes[i];
|
|
if (node.v == false) continue;
|
|
var mesh2 = meshes[node.meshid], meshlinks = mesh2.links[userinfo._id];
|
|
if (meshlinks == null) continue;
|
|
var meshrights = meshlinks.rights;
|
|
if ((view == 3) && (mesh2.mtype == 1)) continue;
|
|
if (sort == 0) {
|
|
// Mesh header
|
|
if (node.meshid != current) {
|
|
deviceHeaderSet();
|
|
var extra = '';
|
|
if (view == 2) { r += '<tr><td colspan=5>'; }
|
|
if (meshes[node.meshid].mtype == 1) { extra = '<span class=devHeaderx>' + ", Intel® AMT pouze" + '</span>'; }
|
|
if ((view == 1) && (current != null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
|
|
if (view == 2) { r += '<div>'; }
|
|
r += '<div class=DevSt style=width:100%;padding-top:4px><span style=float:right>';
|
|
r += '<span id=DevxHeader' + deviceHeaderId + ' class=devHeaderx></span>' + extra;
|
|
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>';
|
|
if (view == 2) { r += '</div>'; }
|
|
current = node.meshid;
|
|
displayedMeshes[current] = 1;
|
|
c = 0;
|
|
}
|
|
} else if (sort == 1) {
|
|
// Power header
|
|
var pwr = node.pwr?node.pwr:0;
|
|
if (pwr !== current) {
|
|
deviceHeaderSet();
|
|
if ((view == 1) && (current !== null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
|
|
|
|
if (view == 2) { r += '<tr><td>'; }
|
|
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>';
|
|
|
|
current = pwr;
|
|
c = 0;
|
|
}
|
|
} else if (sort == 2) {
|
|
// Device header
|
|
if (current == null) { current = '1'; }
|
|
}
|
|
|
|
count++;
|
|
var title = EscapeHtml(node.name);
|
|
if (title.length == 0) { title = '<i>' + "Nic" + '</i>'; }
|
|
if ((node.rname != null) && (node.rname.length > 0)) { title += ' / ' + EscapeHtml(node.rname); }
|
|
var name = EscapeHtml(node.name);
|
|
if (showRealNames == true && node.rname != null) name = EscapeHtml(node.rname);
|
|
if (name.length == 0) { name = '<i>' + "Nic" + '</i>'; }
|
|
|
|
// Node
|
|
var icon = node.icon;
|
|
if ((!node.conn) || (node.conn == 0)) { icon += ' gray'; }
|
|
if (view == 1) {
|
|
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>';
|
|
} else if (view == 2) {
|
|
var states = [];
|
|
if (node.conn) {
|
|
if ((node.conn & 1) != 0) { states.push('<span title=\"' + "Agent je připojen a připraven." + '\">' + "Agent" + '</span>'); }
|
|
if ((node.conn & 2) != 0) { states.push('<span title=\"' + "Intel® AMT CIRA je připojeno a připraveno k použití." + '\">' + "CIRA" + '</span>'); }
|
|
else if ((node.conn & 4) != 0) { states.push('<span title=\"' + "Intel® AMT je směrovatelný." + '\">' + "AMT" + '</span>'); }
|
|
if ((node.conn & 8) != 0) { states.push('<span title=\"' + "Mesh agent je dostupný pomocí přesměrování přes jiného agenta." + '\">' + "Přesměrování" + '</span>'); }
|
|
if ((node.conn & 16) != 0) { states.push('<span title=\"' + "MQTT připojení na zařízení je aktivní." + '\">' + "MQTT" + '</span>'); }
|
|
}
|
|
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)">';
|
|
r += '<div class=deviceBarCheckbox><input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox></div>';
|
|
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>';
|
|
r += '<div class=g1 style=height:18px;float:left></div><div class=g2 style=height:18px;float:right></div>';
|
|
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>';
|
|
r += '<td style=text-align:center>' + getUserShortStr(node);
|
|
r += '<td style=text-align:center>' + (node.ip != null ? node.ip : '');
|
|
r += '<td style=text-align:center>' + states.join(' + ');
|
|
//r += '<td style=text-align:center>' + (node.pwr != null ? powerStateStrings[node.pwr] : '');
|
|
r += '</tr>';
|
|
} 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.
|
|
if ((multiDesktopFilter) && ((multiDesktopFilter.length == 0) || (multiDesktopFilter.indexOf('devid_' + node._id) >= 0))) {
|
|
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)">';
|
|
//r += '<input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox style=float:left>';
|
|
r += '<div class="j' + icon + '" style=width:16px;float:left></div> ' + name + '</div>';
|
|
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 + '\')">' + "Odpojeno" + '</div></div>';
|
|
r += '</div>';
|
|
kvmDivs.push(node._id);
|
|
}
|
|
}
|
|
|
|
// If we are displaying devices by group, put the device in the right group.
|
|
if ((sort == 3) && (r != '')) {
|
|
if (node.tags) {
|
|
for (var j in node.tags) {
|
|
var tag = node.tags[j];
|
|
if (groups[tag] == null) { groups[tag] = r; groupCount[tag] = 1; } else { groups[tag] += r; groupCount[tag] += 1; }
|
|
if (view == 3) break;
|
|
}
|
|
}
|
|
r = '';
|
|
}
|
|
|
|
deviceHeaderTotal++;
|
|
if (typeof deviceHeaderCount[node.state] == 'undefined') { deviceHeaderCount[node.state] = 1; } else { deviceHeaderCount[node.state]++; }
|
|
}
|
|
|
|
// Above 32 devices, gray out the auto connect feature.
|
|
if (kvmDivs.length >= 32) { Q('autoConnectDesktopCheckbox').checked = false; }
|
|
QE('autoConnectDesktopCheckbox', kvmDivs.length < 32);
|
|
|
|
// If displaying devices by groups, sort the group names and display the devices.
|
|
if (sort == 3) {
|
|
if (view == 2) { r = '<table style=width:100%;margin-top:4px cellpadding=0 cellspacing=0><th style=color:gray><th style=color:gray;width:120px>' + "Uživatel" + '<th style=color:gray;width:120px>' + "Adresa" + '<th style=color:gray;width:100px>' + "Konektivita"; }
|
|
|
|
var groupNames = [];
|
|
for (var i in groups) { groupNames.push(i); }
|
|
groupNames.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); });
|
|
for (var j in groupNames) {
|
|
var i = groupNames[j];
|
|
if (view == 2) {
|
|
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];
|
|
} else {
|
|
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];
|
|
}
|
|
}
|
|
}
|
|
|
|
// If there is nothing to display, explain the problem
|
|
if ((r == '') && (meshcount > 0) && (Q('SearchInput').value != '')) {
|
|
if (sort == 3) {
|
|
r = '<div style="margin:30px">' + "Žádné zařízení není v žádné skupině, klikněte na Vytvořit nebo Přidat skupinu zařízení." + '</div>';
|
|
} else {
|
|
r = '<div style="margin:30px">' + "Žádné zařízení nevyhovuje tomuto vyhledávání." + '</div>';
|
|
}
|
|
}
|
|
|
|
if ((view == 1) && (c == 2)) r += '<td><div style=width:301px></div></td>'; // Adds device padding
|
|
|
|
// Display all empty device groups, we need to do this because users can add devices to these at any time.
|
|
if ((sort == 0) && (Q('SearchInput').value == '') && (view < 3)) {
|
|
for (var i in meshes) {
|
|
var mesh = meshes[i], meshlink = mesh.links[userinfo._id];
|
|
if (meshlink != null) {
|
|
var meshrights = meshlink.rights;
|
|
if (displayedMeshes[mesh._id] == null) {
|
|
if ((current != '') && (r != '')) { r += '</tr></table>'; }
|
|
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>';
|
|
r += getMeshActions(mesh, meshrights);
|
|
r += '</span></td></tr><tr>';
|
|
if (mesh.mtype == 1) {
|
|
r += '<td><div style=padding:10px><i>' + "Žádné Intel® AMT zařízení";
|
|
if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addDeviceToMesh(\"' + mesh._id + '\")\'>' + "přidat" + '</a>'; }
|
|
}
|
|
if (mesh.mtype == 2) {
|
|
r += '<td><div style=padding:10px><i>' + "Žádné zařízení v této skupině";
|
|
if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addAgentToMesh(\"' + mesh._id + '\")\'>' + "přidat" + '</a>'; }
|
|
}
|
|
r += '.</i></div></td>';
|
|
current = mesh._id;
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
r += '</tr></table><div style=height:1px></div>'; // This height of 1 div fixes a problem in Linux firefox browsers
|
|
|
|
// Add a "Add Device Group" option
|
|
r += '<div style=border-top-style:solid;border-top-width:1px;border-top-color:#DDDDDD;cursor:pointer;font-size:10px>';
|
|
if ((view < 3) && (sort == 0) && (meshcount > 0) && ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 64) == 0))) {
|
|
r += '<a href=# onclick="return account_createMesh()" title=\"' + "Vytvořit novou skupinu zařízení." + '\" style=cursor:pointer>' + "Přidat skupinu zařízení" + '</a> ';
|
|
}
|
|
if ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 128) == 0)) {
|
|
r += '<a href=# onclick=\'return p10showMeshCmdDialog(0)\' style=cursor:pointer title=\"' + "Stáhnout MeshCmd, což je nástroj pro příkazovou řásku s mnoha funkcemi." + '\">' + "MeshCmd" + '</a> ';
|
|
if (navigator.platform.toLowerCase() == 'win32') { r += '<a href=# onclick=\'return p10showMeshRouterDialog()\' style=cursor:pointer title=\"' + "Stáhnout MeshCentral, což je TCP nástroj pro mapování portů." + '\">' + "Router" + '</a> '; }
|
|
}
|
|
r += '</div><br/>';
|
|
|
|
QH('xdevices', r);
|
|
deviceHeaderSet();
|
|
|
|
// Re-check nodeid's
|
|
var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
|
|
if (checkedNodeids) { for (var i=0;i<elements.length;i++) { elements[i].checked = (checkedNodeids.indexOf(elements[i].value) >= 0); } }
|
|
|
|
for (var i in deviceHeaders) { QH(i, deviceHeaders[i]); }
|
|
for (var i in deviceHeadersTitles) { Q(i).title = deviceHeadersTitles[i]; }
|
|
p1updateInfo();
|
|
|
|
// Take care of KVM surfaces in desktop view mode
|
|
if (view == 3) {
|
|
// Figure out and adjust the size to fill the width of the div
|
|
var vsize = [{ x: 180, y: 101 }, { x: 302, y: 169 }, { x: 454, y: 255 }][Q('sizeselect').selectedIndex];
|
|
//var realw = vsize.x + 2, tw = Q('xdevices').clientWidth - 30, xw = Math.floor(tw / realw);
|
|
var realw = vsize.x + 2, tw = totalDeviceViewWidth - 5, xw = Math.floor(tw / realw);
|
|
xw = realw + Math.floor((tw - (xw * realw)) / xw);
|
|
vsize.y = vsize.y * (xw / vsize.x);
|
|
vsize.x = xw;
|
|
|
|
for (var i in multiDesktop) { multiDesktop[i].xxdelete = true; }
|
|
for (var i in kvmDivs) {
|
|
var id = kvmDivs[i], shortid = id.split('/')[2], desk = multiDesktop[id];
|
|
if (desk != null) {
|
|
// This device already has a canvas, use it.
|
|
desk.m.CanvasId.setAttribute('style', 'background-color:black;width:' + vsize.x + 'px;height:' + vsize.y + 'px');
|
|
Q('xkvmid_' + shortid).appendChild(desk.m.CanvasId);
|
|
delete desk.xxdelete;
|
|
QH('skvmid_' + shortid, ["Odpojeno", "Připojování...", "Nastavení...", '', ''][((desk.m.State == null)?desk.m.state:desk.m.State)]);
|
|
} else {
|
|
var node = getNodeFromId(id);
|
|
if ((desktopNode == node) && (desktop != null)) { // Check if the main desktop is this device, if it is, use that.
|
|
// This device already has a canvas, use it.
|
|
var c = desktop.m.CanvasId;
|
|
c.setAttribute('id', 'kvmid_' + shortid);
|
|
c.setAttribute('style', 'background-color:black;width:' + vsize.x + 'px;height:' + vsize.y + 'px');
|
|
c.setAttribute('onclick', 'toggleKvmDevice(\'' + id + '\')');
|
|
c.removeAttribute('onmousedown');
|
|
c.removeAttribute('onmouseup');
|
|
c.removeAttribute('onmousemove');
|
|
Q('xkvmid_' + shortid).appendChild(c);
|
|
QH('skvmid_' + shortid, ["Odpojeno", "Připojování...", "Nastavení...", '', ''][((desktop.m.State == null)?desktop.m.state:desktop.m.State)]);
|
|
if (desktop.m.SendCompressionLevel) { desktop.m.SendCompressionLevel(1, multidesktopsettings.quality, multidesktopsettings.scaling, multidesktopsettings.framerate); }
|
|
desktop.shortid = shortid;
|
|
desktop.onStateChanged = onMultiDesktopStateChange;
|
|
multiDesktop[id] = desktop;
|
|
desktop = desktopNode = currentNode = null;
|
|
// Setup a replacement desktop
|
|
QH('DeskParent', '<canvas id="Desk" oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></canvas>');
|
|
} else {
|
|
// This is a new device, create a canvas for it.
|
|
var c = document.createElement('canvas');
|
|
c.setAttribute('id', 'kvmid_' + shortid);
|
|
c.setAttribute('width', 640);
|
|
c.setAttribute('height', 480);
|
|
c.setAttribute('oncontextmenu', 'return false');
|
|
c.setAttribute('style', 'background-color:black;width:' + vsize.x + 'px;height:' + vsize.y + 'px');
|
|
c.setAttribute('onclick', 'toggleKvmDevice(\'' + id + '\')');
|
|
try { Q('xkvmid_' + shortid).appendChild(c); } catch (ex) {}
|
|
// Check if we need to auto-connect
|
|
if (Q('autoConnectDesktopCheckbox').checked == true) { setTimeout(function() { connectMultiDesktop(node, 1); }, 100); }
|
|
}
|
|
}
|
|
}
|
|
for (var i in multiDesktop) {
|
|
// If a device is no longer viewed, disconnect it.
|
|
if (multiDesktop[i].xxdelete == true) { multiDesktop[i].Stop(); delete multiDesktop[i]; }
|
|
else if (debugmode && multiDesktop[i].m && multiDesktop[i].m.onScreenSizeChange) {
|
|
mdeskAdjust(multiDesktop[i].m, multiDesktop[i].m.ScreenWidth, multiDesktop[i].m.ScreenHeight, multiDesktop[i].m.CanvasId); // Adjust screen size change
|
|
}
|
|
}
|
|
deskAdjust();
|
|
} else {
|
|
disconnectAllKvmFunction();
|
|
Q('autoConnectDesktopCheckbox').checked = false;
|
|
}
|
|
}
|
|
oldviewmode = view;
|
|
}
|
|
|
|
function toggleKvmDevice(node) {
|
|
if (typeof node == 'string') { node = getNodeFromId(node); } // Convert nodeid to node if needed
|
|
var mesh = meshes[node.meshid], meshrights = mesh.links[userinfo._id].rights;
|
|
if ((meshrights & 8) || (meshrights & 256)) { // Requires remote control rights or desktop view only rights
|
|
//var conn = 0;
|
|
//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)
|
|
if (node.conn & 1) { connectMultiDesktop(node, 1); }
|
|
}
|
|
}
|
|
|
|
function getUserShortStr(node) {
|
|
if (node == null || node.users == null || node.users.length == 0) return '';
|
|
if (node.users.length > 1) { return '<span title="' + EscapeHtml(node.users.join(', ')) + '">' + nobreak(format("{0} uživatelů", node.users.length)) + '</span>'; }
|
|
var u = node.users[0], su = u, i = u.indexOf('\\');
|
|
if (i > 0) { su = u.substring(i + 1); }
|
|
su = EscapeHtml(su);
|
|
if (su.length > 15) { su = su.substring(0, 14) + '…'; }
|
|
return '<span title="' + EscapeHtml(u) + '">' + su + '</span>';
|
|
}
|
|
|
|
function autoConnectDesktops() { if (Q('autoConnectDesktopCheckbox').checked == true) { connectAllKvmFunction(); } }
|
|
function connectAllKvmFunction(force) {
|
|
if (xxdialogMode) return false;
|
|
if (force !== true) { // We need to count how many devices will need to be connected, if it's a lot, prompt first.
|
|
var count = 0;
|
|
for (var i in nodes) {
|
|
var node = nodes[i], nodeid = nodes[i]._id;
|
|
if (multiDesktop[nodeid] == null) {
|
|
var mesh = meshes[node.meshid], meshrights = mesh.links[userinfo._id].rights;
|
|
if ((meshrights & 8) || (meshrights & 256)) { // Requires remote control rights or desktop view only rights
|
|
//var conn = 0;
|
|
//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)
|
|
if (node.conn & 1) { count++; }
|
|
}
|
|
}
|
|
}
|
|
if (count > 8) { setDialogMode(2, "Připojit vše", 3, function() { connectAllKvmFunction(true); }, format("Opravdu připojit k {0} zařízení?", count)); return; }
|
|
}
|
|
|
|
// Perform connect all
|
|
for (var i in nodes) { if (multiDesktop[nodes[i]._id] == null) { toggleKvmDevice(nodes[i]._id); } }
|
|
}
|
|
function disconnectAllKvmFunction() { if (xxdialogMode) return false; for (var nodeid in multiDesktop) { multiDesktop[nodeid].Stop(); } multiDesktop = {}; }
|
|
function onMultiDesktopStateChange(desk, state) { try { QH('skvmid_' + desk.shortid, ["Odpojeno", "Připojování...", "Nastavení...", '', ''][state]); } catch (ex) {} }
|
|
|
|
function showMultiDesktopSettings() {
|
|
QV('d7amtkvm', false);
|
|
QV('d7meshkvm', true);
|
|
d7bitmapquality.value = multidesktopsettings.quality;
|
|
d7bitmapscaling.value = multidesktopsettings.scaling;
|
|
if (multidesktopsettings.framerate) { d7framelimiter.value = multidesktopsettings.framerate; } else { d7framelimiter.value = 1000; }
|
|
setDialogMode(7, "Nastavení vzdálené plochy", 3, showMultiDesktopSettingsChanged);
|
|
}
|
|
|
|
function showMultiDesktopSettingsChanged() {
|
|
multidesktopsettings.quality = d7bitmapquality.value;
|
|
multidesktopsettings.scaling = d7bitmapscaling.value;
|
|
multidesktopsettings.framerate = d7framelimiter.value;
|
|
localStorage.setItem('multidesktopsettings', JSON.stringify(multidesktopsettings));
|
|
// Make changes to all current connections
|
|
for (var i in multiDesktop) { multiDesktop[i].m.SendCompressionLevel(1, multidesktopsettings.quality, multidesktopsettings.scaling, multidesktopsettings.framerate); }
|
|
}
|
|
|
|
function connectMultiDesktop(node, contype) {
|
|
var nodeid = node._id, shortid = nodeid.split('/')[2];
|
|
var desk = multiDesktop[nodeid];
|
|
if (desk == null) {
|
|
if (Q('kvmid_' + shortid) == null) return; // Check if this device is being displayed, if not, exit now.
|
|
if (contype == 2) {
|
|
// Setup the Intel AMT remote desktop
|
|
if ((node.intelamt.user == null) || (node.intelamt.user == '')) { return; }
|
|
desk = CreateAmtRedirect(CreateAmtRemoteDesktop('kvmid_' + shortid), authCookie);
|
|
desk.shortid = shortid;
|
|
//desk.debugmode = debugmode;
|
|
desk.onStateChanged = onMultiDesktopStateChange;
|
|
desk.m.bpp = 1;
|
|
desk.m.useZRLE = true;
|
|
desk.m.showmouse = true;
|
|
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.
|
|
//desk.m.onScreenSizeChange = deskAdjust;
|
|
if (debugmode > 0) { desk.m.onScreenSizeChange = mdeskAdjust; } // Multi-Desktop Adjust
|
|
desk.Start(nodeid, 16994, '*', '*', 0);
|
|
desk.contype = 2;
|
|
multiDesktop[nodeid] = desk;
|
|
} else if (contype == 1) {
|
|
// Setup the Mesh Agent remote desktop
|
|
desk = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('kvmid_' + shortid), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
|
|
desk.shortid = shortid;
|
|
desk.attemptWebRTC = attemptWebRTC;
|
|
desk.onStateChanged = onMultiDesktopStateChange;
|
|
//desk.onConsoleMessageChange = function () { console.log('CONSOLEMSG:', desk.consoleMessage); }
|
|
desk.m.CompressionLevel = multidesktopsettings.quality;
|
|
desk.m.ScalingLevel = multidesktopsettings.scaling;
|
|
desk.m.FrameRateTimer = multidesktopsettings.framerate;
|
|
//desk.m.onDisplayinfo = deskDisplayInfo;
|
|
//desk.m.onScreenSizeChange = deskAdjust;
|
|
if (debugmode > 0) { desk.m.onScreenSizeChange = mdeskAdjust; } // Multi-Desktop Adjust
|
|
desk.Start(nodeid);
|
|
desk.contype = 1;
|
|
multiDesktop[nodeid] = desk;
|
|
}
|
|
} else {
|
|
// Disconnect and clean up the remote desktop
|
|
desk.Stop();
|
|
delete multiDesktop[nodeid];
|
|
}
|
|
}
|
|
|
|
function getMeshActions(mesh, meshrights) {
|
|
if ((meshrights & 4) == 0) return '';
|
|
var r = '';
|
|
if ((features & 1024) == 0) { // If CIRA is allowed
|
|
r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Přidat nový Intel® AMT počítač, který je umístěn v síti Internet." + '\" onclick=\'return addCiraDeviceToMesh(\"' + mesh._id + '\")\'>' + "Přidat CIRA" + '</a>';
|
|
}
|
|
if (mesh.mtype == 1) {
|
|
if ((features & 1) == 0) { // If not WAN-Only
|
|
r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Přidat nový Intel® AMT počítač, který je umístěn v lokální síti." + '\" onclick=\'return addDeviceToMesh(\"' + mesh._id + '\")\'>' + "Přidat lokálně" + '</a>';
|
|
r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Přidat nový Intel® AMT počítač pomocí skenu lokální sítě." + '\" onclick=\'return addAmtScanToMesh(\"' + mesh._id + '\")\'>' + "Skenovat síť" + '</a>';
|
|
}
|
|
if (mesh.amt && (mesh.amt.type == 2)) { // CCM activation
|
|
r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Provedení Intel AMT client control mode (CCM) aktivace." + '\" onclick=\'return showCcmActivation(\"' + mesh._id + '\")\'>' + "Aktivace" + '</a>';
|
|
} else if (mesh.amt && (mesh.amt.type == 3) && ((features & 0x00100000) != 0)) { // ACM activation
|
|
r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Provedení Intel AMT admin control mode (ACM) aktivace." + '\" onclick=\'return showAcmActivation(\"' + mesh._id + '\")\'>' + "Aktivace" + '</a>';
|
|
}
|
|
}
|
|
if (mesh.mtype == 2) {
|
|
r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Přidat nový počítač pomocí agenta." + '\" onclick=\'return addAgentToMesh(\"' + mesh._id + '\")\'>' + "Přidat agenta" + '</a>';
|
|
if ((features & 2) == 0) { r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Pozvat kohokoliv k instalaci agenta pro vzdálené ovládání." + '\" onclick=\'return inviteAgentToMesh(\"' + mesh._id + '\")\'>' + "Pozvat" + '</a>'; }
|
|
}
|
|
return r;
|
|
}
|
|
|
|
function addDeviceToMesh(meshid) {
|
|
if (xxdialogMode) return false;
|
|
var mesh = meshes[meshid];
|
|
var x = format("Přidat nové Intel® AMT zařízení do skupiny \"{0}\".", EscapeHtml(mesh.name)) + '<br /><br />';
|
|
x += addHtmlValue("Název zařízení", '<input id=dp1devicename style=width:230px maxlength=32 autocomplete=off onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
|
|
x += addHtmlValue("Hostname", '<input id=dp1hostname style=width:230px maxlength=32 autocomplete=off placeholder=\"' + "Stejné jako jméno zařízení" + '\" onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
|
|
x += addHtmlValue("Uživatel", '<input id=dp1username style=width:230px maxlength=32 autocomplete=off placeholder=\"' + "admin" + '\" onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
|
|
x += addHtmlValue("Heslo", '<input id=dp1password type=password style=width:230px autocomplete=off maxlength=32 onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
|
|
x += addHtmlValue("Bezpečnost", '<select id=dp1tls style=width:236px><option value=0>' + "Žádné TLS" + '</option><option value=1>' + "TLS vyžadováno" + '</option></select>');
|
|
setDialogMode(2, "Přidat Intel® AMT zařízení", 3, addDeviceToMeshEx, x, meshid);
|
|
validateDeviceToMesh();
|
|
Q('dp1devicename').focus();
|
|
return false;
|
|
}
|
|
|
|
// Intel AMT CCM Activation
|
|
function showCcmActivation(meshid) {
|
|
if (xxdialogMode) return false;
|
|
var servername = serverinfo.name, mesh = meshes[meshid];
|
|
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.
|
|
var url, domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
|
|
if (serverinfo.https == true) {
|
|
var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
|
|
url = 'wss://' + servername + portStr + domainUrl;
|
|
} else {
|
|
var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
|
|
url = 'ws://' + servername + portStr + domainUrl;
|
|
}
|
|
var x = format("Proveďte aktivaci Intel AMT client control mode (CCM) pro skupinu \"{0}\" stažením MeshCMD nástroje a spuštěním takto:", EscapeHtml(mesh.name)) + '<br /><br />';
|
|
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>';
|
|
setDialogMode(2, "Intel® AMT aktivace", 9, null, x);
|
|
Q('idx_dlgOkButton').focus();
|
|
return false;
|
|
}
|
|
|
|
// Intel AMT ACM Activation
|
|
function showAcmActivation(meshid) {
|
|
if (xxdialogMode) return false;
|
|
var servername = serverinfo.name, mesh = meshes[meshid];
|
|
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.
|
|
var url, domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
|
|
if (serverinfo.https == true) {
|
|
var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
|
|
url = 'wss://' + servername + portStr + domainUrl;
|
|
} else {
|
|
var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
|
|
url = 'ws://' + servername + portStr + domainUrl;
|
|
}
|
|
var x = format("Proveďte aktivaci Intel AMT admin control mode (ACM) pro skupinu \"{0}\" stažením MeshCMD nástroje a spuštěním takto:", EscapeHtml(mesh.name)) + '<br /><br />';
|
|
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>';
|
|
if (serverinfo.amtAcmFqdn != null) {
|
|
x += ('<div style=margin-top:8px>' + "Intel AMT bude muset být nastaven s důvěryhodným FQDN v MEBx nebo bude třeba drátová LAN:" + ' <b>' + serverinfo.amtAcmFqdn.join(', ') + '</b></div>');
|
|
}
|
|
setDialogMode(2, "Intel® AMT aktivace", 9, null, x);
|
|
Q('idx_dlgOkButton').focus();
|
|
return false;
|
|
}
|
|
|
|
// Display the Intel AMT scanning dialog box
|
|
function addAmtScanToMesh(meshid) {
|
|
if (xxdialogMode) return false;
|
|
var x = "Zadejte rozsah IP adres pro vyhledání Intel AMT zařízení." + '<br /><br />';
|
|
x += addHtmlValue("IP rozsah", '<input id=dp1range style=width:184px value="192.168.1.0/24" onkeyup=addAmtScanToMeshKeyUp(event) /><input id=dp1rangebutton type=button value=\"' + "Skenovat" + '\" onclick=addAmtScanToMeshButton()></input>');
|
|
x += '<div id=dp1results style="width:100%;height:200px;background-color:white;border:1px gray solid;overflow-y:scroll"></div>';
|
|
setDialogMode(2, "Hledat Intel® AMT zařízení", 3, addAmtScanToMeshEx, x, meshid);
|
|
QE('idx_dlgOkButton', false);
|
|
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>');
|
|
focusTextBox('dp1range');
|
|
return false;
|
|
}
|
|
|
|
function addAmtScanToMeshKeyUp(e) {
|
|
if (e.keyCode == 13) { haltEvent(e); addAmtScanToMeshButton(); }
|
|
}
|
|
|
|
// Called when OK is pressed on the Intel AMT scanning box
|
|
function addAmtScanToMeshEx(button, meshid) {
|
|
var elements = document.getElementsByClassName('DevScanCheckbox'), checkcount = 0;
|
|
for (var i=0;i<elements.length;i++) {
|
|
if (elements[i].checked) {
|
|
var ipaddr = elements[i].getAttribute('tag');
|
|
var amtinfo = amtScanResults[ipaddr];
|
|
meshserver.send({ action: 'addamtdevice', meshid: meshid, devicename: ipaddr, hostname: amtinfo.hostname, amtusername: '', amtpassword: '', amttls: amtinfo.tls });
|
|
}
|
|
}
|
|
}
|
|
|
|
// If the user presses the "Scan" button on the Intel AMT scanning dialog box, start a scan.
|
|
function addAmtScanToMeshButton() {
|
|
QE('dp1range', false);
|
|
QE('dp1rangebutton', false);
|
|
QH('dp1results', '<div style=width:100%;text-align:center;margin-top:12px>' + "Skenuji..." + '</div>');
|
|
meshserver.send({ action: 'scanamtdevice', range: Q('dp1range').value });
|
|
}
|
|
|
|
// Called when a scanned computer is checked or unchecked.
|
|
function addAmtScanToMeshCheckbox() {
|
|
var elements = document.getElementsByClassName('DevScanCheckbox'), checkcount = 0;
|
|
for (var i=0;i<elements.length;i++) { if (elements[i].checked) checkcount++; }
|
|
QE('idx_dlgOkButton', checkcount > 0);
|
|
}
|
|
|
|
function addCiraDeviceToMesh(meshid) {
|
|
if (xxdialogMode) return false;
|
|
var mesh = meshes[meshid];
|
|
|
|
// Replace non alphabetic characters (@ and $) with 'X' because MPS username cannot accept it.
|
|
var meshidx = meshid.split('/')[2].replace(/\@/g, 'X').replace(/\$/g, 'X');
|
|
|
|
var y = '<select id=dlgAddCiraSel onclick=dlgAddCiraSelClick() style=width:230px><option value=0>' + "MeshCommander skript" + '</option><option value=1>' + "Vlastní přihlašovací jméno/heslo" + '</option>';
|
|
if ((features & 16) == 0) { y += ('<option value=2>' + "Vlastní certifikát" + '</option></select>'); } // Only display this option if Intel AMT CIRA with Mutual-Auth is allowed.
|
|
|
|
var x = '';
|
|
x += addHtmlValue("Nastavení", y);
|
|
x += '<hr>';
|
|
|
|
// Setup CIRA using a MeshCommander script (Pretty Simple)
|
|
x += '<div id=dlgAddCira0>' + format("Pro přidání nového Intel® AMT zařízení do skupiny \"{0}\" s CIRA, si musíte stáhnout následující skript <a href='http://meshcommander.com' rel='noreferrer noopener' target='_blank'>MeshCommander</a> a spustit pro konfiguraci počítačů.", EscapeHtml(mesh.name)) + '<br /><br />';
|
|
//x += addHtmlValue('Setup CIRA', '<a href="mescript.ashx?type=1&meshid=' + meshidx.substring(0, 16) + '" download>cira_setup.mescript</a>');
|
|
x += addHtmlValue("Nastavení CIRA", '<a href="mescript.ashx?type=1&meshid=' + meshid + '" download>cira_setup.mescript</a>');
|
|
x += addHtmlValue("Vymazat CIRA", '<a href="mescript.ashx?type=2" download>cira_clean.mescript</a>');
|
|
x += '</div>';
|
|
|
|
// Setup CIRA with user/pass authentication (Somewhat difficult)
|
|
x += '<div id=dlgAddCira1 style=display:none>' + format("Pro přidání nového Intel® AMT zařízení do skupiny \"{0}\" s CIRA, nahrajte následující certifikát mezi důvěryhodné kořenové v rámci Intel AMT", EscapeHtml(mesh.name));
|
|
if (serverinfo.mpspass) { x += (" a autentizovat se na serveru pomocí tohoto uživatelského jména a hesla." + '<br /><br />'); } else { x += (" a autentizovat se na serveru pomocí tohoto uživatelského jména a hesla." + '<br /><br />'); }
|
|
x += addHtmlValue("Root certifikát", '<a href=\"' + "MeshServerRootCert.cer" + '\" download>' + "Root certifikát soubor" + '</a>');
|
|
x += addHtmlValue("Uživatel", '<input style=width:230px readonly value="' + meshidx.substring(0, 16) + '" />');
|
|
if (serverinfo.mpspass) { x += addHtmlValue("Heslo", '<input style=width:230px readonly value="' + EscapeHtml(serverinfo.mpspass) + '" />'); }
|
|
if (serverinfo != null) { x += addHtmlValue("MPS Server", '<input style=width:230px readonly value="' + EscapeHtml(serverinfo.mpsname) + ':' + serverinfo.mpsport + '" />'); }
|
|
x += '</div>';
|
|
|
|
// Setup CIRA with certificate authentication (Really difficult, only if TLS offload is not used)
|
|
if ((features & 16) == 0) {
|
|
x += '<div id=dlgAddCira2 style=display:none>' + format("Pro přidání nového Intel® AMT zařízení do skupiny \"{0}\" s CIRA, nahrajte následující certifikát mezi důvěryhodné kořenové v rámci Intel AMT, tímto klientským certifikátem se pak bude autentizovat s následujícím běžným názvem a připojí se k následujícímu serveru.", EscapeHtml(mesh.name)) + '<br /><br />';
|
|
x += addHtmlValue("Root certifikát", '<a href="MeshServerRootCert.cer" download>' + "Root certifikát soubor" + '</a>');
|
|
x += addHtmlValue("Organizace", '<input style=width:230px readonly value="' + meshidx + '" />');
|
|
if (serverinfo != null) { x += addHtmlValue("MPS Server", '<input style=width:230px readonly value="' + EscapeHtml(serverinfo.mpsname) + ':' + serverinfo.mpsport + '" />'); }
|
|
x += '</div>';
|
|
}
|
|
|
|
setDialogMode(2, "Přidat Intel® AMT CIRA zařízení", 2, null, x, 'fileDownload');
|
|
Q('dlgAddCiraSel').focus();
|
|
return false;
|
|
}
|
|
|
|
function dlgAddCiraSelClick() {
|
|
var val = Q('dlgAddCiraSel').value;
|
|
QV('dlgAddCira0', val == 0);
|
|
QV('dlgAddCira1', val == 1);
|
|
QV('dlgAddCira2', val == 2);
|
|
}
|
|
|
|
// Return true is the input string looks like an email address
|
|
function checkEmail(str) {
|
|
var x = str.split('@');
|
|
var ok = ((x.length == 2) && (x[0].length > 0) && (x[1].split('.').length > 1) && (x[1].length > 2));
|
|
if (ok == true) { var y = x[1].split('.'); for (var i in y) { if (y[i].length == 0) { ok = false; } } }
|
|
return ok;
|
|
}
|
|
|
|
function inviteAgentToMesh(meshid) {
|
|
if (xxdialogMode) return false;
|
|
var x = '', mesh = meshes[meshid];
|
|
if (features & 64) {
|
|
x += addHtmlValue("Typ pozvání", '<select id=d2InviteType onchange=d2ChangedInviteType() style=width:236px><option value=0>Link invitation</option><option value=1>Email invitation</option></select>') + '<hr />';
|
|
x += '<div id=emailInviteDiv style=display:none>' + format("Pozvěte někoho k instalaci agenta. Emailem bude zaslán link s adresou agenta pro skupinu \"{0}\".", EscapeHtml(mesh.name)) + '<br /><br />';
|
|
x += addHtmlValue("Jméno (volitelné)", '<input id=agentInviteName value="" style=width:230px maxlength=64 />');
|
|
x += addHtmlValue("Email", '<input id=agentInviteEmail style=width:230px placeholder=\"' + "example@email.com" + '\" onkeyup=validateAgentInvite()></input>');
|
|
x += addHtmlValue("Operační systém", '<select id=agentInviteNameOs onchange=d2ChangedInviteType() style=width:236px><option value=4>' + "Odeslat odkaz na instalaci" + '</option><option value=0 selected>' + "Všechny podporovány" + '</option><option value=1>' + "Windows pouze" + '</option><option value=3>' + "Apple MacOS pouze" + '</option><option value=2>' + "Linux pouze" + '</option></select>');
|
|
x += '<div id=d2agentexpirediv>';
|
|
x += addHtmlValue("Platnost odkazu", '<select id=agentInviteExpire style=width:236px><option value=1>' + "1 hodina" + '</option><option value=8>' + "8 hodin" + '</option><option value=24>' + "1 den" + '</option><option value=168>' + "1 týden" + '</option><option value=5040>' + "1 měsíc" + '</option><option value=0>' + "Bez limitu" + '</option></select>');
|
|
x += '</div>';
|
|
x += addHtmlValue("Typ instalace", '<select id=agentInviteType style=width:236px><option value=0>' + "Na pozadí a interaktivní" + '</option><option value=2>' + "Pouze na pozadí" + '</option><option value=1>' + "Pouze interaktivní" + '</option></select>');
|
|
x += addHtmlValue("Zpráva" + '<br />' + "(volitelné)", '<textarea id=agentInviteMessage value="" style=width:230px;height:100px;resize:none maxlength=1024 /></textarea>');
|
|
x += '</div>';
|
|
}
|
|
x += '<div id=urlInviteDiv>' + format("Pozvěte někoho k instalaci agenta pomocí sdíleného odkazu. Tento link obsahuje instrukce pro instalaci do skupiny \"{0}\". Link je veřejný a protistrana nepotřebuje žádný účet na tomto serveru.", EscapeHtml(mesh.name)) + '<br /><br />';
|
|
x += addHtmlValue("Platnost odkazu", '<select id=d2inviteExpire style=width:236px onchange=d2RequestInvitationLink()><option value=1>' + "1 hodina" + '</option><option value=8>' + "8 hodin" + '</option><option value=24>' + "1 den" + '</option><option value=168>' + "1 týden" + '</option><option value=5040>' + "1 měsíc" + '</option><option value=0>' + "Bez limitu" + '</option></select>');
|
|
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=\"' + "Kopírovat odkaz do schránky" + '\" style=cursor:pointer onclick=d2CopyInviteToClip()></div></div>';
|
|
setDialogMode(2, "Pozvat", 3, performAgentInvite, x, meshid);
|
|
if (features & 64) { Q('d2InviteType').focus(); d2ChangedInviteType(); } else { Q('d2inviteExpire').focus(); validateAgentInvite(); }
|
|
d2RequestInvitationLink();
|
|
return false;
|
|
}
|
|
|
|
function d2RequestInvitationLink() {
|
|
meshserver.send({ action: 'createInviteLink', meshid: xxdialogTag, expire: parseInt(Q('d2inviteExpire').value), flags: 0 });
|
|
}
|
|
|
|
function d2ChangedInviteType() {
|
|
QV('urlInviteDiv', Q('d2InviteType').value == 0);
|
|
QV('d2agentexpirediv', Q('agentInviteNameOs').value == 4);
|
|
QV('emailInviteDiv', Q('d2InviteType').value == 1);
|
|
validateAgentInvite();
|
|
}
|
|
|
|
function d2CopyInviteToClip() { copyTextToClip(Q('agentInvitationLink').href); }
|
|
|
|
function validateAgentInvite() {
|
|
if ((features & 64) && (Q('d2InviteType').value == 1)) {
|
|
QE('idx_dlgOkButton', checkEmail(Q('agentInviteEmail').value));
|
|
QV('idx_dlgCancelButton', true);
|
|
} else {
|
|
QE('idx_dlgOkButton', true);
|
|
QV('idx_dlgCancelButton', false);
|
|
}
|
|
}
|
|
|
|
function performAgentInvite(button, meshid) {
|
|
if ((features & 64) && (Q('d2InviteType').value == 1)) {
|
|
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) });
|
|
}
|
|
}
|
|
|
|
function addAgentToMesh(meshid) {
|
|
if (xxdialogMode) return false;
|
|
var mesh = meshes[meshid], x = '', installType = 0;
|
|
x += addHtmlValue("Operační systém", '<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 (Odinstalace)" + '</option><option value=4>' + "Linux / BSD (Odinstalace)" + '</option></select>');
|
|
x += '<div id=aginsTypeDiv>';
|
|
x += addHtmlValue("Typ instalace", '<select id=aginsType onchange=addAgentToMeshClick() style=width:236px><option value=0>' + "Na pozadí & interaktivní" + '</option><option value=2>' + "Pouze na pozadí" + '</option><option value=1>' + "Pouze interaktivní" + '</option></select>');
|
|
x += '</div><hr>';
|
|
|
|
// \/:*?"<>|
|
|
var meshfilename = mesh.name
|
|
meshfilename = meshfilename.split('\\').join('').split('/').join('').split(':').join('').split('*').join('').split('?').join('').split('"').join('').split('<').join('').split('>').join('').split('|').join('').split(' ').join('').split('\'').join('');
|
|
|
|
// Windows agent install
|
|
//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 />";
|
|
x += '<div id=agins_windows>' + format("Pro přidání nového zařízení do skupiny \"{0}\", si stáhněte agenta a nainstalujte na zařízení, které chcete spravovat. Tento agent již obsahuje veškeré informace pro připojení na server.", EscapeHtml(mesh.name)) + '<br /><br />';
|
|
x += addHtmlValue("Mesh Agent", '<a id=aginsw32lnk href="meshagents?id=3&meshid=' + meshid.split('/')[2] + '&installflags=0" download onclick="setDialogMode(0)" title=\"' + "32bit verze 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)>');
|
|
x += addHtmlValue("Mesh Agent", '<a id=aginsw64lnk href="meshagents?id=4&meshid=' + meshid.split('/')[2] + '&installflags=0" download onclick="setDialogMode(0)" title=\"' + "64bit verze 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)>');
|
|
if (debugmode > 0) { x += addHtmlValue("Soubor nastavení", '<a id=aginswmshlnk href="meshsettings?id=' + meshid.split('/')[2] + '&installflags=0" rel="noreferrer noopener" target="_blank">' + format("{0} nastavení (.msh)", EscapeHtml(mesh.name)) + '</a>'); }
|
|
x += '</div>';
|
|
|
|
// Linux agent install
|
|
x += '<div id=agins_linux style=display:none>' + format("Pro přidání do {0} spusťte následující příkaz. Je třeba spouštět pod rootem.", EscapeHtml(mesh.name)) + '<br />';
|
|
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>';
|
|
x += '<div style=\'font-size:x-small\'>' + "* Pro BSD, spusť \"pkg install wget sudo bash\" nejprve." + '</div></div>';
|
|
|
|
// MacOS agent install
|
|
x += '<div id=agins_osx style=display:none>' + format("Pro přidání do skupiny \"{0}\", si musíte stáhnout agenta a nainstalovat ho na počítači, který chcete spravovat. Tento agent má všechny potřebné informace pro připojení již v sobě.", EscapeHtml(mesh.name)) + '<br /><br />';
|
|
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="' + "Kopírovat odkaz pro MacOS agenta do schránky" + '" style=cursor:pointer onclick=copyAgentUrl("meshosxagent?id=16&meshid=' + meshid.split('/')[2] + '",0)>');
|
|
x += '</div>';
|
|
|
|
// Windows agent uninstall
|
|
x += '<div id=agins_windows_un style=display:none>' + "Pro odstranění agenta si stáhněte soubor níže, spusťte tento soubor a zvolte \"uninstall\"." + '<br /><br />';
|
|
x += addHtmlValue("Mesh Agent", '<a href="meshagents?id=3" download onclick="setDialogMode(0)" title="' + "32bit verze MeshAgent" + '">' + "Windows (.exe)" + '</a>');
|
|
x += addHtmlValue("Mesh Agent", '<a href="meshagents?id=4" download onclick="setDialogMode(0)" title="' + "64bit verze MeshAgent" + '">' + "Windows x64 (.exe)" + '</a>');
|
|
x += '</div>';
|
|
|
|
// Linux agent uninstall
|
|
x += '<div id=agins_linux_un style=display:none>' + "Chcete-li odebrat agenta, spusťte následující příkaz. Root přihlašovací údaje budou nutné." + '<br />';
|
|
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>';
|
|
x += '</div>';
|
|
|
|
setDialogMode(2, "Přidat agenta", 2, null, x, 'fileDownload');
|
|
var servername = serverinfo.name;
|
|
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.
|
|
var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
|
|
|
|
if (serverinfo.https == true)
|
|
{
|
|
var portStr = (serverinfo.port == 443)?'':(':' + serverinfo.port);
|
|
if ((features & 0x2000) == 0)
|
|
{
|
|
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';
|
|
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';
|
|
}
|
|
else
|
|
{
|
|
// Server asked that agent be installed to preferably not use a HTTP proxy.
|
|
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';
|
|
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';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
|
|
if ((features & 0x2000) == 0)
|
|
{
|
|
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';
|
|
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';
|
|
}
|
|
else
|
|
{
|
|
// Server asked that agent be installed to preferably not use a HTTP proxy.
|
|
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';
|
|
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';
|
|
}
|
|
}
|
|
Q('aginsSelect').focus();
|
|
addAgentToMeshClick();
|
|
return false;
|
|
}
|
|
|
|
function copyAgentUrl(url,addflag) {
|
|
var servername = serverinfo.name;
|
|
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.
|
|
var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
|
|
var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
|
|
var c = 'https://' + servername + portStr + domainUrl + url;
|
|
if (addflag == 1) c += Q('aginsType').value;
|
|
copyTextToClip(c);
|
|
}
|
|
|
|
function addAgentToMeshClick() {
|
|
var v = Q('aginsSelect').value;
|
|
QV('agins_windows', v == 0);
|
|
QV('agins_linux', v == 1);
|
|
QV('agins_osx', v == 2);
|
|
QV('agins_windows_un', v == 3);
|
|
QV('agins_linux_un', v == 4);
|
|
QV('aginsTypeDiv', v == 0);
|
|
|
|
// Fix the links if needed
|
|
Q('aginsw32lnk').href = (Q('aginsw32lnk').href.split('installflags=')[0]) + 'installflags=' + Q('aginsType').value;
|
|
Q('aginsw64lnk').href = (Q('aginsw64lnk').href.split('installflags=')[0]) + 'installflags=' + Q('aginsType').value;
|
|
if (debugmode > 0) { Q('aginswmshlnk').href = (Q('aginswmshlnk').href.split('installflags=')[0]) + 'installflags=' + Q('aginsType').value; }
|
|
}
|
|
|
|
function validateDeviceToMesh() {
|
|
QE('idx_dlgOkButton', (Q('dp1devicename').value.length > 0) && (passwordcheck(Q('dp1password').value)));
|
|
}
|
|
|
|
function addDeviceToMeshEx(button, meshid) {
|
|
var amtuser = Q('dp1username').value;
|
|
if (amtuser == '') amtuser = 'admin';
|
|
var host = Q('dp1hostname').value;
|
|
if (host == '') host = Q('dp1devicename').value;
|
|
meshserver.send({ action: 'addamtdevice', meshid: meshid, devicename: Q('dp1devicename').value, hostname: host, amtusername: amtuser, amtpassword: Q('dp1password').value, amttls: Q('dp1tls').value });
|
|
}
|
|
|
|
function deviceHeaderSet() {
|
|
if (deviceHeaderId == 0) { deviceHeaderId = 1; return; }
|
|
deviceHeaders['DevxHeader' + deviceHeaderId] = ((deviceHeaderTotal == 1) ? "1 nód" : format("{0} zařízení", deviceHeaderTotal));
|
|
//var title = '';
|
|
//for (x in deviceHeaderCount) { if (title.length > 0) title += ', '; title += deviceHeaderCount[x] + ' ' + PowerStateStr2(x); }
|
|
//deviceHeadersTitles["DevxHeader" + deviceHeaderId] = title;
|
|
deviceHeaderId++;
|
|
deviceHeaderCount = {};
|
|
deviceHeaderTotal = 0;
|
|
}
|
|
|
|
var powerStateStrings = ['', '<span title=\"' + "Zařízení je zapnuto." + '\">' + "Zapnuto" + '</span>', '<span title=\"' + "Zařízení je ve stavu spánku (S1)." + '\">' + "Spí" + '</span>', '<span title=\"' + "Zařízení je ve stavu spánku (S2)." + '\">' + "Spí" + '</span>', '<span title=\"' + "Zařízení je v hlubokém spánku (S3)." + '\">' + "Hluboký spánek" + '</span>', '<span title=\"' + "Zařízení je hibernováno (S4)." + '\">' + "Hibernuji" + '</span>', '<span title=\"' + "Zařízení je vypnuto (S5)." + '\">' + "Soft-Off" + '</span>', '<span title=\"' + "Zařízení je detekováno, ale nelze zjistit stav." + '\">' + "Současnost" + '</span>'];
|
|
var powerStateStrings2 = ['', "Zařízení je zapnuto", "Zařízení je ve stavu spánku (S1)", "Zařízení je ve stavu spánku (S2)", "Zařízení je v hlubokém spánku (S3)", "Zařízení je hibernováno (S4)", "Zařízení je ve stavu soft-off (S5)", "Zařízení je přítomno, ale nelze získat stav napájení"];
|
|
var powerColorTable = ['pwsTransparent', 'pwsBlack', 'pwsBlue', 'pwsBlue2', 'pwsLightblue', 'pwsBlueviolet', 'pwsDarkgreen', 'pwsLightseagreen', 'pwsLightseagreen2'];
|
|
function NodeStateStr(node) {
|
|
var states = [];
|
|
if (node.state > 0 && node.state < powerStatetable.length) state.push(powerStatetable[node.state]);
|
|
if (node.conn) {
|
|
if ((node.conn & 1) != 0) { states.push('<span title=\"' + "Agent je připojen a připraven." + '\">' + "Agent" + '</span>'); }
|
|
if ((node.conn & 2) != 0) { states.push('<span title=\"' + "Intel® AMT CIRA je připojeno a připraveno k použití." + '\">' + "CIRA" + '</span>'); }
|
|
else if ((node.conn & 4) != 0) { states.push('<span title=\"' + "Intel® AMT je směrovatelný." + '\">' + "AMT" + '</span>'); }
|
|
if ((node.conn & 8) != 0) { states.push('<span title=\"' + "Mesh agent je dostupný pomocí přesměrování přes jiného agenta." + '\">' + "Přesměrování" + '</span>'); }
|
|
if ((node.conn & 16) != 0) { states.push('<span title=\"' + "MQTT připojení na zařízení je aktivní." + '\">' + "MQTT" + '</span>'); }
|
|
}
|
|
if ((node.pwr != null) && (node.pwr != 0)) { states.push(powerStateStrings[node.pwr]); }
|
|
return states.join(', ');
|
|
}
|
|
|
|
function PowerStateStr(x) {
|
|
if (x < powerStatetable.length) return powerStatetable[x];
|
|
return '';
|
|
}
|
|
|
|
function PowerStateStr2(x) {
|
|
if ((x != 0) && (x < powerStatetable.length)) return powerStatetable[x];
|
|
return "Neznámý";
|
|
}
|
|
|
|
function selectallButtonFunction() {
|
|
var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
|
|
for (var i=0;i<elements.length;i++) { if (elements[i].checked === true) checkcount++; }
|
|
for (var i=0;i<elements.length;i++) { elements[i].checked = (checkcount == 0); }
|
|
p1updateInfo();
|
|
}
|
|
|
|
function p1updateInfo() {
|
|
var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
|
|
for (var i=0;i<elements.length;i++) { if (elements[i].checked === true) { checkcount++; } }
|
|
if (checkcount > 0) {
|
|
QE('GroupActionButton', true);
|
|
Q('SelectAllButton').value = "Vybrat nic";
|
|
QV('cxmgroupsplit', true);
|
|
QV('cxmdesktop', true);
|
|
} else {
|
|
QE('GroupActionButton', false);
|
|
Q('SelectAllButton').value = "Vybrat vše";
|
|
QV('cxmgroupsplit', false);
|
|
QV('cxmdesktop', false);
|
|
}
|
|
}
|
|
|
|
function groupActionFunction() {
|
|
var addedOptions = '', nodeids = getCheckedDevices();
|
|
|
|
// Check if any of the selected devices have a MQTT connection active
|
|
if (features & 0x00400000) {
|
|
for (var i in nodeids) { if ((getNodeFromId(nodeids[i]).conn & 16) != 0) { addedOptions += '<option value=103>' + "Poslat MQTT zprávu" + '</option>'; break; } }
|
|
}
|
|
|
|
// Display the "Uninstall Agent" option if allowed and we selected connected devices.
|
|
for (var i in nodeids) {
|
|
var node = getNodeFromId(nodeids[i]);
|
|
var mesh = meshes[node.meshid];
|
|
var meshrights = mesh.links[userinfo._id].rights;
|
|
if (((node.conn & 1) != 0) && ((meshrights & 32768) != 0)) { addedOptions += '<option value=104>' + "Odinstalovat agenta" + '</option>'; break; }
|
|
}
|
|
|
|
var x = "Vyberte operaci, kterou chcete provést na všech vybraných zařízeních. Akce budou prováděny pouze s náležitými právy." + '<br /><br />';
|
|
x += addHtmlValue("Operace", '<select id=d2groupop><option value=100>' + "Probudit zařízení" + '</option><option value=4>' + "Spící zařízení" + '</option><option value=3>' + "Reset zařízení" + '</option><option value=2>' + "Vypnout zařízení" + '</option><option value=102>' + "Přesunout do skupiny zařízení" + '</option>' + addedOptions + '<option value=101>' + "Smazat zařízení" + '</option></select>');
|
|
setDialogMode(2, "Akce skupiny", 3, groupActionFunctionEx, x);
|
|
}
|
|
|
|
// Get the list of checked devices, removes any duplicates.
|
|
function getCheckedDevices() {
|
|
var nodeids = [], elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
|
|
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); } } } }
|
|
return nodeids;
|
|
}
|
|
|
|
function groupActionFunctionEx() {
|
|
var op = Q('d2groupop').value;
|
|
if (op == 100) {
|
|
// Group wake
|
|
meshserver.send({ action: 'wakedevices', nodeids: getCheckedDevices() });
|
|
} else if (op == 101) {
|
|
// Group delete, ask for confirmation
|
|
var x = "Potvrdit smázání vybraných zařízení?" + '<br /><br />';
|
|
x += '<label><input id=d2check type=checkbox onchange=d2groupActionFunctionDelEx() />' + "Potvrdit" + '</label>';
|
|
setDialogMode(2, "Smazat nody", 3, groupActionFunctionDelEx, x);
|
|
QE('idx_dlgOkButton', false);
|
|
} else if (op == 102) {
|
|
// Move computers to a different group
|
|
p10showChangeGroupDialog(getCheckedDevices());
|
|
} else if (op == 103) {
|
|
// Send MQTT Message
|
|
p10showSendMqttMsgDialog(getCheckedDevices());
|
|
} else if (op == 104) {
|
|
// Uninstall agent
|
|
p10showSendUninstallAgentDialog(getCheckedDevices());
|
|
} else {
|
|
// Power operation
|
|
meshserver.send({ action: 'poweraction', nodeids: getCheckedDevices(), actiontype: parseInt(op) });
|
|
}
|
|
}
|
|
|
|
function d2groupActionFunctionDelEx() { QE('idx_dlgOkButton', Q('d2check').checked); }
|
|
function groupActionFunctionDelEx() { meshserver.send({ action: 'removedevices', nodeids: getCheckedDevices() }); }
|
|
|
|
function onSortSelectChange(skipsave) {
|
|
sort = document.getElementById('sortselect').selectedIndex;
|
|
if (!skipsave) { putstore('sort', sort); }
|
|
}
|
|
|
|
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; }
|
|
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; }
|
|
function deviceSort(a, b) { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; }
|
|
function deviceHostSort(a, b) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; }
|
|
function onSearchFocus(x) { searchFocus = x; }
|
|
function onMapSearchFocus(x) { mapSearchFocus = x; }
|
|
function onUserSearchFocus(x) { userSearchFocus = x; }
|
|
function onConsoleFocus(x) { consoleFocus = x; }
|
|
|
|
function onSearchInputChanged() {
|
|
var x = Q('SearchInput').value.toLowerCase().trim(); putstore('_search', x);
|
|
var userSearch = null, ipSearch = null, groupSearch = null;
|
|
if (x.startsWith('user:')) { userSearch = x.substring(5); }
|
|
else if (x.startsWith('u:')) { userSearch = x.substring(2); }
|
|
else if (x.startsWith('ip:')) { ipSearch = x.substring(3); }
|
|
else if (x.startsWith('group:')) { groupSearch = x.substring(6); }
|
|
else if (x.startsWith('g:')) { groupSearch = x.substring(2); }
|
|
|
|
if (x == '') {
|
|
// No search
|
|
for (var d in nodes) { nodes[d].v = true; }
|
|
} else if (ipSearch != null) {
|
|
// IP address search
|
|
for (var d in nodes) { nodes[d].v = ((nodes[d].ip != null) && (nodes[d].ip.indexOf(ipSearch) >= 0)); }
|
|
} else if (groupSearch != null) {
|
|
// Group filter
|
|
for (var d in nodes) { nodes[d].v = (meshes[nodes[d].meshid].name.toLowerCase().indexOf(groupSearch) >= 0); }
|
|
} else if (userSearch != null) {
|
|
// User search
|
|
for (var d in nodes) {
|
|
nodes[d].v = false;
|
|
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; } } }
|
|
}
|
|
} else {
|
|
// Device name search
|
|
try {
|
|
var rs = x.split(/\s+/).join('|'), rx = new RegExp(rs); // In some cases (like +), this can throw an exception.
|
|
for (var d in nodes) {
|
|
nodes[d].v = (rx.test(nodes[d].name.toLowerCase())) || (nodes[d].rnamel != null && rx.test(nodes[d].rnamel.toLowerCase()));
|
|
if ((nodes[d].v == false) && nodes[d].tags) {
|
|
for (var s in nodes[d].tags) {
|
|
if (rx.test(nodes[d].tags[s].toLowerCase())) {
|
|
nodes[d].v = true;
|
|
break;
|
|
} else {
|
|
nodes[d].v = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (ex) { for (var d in nodes) { nodes[d].v = true; } }
|
|
}
|
|
}
|
|
|
|
var contextelement = null;
|
|
function handleContextMenu(event) {
|
|
hideContextMenu();
|
|
var scrollLeft = (window.pageXOffset !== null) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft;
|
|
var scrollTop = (window.pageYOffset !== null) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
|
|
var elem = document.elementFromPoint(event.pageX - scrollLeft, event.pageY - scrollTop);
|
|
if (elem && elem != null && elem.id == 'connectbutton2' && currentNode && currentNode.agent && (currentNode.agent.id > 0) && (currentNode.agent.id < 5)) {
|
|
contextelement = elem;
|
|
var contextmenudiv = document.getElementById('termShellContextMenu');
|
|
contextmenudiv.style.left = event.pageX + 'px';
|
|
contextmenudiv.style.top = event.pageY + 'px';
|
|
contextmenudiv.style.display = 'block';
|
|
} else if (elem && elem != null && elem.id == 'connectbutton2' && currentNode && currentNode.agent && (currentNode.agent.id > 4)) {
|
|
contextelement = elem;
|
|
var contextmenudiv = document.getElementById('termShellContextMenuLinux');
|
|
contextmenudiv.style.left = event.pageX + 'px';
|
|
contextmenudiv.style.top = event.pageY + 'px';
|
|
contextmenudiv.style.display = 'block';
|
|
} else if (elem && elem != null && elem.id == 'MxMESH') {
|
|
contextelement = elem;
|
|
var contextmenudiv = document.getElementById('meshContextMenu');
|
|
contextmenudiv.style.left = event.pageX + 'px';
|
|
contextmenudiv.style.top = event.pageY + 'px';
|
|
contextmenudiv.style.display = 'block';
|
|
/*} else if (elem && elem != null && elem.classList.contains('pluginTab')) {
|
|
contextelement = elem;
|
|
var contextmenudiv = document.getElementById('pluginTabContextMenu');
|
|
contextmenudiv.style.left = event.pageX + 'px';
|
|
contextmenudiv.style.top = event.pageY + 'px';
|
|
contextmenudiv.style.display = 'block';*/
|
|
} else {
|
|
while (elem && elem != null && elem.id != 'devs') { elem = elem.parentElement; }
|
|
if (!elem || elem == null) return true;
|
|
contextelement = elem;
|
|
var contextmenudiv = document.getElementById('contextMenu');
|
|
contextmenudiv.style.left = event.pageX + 'px';
|
|
contextmenudiv.style.top = event.pageY + 'px';
|
|
contextmenudiv.style.display = 'block';
|
|
|
|
// Get the node and set the menu options
|
|
var nodeid = contextelement.children[1].attributes.onclick.value;
|
|
var node = getNodeFromId(nodeid.substring(12, nodeid.length - 18));
|
|
var mesh = meshes[node.meshid];
|
|
var meshlinks = mesh.links[userinfo._id];
|
|
var meshrights = meshlinks.rights;
|
|
var consoleRights = ((meshrights & 16) != 0);
|
|
|
|
// Check if we have terminal and file access
|
|
var terminalAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 512) == 0));
|
|
var fileAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 1024) == 0));
|
|
|
|
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)));
|
|
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);
|
|
QV('cxfiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8) && fileAccess);
|
|
QV('cxevents', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8));
|
|
QV('cxconsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8));
|
|
}
|
|
|
|
return haltEvent(event);
|
|
}
|
|
|
|
function cmaction(action,event) {
|
|
var nodeid = contextelement.children[1].attributes.onclick.value;
|
|
nodeid = nodeid.substring(12, nodeid.length - 18);
|
|
if (action == 7) { Q('viewselect').value = 3; Q('viewselect').onchange(); Q('autoConnectDesktopCheckbox').checked = true; Q('autoConnectDesktopCheckbox').onclick(); } // Multi-Desktop
|
|
if ((action > 0) && (action < 7)) {
|
|
var panel = [0, 10, 12, 11, 13, 16, 15][action]; // (invalid), General, Desktop, Terminal, Files, Events, Console
|
|
if (event && (event.shiftKey == true)) {
|
|
// Open the device in a different tab
|
|
window.open(window.location.origin + '?node=' + nodeid.split('/')[2] + '&viewmode=' + panel + '&hide=16', 'meshcentral:' + nodeid);
|
|
} else {
|
|
// Go to the right panel
|
|
gotoDevice(nodeid, panel);
|
|
|
|
// If possible, connect...
|
|
var mesh = meshes[currentNode.meshid];
|
|
if ((currentNode.conn & 1) && (mesh.mtype == 2)) {
|
|
if ((panel == 11) && (desktop == null) && (currentNode.agent.caps & 1)) { connectDesktop(null, 1); } // Desktop
|
|
if ((panel == 12) && (terminal == null) && (currentNode.agent.caps & 2)) { connectTerminal(null, 1); } // Terminal
|
|
if ((panel == 13) && (files == null)) { connectFiles(null); } // files
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function cmmeshaction(action) {
|
|
var meshid = contextelement.attributes.onclick.value.substring(10, contextelement.attributes.onclick.value.length - 2);
|
|
var elements = document.getElementsByClassName('DeviceCheckbox');
|
|
if ((action == 1) || (action == 2)) {
|
|
for (var i = 0; i < elements.length; i++) {
|
|
if ((elements[i].attributes) && (elements[i].attributes['class']['value'].split(' ')[0] == meshid)) { elements[i].checked = (action == 1); }
|
|
}
|
|
}
|
|
//if (action == 3) { window.location = "multidesktop.aspx?mesh=" + meshid + "&auto=1"; }
|
|
p1updateInfo();
|
|
}
|
|
|
|
function cmtermaction(action) {
|
|
connectTerminal(null, 1, { protocol: action });
|
|
}
|
|
|
|
/*
|
|
function pluginTabClose() {
|
|
var pluginTab = contextelement;
|
|
var pname = pluginTab.getAttribute('x-data-plugin-sname');
|
|
var pdiv = Q('plugin-'+pname);
|
|
pdiv.parentNode.removeChild(pdiv);
|
|
pluginTab.parentNode.removeChild(pluginTab);
|
|
QV('p42', true);
|
|
goPlugin(-1);
|
|
}
|
|
*/
|
|
|
|
function hideContextMenu() {
|
|
QV('contextMenu', false);
|
|
QV('meshContextMenu', false);
|
|
QV('termShellContextMenu', false);
|
|
QV('termShellContextMenuLinux', false);
|
|
//QV('pluginTabContextMenu', false);
|
|
contextelement = null;
|
|
}
|
|
|
|
//
|
|
// DEVICES MAP
|
|
//
|
|
|
|
// Maps code starts from here. Initialize all the variables
|
|
var xxmap = {
|
|
map: null,
|
|
contextmenu: null,
|
|
activeInteractions: [], // Save Modified features in this list
|
|
showindex: 0,
|
|
markersSource: null, // Initialize a Source Vector
|
|
markersLayer: null,
|
|
mapLayer: null, // Create a tile and use OSM source
|
|
mapView: null, // Sets the initial view
|
|
}
|
|
|
|
{{{StartGeoLocationJS}}}
|
|
|
|
// Add a feature for every Node and change style if connection status changes
|
|
function updateMapMarkers(selectedMesh) {
|
|
if ((xxmap != null) && (xxmap.map == null)) { try { loadmap(); } catch (ex) { console.error('loadmap() exception', ex); } }
|
|
if (xxmap == null) return;
|
|
var boundingBox = null;
|
|
for (var i in nodes) {
|
|
try {
|
|
var loc = map_parseNodeLoc(nodes[i]), feature = xxmap.markersSource.getFeatureById(nodes[i]._id);
|
|
if ((loc != null) && ((nodes[i].meshid == selectedMesh) || (selectedMesh == null))) { // Draw markers for devices with locations
|
|
var lat = loc[0], lon = loc[1], type = loc[2];
|
|
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; } }
|
|
if (feature == null) { addFeature(nodes[i]); boundingBox[4] = 1; } else { updateFeature(nodes[i], feature); feature.setStyle(markerStyle(nodes[i], loc[2])); } // Update Feature
|
|
} else {
|
|
if (feature) { xxmap.markersSource.removeFeature(feature); }
|
|
}
|
|
} catch (ex) { console.error('updateMapMarkers() exception', ex, JSON.stringify(nodes[i])); }
|
|
}
|
|
return boundingBox;
|
|
}
|
|
|
|
// Show node details on hovering over a feature
|
|
var map_cm_popup = new ol.Overlay({ element: Q('xmap-info-window'), positioning: 'bottom-center', stopEvent: false });
|
|
|
|
// Edit Marker item
|
|
var map_cm_editMarker = { text: "Upravit umístění nódu", callback: function (obj) { modifyMarkerloc(obj.data); } };
|
|
|
|
// Clear Marker item
|
|
var map_cm_clearMarker = { text: "Odstranit umístění nódu", callback: function (obj) {
|
|
meshserver.send({ action: 'changedevice', nodeid: obj.data.a, userloc: [] }); // Clear the user position marker
|
|
}};
|
|
|
|
// Save Marker item
|
|
var map_cm_saveMarker = { text: "Uložit umístění nódu", callback: function (obj) { saveMarkerloc(obj.data); } };
|
|
|
|
// Build a context menu for a feature
|
|
var map_cm_nodemenu_items = [
|
|
{ text: "Obecné informace", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 10); } } },
|
|
{ text: "Plocha", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 11); } } },
|
|
{ text: "Terminál", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 12); } } },
|
|
{ text: "Intel® AMT", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 14); } } },
|
|
'-',
|
|
{ text: "Přiblížit", callback: function(obj) { var coords = obj.data.getGeometry().getCoordinates(); zoomToLocation(coords, 19); } },
|
|
{ text: "Oddálit", callback: function(obj) { var coords = obj.data.getGeometry().getCoordinates(); zoomToLocation(coords, 2); } }
|
|
];
|
|
|
|
// Context menu for clicks other than on feature
|
|
var contextmenu_items = [
|
|
{ text: "Obnovit", callback: function () { refreshMap(true, true); } },
|
|
{ text: "Přiblížit na míru", callback: function () { zoomToFitExtent(); } },
|
|
{ text: "Vycentrovat mapu zde", callback: function(obj) { xxmap.mapView.animate({ center: obj.coordinate } ); } },
|
|
{ text: "Umístit nód zde", callback: function(obj) { placeNode(obj.coordinate); } }
|
|
];
|
|
|
|
function stringToIntHash(str) {
|
|
var hash = 0, i;
|
|
for (i = 0; i < str.length; i++) { hash = ((hash << 5) - hash) + str.charCodeAt(i); hash |= 0; }
|
|
return hash;
|
|
};
|
|
|
|
// Get the lat/lon from a node
|
|
function map_parseNodeLoc(node) {
|
|
var loc = null, t = 0;
|
|
if (node.iploc) { loc = node.iploc; t = 1; }
|
|
if (node.wifiloc) { loc = node.wifiloc; t = 2; }
|
|
if (node.gpsloc) { loc = node.gpsloc; t = 3; }
|
|
if (node.userloc) { loc = node.userloc; t = 4; }
|
|
if ((loc == null) || (typeof loc != 'string')) return null;
|
|
loc = loc.split(',');
|
|
if (t == 1) {
|
|
// If this is IP location, randomize the position a little.
|
|
return [ parseFloat(loc[0]) + (stringToIntHash(node._id.substring(0, 20)) / 100000000000), parseFloat(loc[1]) + (stringToIntHash(node._id.substring(20)) / 100000000000), t ];
|
|
} else {
|
|
// Return the real position
|
|
return [ parseFloat(loc[0]), parseFloat(loc[1]), t ];
|
|
}
|
|
}
|
|
|
|
// Load the entire map
|
|
function loadmap() {
|
|
if (xxmap == null) return;
|
|
if ((features & 0x8000) == 0) { xxmap = null; return; } // Geolocation not supported
|
|
QV('viewselectmapoption', true);
|
|
QV('devViewButton4', true);
|
|
try {
|
|
// Initialize a Source Vector
|
|
xxmap.markersSource = new ol.source.Vector();
|
|
|
|
xxmap.markersLayer = new ol.layer.Vector({
|
|
source: xxmap.markersSource
|
|
});
|
|
|
|
// Create a tile and use OSM source
|
|
xxmap.mapLayer = new ol.layer.Tile({ source: new ol.source.OSM() });
|
|
|
|
xxmap.mapView = new ol.View({ // Set the initial view
|
|
center: ol.proj.transform([0, 0], 'EPSG:4326', 'EPSG:3857'),
|
|
zoom: 2,
|
|
minZoom: 2,
|
|
maxZoom: 20,
|
|
extent: ol.proj.transformExtent([-100000, -69.55, 100000, 69.55], 'EPSG:4326', 'EPSG:3857')
|
|
});
|
|
|
|
xxmap.map = new ol.Map({
|
|
target: 'xdevicesmap',
|
|
layers: [xxmap.mapLayer, xxmap.markersLayer],
|
|
view: xxmap.mapView
|
|
});
|
|
|
|
xxmap.map.addOverlay(map_cm_popup);
|
|
|
|
// Goto information tab if a user clicks on a feature
|
|
xxmap.map.on('click', function(evt) {
|
|
var feature = xxmap.map.forEachFeatureAtPixel(evt.pixel, function(feat, layer) { return feat; });
|
|
if (feature) {
|
|
var nodeid = feature.getId();
|
|
if (nodeid != null) { gotoDevice(nodeid, 10); } // Goto general info tab
|
|
else { // For pointer
|
|
var nodeFeatgoto = getCorrespondingFeature(feature); gotoDevice(nodeFeatgoto.getId(), 10);
|
|
}
|
|
}
|
|
});
|
|
|
|
// On hover feature show the name of the node. Also add pointer style
|
|
xxmap.map.on('pointermove', function(evt) {
|
|
var feature = xxmap.map.forEachFeatureAtPixel(evt.pixel, function(feat, layer) { return feat; });
|
|
if (feature) {
|
|
xxmap.map.getTargetElement().style.cursor = 'pointer';
|
|
var coord = feature.getGeometry().getCoordinates();
|
|
// map_cm_popup.setPosition(evt.coordinate);
|
|
map_cm_popup.setPosition(coord);
|
|
var featid = feature.getId();
|
|
if (featid) {
|
|
QH('xmap-info-window', feature.get('name'));
|
|
} else {
|
|
var nodeFeat = getCorrespondingFeature(feature); // Return the node feature associated to pointer.
|
|
QH('xmap-info-window', nodeFeat.get('name'));
|
|
}
|
|
} else {
|
|
xxmap.map.getTargetElement().style.cursor = '';
|
|
QH('xmap-info-window', '');
|
|
}
|
|
});
|
|
|
|
// Initialize context menu for openlayers
|
|
var contextmenu = new ContextMenu({
|
|
width: 160,
|
|
defaultItems: false, // defaultItems are Zoom In/Zoom Out
|
|
items: contextmenu_items
|
|
});
|
|
|
|
// On right click open the context menu
|
|
contextmenu.on("otevřít", function (evt) {
|
|
var feature = xxmap.map.forEachFeatureAtPixel(evt.pixel, function(ft, l){ return ft; });
|
|
xxmap.contextmenu.clear(); //Clear the context menu
|
|
if (feature) {
|
|
var featId = feature.getId();
|
|
if (featId) { addContextMenuItems(feature); } // Node feature will have an id
|
|
else { // If the feature is a pointer, Get its corresponding Node feature
|
|
var nodeFeature = getCorrespondingFeature(feature); //return the node feature associated to pointer.
|
|
if (nodeFeature) { addContextMenuItems(nodeFeature); }
|
|
else{ xxmap.contextmenu.extend(contextmenu_items); }
|
|
}
|
|
}
|
|
else { xxmap.contextmenu.extend(contextmenu_items); }
|
|
});
|
|
if (xxmap.contextmenu == null) { xxmap.contextmenu = contextmenu; }
|
|
xxmap.map.addControl(xxmap.contextmenu);
|
|
//addMeshOptions(); // Adds Mesh names to mesh dropdown
|
|
} catch (ex) {
|
|
console.log(ex);
|
|
QV('viewselectmapoption', false);
|
|
QV('devViewButton4', false);
|
|
xxmap = null;
|
|
}
|
|
}
|
|
|
|
// Add feature on to Map for a Node
|
|
function addFeature(node, lat, lon) {
|
|
var existingfeature = getModifiedFeature(node._id); // Check if Corresponding feature was Modified ( Modifed feature are in active interactions list)
|
|
if (existingfeature) { xxmap.markersSource.addFeature(existingfeature); } // Add that existing feature
|
|
else { // Add new feature for this node
|
|
if (!lat && !lon) { var loc = map_parseNodeLoc(node); lat = loc[0]; lon = loc[1]; }
|
|
|
|
// 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.
|
|
if (lon > 180) { lon = 180 - lon; meshserver.send({ action: 'changedevice', nodeid: node._id, userloc: [ lat, lon ] }); }
|
|
|
|
if ((lat < 90) && (lat > -90) && (lon < 180) && (lon > -180)) { // Check valid lat/lon
|
|
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 });
|
|
feature.setId(node._id); // Set id for the device as nodeid
|
|
feature.setStyle(markerStyle(node));
|
|
xxmap.markersSource.addFeature(feature); // Add the feature to Marker Source
|
|
}
|
|
}
|
|
}
|
|
|
|
// Removing any feature from map
|
|
function removeFeature(node) {
|
|
var feature = xxmap.markersSource.getFeatureById(node._id);
|
|
if (feature) { xxmap.markersSource.removeFeature(feature); }
|
|
}
|
|
|
|
// Update feature
|
|
function updateFeature(node, feature) {
|
|
if (node.conn != feature.get('status') ) { // Update status if changed
|
|
feature.set('status',node.conn)
|
|
feature.setStyle(markerStyle(node));
|
|
}
|
|
|
|
// Since this is IP address location, add some fixed randomness to the location. Avoid pin pile-up.
|
|
var loc = map_parseNodeLoc(node);
|
|
if (loc != null) {
|
|
var lat = loc[0], lon = loc[1];
|
|
if ((lat != feature.get('lat')) || (lon != feature.get('lon'))) { // Update lat and lon if changed
|
|
feature.set('lat', lat); feature.set('lon', lon);
|
|
var modifiedCoordinates = ol.proj.transform([parseFloat(lon), parseFloat(lat)], 'EPSG:4326', 'EPSG:3857');
|
|
feature.getGeometry().setCoordinates(modifiedCoordinates);
|
|
}
|
|
}
|
|
|
|
if (node.name != feature.get('name') ) { feature.set('name', node.name); } // Update name
|
|
}
|
|
|
|
// Enable dragging of a marker after edit option is clicked in context menu
|
|
function modifyMarkerloc(ft){
|
|
var featid = ft.getId();
|
|
if (featid) {
|
|
ft.setStyle(markerStyle(getNodeFromId(ft.a), 4)); // Switch to a user marker
|
|
if ( !getActiveInteractions(ft)) {
|
|
var dragInteration = new ol.interaction.Modify({
|
|
features: new ol.Collection([ft]),
|
|
pixelTolerance: 10
|
|
});
|
|
xxmap.activeInteractions.push({ featureid: featid, feature:ft, interaction: dragInteration }); // Also keep track of Interactions
|
|
xxmap.map.addInteraction(dragInteration);
|
|
}
|
|
}
|
|
}
|
|
|
|
// This will be called when save location option is clicked in context menu
|
|
function saveMarkerloc(ft){
|
|
var featid = ft.getId()
|
|
if (featid) {
|
|
var actInteraction = getActiveInteractions(ft);
|
|
if (actInteraction) { // Check if the interaction exists
|
|
xxmap.map.removeInteraction(actInteraction); //Clear Interaction for that node
|
|
removeInteraction(featid);
|
|
var coord = ft.getGeometry().getCoordinates();
|
|
var v = ol.proj.transform(coord, 'EPSG:3857', 'EPSG:4326');
|
|
if (v[0] > 180) { v[0] = 180 - v[0]; }
|
|
var vx = [ v[1], v[0] ]; // Flip the coordinates around, lat/long
|
|
meshserver.send({ action: 'changedevice', nodeid: featid, userloc: vx }); // Send them to server to save changes
|
|
}
|
|
}
|
|
}
|
|
|
|
// Style the Markers
|
|
function markerStyle(node, type) {
|
|
if (type == null) {
|
|
type = 0;
|
|
if (node.iploc) { type = 1; }
|
|
if (node.wifiloc) { type = 2; }
|
|
if (node.gpsloc) { type = 3; }
|
|
if (node.userloc) { type = 4; }
|
|
}
|
|
var types = ['', '-ip','-wifi','-gps','-user'];
|
|
var color = connStateColor(node);
|
|
var style = new ol.style.Style({
|
|
image: new ol.style.Icon({ color: color, anchor: [0.5, 1], src: 'images/mapmarker' + types[type] + '.png' })
|
|
//stroke: new ol.style.Stroke({ color: '#000', width: 20 })
|
|
//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 }) })
|
|
});
|
|
|
|
//deviceMark.setStyle(new ol.style.Style({
|
|
// text: new ol.style.Text({
|
|
// //font: '12px helvetica,sans-serif',
|
|
// text: currentNode.name,
|
|
// textAlign: 'right',
|
|
// offsetX: -10,
|
|
// fill: new ol.style.Fill({ color: '#000' }),
|
|
// stroke: new ol.style.Stroke({ color: '#fff', width: 2 })
|
|
// }),
|
|
// image: new ol.style.Icon(({ color: [113, 140, 0], src: 'images/dot.png' })) }));
|
|
|
|
return [ style ];
|
|
}
|
|
|
|
// TODO: Add more connection status types. Currently we only change color if connection status changes
|
|
function connStateColor(nodeConn){
|
|
if (nodeConn.conn == 1 || nodeConn.conn == 3 || nodeConn.conn == 5) { return '#00ffdd'; } // Green for connected devices
|
|
return '#C70039'; // Red if the Agent is not connected
|
|
}
|
|
|
|
// Add save/edit option to context menu
|
|
function addContextMenuItems(feature) {
|
|
if (getActiveInteractions(feature)) { // If this feature is modified then display save option in contextmenu
|
|
map_cm_saveMarker.data = feature;
|
|
xxmap.contextmenu.push(map_cm_saveMarker);
|
|
} else {
|
|
map_cm_editMarker.data = feature;
|
|
xxmap.contextmenu.push(map_cm_editMarker);
|
|
var node = getNodeFromId(feature.a);
|
|
if (node.userloc) {
|
|
map_cm_clearMarker.data = feature;
|
|
xxmap.contextmenu.push(map_cm_clearMarker);
|
|
}
|
|
}
|
|
map_cm_nodemenu_items.forEach(function (item){
|
|
if (item.text == "Přiblížit" || item.text == "Oddálit") { item.data = feature; }
|
|
else { if (item != '-') { item.data = feature.getId(); } }
|
|
});
|
|
xxmap.contextmenu.extend(map_cm_nodemenu_items);
|
|
}
|
|
|
|
// Return a active Interaction if it exists in activeInteractions list
|
|
function getActiveInteractions(feature) {
|
|
var featid = feature.getId();
|
|
for (var i = 0; i < xxmap.activeInteractions.length; i++) {
|
|
if (xxmap.activeInteractions[i].featureid == featid) { return xxmap.activeInteractions[i].interaction; }
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Return Modified feature based on Id
|
|
function getModifiedFeature(featid) {
|
|
if (featid) {
|
|
for (var i = 0; i < xxmap.activeInteractions.length; i++) {
|
|
if (xxmap.activeInteractions[i].featureid == featid) { return xxmap.activeInteractions[i].feature; }
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// Remove Interaction
|
|
function removeInteraction(ftid) {
|
|
var index = -1;
|
|
for (var i = 0; i < xxmap.activeInteractions.length; i++) {
|
|
if (xxmap.activeInteractions[i].featureid === ftid) { index = i; break; }
|
|
}
|
|
if (index >= 0) { xxmap.activeInteractions.splice(index, 1); }
|
|
}
|
|
|
|
// Check if pointer coordinates are equal to features and return node feature
|
|
function getCorrespondingFeature(pointerFeat) {
|
|
var pointerCoord = pointerFeat.getGeometry().getCoordinates();
|
|
for (var i = 0; i < xxmap.activeInteractions.length ; i++) {
|
|
var modifiedFeatures = xxmap.activeInteractions[i].feature;
|
|
var fearCoord = modifiedFeatures.getGeometry().getCoordinates();
|
|
if (fearCoord[0].toFixed(5) == pointerCoord[0].toFixed(5) && fearCoord[1].toFixed(5) == pointerCoord[1].toFixed(5) ) { return modifiedFeatures; }
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// Refresh the map and clear list
|
|
function refreshMap(reset, rebound){
|
|
if (reset) {
|
|
xxmap.map.setTarget(null);
|
|
xxmap.map = null;
|
|
xxmap.markersSource = null;
|
|
xxmap.mapView = null;
|
|
xxmap.mapLayer = null;
|
|
xxmap.activeInteractions = []; // Clear Active Interaction list
|
|
}
|
|
//clearMeshOptions();
|
|
//onSelectMeshChange();
|
|
var box = updateMapMarkers();
|
|
if ((box != null) && (rebound || (box[4] == 1))) {
|
|
var clat = (box[0] + box[2]) / 2;
|
|
var clon = (box[1] + box[3]) / 2;
|
|
var cscale = Math.max(Math.abs(box[0] - box[2]), Math.abs(box[1] - box[3]));
|
|
var view = xxmap.map.getView();
|
|
view.setCenter(ol.proj.transform([clon, clat], 'EPSG:4326', 'EPSG:3857'));
|
|
var i = 360, j = -2;
|
|
while (i > cscale) { j++; i = i / 2; }
|
|
view.setZoom(j);
|
|
}
|
|
}
|
|
|
|
// Called When Place a node option is clicked from context menu
|
|
function placeNode(coords) {
|
|
if (xxdialogMode) return;
|
|
var x = '<div style=margin-bottom:6px><label for=selectnode-search>' + "Hledat" + '</label>  <input type=text placeholder="' + "Název zařízení" + '" 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>' + "Žádné zařízení nalezeno." + '</div>';
|
|
for (var i in nodes) {
|
|
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 />';
|
|
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>';
|
|
}
|
|
setDialogMode(2, "Vybrat kam umístit nód", 3, placeNodeEx, x + '</div>', coords);
|
|
onPlaceNodeInputChange();
|
|
}
|
|
|
|
function placeNodeEx(button, coords) {
|
|
var elements = document.getElementsByName('PlaceMapDeviceCheckbox');
|
|
for (var i in elements) {
|
|
if (elements[i].checked) {
|
|
var node = getNodeFromId(elements[i].id.substring(0, elements[i].id.length - 8));
|
|
if (node) {
|
|
var feature = xxmap.markersSource.getFeatureById(i);
|
|
var v = ol.proj.transform(coords, 'EPSG:3857', 'EPSG:4326');
|
|
var vx = [ v[1], v[0] ]; // Flip the coordinates around, lat/long
|
|
if (feature) {
|
|
feature.getGeometry().setCoordinates(coords);
|
|
var activeInteraction = getActiveInteractions(feature);
|
|
if (activeInteraction) {
|
|
saveMarkerloc(feature);
|
|
} else { // If this feature is not saved after its location is changed, then send updated coords to server.
|
|
meshserver.send({ action: 'changedevice', nodeid: node._id, userloc: vx }); // Send them to server to save changes
|
|
}
|
|
} else {
|
|
meshserver.send({ action: 'changedevice', nodeid: node._id, userloc: vx }); // This Node is not yet added to maps.
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Called when the user changes the search box
|
|
function onPlaceNodeInputChange() {
|
|
updatePlaceNodeTable(Q('selectnode-search').value.trim().toLowerCase());
|
|
}
|
|
|
|
// Update the list of devices in the "place on map" table
|
|
function updatePlaceNodeTable(inputSearch) {
|
|
var elements = document.getElementsByName('PlaceMapDeviceCheckbox'), count = 0;
|
|
for (var i in nodes) {
|
|
var visible = ((nodes[i].namel.indexOf(inputSearch) >= 0 || inputSearch == '') || (nodes[i].rnamel != null && nodes[i].rnamel.indexOf(inputSearch) >= 0));
|
|
if (visible) { count++; }
|
|
QV(nodes[i]._id + '-rowid', visible);
|
|
}
|
|
QV('noNodesMapPlace', count == 0);
|
|
//console.log(selected);
|
|
//for (var i in nodes) {
|
|
// if ((nodes[i].name.toLowerCase().indexOf(inputSearch) >= 0 || inputSearch == '') || (nodes[i].rnamel != null && nodes[i].rnamel.toLowerCase().indexOf(inputSearch) >= 0)) {
|
|
// console.log(selected.indexOf(nodes[i]._id));
|
|
// 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':'') + ' />';
|
|
// 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>';
|
|
// }
|
|
//}
|
|
//if (x == '') { x = '<div style=text-align:center;width:100%>No devices found.</div>'; }
|
|
//QH('placenode', '');
|
|
}
|
|
|
|
// Called when a user clicks on a device to toggle selection for placement on map.
|
|
function selectNodeToPlace(e, id) {
|
|
// Toggle checkbox if needed
|
|
if (e.target.name != 'PlaceMapDeviceCheckbox') { var inputElement = Q(id + '-checkid'); inputElement.checked = !inputElement.checked; }
|
|
|
|
// Check button state
|
|
var elements = document.getElementsByName('PlaceMapDeviceCheckbox'), checkcount = 0;
|
|
for (var i in elements) { if (elements[i].checked) checkcount++; }
|
|
QE('idx_dlgOkButton', checkcount > 0);
|
|
}
|
|
|
|
// Add option for available meshes in mesh Dropdown
|
|
function addMeshOptions(addMeshid, meshName) {
|
|
//var meshOptions = Q('select-mesh');
|
|
//if (addMeshid && meshName) {
|
|
// var option = document.createElement('option');
|
|
// option.value =addMeshid;
|
|
// option.text = meshName;
|
|
// meshOptions.add(option); // Add specific option
|
|
//}
|
|
//else {
|
|
// for (var i in meshes) { // Add all options
|
|
// var option = document.createElement('option');
|
|
// option.value = i;
|
|
// option.text = meshes[i].name;
|
|
// meshOptions.add(option);
|
|
// }
|
|
//}
|
|
}
|
|
|
|
// Remove/Modify options in Mesh dropdown (if modMeshname is defined then Modify else Remove)
|
|
function meshOptionRmvMod(delMeshid, modMeshname){
|
|
//var meshOptions = Q('select-mesh');
|
|
//if (delMeshid) {
|
|
// var index=-1;
|
|
// for (var i = 1; i < meshOptions.options.length; i++) {
|
|
// if (meshOptions[i].value === delMeshid) { index=i; }
|
|
// }
|
|
// if (index > 0) {
|
|
// if (modMeshname) {
|
|
// meshOptions[index].innerHTML=modMeshname; // If Mesh name is Modified
|
|
// }
|
|
// else { meshOptions.remove(index); }
|
|
// }
|
|
//}
|
|
}
|
|
|
|
//Check if there is any mesh created
|
|
function meshExists() {
|
|
for (var i in meshes) { if (meshes[i]) { return true; } }
|
|
return false;
|
|
}
|
|
|
|
// Reset Mesh dropdown option to 'All' when a current view mesh is deleted.
|
|
function setMeshView(emeshid) {
|
|
var selectMeshElement=Q('select-mesh');
|
|
var selectedIndex = selectMeshElement.selectedIndex;
|
|
if (selectMeshElement[selectedIndex].value == emeshid) { selectMeshElement[0].selected = true; onSelectMeshChange(); }
|
|
}
|
|
|
|
// Clear all mesh options except 'All'
|
|
function clearMeshOptions() {
|
|
//var meshOptions=Q('select-mesh');
|
|
//for(var i = meshOptions.options.length - 1 ; i > 0 ; i--) { meshOptions.remove(i); }
|
|
}
|
|
|
|
// Make a http get call- Replace this with AJAX get if jquery is used
|
|
function getSearchLocation() {
|
|
try {
|
|
var searchdata = Q('mapSearchLocation').value.trim();
|
|
if (searchdata.length > 0) {
|
|
var xmlhttp = new XMLHttpRequest(); // Compatible with Chrome, Opera, Safari, IE7+, Firefox.
|
|
xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { formatSearchData(xmlhttp.responseText); } }
|
|
xmlhttp.open('GET', 'https://nominatim.openstreetmap.org/search?q=' + searchdata + '&format=json', true); // Get request
|
|
xmlhttp.send();
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
|
|
// Format data recieved from nominatim API and display it on content window
|
|
function formatSearchData(data) {
|
|
try {
|
|
QH('xmapSearchResults','');
|
|
var dataInfo = JSON.parse(data), count = 0, x = '<div class="xmapItem">';
|
|
for (var i = 0; i < dataInfo.length; i++) {
|
|
if (dataInfo[i].display_name && dataInfo[i].boundingbox[0] && dataInfo[i].boundingbox[1] && dataInfo[i].boundingbox[2] && dataInfo[i].boundingbox[3]) {
|
|
count++;
|
|
var itemclass = (i % 2 == 0)?'xmapItemSel1':'xmapItemSel1';
|
|
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>';
|
|
}
|
|
}
|
|
x += '</div>';
|
|
if (count == 1) {
|
|
// If only one result is returned then zoom to that location
|
|
var extent = [ parseFloat(dataInfo[0].boundingbox[2]), parseFloat(dataInfo[0].boundingbox[0]), parseFloat(dataInfo[0].boundingbox[3]), parseFloat(dataInfo[0].boundingbox[1]) ];
|
|
zoomToExtent(extent);
|
|
} else {
|
|
if (count == 0) { x = '<div style=width:200px>' + "Žádné umístění." + '<div>'; }
|
|
QV('xmapSearchResultsDlg', true);
|
|
}
|
|
QH('xmapSearchResults', x);
|
|
}
|
|
catch (e) {}
|
|
}
|
|
|
|
// Zoom into the bounding box
|
|
function mapGotoSelectedLocation(obj) {
|
|
var objchildren = obj.children;
|
|
var boundingBox = objchildren[1].innerHTML.split('!#!');
|
|
var extent = [parseFloat(boundingBox[2]), parseFloat(boundingBox[0]), parseFloat(boundingBox[3]), parseFloat(boundingBox[1])];
|
|
//Q('search-location').value = objchildren[0].innerHTML;
|
|
zoomToExtent(extent);
|
|
mapCloseSearchWindow();
|
|
}
|
|
|
|
// Close the search window
|
|
function mapCloseSearchWindow() {
|
|
QH('xmapSearchResults', '');
|
|
QV('xmapSearchResultsDlg', false);
|
|
}
|
|
|
|
// Zoom to specific cordinates
|
|
function zoomToLocation(coordinates, zoomVal) {
|
|
var view = xxmap.map.getView();
|
|
view.setCenter(coordinates);
|
|
view.setZoom(zoomVal);
|
|
}
|
|
|
|
function zoomToFitExtent() {
|
|
var features = xxmap.markersSource.getFeatures();
|
|
if (features.length > 0) {
|
|
var extent = xxmap.markersSource.getExtent();
|
|
xxmap.map.getView().fit(extent, xxmap.map.getSize());
|
|
}
|
|
}
|
|
|
|
function zoomToExtent(extent){
|
|
var boundingExtent = ol.proj.transformExtent(extent, ol.proj.get('EPSG:4326'), ol.proj.get('EPSG:3857'));
|
|
xxmap.map.getView().fit(boundingExtent, xxmap.map.getSize());
|
|
}
|
|
|
|
{{{EndGeoLocationJS}}}
|
|
|
|
//
|
|
// MY DEVICE
|
|
//
|
|
function refreshDevice(nodeid) {
|
|
if (!currentNode || currentNode._id != nodeid) return;
|
|
gotoDevice(nodeid, xxcurrentView, true);
|
|
}
|
|
|
|
function getNodeRights(nodeid) {
|
|
var node = getNodeFromId(nodeid), mesh = meshes[node.meshid];
|
|
return mesh.links[userinfo._id].rights;
|
|
}
|
|
|
|
var currentNode;
|
|
var powerTimelineNode = null;
|
|
var powerTimelineReq = null;
|
|
var powerTimelineUpdate = null;
|
|
var powerTimeline = null;
|
|
function getCurrentNode() { return currentNode; };
|
|
function gotoDevice(nodeid, panel, refresh, event) {
|
|
// Remind the user to verify the email address
|
|
if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "Nastavení bezpečnosti", 1, null, "Nelze získat přístup k zařízení, dokud nebude ověřena e-mailová adresa. To je vyžadováno pro obnovení hesla. Jdi do \"Můj účet\" pro změnu a ověření emailu."); return; }
|
|
|
|
// Remind the user to add two factor authentication
|
|
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0))) { setDialogMode(2, "Nastavení bezpečnosti", 1, null, "Nelze získat přístup k zařízení, dokud je 2-faktorová autentizace zapnuta. Toto je pro extra bezpečnost. Jdi do \"Můj účet\" a podívej se do sekce\"Nastavení bezpečnosti\"."); return; }
|
|
|
|
if (event && (event.shiftKey == true)) {
|
|
// Open the device in a different tab
|
|
window.open(window.location.origin + '?node=' + nodeid.split('/')[2] + '&viewmode=10&hide=16', 'meshcentral:' + nodeid);
|
|
return;
|
|
}
|
|
|
|
//disconnectAllKvmFunction();
|
|
var node = getNodeFromId(nodeid);
|
|
var mesh = meshes[node.meshid];
|
|
var meshrights = mesh.links[userinfo._id].rights;
|
|
if (!currentNode || currentNode._id != node._id || refresh == true) {
|
|
currentNode = node;
|
|
|
|
// Add node name
|
|
var nname = EscapeHtml(node.name);
|
|
if (nname.length == 0) { nname = '<i>' + "Nic" + '</i>'; }
|
|
if (((meshrights & 4) != 0) && ((!mesh.flags) || ((mesh.flags & 2) == 0))) { nname = '<span tabindex=0 title=\"' + "Klikni zde pro úpravu server-side jména zařízení" + '\" onclick=showEditNodeValueDialog(0) onkeyup="if (event.key == \'Enter\') showEditNodeValueDialog(0)" style=cursor:pointer>' + nname + ' <img class=hoverButton src="images/link5.png" /></span>'; }
|
|
nname += '<span style=color:#AAA;font-size:small> - ' + EscapeHtml(mesh.name) + '</span>';
|
|
QH('p10deviceName', nname);
|
|
QH('p11deviceName', nname);
|
|
QH('p12deviceName', nname);
|
|
QH('p13deviceName', nname);
|
|
QH('p14deviceName', nname);
|
|
QH('p15deviceName', "Konzole - " + nname);
|
|
QH('p16deviceName', nname);
|
|
QH('p17deviceName', nname);
|
|
QH('p19deviceName', nname);
|
|
|
|
// Node attributes
|
|
var x = '<table style=width:100%>';
|
|
|
|
// Attribute: Mesh
|
|
x += addDeviceAttribute('<span title=\"' + "Název skupiny zařízení, do které tento počítač patří." + '\">' + "Skupina" + '</span>', '<a href=# title=\"' + "Název skupiny zařízení, do které tento počítač patří" + '\" onclick=gotoMesh("' + node.meshid + '") style=cursor:pointer>' + EscapeHtml(meshes[node.meshid].name) + '</a>');
|
|
|
|
// Attribute: Name
|
|
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>'); }
|
|
|
|
// Attribute: Host
|
|
if ((features & 1) == 0) { // If not WAN-only, local hostname is in use
|
|
if ((meshrights & 4) != 0) {
|
|
if (node.host) {
|
|
x += addDeviceAttribute("Hostname", '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer>' + EscapeHtml(node.host) + '</span>');
|
|
} else {
|
|
x += addDeviceAttribute("Hostname", '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer><i>' + "Nic" + '</i></span>');
|
|
}
|
|
} else {
|
|
x += addDeviceAttribute("Hostname", EscapeHtml(node.host));
|
|
}
|
|
}
|
|
|
|
// Attribute: Description
|
|
var description = node.desc?EscapeHtml(node.desc):('<i>' + "Nic" + '</i>');
|
|
if ((meshrights & 4) != 0) {
|
|
x += addDeviceAttribute("Popis", '<span onclick=showEditNodeValueDialog(2) style=cursor:pointer>' + description + ' <img class=hoverButton src="images/link5.png" /></span>');
|
|
} else {
|
|
x += addDeviceAttribute("Popis", description);
|
|
}
|
|
|
|
// Attribute: Mesh Agent
|
|
var agentsStr = ["Neznámý", "Windows 32bit konzole", "Windows 64bit konzole", "Windows 32bit služba", "Windows 64bit služba", "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 konzole", "Windows MinCore služba", "NodeJS", "ARM-Linaro", "ARMv6l / ARMv7l", "ARMv8 64bit", "ARMv6l / ARMv7l / NoKVM", "Neznámý", "Neznámý", "FreeBSD x86-64"];
|
|
if ((node.agent != null) && (node.agent.id != null) && (node.agent.ver != null)) {
|
|
var str = '';
|
|
if (node.agent.id <= agentsStr.length) { str = agentsStr[node.agent.id]; } else { str = agentsStr[0]; }
|
|
if (node.agent.ver != 0) { str += ' v' + node.agent.ver; }
|
|
x += addDeviceAttribute("Mesh Agent", str);
|
|
}
|
|
|
|
// Attribute: Intel AMT
|
|
if (node.intelamt != null) {
|
|
var str = '';
|
|
var provisioningStates = { 0: nobreak("Neaktivováno (před)"), 1: nobreak("Neaktivováno"), 2: nobreak("Aktivováno") };
|
|
if (node.intelamt.ver != null && node.intelamt.state == null) { str += '<i>' + "Neznámý stav" + '</i>, v' + node.intelamt.ver; } else
|
|
|
|
if ((node.intelamt.ver == null) && (node.intelamt.state == 2)) { str += '<i>' + "Aktivováno" + '</i>'; }
|
|
else if ((node.intelamt.ver == null) || (node.intelamt.state == null)) { str += '<i>' + "Neznámý stav & verze" + '</i>'; }
|
|
else {
|
|
str += provisioningStates[node.intelamt.state];
|
|
if ((node.intelamt.state == 2) && node.intelamt.flags) { if (node.intelamt.flags & 2) { str += ' <span title=\"' + "Intel AMT je aktivováno v režimu uživatele" + '\">' + "CCM" + '</span>'; } else if (node.intelamt.flags & 4) { str += ' <span title=\"' + "Intel AMT je aktivováno v režimu správce" + '\">' + "ACM" + '</span>'; } }
|
|
str += (', v' + node.intelamt.ver);
|
|
}
|
|
|
|
if (node.intelamt.tls == 1) { str += ', <span title=\"' + "Intel AMT je nastaveno s TLS bezpečností" + '\">' + "TLS" + '</span>'; }
|
|
if (node.intelamt.state == 2) {
|
|
if (node.intelamt.user == null || node.intelamt.user == '') {
|
|
if ((meshrights & 4) != 0) {
|
|
str += ', <i style=color:#FF0000;cursor:pointer title=\"' + "Upravit Intel® AMT pověření" + '\" onclick=editDeviceAmtSettings("' + node._id + '")>' + "Žádné přihlašovací údaje" + '</i>';
|
|
} else {
|
|
str += ', <i style=color:#FF0000>' + "Žádné přihlašovací údaje" + '</i>';
|
|
}
|
|
}
|
|
str += ' ';
|
|
if ((meshrights & 4) != 0) {
|
|
str += '<img src=images/link4.png height=10 width=10 title=\"' + "Upravit Intel® AMT pověření" + '\" style=cursor:pointer onclick=editDeviceAmtSettings("' + node._id + '")>';
|
|
}
|
|
}
|
|
|
|
var meName = '<span title=\"Intel® Manageability Engine\">' + "Intel® ME" + '<span>';
|
|
if (typeof node.intelamt.sku == 'number') {
|
|
if ((node.intelamt.sku & 8) != 0) { meName = '<span title=\"' + "Intel® Active Management Technology" + '\">' + "Intel® AMT" + '<span>'; }
|
|
else if ((node.intelamt.sku & 16) != 0) { meName = '<span title=\"' + "Intel® Standard Manageability" + '\">' + "Intel® SM" + '<span>'; }
|
|
}
|
|
x += addDeviceAttribute(meName, str);
|
|
}
|
|
|
|
if (mesh.mtype == 2) {
|
|
// Attribute: Mesh Agent Tag
|
|
if ((node.agent != null) && (node.agent.tag != null)) {
|
|
var tag = EscapeHtml(node.agent.tag);
|
|
if (tag.startsWith('mailto:')) { tag = '<a href="' + tag + '">' + tag.substring(7) + '</a>'; }
|
|
x += addDeviceAttribute("Značka agenta", tag);
|
|
}
|
|
} else {
|
|
// Attribute: Intel AMT Tag
|
|
if ((node.intelamt != null) && (node.intelamt.tag != null)) {
|
|
var tag = EscapeHtml(node.intelamt.tag);
|
|
if (tag.startsWith('mailto:')) { tag = '<a href="' + tag + '">' + tag.substring(7) + '</a>'; }
|
|
x += addDeviceAttribute("Intel® AMT značka", tag);
|
|
}
|
|
}
|
|
|
|
// Attribute: Intel AMT
|
|
//if (node.intelamt && node.intelamt.user) { x += addDeviceAttribute('Intel® AMT', node.intelamt.user); }
|
|
|
|
// Operating system description
|
|
if (node.osdesc) { x += addDeviceAttribute("Operační systém", node.osdesc); }
|
|
|
|
// Antivirus
|
|
if (node.av && node.av.length > 0) {
|
|
var y = [];
|
|
for (var i in node.av) {
|
|
if (node.av[i].product) {
|
|
var avx = EscapeHtml(node.av[i].product);
|
|
if (node.av[i].enabled !== true) { avx += ' - <span style=color:red>' + "Zakázáno" + '</span>'; }
|
|
if (node.av[i].updated !== true) { avx += ' - <span style=color:red>' + "Zastaralý" + '</span>'; }
|
|
if ((node.av[i].enabled == true) && (node.av[i].updated == true)) { avx += ' - <span style=color:green>' + "OK" + '</span>'; }
|
|
y.push(avx);
|
|
}
|
|
}
|
|
x += addDeviceAttribute("Antivir", y.join('<br />'));
|
|
}
|
|
|
|
// Active Users
|
|
if (node.users && node.conn && (node.users.length > 0) && (node.conn & 1)) { x += addDeviceAttribute(format("Aktivní uživatel{0}", ((node.users.length > 1)?'s':'')), node.users.join(', ')); }
|
|
|
|
// Attribute: Connectivity (Only show this if more than just the agent is connected).
|
|
var connectivity = node.conn;
|
|
if (connectivity && connectivity > 1) {
|
|
var cstate = [];
|
|
if ((node.conn & 1) != 0) cstate.push('<span title=\"' + "Agent je připojen a připraven." + '\">' + "Mesh Agent" + '</span>');
|
|
if ((node.conn & 2) != 0) cstate.push('<span title=\"' + "Intel® AMT CIRA je připojeno a připraveno k použití." + '\">' + "Intel® AMT CIRA" + '</span>');
|
|
else if ((node.conn & 4) != 0) cstate.push('<span title=\"' + "Intel® AMT je směrovatelný a připraven k použití." + '\">' + "Intel® AMT" + '</span>');
|
|
if ((node.conn & 8) != 0) cstate.push('<span title=\"' + "Mesh agent je dostupný pomocí přesměrování přes jiného agenta." + '\">' + "Mesh přesměrování" + '</span>');
|
|
if ((node.conn & 16) != 0) { cstate.push('<span title=\"' + "MQTT připojení na zařízení je aktivní." + '\">' + "MQTT" + '</span>'); }
|
|
x += addDeviceAttribute("Konektivita", cstate.join(', '));
|
|
}
|
|
|
|
// Node grouping tags
|
|
var groupingTags = '<i>' + "Nic" + '</i>';
|
|
if (node.tags != null) { groupingTags = ''; for (var i in node.tags) { groupingTags += '<span class="tagSpan">' + node.tags[i] + '</span>'; } }
|
|
if ((meshrights & 4) != 0) {
|
|
x += addDeviceAttribute('Tags', '<span onclick=showEditNodeValueDialog(3) style=cursor:pointer>' + groupingTags + ' <img class=hoverButton src="images/link5.png" /></span>');
|
|
} else {
|
|
x += addDeviceAttribute('Tags', groupingTags);
|
|
}
|
|
|
|
x += '</table><br />';
|
|
// Show action button, only show if we have permissions 4, 8, 64
|
|
if ((meshrights & 76) != 0) { x += '<input type=button value=\"' + "Akce" + '\" title=\"' + "Akce napájení" + '\" onclick=deviceActionFunction() />'; }
|
|
x += '<input type=button value=\"' + "Poznámky" + '\" title=\"' + "Zobrazit poznámky k tomuto zařízení" + '\" onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponent(node._id) + '") />';
|
|
x += '<input type=button value=\"' + "Log udalostí" + '\" title=\"' + "Napište událost pro toto zařízení" + '\" onclick=writeDeviceEvent("' + encodeURIComponent(node._id) + '") />';
|
|
//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() />'; }
|
|
QH('p10html', x);
|
|
|
|
// Show node last 7 days timeline
|
|
masterUpdate(256);
|
|
|
|
// Show bottom buttons
|
|
x = '<div class="p10html3right">';
|
|
if ((meshrights & 4) != 0) {
|
|
// TODO: Show change group only if there is another mesh of the same type.
|
|
x += ' <a href=# onclick=p10showChangeGroupDialog(["' + node._id + '"]) title=\"' + "Přesunout toto zařízení do jiné skupiny zařízení" + '\">' + "Změnit skupinu" + '</a>';
|
|
x += ' <a href=# onclick=p10showDeleteNodeDialog("' + node._id + '") title=\"' + "Odstranit toto zařízení" + '\">' + "Smazat zařízení" + '</a>';
|
|
}
|
|
x += '</div><div class="p10html3left">';
|
|
if (mesh.mtype == 2) x += '<a href=# onclick=p10showNodeNetInfoDialog("' + node._id + '") title=\"' + "Zobrazit informace o síťovém rozhraní zařízení" + '\">' + "Razhraní" + '</a> ';
|
|
if (xxmap != null) x += '<a href=# onclick=p10showNodeLocationDialog("' + node._id + '") title=\"' + "Zobrazit informace o umístění zařízení" + '\">' + "Umístění" + '</a> ';
|
|
if (((meshrights & 8) != 0) && (mesh.mtype == 2)) x += '<a href=# onclick=p10showMeshCmdDialog(1,"' + node._id + '") title=\"' + "Traffic router je použit k připojení zařízení prostřednictvím tohoto serveru" + '.\">' + "Router" + '</a> ';
|
|
|
|
// RDP link, show this link only of the remote machine is Windows.
|
|
if (((connectivity & 1) != 0) && (clickOnce == true) && (mesh.mtype == 2) && ((meshrights & 8) != 0)) {
|
|
if ((node.agent.id > 0) && (node.agent.id < 5)) { x += '<a href=# onclick=p10clickOnce("' + node._id + '","RDP2",3389) title=\"' + "Vyžaduje Microsoft ClickOnce podporu v prohlížeči" + '.\">' + "RDP" + '</a> '; }
|
|
if (node.agent.id > 4) {
|
|
x += '<a href=# onclick=p10clickOnce("' + node._id + '","PSSH",22) title=\"' + "Vyžaduje Microsoft ClickOnce podporu v prohlížeči." + '\">' + "Putty" + '</a> ';
|
|
x += '<a href=# onclick=p10clickOnce("' + node._id + '","WSCP",22) title=\"' + "Vyžaduje Microsoft ClickOnce podporu v prohlížeči." + '\">' + "WinSCP" + '</a> ';
|
|
}
|
|
}
|
|
|
|
// MQTT options
|
|
if ((meshrights == 0xFFFFFFFF) && (features & 0x00400000)) { x += '<a href=# onclick=p10showMqttLoginDialog("' + node._id + '") title=\"' + "Získat přihlašovací údaje MQTT pro toto zařízení." + '\">' + "MQTT přihlášení" + '</a> '; }
|
|
x += '</div><br>'
|
|
|
|
QH('p10html3', x);
|
|
|
|
// Set the node power state
|
|
var powerstate = PowerStateStr(node.state);
|
|
//if (node.state == 0) { powerstate = 'Unknown State'; }
|
|
if ((connectivity & 1) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "Agent připojen" + '\">' + "Agent připojen" + '</span>'; }
|
|
if ((connectivity & 2) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "Intel® AMT připojeno" + '\">' + "Intel® AMT připojeno" + '</span>'; }
|
|
else if ((connectivity & 4) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "Intel® AMT detekováno" + '\">' + "Intel® AMT detekováno" + '</span>'; }
|
|
if ((connectivity & 16) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "MQTT připojeno" + '\">' + "MQTT kanál připojen" + '</span>'; }
|
|
if ((powerstate == '') && node.lastconnect) { powerstate = '<span style=font-size:12px>' + "Naposledy spatřen:" + '<br />' + printDateTime(new Date(node.lastconnect)) + '</span>'; }
|
|
QH('MainComputerState', powerstate);
|
|
|
|
// Set the node icon
|
|
Q('MainComputerImage').setAttribute('src', 'images/icons256-' + node.icon + '-1.png');
|
|
Q('MainComputerImage').className = ((!node.conn) || (node.conn == 0)?'gray':'');
|
|
|
|
// Check if we have terminal and file access
|
|
var terminalAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 512) == 0));
|
|
var fileAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 1024) == 0));
|
|
var amtAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 2048) == 0));
|
|
|
|
// Setup/Refresh the desktop tab
|
|
if (terminalAccess) { setupTerminal(); }
|
|
if (fileAccess) { setupFiles(); }
|
|
var consoleRights = ((meshrights & 16) != 0);
|
|
if (consoleRights) { setupConsole(); } else { if (panel == 15) { panel = 10; } }
|
|
|
|
// Show or hide the tabs
|
|
// mesh.mtype: 1 = Intel AMT only, 2 = Mesh Agent
|
|
// node.agent.caps (bitmask): 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console
|
|
QV('MainDevDesktop', (((mesh.mtype == 1) && ((typeof node.intelamt.sku !== 'number') || ((node.intelamt.sku & 8) != 0)))
|
|
|| ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0) || (node.intelamt && (node.intelamt.state == 2)))))
|
|
&& ((meshrights & 8) || (meshrights & 256))
|
|
);
|
|
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);
|
|
QV('MainDevFiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8) && fileAccess);
|
|
QV('MainDevAmt', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8) && amtAccess);
|
|
QV('MainDevConsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8));
|
|
QV('MainDevPlugins', false);
|
|
QV('p15uploadCore', (node.agent != null) && (node.agent.caps != null) && ((node.agent.caps & 16) != 0));
|
|
QH('p15coreName', ((node.agent != null) && (node.agent.core != null))?node.agent.core:'');
|
|
|
|
// Setup/Refresh Intel AMT tab
|
|
var amtFrameNode = Q('p14iframe').contentWindow.getCurrentMeshNode();
|
|
if ((amtFrameNode != null) && (amtFrameNode._id != currentNode._id)) { Q('p14iframe').contentWindow.disconnect(); }
|
|
var online = ((node.conn & 6) != 0)?true:false; // If CIRA (2) or AMT (4) connected, enable Commander
|
|
Q('p14iframe').contentWindow.setConnectionState(online);
|
|
Q('p14iframe').contentWindow.setFrameHeight('650px');
|
|
Q('p14iframe').contentWindow.setAuthCallback(updateAmtCredentials);
|
|
|
|
// Display "action" button on desktop/terminal/files
|
|
QV('deskActionsBtn', (meshrights & 72) != 0); // 72 = Wake-up + Remote Control permissions
|
|
QV('termActionsBtn', (meshrights & 72) != 0);
|
|
QV('filesActionsBtn', (meshrights & 72) != 0);
|
|
|
|
// Request the power timeline
|
|
if ((powerTimelineNode != currentNode._id) && (powerTimelineReq != currentNode._id)) {
|
|
QH('p10html2', '');
|
|
powerTimelineReq = currentNode._id;
|
|
meshserver.send({ action: 'powertimeline', nodeid: currentNode._id });
|
|
meshserver.send({ action: 'lastconnect', nodeid: currentNode._id });
|
|
meshserver.send({ action: 'getsysinfo', nodeid: currentNode._id });
|
|
QH('p17info', '');
|
|
}
|
|
|
|
// Reset the desktop tools
|
|
QV('DeskTools', false);
|
|
showDeskToolsProcesses();
|
|
|
|
// Ask for device events
|
|
refreshDeviceEvents();
|
|
|
|
// Update the web page title
|
|
if ((currentNode) && (xxcurrentView >= 10) && (xxcurrentView < 20)) {
|
|
document.title = decodeURIComponent('{{{extitle}}}') + ' - ' + currentNode.name + ' - ' + mesh.name;
|
|
} else {
|
|
document.title = decodeURIComponent('{{{extitle}}}');
|
|
}
|
|
|
|
// Clear user consent status if present
|
|
p11clearConsoleMsg();
|
|
p12clearConsoleMsg();
|
|
p13clearConsoleMsg();
|
|
|
|
// Device refresh plugin handler
|
|
if (pluginHandler != null) {
|
|
pluginHandler.callHook('onDeviceRefreshEnd', nodeid, panel, refresh, event);
|
|
var lastTab = getstore('_curPluginPage', null);
|
|
if (lastTab != null) pluginHandler.callPluginPage(lastTab, Q('p19ph-' + lastTab));
|
|
}
|
|
}
|
|
setupDesktop(); // Always refresh the desktop, even if we are on the same device, we need to do some canvas switching.
|
|
if (!panel) panel = 10;
|
|
go(panel);
|
|
}
|
|
|
|
function writeDeviceEvent(nodeid) {
|
|
if (xxdialogMode) return;
|
|
setDialogMode(2, "Přidat událost zařízení", 3, writeDeviceEventEx, '<textarea id=d2devEvent style=background-color:#fcf3cf;width:100%;height:200px;resize:none;overflow-y:scroll></textarea><span style=font-size:10px>' + "Tím se přidá položka do tohoto logu událostí zařízení." + '<span>', nodeid);
|
|
}
|
|
|
|
function writeDeviceEventEx(buttons, tag) { meshserver.send({ action: 'setDeviceEvent', nodeid: decodeURIComponent(tag), msg: encodeURIComponent(Q('d2devEvent').value) }); }
|
|
|
|
function showNotes(readonly, noteid) {
|
|
if (xxdialogMode) return;
|
|
setDialogMode(2, "Poznámky", 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>' + "Poznámky pro skupinu zařízení si může prohlédnout nebo upravit jen jiný administrátor skupiny." + '<span>', noteid);
|
|
meshserver.send({ action: 'getNotes', id: decodeURIComponent(noteid) });
|
|
}
|
|
|
|
function showNotesEx(buttons, tag) { meshserver.send({ action: 'setNotes', id: decodeURIComponent(tag), notes: encodeURIComponent(Q('d2devNotes').value) }); }
|
|
|
|
function deviceChat(e) {
|
|
if (xxdialogMode) return;
|
|
var url = '/messenger?id=meshmessenger/' + encodeURIComponent(currentNode._id) + '/' + encodeURIComponent(userinfo._id) + '&title=' + currentNode.name;
|
|
if ((authCookie != null) && (authCookie != '')) { url += '&auth=' + authCookie; }
|
|
if (e && (e.shiftKey == true)) {
|
|
window.open(url, 'meshmessenger:' + currentNode._id);
|
|
} else {
|
|
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');
|
|
}
|
|
meshserver.send({ action: 'meshmessenger', nodeid: decodeURIComponent(currentNode._id) });
|
|
}
|
|
|
|
function deviceToggleBackground() {
|
|
if (xxdialogMode) return;
|
|
meshserver.send({ action: 'msg', type: 'deskBackground', nodeid: currentNode._id, op: 1 }); // Toggle desktop background image
|
|
}
|
|
|
|
function deviceUrlFunction() {
|
|
if (xxdialogMode) return;
|
|
setDialogMode(2, "Otevřít stránku na zařízení", 3, deviceUrlFunctionEx, '<input id=d2devurl placeholder="http://server.com" style=width:100%;overflow-y:scroll></input>');
|
|
Q('d2devurl').focus();
|
|
}
|
|
|
|
function deviceUrlFunctionEx() {
|
|
meshserver.send({ action: 'msg', type: 'openUrl', nodeid: currentNode._id, url: Q('d2devurl').value });
|
|
}
|
|
|
|
function deviceToastFunction() {
|
|
if (xxdialogMode) return;
|
|
setDialogMode(2, "Oznámení zařízení", 3, deviceToastFunctionEx, '<textarea id=d2devToast style=width:100%;height:80px;resize:none;overflow-y:scroll></textarea>');
|
|
Q('d2devToast').focus();
|
|
}
|
|
|
|
function deviceToastFunctionEx() {
|
|
meshserver.send({ action: 'toast', nodeids: [ currentNode._id ], title: 'MeshCentral', msg: Q('d2devToast').value });
|
|
}
|
|
|
|
function deviceActionFunction() {
|
|
if (xxdialogMode) return;
|
|
var meshrights = meshes[currentNode.meshid].links[userinfo._id].rights;
|
|
var x = "Vyber operaci na tomto zařízení." + '<br /><br />';
|
|
var y = '<select id=d2deviceop style=float:right;width:250px>';
|
|
if ((meshrights & 64) != 0) { y += '<option value=100>' + "Probudit" + '</option>'; } // Wake-up permission
|
|
if ((meshrights & 8) != 0) { y += '<option value=4>' + "Spánek" + '</option><option value=3>' + "Reset" + '</option><option value=2>' + "Vypnout" + '</option>'; } // Remote control permission
|
|
if ((currentNode.conn & 16) != 0) { y += '<option value=103>' + "Poslat MQTT zprávu" + '</option>'; }
|
|
if (((currentNode.conn & 1) != 0) && ((meshrights & 32768) != 0)) { y += '<option value=104>' + "Odinstalovat agenta" + '</option>'; }
|
|
y += '</select>';
|
|
x += addHtmlValue("Operace", y);
|
|
setDialogMode(2, "Akce zařízení", 3, deviceActionFunctionEx, x);
|
|
}
|
|
|
|
function deviceActionFunctionEx() {
|
|
var op = Q('d2deviceop').value;
|
|
if (op == 100) {
|
|
// Device wake
|
|
meshserver.send({ action: 'wakedevices', nodeids: [currentNode._id] });
|
|
} else if (op == 103) {
|
|
// Send MQTT Message
|
|
p10showSendMqttMsgDialog([currentNode._id]);
|
|
} else if (op == 104) {
|
|
// Uninstall agent
|
|
p10showSendUninstallAgentDialog([currentNode._id]);
|
|
} else {
|
|
// Power operation
|
|
meshserver.send({ action: 'poweraction', nodeids: [ currentNode._id ], actiontype: parseInt(op) });
|
|
}
|
|
}
|
|
|
|
// Called when MeshCommander needs new credentials or updated credentials.
|
|
function updateAmtCredentials(forceDialog) {
|
|
var node = getNodeFromId(currentNode._id);
|
|
if ((forceDialog == true) || (node.intelamt.user == null) || (node.intelamt.user == '')) {
|
|
editDeviceAmtSettings(currentNode._id, updateAmtCredentialsEx);
|
|
} else {
|
|
Q('p14iframe').contentWindow.connectButtonfunctionEx();
|
|
}
|
|
}
|
|
|
|
function updateAmtCredentialsEx(button, tag) {
|
|
Q('p14iframe').contentWindow.connectButtonfunctionEx();
|
|
}
|
|
|
|
// Look to see if we need to update the device timeline
|
|
function updateDeviceTimeline() {
|
|
if ((meshserver.State != 2) || (powerTimelineNode == null) || (powerTimelineUpdate == null) || (currentNode == null)) return;
|
|
if ((powerTimelineNode == powerTimelineReq) && (currentNode._id == powerTimelineNode) && (powerTimelineUpdate < Date.now())) {
|
|
powerTimelineUpdate = null;
|
|
meshserver.send({ action: 'powertimeline', nodeid: currentNode._id });
|
|
meshserver.send({ action: 'lastconnect', nodeid: currentNode._id });
|
|
}
|
|
}
|
|
|
|
// Draw device power bars. The bars are 766px wide.
|
|
function drawDeviceTimeline() {
|
|
if ((currentNode == null) || (xxcurrentView < 10) || (xxcurrentView > 19)) return;
|
|
var timeline = null, now = Date.now();
|
|
if (currentNode._id == powerTimelineNode) { timeline = powerTimeline; }
|
|
|
|
// Calculate when the timeline starts
|
|
var d = new Date();
|
|
d.setHours(0, 0, 0, 0);
|
|
d = new Date(d.getTime() - (1000 * 60 * 60 * 24 * 6));
|
|
var timelineStart = d.getTime();
|
|
|
|
// De-compact the timeline
|
|
var timeline2 = [];
|
|
if (timeline != null && timeline.length > 1) {
|
|
timeline2.push([ 0, timeline[1], timeline[0] ]); // Start, End, Power
|
|
var ct = timeline[1];
|
|
for (var i = 2; i < timeline.length; i += 2) {
|
|
var power = timeline[i], dt = now;
|
|
if (timeline.length > (i + 1)) { dt = timeline[i + 1]; }
|
|
timeline2.push([ ct, ct + dt, power ]); // Start, End, Power
|
|
ct = ct + dt;
|
|
}
|
|
}
|
|
|
|
// Draw the timeline
|
|
var x = '', count = 1, date = new Date();
|
|
var totalWidth = Q('masthead').offsetWidth - (160 + 9 + 9 + 14); // Compute the total width of the power bar
|
|
date.setHours(0, 0, 0, 0);
|
|
for (var i = 0; i < 7; i++) {
|
|
var datavalue = '', start = date.getTime(), end = start + (1000 * 60 * 60 * 24);
|
|
for (var j in timeline2) {
|
|
var block = timeline2[j];
|
|
if (isTimeBlockInside(start, end, block[0], block[1]) == true) {
|
|
var ts = Math.max(start, block[0]);
|
|
var te = Math.min(Math.min(end, block[1]), now);
|
|
var width = Math.round(((te - ts) * totalWidth) / 86400000);
|
|
if (width > 0) {
|
|
var title = format('{0} from {1} to {2}.', powerStateStrings2[block[2]], printTime(new Date(ts)), printTime(new Date(te)));
|
|
datavalue += '<div class="pwState ' + powerColor(block[2]) + '" title="' + title + '" style="width:' + width + 'px;"></div>';
|
|
}
|
|
}
|
|
}
|
|
x += '<tr class=' + (((count % 2) == 0)?'altBack':'') + '><td><div> ' + printDate(date) + '<div></div></div></td><td><div>' + datavalue + '</div></td></tr>';
|
|
++count;
|
|
date = new Date(date.getTime() - (1000 * 60 * 60 * 24)); // Substract one day
|
|
}
|
|
QH('p10html2', '<table cellpadding=2 cellspacing=0><thead><tr style=><th scope=col style=text-align:center;width:150px>' + "Den" + '</th><th scope=col style=text-align:center><a download href="devicepowerevents.ashx?id=' + currentNode._id + '" onclick="setDialogMode(0)"><img title=\"' + "Stáhnout události napájení" + '\" src="images/link4.png" /></a>' + "7 denní statistika provozu" + '</th></tr></thead><tbody>' + x + '</tbody></table>');
|
|
}
|
|
|
|
// Return a color for the given power state
|
|
function powerColor(x) { if (x < powerColorTable.length) { return powerColorTable[x]; } return 'pwsYellow'; }
|
|
|
|
// Return true if the time block is visible within the start/end period
|
|
function isTimeBlockInside(start, end, blockStart, blockEnd) {
|
|
if ((blockStart < start) && (blockEnd > end)) return true; // Block is wider than timespan
|
|
if ((blockStart > start) && (blockStart < end)) return true;
|
|
if ((blockEnd > start) && (blockEnd < end)) return true;
|
|
return false;
|
|
}
|
|
|
|
function addDeviceAttribute(name, value) { return '<tr><td class=style7>' + name + '</td><td class=style9>' + value + '</td></tr>'; }
|
|
|
|
function editDeviceAmtSettings(nodeid, func, arg) {
|
|
if (xxdialogMode) return;
|
|
var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid);
|
|
if ((meshrights & 4) == 0) return;
|
|
x += addHtmlValue("Uživatel", '<input id=dp10username style=width:230px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
|
|
x += addHtmlValue("Heslo", '<input id=dp10password type=password style=width:230px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
|
|
x += addHtmlValue("Bezpečnost", '<select id=dp10tls style=width:236px><option value=0>' + "Žádné TLS" + '</option><option value=1>' + "TLS vyžadováno" + '</option></select>');
|
|
if ((node.intelamt.user != null) && (node.intelamt.user != '')) { buttons = 7; }
|
|
setDialogMode(2, "Upravit Intel® AMT pověření", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func, arg: arg });
|
|
if ((node.intelamt.user != null) && (node.intelamt.user != '')) { Q('dp10username').value = node.intelamt.user; } else { Q('dp10username').value = 'admin'; }
|
|
Q('dp10tls').value = node.intelamt.tls;
|
|
validateDeviceAmtSettings();
|
|
}
|
|
|
|
function validateDeviceAmtSettings() {
|
|
QE('idx_dlgOkButton', passwordcheck(Q('dp10password').value));
|
|
}
|
|
|
|
function editDeviceAmtSettingsEx(button, tag) {
|
|
if (button == 2) {
|
|
// Delete button pressed, remove credentials
|
|
meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: '', pass: '' } });
|
|
} else {
|
|
// Change Intel AMT credentials
|
|
var amtuser = Q('dp10username').value;
|
|
if (amtuser == '') amtuser = 'admin';
|
|
var amtpass = Q('dp10password').value;
|
|
if (amtpass == '') amtuser = '';
|
|
meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: amtuser, pass: amtpass, tls: Q('dp10tls').value } });
|
|
tag.node.intelamt.user = amtuser;
|
|
tag.node.intelamt.tls = Q('dp10tls').value;
|
|
if (tag.func) { setTimeout(function () { tag.func(null, tag.arg); }, 300); }
|
|
}
|
|
}
|
|
|
|
function p10showSendMqttMsgDialog(nodeids) {
|
|
if (xxdialogMode) return false;
|
|
var x = addHtmlValue("Téma", '<input id=dp2topic style=width:230px maxlength=64 onchange=p10validateSendMqttMsgDialog() onkeyup=p10validateSendMqttMsgDialog(event,1) />');
|
|
x += addHtmlValue("Zpráva", '<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>');
|
|
setDialogMode(2, "Poslat MQTT zprávu", 3, p10showSendMqttMsgDialogEx, x, nodeids);
|
|
p10validateSendMqttMsgDialog();
|
|
Q('dp2topic').focus();
|
|
return false;
|
|
}
|
|
|
|
function p10validateSendMqttMsgDialog() {
|
|
QE('idx_dlgOkButton', (Q('dp2topic').value.length > 0) && (Q('dp2msg').value.length > 0));
|
|
}
|
|
|
|
function p10showSendMqttMsgDialogEx(b, nodeids) {
|
|
meshserver.send({ action: 'sendmqttmsg', nodeids: nodeids, topic: Q('dp2topic').value, msg: Q('dp2msg').value });
|
|
}
|
|
|
|
function p10showSendUninstallAgentDialog(nodeids) {
|
|
if (xxdialogMode) return false;
|
|
var x = '';
|
|
if (nodeids.length > 1) { x = format("Opravdu odinstalovat vybraných {0} agentů?", nodeids.length); } else { x = "Opravdu odinstalovat vybraného agenta?"; }
|
|
x += '<br /><br />';
|
|
if (nodeids.length > 1) { x += "To neodstraní zařízení ze serveru, ale zařízení se již nebudou moci připojit k serveru. Veškerý vzdálený přístup k zařízením bude ztracen. Aby tento příkaz fungoval, musí být připojena zařízení."; } else { x += "Toto zařízení ze serveru neodstraní, ale zařízení se již nebude moci připojit k serveru. Veškerý vzdálený přístup k zařízení bude ztracen. Aby mohl tento příkaz fungovat, musí být zařízení připojeno."; }
|
|
x += '<br /><br /><label style=color:red><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "Potvrdit" + '</label>';
|
|
setDialogMode(2, "Odinstalovat agenta", 3, p10showSendUninstallAgentDialogEx, x, nodeids);
|
|
p10validateSendUninstallAgentDialog();
|
|
return false;
|
|
}
|
|
|
|
function p10validateSendUninstallAgentDialog() { QE('idx_dlgOkButton', Q('p10check').checked); }
|
|
function p10showSendUninstallAgentDialogEx(b, nodeids) { meshserver.send({ action: 'uninstallagent', nodeids: nodeids }); }
|
|
|
|
function p10showChangeGroupDialog(nodeids) {
|
|
if (xxdialogMode) return false;
|
|
var targetMeshId = null;
|
|
if (nodeids.length == 1) { try { targetMeshId = meshes[getNodeFromId(nodeids[0])]._id; } catch (ex) { } }
|
|
|
|
// List all available alternative groups
|
|
var y = '<select id=p10newGroup style=width:236px>', count = 0;
|
|
for (var i in meshes) {
|
|
var meshrights = meshes[i].links[userinfo._id].rights;
|
|
if ((meshes[i]._id != targetMeshId) && (meshrights & 4)) { count++; y += '<option value=\'' + meshes[i]._id + '\'>' + meshes[i].name + '</option>'; }
|
|
}
|
|
y += '</select>';
|
|
|
|
if (count > 0) {
|
|
var x = (nodeids.length == 1) ? ("Vybrat novou skupinu pro toto zařízení" + '<br /><br />') : ("Vybrat novou skupinu pro vybraná zařízení" + '<br /><br />');
|
|
x += addHtmlValue("Nová skupina zařízení", y);
|
|
setDialogMode(2, "Změnit skupinu", 3, p10showChangeGroupDialogEx, x, nodeids);
|
|
} else {
|
|
setDialogMode(2, "Změnit skupinu", 1, null, "Žádná další podobná skupina zařízení.");
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function p10showChangeGroupDialogEx(b, nodeids) {
|
|
meshserver.send({ action: 'changeDeviceMesh', nodeids: nodeids, meshid: Q('p10newGroup').value });
|
|
}
|
|
|
|
function p10showDeleteNodeDialog(nodeid) {
|
|
if (xxdialogMode) return false;
|
|
var x = format("Opravdu smazat nód {0}?", EscapeHtml(currentNode.name)) + '<br /><br /><label><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "Potvrdit" + '</label>';
|
|
setDialogMode(2, "Smazat nod", 3, p10showDeleteNodeDialogEx, x, nodeid);
|
|
p10validateDeleteNodeDialog();
|
|
return false;
|
|
}
|
|
|
|
function p10validateDeleteNodeDialog() {
|
|
QE('idx_dlgOkButton', Q('p10check').checked);
|
|
}
|
|
|
|
function p10showDeleteNodeDialogEx(buttons, nodeid) {
|
|
meshserver.send({ action: 'removedevices', nodeids: [ nodeid ] });
|
|
}
|
|
|
|
function p10clickOnce(nodeid, protocol, port) {
|
|
meshserver.send({ action: 'getcookie', nodeid: nodeid, tcpport: port, tag: 'clickonce', protocol: protocol });
|
|
return false;
|
|
}
|
|
|
|
// Show current location
|
|
var d2map = null;
|
|
function p10showNodeLocationDialog() {
|
|
if ((xxdialogMode != null) && (xxdialogTag == '@xxmap')) { setDialogMode(0); } else { if (xxdialogMode) return false; }
|
|
var markers = [], types = ['iploc', 'wifiloc', 'gpsloc', 'userloc'], boundingBox = null;
|
|
|
|
for (var loctype in types) {
|
|
if (currentNode[types[loctype]] != null) {
|
|
var loc = currentNode[types[loctype]].split(','), lat = parseFloat(loc[0]), lon = parseFloat(loc[1]);
|
|
if ((lat < 90) && (lat > -90) && (lon < 180) && (lon > -180)) { // Check valid lat/lon
|
|
var deviceMark = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.fromLonLat([lon, lat])) });
|
|
deviceMark.setStyle(markerStyle(currentNode, parseInt(loctype) + 1));
|
|
markers.push(deviceMark);
|
|
|
|
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; } }
|
|
}
|
|
}
|
|
}
|
|
|
|
// Setup the device mark layer
|
|
var vectorSource = new ol.source.Vector({ features: markers });
|
|
var vectorLayer = new ol.layer.Vector({ source: vectorSource });
|
|
|
|
//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>';
|
|
var x = '<div id=d2map style=width:100%;height:300px></div>';
|
|
setDialogMode(2, "Umístění zařízení", 1, null, x, '@xxmap');
|
|
|
|
var clng = 0, clat = 0, zoom = 8;
|
|
if (boundingBox != null) {
|
|
var clat = (boundingBox[0] + boundingBox[2]) / 2;
|
|
var clng = (boundingBox[1] + boundingBox[3]) / 2;
|
|
var cscale = Math.max(Math.abs(boundingBox[0] - boundingBox[2]), Math.abs(boundingBox[1] - boundingBox[3]));
|
|
var i = 360, zoom = -2;
|
|
while (i > cscale) { zoom++; i = i / 2; }
|
|
}
|
|
|
|
if (markers.length == 1) { zoom = 8; }
|
|
|
|
// Setup the map
|
|
d2map = new ol.Map({
|
|
target: 'd2map',
|
|
interactions: ol.interaction.defaults({dragPan:false, mouseWheelZoom:false}),
|
|
layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), vectorLayer ],
|
|
view: new ol.View({ center: ol.proj.fromLonLat([clng, clat]), zoom: zoom })
|
|
});
|
|
return false;
|
|
}
|
|
|
|
// Show network interfaces
|
|
function p10showNodeNetInfoDialog() {
|
|
if (xxdialogMode) return false;
|
|
setDialogMode(2, "Síťové rozhraní", 1, null, '<div id=d2netinfo>' + "Nahrávání..." + '</div>', 'if' + currentNode._id );
|
|
meshserver.send({ action: 'getnetworkinfo', nodeid: currentNode._id });
|
|
return false;
|
|
}
|
|
|
|
// Show MeshCentral Router dialog
|
|
function p10showMeshRouterDialog() {
|
|
if (xxdialogMode) return;
|
|
var x = '<div>' + "MeshCentral Router je Windows nástroj pro přemapování portů. Múžete si například přesměrovat vzdálené RDP pomocí tohoto serveru. " + '</div><br />';
|
|
x += addHtmlValue('Win32 Executable', '<a style=cursor:pointer download href="meshagents?meshaction=winrouter" onclick="setDialogMode(0)">MeshCentralRouter.exe</a>');
|
|
setDialogMode(2, "MeshCentral Router", 1, null, x, 'fileDownload');
|
|
}
|
|
|
|
// Request MQTT login credentials
|
|
function p10showMqttLoginDialog(nodeid) { meshserver.send({ action: 'getmqttlogin', nodeid: nodeid }); }
|
|
|
|
// Show MeshCmd dialog
|
|
function p10showMeshCmdDialog(mode, nodeid) {
|
|
if (xxdialogMode) return;
|
|
var y = '<select id=aginsSelect onclick=meshCmdOsClick() style=width:236px>';
|
|
y += '<option value=3>' + "Windows (32bit)" + '</option>';
|
|
y += '<option value=4>' + "Windows (64bit)" + '</option>';
|
|
y += '<option value=5>' + "Linux x86 (32bit)" + '</option>';
|
|
y += '<option value=6>' + "Linux x86 (64bit)" + '</option>';
|
|
y += '<option value=16>' + "MacOS (64bit)" + '</option>';
|
|
y += '<option value=25>' + "Linux ARM, Raspberry Pi (32bit)" + '</option>';
|
|
y += '</select>';
|
|
|
|
var x = '';
|
|
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 />'; }
|
|
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 />'; }
|
|
x += addHtmlValue('Operating System', y);
|
|
x += addHtmlValue('MeshCmd', '<a id=meshcmddownloadid href="meshagents?meshcmd=3" download></a>');
|
|
if (mode == 0) { x += addHtmlValue('Action File', '<a href="meshagents?meshaction=generic" download>MeshAction (.txt)</a>'); }
|
|
if (mode == 1) { x += addHtmlValue('Action File', '<a href="meshagents?meshaction=route&nodeid=' + nodeid + '" download>MeshAction (.txt)</a>'); }
|
|
x += '</div>';
|
|
setDialogMode(2, [ "Stáhnout MeshCmd", "Síťový router" ][mode], 9, null, x, 'fileDownload');
|
|
meshCmdOsClick();
|
|
}
|
|
|
|
function meshCmdOsClick() {
|
|
var os = Q('aginsSelect').value, osn = '', osurl = '';
|
|
//Q('meshcmddownloadid').href = 'meshagents?meshcmd=' + os;
|
|
if (os == 3) { osn = 'MeshCmd (Win32 executable)'; }
|
|
if (os == 4) { osn = 'MeshCmd (Win64 executable)'; }
|
|
if (os == 5) { osn = 'MeshCmd (Linux x86, 32bit)'; }
|
|
if (os == 6) { osn = 'MeshCmd (Linux x86, 64bit)'; }
|
|
if (os == 16) { osn = 'MeshCmd (MacOS, 64bit)'; }
|
|
if (os == 25) { osn = 'MeshCmd (Linux ARM, 32bit)'; }
|
|
QH('meshcmddownloadid', osn);
|
|
Q('meshcmddownloadid').setAttribute('href', 'meshagents?meshcmd=' + os);
|
|
}
|
|
|
|
function p10showiconselector() {
|
|
if (xxdialogMode) return;
|
|
var mesh = meshes[currentNode.meshid];
|
|
var meshrights = mesh.links[userinfo._id].rights;
|
|
if ((meshrights & 4) == 0) return;
|
|
|
|
var x = '<br><div style=display:inline-block;width:40px></div>';
|
|
x += '<div tabindex=0 style=display:inline-block class=i1 onclick=p10setIcon(1) onkeypress="if (event.key==\'Enter\') p10setIcon(1)"></div>';
|
|
x += '<div tabindex=0 style=display:inline-block class=i2 onclick=p10setIcon(2) onkeypress="if (event.key==\'Enter\') p10setIcon(2)"></div>';
|
|
x += '<div tabindex=0 style=display:inline-block class=i3 onclick=p10setIcon(3) onkeypress="if (event.key==\'Enter\') p10setIcon(3)"></div>';
|
|
x += '<div tabindex=0 style=display:inline-block class=i4 onclick=p10setIcon(4) onkeypress="if (event.key==\'Enter\') p10setIcon(4)"></div>';
|
|
x += '<div tabindex=0 style=display:inline-block class=i5 onclick=p10setIcon(5) onkeypress="if (event.key==\'Enter\') p10setIcon(5)"></div>';
|
|
x += '<div tabindex=0 style=display:inline-block class=i6 onclick=p10setIcon(6) onkeypress="if (event.key==\'Enter\') p10setIcon(6)"></div><br><br>';
|
|
setDialogMode(2, "Výběr ikony", 0, null, x);
|
|
QV('id_dialogclose', true);
|
|
}
|
|
|
|
function p10setIcon(icon) {
|
|
setDialogMode(0);
|
|
meshserver.send({ action: 'changedevice', nodeid: currentNode._id, icon: icon });
|
|
}
|
|
|
|
var showEditNodeValueDialog_modes = ["Název zařízení", "Hostname", "Popis", "Tagy"];
|
|
var showEditNodeValueDialog_modes2 = ['name', 'host', 'desc', 'tags'];
|
|
var showEditNodeValueDialog_modes3 = ['', '', '', "Značka1, Značka2, Značka"];
|
|
function showEditNodeValueDialog(mode) {
|
|
if (xxdialogMode) return;
|
|
var x = addHtmlValue(showEditNodeValueDialog_modes[mode], '<input id=dp10devicevalue maxlength=64 placeholder="' + showEditNodeValueDialog_modes3[mode] + '" onchange=p10editdevicevalueValidate(' + mode + ',event) onkeyup=p10editdevicevalueValidate(' + mode + ',event) />');
|
|
setDialogMode(2, "Upravit zařízení", 3, showEditNodeValueDialogEx, x, mode);
|
|
var v = currentNode[showEditNodeValueDialog_modes2[mode]];
|
|
if (v == null) v = '';
|
|
if (Array.isArray(v)) { v = v.join(', '); }
|
|
Q('dp10devicevalue').value = v;
|
|
p10editdevicevalueValidate();
|
|
Q('dp10devicevalue').focus();
|
|
}
|
|
|
|
function showEditNodeValueDialogEx(button, mode) {
|
|
var x = { action: 'changedevice', nodeid: currentNode._id };
|
|
x[showEditNodeValueDialog_modes2[mode]] = Q('dp10devicevalue').value;
|
|
meshserver.send(x);
|
|
}
|
|
|
|
function p10editdevicevalueValidate(mode, e) {
|
|
var x = ((mode > 1) || (Q('dp10devicevalue').value.length > 0));
|
|
QE('idx_dlgOkButton', x);
|
|
if ((e != null) && (x == true) && (e.keyCode == 13)) { dialogclose(1); }
|
|
}
|
|
|
|
//
|
|
// DESKTOP
|
|
//
|
|
|
|
var desktopNode;
|
|
function setupDesktop() {
|
|
// Setup the remote desktop
|
|
if ((desktopNode != currentNode) && (desktop != null)) { desktop.Stop(); desktopNode = null; desktop = null; }
|
|
|
|
// If the device desktop is already connected in multi-desktop, use that.
|
|
if ((desktopNode != currentNode) || (desktop == null)) {
|
|
var xdesk = multiDesktop[currentNode._id];
|
|
if (xdesk != null) {
|
|
// This device already has a canvas, use it.
|
|
QH('DeskParent', '');
|
|
var c = xdesk.m.CanvasId;
|
|
c.setAttribute('id', 'Desk');
|
|
c.setAttribute('onmousedown', 'dmousedown(event)');
|
|
c.setAttribute('onmouseup', 'dmouseup(event)');
|
|
c.setAttribute('onmousemove', 'dmousemove(event)');
|
|
c.removeAttribute('onclick');
|
|
Q('DeskParent').appendChild(c);
|
|
desktop = xdesk;
|
|
if (desktop.m.SendCompressionLevel) { desktop.m.SendCompressionLevel(1, desktopsettings.quality, desktopsettings.scaling, desktopsettings.framerate); }
|
|
desktop.onStateChanged = onDesktopStateChange;
|
|
desktopNode = currentNode;
|
|
onDesktopStateChange(desktop, desktop.State);
|
|
delete multiDesktop[currentNode._id];
|
|
} else {
|
|
// Device is not already connected, just setup a blank canvas
|
|
QH('DeskParent', '<canvas id=Desk oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></canvas>');
|
|
desktopNode = currentNode;
|
|
}
|
|
// Setup the mouse wheel
|
|
Q('Desk').addEventListener('DOMMouseScroll', function (e) { return dmousewheel(e); });
|
|
Q('Desk').addEventListener('mousewheel', function (e) { return dmousewheel(e); });
|
|
}
|
|
desktopNode = currentNode;
|
|
updateDesktopButtons();
|
|
deskAdjust();
|
|
|
|
// On some browsers like IE, we can't save screen shots. Hide the scheenshot/capture buttons.
|
|
if (!Q('Desk')['toBlob']) { QV('deskSaveBtn', false); }
|
|
}
|
|
|
|
// Show and enable the right buttons
|
|
function updateDesktopButtons() {
|
|
var mesh = meshes[currentNode.meshid];
|
|
var deskState = 0;
|
|
if (desktop != null) { deskState = desktop.State; }
|
|
var meshrights = mesh.links[userinfo._id].rights;
|
|
|
|
// Show the right buttons
|
|
QV('disconnectbutton1span', (deskState != 0));
|
|
QV('connectbutton1span', (deskState == 0) && ((meshrights & 8) || (meshrights & 256)) && (mesh.mtype == 2) && (currentNode.agent.caps & 1));
|
|
QV('connectbutton1hspan',
|
|
(deskState == 0) &&
|
|
(meshrights & 8) &&
|
|
((mesh.mtype == 1) ||
|
|
((currentNode.intelamt != null) &&
|
|
(currentNode.intelamt.state == 2) &&
|
|
(currentNode.intelamt.ver != null) &&
|
|
(typeof currentNode.intelamt.sku == 'number') &&
|
|
((currentNode.intelamt.sku & 8) != 0))
|
|
)
|
|
);
|
|
|
|
// Show the right settings
|
|
QV('d7amtkvm', (currentNode.intelamt != null && ((currentNode.intelamt.ver != null) || (mesh.mtype == 1))) && ((deskState == 0) || (desktop.contype == 2)));
|
|
QV('d7meshkvm', (webRtcDesktop) || ((mesh.mtype == 2) && (currentNode.agent.caps & 1) && ((deskState == false) || (desktop.contype == 1))));
|
|
|
|
// Enable buttons
|
|
var inputAllowed = (meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) == 0));
|
|
var online = ((currentNode.conn & 1) != 0); // If Agent (1) connected, enable remote desktop
|
|
QE('connectbutton1', online);
|
|
var hwonline = ((currentNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal
|
|
QE('connectbutton1h', hwonline);
|
|
QE('deskSaveBtn', deskState == 3);
|
|
QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (deskState != 0) && (desktopsettings.showfocus));
|
|
QV('DeskClip', (currentNode.agent) && (currentNode.agent.id != 11) && (currentNode.agent.id != 16) && ((desktop == null) || (desktop.contype != 2))); // Clipboard not supported on MacOS
|
|
QE('DeskClip', deskState == 3);
|
|
QE('DeskType', deskState == 3);
|
|
QV('DeskWD', inputAllowed);
|
|
QE('DeskWD', deskState == 3);
|
|
QV('deskkeys', inputAllowed);
|
|
QE('deskkeys', deskState == 3);
|
|
|
|
// Display this only if we have Chat & Notify permissions
|
|
QV('DeskChatButton', ((meshrights & 16384) != 0) && (browserfullscreen == false) && (inputAllowed) && (mesh.mtype == 2) && online);
|
|
QV('DeskNotifyButton', ((meshrights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && (currentNode.agent.id < 5) && (inputAllowed) && (mesh.mtype == 2) && online);
|
|
|
|
QV('DeskToolsButton', (inputAllowed) && (mesh.mtype == 2) && online);
|
|
QV('DeskOpenWebButton', (browserfullscreen == false) && (inputAllowed) && (mesh.mtype == 2) && online);
|
|
QV('DeskBackgroundButton', (deskState == 3) && (desktop.contype == 1) && (mesh.mtype == 2) && (currentNode.agent.id != 11) && (currentNode.agent.id != 16) && online);
|
|
QV('DeskControlSpan', inputAllowed)
|
|
QV('deskActionsBtn', (browserfullscreen == false));
|
|
QV('deskActionsSettings', (browserfullscreen == false));
|
|
if (meshrights & 8) { Q('DeskControl').checked = (getstore('DeskControl', 1) == 1); } else { Q('DeskControl').checked = false; }
|
|
if (online == false) QV('DeskTools', false);
|
|
}
|
|
|
|
// Debug
|
|
var autoConnectDesktopTimer = null;
|
|
function autoConnectDesktop(e) { if (autoConnectDesktopTimer == null) { autoConnectDesktopTimer = setInterval(connectDesktop, 100); } else { clearInterval(autoConnectDesktopTimer); autoConnectDesktopTimer = null; } }
|
|
|
|
function connectDesktop(e, contype) {
|
|
p11clearConsoleMsg();
|
|
if (desktop == null) {
|
|
desktopNode = currentNode;
|
|
if (contype == 2) {
|
|
// Setup the Intel AMT remote desktop
|
|
if ((desktopNode.intelamt.user == null) || (desktopNode.intelamt.user == '')) { editDeviceAmtSettings(desktopNode._id, connectDesktop, 2); return; }
|
|
desktop = CreateAmtRedirect(CreateAmtRemoteDesktop('Desk'), authCookie);
|
|
desktop.debugmode = debugmode;
|
|
desktop.onStateChanged = onDesktopStateChange;
|
|
desktop.m.bpp = (desktopsettings.encoding == 1 || desktopsettings.encoding == 3) ? 1 : 2;
|
|
desktop.m.useZRLE = (desktopsettings.encoding < 3);
|
|
desktop.m.localKeyMap = desktopsettings.localkeymap;
|
|
desktop.m.showmouse = desktopsettings.showmouse;
|
|
desktop.m.onScreenSizeChange = deskAdjust;
|
|
desktop.m.onKvmData = function (x) {
|
|
//console.log('onKvmData (' + x.length + '): ' + x);
|
|
// Send the presense probe only once if needed.
|
|
if (x.length == 0) { if (!desktop.m._sentPresence) { desktop.m._sentPresence = true; desktop.m.sendKvmData(JSON.stringify({ action: 'present', ver: 1 })); } return; }
|
|
var data = null;
|
|
try { data = JSON.parse(x); } catch (e) { }
|
|
if ((data != null) && (data.action != null)) {
|
|
if (data.action == 'restart') {
|
|
// Clear WebRTC channel
|
|
webRtcDesktopReset();
|
|
desktop.m.sendKvmData(JSON.stringify({ action: 'present', ver: 1 }));
|
|
} else if ((data.action == 'present') && (webRtcDesktop == null)) {
|
|
// Setup WebRTC channel
|
|
webRtcDesktop = { platform: data.platform };
|
|
var configuration = null; //{ "iceServers": [ { 'urls': 'stun:stun.services.mozilla.com' }, { 'urls': 'stun:stun.l.google.com:19302' } ] };
|
|
if (typeof RTCPeerConnection !== 'undefined') { webRtcDesktop.webrtc = new RTCPeerConnection(configuration); }
|
|
else if (typeof webkitRTCPeerConnection !== 'undefined') { webRtcDesktop.webrtc = new webkitRTCPeerConnection(configuration); }
|
|
|
|
webRtcDesktop.webchannel = webRtcDesktop.webrtc.createDataChannel("Datový kanál", {}); // { ordered: false, maxRetransmits: 2 }
|
|
webRtcDesktop.webchannel.onopen = function () {
|
|
// Switch to software KVM
|
|
//if (urlvars && urlvars['kvmdatatrace']) { console.log('WebRTC Data Channel Open'); }
|
|
console.log('WebRTC Data Channel Open');
|
|
Q('deskstatus').textContent = StatusStrs[desktop.State] + ", Soft-KVM";
|
|
desktop.m.hold(true);
|
|
webRtcDesktop.webRtcActive = true;
|
|
webRtcDesktop.softdesktop = CreateKvmDataChannel(webRtcDesktop.webchannel, CreateAgentRemoteDesktop('Desk', Q('id_mainarea')), desktop.m);
|
|
webRtcDesktop.softdesktop.m.setRotation(desktop.m.rotation);
|
|
webRtcDesktop.softdesktop.m.onScreenSizeChange = deskAdjust;
|
|
if (desktopsettings.quality) { webRtcDesktop.softdesktop.m.CompressionLevel = desktopsettings.quality; } // Number from 1 to 100. 50 or less is best.
|
|
if (desktopsettings.scaling) { webRtcDesktop.softdesktop.m.ScalingLevel = desktopsettings.scaling; }
|
|
webRtcDesktop.softdesktop.Start();
|
|
|
|
// Check if we can get remote file access
|
|
// ###BEGIN###{DesktopInbandFiles}
|
|
/*
|
|
QV('go24', true); // Files
|
|
downloadFile = null;
|
|
p24files = webRtcDesktop.softdesktop;
|
|
p24targetpath = '';
|
|
webRtcDesktop.softdesktop.onControlMsg = onFilesControlData;
|
|
webRtcDesktop.softdesktop.sendCtrlMsg(JSON.stringify({ action: 'ls', reqid: 1, path: '' })); // Ask for the root folder
|
|
*/
|
|
// ###END###{DesktopInbandFiles}
|
|
}
|
|
webRtcDesktop.webchannel.onclose = function (event) {
|
|
//if (urlvars['kvmdatatrace']) { console.log('WebRTC Data Channel Closed'); }
|
|
console.log('WebRTC Data Channel Closed');
|
|
webRtcDesktopReset();
|
|
}
|
|
webRtcDesktop.webrtc.onicecandidate = function (e) {
|
|
if (e.candidate == null) {
|
|
desktop.m.sendKvmData(JSON.stringify({ action: 'offer', ver: 1, sdp: webRtcDesktop.webrtcoffer.sdp }));
|
|
} else {
|
|
webRtcDesktop.webrtcoffer.sdp += ('a=' + e.candidate.candidate + '\r\n'); // New candidate, add it to the SDP
|
|
}
|
|
}
|
|
webRtcDesktop.webrtc.oniceconnectionstatechange = function () {
|
|
if ((webRtcDesktop != null) && (webRtcDesktop.webrtc != null) && ((webRtcDesktop.webrtc.iceConnectionState == 'disconnected') || (webRtcDesktop.webrtc.iceConnectionState == 'failed'))) { /*console.log('WebRTC ICE Failed');*/ webRtcDesktopReset(); }
|
|
}
|
|
webRtcDesktop.webrtc.createOffer(function (offer) {
|
|
// Got the offer
|
|
webRtcDesktop.webrtcoffer = offer;
|
|
webRtcDesktop.webrtc.setLocalDescription(offer, function () { }, webRtcDesktopReset);
|
|
}, webRtcDesktopReset, { mandatory: { OfferToReceiveAudio: false, OfferToReceiveVideo: false } });
|
|
} else if ((data.action == 'answer') && (webRtcDesktop != null)) {
|
|
// Complete the WebRTC channel
|
|
webRtcDesktop.webrtc.setRemoteDescription(new RTCSessionDescription({ type: 'answer', sdp: data.sdp }), function () { }, webRtcDesktopReset);
|
|
}
|
|
}
|
|
};
|
|
desktop.Start(desktopNode._id, 16994, '*', '*', 0);
|
|
desktop.contype = 2;
|
|
} else {
|
|
// Setup the Mesh Agent remote desktop
|
|
desktop = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('Desk'), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
|
|
desktop.debugmode = debugmode;
|
|
desktop.m.debugmode = debugmode;
|
|
desktop.attemptWebRTC = attemptWebRTC;
|
|
desktop.onStateChanged = onDesktopStateChange;
|
|
desktop.onConsoleMessageChange = function () {
|
|
p11clearConsoleMsg();
|
|
if (desktop.consoleMessage) {
|
|
QH('p11DeskConsoleMsg', EscapeHtml(desktop.consoleMessage).split('\n').join('<br />'));
|
|
QV('p11DeskConsoleMsg', true);
|
|
p11DeskConsoleMsgTimer = setTimeout(p11clearConsoleMsg, 8000);
|
|
}
|
|
}
|
|
desktop.m.CompressionLevel = desktopsettings.quality; // Number from 1 to 100. 50 or less is best.
|
|
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 {
|
|
// Disconnect and clean up the remote desktop
|
|
desktop.Stop();
|
|
webRtcDesktopReset();
|
|
desktopNode = desktop = null;
|
|
if (pluginHandler != null) { pluginHandler.callHook('onDesktopDisconnect'); }
|
|
}
|
|
}
|
|
|
|
function p11clearConsoleMsg() { QV('p11DeskConsoleMsg', false); if (p11DeskConsoleMsgTimer) { clearTimeout(p11DeskConsoleMsgTimer); p11DeskConsoleMsgTimer = null; } }
|
|
function p12clearConsoleMsg() { QV('p12TermConsoleMsg', false); if (p12TermConsoleMsgTimer) { clearTimeout(p12TermConsoleMsgTimer); p12TermConsoleMsgTimer = null; } }
|
|
function p13clearConsoleMsg() { QV('p13FilesConsoleMsg', false); if (p13FilesConsoleMsgTimer) { clearTimeout(p13FilesConsoleMsgTimer); p13FilesConsoleMsgTimer = null; } }
|
|
|
|
var webRtcDesktop = null;
|
|
function webRtcDesktopReset() {
|
|
if (webRtcDesktop == null) return;
|
|
if (webRtcDesktop.softdesktop != null) { webRtcDesktop.softdesktop.Stop(); webRtcDesktop.softdesktop = null; }
|
|
if (webRtcDesktop.webchannel != null) { try { webRtcDesktop.webchannel.close(); } catch (e) { } webRtcDesktop.webchannel = null; }
|
|
if (webRtcDesktop.webrtc != null) { try { webRtcDesktop.webrtc.close(); } catch (e) { } webRtcDesktop.webrtc = null; }
|
|
webRtcDesktop = null;
|
|
// Switch back to hardware KVM
|
|
if (desktop && desktop.m) {
|
|
desktop.m.hold(false);
|
|
Q('deskstatus').textContent = StatusStrs[desktop.State];
|
|
}
|
|
// ###BEGIN###{DesktopInbandFiles}
|
|
/*
|
|
p24files = null;
|
|
p24downloadFileCancel() // If any downloads are in process, cancel them.
|
|
p24uploadFileCancel(); // If any uploads are in process, cancel them.
|
|
QV('go24', false); // Files
|
|
if (currentView == 24) { go(14); }
|
|
*/
|
|
// ###END###{DesktopInbandFiles}
|
|
}
|
|
|
|
function onDesktopStateChange(xdesktop, state) {
|
|
var xstate = state;
|
|
if ((xstate == 3) && (xdesktop.contype == 2)) { xstate++; }
|
|
var str = StatusStrs[xstate];
|
|
if ((desktop != null) && (desktop.webRtcActive == true)) { str += ", WebRTC"; }
|
|
//if (desktop.m.stopInput == true) { str += ', Loopback'; }
|
|
QH('deskstatus', str);
|
|
switch (state) {
|
|
case 0:
|
|
// Disconnect and clean up the remote desktop
|
|
desktop.Stop();
|
|
desktopNode = desktop = null;
|
|
QV('DeskFocus', false);
|
|
QV('termdisplays', false);
|
|
QV('deskRecordIcon', false);
|
|
deskFocusBtn.value = "Zaměřit vše";
|
|
if (fullscreen == true) { deskToggleFull(); }
|
|
webRtcDesktopReset();
|
|
deskPreferedStickyDisplay = 0;
|
|
break;
|
|
case 2:
|
|
break;
|
|
case 3:
|
|
if (desktop && (desktop.serverIsRecording == true)) { QV('deskRecordIcon', true); }
|
|
desktop.startTime = new Date();
|
|
if (updateSessionTimer == null) { updateSessionTimer = setInterval(updateSessionTime, 1000); }
|
|
break;
|
|
default:
|
|
//console.log('Unknown onDesktopStateChange state', state);
|
|
break;
|
|
}
|
|
updateDesktopButtons();
|
|
deskAdjust();
|
|
setTimeout(deskAdjust, 50);
|
|
}
|
|
|
|
function updateSessionTime() {
|
|
// Desktop
|
|
var seconds = 0;
|
|
if (desktop && desktop.startTime) {
|
|
seconds = Math.floor((new Date() - desktop.startTime) / 1000);
|
|
QH('DeskTimer', zeroPad(Math.floor(seconds / 3600), 2) + ':' + zeroPad((Math.floor(seconds / 60) % 60), 2) + ':' + zeroPad((seconds % 60), 2));
|
|
} else {
|
|
QH('DeskTimer', '');
|
|
}
|
|
|
|
// Terminal
|
|
seconds = 0;
|
|
if (terminal && terminal.startTime) {
|
|
seconds = Math.floor((new Date() - terminal.startTime) / 1000);
|
|
QH('TermTimer', zeroPad(Math.floor(seconds / 3600), 2) + ':' + zeroPad((Math.floor(seconds / 60) % 60), 2) + ':' + zeroPad((seconds % 60), 2));
|
|
} else {
|
|
QH('TermTimer', '');
|
|
}
|
|
|
|
if ((desktop == null) && (terminal == null)) { clearInterval(updateSessionTimer); updateSessionTimer = null; }
|
|
}
|
|
|
|
function showDesktopSettings() {
|
|
if (xxdialogMode) return;
|
|
applyDesktopSettings();
|
|
updateDesktopButtons();
|
|
setDialogMode(7, "Nastavení vzdálené plochy", 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;
|
|
desktopsettings.localkeymap = d7localKeyMap.checked;
|
|
localStorage.setItem('desktopsettings', JSON.stringify(desktopsettings));
|
|
applyDesktopSettings();
|
|
if (desktop) {
|
|
if (desktop.contype == 1) {
|
|
if (desktop.State != 0) {
|
|
desktop.m.SendCompressionLevel(1, desktopsettings.quality, desktopsettings.scaling, desktopsettings.framerate);
|
|
}
|
|
}
|
|
if (desktop.contype == 2) {
|
|
if (desktopsettings.showfocus == false) { desktop.m.focusmode = 0; deskFocusBtn.value = "Zaměřit vše"; }
|
|
if (desktop.State != 0) { desktop.Stop(); setTimeout(function () { connectDesktop(null, 2); }, 50); }
|
|
}
|
|
}
|
|
}
|
|
|
|
function applyDesktopSettings() {
|
|
var r = '', ops = (features & 512)?[90,80,70,60,50,40,30,20,10,5,1]:[60,50,40,30,20,10,5,1];
|
|
for (var i in ops) { r += '<option value=' + ops[i] + '>' + ops[i] + '%</option>'; }
|
|
QH('d7bitmapquality', r);
|
|
d7desktopmode.value = desktopsettings.encoding;
|
|
d7showfocus.checked = desktopsettings.showfocus;
|
|
d7showcursor.checked = desktopsettings.showmouse;
|
|
d7bitmapquality.value = 40; // Default value
|
|
if (ops.indexOf(parseInt(desktopsettings.quality)) >= 0) { d7bitmapquality.value = desktopsettings.quality; }
|
|
d7bitmapscaling.value = desktopsettings.scaling;
|
|
if (desktopsettings.framerate) { d7framelimiter.value = desktopsettings.framerate; }
|
|
if (desktopsettings.localkeymap) { d7localKeyMap.checked = desktopsettings.localkeymap; }
|
|
QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (desktop.state != 0) && (desktopsettings.showfocus));
|
|
}
|
|
|
|
// Enter browser fullscreen
|
|
function enterBrowserFullscreen(elem) {
|
|
if (elem.requestFullscreen) { elem.requestFullscreen(); }
|
|
else if (elem.msRequestFullscreen) { elem.msRequestFullscreen(); }
|
|
else if (elem.mozRequestFullScreen) { elem.mozRequestFullScreen(); }
|
|
else if (elem.webkitRequestFullscreen) { elem.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); }
|
|
}
|
|
|
|
// Exit browser fullscreen
|
|
function exitBrowserFullscreen() {
|
|
if (document.exitFullscreen) { document.exitFullscreen(); }
|
|
else if (document.msExitFullscreen) { document.msExitFullscreen(); }
|
|
else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); }
|
|
else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); }
|
|
}
|
|
|
|
// Return true if the browser is fullscreen. This is a delayed method that will return true/false late. Not very useful.
|
|
function isBrowserFullscreen() {
|
|
if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) { return false; } else { return true; }
|
|
}
|
|
|
|
var fullscreen = false;
|
|
var browserfullscreen = false;
|
|
function deskToggleFull(e) {
|
|
fullscreen = !fullscreen;
|
|
if (fullscreen) {
|
|
QC('body').add('fulldesk');
|
|
QS('deskarea3x')['height'] = '100%';
|
|
QS('deskarea3x')['max-height'] = '100%';
|
|
// If shift is pressed, enter browser full screen.
|
|
if (e.shiftKey == true) { enterBrowserFullscreen(Q('deskarea0')); browserfullscreen = true; }
|
|
} else {
|
|
QC('body').remove('fulldesk');
|
|
QS('deskarea3x')['height'] = null;
|
|
QS('deskarea3x')['max-height'] = null;
|
|
if (browserfullscreen == true) { exitBrowserFullscreen(); browserfullscreen = false; }
|
|
}
|
|
deskAdjust();
|
|
updateDesktopButtons();
|
|
}
|
|
|
|
function deskToggleFocus() {
|
|
desktop.m.focusmode = (desktop.m.focusmode + 64) % 192;
|
|
Q('deskFocusBtn').value = ["Zaměřit vše", "malé zaměření", "Velké zaměření"][desktop.m.focusmode / 64];
|
|
}
|
|
|
|
function deskAdjust() {
|
|
var parentH = Q('DeskParent').clientHeight, parentW = Q('DeskParent').clientWidth;
|
|
var deskH = Q('Desk').height, deskW = Q('Desk').width;
|
|
|
|
if (deskAspectRatio == 2) {
|
|
// Scale mode
|
|
QS('Desk')['margin-top'] = null;
|
|
QS('Desk').height = '100%';
|
|
QS('Desk').width = '100%';
|
|
//QS('deskarea3x').height = null;
|
|
QS('DeskParent').overflow = 'hidden';
|
|
} else if (deskAspectRatio == 1) {
|
|
// Zoomed mode
|
|
QS('Desk')['margin-top'] = '0px';
|
|
QS('Desk').height = deskH + 'px';
|
|
QS('Desk').width = deskW + 'px';
|
|
QS('DeskParent').overflow = 'scroll';
|
|
} else {
|
|
// Fixed aspect ratio
|
|
if ((parentH / parentW) > (deskH / deskW)) {
|
|
var hNew = ((deskH * parentW) / deskW) + 'px';
|
|
//if (webPageFullScreen || fullscreen) {
|
|
//QS('deskarea3x').height = null;
|
|
//} else {
|
|
// QS('deskarea3x').height = hNew;
|
|
//QS('deskarea3x').height = null;
|
|
//}
|
|
QS('Desk').height = hNew;
|
|
QS('Desk').width = '100%';
|
|
} else {
|
|
var wNew = ((deskW * parentH) / deskH) + 'px';
|
|
if (webPageFullScreen || fullscreen) {
|
|
QS('Desk').height = null;
|
|
} else {
|
|
QS('Desk').height = '100%';
|
|
}
|
|
QS('Desk').width = wNew;
|
|
}
|
|
QS('Desk')['margin-top'] = null;
|
|
QS('DeskParent').overflow = 'hidden';
|
|
}
|
|
}
|
|
|
|
function mdeskAdjust(mod, sw, sh, cv) {
|
|
if (!mod || !sw || !sh || !cv) return;
|
|
|
|
// Check if we are in single desktop mode
|
|
if (cv.id == 'Desk') { deskAdjust(); return; }
|
|
|
|
// Figure out and adjust the size to fill the width of the div
|
|
var vsize = [{ x: 180, y: 101 }, { x: 302, y: 169 }, { x: 454, y: 255 }][Q('sizeselect').selectedIndex];
|
|
var realw = vsize.x + 2, tw = Q('xdevices').clientWidth - 30, xw = Math.floor(tw / realw);
|
|
xw = realw + Math.floor((tw - (xw * realw)) / xw);
|
|
vsize.y = vsize.y * (xw / vsize.x);
|
|
vsize.x = xw;
|
|
var mh = vsize.y, mw = vsize.x;
|
|
if (mod.State != 0) { mh = vsize.y; mw = (sw / sh) * vsize.y; }
|
|
QS(cv.id)['max-height'] = mh + 'px';
|
|
QS(cv.id)['max-width'] = mw + 'px';
|
|
QS(cv.id)['margin-top'] = '0';
|
|
QS(cv.id)['margin-bottom'] = '0';
|
|
}
|
|
|
|
// Remote desktop special key combos for Windows
|
|
function deskSendKeys() {
|
|
if (xxdialogMode || desktop == null || desktop.State != 3) return;
|
|
var ks = Q('deskkeys').value;
|
|
if (ks == 0) { // WIN+Down arrow
|
|
if (desktop.contype == 2) {
|
|
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
|
|
} else {
|
|
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
|
|
}
|
|
} else if (ks == 1) { // WIN+Up arrow
|
|
if (desktop.contype == 2) {
|
|
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
|
|
} else {
|
|
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
|
|
}
|
|
} else if (ks == 2) { // WIN+L arrow
|
|
if (desktop.contype == 2) {
|
|
desktop.m.sendkey([[0xffe7,1],[0x6c,1],[0x6c,0],[0xffe7,0]]); // Intel AMT: Meta-left down, 'l' press, 'l' release, Meta-left release
|
|
} else {
|
|
desktop.sendCtrlMsg('{"action":"lock"}');
|
|
//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
|
|
//desktop.m.SendKeyMsgKC(desktop.m.KeyAction.EXDOWN, 0x5B);
|
|
//desktop.m.SendKeyMsgKC(desktop.m.KeyAction.DOWN, 76);
|
|
//desktop.m.SendKeyMsgKC(desktop.m.KeyAction.UP, 76);
|
|
//desktop.m.SendKeyMsgKC(desktop.m.KeyAction.EXUP, 0x5B);
|
|
}
|
|
} else if (ks == 3) { // WIN+M arrow
|
|
if (desktop.contype == 2) {
|
|
desktop.m.sendkey([[0xffe7,1],[0x6d,1],[0x6d,0],[0xffe7,0]]); // Intel AMT: Meta-left down, 'm' press, 'm' release, Meta-left release
|
|
} else {
|
|
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
|
|
}
|
|
} else if (ks == 4) { // Shift+WIN+M arrow
|
|
if (desktop.contype == 2) {
|
|
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
|
|
} else {
|
|
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
|
|
}
|
|
} else if (ks == 5) { // WIN
|
|
if (desktop.contype == 2) {
|
|
desktop.m.sendkey([[0xffe7,1],[0xffe7,0]]); // Intel AMT: Meta-left down, Meta-left release
|
|
} else {
|
|
desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B], [desktop.m.KeyAction.EXUP,0x5B]]); // MeshAgent: L-Winkey press, L-Winkey release
|
|
}
|
|
} else if (ks == 6) { // WIN+R
|
|
if (desktop.contype == 2) {
|
|
desktop.m.sendkey([[0xffe7,1],[0x72,1],[0x72,0],[0xffe7,0]]); // Intel AMT: Meta-left down, 'r' press, 'r' release, Meta-left release
|
|
} else {
|
|
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
|
|
}
|
|
} else if (ks == 7) { // ALT-F4
|
|
if (desktop.contype == 2) {
|
|
desktop.m.sendkey([[0xffe9,1],[0xffc1,1],[0xffc1,0],[0xffe9,0]]); // Intel AMT: Alt down, 'F4' press, 'F4' release, Alt release
|
|
} else {
|
|
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
|
|
}
|
|
} else if (ks == 8) { // CTRL-W
|
|
if (desktop.contype == 2) {
|
|
desktop.m.sendkey([[0xffe3,1],[0x77,1],[0x77,0],[0xffe3,0]]); // Intel AMT: Ctrl down, 'w' press, 'w' release, Ctrl release
|
|
} else {
|
|
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
|
|
}
|
|
} else if (ks == 9) { // ALT-TAB
|
|
if (desktop.contype == 2) {
|
|
desktop.m.sendkey([[0xffe9, 1], [0xff09, 1], [0xff09, 0], [0xffe9, 0]]); // Intel AMT: Alt down, 'TAB' press, 'TAB' release, Alt release
|
|
} else {
|
|
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
|
|
}
|
|
} else if (ks == 10) { // CTRL-ALT-DEL
|
|
desktop.m.sendcad();
|
|
} else if (ks == 11) { // WIN-LEFT
|
|
if (desktop.contype == 2) {
|
|
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
|
|
} else {
|
|
desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 37], [desktop.m.KeyAction.UP, 37], [desktop.m.KeyAction.EXUP, 0x5B]]);
|
|
}
|
|
} else if (ks == 12) { // WIN-RIGHT
|
|
if (desktop.contype == 2) {
|
|
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
|
|
} else {
|
|
desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 39], [desktop.m.KeyAction.UP, 39], [desktop.m.KeyAction.EXUP, 0x5B]]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remote desktop typing
|
|
function showDeskType() {
|
|
if (xxdialogMode || desktop == null || desktop.State != 3) return;
|
|
Q('DeskType').blur();
|
|
var x = '<div>' + "Zadejte text a kliknutím na OK jej zadáte na dálku pomocí americké anglické klávesnice. Než budete pokračovat, nezapomeňte vzdálený kurzor na správnou pozici." + '<div>';
|
|
x += '<textarea id=d2typeText style="margin-top:5px;width:100%;height:184px;resize:none" maxlength=2000></textarea>';
|
|
setDialogMode(2, "Vzdálené zadání klávesnice", 3, showDeskTypeEx, x);
|
|
Q('d2typeText').focus();
|
|
}
|
|
|
|
var AmtDeskTypeTimer = null;
|
|
var AmtDeskTypeContent = null;
|
|
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 };
|
|
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 };
|
|
function showDeskTypeEx() {
|
|
var txt = Q('d2typeText').value, ltxt = Q('d2typeText').value.toUpperCase(), x = [], shift = false;
|
|
if (desktop.contype == 2) {
|
|
// Intel AMT
|
|
for (var i in txt) { var a = txt.charCodeAt(i); x.push([a, 1], [a, 0]); }
|
|
AmtDeskTypeContent = x;
|
|
AmtDeskTypeTimer = setInterval(function () {
|
|
var key = AmtDeskTypeContent.shift();
|
|
if (desktop) { desktop.m.sendkey(key[0], key[1]); }
|
|
if ((desktop == null) || (AmtDeskTypeContent.length == 0)) { clearInterval(AmtDeskTypeTimer); AmtDeskTypeContent = null; }
|
|
}, 10);
|
|
} else {
|
|
// MeshAgent
|
|
for (var i in txt) {
|
|
var a = txt.charCodeAt(i), b = ltxt.charCodeAt(i);
|
|
if (((a >= 65) && (a <= 90)) || ((a >= 97) && (a <= 122))) {
|
|
if ((a == b) && (shift == false)) { x.push([desktop.m.KeyAction.DOWN, 16]); shift = true; } // LShift down
|
|
if ((a != b) && (shift == true)) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // LShift up
|
|
} else if ((a >= 48) && (a <= 57)) {
|
|
if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
|
|
} else if (DeskTypeTranslate[a]) {
|
|
if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
|
|
b = DeskTypeTranslate[a];
|
|
} else if (DeskTypeShiftTranslate[a]) {
|
|
if (shift == false) { x.push([desktop.m.KeyAction.DOWN, 16]); shift = true; } // LShift down
|
|
b = DeskTypeShiftTranslate[a];
|
|
}
|
|
x.push([desktop.m.KeyAction.DOWN, b], [desktop.m.KeyAction.UP, b]);
|
|
}
|
|
if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
|
|
desktop.m.SendKeyMsgKC(x);
|
|
}
|
|
}
|
|
|
|
// Show clipboard dialog
|
|
function showDeskClip() {
|
|
if (xxdialogMode || desktop == null || desktop.State != 3) return;
|
|
Q('DeskClip').blur();
|
|
var x = '';
|
|
x += '<input id=dlgClipGet type=button value="Get Clipboard" style=width:120px onclick=showDeskClipGet()>';
|
|
x += '<input id=dlgClipSet type=button value="Set Clipboard" style=width:120px onclick=showDeskClipSet()>';
|
|
x += '<div id=dlgClipStatus style="display:inline-block;margin-left:8px" ></div>';
|
|
x += '<textarea id=d2clipText style="width:100%;height:184px;resize:none" maxlength=65535></textarea>';
|
|
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>' + "Vzdálená schránka je platná 60 sekund." + '</span> </div><div></div>';
|
|
setDialogMode(2, "Vzdálená schránka", 8, null, x, 'clipboard');
|
|
Q('d2clipText').focus();
|
|
}
|
|
|
|
function showDeskClipGet() {
|
|
if (desktop == null || desktop.State != 3) return;
|
|
meshserver.send({ action: 'msg', type: 'getclip', nodeid: currentNode._id });
|
|
}
|
|
|
|
function showDeskClipSet() {
|
|
if (desktop == null || desktop.State != 3) return;
|
|
meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: Q('d2clipText').value });
|
|
QV('linuxClipWarn', currentNode && currentNode.agent && (currentNode.agent.id > 4) && (currentNode.agent.id != 21) && (currentNode.agent.id != 22));
|
|
}
|
|
|
|
// Send CTRL-ALT-DEL
|
|
function sendCAD() {
|
|
if (xxdialogMode || desktop == null || desktop.State != 3) return;
|
|
desktop.m.sendcad();
|
|
}
|
|
|
|
// Show process dialogs
|
|
function toggleDeskTools() {
|
|
if (xxdialogMode) return;
|
|
if (QS('DeskTools').display == 'none') {
|
|
QV('DeskTools', true);
|
|
Q('DeskTools').nodeid = currentNode._id;
|
|
QH('DeskToolsProcesses', '');
|
|
QH('DeskToolsServices', '');
|
|
QV('deskToolsTopTabService', false);
|
|
changeDeskToolTab(0)
|
|
refreshDeskTools(0);
|
|
refreshDeskTools(1);
|
|
} else {
|
|
QV('DeskTools', false);
|
|
}
|
|
}
|
|
|
|
var deskToolTabSelection = 0;
|
|
function changeDeskToolTab(tabnum) {
|
|
deskToolTabSelection = tabnum;
|
|
QV('DeskToolsProcessTab', tabnum == 0);
|
|
QV('DeskToolsServiceTab', tabnum == 1);
|
|
QS('deskToolsTopTabProcess')['bottom'] = (tabnum == 0) ? '0px' : '3px';
|
|
QS('deskToolsTopTabService')['bottom'] = (tabnum == 1) ? '0px' : '3px';
|
|
QS('deskToolsTopTabProcess')['color'] = (tabnum == 0) ? 'black' : 'gray';
|
|
QS('deskToolsTopTabService')['color'] = (tabnum == 1) ? 'black' : 'gray';
|
|
}
|
|
|
|
// Refresh all of the desktop tool panels
|
|
function refreshDeskTools(x) {
|
|
var sel = (x == null) ? deskToolTabSelection : x;
|
|
QV('DeskToolsRefreshButton', false);
|
|
setTimeout(refreshDeskToolsEx, 500);
|
|
if (sel == 0) meshserver.send({ action: 'msg', type: 'ps', nodeid: currentNode._id });
|
|
if (sel == 1) meshserver.send({ action: 'msg', type: 'services', nodeid: currentNode._id });
|
|
}
|
|
function refreshDeskToolsEx() { QV('DeskToolsRefreshButton', true); }
|
|
var deskTools = { sort: 1, ssort: 1, msg: null, smsg: null };
|
|
function sortProcess(sort) { deskTools.sort = sort; showDeskToolsProcesses(deskTools.msg); }
|
|
function sortService(sort) { deskTools.ssort = sort; showDeskToolsServices(deskTools.smsg); }
|
|
function sortProcessPid(a, b) { if (a.p > b.p) return 1; if (a.p < b.p) return (-1); return sortProcessName(a, b); }
|
|
function sortProcessName(a, b) { if (a.d > b.d) return 1; if (a.d < b.d) return (-1); return 0; }
|
|
function showDeskToolsProcesses(message) {
|
|
deskTools.msg = message;
|
|
if (message == null) { QH('DeskToolsProcesses', ''); return; }
|
|
if (Q('DeskTools').nodeid != message.nodeid) return;
|
|
var p = [], processes = null;
|
|
try { processes = JSON.parse(message.value); } catch (e) { }
|
|
if (processes != null) {
|
|
for (var pid in processes) { p.push( { p:parseInt(pid), c:processes[pid].cmd, d:processes[pid].cmd.toLowerCase(), u: processes[pid].user } ); }
|
|
if (deskTools.sort == 0) { p.sort(sortProcessPid); } else if (deskTools.sort == 1) { p.sort(sortProcessName); }
|
|
var x = '';
|
|
for (var i in p) {
|
|
if (p[i].p != 0) {
|
|
var c = p[i].c;
|
|
if (c.length > 30) { c = '<span title="' + c + '">' + c.substring(0,30) + '...</span>' }
|
|
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>';
|
|
}
|
|
}
|
|
QH('DeskToolsProcesses', x);
|
|
}
|
|
}
|
|
function showDeskToolsServices(message) {
|
|
deskTools.smsg = message;
|
|
if (message == null) { QH('DeskToolsProcesses', ''); return; }
|
|
if (Q('DeskTools').nodeid != message.nodeid) return;
|
|
QV('deskToolsTopTabService', true);
|
|
var s = [], services = null;
|
|
try { services = JSON.parse(message.value); } catch (e) { }
|
|
deskTools.services = services;
|
|
if (services != null) {
|
|
for (var i in services) {
|
|
if (services[i].status) {
|
|
// Windows
|
|
s.push({ p: capitalizeFirstLetter(services[i].status.state.toLowerCase()), d: services[i].displayName, i: i });
|
|
} else if (services[i].serviceType) {
|
|
// Linux (TODO: This the service status is not displayed, not sure start/stop/restart will work).
|
|
s.push({ p: services[i].serviceType, d: services[i].name, i: i });
|
|
}
|
|
}
|
|
if (deskTools.ssort == 0) { s.sort(sortProcessPid); } else if (deskTools.ssort == 1) { s.sort(sortProcessName); }
|
|
var x = '';
|
|
for (var i in s) {
|
|
if (s[i].p != 0) {
|
|
var c = s[i].d;
|
|
if (c.length > 30) { c = '<span title="' + c + '">' + c.substring(0, 30) + '...</span>' }
|
|
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>';
|
|
}
|
|
}
|
|
QH('DeskToolsServices', x);
|
|
}
|
|
}
|
|
|
|
function showServiceDetailsDialog(index) {
|
|
if (xxdialogMode) return;
|
|
var service = deskTools.services[index];
|
|
if (service != null) {
|
|
var x = '';
|
|
if (service.name) { x += addHtmlValue("Jméno", service.name); }
|
|
if (service.displayName) { x += addHtmlValue("Zobrazované jméno", service.displayName); }
|
|
if (service.status) {
|
|
if (service.status.state) { x += addHtmlValue("Stav", capitalizeFirstLetter(service.status.state.toLowerCase())); }
|
|
if (service.status.pid) { x += addHtmlValue("PID", service.status.pid); }
|
|
var serviceTypes = [];
|
|
if (service.status.isFileSystemDriver === true) { serviceTypes.push("Ovladač souborového systému"); }
|
|
if (service.status.isInteractive === true) { serviceTypes.push("Interaktivní"); }
|
|
if (service.status.isKernelDriver === true) { serviceTypes.push("Ovladač jádra"); }
|
|
if (service.status.isOwnProcess === true) { serviceTypes.push("OwnProcess"); }
|
|
if (service.status.isSharedProcess === true) { serviceTypes.push("SharedProcess"); }
|
|
if (serviceTypes.length > 0) { x += addHtmlValue("Typ", serviceTypes.join(', ')); }
|
|
}
|
|
x += '<br/><div style=float:right;margin-bottom:12px><input type=button value=\"' + "Zavřít" + '\" 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>';
|
|
setDialogMode(2, "Detaily serveru", 8, null, x, name);
|
|
}
|
|
}
|
|
|
|
function showServiceDetailsDialogEx(action, index) {
|
|
setDialogMode(0);
|
|
if (action == 0) return;
|
|
var service = deskTools.services[index];
|
|
if (service != null) {
|
|
if (action == 1) { meshserver.send({ action: 'msg', type: 'serviceStart', nodeid: currentNode._id, serviceName: service.name }); }
|
|
if (action == 2) { meshserver.send({ action: 'msg', type: 'serviceStop', nodeid: currentNode._id, serviceName: service.name }); }
|
|
if (action == 3) { meshserver.send({ action: 'msg', type: 'serviceRestart', nodeid: currentNode._id, serviceName: service.name }); }
|
|
setTimeout(function () { refreshDeskTools(1) }, 1000);
|
|
}
|
|
}
|
|
|
|
// Toggle mouse and keyboard input
|
|
function toggleKvmControl() { putstore('DeskControl', (Q("DeskControl").checked?1:0)); }
|
|
|
|
// Save the desktop image to file
|
|
function deskSaveImage() {
|
|
if (xxdialogMode || desktop == null || desktop.State != 3) return;
|
|
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);
|
|
Q('Desk')['toBlob'](function (blob) { saveAs(blob, n + '.jpg'); });
|
|
}
|
|
|
|
function deskDisplayInfo(sender, displays, selDisplay) {
|
|
var displayCount = 0, displaySelector = '';
|
|
for (var i in displays) {
|
|
displayCount++;
|
|
displaySelector += '<option' + ((selDisplay == i) ? ' selected' : '') + ' value=' + i + '>' + displays[i] + '</option>';
|
|
if ((deskPreferedStickyDisplay == i) && (selDisplay != deskPreferedStickyDisplay)) { desktop.m.SetDisplay(i); }
|
|
}
|
|
QH('termdisplays', displaySelector);
|
|
QV('termdisplays', displayCount > 1);
|
|
}
|
|
|
|
function deskGetDisplayNumbers(e) { desktop.m.GetDisplayNumbers(); }
|
|
var deskPreferedStickyDisplay = 0;
|
|
function deskSetDisplay(e) { desktop.m.SetDisplay(deskPreferedStickyDisplay = parseInt(Q('termdisplays').value)); Q('termdisplays').blur(); }
|
|
|
|
// Double click detection. This is important for MacOS.
|
|
var dblClickDetectArgs = { t:0, x:0, y:0 };
|
|
function dblClickDetect(e) {
|
|
if (e.buttons != 1) return;
|
|
var t = Date.now();
|
|
if (((t - dblClickDetectArgs.t) < 250) && (Math.abs(e.clientX - dblClickDetectArgs.x) < 2) && (Math.abs(e.clientY - dblClickDetectArgs.y) < 2)) {
|
|
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); } }
|
|
}
|
|
dblClickDetectArgs.t = t;
|
|
dblClickDetectArgs.x = e.clientX;
|
|
dblClickDetectArgs.y = e.clientY;
|
|
}
|
|
|
|
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); }
|
|
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); } }
|
|
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); } } }
|
|
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; }
|
|
function drotate(x) { if (!xxdialogMode && desktop != null) { desktop.m.setRotation(desktop.m.rotation + x); deskAdjust(); deskAdjust(); } }
|
|
function stopProcess(id, name) { setDialogMode(2, "Správa procesů", 3, stopProcessEx, format("Ukončit proces #{0} \"{1}\"?", id, name), id); return false; }
|
|
function stopProcessEx(buttons, tag) { meshserver.send({ action: 'msg', type: 'pskill', nodeid: currentNode._id, value: tag }); setTimeout(refreshDeskTools, 300); }
|
|
|
|
//
|
|
// TERMINAL
|
|
//
|
|
|
|
var terminalNode;
|
|
function setupTerminal() {
|
|
// Setup the terminal
|
|
if ((terminalNode != currentNode) && (terminal != null)) { terminal.Stop(); terminal = null; }
|
|
terminalNode = currentNode;
|
|
updateTerminalButtons();
|
|
}
|
|
|
|
// Show and enable the right buttons
|
|
function updateTerminalButtons() {
|
|
var mesh = meshes[terminalNode.meshid];
|
|
var termState = ((terminal != null) && (terminal.state != 0));
|
|
|
|
// Show the right buttons
|
|
QV('disconnectbutton2span', (termState == true));
|
|
QV('connectbutton2span', (termState == false) && (mesh.mtype == 2) && (currentNode.agent.caps & 2));
|
|
QV('connectbutton2hspan', (termState == false) && ((terminalNode.intelamt != null) && (mesh.mtype == 1 || terminalNode.intelamt.state == 2) && ((terminalNode.intelamt.ver != null) || (mesh.mtype == 1))));
|
|
|
|
// Enable buttons
|
|
var online = ((terminalNode.conn & 1) != 0); // If Agent (1) connected, enable Terminal
|
|
QE('connectbutton2', online);
|
|
var hwonline = ((terminalNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal
|
|
QE('connectbutton2h', hwonline);
|
|
|
|
// Key buttons
|
|
QE('ctrlcbutton', termState);
|
|
QE('ctrlxbutton', termState);
|
|
QE('escbutton', termState);
|
|
QE('bsbutton', termState);
|
|
QE('pastebutton', termState);
|
|
QE('specialkeylist', termState);
|
|
QE('specialkeylistinput', termState);
|
|
|
|
// Terminal settings
|
|
QV('terminalSettingsButtons', (terminal) && (terminal.contype == 2));
|
|
if (terminal) {
|
|
Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
|
|
Q('id_tfxkeysbutton').value = fxEmulations[terminal.m.fxEmulation];
|
|
Q('id_tcrbutton').value = (terminal.m.lineFeed == '\r\n')?"CR+LF":"LF";
|
|
}
|
|
}
|
|
|
|
// Called when the terminal state changes
|
|
function onTerminalStateChange(xterminal, state) {
|
|
var xstate = state;
|
|
if ((xstate == 3) && (xterminal.contype == 2)) { xstate++; }
|
|
var str = StatusStrs[xstate];
|
|
if (terminal.webRtcActive == true) { str += ", WebRTC"; }
|
|
QH('termstatus', str);
|
|
switch (state) {
|
|
case 0:
|
|
// Disconnected, clear the terminal
|
|
QE('termSizeList', true);
|
|
QH('termtitle', '');
|
|
QV('termRecordIcon', false);
|
|
xterminal.m.TermResetScreen();
|
|
xterminal.m.TermDraw();
|
|
if (terminal != null) { terminal.Stop(); terminal = null; }
|
|
break;
|
|
case 3:
|
|
QE('termSizeList', false);
|
|
if (xterminal && (xterminal.serverIsRecording == true)) { QV('termRecordIcon', true); }
|
|
terminal.startTime = new Date();
|
|
if (updateSessionTimer == null) { updateSessionTimer = setInterval(updateSessionTime, 1000); }
|
|
break;
|
|
default:
|
|
QE('termSizeList', false);
|
|
//console.log('Unhandled onTerminalStateChange state', state);
|
|
break;
|
|
}
|
|
updateTerminalButtons();
|
|
}
|
|
|
|
// DEBUG
|
|
var autoConnectTerminalTimer = null;
|
|
function autoConnectTerminal(e) { if (autoConnectTerminalTimer == null) { autoConnectTerminalTimer = setInterval(connectTerminal, 100); } else { clearInterval(autoConnectTerminalTimer); autoConnectTerminalTimer = null; } }
|
|
|
|
function connectTerminal(e, contype, options) {
|
|
p12clearConsoleMsg();
|
|
if (!terminal) {
|
|
if (contype == 2) {
|
|
// Setup the Intel AMT terminal
|
|
if ((terminalNode.intelamt.user == null) || (terminalNode.intelamt.user == '')) { editDeviceAmtSettings(terminalNode._id, connectTerminal, 2); return; }
|
|
var termoptions = {};
|
|
if (Q('termSizeList').value == 2) { termoptions.width = 100; termoptions.height = 30; }
|
|
terminal = CreateAmtRedirect(CreateAmtRemoteTerminal('Term', termoptions), authCookie);
|
|
terminal.debugmode = debugmode;
|
|
terminal.m.debugmode = debugmode;
|
|
terminal.m.onTitleChange = function (sender, title) { QH('termtitle', ' - ' + EscapeHtml(title)); }
|
|
terminal.onStateChanged = onTerminalStateChange;
|
|
terminal.Start(terminalNode._id, 16994, '*', '*', 0);
|
|
terminal.contype = 2;
|
|
Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
|
|
} else {
|
|
// Setup a mesh agent terminal
|
|
var termoptions = { protocol: ((options != null) && (typeof options.protocol == 'number'))?options.protocol:1 };
|
|
if ([1, 2, 3, 4, 21, 22].indexOf(currentNode.agent.id) == -1) {
|
|
if (Q('termSizeList').value == 2) { termoptions.width = 100; termoptions.height = 30; termoptions.xterm = true; }
|
|
if (Q('termSizeList').value == 3) {
|
|
// TODO: Try to improve terminal auto-size.
|
|
termoptions.width = Math.floor((Q('column_l').clientWidth - 60) / 10);
|
|
termoptions.height = Math.floor((Q('column_l').clientHeight - 120) / 20);
|
|
termoptions.xterm = true;
|
|
}
|
|
}
|
|
|
|
// If shift is pressed
|
|
if ((e && (e.shiftKey == true))) {
|
|
if (currentNode.agent.id > 4) {
|
|
if (termoptions.protocol == 1) { termoptions.protocol = 7; } // Switch to user shell
|
|
} else {
|
|
if (termoptions.protocol == 1) { termoptions.protocol = 6; } // Switch to Powershell
|
|
}
|
|
}
|
|
|
|
terminal = CreateAgentRedirect(meshserver, CreateAmtRemoteTerminal('Term', termoptions), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
|
|
terminal.debugmode = debugmode;
|
|
terminal.m.debugmode = debugmode;
|
|
terminal.m.onTitleChange = function (sender, title) { QH('termtitle', ' - ' + EscapeHtml(title)); }
|
|
terminal.m.lineFeed = ([1, 2, 3, 4, 21, 22].indexOf(currentNode.agent.id) >= 0) ? '\r\n' : '\r'; // On windows, send \r\n, on Linux only \r
|
|
terminal.attemptWebRTC = attemptWebRTC;
|
|
terminal.onStateChanged = onTerminalStateChange;
|
|
terminal.onConsoleMessageChange = function () {
|
|
p12clearConsoleMsg();
|
|
if (terminal.consoleMessage) {
|
|
QH('p12TermConsoleMsg', EscapeHtml(terminal.consoleMessage).split('\n').join('<br />'));
|
|
QV('p12TermConsoleMsg', true);
|
|
p12TermConsoleMsgTimer = setTimeout(p12clearConsoleMsg, 8000);
|
|
}
|
|
}
|
|
terminal.Start(terminalNode._id);
|
|
terminal.contype = 1;
|
|
terminal.m.terminalEmulation = 0;
|
|
terminal.m.fxEmulation = 0;
|
|
Q('id_ttypebutton').value = terminalEmulations[0];
|
|
}
|
|
} else {
|
|
//QH('Term', '');
|
|
terminal.Stop();
|
|
terminal = null;
|
|
}
|
|
Q('connectbutton2').blur(); // Deselect the connect button so the button does not get key presses.
|
|
}
|
|
|
|
var terminalEmulations = ["UTF8 Terminál", "Rozšířené ASCII", "Intel ASCII"];
|
|
function termToggleType() {
|
|
if (!terminal || xxdialogMode) return;
|
|
terminal.m.terminalEmulation = (terminal.m.terminalEmulation + 1) % 3;
|
|
Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
|
|
Q('id_ttypebutton').blur(); // Deselect the connect button so the button does not get key presses.
|
|
}
|
|
|
|
var fxEmulations = ["Intel (F10 = ESC+[OM)", "Nebo (F10 = ESC+0)", "VT100+ (F10 = ESC+[OY)"];
|
|
function termToggleFx() {
|
|
if (!terminal || xxdialogMode) return;
|
|
terminal.m.fxEmulation = (terminal.m.fxEmulation + 1) % 3;
|
|
Q('id_tfxkeysbutton').value = fxEmulations[terminal.m.fxEmulation];
|
|
Q('id_tfxkeysbutton').blur(); // Deselect the connect button so the button does not get key presses.
|
|
}
|
|
|
|
function termToggleCr() {
|
|
if (!terminal || xxdialogMode) return;
|
|
if (terminal.m.lineFeed == '\n') { terminal.m.lineFeed = '\r\n'; } else { terminal.m.lineFeed = '\n'; }
|
|
Q('id_tcrbutton').value = (terminal.m.lineFeed == '\r\n') ? "CR+LF" : "LF";
|
|
}
|
|
|
|
function termSendKey(key, id) {
|
|
if (!terminal || xxdialogMode) return;
|
|
terminal.m.TermSendKey(key);
|
|
Q(id).blur(); // Deselect the connect button so the button does not get key presses.
|
|
}
|
|
|
|
function showTermPasteDialog() {
|
|
if (!terminal || xxdialogMode) return;
|
|
Q('pastebutton').blur();
|
|
setDialogMode(2, "Vložit", 3, showTermPasteDialogEx, '<textarea id=d2pasteText style="width:100%;height:184px;resize:none"></textarea>');
|
|
Q('d2pasteText').focus();
|
|
}
|
|
|
|
function showTermPasteDialogEx() {
|
|
if (!terminal) return;
|
|
terminal.m.TermSendKeys(Q('d2pasteText').value);
|
|
}
|
|
|
|
// Send special key
|
|
function sendSpecialKey() {
|
|
terminal.m.TermSendKey(Q('specialkeylist').value);
|
|
Q('specialkeylist').blur();
|
|
Q('specialkeylistinput').blur();
|
|
}
|
|
|
|
//
|
|
// FILES
|
|
//
|
|
|
|
var filesNode;
|
|
function setupFiles() {
|
|
// Setup the files tab
|
|
var samenode = (filesNode == currentNode);
|
|
filesNode = currentNode;
|
|
var online = ((filesNode.conn & 1) != 0)?true:false; // If Agent (1) connected, enable Terminal
|
|
QE('p13Connect', online);
|
|
if (((samenode == false) || (online == false)) && files) { files.Stop(); files = null; }
|
|
}
|
|
|
|
function onFilesStateChange(xfiles, state) {
|
|
p13Connect.value = (state == 0) ? "Připojit" : "Odpojit";
|
|
var str = StatusStrs[state];
|
|
if (files.webRtcActive == true) { str += ", WebRTC"; }
|
|
Q('p13Status').textContent = str;
|
|
switch (state) {
|
|
case 0:
|
|
// Disconnected, clear the files
|
|
QH('p13files', '');
|
|
p13filetree = null;
|
|
p13filetreelocation = [];
|
|
QH('p13currentpath', '');
|
|
QE('p13FolderUp', false);
|
|
QV('filesRecordIcon', false);
|
|
p13setActions();
|
|
if (files != null) { files.Stop(); files = null; }
|
|
break;
|
|
case 3:
|
|
p13targetpath = '';
|
|
if (files) {
|
|
files.sendText({ action: 'ls', reqid: 1, path: '' });
|
|
if (files.serverIsRecording == true) { QV('filesRecordIcon', true); }
|
|
}
|
|
break;
|
|
default:
|
|
//console.log('Unknown onFilesStateChange state', state);
|
|
break;
|
|
}
|
|
}
|
|
|
|
function CreateRemoteFiles(onFileUpdate) {
|
|
var obj = { protocol: 5 };
|
|
obj.onFileUpdate = onFileUpdate;
|
|
obj.xxStateChange = function(state) { }
|
|
obj.ProcessData = function(data) { obj.onFileUpdate(data); }
|
|
return obj;
|
|
}
|
|
|
|
// Debug Only
|
|
var autoConnectFilesTimer = null;
|
|
function autoConnectFiles(e) { if (autoConnectFilesTimer == null) { autoConnectFilesTimer = setInterval(connectFiles, 100); } else { clearInterval(autoConnectFilesTimer); autoConnectFilesTimer = null; } }
|
|
|
|
function connectFiles(e) {
|
|
p13clearConsoleMsg();
|
|
if (!files) {
|
|
// Setup a mesh agent files
|
|
files = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotFiles), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
|
|
files.attemptWebRTC = attemptWebRTC;
|
|
files.onStateChanged = onFilesStateChange;
|
|
files.onConsoleMessageChange = function () {
|
|
p13clearConsoleMsg();
|
|
if (files.consoleMessage) {
|
|
QH('p13FilesConsoleMsg', EscapeHtml(files.consoleMessage).split('\n').join('<br />'));
|
|
QV('p13FilesConsoleMsg', true);
|
|
p13FilesConsoleMsgTimer = setTimeout(p13clearConsoleMsg, 8000);
|
|
}
|
|
}
|
|
files.Start(filesNode._id);
|
|
} else {
|
|
//QH('Term', '');
|
|
files.Stop();
|
|
files = null;
|
|
}
|
|
p13clipboard = p13clipboardFolder = null;
|
|
p13clipboardCut = 0;
|
|
p13updateClipview();
|
|
}
|
|
|
|
var p13filetree = null;
|
|
var p13targetpath = null;
|
|
var p13filetreelocation = [];
|
|
|
|
function p13gotFiles(data) {
|
|
if ((data.length > 0) && (data.charCodeAt(0) != 123)) { p13gotDownloadBinaryData(data); return; }
|
|
//console.log('p13gotFiles', data);
|
|
data = JSON.parse(decode_utf8(data));
|
|
if (data.action == 'download') { p13gotDownloadCommand(data); return; }
|
|
data.path = data.path.replace(/\//g, '\\');
|
|
if ((p13filetree != null) && (data.path == p13filetree.path)) {
|
|
// This is an update to the same folder
|
|
var checkedNames = p13getCheckedNames();
|
|
p13filetree = data;
|
|
p13updateFiles(checkedNames);
|
|
} else {
|
|
// Make both paths use the same seperator not start with /
|
|
var x1 = data.path.replace(/\//g, '\\'), x2 = p13targetpath.replace(/\//g, '\\');
|
|
while ((x1.length > 0) && (x1[0] == '\\')) { x1 = x1.substring(1); }
|
|
while ((x2.length > 0) && (x2[0] == '\\')) { x2 = x2.substring(1); }
|
|
if ((x1 == x2) || ((data.path == '\\') && (p13targetpath == ''))) {
|
|
// This is a different folder
|
|
p13filetree = data;
|
|
p13updateFiles();
|
|
}
|
|
}
|
|
}
|
|
|
|
function p13getCheckedNames() {
|
|
// Save all existing checked boxes
|
|
var checkedNames = [], checkboxes = document.getElementsByName('fd');
|
|
for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { checkedNames.push(p13filetree.dir[checkboxes[i].value].n) }; }
|
|
return checkedNames;
|
|
}
|
|
|
|
function p13updateFiles(checkedNames) {
|
|
var html1 = '', html2 = '', displayPath = '<a href=# style=cursor:pointer onclick="return p13folderup(0)">' + "Root" + '</a>', fullPath = 'Root';
|
|
|
|
// Work on parsing the file path
|
|
var x = p13filetree.path.split('\\');
|
|
p13filetreelocation = [];
|
|
for (var i in x) { if (x[i] != '') { p13filetreelocation.push(x[i]); } } // Remove empty spaces
|
|
for (var i in p13filetreelocation) { displayPath += ' / <a href=# style=cursor:pointer onclick="return p13folderup(' + (parseInt(i) + 1) + ')">' + p13filetreelocation[i] + '</a>' } // Setup the path we display
|
|
var newlinkpath = p13filetreelocation.join('/');
|
|
|
|
// Sort the files
|
|
var filetreexx = p13sort_files(p13filetree.dir);
|
|
|
|
// Display all files and folders at this location
|
|
for (var i in filetreexx) {
|
|
// Figure out the name and shortname
|
|
var f = filetreexx[i], name = f.n, shortname;
|
|
shortname = name;
|
|
if (name.length > 70) { shortname = '<span title="' + EscapeHtml(name) + '">' + EscapeHtml(name.substring(0, 70)) + ("..." + '</span>'); } else { shortname = EscapeHtml(name); }
|
|
name = EscapeHtml(name);
|
|
|
|
// Figure out the date
|
|
var fdatestr = '';
|
|
if (f.d != null) { var fdate = new Date(f.d), fdatestr = printDateTime(fdate) + ' '; }
|
|
|
|
// Figure out the size
|
|
var fsize = '';
|
|
if (f.s != null) { fsize = getFileSizeStr(f.s); }
|
|
|
|
var h = '';
|
|
if (f.t < 3) {
|
|
var right = '', title = '';
|
|
h = '<div class=filelist file=999><input file=999 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'> <span style=float:right title=\"' + title + '\">' + right + '</span><span><div class=fileIcon' + f.t + ' onclick=p13folderset(\"' + encodeURIComponent(f.nx) + '\")></div><a href=# style=cursor:pointer onclick=\'return p13folderset(\"' + encodeURIComponent(f.nx) + '\")\'>' + shortname + '</a></span></div>';
|
|
} else {
|
|
var link = shortname;
|
|
if (f.s > 0) { link = '<a hrf=# rel=\"noreferrer noopener\" target=\"_blank\" style=cursor:pointer onclick=\"return p13downloadfile(\'' + encodeURIComponent(newlinkpath + '/' + name) + '\',\'' + encodeURIComponent(name) + '\',' + f.s + ')\">' + shortname + '</a>'; }
|
|
h = '<div class=filelist file=3><input file=3 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'> <span class=fsize>' + fdatestr + '</span><span style=float:right>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
|
|
}
|
|
|
|
if (f.t < 3) { html1 += h; } else { html2 += h; }
|
|
}
|
|
|
|
// Display the files and path
|
|
QH('p13files', html1 + html2);
|
|
QH('p13currentpath', displayPath);
|
|
QE('p13FolderUp', p13filetreelocation.length != 0);
|
|
|
|
// Re-check all boxes if needed using names
|
|
if (checkedNames != null) { var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkedNames.indexOf(p13filetree.dir[checkboxes[i].value].n) >= 0) { checkboxes[i].checked = true; } } }
|
|
|
|
// Update the actions buttons
|
|
p13setActions();
|
|
}
|
|
|
|
function p13folderset(x) {
|
|
p13targetpath = joinPaths(p13filetree.path, p13filetree.dir[x].n).split('\\').join('/');
|
|
files.sendText({ action: 'ls', reqid: 1, path: p13targetpath });
|
|
}
|
|
|
|
function p13folderup(x) {
|
|
if (x == null) { p13filetreelocation.pop(); } else { while (p13filetreelocation.length > x) { p13filetreelocation.pop(); } }
|
|
p13targetpath = p13filetreelocation.join('/');
|
|
files.sendText({ action: 'ls', reqid: 1, path: p13targetpath });
|
|
return false;
|
|
}
|
|
|
|
var p13sortorder;
|
|
function p13sort_filename(a, b) { if (a.ln > b.ln) return (1 * p13sortorder); if (a.ln < b.ln) return (-1 * p13sortorder); return 0; }
|
|
function p13sort_timestamp(a, b) { if (a.d > b.d) return (1 * p13sortorder); if (a.d < b.d) return (-1 * p13sortorder); return 0; }
|
|
function p13sort_bysize(a, b) { if (a.s == b.s) return p13sort_filename(a, b); return (((a.s - b.s)) * p13sortorder); }
|
|
|
|
function p13sort_files(files) {
|
|
var r = [], sortselection = Q('p13sortdropdown').value;
|
|
for (var i in files) { files[i].nx = i; if (files[i].s == null) { files[i].s = 0; } if (files[i].n == null) { files[i].n = i; } files[i].ln = files[i].n.toLowerCase(); r.push(files[i]); }
|
|
p13sortorder = 1;
|
|
if (sortselection > 3) { p13sortorder = -1; sortselection -= 3; }
|
|
if (sortselection == 1) { r.sort(p13sort_filename); }
|
|
else if (sortselection == 2) { r.sort(p13sort_bysize); }
|
|
else if (sortselection == 3) { r.sort(p13sort_timestamp); }
|
|
return r;
|
|
}
|
|
|
|
function p13setActions() {
|
|
if (p13filetree == null) {
|
|
QE('p13DeleteFileButton', false);
|
|
QE('p13NewFolderButton', false);
|
|
QE('p13UploadButton', false);
|
|
QE('p13RenameFileButton', false);
|
|
QE('p13ViewFileButton', false);
|
|
QE('p13SelectAllButton', false);
|
|
Q('p13SelectAllButton').value = "Vybrat vše";
|
|
QE('p13RefreshButton', false);
|
|
QE('p13CutButton', false);
|
|
QE('p13CopyButton', false);
|
|
QE('p13PasteButton', false);
|
|
} else {
|
|
var cc = p13getFileSelCount(), tc = p13getFileCount(), sfc = p13getFileSelCount(false); // In order: number of entires selected, number of total entries, number of selected entires that are files (not folders)
|
|
var winAgent = ((currentNode.agent.id > 0) && (currentNode.agent.id < 5));
|
|
QE('p13DeleteFileButton', (cc > 0) && ((p13filetreelocation.length > 0) || (winAgent == false)));
|
|
QE('p13NewFolderButton', ((p13filetreelocation.length > 0) || (winAgent == false)));
|
|
QE('p13UploadButton', ((p13filetreelocation.length > 0) || (winAgent == false)));
|
|
QE('p13RenameFileButton', (cc == 1) && ((p13filetreelocation.length > 0) || (winAgent == false)));
|
|
QE('p13ViewFileButton', (cc == 1) && (sfc == 1) && ((p13filetreelocation.length > 0) || (winAgent == false)));
|
|
QE('p13SelectAllButton', tc > 0);
|
|
Q('p13SelectAllButton').value = (cc > 0 ? "Vybrat nic" : "Vybrat vše");
|
|
QE('p13RefreshButton', true);
|
|
QE('p13CutButton', (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
|
|
QE('p13CopyButton', (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
|
|
QE('p13PasteButton', ((p13filetreelocation.length > 0) || (winAgent == false)) && ((p13clipboard != null) && (p13clipboard.length > 0)));
|
|
}
|
|
}
|
|
|
|
function p13getFileSelCount(includeDirs) { var cc = 0; var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == '3'))) cc++; } return cc; }
|
|
function p13getFileSelDirCount() { var cc = 0, checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == '999')) cc++; } return cc; }
|
|
function p13getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fd'); return checkboxes.length; }
|
|
function p13selectallfile() { var nv = (p13getFileSelCount() == 0), checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p13setActions(); }
|
|
function p13createfolder() { setDialogMode(2, "Nový adresář", 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 cc = p13getFileSelCount(), rec = (p13getFileSelDirCount() > 0) ? '<br /><br /><label><input type=checkbox id=p13recdeleteinput>' + "Rekurzivní mazání" + '</label><br>' : '<input type=checkbox id=p13recdeleteinput style=\'display:none\'>'; setDialogMode(2, "Smazat", 3, p13deletefileEx, (cc > 1) ? (format("Smazat {0} vybrané prvky?", cc) + rec) : ("Smazat vybraný prvek?" + rec)); }
|
|
function p13deletefileEx() { var delfiles = [], checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { delfiles.push(p13filetree.dir[checkboxes[i].value].n); } } files.sendText({ action: 'rm', reqid: 1, path: p13filetreelocation.join('/'), delfiles: delfiles, rec: Q('p13recdeleteinput').checked }); p13folderup(999); }
|
|
function p13renamefile() { var renamefile, checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { renamefile = p13filetree.dir[checkboxes[i].value].n; } } setDialogMode(2, "Přejmenovat", 3, p13renamefileEx, '<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% value="' + renamefile + '" />', { action: 'rename', path: p13filetreelocation.join('/'), oldname: renamefile}); focusTextBox('p13renameinput'); p13fileNameCheck(); }
|
|
function p13renamefileEx(b, t) { t.newname = Q('p13renameinput').value; files.sendText(t); p13folderup(999); }
|
|
function p13fileNameCheck(e) { var x = isFilenameValid(Q('p13renameinput').value); QE('idx_dlgOkButton', x); if ((x == true) && (e != null) && (e.keyCode == 13)) { dialogclose(1); } }
|
|
function p13uploadFile() { setDialogMode(2, "Nahrát soubor", 3, p13uploadFileEx, '<input type=file name=files id=p13uploadinput style=width:100% multiple=multiple onchange="updateUploadDialogOk(\'p13uploadinput\')" />'); updateUploadDialogOk('p13uploadinput'); }
|
|
function updateUploadDialogOk(x) { QE('idx_dlgOkButton', Q('p13uploadinput').files.length > 0); }
|
|
function p13uploadFileEx() { p13doUploadFiles(Q('p13uploadinput').files); }
|
|
function p13viewfile() {
|
|
var checkboxes = document.getElementsByName('fd');
|
|
for (var i = 0; i < checkboxes.length; i++) {
|
|
if (checkboxes[i].checked) {
|
|
if (p13filetree.dir[checkboxes[i].value].s <= 204800) {
|
|
p13downloadfile(encodeURIComponent(p13filetreelocation.join('/') + '/' + p13filetree.dir[checkboxes[i].value].n), encodeURIComponent(p13filetree.dir[checkboxes[i].value].n), p13filetree.dir[checkboxes[i].value].s, 'viewer');
|
|
} else { messagebox("Editor souborů", "Jen soubory menší než 200k mohou být editovány."); }
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
var p13clipboard = null, p13clipboardFolder = null, p13clipboardCut = 0;
|
|
function p13copyFile(cut) { var checkboxes = document.getElementsByName('fd'); p13clipboard = []; p13clipboardCut = cut, p13clipboardFolder = p13targetpath; for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == '3')) { p13clipboard.push(p13filetree.dir[checkboxes[i].value].n); } } p13updateClipview(); }
|
|
function p13pasteFile() {
|
|
var x = '';
|
|
if ((p13clipboard != null) && (p13clipboard.length > 0)) {
|
|
if (p13clipboardCut == 0) {
|
|
if (p13clipboard.length > 1) { x = format("Potvrdit kopírování {0} zaznámů do tohoto umístění?", p13clipboard.length); } else { x = format("Potvrdit kopírování jednoho záznamu do tohoto umístění?"); }
|
|
} else {
|
|
if (p13clipboard.length > 1) { x = format("Potvrdit přesun {0} záznamů do tohoto umístění?", p13clipboard.length); } else { x = format("Potvrdit přesun jednoho záznamu do tohoto umístění?"); }
|
|
}
|
|
}
|
|
setDialogMode(2, "Vložit", 3, p13pasteFileEx, x);
|
|
}
|
|
function p13pasteFileEx() { files.sendText({ action: (p13clipboardCut == 0?'copy':'move'), reqid: 1, scpath: p13clipboardFolder, dspath: p13targetpath, names: p13clipboard }); p13folderup(999); if (p13clipboardCut == 1) { p13clipboard = null, p13clipboardFolder = null, p13clipboardCut = 0; p13updateClipview(); } }
|
|
function p13updateClipview() {
|
|
var x = '';
|
|
if ((p13clipboard != null) && (p13clipboard.length > 0)) {
|
|
if (p13clipboardCut == 0) {
|
|
if (p13clipboard.length > 1) {
|
|
x = format("Držím {0} záznamů pro kopii" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Vymazat" + '</a>.', p13clipboard.length);
|
|
} else {
|
|
x = format("Držím jeden záznam pro kopii" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Vymazat" + '</a>.');
|
|
}
|
|
} else {
|
|
if (p13clipboard.length > 1) {
|
|
x = format("Držím {0} zaznamů pro přesun" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Vymazat" + '</a>.', p13clipboard.length);
|
|
} else {
|
|
x = format("Držím jeden záznam pro přesun" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Vymazat" + '</a>.');
|
|
}
|
|
}
|
|
}
|
|
QH('p13bottomstatus', x);
|
|
p13setActions();
|
|
}
|
|
function p13clearClip() { p13clipboard = null; p13clipboardFolder = null; p13clipboardCut = 0; p13updateClipview(); return false; }
|
|
|
|
function p13fileDragDrop(e) {
|
|
haltEvent(e);
|
|
QV('p13bigfail', false);
|
|
QV('p13bigok', false);
|
|
if (e.dataTransfer == null || e.dataTransfer.files.length == 0 || p13filetree == null) return;
|
|
|
|
// Check if these are files we can upload, remove all folders.
|
|
var files = [];
|
|
for (var i in e.dataTransfer.files) { if ((e.dataTransfer.files[i].size != null) && (e.dataTransfer.files[i].size != 0)) { files.push(e.dataTransfer.files[i]); } }
|
|
if (files.length == 0) return;
|
|
|
|
p13doUploadFiles(files);
|
|
}
|
|
|
|
var p13dragtimer = null;
|
|
function p13fileDragOver(e) {
|
|
haltEvent(e);
|
|
if (p13dragtimer != null) { clearTimeout(p13dragtimer); p13dragtimer = null; }
|
|
var ac = (p13filetree != null); // Set to true if we can accept the file
|
|
QV('p13bigok', ac);
|
|
QV('p13bigfail', !ac);
|
|
}
|
|
|
|
function p13fileDragLeave(e) {
|
|
haltEvent(e);
|
|
if (e.target.id != 'p13filetable') {
|
|
QV('p13bigfail', false);
|
|
QV('p13bigok', false);
|
|
} else {
|
|
p13dragtimer = setTimeout(function () { QV('p13bigfail',false); QV('p13bigok',false); p13dragtimer=null; }, 10);
|
|
}
|
|
}
|
|
|
|
//
|
|
// FILES DOWNLOAD
|
|
//
|
|
|
|
var downloadFile; // Global state for file download
|
|
|
|
// Called by the html page to start a download, arguments are: path, file name and file size.
|
|
function p13downloadfile(x, y, z, tag) {
|
|
if (xxdialogMode || downloadFile || !files) return;
|
|
downloadFile = { path: decodeURIComponent(x), file: decodeURIComponent(y), size: z, tsize: 0, data: '', state: 0, id: Math.random(), tag: tag }
|
|
//console.log('p13downloadFileCancel', downloadFile);
|
|
files.sendText({ action: 'download', sub: 'start', id: downloadFile.id, path: downloadFile.path });
|
|
setDialogMode(2, "Stáhnout soubor", 10, p13downloadFileCancel, '<div>' + downloadFile.file + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=' + z + ' />');
|
|
}
|
|
|
|
// Called by the html page to cancel the download
|
|
function p13downloadFileCancel() { setDialogMode(0); files.sendText({ action: 'download', sub: 'cancel', id: downloadFile.id }); downloadFile = null; }
|
|
|
|
// Called by the transport when download control command is received
|
|
function p13gotDownloadCommand(cmd) {
|
|
//console.log('p13gotDownloadCommand', cmd);
|
|
if ((downloadFile == null) || (cmd.id != downloadFile.id)) return;
|
|
if (cmd.sub == 'start') { downloadFile.state = 1; files.sendText({ action: 'download', sub: 'startack', id: downloadFile.id }); }
|
|
else if (cmd.sub == 'cancel') { downloadFile = null; setDialogMode(0); }
|
|
}
|
|
|
|
// Called by the transport when binary data is received
|
|
function p13gotDownloadBinaryData(data) {
|
|
if (!downloadFile || downloadFile.state == 0) return;
|
|
if (data.length > 4) {
|
|
downloadFile.tsize += (data.length - 4); // Add to the total bytes received
|
|
downloadFile.data += data.substring(4); // Append the data
|
|
Q('d2progressBar').value = downloadFile.tsize; // Change the progress bar
|
|
}
|
|
if ((ReadInt(data, 0) & 1) != 0) { // Check end flag
|
|
if (downloadFile.tag == 'viewer') {
|
|
// View the file in the dialog box
|
|
//setDialogMode(2, downloadFile.file, 9, null, '<div style="height:400px;max-height:400px;overflow:auto"><pre>' + EscapeHtml(downloadFile.data) + '</pre></div>');
|
|
setDialogMode(2, EscapeHtml(downloadFile.file), 3, p13editSaveBack, '<textarea id=p13fileeditarea style="height:400px;max-height:400px;width:100%;overflow:auto;resize:none">' + EscapeHtml(downloadFile.data) + '</textarea>', downloadFile.file);
|
|
QS('dialog').width = 'auto';
|
|
QS('dialog').left = '100px';
|
|
QS('dialog').right = '100px';
|
|
downloadFile = null;
|
|
} else {
|
|
// Save the file to disk
|
|
saveAs(data2blob(downloadFile.data), downloadFile.file); downloadFile = null; setDialogMode(0); // Save the file
|
|
}
|
|
} else {
|
|
files.sendText({ action: 'download', sub: 'ack', id: downloadFile.id }); // Send the ACK
|
|
}
|
|
}
|
|
|
|
function p13editSaveBack(b, tag) {
|
|
var data = new TextEncoder().encode(Q('p13fileeditarea').value);
|
|
p13uploadFileContinue(1, [{ name: tag, size: data.byteLength, type: 'text/plain', xdata: data }]);
|
|
}
|
|
|
|
/*
|
|
var downloadFile; // Global state for file download
|
|
|
|
// Called by the html page to start a download, arguments are: path, file name and file size.
|
|
function p13downloadfile(x, y, z) {
|
|
if (xxdialogMode) return;
|
|
downloadFile = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotDownloadData), serverPublicNamePort, authCookie, authRelayCookie, domainUrl); // Create our websocket file transport
|
|
downloadFile.ctrlMsgAllowed = false;
|
|
downloadFile.onStateChanged = onFileDownloadStateChange;
|
|
downloadFile.xpath = decodeURIComponent(x);
|
|
downloadFile.xfile = decodeURIComponent(y);
|
|
downloadFile.xsize = z;
|
|
downloadFile.xtsize = 0;
|
|
downloadFile.xstate = 0;
|
|
downloadFile.Start(filesNode._id);
|
|
setDialogMode(2, "Download File", 10, p13downloadFileCancel, '<div>' + downloadFile.xfile + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=' + z + ' />');
|
|
}
|
|
|
|
// Called by the html page to cancel the download
|
|
function p13downloadFileCancel(button, tag) {
|
|
//console.log('p13downloadFileCancel');
|
|
downloadFile.Stop();
|
|
delete downloadFile;
|
|
downloadFile = null;
|
|
}
|
|
|
|
// Called by the file transport to indicate when the transport connection state has changed
|
|
function onFileDownloadStateChange(xdownloadFile, state) {
|
|
switch (state) {
|
|
case 0: // Transport as disconnected. If this is not part of an abort, we need to save the file
|
|
setDialogMode(0); // Close any dialog boxes if present
|
|
if ((downloadFile != null) && (downloadFile.xstate == 1)) { saveAs(data2blob(downloadFile.xdata), downloadFile.xfile); } // Save the file
|
|
break;
|
|
case 3: // Transport as connected, send a command to indicate we want to start a file download
|
|
downloadFile.send(JSON.stringify({ action: 'download', reqid: 1, path: downloadFile.xpath }));
|
|
break;
|
|
default:
|
|
console.log('Unknown onFileDownloadStateChange state', state);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Called by the transport when data is received
|
|
function p13gotDownloadData(data) {
|
|
if (downloadFile.xstate == 0) { // If state is 0, this is a command confirming if the file will be transfered.
|
|
var cmd = JSON.parse(data);
|
|
if (cmd.action == 'downloadstart') { // Yes, the file is about to start
|
|
downloadFile.xstate = 1; // Switch to state 1, we will start receiving the file data
|
|
downloadFile.xdata = ''; // Start with empty data
|
|
downloadFile.send('a'); // Send the first ACK
|
|
} else if (cmd.action == 'downloaderror') { // Problem opening this file, cancel
|
|
p13downloadFileCancel();
|
|
}
|
|
} else { // We are in the process of receiving the file
|
|
downloadFile.xtsize += (data.length); // Add to the total bytes received
|
|
downloadFile.xdata += data; // Append the data
|
|
Q('d2progressBar').value = downloadFile.xtsize; // Change the progress bar
|
|
downloadFile.send('a'); // Send the ACK
|
|
}
|
|
}
|
|
*/
|
|
|
|
//
|
|
// FILES UPLOAD
|
|
//
|
|
|
|
var uploadFile;
|
|
function p13doUploadFiles(files) {
|
|
if (xxdialogMode) return;
|
|
|
|
// Check if we are going to overwrite any files
|
|
var winAgent = ((currentNode.agent.id > 0) && (currentNode.agent.id < 5));
|
|
var targetFiles = [], overWriteCount = 0;
|
|
for (var i in p13filetree.dir) { if (winAgent) { targetFiles.push(p13filetree.dir[i].n.toLowerCase()); } else { targetFiles.push(p13filetree.dir[i].n); } }
|
|
for (var i = 0; i < files.length; i++) {
|
|
if (winAgent) {
|
|
if (targetFiles.indexOf(files[i].name.toLowerCase()) >= 0) { overWriteCount++; }
|
|
} else {
|
|
if (targetFiles.indexOf(files[i].name) >= 0) { overWriteCount++; }
|
|
}
|
|
}
|
|
|
|
if (overWriteCount == 0) {
|
|
// If no overwrite, go ahead with upload
|
|
p13uploadFileContinue(1, files);
|
|
} else {
|
|
// Otherwise, prompt for confirmation
|
|
setDialogMode(2, "Nahrát soubor", 3, p13uploadFileContinue, format("Nahrání přepíše {0} soubor{1}. Pokračovat?", overWriteCount, addLetterS(overWriteCount)), files);
|
|
}
|
|
}
|
|
|
|
function p13uploadFileContinue(b, files) {
|
|
uploadFile = {};
|
|
uploadFile.xpath = p13filetreelocation.join('/');
|
|
uploadFile.xfiles = files;
|
|
uploadFile.xfilePtr = -1;
|
|
setDialogMode(2, "Nahrát soubor", 10, p13uploadFileCancel, '<div id=p13dfileName>' + "Připojování..." + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=0 />');
|
|
p13uploadReconnect();
|
|
}
|
|
|
|
function onFileUploadStateChange(xdownloadFile, state) {
|
|
switch (state) {
|
|
case 0:
|
|
setTimeout(function () { p13folderup(9999); }, 200); // Delay the file refresh
|
|
break;
|
|
case 3:
|
|
p13uploadNextFile();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Connect again
|
|
function p13uploadReconnect() {
|
|
uploadFile.ws = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotUploadData), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
|
|
uploadFile.ws.attemptWebRTC = false;
|
|
uploadFile.ws.ctrlMsgAllowed = false;
|
|
uploadFile.ws.onStateChanged = onFileUploadStateChange;
|
|
uploadFile.ws.Start(filesNode._id);
|
|
}
|
|
|
|
// Push the next file
|
|
function p13uploadNextFile() {
|
|
uploadFile.xfilePtr++;
|
|
if (uploadFile.xfiles.length > uploadFile.xfilePtr) {
|
|
uploadFile.xptr = 0;
|
|
var file = uploadFile.xfiles[uploadFile.xfilePtr];
|
|
QH('p13dfileName', file.name);
|
|
Q('d2progressBar').max = file.size;
|
|
Q('d2progressBar').value = 0;
|
|
|
|
if (file.xdata == null) {
|
|
// Load the data
|
|
uploadFile.xreader = new FileReader();
|
|
uploadFile.xreader.onload = function () {
|
|
uploadFile.xdata = uploadFile.xreader.result;
|
|
uploadFile.ws.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength }));
|
|
};
|
|
uploadFile.xreader.readAsArrayBuffer(file);
|
|
} else {
|
|
// Data already loaded
|
|
uploadFile.xdata = file.xdata;
|
|
uploadFile.ws.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength }));
|
|
}
|
|
} else {
|
|
p13uploadFileCancel();
|
|
}
|
|
}
|
|
|
|
// Used to cancel the entire transfer.
|
|
function p13uploadFileCancel(button, tag) {
|
|
if (uploadFile != null) {
|
|
if (uploadFile.ws != null) {
|
|
uploadFile.ws.Stop();
|
|
uploadFile.ws = null;
|
|
}
|
|
uploadFile = null;
|
|
}
|
|
setDialogMode(0); // Close any dialog boxes if present
|
|
}
|
|
|
|
// Receive upload ack from the mesh agent, use this to keep sending more data
|
|
function p13gotUploadData(data) {
|
|
var cmd = JSON.parse(data);
|
|
if ((uploadFile == null) || (parseInt(uploadFile.xfilePtr) != parseInt(cmd.reqid))) { return; }
|
|
|
|
if (cmd.action == 'uploadstart') {
|
|
p13uploadNextPart(false);
|
|
for (var i = 0; i < 8; i++) { p13uploadNextPart(true); } // Send 8 more blocks of 4 k to full the websocket.
|
|
} else if (cmd.action == 'uploadack') {
|
|
p13uploadNextPart(false);
|
|
} else if (cmd.action == 'uploaderror') {
|
|
p13uploadFileCancel();
|
|
}
|
|
}
|
|
|
|
// Push the next part of the file into the websocket. If dataPriming is true, push more data only if it's not the last block of the file.
|
|
function p13uploadNextPart(dataPriming) {
|
|
var data = uploadFile.xdata;
|
|
var start = uploadFile.xptr;
|
|
var end = uploadFile.xptr + 4096;
|
|
if (end > data.byteLength) { if (dataPriming == true) { return; } end = data.byteLength; }
|
|
if (start == data.byteLength) {
|
|
if (uploadFile.ws != null) { uploadFile.ws.Stop(); uploadFile.ws = null; }
|
|
if (uploadFile.xfiles.length > uploadFile.xfilePtr + 1) { p13uploadReconnect(); } else { p13uploadFileCancel(); }
|
|
} else {
|
|
var datapart = data.slice(start, end);
|
|
uploadFile.ws.send(datapart);
|
|
uploadFile.xptr = end;
|
|
Q('d2progressBar').value = end;
|
|
}
|
|
}
|
|
|
|
//
|
|
// DEVICE EVENTS
|
|
//
|
|
|
|
var currentDeviceEvents = null;
|
|
function deviceEventsUpdate() {
|
|
var x = '', dateHeader = null;
|
|
for (var i in currentDeviceEvents) {
|
|
var event = currentDeviceEvents[i], time = new Date(event.time);
|
|
if (event.msg) {
|
|
if (event.h == null) { event.h = Math.random(); }
|
|
if (printDate(time) != dateHeader) {
|
|
if (dateHeader != null) x += '</table>';
|
|
dateHeader = printDate(time);
|
|
x += '<table class=p3eventsTable cellpadding=0 cellspacing=0><tr><td colspan=4 class=DevSt>' + dateHeader + '</td></tr>';
|
|
}
|
|
var icon = 'si3';
|
|
if (event.etype == 'user') icon = 'm2';
|
|
if (event.etype == 'server') icon = 'si3';
|
|
|
|
var msg = EscapeHtml(event.msg).split('(R)').join('®');
|
|
if (event.username) {
|
|
if ((userinfo.siteadmin & 2) && (event.userid)) {
|
|
msg = '<a href=# onclick=\'gotoUser("' + encodeURIComponent(event.userid) + '");haltEvent(event);\'>' + EscapeHtml(event.username) + '</a> → ' + msg;
|
|
} else {
|
|
msg = EscapeHtml(event.username) + ' → ' + msg;
|
|
}
|
|
}
|
|
if (event.etype == 'relay' || event.action == 'relaylog') icon = 'relayIcon16';
|
|
x += '<tr onclick=showEventDetails(' + event.h + ',1) onmouseover=eventMouseHover(this,1) onmouseout=eventMouseHover(this,0) style=cursor:pointer><td style=width:18px><div class=' + icon + '></div></td><td class=g1> </td><td class=style10>' + printTime(time) + ' - ' + msg + '</td><td class=g2> </td></tr><tr style=height:2px></tr>';
|
|
}
|
|
}
|
|
if (dateHeader != null) x += '</table>';
|
|
if (x == '') x = '<br><i>' + "Žádné události" + '</i><br><br>';
|
|
QH('p16events', x);
|
|
}
|
|
|
|
function refreshDeviceEvents() {
|
|
meshserver.send({ action: 'events', nodeid: currentNode._id, limit: parseInt(p16limitdropdown.value) });
|
|
}
|
|
|
|
function showEventDetails(h, mode) {
|
|
var eventList, xevent;
|
|
if (mode == 1) { eventList = currentDeviceEvents; }
|
|
if (mode == 2) { eventList = events; }
|
|
if (mode == 3) { eventList = currentUserEvents; }
|
|
for (var i in eventList) { if (eventList[i].h == h) { xevent = eventList[i]; break; } }
|
|
if (xevent) {
|
|
if (xxdialogMode) return false;
|
|
var x = '<div style=overflow-y:auto>';
|
|
for (var i in xevent) {
|
|
if ((i == 'h') || (i == '_id') || (i == 'ids') || (i == 'domain') || (xevent[i] == null) || (typeof xevent[i] == 'object')) continue;
|
|
x += addHtmlValue3(EscapeHtml(i), EscapeHtml(xevent[i]));
|
|
}
|
|
x += '</div>';
|
|
setDialogMode(2, "Detail události", 9, null, x);
|
|
}
|
|
}
|
|
|
|
//
|
|
// CONSOLE
|
|
//
|
|
|
|
function agentConsoleHandleKeys(e) {
|
|
if ((e.ctrlKey) || (e.altKey)) { return true; }
|
|
var processed = 0, box = Q('p15consoleText');
|
|
if (e.key) {
|
|
if (e.keyCode == 13 && consoleFocus == 0) { p15consoleSend(e); processed = 1; }
|
|
else if (e.keyCode == 8 && consoleFocus == 0) { var x = box.value; box.value = x.substring(0, x.length - 1); processed = 1; }
|
|
else if (e.keyCode == 27) { box.value = ''; processed = 1; }
|
|
else if ((e.keyCode == 38) || (e.keyCode == 40)) { // Arrow up || Arrow down
|
|
var hindex = consoleHistory.indexOf(box.value);
|
|
//console.log(hindex, consoleHistory);
|
|
if ((e.keyCode == 38) && ((consoleHistory.length - 1) > hindex)) { box.value = consoleHistory[hindex + 1]; }
|
|
else if ((e.keyCode == 40) && (hindex > 0)) { box.value = consoleHistory[hindex - 1]; }
|
|
else if ((e.keyCode == 40) && (hindex == 0)) { box.value = ''; }
|
|
processed = 1;
|
|
}
|
|
else if (e.key.length === 1) {
|
|
//box.value = ((box.value + e.key));
|
|
insertTextAtCursor(box, e.key);
|
|
processed = 1;
|
|
}
|
|
} else {
|
|
if (e.charCode != 0 && consoleFocus == 0) { box.value = ((box.value + String.fromCharCode(e.charCode))); processed = 1; }
|
|
}
|
|
if (processed > 0) { return haltEvent(e); }
|
|
}
|
|
|
|
// Insert text at the cursor location on the
|
|
function insertTextAtCursor(ctrl, val) {
|
|
if (document.selection) { ctrl.focus(); sel = document.selection.createRange(); sel.text = val; }
|
|
else if (ctrl.selectionStart || ctrl.selectionStart == '0') {
|
|
var start = ctrl.selectionStart, end = ctrl.selectionEnd;
|
|
ctrl.value = ctrl.value.substring(0, start) + val + ctrl.value.substring(end, ctrl.value.length);
|
|
ctrl.setSelectionRange(end + 1, end + 1);
|
|
} else { ctrl.value += myValue; }
|
|
}
|
|
|
|
var consoleNode;
|
|
var consoleServerText = '';
|
|
function setupConsole() {
|
|
if (xxcurrentView == 115) {
|
|
// Setup server console
|
|
var samenode = (consoleNode == 'server');
|
|
consoleNode = 'server';
|
|
|
|
QH('p15deviceName', "Moje serverová konzole");
|
|
QE('p15consoleText', true);
|
|
QH('p15statetext', '');
|
|
QH('p15coreName', '');
|
|
QV('p15outputselecttd', false);
|
|
|
|
if (samenode == false) {
|
|
QH('p15agentConsoleText', consoleServerText);
|
|
Q('p15agentConsoleText').scrollTop = Q('p15agentConsoleText').scrollHeight;
|
|
}
|
|
} else {
|
|
// Setup the console
|
|
var samenode = (consoleNode == currentNode);
|
|
consoleNode = currentNode;
|
|
|
|
var mesh = meshes[consoleNode.meshid];
|
|
var meshrights = mesh.links[userinfo._id].rights;
|
|
if ((meshrights & 16) != 0) {
|
|
if (consoleNode.consoleText == null) { consoleNode.consoleText = ''; }
|
|
if (samenode == false) {
|
|
QH('p15agentConsoleText', consoleNode.consoleText);
|
|
Q('p15agentConsoleText').scrollTop = Q('p15agentConsoleText').scrollHeight;
|
|
}
|
|
var online = (((consoleNode.conn & 1) != 0) || ((consoleNode.conn & 16) != 0)) ? true : false;
|
|
var onlineText = ((consoleNode.conn & 1) != 0) ? "Agent je online" : "Agent je offline"
|
|
if ((consoleNode.conn & 16) != 0) { onlineText += ", MQTT je online" }
|
|
QH('p15statetext', onlineText);
|
|
QE('p15consoleText', online);
|
|
QE('p15uploadCore', ((consoleNode.conn & 1) != 0));
|
|
QV('p15outputselecttd', (consoleNode.conn & 17) == 17);
|
|
} else {
|
|
QH('p15statetext', "Přístup zamítnut");
|
|
QE('p15consoleText', false);
|
|
QE('p15uploadCore', false);
|
|
QV('p15outputselecttd', false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Clear the console for this node
|
|
function p15consoleClear() {
|
|
QH('p15agentConsoleText', '');
|
|
Q('id_p15consoleClear').blur();
|
|
if (xxcurrentView == 115) {
|
|
consoleServerText = '';
|
|
} else {
|
|
consoleNode.consoleText = '';
|
|
}
|
|
}
|
|
|
|
// Send a command to the agent
|
|
var consoleHistory = [];
|
|
function p15consoleSend(e) {
|
|
if (e && e.keyCode != 13) return;
|
|
var v = Q('p15consoleText').value, t = '<div style=color:green>> ' + EscapeHtml(v) + '<br/></div>';
|
|
|
|
if (xxcurrentView == 115) {
|
|
// Send the command to the server - TODO: In the future, we may support multiple servers.
|
|
consoleServerText += t;
|
|
meshserver.send({ action: 'serverconsole', value: v });
|
|
} else {
|
|
if (((consoleNode.conn & 16) != 0) && ((Q('p15outputselect').value == 2) || ((consoleNode.conn & 1) == 0))) {
|
|
// Send the command to MQTT
|
|
t = '<div style=color:orange>' + "MQTT" + '> ' + EscapeHtml(v) + '<br/></div>';
|
|
consoleNode.consoleText += t;
|
|
meshserver.send({ action: 'sendmqttmsg', topic: 'console', nodeids: [ consoleNode._id ], msg: v });
|
|
} else {
|
|
// Send the command to the mesh agent
|
|
consoleNode.consoleText += t;
|
|
meshserver.send({ action: 'msg', type: 'console', nodeid: consoleNode._id, value: v });
|
|
}
|
|
}
|
|
|
|
Q('p15agentConsoleText').innerHTML += t;
|
|
Q('p15agentConsoleText').scrollTop = Q('p15agentConsoleText').scrollHeight;
|
|
Q('p15consoleText').value = '';
|
|
|
|
// Add command to history list
|
|
if (v.length > 0) {
|
|
// Move this command to the top if it already exists
|
|
var j = consoleHistory.indexOf(v);
|
|
if (j >= 0) { consoleHistory.splice(j, 1); }
|
|
consoleHistory.unshift(v);
|
|
consoleHistory.splice(10);
|
|
}
|
|
}
|
|
|
|
// Handle Mesh Agent console data
|
|
function p15consoleReceive(node, data, source) {
|
|
if (node === 'serverconsole') {
|
|
// Server console data
|
|
data = '<div>' + data + '</div>'
|
|
consoleServerText += data;
|
|
if (consoleNode == 'server') {
|
|
Q('p15agentConsoleText').innerHTML += data;
|
|
Q('p15agentConsoleText').scrollTop = Q('p15agentConsoleText').scrollHeight;
|
|
}
|
|
} else {
|
|
// Agent console data
|
|
if (source == 'MQTT') { data = '<div style=color:red>' + "MQTT" + '> ' + EscapeHtml(data) + '<br/></div>'; } else { data = '<div>' + data + '</div>' }
|
|
if (node.consoleText == null) { node.consoleText = data; } else { node.consoleText += data; }
|
|
if (consoleNode == node) {
|
|
Q('p15agentConsoleText').innerHTML += data;
|
|
Q('p15agentConsoleText').scrollTop = Q('p15agentConsoleText').scrollHeight;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Save console text to file
|
|
function p15downloadConsoleText() {
|
|
saveAs(new Blob([Q('p15agentConsoleText').innerText], { type: 'application/octet-stream' }), "console.txt");
|
|
}
|
|
|
|
// Called then user presses the "Change Core" button
|
|
function p15uploadCore(e) {
|
|
if (xxdialogMode) return;
|
|
if (e.shiftKey == true) { meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, type: 'default' }); } // Upload default core
|
|
else if (e.altKey == true) { meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, type: 'clear' }); } // Clear the core
|
|
else if (e.ctrlKey == true) { p15uploadCore2(); } // Upload the core from a file
|
|
else { setDialogMode(2, "Akce agenta", 3, p15uploadCoreEx, addHtmlValue("Akce", '<select id=d3coreMode style=width:230px><option value=1>' + "Nahrát defaultní nastavení" + '</option><option value=2>' + "Vymazat jádro" + '</option><option value=6>' + "Nahrát jádro pro obnovu" + '</option><option value=3>' + "Nahrát hlavní soubor" + '</option><option value=4>' + "Jemné odpojení agenta" + '</option><option value=5>' + "Tvrdě odpojit aenta" + '</option></select>')); }
|
|
}
|
|
|
|
function p15uploadCoreEx() {
|
|
if (Q('d3coreMode').value == 1) {
|
|
// Upload default core
|
|
meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, type: 'default' });
|
|
} else if (Q('d3coreMode').value == 2) {
|
|
// Clear the core
|
|
meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, type: 'clear' });
|
|
} else if (Q('d3coreMode').value == 3) {
|
|
// Upload file as core
|
|
p15uploadCore2();
|
|
} else if (Q('d3coreMode').value == 4) {
|
|
// Soft disconnect the mesh agent
|
|
meshserver.send({ action: 'agentdisconnect', nodeid: consoleNode._id, disconnectMode: 1 });
|
|
} else if (Q('d3coreMode').value == 5) {
|
|
// Hard disconnect the mesh agent
|
|
meshserver.send({ action: 'agentdisconnect', nodeid: consoleNode._id, disconnectMode: 2 });
|
|
} else if (Q('d3coreMode').value == 6) {
|
|
// Upload a recovery core
|
|
meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, type:'recovery' });
|
|
}
|
|
}
|
|
|
|
// Called then user opts to upload a file as core
|
|
function p15uploadCore2() {
|
|
if (xxdialogMode) return;
|
|
Q('d3localmodeform').action = 'uploadmeshcorefile.ashx';
|
|
Q('d3auth').value = authCookie;
|
|
Q('d3attrib').value = currentNode._id;
|
|
setDialogMode(3, "Nahrát jádro agenta", 3, p15uploadCoreEx2);
|
|
d3init();
|
|
}
|
|
|
|
function p15uploadCoreEx2() {
|
|
var mode = Q('d3uploadMode').value;
|
|
if (mode == 1) {
|
|
// Upload local mesh agent core
|
|
Q('d3submit').click();
|
|
} else {
|
|
// Upload server mesh agent code
|
|
var files = d3getFileSel();
|
|
if (files.length == 1) { meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, type: 'custom', path: d3filetreelocation.join('/') + '/' + files[0] }); }
|
|
}
|
|
}
|
|
|
|
//
|
|
// MY ACCOUNT
|
|
//
|
|
|
|
function account_manageAuthApp() {
|
|
if (xxdialogMode || ((features & 4096) == 0)) return;
|
|
if (userinfo.otpsecret == 1) { account_removeOtp(); } else { account_addOtp(); }
|
|
return false;
|
|
}
|
|
|
|
function account_addOtp() {
|
|
if (xxdialogMode || (userinfo.otpsecret == 1) || ((features & 4096) == 0)) return;
|
|
setDialogMode(2, "Aplikace pro autentizaci", 2, function () { meshserver.send({ action: 'otpauth-setup', secret: Q('d2optsecret').attributes.secret.value, token: Q('d2otpauthinput').value }); }, ('<div id=d2optinfo>' + "Nahrávání..." + '</div>'), 'otpauth-request');
|
|
meshserver.send({ action: 'otpauth-request' });
|
|
}
|
|
|
|
function account_addOtpCheck(e) {
|
|
var tokenIsValid = (Q('d2otpauthinput').value.length == 6);
|
|
QE('idx_dlgOkButton', tokenIsValid);
|
|
if (e && (e.keyCode == 13) && tokenIsValid) { dialogclose(1); }
|
|
}
|
|
|
|
function account_removeOtp() {
|
|
if (xxdialogMode || (userinfo.otpsecret != 1) || ((features & 4096) == 0)) return;
|
|
setDialogMode(2, "Aplikace pro autentizaci", 3, function () { meshserver.send({ action: 'otpauth-clear' }); }, "Potvrdit odstranění autentizační aplikace pro 2-faktorové přihlašování?");
|
|
}
|
|
|
|
function account_manageOtp(action) {
|
|
if ((xxdialogMode == 2) && (xxdialogTag == 'otpauth-manage')) { dialogclose(0); }
|
|
if (xxdialogMode || ((features & 4096) == 0)) return false;
|
|
if ((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0)) { meshserver.send({ action: 'otpauth-getpasswords', subaction: action }); }
|
|
return false;
|
|
}
|
|
|
|
function account_manageHardwareOtp() {
|
|
if ((xxdialogMode == 2) && (xxdialogTag == 'otpauth-hardware-manage')) { dialogclose(0); }
|
|
if (xxdialogMode || ((features & 4096) == 0)) return false;
|
|
meshserver.send({ action: 'otp-hkey-get' });
|
|
return false;
|
|
}
|
|
|
|
function account_addhkey(type) {
|
|
if (type == 3) {
|
|
var x = "Napište jméno klíče pro přidání." + '<br /><br />';
|
|
x += addHtmlValue("Jméno klíče", '<input id=dp1keyname style=width:230px maxlength=20 autocomplete=off placeholder="' + "MyKey" + '" onkeyup=account_addhkeyValidate(event,2) />');
|
|
} else if (type == 2) {
|
|
var x = "Zadejte název klíče, vyberte pole OTP a stiskněte tlačítko na YubiKey™." + '<br /><br />';
|
|
x += addHtmlValue("Jméno klíče", '<input id=dp1keyname style=width:230px maxlength=20 autocomplete=off placeholder="' + "MyKey" + '" onkeyup=account_addhkeyValidate(event,1) />');
|
|
x += addHtmlValue("YubiKey™ OTP", '<input id=dp1key style=width:230px autocomplete=off onkeyup=account_addhkeyValidate(event,2) />');
|
|
}
|
|
setDialogMode(2, "Přidat bezpečnostní klíč", 3, account_addhkeyEx, x, type);
|
|
Q('dp1keyname').focus();
|
|
}
|
|
|
|
function account_addhkeyValidate(e,action) {
|
|
if ((e != null) && (e.keyCode == 13)) { if (action == 2) { dialogclose(1); } else { Q('dp1key').focus(); } }
|
|
}
|
|
|
|
function account_addhkeyEx(button, type) {
|
|
var name = Q('dp1keyname').value;
|
|
if (name == '') { name = 'MyKey'; }
|
|
if (type == 2) {
|
|
meshserver.send({ action: 'otp-hkey-yubikey-add', name: name, otp: Q('dp1key').value });
|
|
setDialogMode(2, "Přidat bezpečnostní klíč", 0, null, '<br />' + "Kontrola..." + '<br /><br /><br />', 'otpauth-hardware-manage');
|
|
} else if (type == 3) {
|
|
meshserver.send({ action: 'webauthn-startregister', name: name });
|
|
}
|
|
}
|
|
|
|
function account_removehkey(index) {
|
|
meshserver.send({ action: 'otp-hkey-remove', index: index });
|
|
meshserver.send({ action: 'otp-hkey-get' });
|
|
}
|
|
|
|
var loclist = { 'af': "Afrikaans", 'sq': "Albanian", 'ar': "Arabic (Standard)", 'ar-dz': "Arabic (Algeria)", 'ar-bh': "Arabic (Bahrain)", 'ar-eg': "Arabic (Egypt)", 'ar-iq': "Arabic (Iraq)", 'ar-jo': "Arabic (Jordan)", 'ar-kw': "Arabic (Kuwait)", 'ar-lb': "Arabic (Lebanon)", 'ar-ly': "Arabic (Libya)", 'ar-ma': "Arabic (Morocco)", 'ar-om': "Arabic (Oman)", 'ar-qa': "Arabic (Qatar)", 'ar-sa': "Arabic (Saudi Arabia)", 'ar-sy': "Arabic (Syria)", 'ar-tn': "Arabic (Tunisia)", 'ar-ae': "Arabic (U.A.E.)", 'ar-ye': "Arabic (Yemen)", 'an': "Aragonese", 'hy': "Armenian", 'as': "Assamese", 'ast': "Asturian", 'az': "Azerbaijani", 'eu': "Basque", 'bg': "Bulgarian", 'be': "Belarusian", 'bn': "Bengali", 'bs': "Bosnian", 'br': "Breton", 'my': "Burmese", 'ca': "Catalan", 'ch': "Chamorro", 'ce': "Chechen", 'zh': "Chinese", 'zh-hk': "Chinese (Hong Kong)", 'zh-cn': "Chinese (PRC)", 'zh-sg': "Chinese (Singapore)", 'zh-tw': "Chinese (Taiwan)", 'cv': "Chuvash", 'co': "Corsican", 'cr': "Cree", 'hr': "Croatian", 'cs': "Czech", 'da': "Danish", 'nl': "Dutch (Standard)", 'nl-be': "Dutch (Belgian)", 'en': "English", 'en-au': "English (Australia)", 'en-bz': "English (Belize)", 'en-ca': "English (Canada)", 'en-ie': "English (Ireland)", 'en-jm': "English (Jamaica)", 'en-nz': "English (New Zealand)", 'en-ph': "English (Philippines)", 'en-za': "English (South Africa)", 'en-tt': "English (Trinidad & Tobago)", 'en-gb': "English (United Kingdom)", 'en-us': "English (United States)", 'en-zw': "English (Zimbabwe)", 'eo': "Esperanto", 'et': "Estonian", 'fo': "Faeroese", 'fa': "Farsi (Persian)", 'fj': "Fijian", 'fi': "Finnish", 'fr': "French (Standard)", 'fr-be': "French (Belgium)", 'fr-ca': "French (Canada)", 'fr-fr': "French (France)", 'fr-lu': "French (Luxembourg)", 'fr-mc': "French (Monaco)", 'fr-ch': "French (Switzerland)", 'fy': "Frisian", 'fur': "Friulian", 'gd': "Gaelic (Scots)", 'gd-ie': "Gaelic (Irish)", 'gl': "Galacian", 'ka': "Georgian", 'de': "German (Standard)", 'de-at': "German (Austria)", 'de-de': "German (Germany)", 'de-li': "German (Liechtenstein)", 'de-lu': "German (Luxembourg)", 'de-ch': "German (Switzerland)", 'el': "Greek", 'gu': "Gujurati", 'ht': "Haitian", 'he': "Hebrew", 'hi': "Hindi", 'hu': "Hungarian", 'is': "Icelandic", 'id': "Indonesian", 'iu': "Inuktitut", 'ga': "Irish", 'it': "Italian (Standard)", 'it-ch': "Italian (Switzerland)", 'ja': "Japanese", 'kn': "Kannada", 'ks': "Kashmiri", 'kk': "Kazakh", 'km': "Khmer", 'ky': "Kirghiz", 'tlh': "Klingon", 'ko': "Korean", 'ko-kp': "Korean (North Korea)", 'ko-kr': "Korean (South Korea)", 'la': "Latin", 'lv': "Latvian", 'lt': "Lithuanian", 'lb': "Luxembourgish", 'mk': "FYRO Macedonian", 'ms': "Malay", 'ml': "Malayalam", 'mt': "Maltese", 'mi': "Maori", 'mr': "Marathi", 'mo': "Moldavian", 'nv': "Navajo", 'ng': "Ndonga", 'ne': "Nepali", 'no': "Norwegian", 'nb': "Norwegian (Bokmal)", 'nn': "Norwegian (Nynorsk)", 'oc': "Occitan", 'or': "Oriya", 'om': "Oromo", 'fa-ir': "Persian/Iran", 'pl': "Polish", 'pt': "Portuguese", 'pt-br': "Portuguese (Brazil)", 'pa': "Punjabi", 'pa-in': "Punjabi (India)", 'pa-pk': "Punjabi (Pakistan)", 'qu': "Quechua", 'rm': "Rhaeto-Romanic", 'ro': "Romanian", 'ro-mo': "Romanian (Moldavia)", 'ru': "Russian", 'ru-mo': "Russian (Moldavia)", 'sz': "Sami (Lappish)", 'sg': "Sango", 'sa': "Sanskrit", 'sc': "Sardinian", 'sd': "Sindhi", 'si': "Singhalese", 'sr': "Serbian", 'sk': "Slovak", 'sl': "Slovenian", 'so': "Somani", 'sb': "Sorbian", 'es': "Spanish", 'es-ar': "Spanish (Argentina)", 'es-bo': "Spanish (Bolivia)", 'es-cl': "Spanish (Chile)", 'es-co': "Spanish (Colombia)", 'es-cr': "Spanish (Costa Rica)", 'es-do': "Spanish (Dominican Republic)", 'es-ec': "Spanish (Ecuador)", 'es-sv': "Spanish (El Salvador)", 'es-gt': "Spanish (Guatemala)", 'es-hn': "Spanish (Honduras)", 'es-mx': "Spanish (Mexico)", 'es-ni': "Spanish (Nicaragua)", 'es-pa': "Spanish (Panama)", 'es-py': "Spanish (Paraguay)", 'es-pe': "Spanish (Peru)", 'es-pr': "Spanish (Puerto Rico)", 'es-es': "Spanish (Spain)", 'es-uy': "Spanish (Uruguay)", 'es-ve': "Spanish (Venezuela)", 'sx': "Sutu", 'sw': "Swahili", 'sv': "Swedish", 'sv-fi': "Swedish (Finland)", 'sv-sv': "Swedish (Sweden)", 'ta': "Tamil", 'tt': "Tatar", 'te': "Teluga", 'th': "Thai", 'tig': "Tigre", 'ts': "Tsonga", 'tn': "Tswana", 'tr': "Turkish", 'tk': "Turkmen", 'uk': "Ukrainian", 'hsb': "Upper Sorbian", 'ur': "Urdu", 've': "Venda", 'vi': "Vietnamese", 'vo': "Volapuk", 'wa': "Walloon", 'cy': "Welsh", 'xh': "Xhosa", 'ji': "Yiddish", 'zu': "Zulu" };
|
|
function account_showLocalizationSettings() {
|
|
if (xxdialogMode) return false;
|
|
var n = getstore('loctag', 0), y = '';
|
|
var x = '<select id=d2locselect style=width:240px><option value=\"*\">' + "Hodnota uživatelského prohlížeče" + '</option>';
|
|
for (var i in loclist) { x += '<option value="' + i + '"' + ((n == i)?' selected':'') + '>' + i + ' - ' + loclist[i] + '</option>'; }
|
|
x += '</select>';
|
|
if (serverinfo.languages && serverinfo.languages.length > 0) {
|
|
y += "Změna jazyka vyžaduje obnovení stránky." + '<br /><br />';
|
|
var z = '<select id=d2langselect style=width:240px><option value=\"*\">' + "Hodnota uživatelského prohlížeče" + '</option>';
|
|
for (var i in serverinfo.languages) {
|
|
var lang = serverinfo.languages[i];
|
|
z += '<option value="' + lang + '"' + ((userinfo.lang == lang)?' selected':'') + '>' + lang + ' - ' + loclist[lang] + '</option>';
|
|
}
|
|
z += '</select>';
|
|
y += addHtmlValue("Jazyk", z);
|
|
}
|
|
y += addHtmlValue("Datum & čas", x);
|
|
|
|
if ((userinfo.siteadmin == 0xFFFFFFFF) && (domain == '')) {
|
|
y += '<br /><a rel="noreferrer noopener" target="_blank" href="translator.htm">' + "Pomoct přeložit MeshCentral" + '</a>';
|
|
}
|
|
|
|
setDialogMode(2, "Nastavení lokalizace", 3, account_showLocalizationSettingsEx, y);
|
|
return false;
|
|
}
|
|
|
|
function account_showLocalizationSettingsEx() {
|
|
// Set user language
|
|
var lang = Q('d2langselect').value;
|
|
if ((lang == '*') && (userinfo.lang == null)) { lang = userinfo.lang; }
|
|
if (lang != userinfo.lang) { meshserver.send({ action: 'changelang', lang: lang }); }
|
|
|
|
// Set date localization
|
|
var n = getstore('loctag', 0);
|
|
var m = Q('d2locselect').value;
|
|
if (n != m) {
|
|
if (m != '*') { args.locale = m; } else { delete args.locale; }
|
|
putstore('loctag', args.locale);
|
|
masterUpdate(0xFFFFFFFF); // Refresh everything.
|
|
}
|
|
}
|
|
|
|
function account_enableNotifications() {
|
|
if (Notification) { Notification.requestPermission().then(function (permission) { QV('accountEnableNotificationsSpan', permission != 'granted'); }); }
|
|
return false;
|
|
}
|
|
|
|
function account_showAccountNotifySettings() {
|
|
if (xxdialogMode) return false;
|
|
var x = '';
|
|
x += '<div><label><input id=p2notifyPlayNotifySound type=checkbox />' + "Zvuk notifikací" + '</label></div>';
|
|
x += '<div><label><input id=p2notifyIntelDeviceConnect type=checkbox />' + "Připojení zařízení" + '</label></div>';
|
|
x += '<div><label><input id=p2notifyIntelDeviceDisconnect type=checkbox />' + "Odpojení zařízení" + '</label></div>';
|
|
x += '<div><label><input id=p2notifyIntelAmtKvmActions type=checkbox />' + "Intel® AMT desktop and serial události." + '</label></div>';
|
|
setDialogMode(2, "Nastavení notifikací", 3, account_showAccountNotifySettingsEx, x);
|
|
var n = getstore('notifications', 0);
|
|
Q('p2notifyPlayNotifySound').checked = (n & 1);
|
|
Q('p2notifyIntelDeviceConnect').checked = (n & 2);
|
|
Q('p2notifyIntelDeviceDisconnect').checked = (n & 4);
|
|
Q('p2notifyIntelAmtKvmActions').checked = (n & 8);
|
|
return false;
|
|
}
|
|
|
|
function account_showAccountNotifySettingsEx() {
|
|
var n = 0;
|
|
n += Q('p2notifyPlayNotifySound').checked ? 1 : 0;
|
|
n += Q('p2notifyIntelDeviceConnect').checked ? 2 : 0;
|
|
n += Q('p2notifyIntelDeviceDisconnect').checked ? 4 : 0;
|
|
n += Q('p2notifyIntelAmtKvmActions').checked ? 8 : 0;
|
|
putstore('notifications', n);
|
|
}
|
|
|
|
function account_showVerifyEmail() {
|
|
if (xxdialogMode || (userinfo.emailVerified == true) || (serverinfo.emailcheck != true)) return false;
|
|
var x = "Klikni na OK pro zaslání verifikačního emailu na:" + '<br /><div style=padding:8px><b>' + EscapeHtml(userinfo.email) + '</b></div>' + "Prosím počkejte pár minut než dojde k verifikaci.";
|
|
setDialogMode(2, "Ověření emailu", 3, account_showVerifyEmailEx, x);
|
|
return false;
|
|
}
|
|
|
|
function account_showVerifyEmailEx() {
|
|
meshserver.send({ action: 'verifyemail', email: userinfo.email });
|
|
}
|
|
|
|
function account_showChangeEmail() {
|
|
if (xxdialogMode) return false;
|
|
var x = "Změň si svůj email zde." + '<br /><br />';
|
|
x += addHtmlValue('Email', '<input id=dp2email style=width:230px maxlength=256 onchange=account_validateEmail() onkeyup=account_validateEmail(event) />');
|
|
setDialogMode(2, "Změna emailové adresy", 3, account_changeEmail, x);
|
|
if (userinfo.email != null) { Q('dp2email').value = userinfo.email; }
|
|
account_validateEmail();
|
|
Q('dp2email').focus();
|
|
return false;
|
|
}
|
|
|
|
function account_validateEmail(e, email) {
|
|
QE('idx_dlgOkButton', validateEmail(Q('dp2email').value) && (Q('dp2email').value != userinfo.email));
|
|
if ((e != null) && (e.keyCode == 13)) { dialogclose(1); }
|
|
}
|
|
|
|
function account_changeEmail() {
|
|
meshserver.send({ action: 'changeemail', email: Q('dp2email').value });
|
|
}
|
|
|
|
function account_showDeleteAccount() {
|
|
if (xxdialogMode) return false;
|
|
var x = "Chcete-li tento účet smazat, zadejte do obou políček heslo k účtu a stiskněte OK." + '<br /><br />';
|
|
x += '<form method=post><input type=hidden name=action value=deleteaccount /><input type=hidden name=authcookie value=" + authCookie + " /><table style=margin-left:80px><tr>';
|
|
x += '<td align=right>' + "Heslo:" + '</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>';
|
|
x += '</tr><tr><td align=right>' + "Heslo:" + '</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>';
|
|
x += '</tr></table><br /><div style=padding:10px;margin-bottom:4px>';
|
|
x += '<input id=account_dlgCancelButton type=button value=Cancel style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>';
|
|
x += '<input id=account_dlgOkButton type=submit value=OK style="float:right;width:80px" onclick=dialogclose(1)>';
|
|
x += '</div><br /></form>';
|
|
setDialogMode(2, "Smazat účet", 0, null, x);
|
|
account_validateDeleteAccount();
|
|
Q('apassword1').focus();
|
|
return false;
|
|
}
|
|
|
|
function account_showChangePassword() {
|
|
if (xxdialogMode) return false;
|
|
var x = "Změnit heslo zadáním starého a dvakrát nového hesla níže.";
|
|
if (features & 0x00010000) { " Nápověda hesla může být použita, ale není doporučováno."; }
|
|
x += '<br /><br />';
|
|
//x += "<form action='" + domainUrl + "changepassword' method=post>";
|
|
x += '<table style=margin-left:60px>';
|
|
x += '<tr><td align=right>' + nobreak("Staré heslo:") + '</td><td><input id=apassword0 type=password name=apassword0 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /> <b></b></td></tr>';
|
|
x += '<tr><td align=right>' + nobreak("Nové heslo:") + '</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>';
|
|
x += '<tr><td align=right>' + nobreak("Nové heslo:") + '</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /></td></tr>';
|
|
if (features & 0x00010000) { x += '<tr><td align=right>' + "Nápověda k heslu:" + '</td><td><input id=apasswordhint name=apasswordhint maxlength=250 type=text autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /></td></tr>'; }
|
|
x += '</table>'
|
|
if (passRequirements) {
|
|
var r = [], rc = 0;
|
|
for (var i in passRequirements) { if ((i != 'reset') && (i != 'hint')) { r.push(i + ':' + passRequirements[i]); rc++; } }
|
|
if (rc > 0) { x += '<br /><span style=font-size:x-small>' + "Požadavky: " + r.join(', ') + '.</span>'; }
|
|
}
|
|
x += '<br />';
|
|
//x += '<br /><div style=padding:10px;margin-bottom:4px>';
|
|
//x += '<input id=account_dlgCancelButton type=button value=Cancel style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>';
|
|
//x += '<input id=account_dlgOkButton type=submit value=OK style="float:right;width:80px" onclick=dialogclose(1)>';
|
|
//x += '</div><br /></form>';
|
|
setDialogMode(2, "Změnit heslo", 3, account_showChangePasswordEx, x);
|
|
Q('apassword0').focus();
|
|
account_validateNewPassword();
|
|
return false;
|
|
}
|
|
|
|
function account_showChangePasswordEx() {
|
|
if (Q('apassword1').value == Q('apassword2').value) {
|
|
var r = { action: 'changepassword', oldpass: Q('apassword0').value, newpass: Q('apassword1').value };
|
|
if (features & 0x00010000) { r.hint = Q('apasswordhint').value; }
|
|
meshserver.send(r);
|
|
}
|
|
}
|
|
|
|
function account_createMesh() {
|
|
if (xxdialogMode) return false;
|
|
|
|
// Check if we are disallowed from creating a device group
|
|
if ((userinfo.siteadmin != 0xFFFFFFFF) && ((userinfo.siteadmin & 64) != 0)) { setDialogMode(2, "Nová skupina zařízení", 1, null, "Tento účet nemá práva k vytvoření nové skupiny zařízení."); return false; }
|
|
|
|
// Remind the user to verify the email address
|
|
if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "Nastavení bezpečnosti", 1, null, "Nelze získat přístup k zařízení, dokud nebude ověřena e-mailová adresa. To je vyžadováno pro obnovení hesla. Jdi do \"Můj účet\" pro změnu a ověření emailu."); return false; }
|
|
|
|
// Remind the user to add two factor authentication
|
|
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0))) { setDialogMode(2, "Nastavení bezpečnosti", 1, null, "Nelze získat přístup k zařízení, dokud je 2-faktorová autentizace zapnuta. Toto je pro extra bezpečnost. Jdi do \"Můj účet\" a podívej se do sekce\"Nastavení bezpečnosti\"."); return false; }
|
|
|
|
// We are allowed, let's prompt to information
|
|
var x = "Vytvořit novou skupinu zařízení podle nastavení níže." + '<br /><br />';
|
|
x += addHtmlValue("Jméno", '<input id=dp2meshname style=width:230px maxlength=64 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,1) />');
|
|
x += addHtmlValue("Typ", '<div style=width:230px;margin:0;padding:0><select id=dp2meshtype style=width:100% onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,2) ><option value=2>' + "Spravovat pomocí softwarového agenta" + '</option><option value=1>' + "Intel® AMT pouze, bez agenta" + '</option></select></div>');
|
|
x += addHtmlValue("Popis", '<div style=width:230px;margin:0;padding:0><textarea id=dp2meshdesc maxlength=1024 style=width:100%;resize:none></textarea></div>');
|
|
setDialogMode(2, "Nová skupina zařízení", 3, account_createMeshEx, x);
|
|
account_validateMeshCreate();
|
|
Q('dp2meshname').focus();
|
|
return false;
|
|
}
|
|
|
|
function account_validateMeshCreate(e, x) {
|
|
if ((x == 1) && (e != null) && (e.key == "Zadání") && (Q('dp2meshname').value.length > 0)) { Q('dp2meshtype').focus(); }
|
|
if ((x == 2) && (e != null) && (e.key == "Zadání")) { Q('dp2meshdesc').focus(); }
|
|
QE('idx_dlgOkButton', Q('dp2meshname').value.length > 0);
|
|
}
|
|
|
|
function account_createMeshEx(button, tag) {
|
|
meshserver.send({ action: 'createmesh', meshname: Q('dp2meshname').value, meshtype: Q('dp2meshtype').value, desc: Q('dp2meshdesc').value });
|
|
}
|
|
|
|
function account_validateDeleteAccount() {
|
|
QE('account_dlgOkButton', (Q('apassword1').value.length > 0) && (Q('apassword1').value == Q('apassword2').value));
|
|
}
|
|
|
|
function account_validateNewPassword() {
|
|
var r = '', ok = (Q('apassword0').value.length > 0) && (Q('apassword1').value.length > 0) && (Q('apassword1').value == Q('apassword2').value) && (Q('apassword0').value != Q('apassword1').value);
|
|
if ((features & 0x00010000) && (Q('apasswordhint').value == Q('apassword1').value)) { ok = false; }
|
|
if (Q('apassword1').value != '') {
|
|
if (passRequirements == null || passRequirements == '') {
|
|
// No password requirements, display password strength
|
|
var passStrength = checkPasswordStrength(Q('apassword1').value);
|
|
if (passStrength >= 80) { r = '<span style=color:green>' + "Silné" + '<span>'; } else if (passStrength >= 60) { r = '<span style=color:blue>' + "Dobré" + '<span>'; } else { r = '<span style=color:red>' + "Slabé" + '<span>'; }
|
|
} else {
|
|
// Password requirements provided, use that
|
|
var passReq = checkPasswordRequirements(Q('apassword1').value, passRequirements);
|
|
if (passReq == false) { ok = false; r = '<span style=color:red>' + "Politika" + '<span>' }
|
|
}
|
|
}
|
|
QH('dxPassWarn', r);
|
|
//QE('account_dlgOkButton', ok);
|
|
QE('idx_dlgOkButton', ok);
|
|
}
|
|
|
|
// Return a password strength score
|
|
function checkPasswordStrength(password) {
|
|
var r = 0, letters = {}, varCount = 0, variations = { digits: /\d/.test(password), lower: /[a-z]/.test(password), upper: /[A-Z]/.test(password), nonWords: /\W/.test(password) }
|
|
if (!password) return 0;
|
|
for (var i = 0; i< password.length; i++) { letters[password[i]] = (letters[password[i]] || 0) + 1; r += 5.0 / letters[password[i]]; }
|
|
for (var c in variations) { varCount += (variations[c] == true) ? 1 : 0; }
|
|
return parseInt(r + (varCount - 1) * 10);
|
|
}
|
|
|
|
// Check password requirements
|
|
function checkPasswordRequirements(password, requirements) {
|
|
if ((requirements == null) || (requirements == '') || (typeof requirements != 'object')) return true;
|
|
if (requirements.min) { if (password.length < requirements.min) return false; }
|
|
if (requirements.max) { if (password.length > requirements.max) return false; }
|
|
var num = 0, lower = 0, upper = 0, nonalpha = 0;
|
|
for (var i = 0; i < password.length; i++) {
|
|
if (/\d/.test(password[i])) { num++; }
|
|
if (/[a-z]/.test(password[i])) { lower++; }
|
|
if (/[A-Z]/.test(password[i])) { upper++; }
|
|
if (/\W/.test(password[i])) { nonalpha++; }
|
|
}
|
|
if (requirements.num && (num < requirements.num)) return false;
|
|
if (requirements.lower && (lower < requirements.lower)) return false;
|
|
if (requirements.upper && (upper < requirements.upper)) return false;
|
|
if (requirements.nonalpha && (nonalpha < requirements.nonalpha)) return false;
|
|
return true;
|
|
}
|
|
|
|
function updateMeshes() {
|
|
var r = '';
|
|
var c = 0, count = 0;
|
|
for (i in meshes) {
|
|
// Mesh positioning
|
|
if (c > 1) { r += '</tr><tr>'; c = 0; }
|
|
c++;
|
|
count++;
|
|
|
|
// Mesh rights
|
|
var meshrights = 0;
|
|
if (meshes[i].links[userinfo._id]) { meshrights = meshes[i].links[userinfo._id].rights; }
|
|
var rights = "Částečné práva";
|
|
if (meshrights == 0xFFFFFFFF) rights = "Hlavní administrátor"; else if (meshrights == 0) rights = "Žádná práva";
|
|
|
|
// Print the mesh information
|
|
r += '<div onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=display:inline-block;width:431px;height:50px;padding-top:1px;padding-bottom:1px;float:left><div style=float:left;width:30px;height:100%></div><div tabindex=0 style=height:100%;cursor:pointer onclick=gotoMesh(\'' + i + '\') onkeypress="if (event.key==\'Enter\') gotoMesh(\'' + i + '\')"><div class=mi style=float:left;width:50px;height:50px></div><div style=height:100%><div class=g1></div><div class=e2 style=width:300px><div class=e1>' + EscapeHtml(meshes[i].name) + '</div><div>' + rights + '</div></div><div class=g2 style=float:left></div></div></div></div>';
|
|
}
|
|
|
|
meshcount = count;
|
|
QH('p2meshes', r);
|
|
QV('p2noMeshFound', count == 0);
|
|
}
|
|
|
|
function gotoMesh(meshid) {
|
|
currentMesh = meshes[meshid];
|
|
p20updateMesh();
|
|
go(20);
|
|
return false;
|
|
}
|
|
|
|
function server_showRestoreDlg() {
|
|
if (xxdialogMode) return false;
|
|
var x = "Obnova serveru ze zálohy, <span style=color:red>smaže všechny uživatele a data na tomto serveru.</span>. Udělejte to, pouze pokud víte, co děláte." + '<br /><br />';
|
|
x += '<form action="/restoreserver.ashx" enctype="multipart/form-data" method="post"><div>';
|
|
x += '<input type=hidden name=auth value=' + authCookie + '>';
|
|
x += '<input id=account_dlgFileInput type=file name=datafile style=width:100% accept=".zip,application/octet-stream,application/zip,application/x-zip,application/x-zip-compressed" onchange=account_validateServerRestore()>';
|
|
x += '<input id=account_dlgCancelButton type=button value=' + "Zrušit" + ' style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>';
|
|
x += '<input id=account_dlgOkButton type=submit value=' + "OK" + ' style=float:right;width:80px onclick=dialogclose(1)>';
|
|
x += '</div><br /><br /></form>';
|
|
setDialogMode(2, "Obnova serveru", 0, null, x);
|
|
account_validateServerRestore();
|
|
return false;
|
|
}
|
|
|
|
function account_validateServerRestore() {
|
|
QE('account_dlgOkButton', Q('account_dlgFileInput').files.length == 1);
|
|
}
|
|
|
|
function server_showVersionDlg() {
|
|
if (xxdialogMode) return false;
|
|
setDialogMode(2, "MeshCentral verze", 1, null, "Nahrávání...", 'MeshCentralServerUpdate');
|
|
meshserver.send({ action: 'serverversion' });
|
|
return false;
|
|
}
|
|
|
|
function server_showVersionDlgUpdate() { QE('idx_dlgOkButton', Q('d2updateCheck').checked); }
|
|
function server_showVersionDlgEx() { meshserver.send({ action: 'serverupdate' }); }
|
|
|
|
function server_showErrorsDlg() {
|
|
if (xxdialogMode) return false;
|
|
setDialogMode(2, "MeshCentral chyby", 1, null, "Nahrávání...", 'MeshCentralServerErrors');
|
|
meshserver.send({ action: 'servererrors' });
|
|
return false;
|
|
}
|
|
function server_showErrorsDlgUpdate() { QE('idx_dlgOkButton', Q('d2updateCheck').checked); }
|
|
function server_showErrorsDlgEx() { meshserver.send({ action: 'serverclearerrorlog' }); }
|
|
function d2CopyServerErrorsToClip() { saveAs(new Blob([Q('d2ServerErrorsLogPre').innerText], { type: 'application/octet-stream' }), "servererrors.txt"); }
|
|
|
|
//
|
|
// MY MESHS
|
|
//
|
|
|
|
var currentMesh;
|
|
function p20updateMesh() {
|
|
if (currentMesh == null) return;
|
|
QH('p20meshName', EscapeHtml(currentMesh.name));
|
|
var meshtype = format("Neznámý #{0}", currentMesh.mtype);
|
|
var meshrights = 0;
|
|
try { meshrights = currentMesh.links[userinfo._id].rights; } catch (ex) { }
|
|
if (currentMesh.mtype == 1) meshtype = "Intel® AMT pouze, bez agenta";
|
|
if (currentMesh.mtype == 2) meshtype = "Spravovat pomocí softwarového aenta";
|
|
|
|
var x = '';
|
|
x += addHtmlValue("Jméno", addLinkConditional(EscapeHtml(currentMesh.name), 'p20editmesh(1)', (meshrights & 1) != 0));
|
|
x += addHtmlValue("Popis", addLinkConditional(((currentMesh.desc && currentMesh.desc != '')?EscapeHtml(currentMesh.desc):('<i>' + "Nic" + '</i>')), 'p20editmesh(2)', (meshrights & 1) != 0));
|
|
|
|
// Display group type
|
|
x += addHtmlValue("Typ", meshtype);
|
|
//x += addHtmlValue('Identifier', currentMesh._id.split('/')[2]);
|
|
|
|
// Display features
|
|
if (currentMesh.mtype == 2) {
|
|
var meshFeatures = [];
|
|
if (currentMesh.flags) {
|
|
if (currentMesh.flags & 1) { meshFeatures.push("Automatické odstranění"); }
|
|
if (currentMesh.flags & 2) { meshFeatures.push("Hostname Sync"); }
|
|
}
|
|
meshFeatures = meshFeatures.join(', ');
|
|
if (meshFeatures == '') { meshFeatures = '<i>' + "Nic" + '</i>'; }
|
|
x += addHtmlValue("Funkce", addLinkConditional(meshFeatures, 'p20editmeshfeatures()', meshrights & 1));
|
|
}
|
|
|
|
// Display user consent
|
|
if (currentMesh.mtype == 2) {
|
|
meshFeatures = [];
|
|
var consent = 0;
|
|
if (currentMesh.consent) { consent = currentMesh.consent; }
|
|
if (serverinfo.consent) { consent |= serverinfo.consent; }
|
|
if ((consent & 0x0040) && (consent & 0x0008)) { meshFeatures.push("Výzva na ploše+panel nástrojů"); } else if (consent & 0x0040) { meshFeatures.push("Panel nástrojů na ploše"); } else if (consent & 0x0008) { meshFeatures.push("Výzva na ploše"); } else { if (consent & 0x0001) { meshFeatures.push("Informovat na ploše"); } }
|
|
if (consent & 0x0010) { meshFeatures.push("Výzva terminálu"); } else { if (consent & 0x0002) { meshFeatures.push("Oznámení terminálu"); } }
|
|
if (consent & 0x0020) { meshFeatures.push("Dotaz na soubory"); } else { if (consent & 0x0004) { meshFeatures.push("Upozornit na soubory"); } }
|
|
if (consent == 7) { meshFeatures = ["Vždy upozorňovat"]; }
|
|
if ((consent & 56) == 56) { meshFeatures = ["Vždy se dotázat"]; }
|
|
|
|
meshFeatures = meshFeatures.join(', ');
|
|
if (meshFeatures == '') { meshFeatures = '<i>' + "Nic" + '</i>'; }
|
|
x += addHtmlValue("Souhlas uživatele", addLinkConditional(meshFeatures, 'p20editmeshconsent()', meshrights & 1));
|
|
}
|
|
|
|
// Display user consent
|
|
var meshNotify = 0, meshNotifyStr = [];
|
|
if (userinfo.links && userinfo.links[currentMesh._id] && userinfo.links[currentMesh._id].notify) { meshNotify = userinfo.links[currentMesh._id].notify; }
|
|
if (meshNotify & 2) { meshNotifyStr.push("Připojit"); }
|
|
if (meshNotify & 4) { meshNotifyStr.push("Odpojit"); }
|
|
if (meshNotify & 8) { meshNotifyStr.push("Intel® AMT"); }
|
|
if (meshNotifyStr.length == 0) { meshNotifyStr.push('<i>' + "Nic" + '</i>'); }
|
|
x += addHtmlValue("Notifikace", addLink(meshNotifyStr.join(', '), 'p20editMeshNotify()'));
|
|
|
|
// Intel AMT setup
|
|
var intelAmtPolicy = "Žádná politika";
|
|
if (currentMesh.amt) {
|
|
if (currentMesh.amt.type == 1) { intelAmtPolicy = 'Deactivate Client Control Mode (CCM)'; }
|
|
else if (currentMesh.amt.type == 2) {
|
|
intelAmtPolicy = "Jednoduchý Client Control Mode (CCM)";
|
|
if (currentMesh.amt.cirasetup == 2) { intelAmtPolicy += "+ CIRA"; }
|
|
} else if (currentMesh.amt.type == 3) {
|
|
intelAmtPolicy = "Jednoduchý Admin Control Mode (ACM)";
|
|
if (currentMesh.amt.cirasetup == 2) { intelAmtPolicy += "+ CIRA"; }
|
|
}
|
|
}
|
|
x += addHtmlValue("Intel® AMT", addLinkConditional(intelAmtPolicy, 'p20editMeshAmt()', meshrights & 1));
|
|
|
|
// Display group note support
|
|
if (meshrights & 1) { x += '<br><input type=button value=' + "Poznámky" + ' title=\"' + "Zobrazit poznámky k této skupině zařízení" + '\" onclick=showNotes(false,"' + encodeURIComponent(currentMesh._id) + '") />'; }
|
|
|
|
x += '<br style=clear:both><br>';
|
|
var currentMeshLinks = currentMesh.links[userinfo._id];
|
|
if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += '<a href=# onclick="return p20showAddMeshUserDialog()" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Přidat uživatele" + '</a>'; }
|
|
|
|
if ((meshrights & 4) != 0) {
|
|
if (currentMesh.mtype == 1) {
|
|
x += '<a href=# onclick=\'return addCiraDeviceToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Přidat nový Intel® AMT počítač, který je umístěn v síti Internet." + '\"><img src=images/icon-installmesh.png border=0 height=12 width=12> ' + "Instalace CIRA" + '</a>';
|
|
x += '<a href=# onclick=\'return addDeviceToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Přidat nový Intel® AMT počítač, který je umístěn v lokální síti." + '\"><img src=images/icon-installmesh.png border=0 height=12 width=12> ' + "Lokální instalace" + '</a>';
|
|
if (currentMesh.amt && (currentMesh.amt.type == 2)) { // CCM activation
|
|
x += '<a href=# onclick=\'return showCcmActivation(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Provedení Intel AMT client control mode (CCM) aktivace." + '\"><img src=images/icon-installmesh.png border=0 height=12 width=12> ' + "Aktivace" + '</a>';
|
|
} else if (currentMesh.amt && (currentMesh.amt.type == 3) && ((features & 0x00100000) != 0)) { // ACM activation
|
|
x += '<a href=# onclick=\'return showAcmActivation(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Provedení Intel AMT admin control mode (ACM) aktivace." + '\"><img src=images/icon-installmesh.png border=0 height=12 width=12> ' + "Aktivace" + '</a>';
|
|
}
|
|
}
|
|
if (currentMesh.mtype == 2) {
|
|
x += '<a href=# onclick=\'return addAgentToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Přidat nový počítač pomocí agenta." + '\"><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Instalace" + '</a>';
|
|
x += '<a href=# onclick=\'return inviteAgentToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Pozvat kohokoliv k instalaci agenta pro vzdálené ovládání." + '\"><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Pozvat" + '</a>';
|
|
}
|
|
}
|
|
|
|
x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>' + "Uživatelská oprávnění" + '</th><th scope=col style=text-align:left></th></tr>';
|
|
|
|
// Sort the users for this mesh
|
|
var count = 1, sortedusers = [];
|
|
for (var i in currentMesh.links) {
|
|
var uname = i.split('/')[2];
|
|
if (currentMesh.links[i].name) { uname = currentMesh.links[i].name; }
|
|
if (i == userinfo._id) { uname = userinfo.name; }
|
|
sortedusers.push({ id: i, name: uname, rights: currentMesh.links[i].rights });
|
|
}
|
|
sortedusers.sort(function(a, b) { if (a.name > b.name) return 1; if (a.name < b.name) return -1; return 0; });
|
|
|
|
// Display all users for this mesh
|
|
for (var i in sortedusers) {
|
|
var trash = '', rights = "Částečné práva", r = sortedusers[i].rights;
|
|
if (r == 0xFFFFFFFF) rights = "Hlavní administrátor"; else if (r == 0) rights = "Žádná práva";
|
|
if ((sortedusers[i].id != userinfo._id) && (meshrights == 0xFFFFFFFF || (((meshrights & 2) != 0)))) { trash = '<a href=# onclick=\'return p20deleteUser(event,"' + encodeURIComponent(sortedusers[i].id) + '")\' title=\"' + "Odstranit uživatelská práva pro tuto skupinu zařízení" + '\" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'; }
|
|
x += '<tr tabindex=0 onclick=p20viewuser("' + encodeURIComponent(sortedusers[i].id) + '") onkeypress="if (event.key==\'Enter\') p20viewuser(\'' + encodeURIComponent(sortedusers[i].id) + '\')" style=cursor:pointer' + (((count % 2) == 0) ? ';background-color:#DDD' : '') + '><td><div title=\"' + "Uživatel" + '\" class=m2></div><div> ' + EscapeHtml(decodeURIComponent(sortedusers[i].name)) + '<div></div></div></td><td><div style=float:right>' + trash + '</div><div>' + rights + '</div></td></tr>';
|
|
++count;
|
|
}
|
|
|
|
x += '</tbody></table>';
|
|
|
|
// If we are full administrator on this mesh, allow deletion of the mesh
|
|
if (meshrights == 0xFFFFFFFF) { x += '<div style=font-size:x-small;text-align:right><span><a href=# onclick=p20showDeleteMeshDialog() style=cursor:pointer>' + "Smazat skupinu" + '</a></span></div>'; }
|
|
|
|
QH('p20info', x);
|
|
}
|
|
|
|
function p20editMeshAmt() {
|
|
if (xxdialogMode) return;
|
|
var x = '', acmoption = '';
|
|
if ((features & 0x100000) != 0) { acmoption = '<option value=3>' + "Jednoduchý Admin Control Mode (ACM)" + '</option>'; }
|
|
if (currentMesh.mtype == 1) {
|
|
x += addHtmlValue("Typ", '<select id=dp20amtpolicy style=width:230px onchange=p20editMeshAmtChange()><option value=0>' + "Žádná politika" + '</option><option value=2>' + "Jednoduchý Client Control Mode (CCM)" + '</option>' + acmoption + '</select>');
|
|
} else {
|
|
x += addHtmlValue("Typ", '<select id=dp20amtpolicy style=width:230px onchange=p20editMeshAmtChange()><option value=0>' + "Žádná politika" + '</option><option value=1>' + "Deaktivace Client Control Mode (CCM)" + '</option><option value=2>' + "Jednoduchý Client Control Mode (CCM)" + '</option>' + acmoption + '</select>');
|
|
}
|
|
x += '<div id=dp20amtpolicydiv></div>';
|
|
setDialogMode(2, "Intel® AMT politika", 3, p20editMeshAmtEx, x);
|
|
if (currentMesh.amt) { Q('dp20amtpolicy').value = currentMesh.amt.type; }
|
|
p20editMeshAmtChange();
|
|
|
|
// Set the current Intel AMT policy
|
|
if (currentMesh.amt && (currentMesh.amt.type == 2) || (currentMesh.amt.type == 3)) {
|
|
Q('dp20amtpolicypass').value = currentMesh.amt.password;
|
|
if ((currentMesh.amt.type == 2) && (currentMesh.amt.badpass != null)) { Q('dp20amtbadpass').value = currentMesh.amt.badpass; }
|
|
if ((features & 0x400) == 0) { Q('dp20amtcira').value = currentMesh.amt.cirasetup; }
|
|
}
|
|
|
|
dp20amtValidatePolicy();
|
|
}
|
|
|
|
function p20editMeshAmtChange() {
|
|
var ptype = Q('dp20amtpolicy').value, x = '';
|
|
if (ptype >= 2) {
|
|
x = addHtmlValue("Heslo*", '<input id=dp20amtpolicypass type=password style=width:230px maxlength=32 onchange=dp20amtValidatePolicy() onkeyup=dp20amtValidatePolicy() autocomplete=off />')
|
|
x += addHtmlValue("Heslo*", '<input id=dp20amtpolicypass2 type=password style=width:230px maxlength=32 onchange=dp20amtValidatePolicy() onkeyup=dp20amtValidatePolicy() autocomplete=off />')
|
|
if ((ptype == 2) && (currentMesh.mtype == 2)) { x += addHtmlValue("Hesla nejsou stejná", '<select id=dp20amtbadpass style=width:230px><option value=0>' + "Nic" + '</option><option value=1>' + "ReaktivaceIntel® AMT" + '</option></select>'); }
|
|
if ((features & 0x400) == 0) {
|
|
if (ptype == 2) {
|
|
x += addHtmlValue('<span title="' + "Vzdálený přístup iniciováný klientem" + '">' + "CIRA" + '</span>', '<select id=dp20amtcira style=width:230px><option value=0>' + "Nekonfigurovat" + '</option><option value=1>' + "Nepřipojovat se k serveru" + '</option><option value=2>' + "Připojit se na server" + '</option></select>');
|
|
} else {
|
|
x += addHtmlValue('<span title="' + "Vzdálený přístup iniciováný klientem" + '">' + "CIRA" + '</span>', '<select id=dp20amtcira style=width:230px><option value=0>' + "Nekonfigurovat" + '</option><option value=2>' + "Připojit se na server" + '</option></select>');
|
|
}
|
|
}
|
|
x += '<br/><span style="font-size:10px">' + "* Ponechat prázdné pro vygenerování náhodného hesla každému zařízení." + '</span><br/>';
|
|
if (currentMesh.mtype == 2) {
|
|
if (ptype == 2) {
|
|
x += '<span style="font-size:10px">' + "Tato zásada nebude mít vliv na zařízení s Intel® AMT in ACM módem." + '</span><br/>';
|
|
x += '<span style="font-size:10px">' + "Toto není bezpečná politika, protože agenti budou provádět aktivaci." + '</span>';
|
|
} else {
|
|
x += '<span style="font-size:10px">' + "Během aktivace bude mít agent administrátorská práva." + '</span>';
|
|
}
|
|
}
|
|
}
|
|
QH('dp20amtpolicydiv', x);
|
|
setTimeout(dp20amtValidatePolicy, 1);
|
|
}
|
|
|
|
function dp20amtValidatePolicy() {
|
|
var ok = true, ptype = Q('dp20amtpolicy').value;
|
|
if ((ptype == 2) || (ptype == 3)) {
|
|
var pass = Q('dp20amtpolicypass').value, pass2 = Q('dp20amtpolicypass2').value;
|
|
ok = ((pass === pass2) && ((pass === '') ? true : passwordcheck(pass)));
|
|
}
|
|
QE('idx_dlgOkButton', ok);
|
|
}
|
|
|
|
function p20editMeshAmtEx() {
|
|
var ptype = parseInt(Q('dp20amtpolicy').value), amtpolicy = { type: ptype };
|
|
if (ptype == 2) {
|
|
amtpolicy = { type: ptype, password: Q('dp20amtpolicypass').value };
|
|
if (currentMesh.mtype == 2) { amtpolicy.badpass = parseInt(Q('dp20amtbadpass').value); }
|
|
if ((features & 0x400) == 0) { amtpolicy.cirasetup = parseInt(Q('dp20amtcira').value); } else { amtpolicy.cirasetup = 1; }
|
|
} else if (ptype == 3) {
|
|
amtpolicy = { type: ptype, password: Q('dp20amtpolicypass').value };
|
|
if ((features & 0x400) == 0) { amtpolicy.cirasetup = parseInt(Q('dp20amtcira').value); } else { amtpolicy.cirasetup = 1; }
|
|
}
|
|
meshserver.send({ action: 'meshamtpolicy', meshid: currentMesh._id, amtpolicy: amtpolicy });
|
|
}
|
|
|
|
function p20showDeleteMeshDialog() {
|
|
if (xxdialogMode) return false;
|
|
var x = format("Opravdu smazat skupinu {0}? Smazáním skupiny se smažou všechny informace o zařízeních v této skupině.", EscapeHtml(currentMesh.name)) + '<br /><br />';
|
|
x += '<label><input id=p20check type=checkbox onchange=p20validateDeleteMeshDialog() />' + "Potvrdit" + '</label>';
|
|
setDialogMode(2, "Smazat skupinu", 3, p20showDeleteMeshDialogEx, x);
|
|
p20validateDeleteMeshDialog();
|
|
return false;
|
|
}
|
|
|
|
function p20validateDeleteMeshDialog() {
|
|
QE('idx_dlgOkButton', Q('p20check').checked);
|
|
}
|
|
|
|
function p20showDeleteMeshDialogEx(buttons, tag) {
|
|
meshserver.send({ action: 'deletemesh', meshid: currentMesh._id, meshname: currentMesh.name });
|
|
}
|
|
|
|
function p20editmesh(focus) {
|
|
if (xxdialogMode) return;
|
|
var x = addHtmlValue("Jméno", '<input id=dp20meshname style=width:230px maxlength=32 onchange=p20editmeshValidate() onkeyup=p20editmeshValidate(event) />');
|
|
x += addHtmlValue("Popis", '<div style=width:230px;margin:0;padding:0><textarea id=dp20meshdesc maxlength=1024 style=width:100%;resize:none></textarea></div>');
|
|
setDialogMode(2, "Upravit skupinu zařízení", 3, p20editmeshEx, x);
|
|
Q('dp20meshname').value = currentMesh.name;
|
|
if (currentMesh.desc) Q('dp20meshdesc').value = currentMesh.desc;
|
|
p20editmeshValidate();
|
|
if (focus == 2) { Q('dp20meshdesc').focus(); } else { Q('dp20meshname').focus(); }
|
|
}
|
|
|
|
function p20editmeshEx() {
|
|
meshserver.send({ action: 'editmesh', meshid: currentMesh._id, meshname: Q('dp20meshname').value, desc: Q('dp20meshdesc').value });
|
|
}
|
|
|
|
function p20editmeshValidate(e) {
|
|
QE('idx_dlgOkButton', Q('dp20meshname').value.length > 0);
|
|
if (e && e.key == 'Enter') { Q('dp20meshdesc').focus(); }
|
|
}
|
|
|
|
function p20editmeshconsent() {
|
|
if (xxdialogMode) return;
|
|
var x = '', consent = (currentMesh.consent) ? currentMesh.consent : 0;
|
|
x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px"><b>' + "Plocha" + '</b></div>';
|
|
x += '<div><label><input type=checkbox id=d20flag1 ' + ((consent & 0x0001) ? 'checked' : '') + '>' + "Informovat uživatele" + '</label></div>';
|
|
x += '<div><label><input type=checkbox id=d20flag2 ' + ((consent & 0x0008) ? 'checked' : '') + '>' + "Výzva k souhlasu uživatele" + '</label></div>';
|
|
x += '<div><label><input type=checkbox id=d20flag7 ' + ((consent & 0x0040) ? 'checked' : '') + '>' + "Zobrazit panel nástrojů připojení" + '</label></div>';
|
|
x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:8px"><b>' + "Terminál" + '</b></div>';
|
|
x += '<div><label><input type=checkbox id=d20flag3 ' + ((consent & 0x0002) ? 'checked' : '') + '>' + "Informovat uživatele" + '</label></div>';
|
|
x += '<div><label><input type=checkbox id=d20flag4 ' + ((consent & 0x0010) ? 'checked' : '') + '>' + "Výzva k souhlasu uživatele" + '</label></div>';
|
|
x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:8px"><b>' + "Soubory" + '</b></div>';
|
|
x += '<div><label><input type=checkbox id=d20flag5 ' + ((consent & 0x0004) ? 'checked' : '') + '>' + "Informovat uživatele" + '</label></div>';
|
|
x += '<div><label><input type=checkbox id=d20flag6 ' + ((consent & 0x0020) ? 'checked' : '') + '>' + "Výzva k souhlasu uživatele" + '</label></div>';
|
|
setDialogMode(2, "Upravit souhlas uživatele skupiny zařízení", 3, p20editmeshconsentEx, x);
|
|
if (serverinfo.consent) {
|
|
if (serverinfo.consent & 0x0001) { Q('d20flag1').checked = true; }
|
|
if (serverinfo.consent & 0x0008) { Q('d20flag2').checked = true; }
|
|
if (serverinfo.consent & 0x0002) { Q('d20flag3').checked = true; }
|
|
if (serverinfo.consent & 0x0010) { Q('d20flag4').checked = true; }
|
|
if (serverinfo.consent & 0x0004) { Q('d20flag5').checked = true; }
|
|
if (serverinfo.consent & 0x0020) { Q('d20flag6').checked = true; }
|
|
if (serverinfo.consent & 0x0040) { Q('d20flag7').checked = true; }
|
|
QE('d20flag1', !(serverinfo.consent & 0x0001));
|
|
QE('d20flag2', !(serverinfo.consent & 0x0008));
|
|
QE('d20flag3', !(serverinfo.consent & 0x0002));
|
|
QE('d20flag4', !(serverinfo.consent & 0x0010));
|
|
QE('d20flag5', !(serverinfo.consent & 0x0004));
|
|
QE('d20flag6', !(serverinfo.consent & 0x0020));
|
|
if (debugmode == 1) { QE('d20flag7', !(serverinfo.consent & 0x0040)); }
|
|
}
|
|
}
|
|
|
|
function p20editmeshconsentEx() {
|
|
var consent = 0;
|
|
if (Q('d20flag1').checked) { consent += 0x0001; }
|
|
if (Q('d20flag2').checked) { consent += 0x0008; }
|
|
if (Q('d20flag3').checked) { consent += 0x0002; }
|
|
if (Q('d20flag4').checked) { consent += 0x0010; }
|
|
if (Q('d20flag5').checked) { consent += 0x0004; }
|
|
if (Q('d20flag6').checked) { consent += 0x0020; }
|
|
if (Q('d20flag7').checked) { consent += 0x0040; }
|
|
meshserver.send({ action: 'editmesh', meshid: currentMesh._id, consent: consent });
|
|
}
|
|
|
|
function p20editmeshfeatures() {
|
|
if (xxdialogMode) return;
|
|
var flags = (currentMesh.flags)?currentMesh.flags:0;
|
|
var x = '<div><label><input type=checkbox id=d20flag1 ' + ((flags & 1) ? 'checked' : '') + '>Remove device on disconnect</label><br></div>';
|
|
x += '<div><label><input type=checkbox id=d20flag2 ' + ((flags & 2) ? 'checked' : '') + '>Sync server device name to hostname</label><br></div>';
|
|
setDialogMode(2, "Upravit vlastnosti skupiny zařízení", 3, p20editmeshfeaturesEx, x);
|
|
}
|
|
|
|
function p20editmeshfeaturesEx() {
|
|
var flags = 0;
|
|
if (Q('d20flag1').checked) { flags += 1; }
|
|
if (Q('d20flag2').checked) { flags += 2; }
|
|
meshserver.send({ action: 'editmesh', meshid: currentMesh._id, flags: flags });
|
|
}
|
|
|
|
function p20showAddMeshUserDialog(userid) {
|
|
if (xxdialogMode) return false;
|
|
var x = '';
|
|
if (userid == null) {
|
|
x += "Umožnit uživatelům spravovat tuto skupinu a zařízení v této skupině.";
|
|
if (features & 0x00080000) { x += " Uživatelé se musí před přidáním do skupiny zařízení jednou přihlásit k tomuto serveru." }
|
|
x += '<br /><br /><div style=\'position:relative\'>';
|
|
x += addHtmlValue("Uživatelé", '<input id=dp20username style=width:230px maxlength=32 onchange=p20validateAddMeshUserDialog() onkeyup=p20validateAddMeshUserDialog() placeholder="user1, user2, user3" />');
|
|
x += '<div id=dp20usersuggest class=suggestionBox style=\'top:30px;left:130px;display:none\'></div>';
|
|
x += '</div><br>';
|
|
} else {
|
|
userid = decodeURIComponent(userid);
|
|
var uname = userid.split('/')[2];
|
|
if (users && users[userid]) { uname = users[userid].name; }
|
|
if (userinfo._id == userid) { uname = userinfo.name; }
|
|
x += format("Oprávnění skupiny pro uživatele {0}.", uname) + '<br /><br />';
|
|
}
|
|
x += '<div style="height:120px;overflow-y:scroll;border:1px solid gray">';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20fulladmin>' + "Hlavní administrátor" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editmesh>' + "Upravit skupinu zařízení" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20manageusers>' + "Spravovat uživatele pro skupinu zařízení" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20managecomputers>' + "Správa skupin zařízení" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotecontrol>' + "Vzdálené ovládání" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remoteview style=margin-left:12px>' + "Pouze vzdálené prohlížení" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotelimitedinput style=margin-left:12px>' + "Pouze omezené vstupy" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noterminal style=margin-left:12px>' + "Žádný přístup k terminálu" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20nofiles style=margin-left:12px>' + "Žádný přístup k souborům" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noamt style=margin-left:12px>' + "Žádné Intel® AMT" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshagentconsole>' + "Konzole agenta" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshserverfiles>' + "Soubory serveru" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20wakedevices>' + "Probudit zařízení" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>' + "Upravit popis zařízení" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20limitevents>' + "Zobrazit pouze vlastní události" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20chatnotify>' + "Chat & Upozornění" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20uninstall>' + "Odinstalovat agenta" + '</label><br>';
|
|
x += '</div>';
|
|
if (userid == null) {
|
|
setDialogMode(2, "Přidat uživatele do skupiny zařizení", 3, p20showAddMeshUserDialogEx, x);
|
|
Q('dp20username').focus();
|
|
} else {
|
|
setDialogMode(2, "Upravit uživatelská práva pro skupinu zařízení ", 7, p20showAddMeshUserDialogEx, x, userid);
|
|
var cmeshrights = currentMesh.links[userinfo._id].rights, meshrights = currentMesh.links[userid].rights;
|
|
if (meshrights == 0xFFFFFFFF) {
|
|
Q('p20fulladmin').checked = true;
|
|
} else {
|
|
if (meshrights & 1) { Q('p20editmesh').checked = true; }
|
|
if (meshrights & 2) { Q('p20manageusers').checked = true; }
|
|
if (meshrights & 4) { Q('p20managecomputers').checked = true; }
|
|
if (meshrights & 8) {
|
|
Q('p20remotecontrol').checked = true;
|
|
if (meshrights & 256) { Q('p20remoteview').checked = true; }
|
|
if (meshrights & 512) { Q('p20noterminal').checked = true; }
|
|
if (meshrights & 1024) { Q('p20nofiles').checked = true; }
|
|
if (meshrights & 2048) { Q('p20noamt').checked = true; }
|
|
if (meshrights & 4096) { Q('p20remotelimitedinput').checked = true; }
|
|
}
|
|
if (meshrights & 16) { Q('p20meshagentconsole').checked = true; }
|
|
if (meshrights & 32) { Q('p20meshserverfiles').checked = true; }
|
|
if (meshrights & 64) { Q('p20wakedevices').checked = true; }
|
|
if (meshrights & 128) { Q('p20editnotes').checked = true; }
|
|
if (meshrights & 8192) { Q('p20limitevents').checked = true; }
|
|
if (meshrights & 16384) { Q('p20chatnotify').checked = true; }
|
|
if (meshrights & 32768) { Q('p20uninstall').checked = true; }
|
|
}
|
|
}
|
|
p20validateAddMeshUserDialog();
|
|
return false;
|
|
}
|
|
|
|
function p20setname(name) {
|
|
name = decodeURIComponent(name);
|
|
var xusers = Q('dp20username').value.split(',');
|
|
for (var i in xusers) { xusers[i] = xusers[i].trim(); }
|
|
xusers[xusers.length - 1] = name;
|
|
Q('dp20username').value = xusers.join(', ');
|
|
p20validateAddMeshUserDialog();
|
|
return false;
|
|
}
|
|
|
|
function p20validateAddMeshUserDialog() {
|
|
var meshrights = currentMesh.links[userinfo._id].rights;
|
|
var ok = true;
|
|
if (Q('dp20username')) {
|
|
var xusers = Q('dp20username').value.split(',');
|
|
for (var i in xusers) {
|
|
var xuser = xusers[i] = xusers[i].trim();
|
|
if (xuser.length == 0) { ok = false; } else if (xuser.indexOf('"') >= 0) { ok = false; }
|
|
}
|
|
|
|
// Fill the suggestion box
|
|
var showsuggestbox = false, exactMatch = false;
|
|
if (users != null) {
|
|
var lastuser = xusers[xusers.length - 1].trim(), lastuserl = lastuser.toLowerCase(), matchingUsers = [];
|
|
if (lastuser.length > 0) {
|
|
for (var i in users) {
|
|
if (users[i].name === lastuser) { exactMatch = true; break; }
|
|
if (users[i].name.toLowerCase().indexOf(lastuserl) >= 0) { matchingUsers.push(users[i].name); if (matchingUsers.length >= 8) break; }
|
|
}
|
|
if ((exactMatch == false) && (matchingUsers.length > 0)) {
|
|
var x = '';
|
|
for (var i in matchingUsers) { x += '<a href=# onclick=\'p20setname("' + encodeURIComponent(matchingUsers[i]) + '")\'>' + matchingUsers[i] + '</a><br />'; }
|
|
QH('dp20usersuggest', x);
|
|
showsuggestbox = true;
|
|
}
|
|
}
|
|
}
|
|
QV('dp20usersuggest', showsuggestbox);
|
|
}
|
|
QE('idx_dlgOkButton', ok);
|
|
|
|
var nc = !Q('p20fulladmin').checked;
|
|
QE('p20fulladmin', meshrights == 0xFFFFFFFF);
|
|
QE('p20editmesh', nc && (meshrights == 0xFFFFFFFF));
|
|
QE('p20manageusers', nc);
|
|
QE('p20managecomputers', nc);
|
|
QE('p20remotecontrol', nc);
|
|
QE('p20meshagentconsole', nc);
|
|
QE('p20meshserverfiles', nc);
|
|
QE('p20wakedevices', nc);
|
|
QE('p20editnotes', nc);
|
|
QE('p20limitevents', nc);
|
|
QE('p20remoteview', nc && Q('p20remotecontrol').checked);
|
|
QE('p20remotelimitedinput', nc && Q('p20remotecontrol').checked && !Q('p20remoteview').checked);
|
|
QE('p20noterminal', nc && Q('p20remotecontrol').checked);
|
|
QE('p20nofiles', nc && Q('p20remotecontrol').checked);
|
|
QE('p20noamt', nc && Q('p20remotecontrol').checked);
|
|
QE('p20chatnotify', nc);
|
|
QE('p20uninstall', nc);
|
|
}
|
|
|
|
function p20showAddMeshUserDialogEx(b, t) {
|
|
if (b == 2) {
|
|
p20viewuserEx(b, t);
|
|
} else {
|
|
var meshadmin = 0;
|
|
if (Q('p20fulladmin').checked == true) { meshadmin = 0xFFFFFFFF; } else {
|
|
if (Q('p20editmesh').checked == true) meshadmin += 1;
|
|
if (Q('p20manageusers').checked == true) meshadmin += 2;
|
|
if (Q('p20managecomputers').checked == true) meshadmin += 4;
|
|
if (Q('p20remotecontrol').checked == true) meshadmin += 8;
|
|
if (Q('p20meshagentconsole').checked == true) meshadmin += 16;
|
|
if (Q('p20meshserverfiles').checked == true) meshadmin += 32;
|
|
if (Q('p20wakedevices').checked == true) meshadmin += 64;
|
|
if (Q('p20editnotes').checked == true) meshadmin += 128;
|
|
if (Q('p20remoteview').checked == true) meshadmin += 256;
|
|
if (Q('p20noterminal').checked == true) meshadmin += 512;
|
|
if (Q('p20nofiles').checked == true) meshadmin += 1024;
|
|
if (Q('p20noamt').checked == true) meshadmin += 2048;
|
|
if (Q('p20remotelimitedinput').checked == true) meshadmin += 4096;
|
|
if (Q('p20limitevents').checked == true) meshadmin += 8192;
|
|
if (Q('p20chatnotify').checked == true) meshadmin += 16384;
|
|
if (Q('p20uninstall').checked == true) meshadmin += 32768;
|
|
}
|
|
|
|
if (t == null) {
|
|
var users = Q('dp20username').value.split(','), users2 = [];
|
|
for (var i in users) { users2.push(users[i].trim()); }
|
|
meshserver.send({ action: 'addmeshuser', meshid: currentMesh._id, meshname: currentMesh.name, usernames: users2, meshadmin: meshadmin });
|
|
} else {
|
|
meshserver.send({ action: 'addmeshuser', meshid: currentMesh._id, meshname: currentMesh.name, usernames: [ t.split('/')[2] ], meshadmin: meshadmin });
|
|
}
|
|
}
|
|
}
|
|
|
|
function p20viewuser(userid) {
|
|
if (xxdialogMode) return;
|
|
var xuserid = decodeURIComponent(userid);
|
|
var cmeshrights = currentMesh.links[userinfo._id].rights, meshrights = currentMesh.links[xuserid].rights;
|
|
if (((userinfo._id) != xuserid) && (cmeshrights == 0xFFFFFFFF || (((cmeshrights & 2) != 0) && (meshrights != 0xFFFFFFFF)))) {
|
|
p20showAddMeshUserDialog(userid);
|
|
} else {
|
|
var r = [];
|
|
if (meshrights == 0xFFFFFFFF) r.push("Hlavní administrator (všechna práva)"); else {
|
|
if ((meshrights & 1) != 0) r.push("Upravit skupinu zařízení");
|
|
if ((meshrights & 2) != 0) r.push("Spravovat uživatele pro skupinu zařízení");
|
|
if ((meshrights & 4) != 0) r.push("Správa skupin zařízení");
|
|
if ((meshrights & 8) != 0) r.push("Vzdálené ovládání");
|
|
if ((meshrights & 16) != 0) r.push("Konzole agenta");
|
|
if ((meshrights & 32) != 0) r.push("Soubory serveru");
|
|
if ((meshrights & 64) != 0) r.push("Probudit zařízení");
|
|
if ((meshrights & 128) != 0) r.push("Upravit poznámky");
|
|
if (((meshrights & 8) != 0) && (meshrights & 256) != 0) r.push("Pouze vzdálené prohlížení");
|
|
if (((meshrights & 8) != 0) && (meshrights & 512) != 0) r.push("Žádný terminál");
|
|
if (((meshrights & 8) != 0) && (meshrights & 1024) != 0) r.push("Žádné soubory");
|
|
if (((meshrights & 8) != 0) && (meshrights & 2048) != 0) r.push("Žádné Intel® AMT");
|
|
if (((meshrights & 8) != 0) && ((meshrights & 4096) != 0) && ((meshrights & 256) == 0)) r.push("Omezené vstupy");
|
|
if ((meshrights & 8192) != 0) r.push("Pouze vlastní události");
|
|
if ((meshrights & 16384) != 0) r.push("Chat & Upozornění");
|
|
if ((meshrights & 32768) != 0) r.push("Odinstalace");
|
|
}
|
|
if (r.length == 0) { r.push("Žádná práva"); }
|
|
var uname = xuserid.split('/')[2];
|
|
if (users && users[xuserid]) { uname = users[xuserid].name; }
|
|
if (userinfo._id == xuserid) { uname = userinfo.name; }
|
|
var buttons = 1, x = addHtmlValue("Uživatel", EscapeHtml(decodeURIComponent(uname)));
|
|
if (xuserid.split('/')[2] != uname) { x += addHtmlValue("Identifikátor uživatele", EscapeHtml(xuserid.split('/')[2])); }
|
|
|
|
x += addHtmlValue("Práva", r.join(", "));
|
|
if (((userinfo._id) != xuserid) && (cmeshrights == 0xFFFFFFFF || (((cmeshrights & 2) != 0) && (meshrights != 0xFFFFFFFF)))) buttons += 4;
|
|
setDialogMode(2, "Uživatelé této skupiny zařízení", buttons, p20viewuserEx, x, xuserid);
|
|
}
|
|
}
|
|
|
|
function p20viewuserEx(button, userid) {
|
|
if (button != 2) return;
|
|
var uname = userid.split('/')[2];
|
|
if (users && users[userid]) { uname = users[userid].name; }
|
|
if (userinfo._id == userid) { uname = userinfo.name; }
|
|
setDialogMode(2, "Vzdálený uživatel", 3, p20viewuserEx2, format("Potvrdit odstranění uživatele {0}?", EscapeHtml(decodeURIComponent(uname))), userid);
|
|
}
|
|
function p20deleteUser(e, userid) { haltEvent(e); p20viewuserEx(2, decodeURIComponent(userid)); return false; }
|
|
function p20viewuserEx2(button, userid) { meshserver.send({ action: 'removemeshuser', meshid: currentMesh._id, meshname: currentMesh.name, userid: userid }); }
|
|
|
|
function p20editMeshNotify() {
|
|
if (xxdialogMode) return false;
|
|
var meshNotify = 0;
|
|
if (userinfo.links && userinfo.links[currentMesh._id] && userinfo.links[currentMesh._id].notify) { meshNotify = userinfo.links[currentMesh._id].notify; }
|
|
var x = 'Notification settings must also be turned on in account settings.<br /><br />';
|
|
x += '<div><label><input id=p20notifyIntelDeviceConnect type=checkbox />Device connections.</label></div>';
|
|
x += '<div><label><input id=p20notifyIntelDeviceDisconnect type=checkbox />Device disconnections.</label></div>';
|
|
x += '<div><label><input id=p20notifyIntelAmtKvmActions type=checkbox />Intel® AMT desktop and serial events.</label></div>';
|
|
setDialogMode(2, "Nastavení notifikací", 3, p20editMeshNotifyEx, x);
|
|
Q('p20notifyIntelDeviceConnect').checked = (meshNotify & 2);
|
|
Q('p20notifyIntelDeviceDisconnect').checked = (meshNotify & 4);
|
|
Q('p20notifyIntelAmtKvmActions').checked = (meshNotify & 8);
|
|
return false;
|
|
}
|
|
|
|
function p20editMeshNotifyEx() {
|
|
var meshNotify = 0;
|
|
meshNotify += Q('p20notifyIntelDeviceConnect').checked ? 2 : 0;
|
|
meshNotify += Q('p20notifyIntelDeviceDisconnect').checked ? 4 : 0;
|
|
meshNotify += Q('p20notifyIntelAmtKvmActions').checked ? 8 : 0;
|
|
meshserver.send({ action: 'changemeshnotify', meshid: currentMesh._id, notify: meshNotify });
|
|
}
|
|
|
|
//
|
|
// MY FILES
|
|
//
|
|
|
|
var filetreelinkpath;
|
|
var filetreelocation = [];
|
|
|
|
function updateFiles() {
|
|
QV('MainMenuMyFiles', ((features & 8) == 0));
|
|
if ((features & 8) != 0) return; // If running on a server without files, exit now.
|
|
var html1 = '', html2 = '', displayPath = '<a href=# style=cursor:pointer onclick="return p5folderup(0)">' + "Root" + '</a>', fullPath = 'Root', publicPath, filetreex = filetree, folderdepth = 1;
|
|
|
|
// Navigate to path location, build the paths at the same time
|
|
var filetreelocation2 = [], oldlinkpath = filetreelinkpath, checkedBoxes = [], checkboxes = document.getElementsByName('fc');
|
|
for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { checkedBoxes.push(checkboxes[i].value) }; } // Save all existing checked boxes
|
|
|
|
filetreelinkpath = '';
|
|
for (var i in filetreelocation) {
|
|
if ((filetreex.f != null) && (filetreex.f[filetreelocation[i]] != null)) {
|
|
filetreelocation2.push(filetreelocation[i]);
|
|
fullPath += ' / ' + filetreelocation[i];
|
|
if ((folderdepth == 1)) {
|
|
var sp = filetreelocation[i].split('/');
|
|
publicPath = window.location + sp[0] + 'files/' + sp[2];
|
|
//if (filetreelocation[i] === userinfo._id) { filetreelinkpath += 'self'; } else { filetreelinkpath += (sp[0] + '/' + sp[2]); }
|
|
filetreelinkpath += filetreelocation[i];
|
|
} else {
|
|
if (filetreelinkpath != '') { filetreelinkpath += '/' + filetreelocation[i]; if (folderdepth > 2) { publicPath += '/' + filetreelocation[i]; } }
|
|
}
|
|
filetreex = filetreex.f[filetreelocation[i]];
|
|
displayPath += ' / <a href=# style=cursor:pointer onclick="return p5folderup(' + folderdepth + ')">' + (filetreex.n != null?filetreex.n:filetreelocation[i]) + '</a>';
|
|
folderdepth++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
filetreelocation = filetreelocation2; // In case we could not go down the full path, we set the new path location here.
|
|
var publicfolder = fullPath.toLowerCase().startsWith('root / ' + userinfo._id + ' / public');
|
|
|
|
// Sort the files
|
|
var filetreexx = p5sort_files(filetreex.f);
|
|
|
|
// Display all files and folders at this location
|
|
for (var i in filetreexx) {
|
|
// Figure out the name and shortname
|
|
var f = filetreexx[i], name = f.n, shortname;
|
|
shortname = name;
|
|
if (name.length > 70) { shortname = '<span title="' + EscapeHtml(name) + '">' + EscapeHtml(name.substring(0, 70)) + "..." + '</span>'; } else { shortname = EscapeHtml(name); }
|
|
name = EscapeHtml(name);
|
|
|
|
// Figure out the date
|
|
var fdatestr = '';
|
|
if (f.d != null) { var fdate = new Date(f.d), fdatestr = printDateTime(fdate) + ' '; }
|
|
|
|
// Figure out the size
|
|
var fsize = '';
|
|
if (f.s != null) { fsize = getFileSizeStr(f.s); }
|
|
|
|
var h = '';
|
|
if (f.t < 3 || f.t == 4) {
|
|
var right = (f.t == 1 || f.t == 4)?p5getQuotabar(f):'', title = '';
|
|
h = '<div class=filelist file=999><input file=999 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value="' + name + '"> <span style=float:right title=\"' + title + '\">' + right + '</span><span><div class=fileIcon' + f.t + ' onclick=p5folderset(\"' + encodeURIComponent(f.nx) + '\")></div><a href=# style=cursor:pointer onclick=\'return p5folderset(\"' + encodeURIComponent(f.nx) + '\")\'>' + shortname + '</a></span></div>';
|
|
} else {
|
|
var link = shortname, publiclink = '';
|
|
if (publicfolder) { publiclink = ' (<a style=cursor:pointer title="Display public link" onclick=\'return p5showPublicLink("' + publicPath + '/' + f.nx + '")\'>' + "Odkaz" + '</a>)'; }
|
|
if (f.s > 0) { link = '<a rel="noreferrer noopener" target="_blank" download href="downloadfile.ashx?link=' + encodeURIComponent(filetreelinkpath + '/' + f.nx) + '">' + shortname + '</a>' + publiclink; }
|
|
h = '<div class=filelist file=3><input file=3 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value="' + f.nx + '"> <span class=fsize>' + fdatestr + '</span><span style=float:right>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
|
|
}
|
|
|
|
if (f.t < 3) { html1 += h; } else { html2 += h; }
|
|
}
|
|
|
|
//if (f.parent == null) { }
|
|
QH('p5rightOfButtons', p5getQuotabar(filetreex));
|
|
|
|
QH('p5files', html1 + html2);
|
|
QH('p5currentpath', displayPath);
|
|
QE('p5FolderUp', filetreelocation.length != 0);
|
|
QV('p5PublicShare', publicfolder);
|
|
|
|
// Re-check all boxes if needed
|
|
if (oldlinkpath == filetreelinkpath) {
|
|
checkboxes = document.getElementsByName('fc');
|
|
for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = (checkedBoxes.indexOf(checkboxes[i].value) >= 0); }
|
|
}
|
|
|
|
p5setActions();
|
|
}
|
|
|
|
function getNiceSize(bytes) {
|
|
if (bytes <= 0) return "Překročen limit pro ukládání";
|
|
if (bytes < 2048) return format("{0} bytů zbývá", bytes);
|
|
if (bytes < 2097152) return format("{0} kilobytů zbývá", Math.round(bytes / 1024));
|
|
if (bytes < 2147483648) return format("{0} megabytů zbývá", Math.round(bytes / 1024 / 1024));
|
|
return format("{0} gigabytů zbývá", Math.round(bytes / 1024 / 1024 / 1024));
|
|
}
|
|
|
|
function getNiceSize2(bytes) {
|
|
if (bytes <= 0) return "Nic";
|
|
if (bytes < 2048) return format("{0} b", bytes);
|
|
if (bytes < 2097152) return format("{0} Kb", Math.round(bytes / 1024));
|
|
if (bytes < 2147483648) return format("{0} Mb", Math.round(bytes / 1024 / 1024));
|
|
return format("{0} Gb", Math.round(bytes / 1024 / 1024 / 1024));
|
|
}
|
|
|
|
function p5getQuotabar(f) {
|
|
while (f.t > 1 && f.t != 4) { f = f.parent; }
|
|
if ((f.t != 1 && f.t != 4) || (f.maxbytes == null)) return '';
|
|
var tf = Math.floor(f.s / 1024), tq = (f.maxbytes - f.s);
|
|
var title;
|
|
if (f.c > 1) { title = format("{0}k v {1} souborech. {2}k maximum", tf, f.c, (Math.floor(f.maxbytes / 1024 / 1024))); } else { title = format("{0}k v 1 souboru. {1}k maximum", tf, (Math.floor(f.maxbytes / 1024 / 1024))); }
|
|
return '<span title="' + title + '">' + getNiceSize(tq) + ' <progress style=height:10px;width:100px value=' + f.s + ' max=' + f.maxbytes + ' /></span>';
|
|
}
|
|
|
|
function p5showPublicLink(u) { setDialogMode(2, "Veřejný odkaz", 1, null, '<input type=text style=width:100% value="' + u + '" readonly />'); return false; }
|
|
|
|
var sortorder;
|
|
function p5sort_filename(a, b) { if (a.ln > b.ln) return (1 * sortorder); if (a.ln < b.ln) return (-1 * sortorder); return 0; }
|
|
function p5sort_timestamp(a, b) { if (a.d > b.d) return (1 * sortorder); if (a.d < b.d) return (-1 * sortorder); return 0; }
|
|
function p5sort_bysize(a, b) { if (a.s == b.s) return p5sort_filename(a, b); return (((a.s - b.s)) * sortorder); }
|
|
|
|
function p5sort_files(files) {
|
|
var r = [], sortselection = Q('p5sortdropdown').value;
|
|
for (var i in files) { files[i].nx = i; if (files[i].n == null) { files[i].n = i; } files[i].ln = files[i].n.toLowerCase(); r.push(files[i]); }
|
|
sortorder = 1;
|
|
if (sortselection > 3) { sortorder = -1; sortselection -= 3; }
|
|
if (sortselection == 1) { r.sort(p5sort_filename); }
|
|
else if (sortselection == 2) { r.sort(p5sort_bysize); }
|
|
else if (sortselection == 3) { r.sort(p5sort_timestamp); }
|
|
return r;
|
|
}
|
|
|
|
function p5setActions() {
|
|
var cc = getFileSelCount(), tc = getFileCount(), sfc = getFileSelCount(false); // In order: number of entires selected, number of total entries, number of selected entires that are files (not folders)
|
|
QE('p5DeleteFileButton', (cc > 0) && (filetreelocation.length > 0));
|
|
QE('p5NewFolderButton', filetreelocation.length > 0);
|
|
QE('p5UploadButton', filetreelocation.length > 0);
|
|
QE('p5RenameFileButton', (cc == 1) && (filetreelocation.length > 0));
|
|
//QE('p5ViewFileButton', (cc == 1) && (sfc == 1) && (filetreelocation.length > 0));
|
|
QE('p5SelectAllButton', tc > 0);
|
|
Q('p5SelectAllButton').value = (cc > 0 ? "Vybrat nic" : "Vybrat vše");
|
|
QE('p5CutButton', (sfc > 0) && (cc == sfc));
|
|
QE('p5CopyButton', (sfc > 0) && (cc == sfc));
|
|
QE('p5PasteButton', (p5clipboard != null) && (p5clipboard.length > 0) && (filetreelocation.length > 0));
|
|
}
|
|
|
|
function getFileSelCount(includeDirs) { var cc = 0, checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == '3'))) cc++; } return cc; }
|
|
function getFileSelDirCount() { var cc = 0, checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == '999')) cc++; } return cc; }
|
|
function getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fc'); return checkboxes.length; }
|
|
function p5selectallfile() { var nv = (getFileSelCount() == 0), checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p5setActions(); }
|
|
function setupBackPointers(x) { if (x.f != null) { var fs = 0, fc = 0; for (var i in x.f) { setupBackPointers(x.f[i]); x.f[i].parent = x; if (x.f[i].s) { fs += x.f[i].s; } if (x.f[i].c) { fc += x.f[i].c; } if (x.f[i].t == 3) { fc++; } } x.s = fs; x.c = fc; } return x; }
|
|
function getFileSizeStr(size) { if (size == 1) return "1 byte"; return format("{0} bytů", size); }
|
|
function p5folderup(x) { if (x == null) { filetreelocation.pop(); } else { while (filetreelocation.length > x) { filetreelocation.pop(); } } updateFiles(); return false; }
|
|
function p5folderset(x) { filetreelocation.push(decodeURIComponent(x)); updateFiles(); return false; }
|
|
function p5createfolder() { setDialogMode(2, "Nový adresář", 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 cc = getFileSelCount(), rec = (getFileSelDirCount() > 0) ? '<br /><br /><label><input type=checkbox id=p5recdeleteinput>' + "Rekurzivní mazání" + '</label><br>' : '<input type=checkbox id=p5recdeleteinput style=\'display:none\'>'; setDialogMode(2, "Smazat", 3, p5deletefileEx, (cc > 1) ? (format("Smazat {0} vybrané prvky?", cc) + rec) : ("Smazat vybraný prvek?" + rec)); }
|
|
function p5deletefileEx() { var delfiles = [], checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { delfiles.push(checkboxes[i].value); } } meshserver.send({ action: 'fileoperation', fileop: 'delete', path: filetreelocation, delfiles: delfiles, rec: Q('p5recdeleteinput').checked }); }
|
|
function p5renamefile() { var renamefile, checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { renamefile = checkboxes[i].value; } } setDialogMode(2, "Přejmenovat", 3, p5renamefileEx, '<input type=text id=p5renameinput maxlength=64 onkeyup=p5fileNameCheck(event) style=width:100% value="' + renamefile + '" />', { action: 'fileoperation', fileop: 'rename', path: filetreelocation, oldname: renamefile}); focusTextBox('p5renameinput'); p5fileNameCheck(); }
|
|
function p5renamefileEx(b, t) { t.newname = Q('p5renameinput').value; meshserver.send(t); }
|
|
function p5fileNameCheck(e) { var x = isFilenameValid(Q('p5renameinput').value); QE('idx_dlgOkButton', x); if ((x == true) && (e && e.keyCode == 13)) { dialogclose(1); } }
|
|
var isFilenameValid = (function(){ var x1=/^[^\\/:\*\?"<>\|]+$/, x2=/^\./, x3=/^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; return function isFilenameValid(fname){ return x1.test(fname)&&!x2.test(fname)&&!x3.test(fname)&&(fname[0] != '.'); } })();
|
|
function p5uploadFile() { setDialogMode(2, "Nahrát soubor", 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="p5updateUploadDialogOk(\'p5uploadinput\')" /><input type=hidden name=authCookie value=' + authCookie + ' /><input type=submit id=p5loginSubmit style=display:none /><span id=p5confirmOverwriteSpan style=display:none><br /><label><input type=checkbox id=p5confirmOverwrite onchange="p5updateUploadDialogOk(\'p5uploadinput\')" />' + "Potvrdit přepsání?" + '</label></span></form>'); p5updateUploadDialogOk('p5uploadinput'); }
|
|
function p5uploadFileEx() { Q('p5loginSubmit').click(); }
|
|
function p5updateUploadDialogOk() {
|
|
// Check if these are files we can upload, remove all folders.
|
|
var xallfiles = Q('p5uploadinput').files, files = [];
|
|
for (var i in xallfiles) { if ((xallfiles[i].size != null) && (xallfiles[i].size != 0)) { files.push(xallfiles[i]); } }
|
|
|
|
// Check if these files are duplicates of existing files.
|
|
var filetreex = filetree, allfiles = [], overWriteCount = 0;
|
|
for (var i in filetreelocation) {
|
|
if ((filetreex.f != null) && (filetreex.f[filetreelocation[i]] != null)) { filetreex = filetreex.f[filetreelocation[i]]; }
|
|
}
|
|
QE('idx_dlgOkButton', xallfiles.length > 0);
|
|
if (xallfiles.length > 0) {
|
|
if (filetreex.f != null) {
|
|
for (var i in filetreex.f) { allfiles.push(i); }
|
|
for (var i = 0; i < xallfiles.length; i++) {
|
|
if (allfiles.indexOf(xallfiles[i].name) >= 0) { overWriteCount++; } // TODO: If the server is Windows, we need to lowercase both names.
|
|
}
|
|
}
|
|
QV('p5confirmOverwriteSpan', overWriteCount > 0);
|
|
if (overWriteCount > 0) {
|
|
QE('idx_dlgOkButton', Q('p5confirmOverwrite').checked);
|
|
} else {
|
|
Q('p5confirmOverwrite').checked = false;
|
|
QE('idx_dlgOkButton', true);
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
function p5viewfile() {
|
|
var checkboxes = document.getElementsByName('fc');
|
|
for (var i = 0; i < checkboxes.length; i++) {
|
|
if (checkboxes[i].checked) {
|
|
console.log(filetreelocation.join('/') + '/' + checkboxes[i].value); // TODO: Download and show this file
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
var p5clipboard = null, p5clipboardFolder = null, p5clipboardCut = 0;
|
|
function p5copyFile(cut) {
|
|
var checkboxes = document.getElementsByName('fc'); p5clipboard = []; p5clipboardCut = cut, p5clipboardFolder = Clone(filetreelocation);
|
|
for (var i = 0; i < checkboxes.length; i++) {
|
|
if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == '3')) {
|
|
console.log('yy', checkboxes[i].value);
|
|
p5clipboard.push(checkboxes[i].value);
|
|
}
|
|
}
|
|
p5updateClipview();
|
|
}
|
|
function p5pasteFile() { var x = ''; if ((p5clipboard != null) && (p5clipboard.length > 0)) { x = format("Potvrdit {0} z {1} záznam{2} do tohoto umístění?", (p5clipboardCut == 0?'copy':'move'), p5clipboard.length, ((p5clipboard.length > 1)?'s':'')) } setDialogMode(2, "Vložit", 3, p5pasteFileEx, x); }
|
|
function p5pasteFileEx() { meshserver.send({ action: 'fileoperation', fileop: (p5clipboardCut == 0?'copy':'move'), scpath: p5clipboardFolder, path: filetreelocation, names: p5clipboard }); p5folderup(999); if (p5clipboardCut == 1) { p5clipboard = null, p5clipboardFolder = null, p5clipboardCut = 0; p5updateClipview(); } }
|
|
function p5updateClipview() { var x = ''; if ((p5clipboard != null) && (p5clipboard.length > 0)) { x = format("Držím {0} zaznamů{1} pro {2}", p5clipboard.length, ((p5clipboard.length > 1)?'s':''), (p5clipboardCut == 0?"kopírovat":"přesun")) + ', <a href=# onclick="return p5clearClip()" style=cursor:pointer>' + "Vymazat" + '</a>.' } QH('p5bottomstatus', x); p5setActions(); }
|
|
function p5clearClip() { p5clipboard = null; p5clipboardFolder = null; p5clipboardCut = 0; p5updateClipview(); return false; }
|
|
|
|
function p5fileDragDrop(e) {
|
|
if (xxdialogMode) return;
|
|
haltEvent(e);
|
|
QV('bigfail', false);
|
|
QV('bigok', false);
|
|
//QV('p5fileCatchAllInput', false);
|
|
|
|
// Check if these are files we can upload, remove all folders.
|
|
if (e.dataTransfer == null) return;
|
|
var files = [];
|
|
for (var i in e.dataTransfer.files) { if ((e.dataTransfer.files[i].size != null) && (e.dataTransfer.files[i].size != 0)) { files.push(e.dataTransfer.files[i]); } }
|
|
if (files.length == 0) return;
|
|
|
|
// Check if these files are duplicates of existing files.
|
|
var filetreex = filetree, allfiles = [], overWriteCount = 0;
|
|
for (var i in filetreelocation) {
|
|
if ((filetreex.f != null) && (filetreex.f[filetreelocation[i]] != null)) { filetreex = filetreex.f[filetreelocation[i]]; }
|
|
}
|
|
if (filetreex.f != null) {
|
|
for (var i in filetreex.f) { allfiles.push(i); }
|
|
for (var i = 0; i < e.dataTransfer.files.length; i++) {
|
|
if (allfiles.indexOf(e.dataTransfer.files[i].name) >= 0) { overWriteCount++; } // TODO: If the server is Windows, we need to lowercase both names.
|
|
}
|
|
}
|
|
|
|
if (overWriteCount == 0) {
|
|
// If no overwrite, go ahead with upload
|
|
p5PerformUpload(1, files);
|
|
} else {
|
|
// Otherwise, prompt for confirmation
|
|
setDialogMode(2, "Nahrát soubor", 3, p5PerformUpload, format("Nahrání přepíše {0} soubor{1}. Pokračovat?", overWriteCount, addLetterS(overWriteCount)), files);
|
|
}
|
|
}
|
|
|
|
function p5PerformUpload(b, files) {
|
|
// For Chrome & Firefox
|
|
var error = 0;
|
|
p5uploadFile(); // Display the the dialog box
|
|
try { Q('p5uploadinput').files = files; } catch (ex) { error = 1; } // Set the files in the dialog box
|
|
if (error == 0) { p5uploadFileEx(); } // Press the submit button
|
|
setDialogMode(0); // Close the dialog box
|
|
|
|
// For IE browser - This will not work with very large files
|
|
if (error == 1) {
|
|
if (filetreelocation.length == 0) return;
|
|
var names = [], sizes = [], types = [], datas = [], readercount = files.length, totalSize = 0;
|
|
for (var i = 0; i < files.length; i++) { totalSize += files[i].size; }
|
|
if (totalSize > 1300000) { p5uploadFile(); return; } // File is too large, not sure what the real maximum is.
|
|
for (var i = 0; i < files.length; i++) {
|
|
var reader = new FileReader(), file = files[i];
|
|
names.push(file.name);
|
|
sizes.push(file.size);
|
|
types.push(file.type);
|
|
reader.onload = function (event) {
|
|
datas.push(event.target.result);
|
|
if (--readercount == 0) {
|
|
Q('p5fileDragName').value = names.join('*');
|
|
Q('p5fileDragSize').value = sizes.join('*');
|
|
Q('p5fileDragType').value = types.join('*');
|
|
Q('p5fileDragData').value = datas.join('*'); // This will not work for large files, there is a limit on the data size in a field.
|
|
Q('p5fileDragLink').value = encodeURIComponent(filetreelinkpath);
|
|
Q('p5fileDragAuthCookie').value = authCookie;
|
|
Q('p5loginSubmit2').click();
|
|
}
|
|
}
|
|
reader.readAsDataURL(file);
|
|
}
|
|
}
|
|
}
|
|
|
|
var p5dragtimer = null;
|
|
function p5fileDragOver(e) {
|
|
if (xxdialogMode) return;
|
|
haltEvent(e);
|
|
if (p5dragtimer != null) { clearTimeout(p5dragtimer); p5dragtimer = null; }
|
|
var ac = true; // TODO: Set to true if we can accept the file
|
|
if (filetreelocation.length == 0) { ac = false; }
|
|
QV('bigok', ac);
|
|
QV('bigfail', !ac);
|
|
//QV('p5fileCatchAllInput', ac);
|
|
}
|
|
|
|
function p5fileDragLeave(e) {
|
|
if (xxdialogMode) return;
|
|
haltEvent(e);
|
|
if (e.target.id != 'p5filetable') {
|
|
QV('bigfail', false);
|
|
QV('bigok', false);
|
|
//QV('p5fileCatchAllInput', false);
|
|
} else {
|
|
p5dragtimer = setTimeout(function () { QV('bigfail',false); QV('bigok',false); p5dragtimer=null; }, 10);
|
|
}
|
|
}
|
|
|
|
/*
|
|
function p5fileCatchAllInputChanged(e) {
|
|
p5fileDragLeave(e);
|
|
Q('p5fileDragLink2').value = encodeURIComponent(filetreelinkpath);
|
|
Q('p5fileCatchAllSubmit').click();
|
|
}
|
|
*/
|
|
|
|
//
|
|
// MY EVENTS
|
|
//
|
|
|
|
// Highlights the device being hovered
|
|
function eventMouseHover(e, over) {
|
|
e.children[1].classList.remove('g1s');
|
|
e.children[2].style['background-color'] = ((over == 0) ? '#c9c9c9' : '#b9b9b9');
|
|
e.children[3].classList.remove('g2s');
|
|
if (over == 1) { e.children[1].classList.add('g1s'); e.children[3].classList.add('g2s'); }
|
|
}
|
|
|
|
function eventsUpdate() {
|
|
var x = '', dateHeader = null;
|
|
for (var i in events) {
|
|
var event = events[i], time = new Date(event.time);
|
|
if (event.msg) {
|
|
if (event.h == null) { event.h = Math.random(); }
|
|
if (printDate(time) != dateHeader) {
|
|
if (dateHeader != null) x += '</table>';
|
|
dateHeader = printDate(time);
|
|
x += '<table class=p3eventsTable cellpadding=0 cellspacing=0><tr><td colspan=4 class=DevSt>' + dateHeader + '</td></tr>';
|
|
}
|
|
var icon = 'si3';
|
|
if (event.etype == 'user') icon = 'm2';
|
|
if (event.etype == 'server') icon = 'si3';
|
|
|
|
var msg = EscapeHtml(event.msg).split('(R)').join('®');
|
|
if (event.nodeid) {
|
|
var node = getNodeFromId(event.nodeid);
|
|
if (node != null) {
|
|
icon = 'si' + node.icon;
|
|
msg = '<a href=# onclick=\'gotoDevice("' + event.nodeid + '",10);haltEvent(event);\'>' + EscapeHtml(node.name) + '</a> → ' + msg;
|
|
}
|
|
}
|
|
if (event.username) {
|
|
if ((userinfo.siteadmin & 2) && (event.userid)) {
|
|
msg = '<a href=# onclick=\'gotoUser("' + encodeURIComponent(event.userid) + '");haltEvent(event);\'>' + EscapeHtml(event.username) + '</a> → ' + msg;
|
|
} else {
|
|
msg = EscapeHtml(event.username) + ' → ' + msg;
|
|
}
|
|
}
|
|
if (event.etype == 'relay' || event.action == 'relaylog') icon = 'relayIcon16';
|
|
x += '<tr onclick=showEventDetails(' + event.h + ',2) onmouseover=eventMouseHover(this,1) onmouseout=eventMouseHover(this,0) style=cursor:pointer><td style=width:18px><div class=' + icon + '></div></td><td class=g1> </td><td class=style10>' + printTime(time) + ' - ' + msg + '</td><td class=g2> </td></tr><tr style=height:2px></tr>';
|
|
}
|
|
}
|
|
if (dateHeader != null) x += '</table>';
|
|
if (x == '') x = '<br><i>' + "Žádné události" + '</i><br><br>';
|
|
QH('p3events', x);
|
|
}
|
|
|
|
function refreshEvents() {
|
|
meshserver.send({ action: 'events', limit: parseInt(p3limitdropdown.value) });
|
|
}
|
|
|
|
function p3showDownloadEventsDialog(mode) {
|
|
if (xxdialogMode) return;
|
|
var x = "Stáhnout seznam událostí v níže uvedeném formátu." + '<br /><br />';
|
|
x += addHtmlValue("CSV formát", '<a href=# style=cursor:pointer onclick="return p3downloadEventsDialogCSV(' + mode + ')">' + "eventslist.csv" + '</a>');
|
|
x += addHtmlValue("JSON formát", '<a href=# style=cursor:pointer onclick="return p3downloadEventsDialogJSON(' + mode + ')">' + "eventslist.json" + '</a>');
|
|
setDialogMode(2, "Export seznamu událostí", 1, null, x, mode);
|
|
}
|
|
|
|
function p3downloadEventsDialogCSV(mode) {
|
|
var csv, eventList;
|
|
if (mode == 1) { eventList = currentDeviceEvents; }
|
|
if (mode == 2) { eventList = events; }
|
|
if (mode == 3) { eventList = currentUserEvents; }
|
|
csv = "time, type, action, user, message" + '\r\n';
|
|
for (var i in eventList) { csv += '\"' + eventList[i].time + '\",\"' + eventList[i].etype + '\",\"' + ((eventList[i].action != null) ? eventList[i].action : '') + '\",\"' + ((eventList[i].username != null) ? eventList[i].username : '') + '\",\"' + ((eventList[i].msg != null) ? eventList[i].msg : '') + '\"\r\n'; }
|
|
saveAs(new Blob([csv], { type: 'application/octet-stream' }), "eventslist.csv");
|
|
return false;
|
|
}
|
|
|
|
function p3downloadEventsDialogJSON(mode) {
|
|
var r = [], eventList;
|
|
if (mode == 1) { eventList = currentDeviceEvents; }
|
|
if (mode == 2) { eventList = events; }
|
|
if (mode == 3) { eventList = currentUserEvents; }
|
|
for (var i in eventList) { r.push(events[i]); }
|
|
saveAs(new Blob([JSON.stringify(r)], { type: 'application/octet-stream' }), "eventslist.json");
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// MY USERS
|
|
//
|
|
|
|
function updateUsers() {
|
|
QV('MainMenuMyUsers', (users != null) && ((features & 4) == 0));
|
|
QV('LeftMenuMyUsers', (users != null) && ((features & 4) == 0));
|
|
QV('UserNewAccountButton', ((features & 4) == 0) && (serverinfo.domainauth == false));
|
|
if ((users == null) || ((features & 4) != 0)) { QH('p3users', ''); return; }
|
|
|
|
// Sort the list of user id's
|
|
var sortedUserIds = [], maxUsers = 100, hiddenUsers = 0;
|
|
for (var i in users) { sortedUserIds.push(i); }
|
|
sortedUserIds.sort();
|
|
|
|
// Get search
|
|
var userSearch = Q('UserSearchInput').value.toLowerCase();
|
|
var emailSearch = userSearch;
|
|
if (userSearch.startsWith('email:')) { userSearch = null; emailSearch = emailSearch.substring(6); }
|
|
else if (userSearch.startsWith('name:')) { emailSearch = null; userSearch = userSearch.substring(5); }
|
|
else if (userSearch.startsWith('e:')) { userSearch = null; emailSearch = emailSearch.substring(2); }
|
|
else if (userSearch.startsWith('n:')) { emailSearch = null; userSearch = userSearch.substring(2); }
|
|
|
|
// Display the users using the sorted list
|
|
var x = '<table class=p3usersTable cellpadding=0 cellspacing=0>', addHeader = true;
|
|
x += '<th>' + "Jméno" + '<th style=width:80px>Groups<th style=width:120px>' + nobreak("Poslední přístup") + '<th style=width:120px>' + "Práva";
|
|
|
|
// Online users
|
|
for (var i in sortedUserIds) {
|
|
var user = users[sortedUserIds[i]], sessions = null;
|
|
if (wssessions != null) { sessions = wssessions[user._id]; }
|
|
if ((sessions != null) &&
|
|
((userSearch != null) && ((userSearch == '') || (user.name.toLowerCase().indexOf(userSearch) >= 0)) ||
|
|
((emailSearch != null) && ((user.email != null) && (user.email.toLowerCase().indexOf(emailSearch) >= 0))))
|
|
) {
|
|
if (maxUsers > 0) {
|
|
if (addHeader) { x += '<tr><td class=userTableHeader colspan=4>' + "Online uživatelů"; addHeader = false; }
|
|
x += addUserHtml(user, sessions);
|
|
maxUsers--;
|
|
} else {
|
|
hiddenUsers++;
|
|
}
|
|
}
|
|
}
|
|
addHeader = true;
|
|
// Offline users
|
|
for (var i in sortedUserIds) {
|
|
var user = users[sortedUserIds[i]], sessions = null;
|
|
if (wssessions != null) { sessions = wssessions[user._id]; }
|
|
if ((sessions == null) &&
|
|
((userSearch != null) && ((userSearch == '') || (user.name.toLowerCase().indexOf(userSearch) >= 0)) ||
|
|
((emailSearch != null) && ((user.email != null) && (user.email.toLowerCase().indexOf(emailSearch) >= 0))))
|
|
) {
|
|
if (maxUsers > 0) {
|
|
if (addHeader) { x += '<tr><td class=userTableHeader colspan=4>' + "Nepřipojení uživatelé"; addHeader = false; }
|
|
x += addUserHtml(user, sessions);
|
|
maxUsers--;
|
|
} else {
|
|
hiddenUsers++;
|
|
}
|
|
}
|
|
}
|
|
x += '</table>';
|
|
if (hiddenUsers == 1) { x += '<br />' + "1 další uživatel není zobrazen, pomocí vyhledávacího pole vyhledejte uživatele ..." + '<br />'; }
|
|
else if (hiddenUsers > 1) { x += '<br />' + format("{0} dalších uživatelů není zobrazeno, použijte hledat uživatele pomocí vyhledávacího pole...", hiddenUsers) + '<br />'; }
|
|
if (maxUsers == 100) { x += '<br />' + "Žádný uživatele nalezen." + '<br />'; }
|
|
QH('p3users', x);
|
|
|
|
// Update current user panel if needed
|
|
if ((currentUser != null) && (xxcurrentView == 30)) { gotoUser(encodeURIComponent(currentUser._id),true); }
|
|
}
|
|
|
|
function addUserHtml(user, sessions) {
|
|
var x = '', gray = ' gray', icon = 'm2', msg = '', self = (user.name != userinfo.name), lastAccess = '', permissions = '';
|
|
if (sessions != null) {
|
|
gray = '';
|
|
if (self) {
|
|
msg = '<span style=float:right;margin-top:1px;margin-right:4px title=' + "Chat" + '><a href=# onclick=userChat(event,\"" + encodeURIComponent(user._id) + "\",\"" + encodeURIComponent(user.name) + "\")><img src=\'images/icon-chat.png\' height=16 width=16 style=padding-top:2px /></a></span>';
|
|
msg += '<span style=float:right;margin-top:1px;margin-left:4px;margin-right:4px title=Notify><a href=# onclick=\'return showUserAlertDialog(event,\"" + encodeURIComponent(user._id) + "\")\'><img src=\'images/icon-notify.png\' height=16 width=16 style=padding-top:2px /></a></span>';
|
|
}
|
|
if (sessions == 1) { lastAccess += nobreak("1 session"); } else { lastAccess += nobreak(format("{0} spojení", sessions)); }
|
|
} else {
|
|
if (user.login) { lastAccess += '<span title=\"' + format("Poslední přihlášení: {0}", printDateTime(new Date(user.login * 1000))) + '\">' + printDate(new Date(user.login * 1000)) + '</span>'; }
|
|
}
|
|
if (self) { permissions += '<a href=# style=cursor:pointer onclick=\'return showUserAdminDialog(event,\"' + encodeURIComponent(user._id) + '\")\'>'; }
|
|
if ((user.siteadmin != null) && ((user.siteadmin & 32) != 0) && (user.siteadmin != 0xFFFFFFFF)) { permissions += "Zamknuto" + ', '; }
|
|
permissions += '<span title=\'' + "Oprávnění serveru" + '\'>';
|
|
|
|
var urights = user.siteadmin & (0xFFFFFFFF - 224);
|
|
if ((user.siteadmin == null) || (urights == 0)) {
|
|
permissions += "Uživatel";
|
|
} else if (urights == 8) {
|
|
permissions += "Uživatel + Soubory";
|
|
} else if (user.siteadmin == 0xFFFFFFFF) {
|
|
permissions += "Administrátor";
|
|
} else if ((urights & 2) != 0) {
|
|
permissions += "Správce";
|
|
} else {
|
|
permissions += "Částečný";
|
|
}
|
|
if ((user.siteadmin != null) && (user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & (64 + 128)) != 0)) { permissions += '*'; }
|
|
permissions += '</span>';
|
|
//if ((user.quota != null) && ((user.siteadmin & 8) != 0)) { msg += ", " + (user.quota / 1024) + " k"; }
|
|
if (self) { permissions += '</a>'; }
|
|
|
|
var groups = 0
|
|
if (user.links) { for (var i in user.links) { groups++; } }
|
|
|
|
var username = EscapeHtml(user.name), emailVerified = '';
|
|
if (serverinfo.emailcheck == true) { emailVerified = ((user.emailVerified != true) ? ' <b style=color:red title="Email is not verified">✗</b>' : ' <b style=color:green title="Email is verified">✓</b>'); }
|
|
if (user.email != null) {
|
|
if (((features & 0x200000) == 0) || (user.email.toLowerCase() != user.name.toLowerCase())) {
|
|
// Username & email are different
|
|
username += ', <a href=# onclick=\'return doemail(event,\"' + user.email + '\")\'>' + user.email + '</a>' + emailVerified;
|
|
} else {
|
|
// Username & email are the same
|
|
username += ' <a href=# onclick=\'return doemail(event,\"' + user.email + '\")\'><img src="images/mail12.png" height=9 width=12 title="Send email to user" style="margin-top:2px" /></a>' + emailVerified;
|
|
}
|
|
}
|
|
|
|
if ((user.otpsecret > 0) || (user.otphkeys > 0)) { username += ' <img src="images/key12.png" height=12 width=11 title="2nd factor authentication enabled" style="margin-top:2px" />'; }
|
|
if ((user.siteadmin != null) && ((user.siteadmin & 32) != 0) && (user.siteadmin != 0xFFFFFFFF)) { username += ' <img src="images/padlock12.png" height=12 width=8 title="Account is locked" style="margin-top:2px" />'; }
|
|
|
|
x += '<tr tabindex=0 onmouseover=userMouseHover(this,1) onmouseout=userMouseHover(this,0) onkeypress="if (event.key==\'Enter\') gotoUser(\'' + encodeURIComponent(user._id) + '\')"><td style=cursor:pointer onclick=gotoUser(\"' + encodeURIComponent(user._id) + '\")>';
|
|
x += '<div class=bar>';
|
|
x += '<div class=baricon><div class="' + icon + gray + '"></div></div>';
|
|
x += '<div class=g1></div><div class=g2></div>';
|
|
x += '<div><span>' + username + '</span>' + msg + '</div></div><td style=text-align:center>' + groups + '<td style=text-align:center>' + lastAccess + '<td style=text-align:center>' + permissions;
|
|
return x;
|
|
}
|
|
|
|
// Highlights the user being hovered
|
|
function userMouseHover(element, over) {
|
|
var e = element.children[0].children[0];
|
|
e.children[1].classList.remove('g1s');
|
|
e.children[2].classList.remove('g2s');
|
|
if (over == 1) { e.children[1].classList.add('g1s'); e.children[2].classList.add('g2s'); }
|
|
element.children[0].children[0].style['background-color'] = ((over == 0) ? '#c9c9c9' : '#b9b9b9');
|
|
}
|
|
|
|
function userChat(e, userid, name) {
|
|
haltEvent(e);
|
|
var url = '/messenger?id=meshmessenger/' + userid + '/' + encodeURIComponent(userinfo._id) + '&title=' + name;
|
|
if ((authCookie != null) && (authCookie != '')) { url += '&auth=' + authCookie; }
|
|
window.open(url, 'meshmessenger:' + userid);
|
|
meshserver.send({ action: 'meshmessenger', userid: decodeURIComponent(userid) });
|
|
return false;
|
|
}
|
|
|
|
function showUserAlertDialog(e, userid) {
|
|
if (xxdialogMode) return;
|
|
haltEvent(e);
|
|
setDialogMode(2, format("Informovat {0}", EscapeHtml(users[decodeURIComponent(userid)].name)), 3, showUserAlertDialogEx, "Poslat textovou notifikaci tomuto uživateli." + '<textarea id=d2notifyText maxlength=2048 style="width:100%;height:184px;resize:none"></textarea>', userid);
|
|
Q('d2notifyText').focus();
|
|
return false;
|
|
}
|
|
|
|
function showUserAlertDialogEx(button, userid) { meshserver.send({ action: 'notifyuser', userid: decodeURIComponent(userid), msg: Q('d2notifyText').value }); }
|
|
|
|
function doemail(e, addr) {
|
|
if (xxdialogMode) return false;
|
|
haltEvent(e);
|
|
window.open('mailto:' + addr);
|
|
return false;
|
|
}
|
|
|
|
function p4batchAccountCreate() {
|
|
if (xxdialogMode) return;
|
|
var x = "Vytvořit více účtu najednou pomocí importu JSON souboru s následujícím formátem:" + '<br /><pre>[\r\n {"user":"x1","pass":"x","email":"x1@x"},\r\n {"user":"x2","pass":"x","resetNextLogin":true}\r\n]</pre><input style=width:370px type=file id=d4importFile accept=".json" onchange=p4batchAccountCreateValidate() />';
|
|
setDialogMode(2, "Import uživatelských účtů", 3, p4batchAccountCreateEx, x);
|
|
QE('idx_dlgOkButton', false);
|
|
}
|
|
|
|
function p4batchAccountCreateValidate() {
|
|
QE('idx_dlgOkButton', Q('d4importFile').value != null);
|
|
}
|
|
|
|
function p4batchAccountCreateEx() {
|
|
var fr = new FileReader();
|
|
fr.onload = function (r) {
|
|
var j = null;
|
|
try { j = JSON.parse(r.target.result); } catch (ex) { setDialogMode(2, "Import uživatelských účtů", 1, null, format("Neplatný JSON soubor: {0}.", ex)); return; }
|
|
if ((j != null) && (Array.isArray(j))) {
|
|
var ok = true;
|
|
for (var i in j) {
|
|
if ((typeof j[i].user != 'string') || (j[i].user.length < 1) || (j[i].user.length > 64)) { ok = false; }
|
|
if ((typeof j[i].pass != 'string') || (j[i].pass.length < 1) || (j[i].pass.length > 256)) { ok = false; }
|
|
if (checkPasswordRequirements(j[i].pass, passRequirements) == false) { ok = false; }
|
|
if ((j[i].email != null) && ((typeof j[i].email != 'string') || (j[i].email.length < 1) || (j[i].email.length > 128))) { ok = false; }
|
|
}
|
|
if (ok == false) { setDialogMode(2, "Import uživatelských účtů", 1, null, "Neplatný formát JSON souboru."); } else { meshserver.send({ action: 'adduserbatch', users: j }); }
|
|
} else { setDialogMode(2, "Import uživatelských účtů", 1, null, "Neplatný formát JSON souboru."); }
|
|
};
|
|
fr.readAsText(Q('d4importFile').files[0]);
|
|
}
|
|
|
|
function p4downloadUserInfo() {
|
|
if (xxdialogMode) return;
|
|
var x = "Stáhnout seznam uživatelů v níže uvedeném formátu." + '<br /><br />';
|
|
x += addHtmlValue("CSV formát", '<a href=# style=cursor:pointer onclick=\'return p4downloadUserInfoCSV()\'>' + "userlist.csv" + '</a>');
|
|
x += addHtmlValue("JSON formát", '<a href=# style=cursor:pointer onclick=\'return p4downloadUserInfoJSON()\'>' + "userlist.json" + '</a>');
|
|
setDialogMode(2, "Export seznamu uživatelů", 1, null, x);
|
|
}
|
|
|
|
function p4downloadUserInfoCSV() {
|
|
var csv = "id, jméno, email, vytvoření, poslední přihlášení, skupiny, ověřovatel" + '\r\n';
|
|
for (var i in users) {
|
|
var multiFactor = false, factors = [];
|
|
if ((users[i].otpsecret > 0) || (users[i].otphkeys > 0)) {
|
|
multiFactor = true;
|
|
if (users[i].otpsecret > 0) { factors.push('AuthApp'); }
|
|
if (users[i].otphkeys > 0) { factors.push('SecurityKey'); }
|
|
if (users[i].otpkeys > 0) { factors.push('BackupCodes'); }
|
|
}
|
|
csv += '\"' + users[i]._id + '\",\"' + users[i].name + '\",\"' + (users[i].email ? users[i].email : '') + '\",\"' + (users[i].creation ? new Date(users[i].creation * 1000) : '') + '\",\"' + (users[i].login ? new Date(users[i].login * 1000) : '') + '\",\"' + (users[i].groups ? users[i].groups.join(',') : '') + '\",\"' + (multiFactor ? factors.join(',') : '') + '\"\r\n';
|
|
}
|
|
saveAs(new Blob([csv], { type: 'application/octet-stream' }), "userlist.csv");
|
|
return false;
|
|
}
|
|
|
|
function p4downloadUserInfoJSON() {
|
|
var r = []
|
|
for (var i in users) { r.push(users[i]); }
|
|
saveAs(new Blob([JSON.stringify(r)], { type: 'application/octet-stream' }), "userlist.json");
|
|
return false;
|
|
}
|
|
|
|
function showUserBroadcastDialog() {
|
|
if (xxdialogMode) return;
|
|
var x = "Zaslat hromadnou zprávu všem připojeným uživatelům." + '<textarea id=broadcastMessage value="" maxlength="256"/></textarea>';
|
|
setDialogMode(2, "Hromadná zpráva", 3, showUserBroadcastDialogEx, x);
|
|
Q('broadcastMessage').focus();
|
|
}
|
|
|
|
function showUserBroadcastDialogEx() {
|
|
meshserver.send({ action: 'userbroadcast', msg: Q('broadcastMessage').value });
|
|
}
|
|
|
|
function showCreateNewAccountDialog() {
|
|
if (xxdialogMode) return;
|
|
var x = '';
|
|
if ((features & 0x200000) == 0) { x += addHtmlValue("Jméno", '<input id=p4name maxlength=64 onchange=showCreateNewAccountDialogValidate() onkeyup=showCreateNewAccountDialogValidate() />'); }
|
|
x += addHtmlValue("Email", '<input id=p4email maxlength=256 onchange=showCreateNewAccountDialogValidate() onkeyup=showCreateNewAccountDialogValidate() />');
|
|
x += addHtmlValue("Heslo", '<input id=p4pass1 type=password maxlength=256 onchange=showCreateNewAccountDialogValidate() onkeyup=showCreateNewAccountDialogValidate() />');
|
|
x += addHtmlValue("Heslo", '<input id=p4pass2 type=password maxlength=256 onchange=showCreateNewAccountDialogValidate() onkeyup=showCreateNewAccountDialogValidate() />');
|
|
x += '<div><label><input id=p4randomPassword onchange=showCreateNewAccountDialogValidate() type=checkbox />' + "Náhodné heslo" + '</label></div>';
|
|
x += '<div><label><input id=p4resetNextLogin onchange=showCreateNewAccountDialogValidate() type=checkbox />' + "Vynutit reset hesla při dalším přihlášení." + '</label></div>';
|
|
if (serverinfo.emailcheck) {
|
|
x += '<div><label><input id=p4verifiedEmail onchange=showCreateNewAccountDialogValidate() type=checkbox />' + "Email je ověřen." + '</label></div>';
|
|
x += '<div><label><input id=p4invitationEmail type=checkbox />' + "Zaslat pozvánku emailem." + '</label></div>';
|
|
}
|
|
|
|
if (passRequirements) {
|
|
var r = [], rc = 0;
|
|
for (var i in passRequirements) { if ((i != 'reset') && (i != 'hint')) { r.push(i + ':' + passRequirements[i]); rc++; } }
|
|
if (rc > 0) { x += '<div style=font-size:x-small;padding:6px>' + format("Požadavky: {0}.", r.join(', ')) + '</div>'; }
|
|
}
|
|
|
|
setDialogMode(2, "Vytvořit účet", 3, showCreateNewAccountDialogEx, x);
|
|
showCreateNewAccountDialogValidate();
|
|
if ((features & 0x200000) == 0) { Q('p4name').focus(); } else { Q('p4email').focus(); }
|
|
}
|
|
|
|
function showCreateNewAccountDialogValidate(x) {
|
|
var ve = true;
|
|
if (serverinfo.emailcheck) {
|
|
ve = validateEmail(Q('p4email').value);
|
|
QE('p4verifiedEmail', ve);
|
|
QE('p4invitationEmail', ve && Q('p4resetNextLogin').checked && Q('p4verifiedEmail').checked);
|
|
if (ve == false) { Q('p4verifiedEmail').checked = false; }
|
|
if ((Q('p4resetNextLogin').checked == false) || (Q('p4verifiedEmail').checked == false)) { Q('p4invitationEmail').checked = false; }
|
|
}
|
|
QE('p4pass1', !Q('p4randomPassword').checked);
|
|
QE('p4pass2', !Q('p4randomPassword').checked);
|
|
|
|
if ((x == null) && (Q('p4email').value.length > 0) && (ve == false)) { QE('idx_dlgOkButton', false); return; }
|
|
var ok = true;
|
|
if ((features & 0x200000) == 0) { ok &= (!Q('p4name') || ((Q('p4name').value.length > 0) && (Q('p4name').value.indexOf(' ') == -1))); } // Username is not email address
|
|
if (Q('p4randomPassword').checked == false) { ok &= (Q('p4pass1').value.length > 0 && Q('p4pass1').value == Q('p4pass2').value && checkPasswordRequirements(Q('p4pass1').value, passRequirements)); }
|
|
QE('idx_dlgOkButton', ok);
|
|
}
|
|
|
|
function showCreateNewAccountDialogEx() {
|
|
var username = ((features & 0x200000) == 0) ? Q('p4name').value : Q('p4email').value; // Username is email address
|
|
var x = { action: 'adduser', username: username, email: Q('p4email').value, pass: Q('p4pass1').value, resetNextLogin: Q('p4resetNextLogin').checked, randomPassword: Q('p4randomPassword').checked };
|
|
if (serverinfo.emailcheck) {
|
|
x.emailVerified = Q('p4verifiedEmail').checked;
|
|
x.emailInvitation = Q('p4invitationEmail').checked;
|
|
}
|
|
meshserver.send(x);
|
|
}
|
|
|
|
function showUserGroupDialog(e, userid) {
|
|
if (xxdialogMode) return;
|
|
haltEvent(e);
|
|
userid = decodeURIComponent(userid);
|
|
var user = users[userid.toLowerCase()], groups = "";
|
|
if (user.groups != null) { groups = user.groups.join(', ') }
|
|
var x = "Zadejte seznam administrativních realmů oddělených čárkami." + '<br /><br />';
|
|
x += addHtmlValue("Realmy", '<input id=dp4usergroups style=width:230px value="' + groups + '" placeholder=\"' + "Jméno1, Jméno2, Jméno3" + '\" maxlength=256 onchange=p4validateUserGroups() onkeyup=p4validateUserGroups() />');
|
|
setDialogMode(2, "Administrátorské realmy", 3, showUserGroupDialogEx, x, user);
|
|
focusTextBox('dp4usergroups');
|
|
p4validateUserGroups();
|
|
return false;
|
|
}
|
|
|
|
function p4validateUserGroups() {
|
|
var groups = Q('dp4usergroups').value;
|
|
var k = 0, i = groups.indexOf('\"') + groups.indexOf('/') + groups.indexOf('>') + groups.indexOf('<') + groups.indexOf('\'');
|
|
var g = groups.split(',');
|
|
for (var j in g) { if (g[j].trim().length == 0) k++; }
|
|
QE('idx_dlgOkButton', (groups == '') || ((i == -5) && (k < 1)));
|
|
}
|
|
|
|
function showUserGroupDialogEx(event, user) {
|
|
var groups = Q('dp4usergroups').value, g = groups.split(','), g2 = [];
|
|
for (var j in g) { var x = g[j].trim(); if (x.length > 0) { g2.push(x); } }
|
|
meshserver.send({ action: 'edituser', id: user._id, groups: g2 });
|
|
}
|
|
|
|
function showUserAdminDialog(e, userid) {
|
|
if (xxdialogMode) return;
|
|
haltEvent(e);
|
|
userid = decodeURIComponent(userid);
|
|
var x = '<div><div id=d2AdminPermissions>';
|
|
x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_fileaccess>' + "Soubory serveru" + '</label>, <input type=number onchange=showUserAdminDialogValidate() maxlength=10 id=ua_fileaccessquota>k max, blank for default<br><hr/>';
|
|
x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_fulladmin>' + "Hlavní administrátor" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_serverbackup>' + "Záloha serveru" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_serverrestore>' + "Obnova serveru" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_serverupdate>' + "Aktualizace serveru" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_manageusers>' + "Správa uživatelů" + '</label><br>';
|
|
x += '<hr/></div><label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_lockedaccount>' + "Uzamknout účet" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_nonewgroups>' + "Žádná nová skupina zařízení" + '</label><br>';
|
|
x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_nomeshcmd>' + "Žádné nástroje (MeshCmd/Router)" + '</label><br>';
|
|
x += '</div>';
|
|
var user = users[userid.toLowerCase()];
|
|
setDialogMode(2, "Oprávnění serveru", 3, showUserAdminDialogEx, x, user);
|
|
if (user.siteadmin && user.siteadmin != 0) {
|
|
Q('ua_fulladmin').checked = (user.siteadmin == 0xFFFFFFFF);
|
|
Q('ua_serverbackup').checked = ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1) != 0)); // Server Backup
|
|
Q('ua_manageusers').checked = ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 2) != 0)); // Manage Users
|
|
Q('ua_serverrestore').checked = ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 4) != 0)); // Server Restore
|
|
Q('ua_fileaccess').checked = ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 8) != 0)); // Server Files
|
|
Q('ua_serverupdate').checked = ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 16) != 0)); // Server Update
|
|
Q('ua_lockedaccount').checked = ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 32) != 0)); // Account locked
|
|
Q('ua_nonewgroups').checked = ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 64) != 0)); // No New Groups
|
|
Q('ua_nomeshcmd').checked = ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 128) != 0)); // No Tools (MeshCMD / Router)
|
|
}
|
|
QE('ua_fulladmin', userinfo.siteadmin == 0xFFFFFFFF);
|
|
QE('ua_serverbackup', userinfo.siteadmin == 0xFFFFFFFF);
|
|
QE('ua_manageusers', userinfo.siteadmin == 0xFFFFFFFF);
|
|
QE('ua_serverrestore', userinfo.siteadmin == 0xFFFFFFFF);
|
|
QE('ua_fileaccess', userinfo.siteadmin == 0xFFFFFFFF);
|
|
QE('ua_fileaccessquota', userinfo.siteadmin == 0xFFFFFFFF);
|
|
QE('ua_serverupdate', userinfo.siteadmin == 0xFFFFFFFF);
|
|
QV('d2AdminPermissions', userinfo.siteadmin == 0xFFFFFFFF)
|
|
QE('ua_lockedaccount', (userinfo.siteadmin & 2) && (user.siteadmin != 0xFFFFFFFF) && (userinfo._id != user._id));
|
|
QE('ua_nonewgroups', (userinfo.siteadmin & 2) && (user.siteadmin != 0xFFFFFFFF) && (userinfo._id != user._id));
|
|
QE('ua_nomeshcmd', (userinfo.siteadmin & 2) && (user.siteadmin != 0xFFFFFFFF) && (userinfo._id != user._id));
|
|
Q('ua_fileaccessquota').value = (user.quota != null)?(user.quota / 1024):'';
|
|
showUserAdminDialogValidate();
|
|
return false;
|
|
}
|
|
|
|
function showUserAdminDialogValidate() {
|
|
if (userinfo.siteadmin == 0xFFFFFFFF) {
|
|
QE('ua_serverbackup', !Q('ua_fulladmin').checked);
|
|
QE('ua_manageusers', !Q('ua_fulladmin').checked);
|
|
QE('ua_serverrestore', !Q('ua_fulladmin').checked);
|
|
QE('ua_fileaccess', !Q('ua_fulladmin').checked);
|
|
QE('ua_serverupdate', !Q('ua_fulladmin').checked);
|
|
QE('ua_lockedaccount', !Q('ua_fulladmin').checked);
|
|
QE('ua_nonewgroups', !Q('ua_fulladmin').checked);
|
|
QE('ua_nomeshcmd', !Q('ua_fulladmin').checked);
|
|
QE('ua_fileaccessquota', Q('ua_fileaccess').checked && !Q('ua_fulladmin').checked);
|
|
}
|
|
}
|
|
|
|
function showUserAdminDialogEx(button, user) {
|
|
var siteadmin = 0, quota = parseInt(Q('ua_fileaccessquota').value);
|
|
if (Q('ua_fulladmin').checked == true) { siteadmin = 0xFFFFFFFF; } else {
|
|
if (Q('ua_serverbackup').checked == true) siteadmin += 1;
|
|
if (Q('ua_manageusers').checked == true) siteadmin += 2;
|
|
if (Q('ua_serverrestore').checked == true) siteadmin += 4;
|
|
if (Q('ua_fileaccess').checked == true) siteadmin += 8;
|
|
if (Q('ua_serverupdate').checked == true) siteadmin += 16;
|
|
if (Q('ua_lockedaccount').checked == true) siteadmin += 32;
|
|
if (Q('ua_nonewgroups').checked == true) siteadmin += 64;
|
|
if (Q('ua_nomeshcmd').checked == true) siteadmin += 128;
|
|
}
|
|
var x = { action: 'edituser', id: user._id, siteadmin: siteadmin };
|
|
if (isNaN(quota) == false) { x.quota = (quota * 1024); }
|
|
meshserver.send(x);
|
|
}
|
|
|
|
function onUserSearchInputChanged() { updateUsers(); }
|
|
|
|
//
|
|
// MY USERS GENERAL
|
|
//
|
|
|
|
var currentUser = null;
|
|
function gotoUser(userid, force) {
|
|
if (xxdialogMode && !force) return;
|
|
var user = currentUser = users[decodeURIComponent(userid)];
|
|
if (user == null) { setDialogMode(0); go(4); return; }
|
|
QH('p30userName', user.name);
|
|
QH('p31userName', user.name);
|
|
var self = (user.name == userinfo.name), activeSessions = 0;
|
|
if (wssessions != null && wssessions[user._id]) { activeSessions = wssessions[user._id]; }
|
|
|
|
// Change user grayscale
|
|
Q('MainUserImage').classList.remove('gray');
|
|
if (activeSessions == 0) { Q('MainUserImage').classList.add('gray'); }
|
|
|
|
// Server permissions
|
|
var msg = [], premsg = '';
|
|
if ((user.siteadmin != null) && ((user.siteadmin & 32) != 0) && (user.siteadmin != 0xFFFFFFFF)) { premsg = '<img src="images/padlock12.png" height=12 width=8 title="Account is locked" style="margin-top:2px" /> '; msg.push("Uzamknutý účet"); }
|
|
if ((user.siteadmin == null) || ((user.siteadmin & (0xFFFFFFFF - 224)) == 0)) { msg.push("Žádná práva k serveru"); } else if (user.siteadmin == 8) { msg.push("Přístup k souborům na serveru"); } else if (user.siteadmin == 0xFFFFFFFF) { msg.push("Hlavní administrator"); } else { msg.push("Částečné práva"); }
|
|
if ((user.siteadmin != null) && (user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & (64 + 128)) != 0)) { msg.push("Omezení"); }
|
|
|
|
// Show user attributes
|
|
var x = '<div style=min-height:80px><table style=width:100%>';
|
|
var email = user.email?EscapeHtml(user.email):'<i>' + "Nenastaveno" + '</i>', everify = '';
|
|
if (serverinfo.emailcheck) { everify = ((user.emailVerified == true) ? '<b style=color:green;cursor:pointer title=\"' + "Email ověřen" + '\">✓</b> ' : '<b style=color:red;cursor:pointer title=\"' + "Email není ověřen" + '\">✗</b> '); }
|
|
if (user.name.toLowerCase() != user._id.split('/')[2]) { x += addDeviceAttribute("Identifikátor uživatele", user._id.split('/')[2]); }
|
|
if (((features & 0x200000) == 0) && ((user.siteadmin != 0xFFFFFFFF) || (userinfo.siteadmin == 0xFFFFFFFF))) { // If we are not site admin, we can't change a admin email.
|
|
x += addDeviceAttribute("Email", everify + '<a href=# style=cursor:pointer onclick=p30showUserEmailChangeDialog(event,\"' + userid + '\")>' + email + '</a> <a href=# style=cursor:pointer onclick=\'return doemail(event,\"' + user.email + '\")\'><img class=hoverButton src="images/link1.png" /></a>');
|
|
} else {
|
|
x += addDeviceAttribute("Email", everify + email + ' <a href=# style=cursor:pointer onclick=\'return doemail(event,\"' + user.email + '\")\'><img class=hoverButton src="images/link1.png" /></a>');
|
|
}
|
|
x += addDeviceAttribute("Práva serveru", premsg + '<a href=# style=cursor:pointer onclick=\'return showUserAdminDialog(event,\"' + userid + '\")\'>' + msg.join(', ') + '</a>');
|
|
if (user.quota) x += addDeviceAttribute("Kvóta serveru", EscapeHtml(parseInt(user.quota) / 1024) + ' k');
|
|
x += addDeviceAttribute("Vytváření", printDateTime(new Date(user.creation * 1000)));
|
|
if (user.login) x += addDeviceAttribute("Poslední přihlášení", printDateTime(new Date(user.login * 1000)));
|
|
if (user.passchange == -1) { x += addDeviceAttribute("Heslo", "Bude změněno při příštím přihlášení."); }
|
|
else if (user.passchange) { x += addDeviceAttribute("Heslo", format("Poslední změna: {0}", printDateTime(new Date(user.passchange * 1000)))); }
|
|
|
|
// Device Groups
|
|
var linkCount = 0, linkCountStr = '<i>' + "Nic" + '<i>';
|
|
if (user.links) {
|
|
for (var i in user.links) { linkCount++; }
|
|
if (linkCount == 1) { linkCountStr = "1 skupina"; } else if (linkCount > 1) { linkCountStr = format("{0} skupin", linkCount); }
|
|
}
|
|
x += addDeviceAttribute("Skupiny zařízení", linkCountStr);
|
|
|
|
// Administrative Realms
|
|
if ((userinfo.siteadmin == 0xFFFFFFFF) || (userinfo.siteadmin & 2)) {
|
|
var userGroups = '<i>' + "Nic" + '</i>';
|
|
if (user.groups) { userGroups = ''; for (var i in user.groups) { userGroups += '<span class="tagSpan">' + user.groups[i] + '</span>'; } }
|
|
x += addDeviceAttribute("Administrátorské realmy", addLinkConditional(userGroups, 'showUserGroupDialog(event,\"' + userid + '\")', (userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.groups == null) && (userinfo._id != user._id) && (user.siteadmin != 0xFFFFFFFF))));
|
|
}
|
|
|
|
var multiFactor = 0;
|
|
if ((user.otpsecret > 0) || (user.otphkeys > 0)) {
|
|
multiFactor = 1;
|
|
var factors = [];
|
|
if (user.otpsecret > 0) { factors.push("Autentizační aplikace"); }
|
|
if (user.otphkeys > 0) { factors.push("Bezpečnostní klíč"); }
|
|
if (user.otpkeys > 0) { factors.push("Záloha kódu"); }
|
|
x += addDeviceAttribute("Bezpečnost", '<img src="images/key12.png" height=12 width=11 title=\"' + "2-faktorová autentizace povolena" + '\" style="margin-top:2px" /> ' + factors.join(', '));
|
|
}
|
|
|
|
x += '</table></div><br />';
|
|
|
|
// Add action buttons
|
|
x += '<input type=button value=\"' + "Poznámky" + '\" title=\"' + "Zobrazit poznámky o tomto uživateli" + '\" onclick=showNotes(false,"' + userid + '") />';
|
|
if (!self && (activeSessions > 0)) { x += '<input type=button value=\"' + "Oznámit" + '\" title=\"' + "Poslat notifikaci uživatelovi" + '\" onclick=showUserAlertDialog(event,"' + userid + '") />'; }
|
|
|
|
// Setup the panel
|
|
QH('p30html', x);
|
|
|
|
// Draw the user timeline
|
|
drawUserTimeline();
|
|
|
|
// Check if we can delete this user
|
|
var deletePossible = true;
|
|
if (user._id == userinfo._id) deletePossible = false;
|
|
if (user.siteadmin && user.siteadmin > 0 && userinfo.siteadmin != 0xFFFFFFFF) deletePossible = false;
|
|
|
|
// Show bottom buttons
|
|
x = '<div style=float:right;font-size:x-small>';
|
|
if (deletePossible) x += '<a href=# style=cursor:pointer onclick=\'return p30showDeleteUserDialog()\' title="Remove this user">Delete User</a>';
|
|
x += '</div><div style=font-size:x-small>';
|
|
if (userinfo.siteadmin == 0xFFFFFFFF) x += '<a href=# style=cursor:pointer onclick=\'return p30showUserChangePassDialog(' + multiFactor + ')\' title="Change the password for this user">Change Password</a>';
|
|
x += '</div><br>'
|
|
QH('p30html3', x);
|
|
|
|
// Update user's connection state
|
|
x = '';
|
|
if (activeSessions == 1) { x = "1 session aktivní"; } else if (activeSessions > 1) { x = format("{0} aktivních spojení", activeSessions); }
|
|
QH('MainUserState', x);
|
|
|
|
go(30);
|
|
|
|
// Update user events (TODO: do this only if we change users)
|
|
QH('p31events', '');
|
|
refreshUsersEvents();
|
|
}
|
|
|
|
// Display the user's email change dialog box
|
|
function p30showUserEmailChangeDialog(event) {
|
|
if (xxdialogMode) return false;
|
|
var x = '';
|
|
x += addHtmlValue("Email", '<input id=dp30email style=width:230px maxlength=32 onchange=p30validateEmail() onkeyup=p30validateEmail() />');
|
|
if (serverinfo.emailcheck) { x += addHtmlValue("Status", '<select id=dp30verified style=width:230px onchange=p30validateEmail()><option value=0>Not verified</option><option value=1>Verified</option></select>'); }
|
|
setDialogMode(2, format("Změnit email pro {0}", EscapeHtml(currentUser.name)), 3, p30showUserEmailChangeDialogEx, x);
|
|
Q('dp30email').focus();
|
|
Q('dp30email').value = (currentUser.email?currentUser.email:'');
|
|
if (serverinfo.emailcheck) { Q('dp30verified').value = currentUser.emailVerified?1:0; }
|
|
p30validateEmail();
|
|
return false;
|
|
}
|
|
|
|
// Perform validation on the user's email change dialog box
|
|
function p30validateEmail() {
|
|
var v = Q('dp30email').value, x = v.split('@');
|
|
x = (x.length == 2) && (x[0].length > 0) && (x[1].split('.').length > 1) && (x[1].length > 2) && (v.length < 1024) && ((v != userinfo.email) || ((serverinfo.emailcheck == true) && (Q('dp30verified').value != (userinfo.emailVerified?1:0))));
|
|
QE('idx_dlgOkButton', x);
|
|
}
|
|
|
|
// Send to the server the new user's email address and validation status
|
|
function p30showUserEmailChangeDialogEx() {
|
|
var x = { action: 'edituser', id: currentUser._id, email: Q('dp30email').value };
|
|
if (serverinfo.emailcheck) { x.emailVerified = (Q('dp30verified').value == 1); }
|
|
meshserver.send(x);
|
|
}
|
|
|
|
// Display the user's password change dialog box
|
|
function p30showUserChangePassDialog(multiFactor) {
|
|
if (xxdialogMode) return;
|
|
var x = '';
|
|
x += addHtmlValue("Heslo", '<input id=p4pass1 type=password style=width:230px maxlength=256 onchange=p30showUserChangePassDialogValidate(1) onkeyup=p30showUserChangePassDialogValidate(1)></input>');
|
|
x += addHtmlValue("Heslo", '<input id=p4pass2 type=password style=width:230px maxlength=256 onchange=p30showUserChangePassDialogValidate(1) onkeyup=p30showUserChangePassDialogValidate(1)></input>');
|
|
if (features & 0x00010000) { x += addHtmlValue("Nápověda k heslu", '<input id=p4hint type=text style=width:230px maxlength=256></input>'); }
|
|
|
|
if (passRequirements) {
|
|
var r = [], rc = 0;
|
|
for (var i in passRequirements) { if ((i != 'reset') && (i != 'hint')) { r.push(i + ':' + passRequirements[i]); rc++; } }
|
|
if (rc > 0) { x += '<div style=font-size:x-small;padding:6px>' + format("Požadavky: {0}.", r.join(', ')) + '</div>'; }
|
|
}
|
|
|
|
x += '<div><label><input id=p4resetNextLogin type=checkbox />' + "Vynutit reset hesla při dalším přihlášení." + '</label></div>';
|
|
if (multiFactor == 1) { x += '<div><label><input id=p4twoFactorRemove type=checkbox />' + "Odstranit celou 2-faktorovou autentizaci." + '</label></div>'; }
|
|
setDialogMode(2, format("Změnit heslo pro {0}", EscapeHtml(currentUser.name)), 3, p30showUserChangePassDialogEx, x, multiFactor);
|
|
p30showUserChangePassDialogValidate();
|
|
Q('p4pass1').focus();
|
|
if (currentUser.passchange == -1) { Q('p4resetNextLogin').checked = true; }
|
|
}
|
|
|
|
function p30showUserChangePassDialogValidate() {
|
|
var ok = true;
|
|
if ((Q('p4pass1').value != '') || (Q('p4pass2').value != '')) {
|
|
if (Q('p4pass1').value != Q('p4pass2').value) { ok = false; } else {
|
|
if (passRequirements) { if (checkPasswordRequirements(Q('p4pass1').value, passRequirements) == false) { ok = false; } }
|
|
}
|
|
}
|
|
QE('idx_dlgOkButton', ok);
|
|
}
|
|
|
|
function p30showUserChangePassDialogEx(b, tag) {
|
|
var removeMultiFactor = false;
|
|
if ((tag == 1) && (Q('p4twoFactorRemove').checked == true)) { removeMultiFactor = true; }
|
|
if (Q('p4pass1').value == Q('p4pass2').value) {
|
|
var r = { action: 'changeuserpass', userid: currentUser._id, pass: Q('p4pass1').value, removeMultiFactor: removeMultiFactor, resetNextLogin: Q('p4resetNextLogin').checked };
|
|
if (features & 0x00010000) { r.hint = Q('p4hint').value; }
|
|
meshserver.send(r);
|
|
}
|
|
}
|
|
|
|
function p30showDeleteUserDialog() {
|
|
if (xxdialogMode) return;
|
|
setDialogMode(2, format("Smazat uživatele {0}", EscapeHtml(currentUser.name)), 3, p30showDeleteUserDialogEx, format('Confirm deletion of user {0}?', EscapeHtml(currentUser.name)));
|
|
}
|
|
|
|
function p30showDeleteUserDialogEx() {
|
|
meshserver.send({ action: 'deleteuser', userid: currentUser._id, username: currentUser.name });
|
|
}
|
|
|
|
// Draw device power bars. The bars are 766px wide.
|
|
function drawUserTimeline() {
|
|
var timeline = null, now = Date.now();
|
|
//if (currentNode._id == powerTimelineNode) { timeline = powerTimeline; }
|
|
timeline = [];
|
|
|
|
// Calculate when the timeline starts
|
|
var d = new Date();
|
|
d.setHours(0, 0, 0, 0);
|
|
d = new Date(d.getTime() - (1000 * 60 * 60 * 24 * 6));
|
|
var timelineStart = d.getTime();
|
|
|
|
// De-compact the timeline
|
|
var timeline2 = [];
|
|
if (timeline != null && timeline.length > 1) {
|
|
timeline2.push([ 0, timeline[1], timeline[0] ]); // Start, End, Power
|
|
var ct = timeline[1];
|
|
for (var i = 2; i < timeline.length; i += 2) {
|
|
var power = timeline[i], dt = now;
|
|
if (timeline.length > (i + 1)) { dt = timeline[i + 1]; }
|
|
timeline2.push([ ct, ct + dt, power ]); // Start, End, Power
|
|
ct = ct + dt;
|
|
}
|
|
}
|
|
|
|
// Draw the timeline
|
|
var x = '', count = 1, date = new Date();
|
|
date.setHours(0, 0, 0, 0);
|
|
for (var i = 0; i < 7; i++) {
|
|
var datavalue = '', start = date.getTime(), end = start + (1000 * 60 * 60 * 24);
|
|
for (var j in timeline2) {
|
|
var block = timeline2[j];
|
|
if (isTimeBlockInside(start, end, block[0], block[1]) == true) {
|
|
var ts = Math.max(start, block[0]);
|
|
var te = Math.min(Math.min(end, block[1]), now);
|
|
var width = Math.round((te - ts) / 112794);
|
|
if (width > 0) {
|
|
var title = powerStateStrings2[block[2]] + ' from ' + printTime(new Date(ts)) + ' to ' + printTime(new Date(te)) + '.';
|
|
datavalue += '<div title="' + title + '" style=display:table-cell;width:' + width + 'px;background-color:' + powerColor(block[2]) + ';height:16px></div>';
|
|
}
|
|
}
|
|
}
|
|
x += '<tr style=' + (((count % 2) == 0)?'background-color:#DDD':'') + '><td><div> ' + printDate(date) + '<div></div></div></td><td><div>' + datavalue + '</div></td></tr>';
|
|
++count;
|
|
date = new Date(date.getTime() - (1000 * 60 * 60 * 24)); // Substract one day
|
|
}
|
|
QH('p30html2', '<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:center;width:150px>Day</th><th scope=col style=text-align:center>7 Day Login State</th></tr>' + x + '</tbody></table>');
|
|
}
|
|
|
|
//
|
|
// MY USERS EVENTS
|
|
//
|
|
|
|
var currentUserEvents = null;
|
|
function userEventsUpdate() {
|
|
var x = '', dateHeader = null;
|
|
for (var i in currentUserEvents) {
|
|
var event = currentUserEvents[i], time = new Date(event.time);
|
|
if (event.msg) {
|
|
if (event.h == null) { event.h = Math.random(); }
|
|
if (printDate(time) != dateHeader) {
|
|
if (dateHeader != null) x += '</table>';
|
|
dateHeader = printDate(time);
|
|
x += '<table class=p3eventsTable cellpadding=0 cellspacing=0><tr><td colspan=4 class=DevSt>' + dateHeader + '</td></tr>';
|
|
}
|
|
var icon = 'si3';
|
|
if (event.etype == 'user') icon = 'm2';
|
|
if (event.etype == 'server') icon = 'si3';
|
|
|
|
var msg = EscapeHtml(event.msg).split('(R)').join('®');
|
|
if (event.nodeid) {
|
|
var node = getNodeFromId(event.nodeid);
|
|
if (node != null) {
|
|
icon = 'si' + node.icon;
|
|
msg = '<a href=# onclick=\'gotoDevice("' + event.nodeid + '",10);haltEvent(event);\'>' + EscapeHtml(node.name) + '</a> → ' + msg;
|
|
}
|
|
}
|
|
if (event.username && (event.username != currentUser.name)) {
|
|
if ((userinfo.siteadmin & 2) && (event.userid)) {
|
|
msg = '<a href=# onclick=\'gotoUser("' + encodeURIComponent(event.userid) + '");haltEvent(event);\'>' + EscapeHtml(event.username) + '</a> → ' + msg;
|
|
} else {
|
|
msg = EscapeHtml(event.username) + ' → ' + msg;
|
|
}
|
|
}
|
|
if (event.etype == 'relay' || event.action == 'relaylog') icon = 'relayIcon16';
|
|
x += '<tr onclick=showEventDetails(' + event.h + ',3) onmouseover=eventMouseHover(this,1) onmouseout=eventMouseHover(this,0) style=cursor:pointer><td style=width:18px><div class=' + icon + '></div></td><td class=g1> </td><td class=style10>' + printTime(time) + ' - ' + msg + '</td><td class=g2> </td></tr><tr style=height:2px></tr>';
|
|
}
|
|
}
|
|
if (dateHeader != null) x += '</table>';
|
|
if (x == '') x = '<br><i>' + "Žádné události" + '</i><br><br>';
|
|
QH('p31events', x);
|
|
}
|
|
|
|
function refreshUsersEvents() {
|
|
meshserver.send({ action: 'events', limit: parseInt(p31limitdropdown.value), user: currentUser.name });
|
|
}
|
|
|
|
//
|
|
// FILE SELECTOR, DIALOG 3
|
|
//
|
|
|
|
function d3init() {
|
|
Q('d3localFile').value = '';
|
|
d3modechange();
|
|
}
|
|
|
|
function d3modechange() {
|
|
var mode = Q('d3uploadMode').value;
|
|
QV('d3localmode', mode == 1);
|
|
QV('d3servermode', mode == 2);
|
|
if (mode == 1) { d3setActions(); } else { d3updatefiles(); }
|
|
}
|
|
|
|
var d3filetreelinkpath;
|
|
var d3filetreelocation = [];
|
|
|
|
function d3updatefiles() {
|
|
if (Q('d3uploadMode').value == 1) return;
|
|
var html1 = '', html2 = '', filetreex = filetree, folderdepth = 1;
|
|
|
|
// Navigate to path location, build the paths at the same time
|
|
var d3filetreelocation2 = [], oldlinkpath = d3filetreelinkpath, checkedBoxes = [], checkboxes = document.getElementsByName('fc');
|
|
for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { checkedBoxes.push(checkboxes[i].value) }; } // Save all existing checked boxes
|
|
|
|
d3filetreelinkpath = '';
|
|
for (var i in d3filetreelocation) {
|
|
if ((filetreex.f != null) && (filetreex.f[d3filetreelocation[i]] != null)) {
|
|
d3filetreelocation2.push(d3filetreelocation[i]);
|
|
if ((folderdepth == 1)) {
|
|
var sp = d3filetreelocation[i].split('/');
|
|
publicPath = window.location + sp[0] + 'files/' + sp[2];
|
|
if (d3filetreelocation[i] === userinfo._id) { d3filetreelinkpath += 'self'; } else { d3filetreelinkpath += (sp[0] + '/' + sp[2]); }
|
|
} else {
|
|
if (d3filetreelinkpath != '') { d3filetreelinkpath += '/' + d3filetreelocation[i]; if (folderdepth > 2) { publicPath += '/' + d3filetreelocation[i]; } }
|
|
}
|
|
filetreex = filetreex.f[d3filetreelocation[i]];
|
|
folderdepth++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
d3filetreelocation = d3filetreelocation2; // In case we could not go down the full path, we set the new path location here.
|
|
|
|
// Sort the files
|
|
var filetreexx = p5sort_files(filetreex.f);
|
|
|
|
// Display all files and folders at this location
|
|
for (var i in filetreexx) {
|
|
// Figure out the name and shortname
|
|
var f = filetreexx[i], name = f.n, shortname;
|
|
shortname = name;
|
|
if (name.length > 70) { shortname = '<span title="' + EscapeHtml(name) + '">' + EscapeHtml(name.substring(0, 70)) + ("..." + '</span>'); } else { shortname = EscapeHtml(name); }
|
|
name = EscapeHtml(name);
|
|
|
|
// Figure out the size
|
|
var fsize = '';
|
|
if (f.s != null) { fsize = getFileSizeStr(f.s); }
|
|
|
|
var h = '';
|
|
if (f.t < 3) {
|
|
var title = '';
|
|
h = '<div class=filelist file=999><span style=float:right title=\"' + title + '\"></span><span><div class=fileIcon' + f.t + ' onclick=d3folderset(\"' + encodeURIComponent(f.nx) + '\")></div> <a href=# style=cursor:pointer onclick=\'return d3folderset(\"' + encodeURIComponent(f.nx) + '\")\'>' + shortname + '</a></span></div>';
|
|
} else {
|
|
var link = shortname;
|
|
//if (f.s > 0) { link = "<a rel=\"noreferrer noopener\" target=\"_blank\" href=\"downloadfile.ashx?link=" + encodeURIComponent(filetreelinkpath + '/' + f.nx) + "\">" + shortname + "</a>"; }
|
|
h = '<div class=filelist file=3><input style=float:left name=fcx class=fcb type=checkbox onchange=d3setActions() value="' + f.nx + '"> <span style=float:right>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
|
|
}
|
|
|
|
if (f.t < 3) { html1 += h; } else { html2 += h; }
|
|
}
|
|
|
|
QH('d3serverfiles', html1 + html2);
|
|
QE('p3FolderUp', d3filetreelocation.length > 0);
|
|
d3setActions();
|
|
}
|
|
|
|
function d3folderset(x) { d3filetreelocation.push(decodeURIComponent(x)); d3updatefiles(); return false; }
|
|
function d3folderup(x) { if (x == null) { d3filetreelocation.pop(); } else { while (d3filetreelocation.length > x) { d3filetreelocation.pop(); } } d3updatefiles(); }
|
|
function d3getFileSel() { var cc = []; var checkboxes = document.getElementsByName('fcx'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { cc.push(checkboxes[i].value) } } return cc; }
|
|
function d3setActions() {
|
|
var mode = Q('d3uploadMode').value;
|
|
if (mode == 1) {
|
|
QE('idx_dlgOkButton', Q('d3localFile').value.length > 0);
|
|
} else {
|
|
QE('idx_dlgOkButton', d3getFileSel().length == 1);
|
|
}
|
|
}
|
|
|
|
//
|
|
// NOTIFICATIONS
|
|
//
|
|
|
|
var notifications = [];
|
|
|
|
// Toggle showing notifications
|
|
function clickNotificationIcon(show) {
|
|
//addNotification({ icon:0, text:'test' });
|
|
if (show == true) { QV('notifiyBox', true); } else if (show == false) { QV('notifiyBox', false); } else { QV('notifiyBox', QS('notifiyBox')['display'] == 'none'); }
|
|
drawNotifications();
|
|
}
|
|
|
|
// Set the notification count on the upper right oft he screen
|
|
function setNotificationCount(c) {
|
|
if (parseInt(Q('notificationCount').innerHTML) == c) return; // If the count did not change, exit now.
|
|
QH('notificationCount', c);
|
|
QS('notificationCount')['background-color'] = (c == 0)?'lightblue':'orange';
|
|
QV('notificationCount', c > 0);
|
|
}
|
|
|
|
// Refresh the notification box
|
|
function drawNotifications() {
|
|
var r = '';
|
|
if (notifications.length == 0) {
|
|
r = '<div style=margin:5px>' + "Žádná notifikace" + '</div>';
|
|
} else {
|
|
for (var i in notifications) {
|
|
var n = notifications[i];
|
|
var t = '';
|
|
if (n.title != null) { t = '<b>' + n.title + '</b>: ' }
|
|
var d = new Date(n.time);
|
|
var icon = 0;
|
|
if (n.nodeid != null) {
|
|
var node = getNodeFromId(n.nodeid);
|
|
if (node != null) { icon = node.icon; t = '<b>' + node.name + '</b>: ' }
|
|
}
|
|
|
|
r += '<div title="' + format("Došlo k {0}", printDateTime(d)) + '" id="notifyx' + n.id + '" class=notification style="cursor:pointer;border-top:1px solid ' + ((r == '') ? 'transparent' : 'orange') + '">';
|
|
if (icon) { r += '<div class=j' + icon + ' onclick="notificationSelected(' + n.id + ')" style=margin:5px;float:left></div>'; }
|
|
r += '<div onclick="notificationDelete(' + n.id + ')" class=unselectable title="Clear this notification" style=margin:5px;float:right;color:orange><b>X</b></div><div onclick="notificationSelected(' + n.id + ')" style=margin:5px>' + t + n.text + '</div></div>';
|
|
}
|
|
}
|
|
var deleteall = '';
|
|
if (notifications.length > 1) { deleteall = '<div id="notifyRemoveAll" onclick="deleteAllNotifications()" style="cursor:pointer;border-top:1px solid orange;margin:5px;color:orange;text-align:right;padding-right:3px">Clear all</div>'; }
|
|
QH('notifiyBox', '<div class=customScroll style="max-height:170px;overflow-y:auto;margin:5px">' + r + '</div>' + deleteall );
|
|
}
|
|
|
|
// A notification was selected
|
|
function notificationSelected(id, del) {
|
|
var j = -1;
|
|
for (var i in notifications) { if (notifications[i].id == id) { j = i; } }
|
|
if (j != -1) {
|
|
notificationSelectedEx(notifications[j], id);
|
|
if (del && notifications[j]) {
|
|
if (notifications[j].notification) { notifications[j].notification.close(); delete notifications[j].notification; }
|
|
notificationDelete(id);
|
|
}
|
|
}
|
|
}
|
|
|
|
function notificationSelectedEx(n, id) {
|
|
if (n.nodeid != null) {
|
|
if (n.tag == 'desktop') gotoDevice(n.nodeid, 12); // Desktop
|
|
else if (n.tag == 'terminal') gotoDevice(n.nodeid, 11); // Terminal
|
|
else if (n.tag == 'files') gotoDevice(n.nodeid, 13); // Files
|
|
else if (n.tag == 'intelamt') gotoDevice(n.nodeid, 14); // Intel AMT
|
|
else if (n.tag == 'console') gotoDevice(n.nodeid, 15); // Files
|
|
else gotoDevice(n.nodeid, 10); // General
|
|
} else {
|
|
if ((n.tag != null) && n.tag.startsWith('meshmessenger/')) {
|
|
window.open('/messenger?id=' + n.tag + '&title=' + encodeURIComponent(n.username), n.tag.split('/')[2]);
|
|
notificationDelete(id);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove one notification
|
|
function notificationDelete(id) {
|
|
var j = -1, e = Q('notifyx' + id);
|
|
if (e != null) {
|
|
for (var i in notifications) { if (notifications[i].id == id) { j = i; } }
|
|
if (j != -1) {
|
|
if (notifications[j].notification) { notifications[j].notification.close(); delete notifications[j].notification; }
|
|
notifications.splice(j, 1);
|
|
e.parentNode.removeChild(e);
|
|
setNotificationCount(notifications.length);
|
|
if (notifications.length == 0) { QV('notifiyBox', false); }
|
|
if (notifications.length == 1) { QV('notifyRemoveAll', false); }
|
|
if ((notifications.length > 0) && (j == 0)) {
|
|
var n = notifications[0];
|
|
QS('notifyx' + n.id)['border-top'] = '1px solid transparent';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add a new notification and play the notification sound
|
|
function addNotification(n) {
|
|
// Show notification within the web page.
|
|
if (n.time == null) { n.time = Date.now(); }
|
|
if (n.id == null) { n.id = Math.random(); }
|
|
notifications.unshift(n);
|
|
setNotificationCount(notifications.length);
|
|
clickNotificationIcon(true);
|
|
var notifySettings = getstore('notifications', 0);
|
|
if (notifySettings & 1) { Q('chimes').play(); }
|
|
|
|
// If web notifications are granted, use it.
|
|
var notification = null;
|
|
if (Notification && (Notification.permission == 'granted')) {
|
|
var text = n.text.split('®').join('').split('<b>').join('').split('</b>').join('').split('<br />').join('\r\n'); // Clean up any HTML codes
|
|
if (n.nodeid) {
|
|
var node = getNodeFromId(n.nodeid);
|
|
if (node) { notification = new Notification('{{{title}}} - ' + node.name, { tag: n.tag, body: text, icon: '/images/notify/icons128-' + node.icon + '.png' }); }
|
|
} else {
|
|
if (n.icon == null) { n.icon = 0; }
|
|
var title = n.title;
|
|
if (title == null) { title = ''; } else { title = ' - ' + n.title; }
|
|
notification = new Notification('{{{title}}}' + title, { tag: n.tag, body: text, icon: '/images/notify/icons128-' + n.icon + '.png' });
|
|
}
|
|
notification.id = n.id;
|
|
notification.xtag = n.tag;
|
|
notification.nodeid = n.nodeid;
|
|
notification.username = n.username;
|
|
notification.onclick = function (e) { notificationSelected(e.target.id, true); }
|
|
n.notification = notification;
|
|
}
|
|
}
|
|
|
|
// Remove all notifications
|
|
function deleteAllNotifications() {
|
|
notifications = [];
|
|
setNotificationCount(0);
|
|
drawNotifications();
|
|
QV('notifiyBox', false);
|
|
}
|
|
|
|
//
|
|
// MyServer General
|
|
//
|
|
|
|
function setupGeneralServerStats() {
|
|
window.serverStatCpu = new Chart(document.getElementById('serverCpuChart').getContext('2d'), {
|
|
type: 'doughnut',
|
|
data: { datasets: [{ data: [0, 0], backgroundColor: ['#AAAAAA', '#00AA00'] }], labels: ["Použito", "Volné"] },
|
|
options: { responsive: true, legend: { position: 'none', }, animation: { animateScale: true, animateRotate: true }, width: '60px' }
|
|
});
|
|
window.serverStatMemory = new Chart(document.getElementById('serverMemoryChart').getContext('2d'), {
|
|
type: 'doughnut',
|
|
data: { datasets: [{ data: [0, 0], backgroundColor: ['#AAAAAA', '#00AA00'] }], labels: ["Použito", "Volné"] },
|
|
options: { responsive: true, legend: { position: 'none', }, animation: { animateScale: true, animateRotate: true }, width: '60px' }
|
|
});
|
|
}
|
|
|
|
var lastServerStats = null;
|
|
function updateGeneralServerStats(message) {
|
|
if (message != null) { lastServerStats = message; } else { message = lastServerStats; }
|
|
if (message == null) return;
|
|
|
|
// Paint the pie graphs
|
|
if (typeof message.cpuavg == 'object') {
|
|
var m = Math.min(message.cpuavg[0], 1);
|
|
window.serverStatCpu.config.data.datasets[0].data = [m, 1 - m];
|
|
QH('serverCpuChartText', '<div style=margin-bottom:5px>CPU Load</div><div><b title=\"' + "CPU zatížení v poslední minutě" + '\">' + (Math.round(message.cpuavg[0] * 100.0) / 100.0) + '</b>, <b title=\"' + "CPU zatížení v posledních 5 minutách" + '\">' + (Math.round(message.cpuavg[1] * 100.0) / 100.0) + '</b>, <b title=\"' + "CPU zatížení v posledních 15 minutách" + '\">' + (Math.round(message.cpuavg[2] * 100.0) / 100.0) + '</b></div>');
|
|
QS('serverCpuChartView')['display'] = 'inline-block';
|
|
window.serverStatCpu.update();
|
|
}
|
|
if ((typeof message.totalmem == 'number') && (typeof message.freemem == 'number')) {
|
|
window.serverStatMemory.config.data.datasets[0].data = [message.totalmem - message.freemem, message.freemem];
|
|
QH('serverMemoryChartText', '<div style=margin-bottom:5px>' + "Paměť" + '</div><div><b>' + getNiceSize2(message.freemem) + '</b> ' + "volné" + ', <b>' + getNiceSize2(message.totalmem) + '</b> ' + "celkově" + '</div>');
|
|
QS('serverMemoryChartView')['display'] = 'inline-block';
|
|
window.serverStatMemory.update();
|
|
}
|
|
|
|
// Display all of the server values
|
|
var x = '<div style=width:100% cellpadding=0 cellspacing=0>';
|
|
if (typeof message.values == 'object') {
|
|
for (var i in message.values) {
|
|
x += '<div class=userTableHeader style=margin-bottom:4px;width:200px>' + i + '</div>';
|
|
for (var j in message.values[i]) {
|
|
x += '<div style=display:inline-block><table class=serverStateTableCell><tr><td class=h1></td><td><span>' + j + '</span><span style=float:right>' + message.values[i][j] + '</span></td><td class=h2></td></tr></table></div>';
|
|
}
|
|
}
|
|
}
|
|
x += '</div>';
|
|
|
|
QH('serverStatsTable', x);
|
|
}
|
|
|
|
//
|
|
// MyServer Stats
|
|
//
|
|
|
|
var serverTimelineStats = null;
|
|
var serverTimelineConfig = {
|
|
type: 'line',
|
|
data: { labels: [], datasets: [{ label: '', backgroundColor: 'rgba(255, 99, 132, .5)', borderColor: 'rgb(255, 99, 132)', data: [], fill: true }] },
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
elements: { line: { cubicInterpolationMode: 'monotone' } },
|
|
scales: {
|
|
xAxes: [{ type: 'time', time: { tooltipFormat: 'll HH:mm' }, display: true, scaleLabel: { display: false, labelString: '' } }],
|
|
yAxes: [{ type: 'linear', display: true, scaleLabel: { display: true, labelString: '' } }]
|
|
}
|
|
}
|
|
};
|
|
|
|
function refreshServerTimelineStats(stats) { meshserver.send({ action: 'servertimelinestats', hours: 24 * 30 }); }
|
|
function pastDate(hours) { var t = new Date(); t.setTime(t.getTime() - (60 * 60 * 1000 * hours)); return t; }
|
|
function setServerTimelineStats(stats) { serverTimelineStats = stats; updateServerTimelineStats(); }
|
|
function addServerTimelineStats(stats) {
|
|
if (serverTimelineStats == null) return;
|
|
serverTimelineStats.push(stats);
|
|
var chartType = Q('p40type').value;
|
|
if (chartType == 0) {
|
|
serverTimelineConfig.data.datasets[0].data.push({ x: stats.time, y: stats.conn.ca });
|
|
serverTimelineConfig.data.datasets[1].data.push({ x: stats.time, y: stats.conn.cu });
|
|
serverTimelineConfig.data.datasets[2].data.push({ x: stats.time, y: stats.conn.us });
|
|
serverTimelineConfig.data.datasets[3].data.push({ x: stats.time, y: stats.conn.rs });
|
|
if (stats.conn.am != null) { serverTimelineConfig.data.datasets[4].data.push({ x: stats.time, y: stats.conn.am }); }
|
|
} else if (chartType == 1) {
|
|
serverTimelineConfig.data.datasets[0].data.push({ x: stats.time, y: stats.mem.external / (1024 * 1024) });
|
|
serverTimelineConfig.data.datasets[1].data.push({ x: stats.time, y: stats.mem.heapUsed / (1024 * 1024) });
|
|
serverTimelineConfig.data.datasets[2].data.push({ x: stats.time, y: stats.mem.heapTotal / (1024 * 1024) });
|
|
serverTimelineConfig.data.datasets[3].data.push({ x: stats.time, y: stats.mem.rss / (1024 * 1024) });
|
|
} /* else if (chartType == 2) {
|
|
serverTimelineConfig.data.datasets[0].data.push({ x: stats.time, y: stats.db.meshes });
|
|
serverTimelineConfig.data.datasets[1].data.push({ x: stats.time, y: stats.db.nodes });
|
|
serverTimelineConfig.data.datasets[2].data.push({ x: stats.time, y: stats.db.users });
|
|
serverTimelineConfig.data.datasets[3].data.push({ x: stats.time, y: stats.db.total });
|
|
} */
|
|
updateServerTimelineHours();
|
|
}
|
|
function updateServerTimelineHours() {
|
|
serverTimelineConfig.options.scales.yAxes[0].type = (Q('p40log').checked ? 'logarithmic' : 'linear');
|
|
serverTimelineConfig.options.scales.xAxes[0].time = { min: pastDate(Q('p40time').value) };
|
|
window.serverMainStats.update();
|
|
}
|
|
function setupServerTimelineStats() { window.serverMainStats = new Chart(document.getElementById('serverMainStats').getContext('2d'), serverTimelineConfig); }
|
|
|
|
function updateServerTimelineStats() {
|
|
var data, chartType = Q('p40type').value, timeAfter = pastDate(Q('p40time').value);
|
|
serverTimelineConfig.options.scales.xAxes[0].time = { min: timeAfter };
|
|
if (chartType == 0) { // Connections
|
|
serverTimelineConfig.options.scales.yAxes[0].scaleLabel.labelString = "Čítač připojení";
|
|
data = {
|
|
labels: [pastDate(0), timeAfter],
|
|
datasets: [
|
|
{ label: "Agenti", data: [], backgroundColor: 'rgba(158, 151, 16, .1)', borderColor: 'rgb(158, 151, 16)', fill: true },
|
|
{ label: "Uživatelé", data: [], backgroundColor: 'rgba(16, 84, 158, .1)', borderColor: 'rgb(16, 84, 158)', fill: true },
|
|
{ label: "Uživatelské spojení", data: [], backgroundColor: 'rgba(255, 99, 132, .1)', borderColor: 'rgb(255, 99, 132)', fill: true },
|
|
{ label: "Přesměrované relace", data: [], backgroundColor: 'rgba(39, 158, 16, .1)', borderColor: 'rgb(39, 158, 16)', fill: true },
|
|
{ label: "Intel AMT", data: [], backgroundColor: 'rgba(134, 16, 158, .1)', borderColor: 'rgb(134, 16, 158)', fill: true }
|
|
]
|
|
};
|
|
for (var i = 0; i < serverTimelineStats.length; i++) {
|
|
var t = new Date(serverTimelineStats[i].time);
|
|
if (serverTimelineStats[i].conn) {
|
|
data.datasets[0].data.push({ x: serverTimelineStats[i].time, y: serverTimelineStats[i].conn.ca });
|
|
data.datasets[1].data.push({ x: serverTimelineStats[i].time, y: serverTimelineStats[i].conn.cu });
|
|
data.datasets[2].data.push({ x: serverTimelineStats[i].time, y: serverTimelineStats[i].conn.us });
|
|
data.datasets[3].data.push({ x: serverTimelineStats[i].time, y: serverTimelineStats[i].conn.rs });
|
|
if (serverTimelineStats[i].conn.am != null) { data.datasets[4].data.push({ x: serverTimelineStats[i].time, y: serverTimelineStats[i].conn.am }); }
|
|
}
|
|
}
|
|
} else if (chartType == 1) { // Memory
|
|
serverTimelineConfig.options.scales.yAxes[0].scaleLabel.labelString = "Megabytů";
|
|
data = {
|
|
labels: [pastDate(0), timeAfter],
|
|
datasets: [
|
|
{ label: 'External', data: [], backgroundColor: 'rgba(158, 151, 16, .1)', borderColor: 'rgb(158, 151, 16)', fill: true },
|
|
{ label: 'Heap Used', data: [], backgroundColor: 'rgba(16, 84, 158, .1)', borderColor: 'rgb(16, 84, 158)', fill: true },
|
|
{ label: 'Heap Total', data: [], backgroundColor: 'rgba(255, 99, 132, .1)', borderColor: 'rgb(255, 99, 132)', fill: true },
|
|
{ label: 'RSS', data: [], backgroundColor: 'rgba(39, 158, 16, .1)', borderColor: 'rgb(39, 158, 16)', fill: true }
|
|
]
|
|
};
|
|
for (var i = 0; i < serverTimelineStats.length; i++) {
|
|
data.datasets[0].data.push({ x: serverTimelineStats[i].time, y: serverTimelineStats[i].mem.external / (1024 * 1024) });
|
|
data.datasets[1].data.push({ x: serverTimelineStats[i].time, y: serverTimelineStats[i].mem.heapUsed / (1024 * 1024) });
|
|
data.datasets[2].data.push({ x: serverTimelineStats[i].time, y: serverTimelineStats[i].mem.heapTotal / (1024 * 1024) });
|
|
data.datasets[3].data.push({ x: serverTimelineStats[i].time, y: serverTimelineStats[i].mem.rss / (1024 * 1024) });
|
|
}
|
|
} /*else if (chartType == 2) { // Database
|
|
serverTimelineConfig.options.scales.yAxes[0].scaleLabel.labelString = 'Records';
|
|
data = {
|
|
labels: [pastDate(0), timeAfter],
|
|
datasets: [
|
|
{ label: 'Groups', data: [], backgroundColor: 'rgba(158, 151, 16, .1)', borderColor: 'rgb(158, 151, 16)', fill: true },
|
|
{ label: 'Devices', data: [], backgroundColor: 'rgba(16, 84, 158, .1)', borderColor: 'rgb(16, 84, 158)', fill: true },
|
|
{ label: 'Users', data: [], backgroundColor: 'rgba(255, 99, 132, .1)', borderColor: 'rgb(255, 99, 132)', fill: true },
|
|
{ label: 'Records', data: [], backgroundColor: 'rgba(39, 158, 16, .1)', borderColor: 'rgb(39, 158, 16)', fill: true }
|
|
]
|
|
};
|
|
for (var i = 0; i < serverTimelineStats.length; i++) {
|
|
data.datasets[0].data.push({ x: serverTimelineStats[i].time, y: serverTimelineStats[i].db.meshes });
|
|
data.datasets[1].data.push({ x: serverTimelineStats[i].time, y: serverTimelineStats[i].db.nodes });
|
|
data.datasets[2].data.push({ x: serverTimelineStats[i].time, y: serverTimelineStats[i].db.users });
|
|
data.datasets[3].data.push({ x: serverTimelineStats[i].time, y: serverTimelineStats[i].db.total });
|
|
}
|
|
}*/
|
|
serverTimelineConfig.data = data;
|
|
window.serverMainStats.update();
|
|
}
|
|
|
|
function p40downloadEvents() {
|
|
var csv = "time, conn.agent, conn.users, conn.usersessions, conn.relaysession, conn.intelamt, mem.external, mem.heapused, mem.heaptotal, mem.rss" + '\r\n';
|
|
for (var i = 0; i < serverTimelineStats.length; i++) {
|
|
if (serverTimelineStats[i].conn && serverTimelineStats[i].mem) {
|
|
csv += new Date(serverTimelineStats[i].time) + ', ' + serverTimelineStats[i].conn.ca + ', ' + serverTimelineStats[i].conn.cu + ', ' + serverTimelineStats[i].conn.us + ', ' + serverTimelineStats[i].conn.rs + ', ' + (serverTimelineStats[i].conn.am ? serverTimelineStats[i].conn.am : '') + ', ' + serverTimelineStats[i].mem.external + ', ' + serverTimelineStats[i].mem.heapUsed + ', ' + serverTimelineStats[i].mem.heapTotal + ', ' + serverTimelineStats[i].mem.rss + '\r\n';
|
|
}
|
|
}
|
|
saveAs(new Blob([csv], { type: 'application/octet-stream' }), "ServerStats.csv");
|
|
}
|
|
|
|
//
|
|
// My Server Tracing
|
|
//
|
|
|
|
var serverTrace = [];
|
|
var serverTraceSources = [];
|
|
|
|
function displayServerTrace() {
|
|
var x = '', max = parseInt(Q('p41limitdropdown').value);
|
|
if (serverTrace.length > max) { serverTrace.splice(max); }
|
|
for (var i in serverTrace) { x += '<div class=traceEvent>' + EscapeHtml(new Date(serverTrace[i].time).toLocaleTimeString()) + ' - <b>' + EscapeHtml(serverTrace[i].source.toUpperCase()) + '</b>: ' + EscapeHtml(serverTrace[i].args.join(', ')) + '</div>' }
|
|
QH('p41events', x);
|
|
}
|
|
|
|
function clearServerTracing() { serverTrace = []; displayServerTrace(); }
|
|
|
|
function setServerTracing() {
|
|
var x = '';
|
|
x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:5px"><b>' + "Hlavní server" + '</b></div>';
|
|
x += '<div><label><input type=checkbox id=p41c1 ' + ((serverTraceSources.indexOf('cookie') >= 0) ? 'checked' : '') + '>' + "Cookie dekodér" + '</label></div>';
|
|
x += '<div><label><input type=checkbox id=p41c2 ' + ((serverTraceSources.indexOf('dispatch') >= 0) ? 'checked' : '') + '>' + "Odesílatel" + '</label></div>';
|
|
x += '<div><label><input type=checkbox id=p41c3 ' + ((serverTraceSources.indexOf('main') >= 0) ? 'checked' : '') + '>' + "Zprávy hlavního serveru" + '</label></div>';
|
|
x += '<div><label><input type=checkbox id=p41c4 ' + ((serverTraceSources.indexOf('peer') >= 0) ? 'checked' : '') + '>' + "MeshCentral Server Peering" + '</label></div>';
|
|
x += '<div><label><input type=checkbox id=p41c15 ' + ((serverTraceSources.indexOf('agent') >= 0) ? 'checked' : '') + '>' + "MeshAgent provoz" + '</label></div>';
|
|
x += '<div><label><input type=checkbox id=p41c14 ' + ((serverTraceSources.indexOf('agentupdate') >= 0) ? 'checked' : '') + '>' + "MeshAgent aktualizace" + '</label></div>';
|
|
x += '<div><label><input type=checkbox id=p41c16 ' + ((serverTraceSources.indexOf('cert') >= 0) ? 'checked' : '') + '>' + "Certifikáty serveru" + '</label></div>';
|
|
x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:5px"><b>' + "Webový server" + '</b></div>';
|
|
x += '<div><label><input type=checkbox id=p41c5 ' + ((serverTraceSources.indexOf('web') >= 0) ? 'checked' : '') + '>' + "Webový server" + '</label></div>';
|
|
x += '<div><label><input type=checkbox id=p41c6 ' + ((serverTraceSources.indexOf('webrequest') >= 0) ? 'checked' : '') + '>' + "Požadavky webového serveru" + '</label></div>';
|
|
x += '<div><label><input type=checkbox id=p41c7 ' + ((serverTraceSources.indexOf('relay') >= 0) ? 'checked' : '') + '>' + "Web Socket Relay" + '</label></div>';
|
|
//x += '<div><label><input type=checkbox id=p41c8 ' + ((serverTraceSources.indexOf('webrelaydata') >= 0) ? 'checked' : '') + '>' + "Traffic Relay 2 Data" + '</label></div>';
|
|
x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:5px"><b>' + "Intel AMT" + '</b></div>';
|
|
x += '<div><label><input type=checkbox id=p41c9 ' + ((serverTraceSources.indexOf('webrelay') >= 0) ? 'checked' : '') + '>' + "Přesměrování spojení" + '</label></div>';
|
|
x += '<div><label><input type=checkbox id=p41c10 ' + ((serverTraceSources.indexOf('mps') >= 0) ? 'checked' : '') + '>' + "CIRA Server" + '</label></div>';
|
|
x += '<div><label><input type=checkbox id=p41c11 ' + ((serverTraceSources.indexOf('mpscmd') >= 0) ? 'checked' : '') + '>' + "CIRA Server příkazy" + '</label></div>';
|
|
//x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:5px"><b>Legacy</b></div>';
|
|
//x += '<div><label><input type=checkbox id=p41c12 ' + ((serverTraceSources.indexOf('swarm') >= 0) ? 'checked' : '') + ">' + "Legacy Swarm Server" + '</label></div>";
|
|
//x += '<div><label><input type=checkbox id=p41c13 ' + ((serverTraceSources.indexOf('swarmcmd') >= 0) ? 'checked' : '') + ">' + "Legacy Swarm Server Commands" + '</label></div>";
|
|
setDialogMode(2, "Trasování serveru", 7, setServerTracingEx, x);
|
|
}
|
|
|
|
function setServerTracingEx(b) {
|
|
var sources = [], allsources = ['cookie', 'dispatch', 'main', 'peer', 'web', 'webrequest', 'relay', 'webrelaydata', 'webrelay', 'mps', 'mpscmd', 'swarm', 'swarmcmd', 'agentupdate', 'agent', 'cert'];
|
|
if (b == 1) { for (var i = 1; i < 17; i++) { try { if (Q('p41c' + i).checked) { sources.push(allsources[i - 1]); } } catch (ex) { } } }
|
|
meshserver.send({ action: 'traceinfo', traceSources: sources });
|
|
}
|
|
|
|
function p41downloadServerTrace() {
|
|
var csv = "time, source, message" + '\r\n';
|
|
for (var i in serverTrace) { csv += '\"' + new Date(serverTrace[i].time).toLocaleTimeString() + '\",\"' + serverTrace[i].source + '\",\"' + serverTrace[i].args.join(', ') + '\"\r\n'; }
|
|
saveAs(new Blob([csv], { type: 'application/octet-stream' }), "servertrace.csv");
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// POPUP DIALOG
|
|
//
|
|
|
|
// null = Hidden, 1 = Generic Message
|
|
var xxdialogMode;
|
|
var xxdialogFunc;
|
|
var xxdialogButtons;
|
|
var xxdialogTag;
|
|
var xxcurrentView = -1;
|
|
|
|
// Display a dialog box
|
|
// Parameters: Dialog Mode (0 = none), Dialog Title, Buttons (1 = OK, 2 = Cancel, 3 = OK & Cancel), Call back function(0 = Cancel, 1 = OK), Dialog Content (Mode 2 only)
|
|
function setDialogMode(x, y, b, f, c, tag) {
|
|
setSessionActivity();
|
|
QV('uiMenu', false);
|
|
xxdialogMode = x;
|
|
xxdialogFunc = f;
|
|
xxdialogButtons = b;
|
|
xxdialogTag = tag;
|
|
QS('dialog').width = null; // Reset dialog size
|
|
QS('dialog').left = null;
|
|
QS('dialog').right = null;
|
|
QE('idx_dlgOkButton', true);
|
|
QV('idx_dlgOkButton', b & 1);
|
|
QV('idx_dlgCancelButton', b & 2);
|
|
QV('id_dialogclose', (b & 2) || (b & 8));
|
|
QV('idx_dlgDeleteButton', b & 4);
|
|
QV('idx_dlgButtonBar', b & 7);
|
|
if (y) QH('id_dialogtitle', y);
|
|
for (var i = 1; i < 24; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
|
|
QV('dialog', x);
|
|
if (c) { if (x == 2) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } }
|
|
}
|
|
|
|
function dialogclose(x) {
|
|
setSessionActivity();
|
|
var f = xxdialogFunc, b = xxdialogButtons, t = xxdialogTag;
|
|
setDialogMode();
|
|
if (((b & 8) || x) && f) f(x, t);
|
|
}
|
|
|
|
function center() {
|
|
setSessionActivity();
|
|
if (xxcurrentView == 11) { deskAdjust(); }
|
|
else if (xxcurrentView == 10) { masterUpdate(256); }
|
|
else if (xxcurrentView == 1) { masterUpdate(4); }
|
|
}
|
|
function messagebox(t, m) { setSessionActivity(); QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
|
|
function statusbox(t, m) { setSessionActivity(); QH('id_dialogMessage', m); setDialogMode(1, t); }
|
|
|
|
function goBack() {
|
|
setSessionActivity();
|
|
if (xxdialogMode) return;
|
|
if (fullscreen) { deskToggleFull(); }
|
|
if ((xxcurrentView >= 10) && (xxcurrentView < 20)) { go(1); } // Return to My Devices
|
|
if ((xxcurrentView >= 20) && (xxcurrentView < 30)) { go(2); } // Return to My Account
|
|
if ((xxcurrentView >= 30) && (xxcurrentView < 40)) { go(4); } // Return to My Users
|
|
}
|
|
|
|
function go(x, event) {
|
|
setSessionActivity();
|
|
if (xxdialogMode) return;
|
|
QV('uiMenu', false);
|
|
|
|
// If "shift" is pressed, open a new tab.
|
|
if (event && (event.shiftKey == true) && (x != 15) && ('{{currentNode}}' == '')) {
|
|
// Open the device in a different tab
|
|
if ((x >= 10) && (x <= 19)) {
|
|
if (currentNode) { window.open(window.location.origin + '?node=' + currentNode._id.split('/')[2] + '&viewmode=' + x + '&hide=16', 'meshcentral:' + currentNode._id); }
|
|
} else if (x < 10) {
|
|
window.open(window.location.origin + '?viewmode=' + x + '&hide=0', 'meshcentral:' + x);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (xxcurrentView == x) return;
|
|
|
|
// Edit this line when adding a new screen
|
|
for (var i = 0; i < 44; i++) { QV('p' + i, i == x); }
|
|
xxcurrentView = x;
|
|
|
|
// Remove top bar selection
|
|
var mainBarItems = ['MainMenuMyDevices', 'MainMenuMyAccount', 'MainMenuMyEvents', 'MainMenuMyFiles', 'MainMenuMyUsers', 'MainMenuMyServer'];
|
|
for (var i in mainBarItems) {
|
|
QC(mainBarItems[i]).remove('fullselect');
|
|
QC(mainBarItems[i]).remove('semiselect');
|
|
}
|
|
|
|
// Remove left bar selection
|
|
var leftBarItems = ['LeftMenuMyDevices', 'LeftMenuMyAccount', 'LeftMenuMyEvents', 'LeftMenuMyFiles', 'LeftMenuMyUsers', 'LeftMenuMyServer'];
|
|
for (var i in leftBarItems) {
|
|
QC(leftBarItems[i]).remove('lbbuttonsel');
|
|
QC(leftBarItems[i]).remove('lbbuttonsel2');
|
|
}
|
|
|
|
// Define class for Menu(s) as fully or semi active.
|
|
var mainMenuActiveClass = (x < 9 ? 'fullselect' : 'semiselect');
|
|
var leftMenuActiveClass = (((x < 9) || (x == 115) || (x == 40) || (x == 41) || (x == 42)) ? 'lbbuttonsel2' : 'lbbuttonsel');
|
|
|
|
// My Devices
|
|
if (x == 1 || (x >= 10 && x < 20)) QC('MainMenuMyDevices').add(mainMenuActiveClass);
|
|
if (x == 1 || (x >= 10 && x < 20)) QC('LeftMenuMyDevices').add(leftMenuActiveClass);
|
|
|
|
// My Account
|
|
if (x == 2 || (x >= 20 && x < 30)) QC('MainMenuMyAccount').add(mainMenuActiveClass);
|
|
if (x == 2 || (x >= 20 && x < 30)) QC('LeftMenuMyAccount').add(leftMenuActiveClass);
|
|
|
|
// My Events
|
|
if (x == 3) QC('MainMenuMyEvents').add(mainMenuActiveClass);
|
|
if (x == 3) QC('LeftMenuMyEvents').add(leftMenuActiveClass);
|
|
|
|
// My Users
|
|
if (x == 4 || (x >= 30 && x < 40)) QC('MainMenuMyUsers').add(mainMenuActiveClass);
|
|
if (x == 4 || (x >= 30 && x < 40)) QC('LeftMenuMyUsers').add(leftMenuActiveClass);
|
|
|
|
// My Files
|
|
if (x == 5) QC('MainMenuMyFiles').add(mainMenuActiveClass);
|
|
if (x == 5) QC('LeftMenuMyFiles').add(leftMenuActiveClass);
|
|
|
|
// My Server
|
|
if ((x == 6) || (x == 115)) QC('MainMenuMyServer').add(mainMenuActiveClass);
|
|
if ((x == 6) || (x == 115) || (x == 40) || (x == 41) || (x == 42) || (x == 43)) QC('LeftMenuMyServer').add(leftMenuActiveClass);
|
|
QV('ServerPlugins', pluginHandler != null);
|
|
|
|
// column_l max-height
|
|
if (webPageStackMenu && (x >= 10)) { QC('column_l').add('room4submenu'); } else { QC('column_l').remove('room4submenu'); }
|
|
|
|
// If we are going to panel 0 in "full screen mode", hide the left bar.
|
|
QV('topbar', x != 0);
|
|
if ((x == 0) && (webPageFullScreen)) { QC('body').add('arg_hide'); }
|
|
|
|
QV('MainSubMenuSpan', x >= 10 && x < 20);
|
|
QV('UserDummyMenuSpan', (x < 10) && (x != 6) && webPageFullScreen);
|
|
QV('MeshSubMenuSpan', x >= 20 && x < 30);
|
|
QV('UserSubMenuSpan', x >= 30 && x < 40);
|
|
QV('ServerSubMenuSpan', x == 6 || x == 115 || x == 40 || x == 41 || x == 42 || x == 43);
|
|
var panels = { 10: 'MainDev', 11: 'MainDevDesktop', 12: 'MainDevTerminal', 13: 'MainDevFiles', 14: 'MainDevAmt', 15: 'MainDevConsole', 16: 'MainDevEvents', 17: 'MainDevInfo', 19: 'MainDevPlugins', 20: 'MeshGeneral', 30: 'UserGeneral', 31: 'UserEvents', 6: 'ServerGeneral', 40: 'ServerStats', 41: 'ServerTrace', 42: 'ServerPlugins', 115: 'ServerConsole' };
|
|
for (var i in panels) {
|
|
QC(panels[i]).remove('style3x');
|
|
QC(panels[i]).remove('style3sel');
|
|
QC(panels[i]).add((x == i) ? 'style3sel' : 'style3x');
|
|
}
|
|
|
|
// If going to the remote desktop tab, adjust the tab.
|
|
if (x == 11) { deskAdjust(); }
|
|
|
|
// Panel 115 is weird, it's panel 15 for device console but used as a server console.
|
|
if (x == 115) { QV('p15', true); }
|
|
QV('p15uploadCore', x != 115);
|
|
QV('p15BackButton', x != 115);
|
|
if ((x == 15) || (x == 115)) { setupConsole(); }
|
|
|
|
if (x == 1) masterUpdate(4);
|
|
|
|
// Setup web notifications
|
|
if ((x == 2) && Notification) { QV('accountEnableNotificationsSpan', Notification.permission != 'granted'); }
|
|
|
|
// Fetch the server timeline stats if needed
|
|
if ((x == 40) && (serverTimelineStats == null)) { refreshServerTimelineStats(); }
|
|
|
|
// MyServer Plugins
|
|
if (x == 42) { refreshPluginLatest(); }
|
|
|
|
// Update the web page title
|
|
if ((currentNode) && (x >= 10) && (x < 20)) {
|
|
document.title = decodeURIComponent('{{{extitle}}}') + ' - ' + currentNode.name + ' - ' + meshes[currentNode.meshid].name;
|
|
} else {
|
|
document.title = decodeURIComponent('{{{extitle}}}');
|
|
}
|
|
}
|
|
|
|
//
|
|
// Plugin Management
|
|
//
|
|
|
|
function updatePluginList(versInfo) {
|
|
if (pluginHandler == null) return;
|
|
if (Array.isArray(versInfo)) { versInfo.forEach(function(v) { updatePluginList(v); }); }
|
|
QV('pluginNoneNotice', installedPluginList.length == 0);
|
|
if (installedPluginList.length) {
|
|
if (versInfo != null) {
|
|
if (installedPluginList['version_info'] == null) installedPluginList['version_info'] = [];
|
|
installedPluginList['version_info'][versInfo.id] = versInfo;
|
|
}
|
|
var tr = Q('p42tbl').querySelectorAll('.p42tblRow');
|
|
if (tr.length) {
|
|
for (var i in Object.values(tr)) {
|
|
tr[i].parentNode.removeChild(tr[i]);
|
|
}
|
|
}
|
|
var statusMap = {
|
|
0: {
|
|
'text': 'Disabled',
|
|
'color': '858483'
|
|
},
|
|
1: {
|
|
'text': 'Installed',
|
|
'color': '00aa00'
|
|
}
|
|
};
|
|
var statusAvailability = {
|
|
0: {
|
|
'install': 'Install',
|
|
'delete': 'Delete'
|
|
},
|
|
1: {
|
|
'disable': 'Disable',
|
|
'upgrade': 'Upgrade',
|
|
// 'downgrade': 'Downgrade' // disabling until plugins have prior versions available for better testing
|
|
}
|
|
};
|
|
var vers_not_compat = ' [ <span onclick="return setDialogMode(2, \'Compatibility Issue\', 1, null, \'This plugin version is not compatible with your MeshCentral installation, please upgrade MeshCentral first.\');" title="Version incompatible, please upgrade your MeshCentral installation first" style="cursor: pointer; color:red;"> ! </span> ]';
|
|
|
|
var tbl = Q('p42tbl');
|
|
installedPluginList.forEach(function(p){
|
|
var cant_action = [];
|
|
if (p.hasAdminPanel == true && p.status) {
|
|
p.nameHtml = '<a onclick="return goPlugin(\'' + p.shortName + '\', \'' + p.name.replace(/'/g, "\\'") + '\');">' + p.name + '</a>';
|
|
} else {
|
|
p.nameHtml = p.name;
|
|
}
|
|
p.statusText = statusMap[p.status].text;
|
|
p.statusColor = statusMap[p.status].color;
|
|
|
|
if (p.versionHistoryUrl == null) { cant_action.push('downgrade'); }
|
|
if (!p.status) { p.version = ' - '; } // It isn't technically installed, so no version number
|
|
p.upgradeAvail = "Kontrola...";
|
|
if (installedPluginList['version_info'] != null && installedPluginList['version_info'][p._id] != null) {
|
|
var vin = installedPluginList['version_info'][p._id];
|
|
if (vin.hasUpdate) {
|
|
p.upgradeAvail = '<a title="View Changelog" target="_blank" href="' + vin.changelogUrl + '">' + vin.version + '</a>';
|
|
} else {
|
|
cant_action.push('upgrade');
|
|
if (p.status) p.upgradeAvail = "Zastaralý";
|
|
else p.upgradeAvail = '<a title="View Changelog" target="_blank" href="' + vin.changelogUrl + '">' + vin.version + '</a>';
|
|
}
|
|
if (!vin.meshCentralCompat) {
|
|
p.upgradeAvail += vers_not_compat;
|
|
cant_action.push('install');
|
|
cant_action.push('upgrade');
|
|
}
|
|
}
|
|
|
|
p.actions = '<select onchange="return pluginAction(this,\'' + p._id + '\');"><option value=""> --</option>';
|
|
var entries = Object.entries(statusAvailability[p.status]);
|
|
for (var k in entries) {
|
|
if (cant_action.indexOf(entries[k][0]) === -1) {
|
|
p.actions += '<option value="' + entries[k][0] + '">' + entries[k][1] + '</option>';
|
|
}
|
|
}
|
|
p.actions += '</select>';
|
|
|
|
let tpl = '<td><img style=margin-top:3px src=images/plugin24.png></td><td class=gradTable1> </td><td class=gradTable2>' + p.nameHtml + '</td><td class=gradTable2>' + p.description + '</td><td class=gradTable2 style=text-align:center><a href="' + p.homepage + '" target="_blank">Home</a></td><td class=gradTable2 style=text-align:center>' + p.version + '</td><td style=text-align:center class="pluginUpgradeAvailable gradTable2">' + p.upgradeAvail + '</td><td class=gradTable2 style="text-align:center;color:#' + p.statusColor + '">' + p.statusText + '</td><td class="pluginAction gradTable2" style=text-align:center>' + p.actions + '</td><td class=gradTable3> </td>';
|
|
let tr = tbl.insertRow(-1);
|
|
tr.innerHTML = tpl;
|
|
tr.classList.add('p42tblRow');
|
|
tr.setAttribute('data-id', p._id);
|
|
tr.setAttribute('id', 'pluginRow-' + p._id);
|
|
});
|
|
} else {
|
|
var tr = Q('p42tbl').querySelectorAll('.p42tblRow');
|
|
for (var i in Object.values(tr)) { tr[i].parentNode.removeChild(tr[i]); }
|
|
}
|
|
if (versInfo == null) refreshPluginLatest();
|
|
}
|
|
|
|
function refreshPluginLatest() {
|
|
if (pluginHandler == null) return;
|
|
meshserver.send({ action: 'pluginLatestCheck' });
|
|
}
|
|
|
|
function distributeCore() {
|
|
if (pluginHandler == null) return;
|
|
meshserver.send({ action: 'distributeCore', nodes: nodes }); // All nodes the user has access to
|
|
QV('pluginRestartNotice', false);
|
|
}
|
|
|
|
function pluginActionEx() {
|
|
if (pluginHandler == null) return;
|
|
var act = Q('lastPluginAct').value, id = Q('lastPluginId').value, pVersUrl = Q('lastPluginVersion').value;
|
|
|
|
switch(act) {
|
|
case 'upgrade':
|
|
case 'install':
|
|
meshserver.send({ 'action': 'installplugin', 'id': id, 'version_only': false });
|
|
break;
|
|
case 'downgrade':
|
|
Q('lastPluginVersion').querySelectorAll('option').forEach(function(opt) {
|
|
if (opt.value == pVersUrl) pVers = opt.text;
|
|
});
|
|
meshserver.send({ 'action': 'installplugin', 'id': id, 'version_only': { 'name': pVers, 'url': pVersUrl }});
|
|
break;
|
|
case 'delete':
|
|
meshserver.send({ 'action': 'removeplugin', 'id': id });
|
|
break;
|
|
case 'disable':
|
|
meshserver.send({ 'action': 'disableplugin', 'id': id });
|
|
break;
|
|
}
|
|
QV('pluginRestartNotice', true);
|
|
}
|
|
|
|
function pluginAction(elem, id) {
|
|
if (pluginHandler == null) return;
|
|
if (elem.value == 'downgrade') {
|
|
meshserver.send({ 'action': 'getpluginversions', 'id': id });
|
|
} else {
|
|
var plugin = null;
|
|
for (var i in installedPluginList) { if (installedPluginList[i]._id == id) { plugin = installedPluginList[i]; } }
|
|
setDialogMode(2, "Akce pluginu", 3, pluginActionEx, format("Opravdu {0} plugin: {1}", elem.value, plugin.name) + '<input id="lastPluginAct" type="hidden" value="' + elem.value + '" /><input id="lastPluginId" type="hidden" value="' + id + '" /><input id="lastPluginVersion" type="hidden" value="" />');
|
|
}
|
|
elem.value = '';
|
|
}
|
|
|
|
function goPlugin(pname, title) {
|
|
if (pluginHandler == null) return;
|
|
if (pname == null) { Q('p43iframe').src = ''; } else { QH('p43title', title); Q('p43iframe').src = '/pluginadmin.ashx?pin=' + pname; go(43); }
|
|
}
|
|
|
|
// Generic methods
|
|
function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }
|
|
function putstore(name, val) {
|
|
try {
|
|
if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return;
|
|
if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { }
|
|
if (name[0] != '_') {
|
|
var s = {};
|
|
for (var i = 0, len = localStorage.length; i < len; ++i) {
|
|
var k = localStorage.key(i);
|
|
if (k[0] != '_') {
|
|
s[k] = localStorage.getItem(k);
|
|
if ((k != 'desktopsettings') && (typeof s[k] == 'string') && (s[k].length > 64)) { delete s[k]; }
|
|
}
|
|
}
|
|
meshserver.send({ action: 'userWebState', state: JSON.stringify(s) });
|
|
}
|
|
}
|
|
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; } }
|
|
function addLink(x, f) { return '<span tabindex=0 style=cursor:pointer;text-decoration:none onclick=\'' + f + '\' onkeypress=\"if (event.key==\'Enter\') {' + f + '} \">' + x + ' <img class=hoverButton src=images/link5.png></span>'; }
|
|
function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
|
|
function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
|
|
function addOption(q, t, i) { var option = document.createElement('option'); option.text = t; option.value = i; Q(q).add(option); }
|
|
function passwordcheck(p) { return (p.length > 7) && (/\d/.test(p)) && (/[a-z]/.test(p)) && (/[A-Z]/.test(p)) && (/\W/.test(p)); }
|
|
function methodcheck(r) { if (r && r != null && r.Body && r.Body.ReturnValueStr != 'SUCCESS') { messagebox("Chybová volání", r.Header.Method + ': ' + r.Body.ReturnValueStr.replace('_', ' ')); return true; } return false; }
|
|
function TableStart() { return '<table cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td width=200px><p><td>'; }
|
|
function TableStart2() { return '<table cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td><p><td>'; }
|
|
function TableEntry(n, v) { return '<tr><td><p>' + n + '<td>' + v; }
|
|
function FullTable(x, e) { var r = TableStart(); for (i in x) { if (i && x[i]) r += TableEntry(i, x[i]); } return r + TableEnd(e); }
|
|
function TableEnd(n) { return '<tr><td colspan=2><p>' + (n?n:'') + '</table>'; }
|
|
function AddButton(v, f) { return '<input type=button value="' + v + '" onclick="' + f + '" style=margin:4px>'; }
|
|
function AddButton2(v, f) { return '<input type=button value="' + v + '" onclick="' + f + '">'; }
|
|
function AddRefreshButton(f) { return '<input type=button name=refreshbtn value=Refresh onclick="refreshButtons(false);' + f + '" style=margin:4px ' + (refreshButtonsState==false?'disabled':'') + '>'; }
|
|
function MoreStart() { return '<a href=# style=cursor:pointer;color:blue id=morexxx1 onclick=QV(\"morexxx1\",false);QV(\"morexxx2\",true)>▼ ' + "Více" + '</a><div id=morexxx2 style=display:none><br><hr>'; };
|
|
function MoreEnd() { return '<a href=# style=cursor:pointer;color:blue onclick=QV(\"morexxx2\",false);QV(\"morexxx1\",true)>▲ ' + "Méně" + '</a></div>'; };
|
|
function getSelectedOptions(sel) { var opts = [], opt; for (var i = 0, len = sel.options.length; i < len; i++) { opt = sel.options[i]; if (opt.selected) { opts.push(opt.value); } } return opts; }
|
|
function getInstance(x, y) { for (var i in x) { if (x[i]['InstanceID'] == y) return x[i]; } return null; }
|
|
function getItem(x, y, z) { for (var i in x) { if (x[i][y] == z) return x[i]; } return null; }
|
|
function guidToStr(g) { return g.substring(6, 8) + g.substring(4, 6) + g.substring(2, 4) + g.substring(0, 2) + '-' + g.substring(10, 12) + g.substring(8, 10) + '-' + g.substring(14, 16) + g.substring(12, 14) + '-' + g.substring(16, 20) + '-' + g.substring(20); }
|
|
function getUrlVars() { var j, hash, vars = [], hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); for (var i = 0; i < hashes.length; i++) { j = hashes[i].indexOf('='); if (j > 0) { vars[hashes[i].substring(0, j)] = hashes[i].substring(j + 1, hashes[i].length); } } return vars; }
|
|
//function getDocWidth() { if (window.innerWidth) return window.innerWidth; if (document.documentElement && document.documentElement.clientWidth && document.documentElement.clientWidth != 0) return document.documentElement.clientWidth; return document.getElementsByTagName('body')[0].clientWidth; }
|
|
//function addHtmlValue(t, v) { return '<div style=height:20px><div style=float:right;width:220px><b>' + v + '</b></div><div>' + t + '</div></div>'; }
|
|
function addHtmlValue(t, v) { return '<table><td style=width:120px>' + t + '<td><b>' + v + '</b></table>'; }
|
|
function addHtmlValue2(t, v) { return '<div><div style=display:inline-block;float:right>' + v + '</div><div style=display:inline-block>' + t + '</div></div>'; }
|
|
function addHtmlValue3(t, v) { return '<div><b>' + t + '</b></div><div style=margin-left:16px>' + v + '</div>'; }
|
|
function parseUriArgs() { var name, r = {}, parsedUri = window.document.location.href.split(/[\?&|\=]/); parsedUri.splice(0, 1); for (x in parsedUri) { switch (x % 2) { case 0: { name = decodeURIComponent(parsedUri[x]); break; } case 1: { r[name] = decodeURIComponent(parsedUri[x]); var x = parseInt(r[name]); if (x == r[name]) { r[name] = x; } break; } default: { break; } } } return r; }
|
|
function focusTextBox(x) { setTimeout(function(){ Q(x).selectionStart = Q(x).selectionEnd = 65535; Q(x).focus(); }, 0); }
|
|
function validateEmail(v) { var emailReg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return emailReg.test(v); } // New version
|
|
function isPrivateIP(a) { return (a.startsWith('10.') || a.startsWith('172.16.') || a.startsWith('192.168.')); }
|
|
function u2fSupported() { return (window.u2f && ((navigator.userAgent.indexOf('Chrome/') > 0) || (navigator.userAgent.indexOf('Firefox/') > 0) || (navigator.userAgent.indexOf('Opera/') > 0) || (navigator.userAgent.indexOf('Safari/') > 0))); }
|
|
function findOne(arr1, arr2) { if ((arr1 == null) || (arr2 == null)) return false; return arr2.some(function (v) { return arr1.indexOf(v) >= 0; }); };
|
|
function copyTextToClip(txt) { function selectElementText(e) { if (document.selection) { var range = document.body.createTextRange(); range.moveToElementText(e); range.select(); } else if (window.getSelection) { var range = document.createRange(); range.selectNode(e); window.getSelection().removeAllRanges(); window.getSelection().addRange(range); } } var e = document.createElement('DIV'); e.textContent = txt; document.body.appendChild(e); selectElementText(e); document.execCommand('copy'); e.remove(); }
|
|
function copyTextToClip2(txt) { function selectElementText(e) { if (document.selection) { var range = document.body.createTextRange(); range.moveToElementText(e); range.select(); } else if (window.getSelection) { var range = document.createRange(); range.selectNode(e); window.getSelection().removeAllRanges(); window.getSelection().addRange(range); } } var e = document.createElement('DIV'); e.textContent = decodeURIComponent(txt); document.body.appendChild(e); selectElementText(e); document.execCommand('copy'); e.remove(); }
|
|
function capitalizeFirstLetter(x) { return x.charAt(0).toUpperCase() + x.slice(1); }
|
|
function printDate(d) { return d.toLocaleDateString(args.locale); }
|
|
function printTime(d) { return d.toLocaleTimeString(args.locale); }
|
|
function printDateTime(d) { return d.toLocaleString(args.locale); }
|
|
function addDetailItem(title, value, state) { return '<div><span style=float:right>' + value + '</span><span>' + title + '</span></div>'; }
|
|
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; }); };
|
|
function addTextLink(subtext, text, link) { var i = text.toLowerCase().indexOf(subtext.toLowerCase()); if (i == -1) { return text; } return text.substring(0, i) + '<a href=\"' + link + '\">' + subtext + '</a>' + text.substring(i + subtext.length); }
|
|
function nobreak(x) { return x.split(' ').join(' '); }
|
|
|
|
</script>
|
|
|
|
|
|
</body></html> |