Removed all files now part of other repos, moved default webapp source up
[guacamole.git] / src / main / webapp / index.html
1 <!DOCTYPE HTML>
2
3 <!--
4     Guacamole - Clientless Remote Desktop
5     Copyright (C) 2010  Michael Jumper
6
7     This program is free software: you can redistribute it and/or modify
8     it under the terms of the GNU Affero General Public License as published by
9     the Free Software Foundation, either version 3 of the License, or
10     (at your option) any later version.
11
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU Affero General Public License for more details.
16
17     You should have received a copy of the GNU Affero General Public License
18     along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 -->
20
21 <html>
22
23     <head>
24         <link rel="icon" type="image/png" href="images/guacamole-icon-64.png"/>
25         <link rel="stylesheet" type="text/css" href="guacamole.css"/>
26         <link rel="stylesheet" type="text/css" href="guac-web-lib/css/guacamole.css"/>
27         <link rel="stylesheet" type="text/css" href="keyboard.css"/>
28         <title>Guacamole</title>
29     </head>
30
31     <body>
32
33         <div id="login-ui">
34             <div id="login-dialog-middle">
35
36                 <div id="login-logo">
37                     <img src="images/login-logo.png" alt="\_GUAC_/"/>
38                 </div>
39
40                 <div id="login-dialog">
41
42                     <h1>Guacamole Login</h1>
43
44                     <p id="login-error"></p>
45
46                     <form id="login-form" action="login" method="post">
47                         <table id="login-fields">
48                             <tr>
49                                 <th>Username</th>
50                                 <td><input type="text" name="username" id="username"/></td>
51                             </tr>
52                             <tr>
53                                 <th>Password</th>
54                                 <td><input type="password" name="password" id="password"/></td>
55                             </tr>
56                         </table>
57
58                         <div id="buttons">
59                             <input type="submit" name="login" id="login" value="Login"/>
60                         </div>
61                     </form>
62                 </div>
63
64             </div>
65         </div>
66
67         <!-- Main UI - hidden until login succeeds -->
68         <div id="main-guacamole-ui" style="display: none">
69
70             <!-- Menu -->
71             <div id="menu">
72
73                 <!-- Clipboard -->
74                 <button id="showClipboard">Show Clipboard</button>
75                 <div id="clipboardDiv">
76                     <h2>Clipboard</h2>
77                     <p>
78                     Text copied/cut within Guacamole will appear here. Changes to the text will affect the remote clipboard, and will be pastable within the remote desktop. Use the textbox below as an interface between the client and server clipboards.
79                     </p>
80                     <textarea rows="10" cols="40" id="clipboard"></textarea>
81                 </div>
82
83                 <button id="showKeyboard">Show Keyboard</button>
84                 <button id="CtrlAltDelete">Ctrl-Alt-Delete</button>
85
86                 <!-- Logo and status -->
87                 <img id="logo" src="images/guacamole-logo.png" alt="Guacamole" title="__GUAC_VERSION"/>
88                 <span id="state"></span>
89
90                 <a href="agpl-3.0-standalone.html"><img id="license" src="images/agpl-logo.png" alt="AGPLv3"/></a>
91             </div>
92
93
94             <!-- Display -->
95             <div id="display" class="guac-display guac-loading">
96                 <!-- On-screen keyboard -->
97                 <div id="keyboardContainer"></div>
98             </div>
99
100
101             <!-- Error Dialog-->
102             <div id="errorDialog" class="errorDialogOuter">
103                 <div class="errorDialogMiddle">
104                     <div class="errorDialog">
105                         <h1>Error</h1>
106                         <p id="errorText"></p>
107                         <div class="buttons"><button id="reconnect">Reconnect</button></div>
108                     </div>
109                 </div>
110             </div>
111         </div>
112
113
114         <!-- Scripts -->
115         <script type="text/javascript" src="guac-web-lib/javascript/keymap.js"></script>
116         <script type="text/javascript" src="guac-web-lib/javascript/keyboard.js"></script>
117         <script type="text/javascript" src="guac-web-lib/javascript/mouse.js"></script>
118         <script type="text/javascript" src="guac-web-lib/javascript/layer.js"></script>
119         <script type="text/javascript" src="guac-web-lib/javascript/guacamole.js"></script>
120         <script type="text/javascript" src="guac-web-lib/javascript/oskeyboard.js"></script>
121
122         <!-- Init -->
123         <script type="text/javascript"> /* <![CDATA[ */
124
125             var loginForm = document.getElementById("login-form");
126             var loginUI = document.getElementById("login-ui");
127
128             loginForm.onsubmit = function() {
129
130                 var username = document.getElementById("username");
131                 var password = document.getElementById("password");
132
133                 var data =
134                        "username=" + encodeURIComponent(username.value)
135                     + "&password=" + encodeURIComponent(password.value)
136
137                 var xmlhttprequest = new XMLHttpRequest();
138                 xmlhttprequest.open("POST", "login", false);
139                 xmlhttprequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
140                 xmlhttprequest.setRequestHeader("Content-length", data.length);
141                 xmlhttprequest.send(data);
142
143                 if (xmlhttprequest.status == 200) {
144                     loginUI.style.display = "none";
145                     startGuacamole();
146                 }
147                 else {
148
149                     var loginError = document.getElementById("login-error");
150
151                     // Display error, reset and refocus password field
152                     loginError.textContent = "Invalid login. Please try again.";
153                     password.value = "";
154                     password.focus();
155
156                 }
157
158                 return false;
159
160             }
161
162             // Shows guacamole interface and initiates connection to guacamole
163             function startGuacamole() {
164
165                 document.getElementById("main-guacamole-ui").style.display = "block";
166
167                 var menu = document.getElementById("menu");
168                 var display = document.getElementById("display");
169                 var logo = document.getElementById("logo");
170
171                 var errorDialog = document.getElementById("errorDialog");
172                 var errorDialogText = document.getElementById("errorText");
173
174                 // Position display correctly
175                 window.onresize = function() {
176                     display.style.top = menu.offsetHeight + "px";
177                 };
178
179                 window.onresize();
180
181                 // Instantiate client
182                 var guac = new GuacamoleClient(display);
183
184                 var state = document.getElementById("state");
185                 guac.setOnStateChangeHandler(function(clientState) {
186
187                         switch (clientState) {
188                             case 0:
189                                 state.textContent = "Idle."
190                                 break;
191                             case 1:
192                                 state.textContent = "Connecting...";
193                                 break;
194                             case 2:
195                                 state.textContent = "Connected, waiting for first update...";
196                                 break;
197                             case 3:
198                                 display.className = display.className.replace(/guac-loading/, '');
199                                 menu.className = "connected";
200                                 state.textContent = "Connected.";
201                                 break;
202                             case 4:
203                                 state.textContent = "Disconnecting...";
204                                 break;
205                             case 5:
206                                 state.textContent = "Disconnected.";
207                                 break;
208                             default:
209                                 state.textContent = "Unknown";
210                         }
211                 });
212
213                 // Cache error image (might not be available when error occurs)
214                 var guacErrorImage = new Image();
215                 guacErrorImage.src = "images/noguacamole-logo.png";
216
217                 guac.setErrorHandler(function(error) {
218                     menu.className = "error";
219                     logo.src = guacErrorImage.src;
220                     errorDialogText.textContent = error;
221                     errorDialog.style.visibility = "visible";
222                 });
223
224                 // Reconnect button
225                 var reconnect = document.getElementById("reconnect");
226                 reconnect.onclick = function() {
227                     window.location.reload();
228                 };
229
230                 // Connect
231                 guac.connect();
232
233                 // Disconnect on close
234                 window.onunload = function() {
235                     guac.disconnect();
236                 }
237
238                 // Handle clipboard events
239                 var clipboardElement = document.getElementById("clipboard");
240                 clipboardElement.onchange = function() {
241
242                     var text = clipboardElement.value;
243                     guac.setClipboard(text);
244
245                 };
246
247                 // Ignore keypresses when clipboard is focused
248                 clipboardElement.onfocus = function() {
249                     guac.disableKeyboard();
250                 };
251
252                 // Capture keypresses when clipboard is not focused
253                 clipboardElement.onblur = function() {
254                     guac.enableKeyboard();
255                 };
256
257                 // Server copy handler
258                 guac.setClipboardHandler(
259                     function(data) {
260                         clipboardElement.value = data;
261                     }
262                 );
263
264
265                 // Show/Hide clipboard
266                 var clipboardDiv = document.getElementById("clipboardDiv");
267                 var showClipboard = document.getElementById("showClipboard");
268                 showClipboard.onclick = function() {
269
270                     var displayed = clipboardDiv.style.display;
271                     if (displayed != "block") {
272                         clipboardDiv.style.display = "block";
273                         showClipboard.innerHTML = "Hide Clipboard";
274                     }
275                     else {
276                         clipboardDiv.style.display = "none";
277                         showClipboard.innerHTML = "Show Clipboard";
278                         clipboardElement.onchange();
279                     }
280
281                 };
282
283
284                 // Show/Hide keyboard
285                 var keyboardContainer = document.getElementById("keyboardContainer");
286                 var showKeyboard = document.getElementById("showKeyboard");
287                 showKeyboard.onclick = function() {
288
289                     var displayed = keyboardContainer.style.display;
290                     if (displayed != "block") {
291                         keyboardContainer.style.display = "block";
292                         showKeyboard.textContent = "Hide Keyboard";
293                     }
294                     else {
295                         keyboardContainer.style.display = "none";
296                         showKeyboard.textContent = "Show Keyboard";
297                     }
298
299                 };
300
301                 // On-screen keyboard
302                 var osKeyboard = new GuacamoleOnScreenKeyboard("layouts/en-us-qwerty.xml");
303                 keyboardContainer.appendChild(osKeyboard);
304
305                 osKeyboard.setKeyPressedHandler(
306                         function(keysym) {
307                             guac.pressKey(keysym);
308                         }
309                 );
310
311                 osKeyboard.setKeyReleasedHandler(
312                         function(keysym) {
313                             guac.releaseKey(keysym);
314                         }
315                 );
316
317                 // Send Ctrl-Alt-Delete
318                 var CtrlAltDelete = document.getElementById("CtrlAltDelete");
319
320                 CtrlAltDelete.onclick = function() {
321                     guac.pressKey(KEYSYM_CTRL);
322                     guac.pressKey(KEYSYM_ALT);
323                     guac.pressKey(KEYSYM_DELETE);
324                     guac.releaseKey(KEYSYM_DELETE);
325                     guac.releaseKey(KEYSYM_ALT);
326                     guac.releaseKey(KEYSYM_CTRL);
327                 }
328
329             }
330
331             /* ]]> */ </script>
332
333     </body>
334
335 </html>