mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-26 23:25:53 -05:00
3391 lines
219 KiB
Handlebars
3391 lines
219 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">
|
||
<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/agent-redir-ws-0.1.1.js"></script>
|
||
<script type="text/javascript" src="scripts/agent-desktop-0.0.2.js"></script>
|
||
<script type="text/javascript" src="scripts/amt-0.2.0.js"></script>
|
||
<script type="text/javascript" src="scripts/amt-redir-ws-0.1.0.js"></script>
|
||
<script type="text/javascript" src="scripts/amt-desktop-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 keeplink="1" type="text/javascript" src="scripts/filesaver.js"></script>
|
||
<title>{{{title}}}</title>
|
||
<style>
|
||
a {
|
||
color: #036;
|
||
text-decoration: underline;
|
||
}
|
||
|
||
#footer a {
|
||
color: #fff;
|
||
text-decoration: underline;
|
||
}
|
||
|
||
#footer a:hover {
|
||
color: #fff;
|
||
text-decoration: none;
|
||
}
|
||
|
||
.i1 {
|
||
background: url(../images/icons50.png) 0px 0px;
|
||
height: 50px;
|
||
width: 50px;
|
||
border: none;
|
||
}
|
||
|
||
.i2 {
|
||
background: url(../images/icons50.png) -50px 0px;
|
||
height: 50px;
|
||
width: 50px;
|
||
border: none;
|
||
}
|
||
|
||
.i3 {
|
||
background: url(../images/icons50.png) -100px 0px;
|
||
height: 50px;
|
||
width: 50px;
|
||
border: none;
|
||
}
|
||
|
||
.i4 {
|
||
background: url(../images/icons50.png) -150px 0px;
|
||
height: 50px;
|
||
width: 50px;
|
||
border: none;
|
||
}
|
||
|
||
.i5 {
|
||
background: url(../images/icons50.png) -200px 0px;
|
||
height: 50px;
|
||
width: 50px;
|
||
border: none;
|
||
}
|
||
|
||
.i6 {
|
||
background: url(../images/icons50.png) -250px 0px;
|
||
height: 50px;
|
||
width: 50px;
|
||
border: none;
|
||
}
|
||
|
||
.m0 {
|
||
background: url(../images/images16.png) -32px 0px;
|
||
height: 16px;
|
||
width: 16px;
|
||
border: none;
|
||
float: left;
|
||
}
|
||
|
||
.m1 {
|
||
background: url(../images/images16.png) -16px 0px;
|
||
height: 16px;
|
||
width: 16px;
|
||
border: none;
|
||
float: left;
|
||
}
|
||
|
||
.m2 {
|
||
background: url(../images/images16.png) -96px 0px;
|
||
height: 16px;
|
||
width: 16px;
|
||
border: none;
|
||
float: left;
|
||
}
|
||
|
||
.m3 {
|
||
background: url(../images/images16.png) -112px 0px;
|
||
height: 16px;
|
||
width: 16px;
|
||
border: none;
|
||
float: left;
|
||
}
|
||
|
||
.gray {
|
||
/*filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale");*/ /* Firefox 10+, Firefox on Android */
|
||
filter: gray; /* IE6-9 */
|
||
-webkit-filter: grayscale(100%) opacity(60%); /* Chrome 19+, Safari 6+, Safari 6+ iOS */
|
||
}
|
||
|
||
.DevSt {
|
||
padding-left: 5px;
|
||
border-bottom-style: solid;
|
||
border-bottom-width: 1px;
|
||
border-bottom-color: #DDDDDD;
|
||
}
|
||
|
||
.noselect {
|
||
-webkit-touch-callout: none;
|
||
-webkit-user-select: none;
|
||
-khtml-user-select: none;
|
||
-moz-user-select: none;
|
||
-ms-user-select: none;
|
||
user-select: none;
|
||
}
|
||
|
||
.fileIcon1 {
|
||
background: url(data:image/gif;base64,R0lGODlhEAAQAJEDAPb49Y2Sj9LT2f///yH5BAEAAAMALAAAAAAQABAAAAImnI+py+1vhJwyUYAzHTL4D3qdlJWaIFJqmKod607sDKIiDUP63hQAOw==);
|
||
height: 16px;
|
||
width: 16px;
|
||
cursor: pointer;
|
||
border: none;
|
||
float: left;
|
||
margin-top: 1px;
|
||
}
|
||
|
||
.fileIcon2 {
|
||
background: url(data:image/gif;base64,R0lGODlhEAAQAJEDAM2xV/Xur+XPgP///yH5BAEAAAMALAAAAAAQABAAAAJD3ISZIGHWUGihznesYDYATFVM+D2hJ4lgN1olxALAtAlmPCJvuMmJd6PJckDYwicrHhTD5o7plJmg0Uc0asNMkphHAQA7);
|
||
height: 16px;
|
||
width: 16px;
|
||
cursor: pointer;
|
||
border: none;
|
||
float: left;
|
||
margin-top: 1px;
|
||
}
|
||
|
||
.fileIcon3 {
|
||
background: url(data:image/gif;base64,R0lGODlhEAAQAJEDAPb19IGBgbq6uv///yH5BAEAAAMALAAAAAAQABAAAAIy3ISpxgcPH2ouQgFEw1YmxnUXKEaaEZZnVWZk66JwzKpvuwZzwOgwb/C1gIOA8Yg8DgoAOw==);
|
||
height: 16px;
|
||
width: 16px;
|
||
cursor: pointer;
|
||
border: none;
|
||
float: left;
|
||
margin-top: 1px;
|
||
}
|
||
|
||
.fileIcon4 {
|
||
background: url(../images/meshicon16.png);
|
||
height: 16px;
|
||
width: 16px;
|
||
cursor: pointer;
|
||
border: none;
|
||
float: left;
|
||
margin-top: 1px;
|
||
}
|
||
|
||
.filelist {
|
||
-moz-user-select: none;
|
||
-khtml-user-select: none;
|
||
-webkit-user-select: none;
|
||
-o-user-select: none;
|
||
cursor: default;
|
||
-khtml-user-drag: element;
|
||
background-color: white;
|
||
clear: both;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body onload="if (typeof(startup) !== 'undefined') startup();" style="overflow-y:hidden;margin:0;padding:0;border:0;color:black;font-size:13px;font-family:\'Trebuchet MS\', Arial, Helvetica, sans-serif">
|
||
<div id="container">
|
||
<div id="mastheadx"></div>
|
||
<div id="masthead" style="background:url(logo.png) 0px 0px;background-size:341px 50px;background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden">
|
||
<div style="width:calc(100% - 50px);overflow:hidden">
|
||
<div style="float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:6px">
|
||
<strong><font style="font-size:36px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
|
||
</div>
|
||
<div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:10px">
|
||
<strong><font style="font-size:12px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
|
||
</div>
|
||
</div>
|
||
<img id="topMenuIcon" class="noselect" style="position:absolute;right:0;top:10px;bottom:50px;color:#c8c8c8;font-size:44px;margin-right:8px;cursor:pointer;display:none" onclick="topMenu()" src="/images/3bars-30.png" width="30" height="30">
|
||
</div>
|
||
<div id="page_content" style="overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%">
|
||
<div id="column_l" style="width:100%;padding:0;position:absolute;bottom:0px;top:0px">
|
||
<div id="p0" style="display:none;width:100%;height:100%">
|
||
<div style="display:flex;align-items:center;width:100%;height:100%">
|
||
<div id="p0message" style="text-align:center;width:100%"><span id="p0span">サーバーが切断されました</span>、 <href onclick="reload()" style="cursor:pointer"><u>クリックして再接続</u></href>。</div>
|
||
</div>
|
||
</div>
|
||
<div id="p1" style="display:none;width:100%;height:100%">
|
||
<div style="display:flex;align-items:center;width:100%;height:100%">
|
||
<div id="p1message" style="text-align:center;width:100%"></div>
|
||
</div>
|
||
</div>
|
||
<div id="p2" style="display:none">
|
||
<div id="xdevices"></div>
|
||
</div>
|
||
<div id="p3" style="display:none;position:absolute;bottom:0;top:0;width:100%">
|
||
<table cellspacing="0" style="margin:0;padding:0;border-spacing:0;border:0;">
|
||
<tbody><tr style="padding:0">
|
||
<td style="padding:0;color:#c8c8c8;text-align:center;cursor:pointer" width="60px" valign="top" onclick="goBack()">
|
||
<div style="padding:0;background-color:#036;width:10px;height:10px;float:right;border:0">
|
||
<div style="background-color:white;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid white;border-bottom:1px solid white"></div>
|
||
</div>
|
||
<div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">◀</div>
|
||
</td>
|
||
<td>
|
||
<img src="/images/user-50.png" width="50" height="50">
|
||
</td>
|
||
<td>
|
||
<div style="margin-left:5px">
|
||
<strong style="font-size:large"><span id="p3userName"></span></strong><br>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<div id="p3info" style="overflow-y:scroll;position:absolute;top:55px;bottom:0px;width:100%">
|
||
<div style="margin-left:8px">
|
||
<div id="p3AccountActions">
|
||
<p><strong>アカウントのセキュリティ</strong></p>
|
||
<div style="margin-left:9px;margin-bottom:8px">
|
||
<div id="manageAuthApp" style="margin-top:5px;display:none"><a onclick="account_manageAuthApp()" style="cursor:pointer">認証アプリを管理する</a></div>
|
||
<div id="manageOtp" style="margin-top:5px;display:none"><a onclick="account_manageOtp(0)" style="cursor:pointer">バックアップコードを管理する</a></div>
|
||
</div>
|
||
<p><strong>アカウントアクション</strong></p>
|
||
<div style="margin-left:9px;margin-bottom:8px">
|
||
<div style="margin-top:5px"><span id="verifyEmailId" style="display:none"><a onclick="account_showVerifyEmail()" style="cursor:pointer">Eメールを確認します</a></span></div>
|
||
<div style="margin-top:5px"><span id="changeEmailId" style="display:none"><a onclick="account_showChangeEmail()" style="cursor:pointer">メールアドレスを変更する</a></span></div>
|
||
<div style="margin-top:5px"><a onclick="account_showChangePassword()" style="cursor:pointer">パスワードを変更する</a><span id="p2nextPasswordUpdateTime"></span></div>
|
||
<div style="margin-top:5px"><a onclick="account_showDeleteAccount()" style="cursor:pointer">アカウントを削除する</a></div>
|
||
</div>
|
||
<br style="clear:both">
|
||
</div>
|
||
<strong>デバイスグループ</strong>
|
||
<span id="p3createMeshLink1">( <a onclick="account_createMesh()" style="cursor:pointer"><img src="images/icon-addnew.png" width="12" height="12" border="0"> 新しい</a> )</span>
|
||
<br><br>
|
||
<div id="p3meshes"></div>
|
||
<div id="p3noMeshFound" style="margin-left:9px;display:none">デバイスグループはありません。<span id="p3createMeshLink2"> <a onclick="account_createMesh()" style="cursor:pointer"><strong>ここから始めましょう!</strong></a></span></div>
|
||
<br style="clear:both">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="p5" style="display:none">
|
||
<table cellspacing="0" style="margin:0;padding:0;border-spacing:0;border:0;">
|
||
<tbody><tr style="padding:0">
|
||
<td style="padding:0;color:#c8c8c8;text-align:center;cursor:pointer" width="60px" valign="top" onclick="goBack()">
|
||
<div style="padding:0;background-color:#036;width:10px;height:10px;float:right;border:0">
|
||
<div style="background-color:white;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid white;border-bottom:1px solid white"></div>
|
||
</div>
|
||
<div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">◀</div>
|
||
</td>
|
||
<td>
|
||
<img src="/images/user-50.png" width="50" height="50">
|
||
</td>
|
||
<td>
|
||
<div style="margin-left:5px">
|
||
<strong style="font-size:large">私のファイル</strong><br>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<div id="p5myfiles" style="overflow-y:scroll;position:absolute;top:55px;bottom:0px;width:100%">
|
||
<table id="p5toolbar" style="width:100%;height:78px" cellpadding="0" cellspacing="0">
|
||
<tbody><tr>
|
||
<td style="width:100%;background-color:#d3d9d6;text-align:left;padding:4px" valign="bottom">
|
||
<div style="width:100%;text-align:center">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p5FolderUp" disabled="disabled" onclick="p5folderup()" value="アップ">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p5SelectAllButton" disabled="disabled" onclick="p5selectallfile()" value="すべて選択" onkeypress="return false" onkeydown="return false">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p5RenameFileButton" disabled="disabled" value="リネーム" onclick="p5renamefile()" onkeypress="return false" onkeydown="return false">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p5DeleteFileButton" disabled="disabled" value="削除する" onclick="p5deletefile()" onkeypress="return false" onkeydown="return false">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p5NewFolderButton" disabled="disabled" value="フォルダ" onclick="p5createfolder()" onkeypress="return false" onkeydown="return false">
|
||
</div>
|
||
<div style="width:100%;text-align:center">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p5UploadButton" disabled="disabled" value="アップロードする" onclick="p5uploadFile()" onkeypress="return false" onkeydown="return false">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p5CutButton" disabled="disabled" value="カット" onclick="p5copyFile(1)" onkeypress="return false" onkeydown="return false">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p5CopyButton" disabled="disabled" value="コピー" onclick="p5copyFile(0)" onkeypress="return false" onkeydown="return false">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p5PasteButton" disabled="disabled" value="ペースト" onclick="p5pasteFile()" onkeypress="return false" onkeydown="return false">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p5RefreshButton" value="リフレッシュ" onclick="p5refreshFiles()" onkeypress="return false" onkeydown="return false">
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="background-color:#E4E9E7;height:28px">
|
||
<table style="width:100%">
|
||
<tbody><tr>
|
||
<td id="p5currentpath" style="overflow:hidden;padding-left:4px;padding-top:2px"></td>
|
||
<td style="text-align:right;padding-right:4px">
|
||
<select id="p5sortdropdown" onchange="updateFiles()">
|
||
<option value="1" selected="selected">名前順</option>
|
||
<option value="2">サイズで並べ替え</option>
|
||
<option value="3">日付けで並び替え</option>
|
||
<option value="4">名前で降順</option>
|
||
<option value="5">サイズで降順</option>
|
||
<option value="6">日付で降順</option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
</tbody></table>
|
||
</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<div id="p5filetable" style="width:100%;height:calc(100% - 133px);overflow:auto;-webkit-user-select:none">
|
||
<!--
|
||
<div id="p5bigok" style="width:256px;overflow:hidden;position:absolute;left:337px;top:200px;text-align:center;font-size:1600%;color:#AAAAAA;display:none"><b>✓</b></div>
|
||
<div id="p5bigfail" style="width:256px;overflow:hidden;position:absolute;left:337px;top:200px;text-align:center;font-size:1600%;color:#AAAAAA;display:none"><b>✗</b></div>
|
||
-->
|
||
<span id="p5files"></span>
|
||
</div>
|
||
<table id="p5toolbarBottom" style="width:100%;height:22px;position:absolute;bottom:0px;background-color:#D3D9D6" cellpadding="0" cellspacing="0">
|
||
<tbody><tr>
|
||
<td style="text-align:left;padding:3px"> <span id="p5bottomstatus"></span></td>
|
||
<td id="p5rightOfButtons" style="text-align:right;padding:3px"></td>
|
||
</tr>
|
||
</tbody></table>
|
||
</div>
|
||
</div>
|
||
<div id="p10" style="display:none;position:absolute;bottom:0;top:0;width:100%;overflow:hidden">
|
||
<table cellspacing="0" style="margin:0;padding:0;border-spacing:0;border:0;position:absolute;top:0">
|
||
<tbody><tr style="padding:0">
|
||
<td style="padding:0;color:#c8c8c8;text-align:center;cursor:pointer" width="60px" valign="top" onclick="goBack()">
|
||
<div style="padding:0;background-color:#036;width:10px;height:10px;float:right;border:0">
|
||
<div style="background-color:white;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid white;border-bottom:1px solid white"></div>
|
||
</div>
|
||
<div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">◀</div>
|
||
</td>
|
||
<td>
|
||
<a id="MainComputerImage" style="cursor:pointer" onclick="p10showiconselector()"></a>
|
||
</td>
|
||
<td>
|
||
<div style="margin-left:5px">
|
||
<strong><span id="p10deviceName"></span></strong><br>
|
||
<span id="MainComputerState"></span>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<div id="p10general" style="overflow-y:scroll;position:absolute;top:55px;bottom:0px;width:100%">
|
||
<div id="p10html" style="margin-left:8px;margin-right:8px"></div>
|
||
<div id="p10html2"></div>
|
||
<div id="p10html3"></div>
|
||
</div>
|
||
<div id="p10desktop" style="overflow:hidden;position:absolute;top:55px;bottom:0px;width:100%;display:none">
|
||
<div id="deskarea1" style="position:absolute;top:0px;width:100%;height:25px">
|
||
<div style="padding-top:2px;padding-bottom:2px;background:#C0C0C0">
|
||
<div style="float:right;text-align:right">
|
||
<span id="p14power"></span>
|
||
<input id="DeskSoftInput" type="text" style="width:25px;display:none;opacity:.2" onblur="toggleSoftKeys(0)" onkeypress="return ondeskkeypress(event)" onkeydown="return ondeskkeydown(event)" onkeyup="return ondeskkeyup(event)">
|
||
</div>
|
||
<div style="margin-left:3px">
|
||
<input type="button" id="connectbutton1" value="つなぐ" onclick="connectDesktop(event,1)" onkeypress="return false" onkeydown="return false" disabled="disabled">
|
||
<input type="button" id="connectbutton1h" value="HW Connect" onclick="connectDesktop(event,2)" onkeypress="return false" onkeydown="return false" disabled="disabled">
|
||
<input type="button" id="disconnectbutton1" value="切断する" onclick="connectDesktop(event,0)" onkeypress="return false" onkeydown="return false">
|
||
<span id="deskstatus">切断されました</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="deskarea3" style="position:absolute;top:25px;width:100%;height:calc(100% - 50px)">
|
||
<div id="deskarea3x" style="background:black;text-align:center;height:100%;position:relative">
|
||
<div id="DeskParent" style="height:100%">
|
||
<canvas id="Desk" width="640" height="200" style="width:100%;-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown="dmousedown(event)" onmouseup="dmouseup(event)" onmousemove="dmousemove(event)" onmousewheel="dmousewheel(event)"></canvas>
|
||
</div>
|
||
<div id="DeskTools" style="position:absolute;width:400px;height:100%;background-color:gray;top:0;right:0;border-left:2px solid lightgray;display:none">
|
||
<a id="DeskToolsRefreshButton" style="float:right;padding:3px;cursor:pointer" onclick="refreshDeskTools()">リフレッシュ</a>
|
||
<div id="DeskToolsBar" style="position:absolute;padding:3px;border-radius: 3px 3px 0px 0px;top:5px;left:4px;bottom:26px;background-color:lightgray;cursor:pointer">プロセス</div>
|
||
<div style="position:absolute;top:26px;left:4px;right:4px;bottom:4px;background-color:lightgray;text-align:left">
|
||
<div style="border-bottom:1px solid darkgray;padding:3px"><a style="width:50px;padding-right:5px;float:left;cursor:pointer" onclick="sortProcess(0)">PID</a><a style="cursor:pointer" onclick="sortProcess(1)">名</a></div>
|
||
<div id="DeskToolsProcesses" style="overflow-y:scroll;position:absolute;top:24px;bottom:0px;width:100%"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="deskarea4" style="position:absolute;bottom:0px;width:100%;height:25px">
|
||
<div style="padding-top:2px;padding-bottom:2px;background:#C0C0C0">
|
||
<div style="float:right;text-align:right">
|
||
<select id="termdisplays" style="display:none" onchange="deskSetDisplay(event)" onclick="deskGetDisplayNumbers(event)"></select>
|
||
<span id="DeskToastButton"><img src="images/icon-notify.png" onclick="deviceToastFunction()" height="16" width="16" style="padding-top:2px"></span>
|
||
<!--<input id=DeskToolsButton type=button value=Tools onkeypress="return false" onkeydown="return false" onclick="toggleDeskTools()"> -->
|
||
</div>
|
||
<div>
|
||
<input id="deskActionsBtn" type="button" style="margin-left:3px" onkeypress="return false" onkeydown="return false" value="行動" onclick="deviceActionFunction()">
|
||
<input type="button" value="設定" onkeypress="return false" onkeydown="return false" onclick="showDesktopSettings()">
|
||
<input type="button" onkeypress="return false" onkeydown="return false" value="電源アクション..." onclick="showPowerActionDlg()" style="display:none">
|
||
<input id="DeskSpecialKeys" type="button" value="特別なキー" onkeypress="return false" onkeydown="return false" onclick="sendSpecialKeys()">
|
||
<input id="DeskSoftKeys" type="button" value="キーボード" onkeypress="return false" onkeydown="return false" onclick="toggleSoftKeys(1)">
|
||
<label><span id="DeskControlSpan" style="display:none"><input id="DeskControl" type="checkbox" onkeypress="return false" onkeydown="return false">入力</span></label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="p10files" style="overflow-y:scroll;position:absolute;top:55px;bottom:0px;width:100%;display:none">
|
||
<table id="p13toolbar" style="width:100%;height:111px" cellpadding="0" cellspacing="0">
|
||
<tbody><tr>
|
||
<td style="background-color:#C0C0C0;border-bottom:2px solid black;padding:2px">
|
||
<div style="float:right;text-align:right">
|
||
<input id="filesActionsBtn" type="button" onkeypress="return false" onkeydown="return false" value="行動" onclick="deviceActionFunction()" style="margin-right:2px">
|
||
</div>
|
||
<div style="margin-left:2px">
|
||
<input id="p13AutoConnect" value="自動接続" onclick="autoConnectFiles(event)" onkeypress="return false" onkeydown="return false" type="button" style="display:none">
|
||
<input id="p13Connect" value="つなぐ" onclick="connectFiles(event)" onkeypress="return false" onkeydown="return false" type="button">
|
||
<span id="p13Status">切断されました</span>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="width:100%;background-color:#d3d9d6;text-align:left;padding:4px" valign="bottom">
|
||
<div style="width:100%;text-align:center">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p13FolderUp" disabled="disabled" onclick="p13folderup()" value="アップ">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p13SelectAllButton" disabled="disabled" onclick="p13selectallfile()" value="すべて選択" onkeypress="return false" onkeydown="return false">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p13RenameFileButton" disabled="disabled" value="リネーム" onclick="p13renamefile()" onkeypress="return false" onkeydown="return false">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p13DeleteFileButton" disabled="disabled" value="削除する" onclick="p13deletefile()" onkeypress="return false" onkeydown="return false">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p13NewFolderButton" disabled="disabled" value="フォルダ" onclick="p13createfolder()" onkeypress="return false" onkeydown="return false">
|
||
</div>
|
||
<div style="width:100%;text-align:center">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p13UploadButton" disabled="disabled" value="アップロードする" onclick="p13uploadFile()" onkeypress="return false" onkeydown="return false">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p13CutButton" disabled="disabled" value="カット" onclick="p13copyFile(1)" onkeypress="return false" onkeydown="return false">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p13CopyButton" disabled="disabled" value="コピー" onclick="p13copyFile(0)" onkeypress="return false" onkeydown="return false">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p13PasteButton" disabled="disabled" value="ペースト" onclick="p13pasteFile()" onkeypress="return false" onkeydown="return false">
|
||
<input type="button" style="width:calc(100%/5 - 5px)" id="p13RefreshButton" disabled="disabled" value="リフレッシュ" onclick="p13folderup(9999)" onkeypress="return false" onkeydown="return false">
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="background-color:#E4E9E7;height:28px">
|
||
<table style="width:100%">
|
||
<tbody><tr>
|
||
<td id="p13currentpath" style="overflow:hidden;padding-left:4px;padding-top:2px"></td>
|
||
<td style="text-align:right;padding-right:4px">
|
||
<select id="p13sortdropdown" onchange="p13updateFiles()">
|
||
<option value="1" selected="selected">名前順</option>
|
||
<option value="2">サイズで並べ替え</option>
|
||
<option value="3">日付けで並び替え</option>
|
||
<option value="4">名前で降順</option>
|
||
<option value="5">サイズで降順</option>
|
||
<option value="6">日付で降順</option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
</tbody></table>
|
||
</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<div id="p13filetable" style="width:100%;height:calc(100% - 133px);overflow:auto;-webkit-user-select:none">
|
||
<!--
|
||
<div id="p13bigok" style="width:256px;overflow:hidden;position:absolute;left:337px;top:200px;text-align:center;font-size:1600%;color:#AAAAAA;display:none"><b>✓</b></div>
|
||
<div id="p13bigfail" style="width:256px;overflow:hidden;position:absolute;left:337px;top:200px;text-align:center;font-size:1600%;color:#AAAAAA;display:none"><b>✗</b></div>
|
||
-->
|
||
<span id="p13files"></span>
|
||
</div>
|
||
<table id="p13toolbarBottom" style="width:100%;height:22px;position:absolute;bottom:0px" cellpadding="0" cellspacing="0">
|
||
<tbody><tr><td style="text-align:left;padding:3px;text-align:center;background-color:#D3D9D6"> <span id="p13bottomstatus"></span></td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
</div>
|
||
<div id="p20" style="display:none;position:absolute;bottom:0;top:0;width:100%">
|
||
<table cellspacing="0" style="margin:0;padding:0;border-spacing:0;border:0;">
|
||
<tbody><tr style="padding:0">
|
||
<td style="padding:0;color:#c8c8c8;text-align:center;cursor:pointer" width="60px" valign="top" onclick="goBack()">
|
||
<div style="padding:0;background-color:#036;width:10px;height:10px;float:right;border:0">
|
||
<div style="background-color:white;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid white;border-bottom:1px solid white"></div>
|
||
</div>
|
||
<div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">◀</div>
|
||
</td>
|
||
<td onclick="p20editmesh(1)">
|
||
<img src="/images/meshicon50.png" width="50" height="50">
|
||
</td>
|
||
<td onclick="p20editmesh(1)">
|
||
<div style="margin-left:5px">
|
||
<strong style="font-size:large"><span id="p20meshName"></span></strong><br>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<div id="p20info" style="margin-left:8px;margin-right:8px"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="footer" style="height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0px">
|
||
<table id="footerMenu" cellpadding="0" cellspacing="0" style="height:32px;width:100%;color:white;cursor:pointer;table-layout:fixed"></table>
|
||
</div>
|
||
</div>
|
||
<div id="dialog" style="z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:5px;position:fixed;top:90px;width:300px;display:none">
|
||
<div style="width:100%;background-color:#003366;color:#FFF;border-radius:5px 5px 0 0">
|
||
<div id="id_dialogclose" style="float:right;padding:5px;cursor:pointer" onclick="setDialogMode()"><b>バツ</b></div>
|
||
<div id="id_dialogtitle" style="padding:5px"></div>
|
||
<div style="width:100%;margin:6px"></div>
|
||
</div>
|
||
<div style="margin-right:16px;margin-left:8px">
|
||
<div id="dialog1" style="margin:auto;text-align:center;margin:3px">
|
||
<div id="id_dialogMessage" style="padding:10px"></div>
|
||
</div>
|
||
<div id="dialog2" style="margin:auto;margin:3px">
|
||
<div id="id_dialogOptions"></div>
|
||
</div>
|
||
<div id="dialog3" style="margin:auto;margin:3px">
|
||
<select id="deskkeys" style="width:100%">
|
||
<option value="10">Ctrl + Alt + Del</option>
|
||
<option value="11">タブ</option>
|
||
<option value="5">勝つ</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>
|
||
</select>
|
||
</div>
|
||
<div id="dialog7" style="margin:auto;margin:3px">
|
||
<div id="d7meshkvm">
|
||
<h4 style="width:100%;border-bottom:1px solid gray">エージェントリモートデスクトップ</h4>
|
||
<div style="margin:3px 0 3px 0">
|
||
<select id="d7bitmapquality" style="float:right;width:200px;height:20px" dir="rtl"></select>
|
||
<div style="height:20px">品質</div>
|
||
</div>
|
||
<div style="margin:3px 0 3px 0">
|
||
<select id="d7bitmapscaling" style="float:right;width:200px;height:20px" 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 style="height:20px">スケーリング</div>
|
||
</div>
|
||
<div style="margin:3px 0 3px 0">
|
||
<select id="d7framelimiter" style="float:right;width:200px;height:20px" dir="rtl">
|
||
<option selected="selected" value="50">速い</option>
|
||
<option value="100">中</option>
|
||
<option value="400">スロー</option>
|
||
<option value="1000">非常に遅い</option>
|
||
</select>
|
||
<div style="height:20px">レート</div>
|
||
</div>
|
||
</div>
|
||
<div id="d7amtkvm">
|
||
<h4 style="width:100%;border-bottom:1px solid gray">インテル®AMTハードウェアKVM</h4>
|
||
<div style="height:26px">
|
||
<select id="d7desktopmode" style="float:right;width:200px">
|
||
<option value="1">RLE8、最速</option>
|
||
<option value="2">RLE16、推奨</option>
|
||
<option value="3">RAW8、遅い</option>
|
||
<option value="4">RAW16、非常に遅い</option>
|
||
</select>
|
||
<div>エンコーディング</div>
|
||
</div>
|
||
<div style="height:60px">
|
||
<div style="float:right;border:1px solid #666;width:200px;height:60px;overflow-y:scroll;background-color:white">
|
||
<label><input type="checkbox" id="d7showfocus">フォーカスツールを表示</label><br>
|
||
<label><input type="checkbox" id="d7showcursor">ローカルマウスカーソルを表示</label><br>
|
||
</div>
|
||
<div>その他</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="idx_dlgButtonBar" style="padding:10px;margin-bottom:20px">
|
||
<input id="idx_dlgCancelButton" type="button" value="キャンセル" style="float:right;width:80px;margin-left:5px" onclick="dialogclose(0)">
|
||
<input id="idx_dlgOkButton" type="button" value="OK" style="float:right;width:80px" onclick="dialogclose(1)">
|
||
</div>
|
||
</div>
|
||
<div id="topMenu" style="z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:0px 0px 5px 5px;position:fixed;top:50px;right:5px;width:170px;display:none">
|
||
<div style="padding:12px;border-top:1px solid gray;color:black;cursor:pointer" onclick="topMenu(2)">私のファイル</div>
|
||
<div style="padding:12px;border-top:1px solid gray;color:black;cursor:pointer" onclick="topMenu(1)">マイアカウント</div>
|
||
<div id="logoutMenuOption"><a href="/logout"><div style="padding:12px;border-top:1px solid gray;color:black;cursor:pointer">ログアウト</div></a></div>
|
||
</div>
|
||
<iframe name="fileUploadFrame" style="display:none"></iframe>
|
||
<script>
|
||
'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 = parseUriArgs();
|
||
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 authCookieRenewTimer = null;
|
||
var meshserver = null;
|
||
var xdr = null;
|
||
var serverinfo = null;
|
||
var nodes = [];
|
||
var meshes = {};
|
||
var filetree = {};
|
||
var userinfo = null;
|
||
var serverinfo = null;
|
||
var users = null;
|
||
var nodeShortIdent = 0;
|
||
var serverPublicNamePort = '{{{serverDnsName}}}:{{{serverPublicPort}}}';
|
||
var debugmode = false;
|
||
var attemptWebRTC = ((features & 128) != 0);
|
||
var StatusStrs = ["切断されました", "接続しています...", "セットアップ...", "接続済み", "Intel&reg;接続されたAMT"];
|
||
var files;
|
||
var passRequirements = '{{{passRequirements}}}';
|
||
if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); }
|
||
var sessionActivity = Date.now();
|
||
|
||
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; }
|
||
}
|
||
|
||
if (!args.locale) { var x = getstore('loctag', 0); if ((x != null) && (x != '*')) { args.locale = x; } }
|
||
|
||
window.onresize = center;
|
||
center();
|
||
QV('changeEmailId', (features & 0x200000) == 0);
|
||
QH('p1message', "接続しています...");
|
||
go(1);
|
||
|
||
// Connect to the mesh server
|
||
meshserver = MeshServerCreateControl(domainUrl, authCookie);
|
||
meshserver.onStateChanged = onStateChanged;
|
||
meshserver.onMessage = onMessage;
|
||
meshserver.Start();
|
||
|
||
// Load desktop settings
|
||
var t = localStorage.getItem('desktopsettings');
|
||
if (t != null) { desktopsettings = JSON.parse(t); }
|
||
applyDesktopSettings();
|
||
}
|
||
|
||
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
|
||
if (errorCode == 'noauth') { QH('p0span', "認証を実行できません"); return; }
|
||
if (prevState == 2) { setTimeout(serverPoll, 5000); } else { QH('p0span', "Webソケットに接続できません"); }
|
||
// Clean up here
|
||
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' });
|
||
meshserver.send({ action: 'files' });
|
||
if (xxcurrentView < 2) { go(2); }
|
||
authCookieRenewTimer = setInterval(function () { meshserver.send({ action: 'authcookie' }); }, 1800000); // Request a cookie refresh every 30 minutes.
|
||
}
|
||
QV('topMenuIcon', state == 2);
|
||
}
|
||
|
||
// Poll the server, if it responds, refresh the page.
|
||
function serverPoll() {
|
||
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();
|
||
}
|
||
|
||
function updateSelf() {
|
||
QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
||
QV('manageAuthApp', features & 4096);
|
||
QV('manageOtp', ((features & 4096) != 0) && ((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0)));
|
||
|
||
// On the mobile app, don't allow group creation (for now).
|
||
QV('p3createMeshLink1', false);
|
||
QV('p3createMeshLink2', false);
|
||
|
||
if (typeof userinfo.passchange == 'number') {
|
||
if (userinfo.passchange == -1) { QH('p2nextPasswordUpdateTime', " -次回ログイン時にリセット。"); }
|
||
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', " -次回ログイン時にリセット。"); }
|
||
else if (seconds < 3600) { QH('p2nextPasswordUpdateTime', format(" -{0}分でリセット{1}。", Math.floor(seconds / 60), addLetterS(Math.floor(seconds / 60)))); }
|
||
else if (seconds < 86400) { QH('p2nextPasswordUpdateTime', format(" -{0}時間でリセット{1}。", Math.floor(seconds / 3600), addLetterS(Math.floor(seconds / 3600)))); }
|
||
else { QH('p2nextPasswordUpdateTime', format(" -{0}日でリセット{1}。"), Math.floor(seconds / 86400), addLetterS(Math.floor(seconds / 86400))); }
|
||
}
|
||
}
|
||
}
|
||
|
||
function addLetterS(x) { return (x > 1) ? 's' : ''; }
|
||
function setSessionActivity() { sessionActivity = Date.now(); }
|
||
function checkIdleSessionTimeout() { var delta = (Date.now() - sessionActivity); if (delta > serverinfo.timeout) { window.location.href = 'logout'; } }
|
||
|
||
function onMessage(server, message) {
|
||
switch (message.action) {
|
||
case 'serverinfo': {
|
||
serverinfo = message.serverinfo;
|
||
if (serverinfo.timeout) { setInterval(checkIdleSessionTimeout, 10000); checkIdleSessionTimeout(); }
|
||
QV('p3AccountActions', ((features & 4) == 0) && (serverinfo.domainauth == false)); // Hide Account Actions if in single user mode or domain authentication
|
||
QV('logoutMenuOption', ((features & 4) == 0) && (serverinfo.domainauth == false)); // Hide logout if in single user mode or domain authentication
|
||
break;
|
||
}
|
||
case 'authcookie': {
|
||
// Got an authentication cookie refresh
|
||
authCookie = message.cookie;
|
||
authRelayCookie = message.rcookie;
|
||
break;
|
||
}
|
||
case 'userinfo': {
|
||
userinfo = message.userinfo;
|
||
QH('p3userName', userinfo.name);
|
||
//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]; }
|
||
updateMeshes();
|
||
updateDevices();
|
||
break;
|
||
}
|
||
case 'files': {
|
||
filetree = setupBackPointers(message.filetree);
|
||
updateFiles();
|
||
//d3updatefiles();
|
||
break;
|
||
}
|
||
case 'nodes': {
|
||
nodes = [];
|
||
for (var m in message.nodes) {
|
||
for (var n in message.nodes[m]) {
|
||
if (!meshes[m]) { console.log('Invalid mesh (1): ' + m); 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;
|
||
if (!message.nodes[m][n].icon) message.nodes[m][n].icon = 1;
|
||
message.nodes[m][n].ident = ++nodeShortIdent;
|
||
nodes.push(message.nodes[m][n]);
|
||
}
|
||
}
|
||
//onSortSelectChange();
|
||
//onSearchInputChanged();
|
||
updateDevices();
|
||
//refreshMap(false, true);
|
||
if (xxcurrentView == 0) { if ('{{viewmode}}' != '') { go(parseInt('{{viewmode}}')); } else { setDialogMode(0); go(2); } }
|
||
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
|
||
if (currentNode._id == message.nodeid) { drawDeviceTimeline(); }
|
||
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', "インストール<a href=\"https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2\" rel=\"noreferrer noopener\" target=_blank> Google Authenticator </a>または互換性のあるアプリケーションの場合、<a href=\"' + message.url +'\" rel=\"noreferrer noopener\" target=_blank>このリンク</a>を使用するか、下に秘密を入力します。次に、現在の6桁のトークンを入力して、2段階ログインを有効にします。" + '<br /><br /><div style=width:100%;text-align:center><tt id=d2optsecret secret=\"' + message.secret + '\" style=font-size:15px>' + secret + '</tt><br /><br />Token: <input type=text onkeypress=\"return (event.keyCode == 8) || (event.charCode >= 48 && event.charCode <= 57)\" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text></div>');
|
||
QV('idx_dlgOkButton', true);
|
||
QE('idx_dlgOkButton', false);
|
||
Q('d2otpauthinput').focus();
|
||
}
|
||
break;
|
||
}
|
||
case 'otpauth-setup': {
|
||
if (xxdialogMode) return;
|
||
setDialogMode(2, "認証アプリ", 1, null, message.success ? "<b style = color:green> 2段階ログインの有効化に成功</ b>。再度ログインするには、有効なトークンが必要になります。" : "<b style = color:red> 2段階ログインの有効化に失敗しました</ b>。アプリケーションから秘密をクリアして、再試行してください。適切なコードを入力するのに数分しかかかりません。");
|
||
break;
|
||
}
|
||
case 'otpauth-clear': {
|
||
if (xxdialogMode) return;
|
||
setDialogMode(2, "認証アプリ", 1, null, message.success ? "<b style = color:green> 2段階のログインアクティベーションが削除されました</ b>。この機能はいつでも再アクティブ化できます。" : "<b style = color:red> 2段階のログインアクティベーションの削除に失敗しました</ b>。再試行する。");
|
||
break;
|
||
}
|
||
case 'otpauth-getpasswords': {
|
||
if (xxdialogMode) return;
|
||
var x = "ワンタイムトークンは、セカンダリ認証として使用できます。セットを生成して印刷し、安全な場所に保管してください。";
|
||
x += '<div style=\'border-radius:6px;border: 2px dashed #888;width:100%;margin-top:8px\'><div style=\'padding:8px;font-family:Arial, Helvetica, sans-serif;font-size:20px;font-weight:bold\'><table style=width:100%;text-align:center>';
|
||
if (message.passwords) {
|
||
var j = 0;
|
||
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); } else { x += '<td><strike style=color:#BBB>' + p.substring(0, 4) + ' ' + p.substring(4); + '</strike>'; }
|
||
}
|
||
} else {
|
||
x += '<tr><td>' + "アクティブなトークンがありません";
|
||
}
|
||
x += '</table></div></div><br />';
|
||
x += '<div><input type=button value=\'' + "閉じる" + '\' onclick=setDialogMode(0) style=float:right></input>';
|
||
x += '<input type=button value=\'' + "新しいトークン" + '\' onclick=\'account_manageOtp(1);\'></input>';
|
||
if (message.passwords != null) { x += '<input type=button value=\'' + "クリア" + '\' onclick=\'account_manageOtp(2);\'></input>'; }
|
||
x += '</div><br />';
|
||
setDialogMode(2, "バックアップコードの管理", 8, null, x, 'otpauth-manage');
|
||
break;
|
||
}
|
||
case 'event': {
|
||
/*
|
||
if (!message.event.nolog) {
|
||
events.unshift(message.event);
|
||
var eventLimit = parseInt(p3limitdropdown.value);
|
||
while (events.length > eventLimit) { events.pop(); } // Remove element(s) at the end
|
||
events_update();
|
||
}
|
||
*/
|
||
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 webstate = JSON.parse(message.event.state);
|
||
for (var i in webstate) { localStorage.setItem(i, webstate[i]); }
|
||
|
||
// Update the web page
|
||
if ((webstate.loctag != null) && (webstate.loctag != oldLoctag)) {
|
||
if (webstate.loctag != null) { args.locale = webstate.loctag; } else { delete args.locale; }
|
||
updateDevices();
|
||
updateMeshes();
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
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' }); }
|
||
userinfo = message.event.account;
|
||
if (oldsiteadmin != newsiteadmin) updateSiteAdmin();
|
||
updateSelf();
|
||
}
|
||
break;
|
||
}
|
||
case 'createmesh': {
|
||
// A new mesh was created
|
||
if (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 };
|
||
updateMeshes();
|
||
updateDevices();
|
||
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 (meshes[message.event.meshid].name != message.event.name) {
|
||
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(); } }
|
||
}
|
||
meshes[message.event.meshid].desc = message.event.desc;
|
||
meshes[message.event.meshid].links = message.event.links;
|
||
|
||
// 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(2); }
|
||
}
|
||
}
|
||
updateMeshes();
|
||
updateDevices();
|
||
meshserver.send({ action: 'files' });
|
||
|
||
// If we are looking at a mesh that is now deleted, move back to "My Account"
|
||
if (xxcurrentView == 20 && currentMesh._id == message.event.meshid) { p20updateMesh(); }
|
||
break;
|
||
}
|
||
case 'deletemesh': {
|
||
// Delete the mesh
|
||
if (meshes[message.event.meshid]) {
|
||
delete meshes[message.event.meshid];
|
||
updateMeshes();
|
||
meshserver.send({ action: 'files' });
|
||
}
|
||
|
||
// 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;
|
||
updateDevices();
|
||
|
||
// 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(2); }
|
||
|
||
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;
|
||
nodes.push(node);
|
||
//onSortSelectChange();
|
||
//onSearchInputChanged();
|
||
updateDevices();
|
||
//updateMapMarkers();
|
||
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(2); }
|
||
currentNode = null;
|
||
// TODO: Correctly disconnect from this node (Desktop/Terminal/Files...)
|
||
}
|
||
nodes.splice(index, 1);
|
||
updateDevices();
|
||
//updateMapMarkers();
|
||
}
|
||
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.host = message.event.node.host;
|
||
node.desc = message.event.node.desc;
|
||
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; }
|
||
}
|
||
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; }
|
||
|
||
//onSortSelectChange(true);
|
||
//drawNotifications();
|
||
refreshDevice(node._id);
|
||
//updateMapMarkers();
|
||
updateDevices();
|
||
|
||
//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(2); } currentNode = null; }
|
||
nodes.splice(index, 1);
|
||
} else {
|
||
// We see the new mesh, move this device
|
||
node.meshid = message.event.newMeshId;
|
||
node.meshnamel = meshes[message.event.newMeshId].name.toLowerCase();
|
||
}
|
||
updateDevices();
|
||
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);
|
||
updateDevices();
|
||
}
|
||
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];
|
||
|
||
// Change the node connection state
|
||
node.conn = message.event.conn;
|
||
node.pwr = message.event.pwr;
|
||
updateDevices();
|
||
//updateMapMarkers();
|
||
//refreshDevice(node._id);
|
||
}
|
||
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 = message.event.time; }
|
||
break;
|
||
}
|
||
case 'notify': {
|
||
//var n = { text: message.event.value };
|
||
//if (message.event.tag != null) { n.tag = message.event.tag; }
|
||
//addNotification(n);
|
||
break;
|
||
}
|
||
case 'stopped': { // Server is stopping.
|
||
// TODO: Disconnect
|
||
break;
|
||
}
|
||
default:
|
||
//console.log('Unknown message.event.action', message.event.action);
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
default:
|
||
//console.log('Unknown message.action', message.action);
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Menu System
|
||
//
|
||
|
||
function topMenu(select) {
|
||
if ((xxdialogMode != null) && (xxdialogMode != 0) && (xxdialogMode != 999)) return;
|
||
if (select === undefined) {
|
||
var x = (QS('topMenu').display == 'none');
|
||
if (x == true) { if ((xxdialogMode == 0) || (xxdialogMode == null)) { QV('topMenu', true); xxdialogMode = 999; } } else { QV('topMenu', false); xxdialogMode = 0; }
|
||
} else {
|
||
QV('topMenu', false);
|
||
xxdialogMode = 0;
|
||
if ((select == 1) && (xxcurrentView != 3)) { goForward('account'); } // My Account
|
||
if ((select == 2) && (xxcurrentView != 5)) { goForward('files'); } // My Files
|
||
}
|
||
}
|
||
|
||
var backStack = [];
|
||
function goBack() { if (xxdialogMode) return; if (backStack.length > 0) { backStack.pop(); } goStack(); }
|
||
function goForward(id) { if (xxdialogMode) return; backStack.push(id); goStack(); }
|
||
function goStack() {
|
||
if (backStack.length == 0) { go(2); return; }
|
||
var id = backStack[backStack.length - 1], idtype = id.split('/')[0];
|
||
if (idtype == 'node') { setupDeviceMenu(0); gotoDevice(id); }
|
||
if (idtype == 'mesh') { gotoMesh(id); }
|
||
if (idtype == 'account') { go(3); }
|
||
if (idtype == 'devices') { go(2); }
|
||
if (idtype == 'files') { go(5); }
|
||
}
|
||
|
||
function updateFooterMenu(options) {
|
||
while (options != null && options.length < 3) { options.push({ n: '' }); }
|
||
var x = '', prev = '';
|
||
if (options != null) { for (var i in options) { x += '<td style="cursor:pointer' + ((prev == '') ? '' : ';border-left:solid 1px white') + '" onclick="' + options[i].f + '">' + options[i].n; prev = options[i].n; } }
|
||
QH('footerMenu', '<tr>' + x);
|
||
}
|
||
|
||
//
|
||
// MY ACCOUNT
|
||
//
|
||
|
||
function account_manageAuthApp() {
|
||
if (xxdialogMode || ((features & 4096) == 0)) return;
|
||
if (userinfo.otpsecret == 1) { account_removeOtp(); } else { account_addOtp(); }
|
||
}
|
||
|
||
function account_addOtp() {
|
||
if (xxdialogMode || (userinfo.otpsecret == 1) || ((features & 4096) == 0)) return;
|
||
setDialogMode(2, "認証アプリ", 2, function () { meshserver.send({ action: 'otpauth-setup', secret: Q('d2optsecret').attributes.secret.value, token: Q('d2otpauthinput').value }); }, '<div id=d2optinfo>' + "読み込み中..." + '</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, "認証アプリ", 3, function () { meshserver.send({ action: 'otpauth-clear' }); }, "認証アプリケーションの削除2段階ログインを確認しますか?");
|
||
}
|
||
|
||
function account_manageOtp(action) {
|
||
if ((xxdialogMode == 2) && (xxdialogTag == 'otpauth-manage')) { dialogclose(0); }
|
||
if (xxdialogMode || (userinfo.otpsecret != 1) || ((features & 4096) == 0)) return;
|
||
meshserver.send({ action: 'otpauth-getpasswords', subaction: action });
|
||
}
|
||
|
||
function account_showVerifyEmail() {
|
||
if (xxdialogMode || (userinfo.emailVerified == true) || (serverinfo.emailcheck != true)) return;
|
||
var x = "[OK]をクリックして確認メールを送信します:" + '<br /><div style=padding:8px><b>' + EscapeHtml(userinfo.email) + '</b></div>' + "確認を受けるまで数分お待ちください。";
|
||
setDialogMode(2, "メール確認", 3, account_showVerifyEmailEx, x);
|
||
}
|
||
|
||
function account_showVerifyEmailEx() {
|
||
meshserver.send({ action: 'verifyemail', email: userinfo.email });
|
||
}
|
||
|
||
function account_showChangeEmail() {
|
||
if (xxdialogMode) return;
|
||
var x = addHtmlValue("Eメール", '<input id=dp3email style=width:170px maxlength=256 onchange=account_validateEmail() onkeyup=account_validateEmail(event) />');
|
||
setDialogMode(2, "メールアドレスの変更", 3, account_changeEmail, x);
|
||
if (userinfo.email != null) { Q('dp3email').value = userinfo.email; }
|
||
account_validateEmail();
|
||
Q('dp3email').focus();
|
||
}
|
||
|
||
function account_validateEmail(e, email) {
|
||
QE('idx_dlgOkButton', validateEmail(Q('dp3email').value) && (Q('dp3email').value != userinfo.email));
|
||
if ((e != null) && (e.keyCode == 13)) { dialogclose(1); }
|
||
}
|
||
|
||
function account_changeEmail() {
|
||
meshserver.send({ action: 'changeemail', email: Q('dp3email').value });
|
||
}
|
||
|
||
function account_showDeleteAccount() {
|
||
if (xxdialogMode) return;
|
||
var x = '<form method=post><table style=margin-left:10px><input type=hidden name=action value=deleteaccount /><input type=hidden name=authcookie value=' + authCookie + ' /><tr>';
|
||
x += '<td align=right>' + "パスワード:" + '</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>';
|
||
x += '</tr><tr><td align=right>' + "パスワード:" + '</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>';
|
||
x += '</tr></table><div style=padding:10px;margin-bottom:4px>';
|
||
x += '<input id=account_dlgCancelButton type=button value=\"' + "キャンセル" + '\" 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, "アカウントを削除する", 0, null, x);
|
||
account_validateDeleteAccount();
|
||
Q('apassword1').focus();
|
||
}
|
||
|
||
|
||
function account_showChangePassword() {
|
||
if (xxdialogMode) return false;
|
||
var x = '<table style=margin-left:10px>';
|
||
x += '<tr><td align=right>' + nobreak("以前のパスワード:") + '</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("新しいパスワード:") + '</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("新しいパスワード:") + '</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>' + "パスワードのヒント:" + '</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>' + format("要件:{0}。", r.join(', ')) + '</span>'; }
|
||
}
|
||
x += '<br />';
|
||
setDialogMode(2, "パスワードを変更する", 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;
|
||
|
||
// Check if we are disallowed from creating a device group
|
||
if ((userinfo.siteadmin != 0xFFFFFFFF) && ((userinfo.siteadmin & 64) != 0)) { setDialogMode(2, "新しいデバイスグループ", 1, null, "このアカウントには、新しいデバイスグループを作成する権限がありません。"); return; }
|
||
|
||
// Remind the user to verify the email address
|
||
if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "アカウントのセキュリティ", 1, null, "メールアドレスが確認されるまでデバイスにアクセスできません。これはパスワードの回復に必要です。 「マイアカウント」に移動して、メールアドレスを変更および確認します。"); return; }
|
||
|
||
// Remind the user to add two factor authentication
|
||
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0))) { setDialogMode(2, "アカウントのセキュリティ", 1, null, "二要素認証が有効になるまでデバイスにアクセスできません。これは、追加のセキュリティのために必要です。 「マイアカウント」に移動して、「アカウントセキュリティ」セクションを確認します。"); return; }
|
||
|
||
// We are allowed, let's prompt to information
|
||
var x = addHtmlValue("名", '<input id=dp3meshname style=width:170px maxlength=64 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate() />');
|
||
x += addHtmlValue("タイプ", '<div style=width:170px;margin:0;padding:0><select id=dp3meshtype style=width:100% onchange=account_validateMeshCreate() ><option value=2>' + "ソフトウェアエージェントグループ" + '</option><option value=1>' + "Intel&reg; AMTのみ" + '</option></select></div>');
|
||
x += addHtmlValue("説明", '<div style=width:170px;margin:0;padding:0><textarea id=dp3meshdesc maxlength=1024 style=width:100%;resize:none></textarea></div>');
|
||
setDialogMode(2, "デバイスグループを作成する", 3, account_createMeshEx, x);
|
||
account_validateMeshCreate();
|
||
Q('dp3meshname').focus();
|
||
}
|
||
|
||
function account_validateMeshCreate() {
|
||
QE('idx_dlgOkButton', Q('dp3meshname').value.length > 0);
|
||
}
|
||
|
||
function account_createMeshEx(button, tag) {
|
||
meshserver.send({ action: 'createmesh', meshname: Q('dp3meshname').value, meshtype: Q('dp3meshtype').value, desc: Q('dp3meshdesc').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>Strong<span>'; } else if (passStrength >= 60) { r = '<span style=color:blue>●<span>'; } else { r = '<span style=color:red>●<span>'; }
|
||
} else {
|
||
// Password requirements provided, use that
|
||
var passReq = checkPasswordRequirements(Q('apassword1').value, passRequirements);
|
||
if (passReq == false) { ok = false; r = '<span style=color:red>' + "方針" + '<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 = '', count = 0;
|
||
for (i in meshes) {
|
||
count++;
|
||
|
||
// Mesh rights
|
||
var meshrights = meshes[i].links[userinfo._id].rights;
|
||
var rights = "部分的権利";
|
||
if (meshrights == 0xFFFFFFFF) rights = "完全な管理者"; else if (meshrights == 0) rights = "権利なし";
|
||
|
||
// Print the mesh information
|
||
r += '<div style=cursor:pointer onclick=goForward(\'' + i + '\')>';
|
||
r += '<div style="float:left;margin-left:4px"><img src="/images/meshicon50.png" width=50 height=50 /></div>';
|
||
r += '<div style="width:auto;height:40px;background-color:lightgray;margin-top:5px;margin-bottom:5px;margin-left:60px;padding-top:5px;padding-bottom:5px;border-radius:8px 0px 0px 8px">';
|
||
r += '<div><div style=padding-left:12px;padding-top:2px><b>' + EscapeHtml(meshes[i].name) + '</b></div><div style=padding-left:12px;padding-top:3px;color:gray>' + rights + '</div></div>';
|
||
r += '</div></div>';
|
||
}
|
||
|
||
QH('p3meshes', r);
|
||
QV('p3noMeshFound', count == 0);
|
||
}
|
||
|
||
function gotoMesh(meshid) {
|
||
currentMesh = meshes[meshid];
|
||
if (currentMesh == null) { goBack(); }
|
||
p20updateMesh();
|
||
go(20);
|
||
}
|
||
|
||
//
|
||
// MY FILES
|
||
//
|
||
|
||
var filetreelinkpath;
|
||
var filetreelocation = [];
|
||
|
||
function p5refreshFiles() { meshserver.send({ action: 'files' }); }
|
||
|
||
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 style=cursor:pointer onclick=p5folderup(0)>' + "ルート" + '</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 style=cursor:pointer onclick=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 > 40) { shortname = EscapeHtml(name.substring(0, 40)) + "..."; } else { shortname = EscapeHtml(name); }
|
||
name = EscapeHtml(name);
|
||
|
||
// Figure out the date
|
||
//var fdatestr = '';
|
||
//if (f.d != null) { var fdate = new Date(f.d), fdatestr = (fdate.getMonth() + 1) + '/' + (fdate.getDate()) + '/' + fdate.getFullYear() + ' ' + printTime(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) : '';
|
||
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;padding-right:4px>' + right + '</span><span><div class=fileIcon' + f.t + '></div><a style=cursor:pointer onclick=p5folderset(\"' + encodeURIComponent(f.nx) + '\")>' + shortname + '</a></span></div>';
|
||
} else {
|
||
var link = shortname;
|
||
var publiclink = '';
|
||
if (publicfolder) { publiclink = ' (<a style=cursor:pointer onclick=\'p5showPublicLink(\"' + publicPath + '/' + f.nx + '\")\'>' + "リンク" + '</a>)'; }
|
||
if (f.s > 0) { link = '<a rel=\"noreferrer noopener\" target=\"_blank\" 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 style=float:right;padding-right:4px>' + 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 "ストレージを超えています";
|
||
if (bytes < 2048) return format("{0} b残り", bytes);
|
||
if (bytes < 2097152) return format("{0} k残り", Math.round(bytes / 1024));
|
||
if (bytes < 2147483648) return format("残り{0} m", Math.round(bytes / 1024 / 1024));
|
||
return format("{0} g残り", 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 '';
|
||
return getNiceSize(f.maxbytes - f.s) + ' <progress style=height:10px;width:100px value=' + f.s + ' max=' + f.maxbytes + ' />';
|
||
}
|
||
|
||
function p5showPublicLink(u) { setDialogMode(2, "公開リンク", 1, null, '<input type=text style=width:100% value="' + u + '" readonly />'); }
|
||
|
||
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('p5SelectAllButton', tc > 0);
|
||
Q('p5SelectAllButton').value = (cc > 0 ? "なし" : "すべて");
|
||
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バイト"; return format("{0}バイト", 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, "新しいフォルダ", 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>' + "再帰削除" + '</label><br>' : '<input type=checkbox id=p5recdeleteinput style=\'display:none\'>'; setDialogMode(2, "削除する", 3, p5deletefileEx, (cc > 1) ? (format("選択したアイテム{0}を削除しますか?", cc) + rec) : ("選択したアイテムを削除しますか?" + 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, "リネーム", 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, "ファイルをアップロードする", 3, p5uploadFileEx, '<form method=post enctype=multipart/form-data action=uploadfile.ashx target=fileUploadFrame><input type=text name=link style=display:none id=p5uploadpath value=\"' + encodeURIComponent(filetreelinkpath) + '\" /><input type=file name=files id=p5uploadinput style=width:100% multiple=multiple onchange="updateUploadDialogOk(\'p5uploadinput\')" /><input type=hidden name=authCookie value=' + authCookie + ' /><input type=submit id=p5loginSubmit style=display:none /></form>'); updateUploadDialogOk('p5uploadinput'); }
|
||
function p5uploadFileEx() { Q('p5loginSubmit').click(); }
|
||
function updateUploadDialogOk(x) { QE('idx_dlgOkButton', Q(x).value != ''); }
|
||
|
||
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')) { p5clipboard.push(checkboxes[i].value); } } p5updateClipview(); }
|
||
function p5pasteFile() { var x = ''; if ((p5clipboard != null) && (p5clipboard.length > 0)) { x = format("{1}エントリ{2}のうち{0}をこの場所に拘束しますか?", (p5clipboardCut == 0 ? 'copy' : 'move'), p5clipboard.length, ((p5clipboard.length > 1) ? 's' : '')) } setDialogMode(2, "ペースト", 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("{2}の{0}エントリを保持しています{1}", p5clipboard.length, ((p5clipboard.length > 1) ? 's' : ''), (p5clipboardCut == 0 ? "コピー" : "動く")) + ', <a href=# onclick="return p5clearClip()" style=cursor:pointer>' + "クリア" + '</a>.' } QH('p5bottomstatus', x); p5setActions(); }
|
||
function p5clearClip() { p5clipboard = null; p5clipboardFolder = null; p5clipboardCut = 0; p5updateClipview(); return false; }
|
||
|
||
function p5fileDragDrop(e) {
|
||
haltEvent(e);
|
||
QV('bigfail', false);
|
||
QV('bigok', false);
|
||
//QV('p5fileCatchAllInput', false);
|
||
if (e.dataTransfer == null || e.dataTransfer.files.length == 0 || filetreelocation.length == 0) return;
|
||
var names = [], sizes = [], types = [], datas = [], readercount = e.dataTransfer.files.length;
|
||
for (var i = 0; i < e.dataTransfer.files.length; i++) {
|
||
var reader = new FileReader(), file = e.dataTransfer.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('*');
|
||
Q('p5fileDragLink').value = encodeURIComponent(filetreelinkpath);
|
||
Q('p5loginSubmit2').click();
|
||
}
|
||
}
|
||
reader.readAsDataURL(file);
|
||
}
|
||
}
|
||
|
||
var p5dragtimer = null;
|
||
function p5fileDragOver(e) {
|
||
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) {
|
||
haltEvent(e);
|
||
if (e.target.id != 'p5filetable') {
|
||
QV('bigfail', false);
|
||
QV('bigok', false);
|
||
//QV('p5fileCatchAllInput', false);
|
||
} else {
|
||
p5dragtimer = setTimeout('QV(\'bigfail\',false);QV(\'bigok\',false);p5dragtimer=null;', 200);
|
||
}
|
||
}
|
||
|
||
//
|
||
// MY DEVICES
|
||
//
|
||
|
||
function ondeskkeypress(e) {
|
||
toggleSoftKeys(0);
|
||
Q('DeskSoftInput').value = '';
|
||
setSessionActivity();
|
||
if (desktop && !xxdialogMode && xxcurrentView == 10) {
|
||
// 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);
|
||
}
|
||
}
|
||
|
||
function ondeskkeydown(e) {
|
||
toggleSoftKeys(0);
|
||
Q('DeskSoftInput').value = '';
|
||
setSessionActivity();
|
||
if (desktop && !xxdialogMode && xxcurrentView == 10) {
|
||
// 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);
|
||
}
|
||
}
|
||
|
||
function ondeskkeyup(e) {
|
||
toggleSoftKeys(0);
|
||
Q('DeskSoftInput').value = '';
|
||
setSessionActivity();
|
||
if (desktop && !xxdialogMode && xxcurrentView == 10) {
|
||
// 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);
|
||
}
|
||
}
|
||
|
||
// Since the update device call can be quite frequent, we can moderate it and only call it at most 5 times a second.
|
||
var updateDevicesTimer = null;
|
||
function updateDevices() { if (updateDevicesTimer != null) return; updateDevicesTimer = setTimeout(updateDevicesEx, 200); }
|
||
|
||
var sort = 0;
|
||
var deviceHeaderId = 0;
|
||
var deviceHeaderCount;
|
||
var deviceHeaders = {};
|
||
var showRealNames = false;
|
||
var deviceHeaderTotal = 0;
|
||
var deviceHeaders = {};
|
||
var deviceHeadersTitles = {};
|
||
function updateDevicesEx() {
|
||
if (updateDevicesTimer != null) { clearTimeout(updateDevicesTimer); updateDevicesTimer = null; }
|
||
var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, groups = {}, groupCount = {};
|
||
|
||
// 3 wide, list view or desktop view
|
||
deviceHeaderId = 0;
|
||
deviceHeaderCount = {};
|
||
deviceHeaderTotal = 0;
|
||
deviceHeaders = {};
|
||
deviceHeadersTitles = {};
|
||
var current;
|
||
|
||
// 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); } }
|
||
|
||
// Go thru the list of nodes and display them
|
||
for (var i in nodes) {
|
||
if (nodes[i].v == false) continue;
|
||
var mesh2 = meshes[nodes[i].meshid], meshlinks = mesh2.links[userinfo._id];
|
||
if (meshlinks == null) continue;
|
||
var meshrights = meshlinks.rights;
|
||
|
||
if (sort == 0) {
|
||
// Mesh header
|
||
nodes.sort(meshSort);
|
||
if (nodes[i].meshid != current) {
|
||
deviceHeaderSet();
|
||
var extra = '';
|
||
if (meshes[nodes[i].meshid].mtype == 1) { extra = '<span style=color:lightgray>' + "、Intel&reg; AMTのみ" + '</span>'; }
|
||
if (current != null) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
|
||
r += '<div class=DevSt style=padding-top:4px><span style=float:right>';
|
||
//r += getMeshActions(mesh2, meshrights);
|
||
r += '</span><span id=MxMESH style=cursor:pointer onclick=goForward("' + nodes[i].meshid + '")>' + EscapeHtml(meshes[nodes[i].meshid].name) + '</span>' + extra + '<span id=DevxHeader' + deviceHeaderId + ' style=color:lightgray></span></div>';
|
||
current = nodes[i].meshid;
|
||
displayedMeshes[current] = 1;
|
||
c = 0;
|
||
}
|
||
} else if (sort == 1) {
|
||
// Power header
|
||
if (nodes[i].pwr !== current) {
|
||
deviceHeaderSet();
|
||
if (current !== null) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
|
||
r += '<div class=DevSt style=width:100%;padding-top:4px><span>' + PowerStateStr2(nodes[i].pwr) + '</span><span id=DevxHeader' + deviceHeaderId + ' style=color:lightgray></span></div>';
|
||
current = nodes[i].pwr;
|
||
c = 0;
|
||
}
|
||
} else if (sort == 2) {
|
||
// Device header
|
||
if (current == null) { current = '1'; }
|
||
}
|
||
|
||
count++;
|
||
var title = EscapeHtml(nodes[i].name);
|
||
if (title.length == 0) { title = '<i>' + "なし" + '</i>'; }
|
||
if ((nodes[i].rname != null) && (nodes[i].rname.length > 0)) { title += " /" + EscapeHtml(nodes[i].rname); }
|
||
var name = EscapeHtml(nodes[i].name);
|
||
if (showRealNames == true && nodes[i].rname != null) name = EscapeHtml(nodes[i].rname);
|
||
if (name.length == 0) { name = '<i>' + "なし" + '</i>'; }
|
||
|
||
// Node
|
||
var icon = nodes[i].icon, nodestate = NodeStateStr(nodes[i]);
|
||
if ((!nodes[i].conn) || (nodes[i].conn == 0)) { icon += ' gray'; }
|
||
r += '<div style=cursor:pointer onclick=goForward(\'' + nodes[i]._id + '\')>';
|
||
r += '<div class="i' + icon + '" style="float:left;margin-left:4px"></div>';
|
||
r += '<div style="width:auto;height:40px;background-color:lightgray;margin-top:5px;margin-bottom:5px;margin-left:60px;padding-top:5px;padding-bottom:5px;border-radius:8px 0px 0px 8px">';
|
||
r += '<div><div style=padding-left:12px;padding-top:2px><b>' + name + '</b></div><div style=padding-left:12px;padding-top:3px;color:gray>' + nodestate + '</div></div>';
|
||
r += '</div></div>';
|
||
|
||
// If we are displaying devices by group, put the device in the right group.
|
||
/*
|
||
if ((sort == 3) && (r != '')) {
|
||
if (nodes[i].tags) {
|
||
for (var j in nodes[i].tags) {
|
||
var tag = nodes[i].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[nodes[i].state] == 'undefined') { deviceHeaderCount[nodes[i].state] = 1; } else { deviceHeaderCount[nodes[i].state]++; }
|
||
}
|
||
|
||
// Display all empty meshes, we need to do this because users can add devices to these at any time.
|
||
if (sort == 0) {
|
||
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 += '<div><div colspan=3 class=DevSt><span style=float:right>';
|
||
//r += getMeshActions(mesh, meshrights);
|
||
r += '</span><span id=MxMESH style=cursor:pointer onclick=goForward("' + mesh._id + '")>' + EscapeHtml(mesh.name) + '</span></div>';
|
||
if (mesh.mtype == 1) { r += '<div style=padding:10px><i>' + "Intel&reg;なしこのグループのAMTデバイス"; }
|
||
if (mesh.mtype == 2) { r += '<div style=padding:10px><i>' + "このグループにデバイスはありません"; }
|
||
r += '.</i></div></div>';
|
||
current = mesh._id;
|
||
count++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (count == 0) {
|
||
QH('xdevices', '<div style="margin-top:50px;text-align:center"><span style="font-size:30px">' + "デバイスなし" + '</span><br /><br />' + "このWebサイトのデスクトップバージョンを使用して、デバイスを追加します。" + '</div>');
|
||
} else {
|
||
QH('xdevices', r);
|
||
}
|
||
deviceHeaderSet();
|
||
for (var i in deviceHeaders) { QH(i, deviceHeaders[i]); }
|
||
for (var i in deviceHeadersTitles) { Q(i).title = deviceHeadersTitles[i]; }
|
||
}
|
||
|
||
var powerStatetable = ['', "パワード", "睡眠", "睡眠", "睡眠", "冬眠", "電源を切る", "プレゼント"];
|
||
var powerStateStrings = ['', "パワード", "睡眠", "睡眠", "深い眠り", "冬眠", "ソフトオフ", "プレゼント"];
|
||
var powerStateStrings2 = ['', "デバイスに電源が入っています", "デバイスはスリープ状態です(S1)", "デバイスはスリープ状態です(S2)", "デバイスはディープスリープ状態です(S3)", "デバイスは休止状態です(S4)", "デバイスはソフトオフ状態です(S5)", "デバイスは存在しますが、電源状態を判別できません"];
|
||
var powerColorTable = ['#00000000', 'black', 'blue', 'blue', 'lightblue', 'blueviolet', 'darkgreen', 'lightseagreen', 'lightseagreen'];
|
||
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>' + "エージェント" + '</span>'); }
|
||
if ((node.conn & 2) != 0) { states.push('<span>' + "CIRA" + '</span>'); }
|
||
else if ((node.conn & 4) != 0) { states.push('<span>' + "Intel&reg; AMT" + '</span>'); }
|
||
if ((node.conn & 8) != 0) { states.push('<span>' + "リレー" + '</span>'); }
|
||
if ((node.conn & 16) != 0) { states.push('<span>' + "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 "未知の";
|
||
}
|
||
|
||
function onSortSelectChange(skipsave) {
|
||
sort = document.getElementById('sortselect').selectedIndex;
|
||
if (!skipsave) { putstore('sort', sort); }
|
||
updateDevicesEx();
|
||
}
|
||
|
||
function deviceHeaderSet() {
|
||
if (deviceHeaderId == 0) { deviceHeaderId = 1; return; }
|
||
deviceHeaders['DevxHeader' + deviceHeaderId] = ', ' + deviceHeaderTotal + ((deviceHeaderTotal == 1) ? " ノード" : " ノード");
|
||
var title = '';
|
||
for (var x in deviceHeaderCount) { if (title.length > 0) title += ', '; title += deviceHeaderCount[x] + ' ' + PowerStateStr2(x); }
|
||
deviceHeadersTitles['DevxHeader' + deviceHeaderId] = title;
|
||
deviceHeaderId++;
|
||
deviceHeaderCount = {};
|
||
deviceHeaderTotal = 0;
|
||
}
|
||
|
||
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) { 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; } } if (ap > bp) return 1; if (ap < bp) return -1; 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; }
|
||
|
||
//
|
||
// 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 currentDevicePanel = 0;
|
||
var currentNode;
|
||
var powerTimelineNode = null;
|
||
var powerTimelineReq = null;
|
||
var powerTimelineUpdate = null;
|
||
var powerTimeline = null;
|
||
function getCurrentNode() { return currentNode; };
|
||
function gotoDevice(nodeid, panel, refresh) {
|
||
|
||
// Remind the user to verify the email address
|
||
if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "アカウントのセキュリティ", 1, null, "メールアドレスが確認されるまでデバイスにアクセスできません。これはパスワードの回復に必要です。 「マイアカウント」に移動して、メールアドレスを変更および確認します。"); return; }
|
||
|
||
// Remind the user to add two factor authentication
|
||
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0))) { setDialogMode(2, "アカウントのセキュリティ", 1, null, "二要素認証が有効になるまでデバイスにアクセスできません。これは、追加のセキュリティのために必要です。 「マイアカウント」に移動して、「アカウントセキュリティ」セクションを確認します。"); return; }
|
||
|
||
var node = getNodeFromId(nodeid);
|
||
if (node == null) { goBack(); return; }
|
||
var mesh = meshes[node.meshid];
|
||
if (mesh == null) { goBack(); return; }
|
||
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>' + "なし" + '</i>'; }
|
||
if ((meshrights & 4) != 0) { nname = '<span onclick=showEditNodeValueDialog(0) style=cursor:pointer>' + nname + '</span>'; }
|
||
QH('p10deviceName', nname);
|
||
|
||
// Node attributes
|
||
var x = '<table style=width:100%>';
|
||
|
||
// Attribute: Mesh
|
||
x += addDeviceAttribute('<span>' + "グループ" + '</span>', '<a onclick=goForward("' + node.meshid + '") style=cursor:pointer>' + EscapeHtml(meshes[node.meshid].name) + '</a>');
|
||
|
||
// Attribute: Name
|
||
if (node.rname != null) { x += addDeviceAttribute('<span>' + "名" + '</span>', '<span>' + EscapeHtml(node.rname) + '</span>'); }
|
||
|
||
// Attribute: Host
|
||
if ((mesh.mtype == 1) || (node.name != node.host)) {
|
||
if ((meshrights & 4) != 0) {
|
||
if (node.host) {
|
||
x += addDeviceAttribute("ホスト名", '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer>' + EscapeHtml(node.host) + '</span>');
|
||
} else {
|
||
x += addDeviceAttribute("ホスト名", '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer><i>' + "なし" + '</i></span>');
|
||
}
|
||
} else {
|
||
x += addDeviceAttribute("ホスト名", EscapeHtml(node.host));
|
||
}
|
||
}
|
||
|
||
// Attribute: Description
|
||
var description = node.desc ? EscapeHtml(node.desc) : '<i>' + "なし" + '</i>';
|
||
if ((meshrights & 4) != 0) {
|
||
x += addDeviceAttribute("説明", '<span onclick=showEditNodeValueDialog(2) style=cursor:pointer>' + description + '</span>');
|
||
} else {
|
||
x += addDeviceAttribute("説明", description);
|
||
}
|
||
|
||
// Attribute: Mesh Agent
|
||
var agentsStr = ["未知の", "Windows 32ビットコンソール", "Windows 64ビットコンソール", "Windows 32ビットサービス", "Windows 64ビットサービス", "Linux 32ビット", "Linux 64ビット", "MIPS", "XENx86", "Android ARM", "Linux ARM", "MacOS 32ビット", "Android x86", "PogoPlug ARM", "Android APK", "Linux Poky x86-32bit", "MacOS 64ビット", "ChromeOS", "Linux Poky x86-64bit", "Linux NoKVM x86-32bit", "Linux NoKVM x86-64ビット", "Windows MinCoreコンソール", "Windows MinCoreサービス", "NodeJS", "ARM-リナロ", "ARMv6l / ARMv7l", "ARMv8 64ビット", "ARMv6l / ARMv7l / NoKVM", "未知の", "未知の", "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("エージェント", str);
|
||
}
|
||
|
||
// Attribute: Intel AMT
|
||
if (node.intelamt != null) {
|
||
var str = '';
|
||
var provisioningStates = { 0: nobreak("アクティブ化されていない(前)"), 1: nobreak("アクティブ化されていない(イン)"), 2: nobreak("有効化") };
|
||
if (node.intelamt.ver != null && node.intelamt.state == null) { str += '<i>' + nobreak("不明な状態") + '</i>, v' + node.intelamt.ver; } else
|
||
|
||
if ((node.intelamt.ver == null) && (node.intelamt.state == 2)) { str += '<i>' + "有効化" + '</i>'; }
|
||
else if ((node.intelamt.ver == null) || (node.intelamt.state == null)) { str += '<i>' + "不明なバージョンと状態" + '</i>'; }
|
||
else {
|
||
str += provisioningStates[node.intelamt.state];
|
||
if (node.intelamt.flags) { if (node.intelamt.flags & 2) { str = ' <span>' + "CCM" + '</span>'; } else if (node.intelamt.flags & 4) { str = ' <span>' + "ACM" + '</span>'; } }
|
||
str += (', v' + node.intelamt.ver);
|
||
}
|
||
|
||
if (node.intelamt.tls == 1) { str += ', <span>' + "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 onclick=editDeviceAmtSettings("' + node._id + '")>' + nobreak("資格情報なし") + '</i>';
|
||
} else {
|
||
str += ', <i style=color:#FF0000>' + "資格情報なし" + '</i>';
|
||
}
|
||
}
|
||
str += ' ';
|
||
if ((meshrights & 4) != 0) {
|
||
str += '<img src=images/link4.png height=10 width=10 style=cursor:pointer onclick=editDeviceAmtSettings("' + node._id + '")>';
|
||
}
|
||
}
|
||
|
||
var meName = "Intel&reg;私";
|
||
if (typeof node.intelamt.sku == 'number') {
|
||
if ((node.intelamt.sku & 8) != 0) { meName = "Intel&reg; AMT"; }
|
||
else if ((node.intelamt.sku & 16) != 0) { meName = "Intel&reg; SM"; }
|
||
}
|
||
x += addDeviceAttribute(meName, str);
|
||
}
|
||
|
||
// Attribute: Mesh Agent Tag
|
||
if ((node.agent != null) && (node.agent.tag != null) && (node.agent.tag != 'mailto:')) {
|
||
var tag = EscapeHtml(node.agent.tag);
|
||
if (tag.startsWith('mailto:')) { tag = '<a href="' + tag + '">' + tag.substring(7) + '</a>'; }
|
||
x += addDeviceAttribute("エージェントタグ", tag);
|
||
}
|
||
|
||
// Attribute: Intel AMT
|
||
//if (node.intelamt && node.intelamt.user) { x += addDeviceAttribute('Intel® AMT', node.intelamt.user); }
|
||
|
||
// 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>' + "エージェント" + '</span>');
|
||
if ((node.conn & 2) != 0) cstate.push('<span>' + "Intel&reg; AMT CIRA" + '</span>');
|
||
else if ((node.conn & 4) != 0) cstate.push('<span>' + "Intel&reg; AMT" + '</span>');
|
||
if ((node.conn & 8) != 0) cstate.push('<span>' + "エージェントリレー" + '</span>');
|
||
if ((node.conn & 16) != 0) cstate.push('<span>' + "MQTT" + '</span>');
|
||
x += addDeviceAttribute("接続性", cstate.join(', '));
|
||
}
|
||
|
||
// Node tags
|
||
var groupingTags = '<i>' + "なし" + '</i>';
|
||
if (node.tags != null) { groupingTags = ''; for (var i in node.tags) { groupingTags += '<span style="background-color:lightgray;padding:3px;margin-right:4px;border-radius:5px">' + node.tags[i] + '</span>'; } }
|
||
if ((meshrights & 4) != 0) {
|
||
x += addDeviceAttribute("タグ", '<span onclick=showEditNodeValueDialog(3) style=cursor:pointer>' + groupingTags + '</span>');
|
||
} else {
|
||
x += addDeviceAttribute("タグ", 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=Actions onclick=deviceActionFunction() />'; }
|
||
//x += '<input type=button value=Notes onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponent(node._id) + '") />';
|
||
//if ((connectivity & 1) && (meshrights & 8) && (node.agent.id < 5)) { x += '<input type=button value=Toast onclick=deviceToastFunction() />'; }
|
||
QH('p10html', x);
|
||
|
||
// Show node last 7 days timeline
|
||
//drawDeviceTimeline();
|
||
setupFiles();
|
||
|
||
// Show bottom buttons
|
||
x = '<div style=float:right;font-size:x-small;margin-right:10px>';
|
||
if ((meshrights & 4) != 0) x += '<a style=cursor:pointer onclick=p10showDeleteNodeDialog("' + node._id + '")>' + "デバイスを削除" + '</a>';
|
||
x += '</div><div style=font-size:x-small>';
|
||
//if (mesh.mtype == 2) x += '<a style=cursor:pointer onclick=p10showNodeNetInfoDialog("' + node._id + '")>Interfaces</a> ';
|
||
//if (xxmap != null) x += '<a style=cursor:pointer onclick=p10showNodeLocationDialog("' + node._id + '")>Location</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 += ', '; } powerstate += '<span style=font-size:10px>' + "メッシュエージェント" + '</span>'; }
|
||
if ((connectivity & 2) != 0) { if (powerstate.length > 0) { powerstate += ', '; } powerstate += '<span style=font-size:10px>' + "Intel&reg;接続されたAMT" + '</span>'; }
|
||
else if ((connectivity & 4) != 0) { if (powerstate.length > 0) { powerstate += ', '; } powerstate += '<span style=font-size:10px>' + "Intel&reg; AMTが検出されました" + '</span>'; }
|
||
if ((connectivity & 16) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px>' + "MQTTチャネルが接続されました" + '</span>'; }
|
||
QH('MainComputerState', powerstate);
|
||
|
||
// Set the node icon
|
||
QH('MainComputerImage', '<div class="i' + node.icon + '"></div>');
|
||
|
||
// Request the power timeline
|
||
if ((powerTimelineNode != currentNode._id) && (powerTimelineReq != currentNode._id)) { QH('p10html2', ''); powerTimelineReq = currentNode._id; meshserver.send({ action: 'powertimeline', nodeid: currentNode._id }); }
|
||
}
|
||
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);
|
||
|
||
// Update the footer menu
|
||
setupDeviceMenu();
|
||
}
|
||
|
||
function deviceToastFunction() {
|
||
if (xxdialogMode) return;
|
||
setDialogMode(2, "デバイストースト", 3, deviceToastFunctionEx, '<textarea id=d2devToast style=width:100%;height:80px;resize:none;overflow-y:scroll></textarea>');
|
||
}
|
||
|
||
function deviceToastFunctionEx() {
|
||
meshserver.send({ action: 'toast', nodeids: [currentNode._id], title: 'MeshCentral', msg: Q('d2devToast').value });
|
||
}
|
||
|
||
function setupDeviceMenu(op, obj) {
|
||
var meshrights = 0;
|
||
if (currentNode) { meshrights = meshes[currentNode.meshid].links[userinfo._id].rights; }
|
||
if (op != null) { currentDevicePanel = op; }
|
||
QV('p10general', currentDevicePanel == 0);
|
||
QV('p10desktop', currentDevicePanel == 1); // Show if we have remote control rights or desktop view only rights
|
||
QV('p10files', currentDevicePanel == 2);
|
||
var menus = [];
|
||
if (currentDevicePanel != 0) { menus.push({ n: 'General', f: 'setupDeviceMenu(0)' }); }
|
||
if ((currentDevicePanel != 1) &&
|
||
(currentNode != null) &&
|
||
((meshrights & 8) || (meshrights & 256)) &&
|
||
(((meshes[currentNode.meshid].mtype == 1) && ((typeof currentNode.intelamt.sku !== 'number') || ((currentNode.intelamt.sku & 8) != 0))) || (currentNode.agent && (currentNode.agent.caps & 1)))
|
||
) { menus.push({ n: 'Desktop', f: 'setupDeviceMenu(1)' }); }
|
||
if ((currentDevicePanel != 2) && (currentNode != null) && (meshrights & 8) && ((meshrights == 0xFFFFFFFF) || ((meshrights & 1024) == 0)) && ((currentNode.mtype == 2) && (currentNode.agent.caps & 4))) { menus.push({ n: 'Files', f: 'setupDeviceMenu(2)' }); }
|
||
updateFooterMenu(menus);
|
||
}
|
||
|
||
function deviceActionFunction() {
|
||
if (xxdialogMode) return;
|
||
var meshrights = meshes[currentNode.meshid].links[userinfo._id].rights;
|
||
var x = "このデバイスで実行する操作を選択します。" + '<br /><br />';
|
||
var y = '<select id=d2deviceop style=float:right;width:170px>';
|
||
if ((meshrights & 64) != 0) { y += '<option value=100>' + "目を覚ます" + '</option>'; } // Wake-up permission
|
||
if ((meshrights & 8) != 0) { y += '<option value=4>' + "睡眠" + '</option><option value=3>' + "リセットする" + '</option><option value=2>' + "電源を切る" + '</option>'; } // Remote control permission
|
||
y += '</select>';
|
||
x += addHtmlValue("操作", y);
|
||
setDialogMode(2, "デバイスアクション", 3, deviceActionFunctionEx, x);
|
||
}
|
||
|
||
function deviceActionFunctionEx() {
|
||
var op = Q('d2deviceop').value;
|
||
if (op == 100) {
|
||
// Device wake
|
||
meshserver.send({ action: 'wakedevices', nodeids: [currentNode._id] });
|
||
} else {
|
||
// Power operation
|
||
meshserver.send({ action: 'poweraction', nodeids: [currentNode._id], actiontype: op });
|
||
}
|
||
}
|
||
|
||
// 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 }); }
|
||
}
|
||
|
||
// Draw device power bars. The bars are 766px wide.
|
||
function drawDeviceTimeline() {
|
||
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 - (90 + 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) { datavalue += '<div 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('p10html2', '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse;width:calc(100% - 18px);margin:9px" border=0 cellpadding=2 cellspacing=0><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:center;width:90px>Day</th><th scope=col style=text-align:center>Power State</th></tr>' + x + '</tbody></table>');
|
||
}
|
||
|
||
// Return a color for the given power state
|
||
function powerColor(x) { if (x < powerColorTable.length) { return powerColorTable[x]; } return 'yellow'; }
|
||
|
||
// 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 style=width:100px;color:gray>' + name + '</td><td style=overflow:hidden>' + value + '</td></tr>';
|
||
}
|
||
|
||
function editDeviceAmtSettings(nodeid, func) {
|
||
if (xxdialogMode) return;
|
||
var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid);
|
||
if ((meshrights & 4) == 0) return;
|
||
x += addHtmlValue("ユーザー名", '<input id=dp10username style=width:170px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
|
||
x += addHtmlValue("パスワード", '<input id=dp10password type=password style=width:170px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
|
||
x += addHtmlValue("セキュリティ", '<select id=dp10tls style=width:176px><option value=0>' + "TLSセキュリティなし" + '</option><option value=1>' + "TLSセキュリティが必要" + '</option></select>');
|
||
if ((node.intelamt.user != null) && (node.intelamt.user != '')) { buttons = 7; }
|
||
setDialogMode(2, "Intelを編集&reg; AMTクレデンシャル", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func });
|
||
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(tag.func, 300); }
|
||
}
|
||
}
|
||
|
||
function p10showDeleteNodeDialog(nodeid) {
|
||
if (xxdialogMode) return;
|
||
setDialogMode(2, "ノードを削除", 3, p10showDeleteNodeDialogEx, format("{0}を削除しますか?", EscapeHtml(currentNode.name)) + '<br /><br /><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "確認する", nodeid);
|
||
p10validateDeleteNodeDialog();
|
||
}
|
||
|
||
function p10validateDeleteNodeDialog() {
|
||
QE('idx_dlgOkButton', Q('p10check').checked);
|
||
}
|
||
|
||
function p10showDeleteNodeDialogEx(buttons, nodeid) {
|
||
meshserver.send({ action: 'removedevices', nodeids: [nodeid] });
|
||
}
|
||
|
||
function p10showiconselector() {
|
||
if (xxdialogMode) return;
|
||
var mesh = meshes[currentNode.meshid];
|
||
var meshrights = mesh.links[userinfo._id].rights;
|
||
if ((meshrights & 4) == 0) return;
|
||
|
||
var x = '<table align=center><td>';
|
||
x += '<div style=display:inline-block class=i1 onclick=p10setIcon(1)></div>';
|
||
x += '<div style=display:inline-block class=i2 onclick=p10setIcon(2)></div>';
|
||
x += '<div style=display:inline-block class=i3 onclick=p10setIcon(3)></div><br>';
|
||
x += '<div style=display:inline-block class=i4 onclick=p10setIcon(4)></div>';
|
||
x += '<div style=display:inline-block class=i5 onclick=p10setIcon(5)></div>';
|
||
x += '<div style=display:inline-block class=i6 onclick=p10setIcon(6)></div></table>';
|
||
setDialogMode(2, "アイコンの選択", 0, null, x);
|
||
QV('id_dialogclose', true);
|
||
}
|
||
|
||
function p10setIcon(icon) {
|
||
setDialogMode(0);
|
||
meshserver.send({ action: 'changedevice', nodeid: currentNode._id, icon: icon });
|
||
}
|
||
|
||
var showEditNodeValueDialog_modes = ["装置名", "ホスト名", "説明", "タグ"];
|
||
var showEditNodeValueDialog_modes2 = ['name', 'host', 'desc', 'tags'];
|
||
var showEditNodeValueDialog_modes3 = ['', '', '', "Group1、Group2、Group3"];
|
||
function showEditNodeValueDialog(mode) {
|
||
if (xxdialogMode) return;
|
||
var x = addHtmlValue(showEditNodeValueDialog_modes[mode], '<input id=dp10devicevalue style=width:170px maxlength=64 placeholder="' + showEditNodeValueDialog_modes3[mode] + '" onchange=p10editdevicevalueValidate(' + mode + ',event) onkeyup=p10editdevicevalueValidate(' + mode + ',event) />');
|
||
setDialogMode(2, "デバイスを編集", 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 desktop;
|
||
var desktopNode;
|
||
var desktopsettings = { encoding: 2, showfocus: false, showmouse: true, showcad: true, quality: 40, scaling: 1024, framerate: 50 };
|
||
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)) {
|
||
// Device is not already connected, just setup a blank canvas
|
||
QH('DeskParent', '<canvas id=Desk width=640 height=200 style="width:100%;-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></canvas>');
|
||
desktopNode = currentNode;
|
||
// 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();
|
||
|
||
// 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('disconnectbutton1', (deskState != 0));
|
||
QV('connectbutton1', (deskState == 0) && (mesh.mtype == 2) && ((meshrights & 8) || (meshrights & 256)));
|
||
QV('connectbutton1h',
|
||
(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', (mesh.mtype == 2) && ((deskState == false) || (desktop.contype == 1)));
|
||
|
||
// Enable buttons
|
||
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('DeskCAD', meshrights & 8);
|
||
//QE('DeskCAD', deskState == 3);
|
||
//QV('DeskWD', (currentNode.agent) && (currentNode.agent.id < 5));
|
||
//QE('DeskWD', deskState == 3);
|
||
//QV('deskkeys', (currentNode.agent) && (currentNode.agent.id < 5));
|
||
//QE('deskkeys', deskState == 3);
|
||
//QE('DeskToolsButton', online);
|
||
QV('DeskToastButton', ((meshrights & 16384) != 0) && (currentNode.agent) && (currentNode.agent.id < 5) && (meshrights & 8));
|
||
//QE('DeskToastButton', online);
|
||
QV('deskActionsBtn', meshrights & 8);
|
||
Q('DeskControl').checked = ((meshrights & 8) != 0);
|
||
if (online == false) QV('DeskTools', false);
|
||
}
|
||
|
||
function connectDesktop(e, contype) {
|
||
setSessionActivity();
|
||
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); 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.showmouse = desktopsettings.showmouse;
|
||
desktop.m.onScreenSizeChange = deskAdjust;
|
||
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.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();
|
||
desktopNode = desktop = null;
|
||
}
|
||
}
|
||
|
||
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('termdisplays', false);
|
||
if (fullscreen == true) { deskToggleFull(); }
|
||
break;
|
||
case 2:
|
||
break;
|
||
default:
|
||
//console.log('Unknown onDesktopStateChange state', state);
|
||
break;
|
||
}
|
||
updateDesktopButtons();
|
||
deskAdjust();
|
||
setTimeout(deskAdjust, 50);
|
||
}
|
||
|
||
function showDesktopSettings() {
|
||
if (xxdialogMode) return;
|
||
applyDesktopSettings();
|
||
updateDesktopButtons();
|
||
setDialogMode(7, "リモートデスクトップ設定", 3, showDesktopSettingsChanged);
|
||
}
|
||
|
||
function showDesktopSettingsChanged() {
|
||
desktopsettings.encoding = d7desktopmode.value;
|
||
desktopsettings.showfocus = d7showfocus.checked;
|
||
desktopsettings.showmouse = d7showcursor.checked;
|
||
desktopsettings.quality = d7bitmapquality.value;
|
||
desktopsettings.scaling = d7bitmapscaling.value;
|
||
desktopsettings.framerate = d7framelimiter.value;
|
||
localStorage.setItem('desktopsettings', JSON.stringify(desktopsettings));
|
||
applyDesktopSettings();
|
||
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 (desktop.State != 0) { desktop.Stop(); setTimeout(function () { connectDesktop(null, 2); }, 50); }
|
||
}
|
||
}
|
||
}
|
||
|
||
function applyDesktopSettings() {
|
||
var r = '', ops = (features & 512) ? [90, 70, 50, 40, 30, 20, 10, 5, 1] : [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; }
|
||
}
|
||
|
||
var fullscreen = false;
|
||
/*
|
||
function deskToggleFull() {
|
||
fullscreen = !fullscreen;
|
||
QV('mastheadx', !fullscreen);
|
||
QV('masthead', !fullscreen);
|
||
QV('topbar', !fullscreen);
|
||
QV('p11deviceNameHeader', !fullscreen);
|
||
QV('footer', !fullscreen);
|
||
QV('column_l_bottomgap', !fullscreen);
|
||
QV('idx_deskFullBtn2', fullscreen);
|
||
QV('deskFullBtn', !fullscreen);
|
||
if (fullscreen) {
|
||
QS('container').width = '100%';
|
||
QS('container')['border-right'] = '0';
|
||
QS('container')['border-left'] = '0';
|
||
QS('column_l').padding = '0';
|
||
QS('column_l').width = '100%';
|
||
} else {
|
||
QS('container').width = '960px';
|
||
QS('container')['border-right'] = '1px solid #b7b7b7';
|
||
QS('container')['border-left'] = '1px solid #b7b7b7';
|
||
QS('column_l').padding = '0 15px';
|
||
QS('column_l').width = '930px';
|
||
toggleFullScreen();
|
||
}
|
||
deskAdjust();
|
||
}
|
||
*/
|
||
|
||
function deskAdjust() {
|
||
var x = (Q('DeskParent').clientHeight - Q('Desk').clientHeight) / 2;
|
||
if (x < 0) {
|
||
var mh = Q('DeskParent').clientHeight, mw = 9999;
|
||
if (desktop) { mw = (desktop.m.width / desktop.m.height) * mh; }
|
||
QS('Desk')['max-height'] = mh + 'px';
|
||
QS('Desk')['max-width'] = mw + 'px';
|
||
x = 0;
|
||
} else {
|
||
QS('Desk')['max-height'] = null;
|
||
QS('Desk')['max-width'] = null;
|
||
}
|
||
QS('Desk')['margin-top'] = x + 'px';
|
||
QS('Desk')['margin-bottom'] = x + 'px';
|
||
}
|
||
|
||
// 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) { // TAB
|
||
if (desktop.contype == 2) {
|
||
desktop.m.sendkey([[0xff09, 1], [0xff09, 0]]); // Intel AMT: 'TAB' press, 'TAB' release
|
||
} else {
|
||
desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.DOWN, 9], [desktop.m.KeyAction.UP, 9]]); // MeshAgent: 'TAB' press, 'TAB' release
|
||
}
|
||
}
|
||
}
|
||
|
||
function sendSpecialKeys() {
|
||
if (xxdialogMode || desktop == null || desktop.State != 3) return;
|
||
setDialogMode(3, "特別なキー", 3, deskSendKeys);
|
||
}
|
||
|
||
// Send CTRL-ALT-DEL
|
||
/*
|
||
function sendCAD() {
|
||
if (xxdialogMode || desktop == null || desktop.State != 3) return;
|
||
desktop.m.sendcad();
|
||
}
|
||
*/
|
||
|
||
// Toggle soft keyboard
|
||
function toggleSoftKeys(x) {
|
||
QV('DeskSoftInput', x == 1);
|
||
if (x == 1) { Q('DeskSoftInput').focus(); }
|
||
}
|
||
|
||
// Show process dialogs
|
||
function toggleDeskTools() {
|
||
setSessionActivity();
|
||
if (xxdialogMode) return;
|
||
if (QS('DeskTools').display == 'none') {
|
||
QV('DeskTools', true);
|
||
Q('DeskTools').nodeid = currentNode._id;
|
||
refreshDeskTools();
|
||
} else {
|
||
QV('DeskTools', false);
|
||
}
|
||
}
|
||
|
||
// Refresh all of the desktop tool panels
|
||
function refreshDeskTools() {
|
||
setSessionActivity();
|
||
QV('DeskToolsRefreshButton', false);
|
||
setTimeout(refreshDeskToolsEx, 500);
|
||
meshserver.send({ action: 'msg', type: 'ps', nodeid: currentNode._id });
|
||
}
|
||
function refreshDeskToolsEx() { QV('DeskToolsRefreshButton', true); }
|
||
var deskTools = { sort: 1, msg: null };
|
||
function sortProcess(sort) { deskTools.sort = sort; showDeskToolsProcesses(deskTools.msg); }
|
||
function sortProcessPid(a, b) { if (a.p > b.p) return 1; if (a.p < b.p) return (-1); return 0; }
|
||
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) { }
|
||
console.log(processes);
|
||
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) { x += '<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>' + p[i].p + '</div><a style=float:right;padding-right:5px;cursor:pointer onclick=stopProcess(' + p[i].p + ',"' + p[i].c + '")><img width=10 height=10 src="images/trash.png"></a><div style=float:right;padding-right:5px>' + (p[i].u ? p[i].u : '') + '</div><div>' + p[i].c + '</div></div>'; } }
|
||
QH('DeskToolsProcesses', x);
|
||
}
|
||
}
|
||
|
||
// Save the desktop image to file
|
||
function deskSaveImage() {
|
||
setSessionActivity();
|
||
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, info, selDisplay, selItem) {
|
||
var txt = Q('termdisplays').value;
|
||
if (info.length > 0) { var options = ''; for (var x in info) { options += '<option' + ((txt == info[x]) ? ' selected' : '') + '>' + info[x] + '</option>'; } QH('termdisplays', options); }
|
||
QV('termdisplays', info.length > 0);
|
||
}
|
||
|
||
function deskGetDisplayNumbers(e) { desktop.m.GetDisplayNumbers(); }
|
||
|
||
function deskSetDisplay(e) {
|
||
setSessionActivity();
|
||
var display = 0, txt = Q('termdisplays').value;
|
||
if (txt == "すべてのディスプレイ") display = 65535; else display = parseInt(txt.substring(8));
|
||
desktop.m.SetDisplay(display);
|
||
}
|
||
|
||
function dmousedown(e) { setSessionActivity(); if ((!xxdialogMode && desktop != null)) desktop.m.mousedown(e) }
|
||
function dmouseup(e) { setSessionActivity(); if ((!xxdialogMode && desktop != null)) desktop.m.mouseup(e) }
|
||
function dmousemove(e) { setSessionActivity(); if ((!xxdialogMode && desktop != null)) desktop.m.mousemove(e) }
|
||
function dmousewheel(e) { setSessionActivity(); if ((!xxdialogMode && desktop != null) && 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, "プロセス制御", 3, stopProcessEx, format("プロセス#{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); }
|
||
|
||
//
|
||
// 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) {
|
||
setSessionActivity();
|
||
p13Connect.value = (state == 0) ? "つなぐ" : "切断する";
|
||
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);
|
||
p13setActions();
|
||
if (files != null) { files.Stop(); files = null; }
|
||
break;
|
||
case 3:
|
||
p13targetpath = '';
|
||
files.sendText({ action: 'ls', reqid: 1, path: '' });
|
||
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) {
|
||
if (!files) {
|
||
// Setup a mesh agent files
|
||
files = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotFiles), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
|
||
files.attemptWebRTC = attemptWebRTC;
|
||
files.onStateChanged = onFilesStateChange;
|
||
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) {
|
||
setSessionActivity();
|
||
//console.log('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 style=cursor:pointer onclick=p13folderup(0)>' + "ルート" + '</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 style=cursor:pointer onclick=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 = EscapeHtml(name.substring(0, 70)) + "..."; } 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 right = '';
|
||
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>' + right + '</span><span><div class=fileIcon' + f.t + '></div><a style=cursor:pointer onclick=p13folderset(\"' + encodeURIComponent(f.nx) + '\")>' + shortname + '</a></span></div>';
|
||
} else {
|
||
var link = shortname;
|
||
if (f.s > 0) { link = '<a rel=\"noreferrer noopener\" target=\"_blank\" style=cursor:pointer onclick=\"p13downloadfile(\'' + encodeURIComponent(newlinkpath + '/' + name) + '\',\'' + encodeURIComponent(name) + '\',' + f.s + ')\">' + shortname + '</a>'; }
|
||
h = '<div class=filelist file=3><input file=3 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'> <span style=float:right;padding-right:4px>' + 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 });
|
||
}
|
||
|
||
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('p13SelectAllButton', false);
|
||
Q('p13SelectAllButton').value = "すべて";
|
||
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('p13SelectAllButton', tc > 0);
|
||
Q('p13SelectAllButton').value = (cc > 0 ? "なし" : "すべて");
|
||
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, "新しいフォルダ", 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>' + "再帰削除" + '</label><br>' : '<input type=checkbox id=p13recdeleteinput style=\'display:none\'>'; setDialogMode(2, "削除する", 3, p13deletefileEx, (cc > 1) ? (format("選択したアイテム{0}を削除しますか?", cc) + rec) : ("選択したアイテムを削除しますか?" + 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, "リネーム", 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, "ファイルをアップロードする", 3, p13uploadFileEx, '<input type=file name=files id=p13uploadinput style=width:100% multiple=multiple onchange="updateUploadDialogOk(\'p13uploadinput\')" />'); updateUploadDialogOk('p13uploadinput'); }
|
||
function p13uploadFileEx() { p13doUploadFiles(Q('p13uploadinput').files); }
|
||
function p13viewfile() {
|
||
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("ファイルエディター", "編集できるのは200k未満のファイルのみです。"); }
|
||
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("{0}エントリのコピーをこの場所に確認しますか?", p13clipboard.length); } else { x = format("この場所への1つのエントリのコピーを確認しますか?"); }
|
||
} else {
|
||
if (p13clipboard.length > 1) { x = format("{0}エントリのこの場所への移動を確認しますか?", p13clipboard.length); } else { x = format("1エントリのこの場所への移動を確認しますか?"); }
|
||
}
|
||
}
|
||
setDialogMode(2, "ペースト", 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("コピー用に{0}エントリを保持しています" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "クリア" + '</a>.', p13clipboard.length);
|
||
} else {
|
||
x = format("コピー用に1つのエントリを保持" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "クリア" + '</a>.');
|
||
}
|
||
} else {
|
||
if (p13clipboard.length > 1) {
|
||
x = format("移動のために{0}エントリを保持しています" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "クリア" + '</a>.', p13clipboard.length);
|
||
} else {
|
||
x = format("移動のために1つのエントリを保持" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "クリア" + '</a>.');
|
||
}
|
||
}
|
||
}
|
||
QH('p13bottomstatus', x);
|
||
p13setActions();
|
||
}
|
||
function p13clearClip() { p13clipboard = null; p13clipboardFolder = null; p13clipboardCut = 0; p13updateClipview(); return false; } function updateUploadDialogOk(x) { QE('idx_dlgOkButton', Q(x).value != ''); }
|
||
function getFileSelCount(includeDirs) { var cc = 0; var checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == "3"))) cc++; } return cc; }
|
||
function getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fc'); return checkboxes.length; }
|
||
|
||
//
|
||
// 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) {
|
||
if (xxdialogMode || downloadFile || !files) return;
|
||
downloadFile = { path: decodeURIComponent(x), file: decodeURIComponent(y), size: z, tsize: 0, data: '', state: 0, id: Math.random() }
|
||
//console.log('p13downloadFileCancel', downloadFile);
|
||
files.sendText({ action: 'download', sub: 'start', id: downloadFile.id, path: downloadFile.path });
|
||
setDialogMode(2, "ダウンロードファイル", 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
|
||
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
|
||
}
|
||
}
|
||
|
||
/*
|
||
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;
|
||
uploadFile = {};
|
||
uploadFile.xpath = p13filetreelocation.join('/');
|
||
uploadFile.xfiles = files;
|
||
uploadFile.xfilePtr = -1;
|
||
setDialogMode(2, "ファイルをアップロードする", 10, p13uploadFileCancel, '<div id=p13dfileName>' + "接続しています..." + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=0 />');
|
||
p13uploadReconnect();
|
||
}
|
||
|
||
function onFileUploadStateChange(xdownloadFile, state) {
|
||
switch (state) {
|
||
case 0:
|
||
p13folderup(9999);
|
||
break;
|
||
case 3:
|
||
p13uploadNextFile();
|
||
break;
|
||
default:
|
||
console.log('Unknown onFileUploadStateChange state', state);
|
||
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;
|
||
|
||
uploadFile.xreader = new FileReader();
|
||
uploadFile.xreader.onload = function () {
|
||
uploadFile.xdata = uploadFile.xreader.result;
|
||
uploadFile.ws.sendText({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength });
|
||
};
|
||
uploadFile.xreader.readAsArrayBuffer(file);
|
||
} 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;
|
||
}
|
||
}
|
||
|
||
//
|
||
// MY MESHS
|
||
//
|
||
|
||
var currentMesh;
|
||
function p20updateMesh() {
|
||
if (currentMesh == null) return;
|
||
QH('p20meshName', EscapeHtml(currentMesh.name));
|
||
var meshtype = format("不明な#{0}", currentMesh.mtype);
|
||
var meshrights = currentMesh.links[userinfo._id].rights;
|
||
if (currentMesh.mtype == 1) meshtype = "Intel&reg; AMTのみ、エージェントなし";
|
||
if (currentMesh.mtype == 2) meshtype = "ソフトウェアエージェントを使用して管理";
|
||
|
||
var x = '';
|
||
x += addHtmlValue("名", addLinkConditional(EscapeHtml(currentMesh.name), 'p20editmesh(1)', (meshrights & 1) != 0));
|
||
x += addHtmlValue("説明", addLinkConditional(((currentMesh.desc && currentMesh.desc != '') ? EscapeHtml(currentMesh.desc) : ('<i>' + "なし" + '</i>')), 'p20editmesh(2)', (meshrights & 1) != 0));
|
||
x += addHtmlValue("タイプ", meshtype);
|
||
//x += addHtmlValue('Identifier', currentMesh._id.split('/')[2]);
|
||
|
||
//x += '<br><input type=button value=Notes 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 += '<div style=margin-bottom:6px><a onclick=p20showAddMeshUserDialog() style=cursor:pointer><img src=images/icon-addnew.png border=0 height=12 width=12>' + " ユーザーを追加する" + '</a></div>'; }
|
||
|
||
/*
|
||
if ((meshrights & 4) != 0) {
|
||
if (currentMesh.mtype == 1) {
|
||
x += '<a onclick=addCiraDeviceToMesh(\"' + currentMesh._id + '\") style=cursor:pointer;margin-right:10px><img src=images/icon-installmesh.png border=0 height=12 width=12> Install CIRA</a>';
|
||
x += '<a onclick=addDeviceToMesh(\"' + currentMesh._id + '\") style=cursor:pointer;margin-right:10px><img src=images/icon-installmesh.png border=0 height=12 width=12> Install local</a>';
|
||
}
|
||
if (currentMesh.mtype == 2) {
|
||
x += '<a onclick=addAgentToMesh(\"' + currentMesh._id + '\") style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> Install</a>';
|
||
}
|
||
}
|
||
*/
|
||
|
||
/*
|
||
function getMeshActions(mesh, meshrights) {
|
||
if ((meshrights & 4) == 0) return '';
|
||
var r = '';
|
||
if (mesh.mtype == 1) {
|
||
r += ' <a style=cursor:pointer;font-size:10px onclick=addCiraDeviceToMesh(\"' + mesh._id + '\")>Add CIRA</a>';
|
||
r += ' <a style=cursor:pointer;font-size:10px onclick=addDeviceToMesh(\"' + mesh._id + '\")>Add Local</a>';
|
||
}
|
||
if (mesh.mtype == 2) {
|
||
r += ' <a style=cursor:pointer;font-size:10px onclick=addAgentToMesh(\"' + mesh._id + '\")>Add Agent</a>';
|
||
}
|
||
return r;
|
||
}
|
||
*/
|
||
|
||
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>' + "ユーザー認証" + '</th></tr>';
|
||
|
||
// Sort the users for this mesh
|
||
var count = 1, sortedusers = [];
|
||
for (var i in currentMesh.links) { sortedusers.push({ id: i, name: i.split('/')[2], 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 = "部分的権利", r = sortedusers[i].rights;
|
||
if (r == 0xFFFFFFFF) rights = "完全な管理者"; else if (r == 0) rights = "権利なし";
|
||
if ((i != userinfo._id) && (meshrights == 0xFFFFFFFF || (((meshrights & 2) != 0)))) { trash = '<a onclick=p20deleteUser(event,"' + encodeURIComponent(sortedusers[i].id) + '") style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'; }
|
||
x += '<tr onclick=p20viewuser("' + encodeURIComponent(sortedusers[i].id) + '") style=height:32px;cursor:pointer' + (((count % 2) == 0) ? ';background-color:#DDD' : '') + '><td>';
|
||
x += '<div style=float:right>' + trash + '</div><div style=float:right;padding-right:4px>' + rights + '</div><div class=m2></div><div> ' + EscapeHtml(decodeURIComponent(sortedusers[i].name)) + '<div></div></div>';
|
||
x += '</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:small;text-align:right;margin-top:6px><span><a onclick=p20showDeleteMeshDialog() style=cursor:pointer>' + "グループを削除" + '</a></span></div>'; }
|
||
|
||
QH('p20info', x);
|
||
}
|
||
|
||
function p20showDeleteMeshDialog() {
|
||
if (xxdialogMode) return false;
|
||
var x = format("グループ{0}を削除してもよろしいですか?デバイスグループを削除すると、このグループ内のデバイスに関するすべての情報も削除されます。", EscapeHtml(currentMesh.name)) + '<br /><br />';
|
||
x += '<label><input id=p20check type=checkbox onchange=p20validateDeleteMeshDialog() />' + "確認する" + '</label>';
|
||
setDialogMode(2, "グループを削除", 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("名", '<input id=dp20meshname style=width:170px maxlength=32 onchange=p20editmeshValidate() onkeyup=p20editmeshValidate() />');
|
||
x += addHtmlValue("説明", '<input id=dp20meshdesc style=width:170px maxlength=1024 onkeyup=p20editmeshValidate() />');
|
||
setDialogMode(2, "デバイスグループの編集", 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() {
|
||
QE('idx_dlgOkButton', Q('dp20meshname').value.length > 0);
|
||
}
|
||
|
||
function p20showAddMeshUserDialog() {
|
||
if (xxdialogMode) return;
|
||
var x = addHtmlValue('User', '<input id=dp20username style=width:170px maxlength=32 onchange=p20validateAddMeshUserDialog() onkeyup=p20validateAddMeshUserDialog() />');
|
||
x += '<div style="border:2px groove gray;background-color:white;max-height:120px;overflow-y:scroll">';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20fulladmin>' + "完全な管理者" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editmesh>' + "デバイスグループの編集" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20manageusers>' + "デバイスグループユーザーの管理" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20managecomputers>' + "デバイスグループコンピューターの管理" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotecontrol>' + "リモコン" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remoteview style=margin-left:12px>' + "リモートビューのみ" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotelimitedinput style=margin-left:12px>' + "限定入力のみ" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noterminal style=margin-left:12px>' + "ターミナルアクセスなし" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20nofiles style=margin-left:12px>' + "ファイルアクセスなし" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noamt style=margin-left:12px>' + "Intel&reg;なしAMT" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshagentconsole>' + "メッシュエージェントコンソール" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshserverfiles>' + "サーバーファイル" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20wakedevices>' + "ウェイクデバイス" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>' + "デバイスノートの編集" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20limitevents>' + "自分のイベントのみを表示" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20chatnotify>' + "チャットと通知" + '</label><br>';
|
||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20uninstall>' + "エージェントのアンインストール" + '</label><br>';
|
||
x += '</div>';
|
||
setDialogMode(2, "メッシュにユーザーを追加", 3, p20showAddMeshUserDialogEx, x);
|
||
p20validateAddMeshUserDialog();
|
||
Q('dp20username').focus();
|
||
}
|
||
|
||
function p20validateAddMeshUserDialog() {
|
||
var meshrights = currentMesh.links[userinfo._id].rights;
|
||
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() {
|
||
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;
|
||
}
|
||
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 });
|
||
}
|
||
|
||
function p20viewuser(userid) {
|
||
if (xxdialogMode) return;
|
||
userid = decodeURIComponent(userid);
|
||
var r = [], cmeshrights = currentMesh.links[userinfo._id].rights, meshrights = currentMesh.links[userid].rights;
|
||
if (meshrights == 0xFFFFFFFF) r.push("完全な管理者"); else {
|
||
if ((meshrights & 1) != 0) r.push("デバイスグループの編集");
|
||
if ((meshrights & 2) != 0) r.push("デバイスグループユーザーの管理");
|
||
if ((meshrights & 4) != 0) r.push("デバイスグループコンピューターの管理");
|
||
if ((meshrights & 8) != 0) r.push("リモコン");
|
||
if ((meshrights & 16) != 0) r.push("エージェントコンソール");
|
||
if ((meshrights & 32) != 0) r.push("サーバーファイル");
|
||
if ((meshrights & 64) != 0) r.push("ウェイクデバイス");
|
||
if ((meshrights & 128) != 0) r.push("メモを編集");
|
||
if ((meshrights & 256) != 0) r.push("リモートビューのみ");
|
||
if ((meshrights & 512) != 0) r.push("ターミナルなし");
|
||
if ((meshrights & 1024) != 0) r.push("ファイルなし");
|
||
if ((meshrights & 2048) != 0) r.push("Intel&reg;なしAMT");
|
||
if (((meshrights & 8) != 0) && ((meshrights & 4096) != 0) && ((meshrights & 256) == 0)) r.push("制限された入力");
|
||
if ((meshrights & 8192) != 0) r.push("自己イベントのみ");
|
||
if ((meshrights & 16384) != 0) r.push("チャットと通知");
|
||
if ((meshrights & 32768) != 0) r.push("アンインストール");
|
||
}
|
||
if (r.length == 0) { r.push("権利なし"); }
|
||
var buttons = 1, x = addHtmlValue("ユーザー", EscapeHtml(decodeURIComponent(userid.split('/')[2])));
|
||
x += addHtmlValue("許可", r.join("、"));
|
||
if (((userinfo._id) != userid) && (cmeshrights == 0xFFFFFFFF || (((cmeshrights & 2) != 0) && (meshrights != 0xFFFFFFFF)))) buttons += 4;
|
||
setDialogMode(2, "デバイスグループユーザー", buttons, p20viewuserEx, x, userid);
|
||
}
|
||
|
||
function p20viewuserEx(button, userid) { if (button != 2) return; setDialogMode(2, "リモートメッシュユーザー", 3, p20viewuserEx2, format("ユーザー{0}の削除を確認しますか?", userid.split('/')[2]), userid); }
|
||
function p20deleteUser(e, userid) { haltEvent(e); p20viewuserEx(2, decodeURIComponent(userid)); }
|
||
function p20viewuserEx2(button, userid) { meshserver.send({ action: 'removemeshuser', meshid: currentMesh._id, meshname: currentMesh.name, userid: userid }); }
|
||
|
||
//
|
||
// PANELS
|
||
//
|
||
|
||
var xxcurrentView = -1;
|
||
function go(x) {
|
||
setSessionActivity();
|
||
if (xxdialogMode || xxcurrentView == x) return;
|
||
updateFooterMenu();
|
||
setDialogMode(0);
|
||
// Edit this line when adding a new screen
|
||
for (var i = 0; i < 32; i++) { QV('p' + i, i == x); }
|
||
xxcurrentView = x;
|
||
}
|
||
|
||
//
|
||
// POPUP DIALOG
|
||
//
|
||
|
||
// undefined = Hidden, 1 = Generic Message
|
||
var xxdialogMode;
|
||
var xxdialogFunc;
|
||
var xxdialogButtons;
|
||
var xxdialogTag;
|
||
|
||
// 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();
|
||
xxdialogMode = x;
|
||
xxdialogFunc = f;
|
||
xxdialogButtons = b;
|
||
xxdialogTag = tag;
|
||
QE('idx_dlgOkButton', true);
|
||
QV('idx_dlgOkButton', b & 1);
|
||
QV('idx_dlgCancelButton', b & 2);
|
||
QV('id_dialogclose', (b & 2) || (b & 8));
|
||
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;
|
||
var b = xxdialogButtons;
|
||
var t = xxdialogTag;
|
||
setDialogMode();
|
||
if (((b & 8) || x) && f) f(x, t);
|
||
}
|
||
|
||
function putstore(name, val) { try { if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return; if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { } if (name[0] != '_') { var s = {}; for (var i = 0, len = localStorage.length; i < len; ++i) { var k = localStorage.key(i); if (k[0] != '_') { s[k] = localStorage.getItem(k); } } meshserver.send({ action: 'userWebState', state: JSON.stringify(s) }); } }
|
||
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 center() { QS('dialog').left = ((((getDocWidth() - 300) / 2)) + 'px'); deskAdjust(); deskAdjust(); /*drawDeviceTimeline();*/ }
|
||
function messagebox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
|
||
function statusbox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t); }
|
||
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 haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
|
||
function haltReturn(e) { if (e.keyCode == 13) { haltEvent(e); } }
|
||
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); }
|
||
function reload() { window.location.href = window.location.href; }
|
||
function getNodeFromId(id) { for (var i in nodes) { if (nodes[i]._id == id) return nodes[i]; } return null; }
|
||
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 addLink(x, f) { return '<a style=cursor:pointer;color:darkblue;text-decoration:none onclick=\'' + f + '\'>♦ ' + x + '</a>'; }
|
||
function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
|
||
function passwordcheck(p) { var re = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()]).{8,}/; return re.test(p); }
|
||
function getFileSizeStr(size) { if (size == 1) return "1バイト"; return format('{0} bytes', size); }
|
||
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 focusTextBox(x) { setTimeout(function () { Q(x).selectionStart = Q(x).selectionEnd = 65535; Q(x).focus(); }, 0); }
|
||
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 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 printDate(d) { return d.toLocaleDateString(args.locale); }
|
||
function printTime(d) { return d.toLocaleTimeString(args.locale); }
|
||
function printDateTime(d) { return d.toLocaleString(args.locale); }
|
||
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 nobreak(x) { return x.split(' ').join(' '); }
|
||
|
||
</script>
|
||
|
||
</body></html> |