Merge branch '16115-sharing-links'. Closes #16115
[arvados.git] / public / webshell / index.html
1 <!DOCTYPE html>
2     <head>
3     <title></title>
4     <link rel="stylesheet" href="styles.css" type="text/css">
5     <style type="text/css">
6       body {
7         margin: 0px;
8       }
9       #notoken {
10         position: absolute;
11         top: 0;
12         left: 0;
13         right: 0;
14         bottom: 0;
15         text-align: center;
16         vertical-align: middle;
17         line-height: 100vh;
18         z-index: 100;
19         font-family: sans;
20       }
21     </style>
22     <script type="text/javascript"><!--
23       (function() {
24         // We would like to hide overflowing lines as this can lead to
25         // visually jarring results if the browser substitutes oversized
26         // Unicode characters from different fonts. Unfortunately, a bug
27         // in Firefox prevents it from allowing multi-line text
28         // selections whenever we change the "overflow" style. So, only
29         // do so for non-Netscape browsers.
30         if (typeof navigator.appName == 'undefined' ||
31             navigator.appName != 'Netscape') {
32           document.write('<style type="text/css">' +
33                          '#vt100 #console div, #vt100 #alt_console div {' +
34                          '  overflow: hidden;' +
35                          '}' +
36                          '</style>');
37         }
38       })();
39       var sh;
40       var urlParams = new URLSearchParams(window.location.search);
41       var token = urlParams.get('token');
42       var user = urlParams.get('login');
43       var host = urlParams.get('host');
44       var timeout = urlParams.get('timeout');
45       urlParams = null;
46
47       var idleTimeoutMs = timeout * 1000;
48
49       function updateIdleTimer() {
50         var currentTime = Date.now();
51         var lastTime = localStorage.getItem('lastActiveTimestamp');
52         if (currentTime - lastTime > 1000) {
53           localStorage.setItem('lastActiveTimestamp', currentTime);
54         }
55       }
56
57       function checkIdleTimer() {
58         var currentTime = Date.now();
59         var lastTime = localStorage.getItem('lastActiveTimestamp');
60         if (currentTime - lastTime > idleTimeoutMs) {
61           //logout
62           sh.reset();
63           sh.sessionClosed("Session timed out after " + timeout + " seconds.");
64           document.body.onmousemove = undefined;
65           document.body.onkeydown = undefined;
66         } else {
67           setTimeout(checkIdleTimer, 1000);
68         }
69       }
70
71       function login() {
72         sh = new ShellInABox(host);
73
74         var findText = function(txt) {
75           var a = document.querySelectorAll("span.ansi0");
76           for (var i = 0; i < a.length; i++) {
77             if (a[i].textContent.indexOf(txt) > -1) {
78               return true;
79             }
80           }
81           return false;
82         }
83
84         var trySendToken = function() {
85           // change this text when PAM is reconfigured to present a
86           // password prompt that we can wait for.
87           if (findText("assword:")) {
88              sh.keysPressed(token + "\n");
89              sh.vt100('(sent authentication token)\n');
90              token = null;
91              if (timeout > 0) {
92                updateIdleTimer();
93                document.body.onmousemove = updateIdleTimer;
94                document.body.onkeydown = updateIdleTimer;
95                setTimeout(checkIdleTimer, 1000);
96              }
97           } else {
98             setTimeout(trySendToken, 200);
99           }
100         };
101
102         var trySendLogin = function() {
103           if (findText("login:")) {
104             sh.keysPressed(user + "\n");
105             // Make this wait shorter when PAM is reconfigured to
106             // present a password prompt that we can wait for.
107             setTimeout(trySendToken, 200);
108           } else {
109             setTimeout(trySendLogin, 200);
110           }
111         };
112
113         trySendLogin();
114       }
115
116       function init() {
117         if (token) {
118           history.replaceState(null, "", `/webshell/?host=${encodeURIComponent(host)}&timeout=${timeout}&login=${encodeURIComponent(user)}`);
119         } else if (localStorage.getItem('apiToken')) {
120           token = localStorage.getItem('apiToken');
121         } else {
122           document.getElementById("notoken").style.display = "block";
123           return;
124         }
125         login();
126       }
127     // -->
128 </script>
129     <script type="text/javascript" src="shell_in_a_box.js"></script>
130   </head>
131   <!-- Load ShellInABox from a timer as Konqueror sometimes fails to
132        correctly deal with the enclosing frameset (if any), if we do not
133        do this
134    -->
135 <body onload="setTimeout(init, 1000)"
136     scroll="no"><noscript>JavaScript must be enabled for ShellInABox</noscript>
137     <div id="notoken" style="display: none;">
138       Error: No token found. Please return to <a href="/virtual-machines-user">Virtual Machines</a> and try again.
139     </div>
140 </body>
141 </html>