mirror of
https://github.com/OpenNebula/one.git
synced 2025-01-12 09:17:41 +03:00
Update noVNC master commit 75d69b9f621606c3b2db48e4778ff41307f65c6d
This commit is contained in:
parent
2cad5fc87c
commit
732528eef6
32
src/sunstone/public/vendor/noVNC/LICENSE.txt
vendored
32
src/sunstone/public/vendor/noVNC/LICENSE.txt
vendored
@ -1,7 +1,7 @@
|
||||
noVNC is Copyright (C) 2011 Joel Martin <github@martintribe.org>
|
||||
|
||||
The noVNC core library is licensed under the LGPLv3 (GNU Lesser
|
||||
General Public License). The noVNC core library is composed of the
|
||||
The noVNC core library files are licensed under the MPL 2.0 (Mozilla
|
||||
Public License 2.0). The noVNC core library is composed of the
|
||||
Javascript code necessary for full noVNC operation. This includes (but
|
||||
is not limited to):
|
||||
|
||||
@ -10,6 +10,7 @@ is not limited to):
|
||||
include/display.js
|
||||
include/input.js
|
||||
include/jsunzip.js
|
||||
include/keysym.js
|
||||
include/logo.js
|
||||
include/rfb.js
|
||||
include/ui.js
|
||||
@ -36,22 +37,16 @@ The HTML, CSS, font and image files are licensed as follows:
|
||||
images/ : Creative Commons Attribution-ShareAlike
|
||||
http://creativecommons.org/licenses/by-sa/3.0/
|
||||
|
||||
In addition the following file, which is part of the noVNC core
|
||||
library, may be licensed under either the LGPL-2, LGPL-3 or MPL 2.0
|
||||
when it used separately from the noVNC core library.
|
||||
|
||||
include/input.js : LGPL-2 or any later version
|
||||
|
||||
Some portions of noVNC are copyright to their individual authors.
|
||||
Please refer to the individual source files and/or to the noVNC commit
|
||||
history: https://github.com/kanaka/noVNC/commits/master
|
||||
|
||||
The are several files and projects that have been incorporated into
|
||||
the noVNC core library. Here is a list of those files and the original
|
||||
licenses (all LGPL-3 compatible):
|
||||
licenses (all MPL 2.0 compatible):
|
||||
|
||||
include/base64.js : MPL 2.0
|
||||
|
||||
include/base64.js : MPL 1.1, GPL-2 or LGPL-2.1
|
||||
|
||||
include/des.js : Various BSD style licenses
|
||||
|
||||
include/jsunzip.js : zlib/libpng license
|
||||
@ -59,20 +54,29 @@ licenses (all LGPL-3 compatible):
|
||||
include/web-socket-js/ : New BSD license (3-clause). Source code at
|
||||
http://github.com/gimite/web-socket-js
|
||||
|
||||
include/chrome-app/tcp-stream.js
|
||||
: Apache 2.0 license
|
||||
|
||||
utils/websockify
|
||||
utils/websocket.py : LGPL 3
|
||||
|
||||
The following license texts are included:
|
||||
|
||||
docs/LICENSE.MPL-2.0
|
||||
docs/LICENSE.LGPL-3 and
|
||||
docs/LICENSE.GPL-3
|
||||
docs/LICENSE.OFL-1.1
|
||||
docs/LICENSE.BSD-3-Clause (New BSD)
|
||||
docs/LICENSE.BSD-2-Clause (Simplified BSD / FreeBSD)
|
||||
docs/LICENSE.zlib
|
||||
docs/LICENSE.MPL-2.0
|
||||
docs/LICENSE.Apache-2.0
|
||||
|
||||
Or alternatively the license texts may be found here:
|
||||
|
||||
http://www.mozilla.org/MPL/2.0/
|
||||
http://www.gnu.org/licenses/lgpl.html and
|
||||
http://www.gnu.org/licenses/gpl.html
|
||||
http://scripts.sil.org/OFL
|
||||
http://www.mozilla.org/MPL/1.1/
|
||||
http://www.mozilla.org/MPL/2.0/
|
||||
http://en.wikipedia.org/wiki/BSD_licenses
|
||||
http://www.gzip.org/zlib/zlib_license.html
|
||||
http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
187
src/sunstone/public/vendor/noVNC/base.css
vendored
187
src/sunstone/public/vendor/noVNC/base.css
vendored
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* noVNC base CSS
|
||||
* Copyright (C) 2012 Joel Martin
|
||||
* noVNC is licensed under the LGPL-3 (see LICENSE.txt)
|
||||
* Copyright (C) 2013 Samuel Mannehed for Cendio AB
|
||||
* noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
|
||||
* This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
|
||||
*/
|
||||
|
||||
@ -51,7 +52,6 @@ html {
|
||||
float:right;
|
||||
}
|
||||
|
||||
|
||||
#noVNC_view_drag_button {
|
||||
display: none;
|
||||
}
|
||||
@ -62,34 +62,36 @@ html {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#noVNC_extra_keys {
|
||||
display: inline;
|
||||
list-style-type: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.noVNC-buttons-left {
|
||||
float: left;
|
||||
padding-left:10px;
|
||||
padding-top:4px;
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.noVNC-buttons-right {
|
||||
float:right;
|
||||
right: 0px;
|
||||
padding-right:10px;
|
||||
padding-top:4px;
|
||||
}
|
||||
|
||||
#noVNC_status_bar {
|
||||
margin-top: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#noVNC_status_bar div {
|
||||
font-size: 12px;
|
||||
padding-top: 4px;
|
||||
width:100%;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#noVNC_status {
|
||||
height:20px;
|
||||
font-size: 12px;
|
||||
padding-top: 4px;
|
||||
height:32px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#noVNC_settings_menu {
|
||||
margin: 3px;
|
||||
text-align: left;
|
||||
@ -104,22 +106,12 @@ html {
|
||||
float:right;
|
||||
}
|
||||
|
||||
.noVNC_status_normal {
|
||||
background: #eee;
|
||||
}
|
||||
.noVNC_status_error {
|
||||
background: #f44;
|
||||
}
|
||||
.noVNC_status_warn {
|
||||
background: #ff4;
|
||||
}
|
||||
|
||||
/* Do not set width/height for VNC_screen or VNC_canvas or incorrect
|
||||
* scaling will occur. Canvas resizes to remote VNC settings */
|
||||
#noVNC_screen_pad {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
height: 44px;
|
||||
height: 36px;
|
||||
}
|
||||
#noVNC_screen {
|
||||
text-align: center;
|
||||
@ -154,14 +146,14 @@ html {
|
||||
/*Bubble contents divs*/
|
||||
#noVNC_settings {
|
||||
display:none;
|
||||
margin-top:77px;
|
||||
margin-top:73px;
|
||||
right:20px;
|
||||
position:fixed;
|
||||
}
|
||||
|
||||
#noVNC_controls {
|
||||
display:none;
|
||||
margin-top:77px;
|
||||
margin-top:73px;
|
||||
right:12px;
|
||||
position:fixed;
|
||||
}
|
||||
@ -173,7 +165,7 @@ html {
|
||||
display:none;
|
||||
position:fixed;
|
||||
|
||||
margin-top:77px;
|
||||
margin-top:73px;
|
||||
right:20px;
|
||||
left:20px;
|
||||
padding:15px;
|
||||
@ -186,9 +178,30 @@ html {
|
||||
border-radius:10px;
|
||||
}
|
||||
|
||||
#noVNC_popup_status_panel {
|
||||
display:none;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
|
||||
margin:15px;
|
||||
margin-top:60px;
|
||||
padding:15px;
|
||||
width:auto;
|
||||
|
||||
text-align:center;
|
||||
font-weight:bold;
|
||||
word-wrap:break-word;
|
||||
color:#fff;
|
||||
background:rgba(0,0,0,0.65);
|
||||
|
||||
-webkit-border-radius:10px;
|
||||
-moz-border-radius:10px;
|
||||
border-radius:10px;
|
||||
}
|
||||
|
||||
#noVNC_clipboard {
|
||||
display:none;
|
||||
margin-top:77px;
|
||||
margin-top:73px;
|
||||
right:30px;
|
||||
position:fixed;
|
||||
}
|
||||
@ -207,17 +220,11 @@ html {
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.noVNC_status_warn {
|
||||
background-color:yellow;
|
||||
}
|
||||
|
||||
/*
|
||||
* Advanced Styling
|
||||
*/
|
||||
|
||||
/* Control bar */
|
||||
#noVNC-control-bar {
|
||||
position:fixed;
|
||||
.noVNC_status_normal {
|
||||
background: #b2bdcd; /* Old browsers */
|
||||
background: -moz-linear-gradient(top, #b2bdcd 0%, #899cb3 49%, #7e93af 51%, #6e84a3 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#b2bdcd), color-stop(49%,#899cb3), color-stop(51%,#7e93af), color-stop(100%,#6e84a3)); /* Chrome,Safari4+ */
|
||||
@ -225,9 +232,32 @@ html {
|
||||
background: -o-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Opera11.10+ */
|
||||
background: -ms-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* W3C */
|
||||
}
|
||||
.noVNC_status_error {
|
||||
background: #f04040; /* Old browsers */
|
||||
background: -moz-linear-gradient(top, #f04040 0%, #899cb3 49%, #7e93af 51%, #6e84a3 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f04040), color-stop(49%,#899cb3), color-stop(51%,#7e93af), color-stop(100%,#6e84a3)); /* Chrome,Safari4+ */
|
||||
background: -webkit-linear-gradient(top, #f04040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #f04040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Opera11.10+ */
|
||||
background: -ms-linear-gradient(top, #f04040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #f04040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* W3C */
|
||||
}
|
||||
.noVNC_status_warn {
|
||||
background: #f0f040; /* Old browsers */
|
||||
background: -moz-linear-gradient(top, #f0f040 0%, #899cb3 49%, #7e93af 51%, #6e84a3 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f0f040), color-stop(49%,#899cb3), color-stop(51%,#7e93af), color-stop(100%,#6e84a3)); /* Chrome,Safari4+ */
|
||||
background: -webkit-linear-gradient(top, #f0f040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #f0f040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Opera11.10+ */
|
||||
background: -ms-linear-gradient(top, #f0f040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #f0f040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* W3C */
|
||||
}
|
||||
|
||||
/* Control bar */
|
||||
#noVNC-control-bar {
|
||||
position:fixed;
|
||||
|
||||
display:block;
|
||||
height:44px;
|
||||
height:36px;
|
||||
left:0;
|
||||
top:0;
|
||||
width:100%;
|
||||
@ -368,22 +398,85 @@ html {
|
||||
font-size: 180px;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 481px) and (max-width: 640px) {
|
||||
.noVNC_status_button {
|
||||
font-size: 10px;
|
||||
.noVNC-buttons-left {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.noVNC-buttons-right {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
#noVNC_status {
|
||||
z-index: 0;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
#showExtraKeysButton { display: none; }
|
||||
#toggleCtrlButton { display: inline; }
|
||||
#toggleAltButton { display: inline; }
|
||||
#sendTabButton { display: inline; }
|
||||
#sendEscButton { display: inline; }
|
||||
|
||||
/* left-align the status text on lower resolutions */
|
||||
@media screen and (max-width: 800px){
|
||||
#noVNC_status {
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
width: auto;
|
||||
float: left;
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 640px){
|
||||
#noVNC_clipboard_text {
|
||||
width: 410px;
|
||||
}
|
||||
#noVNC_logo {
|
||||
font-size: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 321px) and (max-width: 480px) {
|
||||
.noVNC_status_button {
|
||||
font-size: 10px;
|
||||
}
|
||||
.noVNC-buttons-left {
|
||||
padding-left: 0px;
|
||||
}
|
||||
.noVNC-buttons-right {
|
||||
padding-right: 0px;
|
||||
}
|
||||
/* collapse the extra keys on lower resolutions */
|
||||
#showExtraKeysButton {
|
||||
display: inline;
|
||||
}
|
||||
#toggleCtrlButton {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
left: 0px;
|
||||
}
|
||||
#toggleAltButton {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 65px;
|
||||
left: 0px;
|
||||
}
|
||||
#sendTabButton {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 0px;
|
||||
}
|
||||
#sendEscButton {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 135px;
|
||||
left: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 321px) and (max-width: 480px) {
|
||||
#noVNC_clipboard_text {
|
||||
width: 250px;
|
||||
}
|
||||
|
108
src/sunstone/public/vendor/noVNC/base64.js
vendored
108
src/sunstone/public/vendor/noVNC/base64.js
vendored
@ -1,45 +1,8 @@
|
||||
/*
|
||||
* Modified from:
|
||||
* http://lxr.mozilla.org/mozilla/source/extensions/xml-rpc/src/nsXmlRpcClient.js#956
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla XML-RPC Client component.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Digital Creations 2, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Martijn Pieters <mj@digicool.com> (original author)
|
||||
* Samuel Sieb <samuel@sieb.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
// From: http://hg.mozilla.org/mozilla-central/raw-file/ec10630b1a54/js/src/devtools/jint/sunspider/string-base64.js
|
||||
|
||||
/*jslint white: false, bitwise: false, plusplus: false */
|
||||
/*global console */
|
||||
@ -47,36 +10,39 @@
|
||||
var Base64 = {
|
||||
|
||||
/* Convert data (an array of integers) to a Base64 string. */
|
||||
toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
|
||||
toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''),
|
||||
base64Pad : '=',
|
||||
|
||||
encode: function (data) {
|
||||
"use strict";
|
||||
var result = '',
|
||||
chrTable = Base64.toBase64Table.split(''),
|
||||
pad = Base64.base64Pad,
|
||||
length = data.length,
|
||||
i;
|
||||
var result = '';
|
||||
var toBase64Table = Base64.toBase64Table;
|
||||
var length = data.length
|
||||
var lengthpad = (length%3);
|
||||
var i = 0, j = 0;
|
||||
// Convert every three bytes to 4 ascii characters.
|
||||
/* BEGIN LOOP */
|
||||
for (i = 0; i < (length - 2); i += 3) {
|
||||
result += chrTable[data[i] >> 2];
|
||||
result += chrTable[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
|
||||
result += chrTable[((data[i+1] & 0x0f) << 2) + (data[i+2] >> 6)];
|
||||
result += chrTable[data[i+2] & 0x3f];
|
||||
result += toBase64Table[data[i] >> 2];
|
||||
result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
|
||||
result += toBase64Table[((data[i+1] & 0x0f) << 2) + (data[i+2] >> 6)];
|
||||
result += toBase64Table[data[i+2] & 0x3f];
|
||||
}
|
||||
/* END LOOP */
|
||||
|
||||
// Convert the remaining 1 or 2 bytes, pad out to 4 characters.
|
||||
if (length%3) {
|
||||
i = length - (length%3);
|
||||
result += chrTable[data[i] >> 2];
|
||||
if ((length%3) === 2) {
|
||||
result += chrTable[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
|
||||
result += chrTable[(data[i+1] & 0x0f) << 2];
|
||||
result += pad;
|
||||
} else {
|
||||
result += chrTable[(data[i] & 0x03) << 4];
|
||||
result += pad + pad;
|
||||
}
|
||||
if (lengthpad === 2) {
|
||||
j = length - lengthpad;
|
||||
result += toBase64Table[data[j] >> 2];
|
||||
result += toBase64Table[((data[j] & 0x03) << 4) + (data[j+1] >> 4)];
|
||||
result += toBase64Table[(data[j+1] & 0x0f) << 2];
|
||||
result += toBase64Table[64];
|
||||
} else if (lengthpad === 1) {
|
||||
j = length - lengthpad;
|
||||
result += toBase64Table[data[j] >> 2];
|
||||
result += toBase64Table[(data[j] & 0x03) << 4];
|
||||
result += toBase64Table[64];
|
||||
result += toBase64Table[64];
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -97,12 +63,12 @@ toBinaryTable : [
|
||||
decode: function (data, offset) {
|
||||
"use strict";
|
||||
offset = typeof(offset) !== 'undefined' ? offset : 0;
|
||||
var binTable = Base64.toBinaryTable,
|
||||
pad = Base64.base64Pad,
|
||||
result, result_length, idx, i, c, padding,
|
||||
leftbits = 0, // number of bits decoded, but yet to be appended
|
||||
leftdata = 0, // bits decoded, but yet to be appended
|
||||
data_length = data.indexOf('=') - offset;
|
||||
var toBinaryTable = Base64.toBinaryTable;
|
||||
var base64Pad = Base64.base64Pad;
|
||||
var result, result_length, idx, i, c, padding;
|
||||
var leftbits = 0; // number of bits decoded, but yet to be appended
|
||||
var leftdata = 0; // bits decoded, but yet to be appended
|
||||
var data_length = data.indexOf('=') - offset;
|
||||
|
||||
if (data_length < 0) { data_length = data.length - offset; }
|
||||
|
||||
@ -111,9 +77,10 @@ decode: function (data, offset) {
|
||||
result = new Array(result_length);
|
||||
|
||||
// Convert one by one.
|
||||
/* BEGIN LOOP */
|
||||
for (idx = 0, i = offset; i < data.length; i++) {
|
||||
c = binTable[data.charCodeAt(i) & 0x7f];
|
||||
padding = (data.charAt(i) === pad);
|
||||
c = toBinaryTable[data.charCodeAt(i) & 0x7f];
|
||||
padding = (data.charAt(i) === base64Pad);
|
||||
// Skip illegal characters and whitespace
|
||||
if (c === -1) {
|
||||
console.error("Illegal character code " + data.charCodeAt(i) + " at position " + i);
|
||||
@ -134,6 +101,7 @@ decode: function (data, offset) {
|
||||
leftdata &= (1 << leftbits) - 1;
|
||||
}
|
||||
}
|
||||
/* END LOOP */
|
||||
|
||||
// If there are any bits left, the base64 string was corrupted
|
||||
if (leftbits) {
|
||||
|
25
src/sunstone/public/vendor/noVNC/black.css
vendored
25
src/sunstone/public/vendor/noVNC/black.css
vendored
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* noVNC base CSS
|
||||
* noVNC black CSS
|
||||
* Copyright (C) 2012 Joel Martin
|
||||
* noVNC is licensed under the LGPL-3 (see LICENSE.txt)
|
||||
* Copyright (C) 2013 Samuel Mannehed for Cendio AB
|
||||
* noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
|
||||
* This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
|
||||
*/
|
||||
|
||||
@ -9,7 +10,7 @@
|
||||
background-color:#000;
|
||||
}
|
||||
|
||||
#noVNC-control-bar {
|
||||
.noVNC_status_normal {
|
||||
background: #4c4c4c; /* Old browsers */
|
||||
background: -moz-linear-gradient(top, #4c4c4c 0%, #2c2c2c 50%, #000000 51%, #131313 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#4c4c4c), color-stop(50%,#2c2c2c), color-stop(51%,#000000), color-stop(100%,#131313)); /* Chrome,Safari4+ */
|
||||
@ -18,6 +19,24 @@
|
||||
background: -ms-linear-gradient(top, #4c4c4c 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #4c4c4c 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* W3C */
|
||||
}
|
||||
.noVNC_status_error {
|
||||
background: #f04040; /* Old browsers */
|
||||
background: -moz-linear-gradient(top, #f04040 0%, #2c2c2c 50%, #000000 51%, #131313 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f04040), color-stop(50%,#2c2c2c), color-stop(51%,#000000), color-stop(100%,#131313)); /* Chrome,Safari4+ */
|
||||
background: -webkit-linear-gradient(top, #f04040 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #f04040 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* Opera11.10+ */
|
||||
background: -ms-linear-gradient(top, #f04040 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #f04040 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* W3C */
|
||||
}
|
||||
.noVNC_status_warn {
|
||||
background: #f0f040; /* Old browsers */
|
||||
background: -moz-linear-gradient(top, #f0f040 0%, #2c2c2c 50%, #000000 51%, #131313 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f0f040), color-stop(50%,#2c2c2c), color-stop(51%,#000000), color-stop(100%,#131313)); /* Chrome,Safari4+ */
|
||||
background: -webkit-linear-gradient(top, #f0f040 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #f0f040 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* Opera11.10+ */
|
||||
background: -ms-linear-gradient(top, #f0f040 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #f0f040 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* W3C */
|
||||
}
|
||||
|
||||
.triangle-right {
|
||||
border:2px solid #fff;
|
||||
|
37
src/sunstone/public/vendor/noVNC/blue.css
vendored
37
src/sunstone/public/vendor/noVNC/blue.css
vendored
@ -1,11 +1,12 @@
|
||||
/*
|
||||
* noVNC base CSS
|
||||
* noVNC blue CSS
|
||||
* Copyright (C) 2012 Joel Martin
|
||||
* noVNC is licensed under the LGPL-3 (see LICENSE.txt)
|
||||
* Copyright (C) 2013 Samuel Mannehed for Cendio AB
|
||||
* noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
|
||||
* This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
|
||||
*/
|
||||
|
||||
#noVNC-control-bar {
|
||||
.noVNC_status_normal {
|
||||
background-color:#04073d;
|
||||
background-image: -webkit-gradient(
|
||||
linear,
|
||||
@ -20,6 +21,36 @@
|
||||
rgb(4,7,61) 50%
|
||||
);
|
||||
}
|
||||
.noVNC_status_error {
|
||||
background-color:#f04040;
|
||||
background-image: -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0.54, rgb(240,64,64)),
|
||||
color-stop(0.5, rgb(4,7,61))
|
||||
);
|
||||
background-image: -moz-linear-gradient(
|
||||
center bottom,
|
||||
rgb(4,7,61) 54%,
|
||||
rgb(249,64,64) 50%
|
||||
);
|
||||
}
|
||||
.noVNC_status_warn {
|
||||
background-color:#f0f040;
|
||||
background-image: -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0.54, rgb(240,240,64)),
|
||||
color-stop(0.5, rgb(4,7,61))
|
||||
);
|
||||
background-image: -moz-linear-gradient(
|
||||
center bottom,
|
||||
rgb(4,7,61) 54%,
|
||||
rgb(240,240,64) 50%
|
||||
);
|
||||
}
|
||||
|
||||
.triangle-right {
|
||||
border:2px solid #fff;
|
||||
|
75
src/sunstone/public/vendor/noVNC/display.js
vendored
75
src/sunstone/public/vendor/noVNC/display.js
vendored
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* noVNC: HTML5 VNC client
|
||||
* Copyright (C) 2012 Joel Martin
|
||||
* Licensed under LGPL-3 (see LICENSE.txt)
|
||||
* Licensed under MPL 2.0 (see LICENSE.txt)
|
||||
*
|
||||
* See README.md for usage and integration instructions.
|
||||
*/
|
||||
@ -502,8 +502,8 @@ that.finishTile = function() {
|
||||
// else: No-op, if not prefer_js then already done by setSubTile
|
||||
};
|
||||
|
||||
rgbImageData = function(x, y, width, height, arr, offset) {
|
||||
var img, i, j, data, v = viewport;
|
||||
rgbImageData = function(x, y, vx, vy, width, height, arr, offset) {
|
||||
var img, i, j, data;
|
||||
/*
|
||||
if ((x - v.x >= v.w) || (y - v.y >= v.h) ||
|
||||
(x - v.x + width < 0) || (y - v.y + height < 0)) {
|
||||
@ -519,11 +519,11 @@ rgbImageData = function(x, y, width, height, arr, offset) {
|
||||
data[i + 2] = arr[j + 2];
|
||||
data[i + 3] = 255; // Set Alpha
|
||||
}
|
||||
c_ctx.putImageData(img, x - v.x, y - v.y);
|
||||
c_ctx.putImageData(img, x - vx, y - vy);
|
||||
};
|
||||
|
||||
bgrxImageData = function(x, y, width, height, arr, offset) {
|
||||
var img, i, j, data, v = viewport;
|
||||
bgrxImageData = function(x, y, vx, vy, width, height, arr, offset) {
|
||||
var img, i, j, data;
|
||||
/*
|
||||
if ((x - v.x >= v.w) || (y - v.y >= v.h) ||
|
||||
(x - v.x + width < 0) || (y - v.y + height < 0)) {
|
||||
@ -539,10 +539,10 @@ bgrxImageData = function(x, y, width, height, arr, offset) {
|
||||
data[i + 2] = arr[j ];
|
||||
data[i + 3] = 255; // Set Alpha
|
||||
}
|
||||
c_ctx.putImageData(img, x - v.x, y - v.y);
|
||||
c_ctx.putImageData(img, x - vx, y - vy);
|
||||
};
|
||||
|
||||
cmapImageData = function(x, y, width, height, arr, offset) {
|
||||
cmapImageData = function(x, y, vx, vy, width, height, arr, offset) {
|
||||
var img, i, j, data, bgr, cmap;
|
||||
img = c_ctx.createImageData(width, height);
|
||||
data = img.data;
|
||||
@ -554,23 +554,23 @@ cmapImageData = function(x, y, width, height, arr, offset) {
|
||||
data[i + 2] = bgr[0];
|
||||
data[i + 3] = 255; // Set Alpha
|
||||
}
|
||||
c_ctx.putImageData(img, x - viewport.x, y - viewport.y);
|
||||
c_ctx.putImageData(img, x - vx, y - vy);
|
||||
};
|
||||
|
||||
that.blitImage = function(x, y, width, height, arr, offset) {
|
||||
if (conf.true_color) {
|
||||
bgrxImageData(x, y, width, height, arr, offset);
|
||||
bgrxImageData(x, y, viewport.x, viewport.y, width, height, arr, offset);
|
||||
} else {
|
||||
cmapImageData(x, y, width, height, arr, offset);
|
||||
cmapImageData(x, y, viewport.x, viewport.y, width, height, arr, offset);
|
||||
}
|
||||
};
|
||||
|
||||
that.blitRgbImage = function(x, y, width, height, arr, offset) {
|
||||
if (conf.true_color) {
|
||||
rgbImageData(x, y, width, height, arr, offset);
|
||||
rgbImageData(x, y, viewport.x, viewport.y, width, height, arr, offset);
|
||||
} else {
|
||||
// prolly wrong...
|
||||
cmapImageData(x, y, width, height, arr, offset);
|
||||
cmapImageData(x, y, viewport.x, viewport.y, width, height, arr, offset);
|
||||
}
|
||||
};
|
||||
|
||||
@ -657,11 +657,18 @@ return constructor(); // Return the public API interface
|
||||
|
||||
|
||||
/* Set CSS cursor property using data URI encoded cursor file */
|
||||
function changeCursor(target, pixels, mask, hotx, hoty, w, h, cmap) {
|
||||
function changeCursor(target, pixels, mask, hotx, hoty, w0, h0, cmap) {
|
||||
"use strict";
|
||||
var cur = [], rgb, IHDRsz, RGBsz, ANDsz, XORsz, url, idx, alpha, x, y;
|
||||
//Util.Debug(">> changeCursor, x: " + hotx + ", y: " + hoty + ", w: " + w + ", h: " + h);
|
||||
|
||||
//Util.Debug(">> changeCursor, x: " + hotx + ", y: " + hoty + ", w0: " + w0 + ", h0: " + h0);
|
||||
|
||||
var w = w0;
|
||||
var h = h0;
|
||||
if (h < w)
|
||||
h = w; // increase h to make it square
|
||||
else
|
||||
w = h; // increace w to make it square
|
||||
|
||||
// Push multi-byte little-endian values
|
||||
cur.push16le = function (num) {
|
||||
this.push((num ) & 0xFF,
|
||||
@ -715,22 +722,28 @@ function changeCursor(target, pixels, mask, hotx, hoty, w, h, cmap) {
|
||||
// 62: color data (RGBQUAD icColors[])
|
||||
for (y = h-1; y >= 0; y -= 1) {
|
||||
for (x = 0; x < w; x += 1) {
|
||||
idx = y * Math.ceil(w / 8) + Math.floor(x/8);
|
||||
alpha = (mask[idx] << (x % 8)) & 0x80 ? 255 : 0;
|
||||
|
||||
if (cmap) {
|
||||
idx = (w * y) + x;
|
||||
rgb = cmap[pixels[idx]];
|
||||
cur.push(rgb[2]); // blue
|
||||
cur.push(rgb[1]); // green
|
||||
cur.push(rgb[0]); // red
|
||||
cur.push(alpha); // alpha
|
||||
if (x >= w0 || y >= h0) {
|
||||
cur.push(0); // blue
|
||||
cur.push(0); // green
|
||||
cur.push(0); // red
|
||||
cur.push(0); // alpha
|
||||
} else {
|
||||
idx = ((w * y) + x) * 4;
|
||||
cur.push(pixels[idx + 2]); // blue
|
||||
cur.push(pixels[idx + 1]); // green
|
||||
cur.push(pixels[idx ]); // red
|
||||
cur.push(alpha); // alpha
|
||||
idx = y * Math.ceil(w0 / 8) + Math.floor(x/8);
|
||||
alpha = (mask[idx] << (x % 8)) & 0x80 ? 255 : 0;
|
||||
if (cmap) {
|
||||
idx = (w0 * y) + x;
|
||||
rgb = cmap[pixels[idx]];
|
||||
cur.push(rgb[2]); // blue
|
||||
cur.push(rgb[1]); // green
|
||||
cur.push(rgb[0]); // red
|
||||
cur.push(alpha); // alpha
|
||||
} else {
|
||||
idx = ((w0 * y) + x) * 4;
|
||||
cur.push(pixels[idx + 2]); // blue
|
||||
cur.push(pixels[idx + 1]); // green
|
||||
cur.push(pixels[idx ]); // red
|
||||
cur.push(alpha); // alpha
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
83
src/sunstone/public/vendor/noVNC/input.js
vendored
83
src/sunstone/public/vendor/noVNC/input.js
vendored
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* noVNC: HTML5 VNC client
|
||||
* Copyright (C) 2011 Joel Martin
|
||||
* Licensed under LGPL-2 or any later version (see LICENSE.txt)
|
||||
* Copyright (C) 2012 Joel Martin
|
||||
* Copyright (C) 2013 Samuel Mannehed for Cendio AB
|
||||
* Licensed under MPL 2.0 or any later version (see LICENSE.txt)
|
||||
*/
|
||||
|
||||
/*jslint browser: true, white: false, bitwise: false */
|
||||
@ -83,6 +84,10 @@ function getKeysymSpecial(evt) {
|
||||
case 122 : keysym = 0xFFC8; break; // F11
|
||||
case 123 : keysym = 0xFFC9; break; // F12
|
||||
|
||||
case 225 : keysym = 0xFE03; break; // AltGr
|
||||
case 91 : keysym = 0xFFEC; break; // Super_R (Win Key)
|
||||
case 93 : keysym = 0xFF67; break; // Menu (Win Menu)
|
||||
|
||||
default : break;
|
||||
}
|
||||
}
|
||||
@ -106,6 +111,10 @@ function getKeysymSpecial(evt) {
|
||||
if (Util.Engine.gecko || Util.Engine.presto) {
|
||||
keysym = 45; }
|
||||
break;
|
||||
case 173 : // - (Mozilla)
|
||||
if (Util.Engine.gecko) {
|
||||
keysym = 45; }
|
||||
break;
|
||||
case 189 : keysym = 45; break; // - (IE)
|
||||
case 190 : keysym = 46; break; // . (Mozilla, IE)
|
||||
case 191 : keysym = 47; break; // / (Mozilla, IE)
|
||||
@ -478,7 +487,11 @@ function Mouse(defaults) {
|
||||
"use strict";
|
||||
|
||||
var that = {}, // Public API methods
|
||||
conf = {}; // Configuration attributes
|
||||
conf = {}, // Configuration attributes
|
||||
mouseCaptured = false;
|
||||
|
||||
var doubleClickTimer = null,
|
||||
lastTouchPos = null;
|
||||
|
||||
// Configuration attributes
|
||||
Util.conf_defaults(conf, that, defaults, [
|
||||
@ -491,11 +504,31 @@ Util.conf_defaults(conf, that, defaults, [
|
||||
['touchButton', 'rw', 'int', 1, 'Button mask (1, 2, 4) for touch devices (0 means ignore clicks)']
|
||||
]);
|
||||
|
||||
function captureMouse() {
|
||||
// capturing the mouse ensures we get the mouseup event
|
||||
if (conf.target.setCapture) {
|
||||
conf.target.setCapture();
|
||||
}
|
||||
|
||||
// some browsers give us mouseup events regardless,
|
||||
// so if we never captured the mouse, we can disregard the event
|
||||
mouseCaptured = true;
|
||||
}
|
||||
|
||||
function releaseMouse() {
|
||||
if (conf.target.releaseCapture) {
|
||||
conf.target.releaseCapture();
|
||||
}
|
||||
mouseCaptured = false;
|
||||
}
|
||||
//
|
||||
// Private functions
|
||||
//
|
||||
|
||||
function resetDoubleClickTimer() {
|
||||
doubleClickTimer = null;
|
||||
}
|
||||
|
||||
function onMouseButton(e, down) {
|
||||
var evt, pos, bmask;
|
||||
if (! conf.focused) {
|
||||
@ -503,8 +536,34 @@ function onMouseButton(e, down) {
|
||||
}
|
||||
evt = (e ? e : window.event);
|
||||
pos = Util.getEventPosition(e, conf.target, conf.scale);
|
||||
|
||||
if (e.touches || e.changedTouches) {
|
||||
// Touch device
|
||||
|
||||
// When two touches occur within 500 ms of each other and are
|
||||
// closer than 20 pixels together a double click is triggered.
|
||||
if (down == 1) {
|
||||
if (doubleClickTimer == null) {
|
||||
lastTouchPos = pos;
|
||||
} else {
|
||||
clearTimeout(doubleClickTimer);
|
||||
|
||||
// When the distance between the two touches is small enough
|
||||
// force the position of the latter touch to the position of
|
||||
// the first.
|
||||
|
||||
var xs = lastTouchPos.x - pos.x;
|
||||
var ys = lastTouchPos.y - pos.y;
|
||||
var d = Math.sqrt((xs * xs) + (ys * ys));
|
||||
|
||||
// The goal is to trigger on a certain physical width, the
|
||||
// devicePixelRatio brings us a bit closer but is not optimal.
|
||||
if (d < 20 * window.devicePixelRatio) {
|
||||
pos = lastTouchPos;
|
||||
}
|
||||
}
|
||||
doubleClickTimer = setTimeout(resetDoubleClickTimer, 500);
|
||||
}
|
||||
bmask = conf.touchButton;
|
||||
// If bmask is set
|
||||
} else if (evt.which) {
|
||||
@ -518,7 +577,7 @@ function onMouseButton(e, down) {
|
||||
}
|
||||
//Util.Debug("mouse " + pos.x + "," + pos.y + " down: " + down +
|
||||
// " bmask: " + bmask + "(evt.button: " + evt.button + ")");
|
||||
if (bmask > 0 && conf.onMouseButton) {
|
||||
if (conf.onMouseButton) {
|
||||
Util.Debug("onMouseButton " + (down ? "down" : "up") +
|
||||
", x: " + pos.x + ", y: " + pos.y + ", bmask: " + bmask);
|
||||
conf.onMouseButton(pos.x, pos.y, down, bmask);
|
||||
@ -528,11 +587,17 @@ function onMouseButton(e, down) {
|
||||
}
|
||||
|
||||
function onMouseDown(e) {
|
||||
captureMouse();
|
||||
onMouseButton(e, 1);
|
||||
}
|
||||
|
||||
function onMouseUp(e) {
|
||||
if (!mouseCaptured) {
|
||||
return;
|
||||
}
|
||||
|
||||
onMouseButton(e, 0);
|
||||
releaseMouse();
|
||||
}
|
||||
|
||||
function onMouseWheel(e) {
|
||||
@ -580,9 +645,9 @@ function onMouseDisable(e) {
|
||||
evt = (e ? e : window.event);
|
||||
pos = Util.getEventPosition(e, conf.target, conf.scale);
|
||||
/* Stop propagation if inside canvas area */
|
||||
if ((pos.x >= 0) && (pos.y >= 0) &&
|
||||
(pos.x < conf.target.offsetWidth) &&
|
||||
(pos.y < conf.target.offsetHeight)) {
|
||||
if ((pos.realx >= 0) && (pos.realy >= 0) &&
|
||||
(pos.realx < conf.target.offsetWidth) &&
|
||||
(pos.realy < conf.target.offsetHeight)) {
|
||||
//Util.Debug("mouse event disabled");
|
||||
Util.stopEvent(e);
|
||||
return false;
|
||||
@ -601,10 +666,12 @@ that.grab = function() {
|
||||
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
Util.addEvent(c, 'touchstart', onMouseDown);
|
||||
Util.addEvent(window, 'touchend', onMouseUp);
|
||||
Util.addEvent(c, 'touchend', onMouseUp);
|
||||
Util.addEvent(c, 'touchmove', onMouseMove);
|
||||
} else {
|
||||
Util.addEvent(c, 'mousedown', onMouseDown);
|
||||
Util.addEvent(window, 'mouseup', onMouseUp);
|
||||
Util.addEvent(c, 'mouseup', onMouseUp);
|
||||
Util.addEvent(c, 'mousemove', onMouseMove);
|
||||
Util.addEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel',
|
||||
@ -624,10 +691,12 @@ that.ungrab = function() {
|
||||
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
Util.removeEvent(c, 'touchstart', onMouseDown);
|
||||
Util.removeEvent(window, 'touchend', onMouseUp);
|
||||
Util.removeEvent(c, 'touchend', onMouseUp);
|
||||
Util.removeEvent(c, 'touchmove', onMouseMove);
|
||||
} else {
|
||||
Util.removeEvent(c, 'mousedown', onMouseDown);
|
||||
Util.removeEvent(window, 'mouseup', onMouseUp);
|
||||
Util.removeEvent(c, 'mouseup', onMouseUp);
|
||||
Util.removeEvent(c, 'mousemove', onMouseMove);
|
||||
Util.removeEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel',
|
||||
|
26
src/sunstone/public/vendor/noVNC/jsunzip.js
vendored
26
src/sunstone/public/vendor/noVNC/jsunzip.js
vendored
@ -352,20 +352,28 @@ this.getbit = function(d)
|
||||
}
|
||||
|
||||
/* read a num bit value from a stream and add base */
|
||||
function read_bits_direct(source, bitcount, tag, idx, num)
|
||||
{
|
||||
var val = 0;
|
||||
while (bitcount < 24) {
|
||||
tag = tag | (source[idx++] & 0xff) << bitcount;
|
||||
bitcount += 8;
|
||||
}
|
||||
val = tag & (0xffff >> (16 - num));
|
||||
tag >>= num;
|
||||
bitcount -= num;
|
||||
return [bitcount, tag, idx, val];
|
||||
}
|
||||
this.read_bits = function(d, num, base)
|
||||
{
|
||||
if (!num)
|
||||
return base;
|
||||
|
||||
var val = 0;
|
||||
while (d.bitcount < 24) {
|
||||
d.tag = d.tag | (d.source[d.sourceIndex++] & 0xff) << d.bitcount;
|
||||
d.bitcount += 8;
|
||||
}
|
||||
val = d.tag & (0xffff >> (16 - num));
|
||||
d.tag >>= num;
|
||||
d.bitcount -= num;
|
||||
return val + base;
|
||||
var ret = read_bits_direct(d.source, d.bitcount, d.tag, d.sourceIndex, num);
|
||||
d.bitcount = ret[0];
|
||||
d.tag = ret[1];
|
||||
d.sourceIndex = ret[2];
|
||||
return ret[3] + base;
|
||||
}
|
||||
|
||||
/* given a data stream and a tree, decode a symbol */
|
||||
|
18
src/sunstone/public/vendor/noVNC/playback.js
vendored
18
src/sunstone/public/vendor/noVNC/playback.js
vendored
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* noVNC: HTML5 VNC client
|
||||
* Copyright (C) 2012 Joel Martin
|
||||
* Licensed under LGPL-3 (see LICENSE.LGPL-3)
|
||||
* Licensed under MPL 2.0 (see LICENSE.txt)
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
@ -79,10 +79,22 @@ queue_next_packet = function () {
|
||||
}
|
||||
};
|
||||
|
||||
var bytes_processed = 0;
|
||||
|
||||
do_packet = function () {
|
||||
//Util.Debug("Processing frame: " + frame_idx);
|
||||
var frame = VNC_frame_data[frame_idx];
|
||||
rfb.recv_message({'data' : frame.slice(frame.indexOf('{', 1) + 1)});
|
||||
var frame = VNC_frame_data[frame_idx],
|
||||
start = frame.indexOf('{', 1) + 1;
|
||||
bytes_processed += frame.length - start;
|
||||
if (VNC_frame_encoding === 'binary') {
|
||||
var u8 = new Uint8Array(frame.length - start);
|
||||
for (var i = 0; i < frame.length - start; i++) {
|
||||
u8[i] = frame.charCodeAt(start + i);
|
||||
}
|
||||
rfb.recv_message({'data' : u8});
|
||||
} else {
|
||||
rfb.recv_message({'data' : frame.slice(start)});
|
||||
}
|
||||
frame_idx += 1;
|
||||
|
||||
queue_next_packet();
|
||||
|
168
src/sunstone/public/vendor/noVNC/rfb.js
vendored
168
src/sunstone/public/vendor/noVNC/rfb.js
vendored
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* noVNC: HTML5 VNC client
|
||||
* Copyright (C) 2012 Joel Martin
|
||||
* Licensed under LGPL-3 (see LICENSE.txt)
|
||||
* Copyright (C) 2013 Samuel Mannehed for Cendio AB
|
||||
* Licensed under MPL 2.0 (see LICENSE.txt)
|
||||
*
|
||||
* See README.md for usage and integration instructions.
|
||||
*
|
||||
@ -102,7 +103,6 @@ var that = {}, // Public API methods
|
||||
fb_height = 0,
|
||||
fb_name = "",
|
||||
|
||||
last_req_time = 0,
|
||||
rre_chunk_sz = 100,
|
||||
|
||||
timing = {
|
||||
@ -147,9 +147,6 @@ Util.conf_defaults(conf, that, defaults, [
|
||||
|
||||
['viewportDrag', 'rw', 'bool', false, 'Move the viewport on mouse drags'],
|
||||
|
||||
['check_rate', 'rw', 'int', 217, 'Timing (ms) of send/receive check'],
|
||||
['fbu_req_rate', 'rw', 'int', 1413, 'Timing (ms) of frameBufferUpdate requests'],
|
||||
|
||||
// Callback functions
|
||||
['onUpdateState', 'rw', 'func', function() { },
|
||||
'onUpdateState(rfb, state, oldstate, statusMsg): RFB state update/change '],
|
||||
@ -163,6 +160,10 @@ Util.conf_defaults(conf, that, defaults, [
|
||||
'onFBUReceive(rfb, fbu): RFB FBU received but not yet processed '],
|
||||
['onFBUComplete', 'rw', 'func', function() { },
|
||||
'onFBUComplete(rfb, fbu): RFB FBU received and processed '],
|
||||
['onFBResize', 'rw', 'func', function() { },
|
||||
'onFBResize(rfb, width, height): frame buffer resized'],
|
||||
['onDesktopName', 'rw', 'func', function() { },
|
||||
'onDesktopName(rfb, name): desktop name received'],
|
||||
|
||||
// These callback names are deprecated
|
||||
['updateState', 'rw', 'func', function() { },
|
||||
@ -299,7 +300,8 @@ function connect() {
|
||||
uri += rfb_host + ":" + rfb_port + "/" + rfb_path;
|
||||
}
|
||||
Util.Info("connecting to " + uri);
|
||||
ws.open(uri);
|
||||
// TODO: make protocols a configurable
|
||||
ws.open(uri, ['binary', 'base64']);
|
||||
|
||||
Util.Debug("<< RFB.connect");
|
||||
}
|
||||
@ -397,7 +399,7 @@ updateState = function(state, statusMsg) {
|
||||
}
|
||||
|
||||
if (msgTimer) {
|
||||
clearInterval(msgTimer);
|
||||
clearTimeout(msgTimer);
|
||||
msgTimer = null;
|
||||
}
|
||||
|
||||
@ -438,13 +440,13 @@ updateState = function(state, statusMsg) {
|
||||
|
||||
if (connTimer && (rfb_state !== 'connect')) {
|
||||
Util.Debug("Clearing connect timer");
|
||||
clearInterval(connTimer);
|
||||
clearTimeout(connTimer);
|
||||
connTimer = null;
|
||||
}
|
||||
|
||||
if (disconnTimer && (rfb_state !== 'disconnect')) {
|
||||
Util.Debug("Clearing disconnect timer");
|
||||
clearInterval(disconnTimer);
|
||||
clearTimeout(disconnTimer);
|
||||
disconnTimer = null;
|
||||
}
|
||||
|
||||
@ -563,44 +565,18 @@ function genDES(password, challenge) {
|
||||
return (new DES(passwd)).encrypt(challenge);
|
||||
}
|
||||
|
||||
function flushClient() {
|
||||
if (mouse_arr.length > 0) {
|
||||
//send(mouse_arr.concat(fbUpdateRequests()));
|
||||
ws.send(mouse_arr);
|
||||
setTimeout(function() {
|
||||
ws.send(fbUpdateRequests());
|
||||
}, 50);
|
||||
|
||||
mouse_arr = [];
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// overridable for testing
|
||||
checkEvents = function() {
|
||||
var now;
|
||||
if (rfb_state === 'normal' && !viewportDragging) {
|
||||
if (! flushClient()) {
|
||||
now = new Date().getTime();
|
||||
if (now > last_req_time + conf.fbu_req_rate) {
|
||||
last_req_time = now;
|
||||
ws.send(fbUpdateRequests());
|
||||
}
|
||||
}
|
||||
if (rfb_state === 'normal' && !viewportDragging && mouse_arr.length > 0) {
|
||||
ws.send(mouse_arr);
|
||||
mouse_arr = [];
|
||||
}
|
||||
setTimeout(checkEvents, conf.check_rate);
|
||||
};
|
||||
|
||||
keyPress = function(keysym, down) {
|
||||
var arr;
|
||||
|
||||
if (conf.view_only) { return; } // View only, skip keyboard events
|
||||
|
||||
arr = keyEvent(keysym, down);
|
||||
arr = arr.concat(fbUpdateRequests());
|
||||
ws.send(arr);
|
||||
ws.send(keyEvent(keysym, down));
|
||||
};
|
||||
|
||||
mouseButton = function(x, y, down, bmask) {
|
||||
@ -619,7 +595,6 @@ mouseButton = function(x, y, down, bmask) {
|
||||
return;
|
||||
} else {
|
||||
viewportDragging = false;
|
||||
ws.send(fbUpdateRequests()); // Force immediate redraw
|
||||
}
|
||||
}
|
||||
|
||||
@ -627,7 +602,8 @@ mouseButton = function(x, y, down, bmask) {
|
||||
|
||||
mouse_arr = mouse_arr.concat(
|
||||
pointerEvent(display.absX(x), display.absY(y)) );
|
||||
flushClient();
|
||||
ws.send(mouse_arr);
|
||||
mouse_arr = [];
|
||||
};
|
||||
|
||||
mouseMove = function(x, y) {
|
||||
@ -650,7 +626,9 @@ mouseMove = function(x, y) {
|
||||
if (conf.view_only) { return; } // View only, skip mouse events
|
||||
|
||||
mouse_arr = mouse_arr.concat(
|
||||
pointerEvent(display.absX(x), display.absY(y)) );
|
||||
pointerEvent(display.absX(x), display.absY(y)));
|
||||
|
||||
checkEvents();
|
||||
};
|
||||
|
||||
|
||||
@ -870,6 +848,7 @@ init_msg = function() {
|
||||
/* Connection name/title */
|
||||
name_length = ws.rQshift32();
|
||||
fb_name = ws.rQshiftStr(name_length);
|
||||
conf.onDesktopName(that, fb_name);
|
||||
|
||||
if (conf.true_color && fb_name === "Intel(r) AMT KVM")
|
||||
{
|
||||
@ -878,6 +857,7 @@ init_msg = function() {
|
||||
}
|
||||
|
||||
display.set_true_color(conf.true_color);
|
||||
conf.onFBResize(that, fb_width, fb_height);
|
||||
display.resize(fb_width, fb_height);
|
||||
keyboard.grab();
|
||||
mouse.grab();
|
||||
@ -892,13 +872,12 @@ init_msg = function() {
|
||||
|
||||
response = pixelFormat();
|
||||
response = response.concat(clientEncodings());
|
||||
response = response.concat(fbUpdateRequests());
|
||||
response = response.concat(fbUpdateRequests()); // initial fbu-request
|
||||
timing.fbu_rt_start = (new Date()).getTime();
|
||||
timing.pixels = 0;
|
||||
ws.send(response);
|
||||
|
||||
/* Start pushing/polling */
|
||||
setTimeout(checkEvents, conf.check_rate);
|
||||
checkEvents();
|
||||
|
||||
if (conf.encrypt) {
|
||||
updateState('normal', "Connected (encrypted) to: " + fb_name);
|
||||
@ -926,6 +905,10 @@ normal_msg = function() {
|
||||
switch (msg_type) {
|
||||
case 0: // FramebufferUpdate
|
||||
ret = framebufferUpdate(); // false means need more data
|
||||
if (ret) {
|
||||
// only allow one outstanding fbu-request at a time
|
||||
ws.send(fbUpdateRequests());
|
||||
}
|
||||
break;
|
||||
case 1: // SetColourMapEntries
|
||||
Util.Debug("SetColourMapEntries");
|
||||
@ -1122,6 +1105,7 @@ encHandlers.COPYRECT = function display_copy_rect() {
|
||||
|
||||
var old_x, old_y;
|
||||
|
||||
FBU.bytes = 4;
|
||||
if (ws.rQwait("COPYRECT", 4)) { return false; }
|
||||
display.renderQ_push({
|
||||
'type': 'copy',
|
||||
@ -1141,6 +1125,7 @@ encHandlers.RRE = function display_rre() {
|
||||
var color, x, y, width, height, chunk;
|
||||
|
||||
if (FBU.subrects === 0) {
|
||||
FBU.bytes = 4+fb_Bpp;
|
||||
if (ws.rQwait("RRE", 4+fb_Bpp)) { return false; }
|
||||
FBU.subrects = ws.rQshift32();
|
||||
color = ws.rQshiftBytes(fb_Bpp); // Background
|
||||
@ -1357,6 +1342,45 @@ function display_tight(isTightPNG) {
|
||||
return uncompressed.data;
|
||||
}
|
||||
|
||||
var indexedToRGB = function (data, numColors, palette, width, height) {
|
||||
// Convert indexed (palette based) image data to RGB
|
||||
// TODO: reduce number of calculations inside loop
|
||||
var dest = [];
|
||||
var x, y, b, w, w1, dp, sp;
|
||||
if (numColors === 2) {
|
||||
w = Math.floor((width + 7) / 8);
|
||||
w1 = Math.floor(width / 8);
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < w1; x++) {
|
||||
for (b = 7; b >= 0; b--) {
|
||||
dp = (y*width + x*8 + 7-b) * 3;
|
||||
sp = (data[y*w + x] >> b & 1) * 3;
|
||||
dest[dp ] = palette[sp ];
|
||||
dest[dp+1] = palette[sp+1];
|
||||
dest[dp+2] = palette[sp+2];
|
||||
}
|
||||
}
|
||||
for (b = 7; b >= 8 - width % 8; b--) {
|
||||
dp = (y*width + x*8 + 7-b) * 3;
|
||||
sp = (data[y*w + x] >> b & 1) * 3;
|
||||
dest[dp ] = palette[sp ];
|
||||
dest[dp+1] = palette[sp+1];
|
||||
dest[dp+2] = palette[sp+2];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < width; x++) {
|
||||
dp = (y*width + x) * 3;
|
||||
sp = data[y*width + x] * 3;
|
||||
dest[dp ] = palette[sp ];
|
||||
dest[dp+1] = palette[sp+1];
|
||||
dest[dp+2] = palette[sp+2];
|
||||
}
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
};
|
||||
var handlePalette = function() {
|
||||
var numColors = rQ[rQi + 2] + 1;
|
||||
var paletteSize = numColors * fb_depth;
|
||||
@ -1388,45 +1412,12 @@ function display_tight(isTightPNG) {
|
||||
}
|
||||
|
||||
// Convert indexed (palette based) image data to RGB
|
||||
// TODO: reduce number of calculations inside loop
|
||||
var dest = [];
|
||||
var x, y, b, w, w1, dp, sp;
|
||||
if (numColors === 2) {
|
||||
w = Math.floor((FBU.width + 7) / 8);
|
||||
w1 = Math.floor(FBU.width / 8);
|
||||
for (y = 0; y < FBU.height; y++) {
|
||||
for (x = 0; x < w1; x++) {
|
||||
for (b = 7; b >= 0; b--) {
|
||||
dp = (y*FBU.width + x*8 + 7-b) * 3;
|
||||
sp = (data[y*w + x] >> b & 1) * 3;
|
||||
dest[dp ] = palette[sp ];
|
||||
dest[dp+1] = palette[sp+1];
|
||||
dest[dp+2] = palette[sp+2];
|
||||
}
|
||||
}
|
||||
for (b = 7; b >= 8 - FBU.width % 8; b--) {
|
||||
dp = (y*FBU.width + x*8 + 7-b) * 3;
|
||||
sp = (data[y*w + x] >> b & 1) * 3;
|
||||
dest[dp ] = palette[sp ];
|
||||
dest[dp+1] = palette[sp+1];
|
||||
dest[dp+2] = palette[sp+2];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (y = 0; y < FBU.height; y++) {
|
||||
for (x = 0; x < FBU.width; x++) {
|
||||
dp = (y*FBU.width + x) * 3;
|
||||
sp = data[y*FBU.width + x] * 3;
|
||||
dest[dp ] = palette[sp ];
|
||||
dest[dp+1] = palette[sp+1];
|
||||
dest[dp+2] = palette[sp+2];
|
||||
}
|
||||
}
|
||||
}
|
||||
var rgb = indexedToRGB(data, numColors, palette, FBU.width, FBU.height);
|
||||
|
||||
// Add it to the render queue
|
||||
display.renderQ_push({
|
||||
'type': 'blitRgb',
|
||||
'data': dest,
|
||||
'data': rgb,
|
||||
'x': FBU.x,
|
||||
'y': FBU.y,
|
||||
'width': FBU.width,
|
||||
@ -1577,10 +1568,9 @@ encHandlers.DesktopSize = function set_desktopsize() {
|
||||
Util.Debug(">> set_desktopsize");
|
||||
fb_width = FBU.width;
|
||||
fb_height = FBU.height;
|
||||
conf.onFBResize(that, fb_width, fb_height);
|
||||
display.resize(fb_width, fb_height);
|
||||
timing.fbu_rt_start = (new Date()).getTime();
|
||||
// Send a new non-incremental request
|
||||
ws.send(fbUpdateRequests());
|
||||
|
||||
FBU.bytes = 0;
|
||||
FBU.rects -= 1;
|
||||
@ -1663,6 +1653,11 @@ clientEncodings = function() {
|
||||
if ((encodings[i][0] === "Cursor") &&
|
||||
(! conf.local_cursor)) {
|
||||
Util.Debug("Skipping Cursor pseudo-encoding");
|
||||
|
||||
// TODO: remove this when we have tight+non-true-color
|
||||
} else if ((encodings[i][0] === "TIGHT") &&
|
||||
(! conf.true_color)) {
|
||||
Util.Warn("Skipping tight, only support with true color");
|
||||
} else {
|
||||
//Util.Debug("Adding encoding: " + encodings[i][0]);
|
||||
encList.push(encodings[i][1]);
|
||||
@ -1801,7 +1796,6 @@ that.sendCtrlAltDel = function() {
|
||||
arr = arr.concat(keyEvent(0xFFFF, 0)); // Delete
|
||||
arr = arr.concat(keyEvent(0xFFE9, 0)); // Alt
|
||||
arr = arr.concat(keyEvent(0xFFE3, 0)); // Control
|
||||
arr = arr.concat(fbUpdateRequests());
|
||||
ws.send(arr);
|
||||
};
|
||||
|
||||
@ -1818,7 +1812,6 @@ that.sendKey = function(code, down) {
|
||||
arr = arr.concat(keyEvent(code, 1));
|
||||
arr = arr.concat(keyEvent(code, 0));
|
||||
}
|
||||
arr = arr.concat(fbUpdateRequests());
|
||||
ws.send(arr);
|
||||
};
|
||||
|
||||
@ -1830,15 +1823,16 @@ that.clipboardPasteFrom = function(text) {
|
||||
};
|
||||
|
||||
// Override internal functions for testing
|
||||
that.testMode = function(override_send) {
|
||||
that.testMode = function(override_send, data_mode) {
|
||||
test_mode = true;
|
||||
that.recv_message = ws.testMode(override_send);
|
||||
that.recv_message = ws.testMode(override_send, data_mode);
|
||||
|
||||
checkEvents = function () { /* Stub Out */ };
|
||||
that.connect = function(host, port, password) {
|
||||
rfb_host = host;
|
||||
rfb_port = port;
|
||||
rfb_password = password;
|
||||
init_vars();
|
||||
updateState('ProtocolVersion', "Starting VNC handshake");
|
||||
};
|
||||
};
|
||||
|
301
src/sunstone/public/vendor/noVNC/ui.js
vendored
301
src/sunstone/public/vendor/noVNC/ui.js
vendored
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* noVNC: HTML5 VNC client
|
||||
* Copyright (C) 2012 Joel Martin
|
||||
* Licensed under LGPL-3 (see LICENSE.txt)
|
||||
* Copyright (C) 2013 Samuel Mannehed for Cendio AB
|
||||
* Licensed under MPL 2.0 (see LICENSE.txt)
|
||||
*
|
||||
* See README.md for usage and integration instructions.
|
||||
*/
|
||||
@ -10,17 +11,37 @@
|
||||
/*jslint white: false, browser: true */
|
||||
/*global window, $D, Util, WebUtil, RFB, Display */
|
||||
|
||||
// Load supporting scripts
|
||||
window.onscriptsload = function () { UI.load(); };
|
||||
Util.load_scripts(["webutil.js", "base64.js", "websock.js", "des.js",
|
||||
"input.js", "display.js", "jsunzip.js", "rfb.js",
|
||||
"keysym.js"]);
|
||||
|
||||
var UI = {
|
||||
|
||||
rfb_state : 'loaded',
|
||||
settingsOpen : false,
|
||||
connSettingsOpen : false,
|
||||
popupStatusOpen : false,
|
||||
clipboardOpen: false,
|
||||
keyboardVisible: false,
|
||||
hideKeyboardTimeout: null,
|
||||
extraKeysVisible: false,
|
||||
ctrlOn: false,
|
||||
altOn: false,
|
||||
isTouchDevice: false,
|
||||
|
||||
// Setup rfb object, load settings from browser storage, then call
|
||||
// UI.init to setup the UI/menus
|
||||
load: function (callback) {
|
||||
WebUtil.initSettings(UI.start, callback);
|
||||
},
|
||||
|
||||
// Render default UI and initialize settings menu
|
||||
load: function() {
|
||||
var html = '', i, sheet, sheets, llevels;
|
||||
start: function(callback) {
|
||||
var html = '', i, sheet, sheets, llevels, port, autoconnect;
|
||||
|
||||
UI.isTouchDevice = 'ontouchstart' in document.documentElement;
|
||||
|
||||
// Stylesheet selection dropdown
|
||||
sheet = WebUtil.selectStylesheet();
|
||||
@ -44,13 +65,25 @@ load: function() {
|
||||
// call twice to get around webkit bug
|
||||
WebUtil.selectStylesheet(UI.getSetting('stylesheet'));
|
||||
|
||||
// if port == 80 (or 443) then it won't be present and should be
|
||||
// set manually
|
||||
port = window.location.port;
|
||||
if (!port) {
|
||||
if (window.location.protocol.substring(0,5) == 'https') {
|
||||
port = 443;
|
||||
}
|
||||
else if (window.location.protocol.substring(0,4) == 'http') {
|
||||
port = 80;
|
||||
}
|
||||
}
|
||||
|
||||
/* Populate the controls if defaults are provided in the URL */
|
||||
UI.initSetting('host', window.location.hostname);
|
||||
UI.initSetting('port', window.location.port);
|
||||
UI.initSetting('port', port);
|
||||
UI.initSetting('password', '');
|
||||
UI.initSetting('encrypt', (window.location.protocol === "https:"));
|
||||
UI.initSetting('true_color', true);
|
||||
UI.initSetting('cursor', false);
|
||||
UI.initSetting('cursor', !UI.isTouchDevice);
|
||||
UI.initSetting('shared', true);
|
||||
UI.initSetting('view_only', false);
|
||||
UI.initSetting('connectTimeout', 2);
|
||||
@ -59,7 +92,17 @@ load: function() {
|
||||
|
||||
UI.rfb = RFB({'target': $D('noVNC_canvas'),
|
||||
'onUpdateState': UI.updateState,
|
||||
'onClipboard': UI.clipReceive});
|
||||
'onClipboard': UI.clipReceive,
|
||||
'onDesktopName': UI.updateDocumentTitle});
|
||||
|
||||
autoconnect = WebUtil.getQueryVar('autoconnect', false);
|
||||
if (autoconnect === 'true' || autoconnect == '1') {
|
||||
autoconnect = true;
|
||||
UI.connect();
|
||||
} else {
|
||||
autoconnect = false;
|
||||
}
|
||||
|
||||
UI.updateVisualState();
|
||||
|
||||
// Unfocus clipboard when over the VNC area
|
||||
@ -71,7 +114,7 @@ load: function() {
|
||||
// };
|
||||
|
||||
// Show mouse selector buttons on touch screen devices
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
if (UI.isTouchDevice) {
|
||||
// Show mobile buttons
|
||||
$D('noVNC_mobile_buttons').style.display = "inline";
|
||||
UI.setMouseButton();
|
||||
@ -91,6 +134,7 @@ load: function() {
|
||||
//UI.setOnscroll();
|
||||
//UI.setResize();
|
||||
}
|
||||
UI.setBarPosition();
|
||||
|
||||
$D('noVNC_host').focus();
|
||||
|
||||
@ -104,21 +148,69 @@ load: function() {
|
||||
} );
|
||||
|
||||
// Show description by default when hosted at for kanaka.github.com
|
||||
if (location.host === "kanaka.github.com") {
|
||||
if (location.host === "kanaka.github.io") {
|
||||
// Open the description dialog
|
||||
$D('noVNC_description').style.display = "block";
|
||||
} else {
|
||||
// Open the connect panel on first load
|
||||
UI.toggleConnectPanel();
|
||||
// Show the connect panel on first load unless autoconnecting
|
||||
if (autoconnect === UI.connSettingsOpen) {
|
||||
UI.toggleConnectPanel();
|
||||
}
|
||||
}
|
||||
|
||||
// Add mouse event click/focus/blur event handlers to the UI
|
||||
UI.addMouseHandlers();
|
||||
|
||||
if (typeof callback === "function") {
|
||||
callback(UI.rfb);
|
||||
}
|
||||
},
|
||||
|
||||
addMouseHandlers: function() {
|
||||
// Setup interface handlers that can't be inline
|
||||
$D("noVNC_view_drag_button").onclick = UI.setViewDrag;
|
||||
$D("noVNC_mouse_button0").onclick = function () { UI.setMouseButton(1); };
|
||||
$D("noVNC_mouse_button1").onclick = function () { UI.setMouseButton(2); };
|
||||
$D("noVNC_mouse_button2").onclick = function () { UI.setMouseButton(4); };
|
||||
$D("noVNC_mouse_button4").onclick = function () { UI.setMouseButton(0); };
|
||||
$D("showKeyboard").onclick = UI.showKeyboard;
|
||||
|
||||
$D("keyboardinput").oninput = UI.keyInput;
|
||||
$D("keyboardinput").onblur = UI.keyInputBlur;
|
||||
|
||||
$D("showExtraKeysButton").onclick = UI.showExtraKeys;
|
||||
$D("toggleCtrlButton").onclick = UI.toggleCtrl;
|
||||
$D("toggleAltButton").onclick = UI.toggleAlt;
|
||||
$D("sendTabButton").onclick = UI.sendTab;
|
||||
$D("sendEscButton").onclick = UI.sendEsc;
|
||||
|
||||
$D("sendCtrlAltDelButton").onclick = UI.sendCtrlAltDel;
|
||||
$D("noVNC_status").onclick = UI.togglePopupStatusPanel;
|
||||
$D("noVNC_popup_status_panel").onclick = UI.togglePopupStatusPanel;
|
||||
$D("clipboardButton").onclick = UI.toggleClipboardPanel;
|
||||
$D("settingsButton").onclick = UI.toggleSettingsPanel;
|
||||
$D("connectButton").onclick = UI.toggleConnectPanel;
|
||||
$D("disconnectButton").onclick = UI.disconnect;
|
||||
$D("descriptionButton").onclick = UI.toggleConnectPanel;
|
||||
|
||||
$D("noVNC_clipboard_text").onfocus = UI.displayBlur;
|
||||
$D("noVNC_clipboard_text").onblur = UI.displayFocus;
|
||||
$D("noVNC_clipboard_text").onchange = UI.clipSend;
|
||||
$D("noVNC_clipboard_clear_button").onclick = UI.clipClear;
|
||||
|
||||
$D("noVNC_settings_menu").onmouseover = UI.displayBlur;
|
||||
$D("noVNC_settings_menu").onmouseover = UI.displayFocus;
|
||||
$D("noVNC_apply").onclick = UI.settingsApply;
|
||||
|
||||
$D("noVNC_connect_button").onclick = UI.connect;
|
||||
},
|
||||
|
||||
// Read form control compatible setting from cookie
|
||||
getSetting: function(name) {
|
||||
var val, ctrl = $D('noVNC_' + name);
|
||||
val = WebUtil.readCookie(name);
|
||||
if (ctrl.type === 'checkbox') {
|
||||
if (val.toLowerCase() in {'0':1, 'no':1, 'false':1}) {
|
||||
val = WebUtil.readSetting(name);
|
||||
if (val !== null && ctrl.type === 'checkbox') {
|
||||
if (val.toString().toLowerCase() in {'0':1, 'no':1, 'false':1}) {
|
||||
val = false;
|
||||
} else {
|
||||
val = true;
|
||||
@ -134,7 +226,7 @@ updateSetting: function(name, value) {
|
||||
var i, ctrl = $D('noVNC_' + name);
|
||||
// Save the cookie for this session
|
||||
if (typeof value !== 'undefined') {
|
||||
WebUtil.createCookie(name, value);
|
||||
WebUtil.writeSetting(name, value);
|
||||
}
|
||||
|
||||
// Update the settings control
|
||||
@ -170,7 +262,7 @@ saveSetting: function(name) {
|
||||
} else {
|
||||
val = ctrl.value;
|
||||
}
|
||||
WebUtil.createCookie(name, val);
|
||||
WebUtil.writeSetting(name, val);
|
||||
//Util.Debug("Setting saved '" + name + "=" + val + "'");
|
||||
return val;
|
||||
},
|
||||
@ -182,7 +274,7 @@ initSetting: function(name, defVal) {
|
||||
// Check Query string followed by cookie
|
||||
val = WebUtil.getQueryVar(name);
|
||||
if (val === null) {
|
||||
val = WebUtil.readCookie(name, defVal);
|
||||
val = WebUtil.readSetting(name, defVal);
|
||||
}
|
||||
UI.updateSetting(name, val);
|
||||
//Util.Debug("Setting '" + name + "' initialized to '" + val + "'");
|
||||
@ -196,20 +288,39 @@ forceSetting: function(name, val) {
|
||||
},
|
||||
|
||||
|
||||
// Show the popup status panel
|
||||
togglePopupStatusPanel: function() {
|
||||
var psp = $D('noVNC_popup_status_panel');
|
||||
if (UI.popupStatusOpen === true) {
|
||||
psp.style.display = "none";
|
||||
UI.popupStatusOpen = false;
|
||||
} else {
|
||||
psp.innerHTML = $D('noVNC_status').innerHTML;
|
||||
psp.style.display = "block";
|
||||
psp.style.left = window.innerWidth/2 -
|
||||
parseInt(window.getComputedStyle(psp, false).width)/2 -30 + "px";
|
||||
UI.popupStatusOpen = true;
|
||||
}
|
||||
},
|
||||
|
||||
// Show the clipboard panel
|
||||
toggleClipboardPanel: function() {
|
||||
// Close the description panel
|
||||
$D('noVNC_description').style.display = "none";
|
||||
//Close settings if open
|
||||
// Close settings if open
|
||||
if (UI.settingsOpen === true) {
|
||||
UI.settingsApply();
|
||||
UI.closeSettingsMenu();
|
||||
}
|
||||
//Close connection settings if open
|
||||
// Close connection settings if open
|
||||
if (UI.connSettingsOpen === true) {
|
||||
UI.toggleConnectPanel();
|
||||
}
|
||||
//Toggle Clipboard Panel
|
||||
// Close popup status panel if open
|
||||
if (UI.popupStatusOpen === true) {
|
||||
UI.togglePopupStatusPanel();
|
||||
}
|
||||
// Toggle Clipboard Panel
|
||||
if (UI.clipboardOpen === true) {
|
||||
$D('noVNC_clipboard').style.display = "none";
|
||||
$D('clipboardButton').className = "noVNC_status_button";
|
||||
@ -225,21 +336,29 @@ toggleClipboardPanel: function() {
|
||||
toggleConnectPanel: function() {
|
||||
// Close the description panel
|
||||
$D('noVNC_description').style.display = "none";
|
||||
//Close connection settings if open
|
||||
// Close connection settings if open
|
||||
if (UI.settingsOpen === true) {
|
||||
UI.settingsApply();
|
||||
UI.closeSettingsMenu();
|
||||
$D('connectButton').className = "noVNC_status_button";
|
||||
}
|
||||
// Close clipboard panel if open
|
||||
if (UI.clipboardOpen === true) {
|
||||
UI.toggleClipboardPanel();
|
||||
}
|
||||
// Close popup status panel if open
|
||||
if (UI.popupStatusOpen === true) {
|
||||
UI.togglePopupStatusPanel();
|
||||
}
|
||||
|
||||
//Toggle Connection Panel
|
||||
// Toggle Connection Panel
|
||||
if (UI.connSettingsOpen === true) {
|
||||
$D('noVNC_controls').style.display = "none";
|
||||
$D('connectButton').className = "noVNC_status_button";
|
||||
UI.connSettingsOpen = false;
|
||||
UI.saveSetting('host');
|
||||
UI.saveSetting('port');
|
||||
//UI.saveSetting('password');
|
||||
} else {
|
||||
$D('noVNC_controls').style.display = "block";
|
||||
$D('connectButton').className = "noVNC_status_button_selected";
|
||||
@ -263,7 +382,7 @@ toggleSettingsPanel: function() {
|
||||
if (UI.rfb.get_display().get_cursor_uri()) {
|
||||
UI.updateSetting('cursor');
|
||||
} else {
|
||||
UI.updateSetting('cursor', false);
|
||||
UI.updateSetting('cursor', !UI.isTouchDevice);
|
||||
$D('noVNC_cursor').disabled = true;
|
||||
}
|
||||
UI.updateSetting('clip');
|
||||
@ -283,13 +402,18 @@ toggleSettingsPanel: function() {
|
||||
openSettingsMenu: function() {
|
||||
// Close the description panel
|
||||
$D('noVNC_description').style.display = "none";
|
||||
// Close clipboard panel if open
|
||||
if (UI.clipboardOpen === true) {
|
||||
UI.toggleClipboardPanel();
|
||||
}
|
||||
//Close connection settings if open
|
||||
// Close connection settings if open
|
||||
if (UI.connSettingsOpen === true) {
|
||||
UI.toggleConnectPanel();
|
||||
}
|
||||
// Close popup status panel if open
|
||||
if (UI.popupStatusOpen === true) {
|
||||
UI.togglePopupStatusPanel();
|
||||
}
|
||||
$D('noVNC_settings').style.display = "block";
|
||||
$D('settingsButton').className = "noVNC_status_button_selected";
|
||||
UI.settingsOpen = true;
|
||||
@ -373,8 +497,6 @@ setMouseButton: function(num) {
|
||||
updateState: function(rfb, state, oldstate, msg) {
|
||||
var s, sb, c, d, cad, vd, klass;
|
||||
UI.rfb_state = state;
|
||||
s = $D('noVNC_status');
|
||||
sb = $D('noVNC_status_bar');
|
||||
switch (state) {
|
||||
case 'failed':
|
||||
case 'fatal':
|
||||
@ -404,9 +526,8 @@ updateState: function(rfb, state, oldstate, msg) {
|
||||
}
|
||||
|
||||
if (typeof(msg) !== 'undefined') {
|
||||
s.setAttribute("class", klass);
|
||||
sb.setAttribute("class", klass);
|
||||
s.innerHTML = msg;
|
||||
$D('noVNC-control-bar').setAttribute("class", klass);
|
||||
$D('noVNC_status').innerHTML = msg;
|
||||
}
|
||||
|
||||
UI.updateVisualState();
|
||||
@ -423,7 +544,7 @@ updateVisualState: function() {
|
||||
UI.rfb.get_display().get_cursor_uri()) {
|
||||
$D('noVNC_cursor').disabled = connected;
|
||||
} else {
|
||||
UI.updateSetting('cursor', false);
|
||||
UI.updateSetting('cursor', !UI.isTouchDevice);
|
||||
$D('noVNC_cursor').disabled = true;
|
||||
}
|
||||
$D('noVNC_shared').disabled = connected;
|
||||
@ -437,13 +558,16 @@ updateVisualState: function() {
|
||||
UI.setMouseButton(1);
|
||||
$D('clipboardButton').style.display = "inline";
|
||||
$D('showKeyboard').style.display = "inline";
|
||||
$D('noVNC_extra_keys').style.display = "";
|
||||
$D('sendCtrlAltDelButton').style.display = "inline";
|
||||
} else {
|
||||
UI.setMouseButton();
|
||||
$D('clipboardButton').style.display = "none";
|
||||
$D('showKeyboard').style.display = "none";
|
||||
$D('noVNC_extra_keys').style.display = "none";
|
||||
$D('sendCtrlAltDelButton').style.display = "none";
|
||||
}
|
||||
|
||||
// State change disables viewport dragging.
|
||||
// It is enabled (toggled) by direct click on the button
|
||||
UI.setViewDrag(false);
|
||||
@ -466,6 +590,12 @@ updateVisualState: function() {
|
||||
},
|
||||
|
||||
|
||||
// Display the desktop name in the document title
|
||||
updateDocumentTitle: function(rfb, name) {
|
||||
document.title = name + " - noVNC";
|
||||
},
|
||||
|
||||
|
||||
clipReceive: function(rfb, text) {
|
||||
Util.Debug(">> UI.clipReceive: " + text.substr(0,40) + "...");
|
||||
$D('noVNC_clipboard_text').value = text;
|
||||
@ -584,7 +714,8 @@ setViewDrag: function(drag) {
|
||||
vmb.style.display = "none";
|
||||
}
|
||||
|
||||
if (typeof(drag) === "undefined") {
|
||||
if (typeof(drag) === "undefined" ||
|
||||
typeof(drag) === "object") {
|
||||
// If not specified, then toggle
|
||||
drag = !UI.rfb.get_viewportDrag();
|
||||
}
|
||||
@ -599,23 +730,123 @@ setViewDrag: function(drag) {
|
||||
|
||||
// On touch devices, show the OS keyboard
|
||||
showKeyboard: function() {
|
||||
var kbi, skb, l;
|
||||
kbi = $D('keyboardinput');
|
||||
skb = $D('showKeyboard');
|
||||
l = kbi.value.length;
|
||||
if(UI.keyboardVisible === false) {
|
||||
$D('keyboardinput').focus();
|
||||
kbi.focus();
|
||||
kbi.setSelectionRange(l, l); // Move the caret to the end
|
||||
UI.keyboardVisible = true;
|
||||
$D('showKeyboard').className = "noVNC_status_button_selected";
|
||||
skb.className = "noVNC_status_button_selected";
|
||||
} else if(UI.keyboardVisible === true) {
|
||||
$D('keyboardinput').blur();
|
||||
$D('showKeyboard').className = "noVNC_status_button";
|
||||
kbi.blur();
|
||||
skb.className = "noVNC_status_button";
|
||||
UI.keyboardVisible = false;
|
||||
}
|
||||
},
|
||||
|
||||
keepKeyboard: function() {
|
||||
clearTimeout(UI.hideKeyboardTimeout);
|
||||
if(UI.keyboardVisible === true) {
|
||||
$D('keyboardinput').focus();
|
||||
$D('showKeyboard').className = "noVNC_status_button_selected";
|
||||
} else if(UI.keyboardVisible === false) {
|
||||
$D('keyboardinput').blur();
|
||||
$D('showKeyboard').className = "noVNC_status_button";
|
||||
}
|
||||
},
|
||||
|
||||
// When keypress events are left uncought, catch the input events from
|
||||
// the keyboardinput element instead and send the corresponding key events.
|
||||
keyInput: function(event) {
|
||||
var elem, input, len;
|
||||
elem = $D('keyboardinput');
|
||||
input = event.target.value;
|
||||
len = (elem.selectionStart > input.length) ? elem.selectionStart : input.length;
|
||||
|
||||
if (len < 1) { // something removed?
|
||||
UI.rfb.sendKey(0xff08); // send BACKSPACE
|
||||
} else if (len > 1) { // new input?
|
||||
for (var i = len-1; i > 0; i -= 1) {
|
||||
// HTML does not consider trailing whitespaces as a part of the string
|
||||
// and they are therefore undefined.
|
||||
if (input[len-i] !== undefined) {
|
||||
UI.rfb.sendKey(input.charCodeAt(len-i)); // send charCode
|
||||
} else {
|
||||
UI.rfb.sendKey(0x0020); // send SPACE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In order to be able to delete text which has been written in
|
||||
// another session there has to always be text in the
|
||||
// keyboardinput element with which backspace can interact.
|
||||
// We also need to reset the input field text to avoid overflow.
|
||||
elem.value = "x";
|
||||
},
|
||||
|
||||
keyInputBlur: function() {
|
||||
$D('showKeyboard').className = "noVNC_status_button";
|
||||
//Weird bug in iOS if you change keyboardVisible
|
||||
//here it does not actually occur so next time
|
||||
//you click keyboard icon it doesnt work.
|
||||
setTimeout(function() { UI.setKeyboard(); },100);
|
||||
UI.hideKeyboardTimeout = setTimeout(function() { UI.setKeyboard(); },100);
|
||||
},
|
||||
|
||||
showExtraKeys: function() {
|
||||
UI.keepKeyboard();
|
||||
if(UI.extraKeysVisible === false) {
|
||||
$D('toggleCtrlButton').style.display = "inline";
|
||||
$D('toggleAltButton').style.display = "inline";
|
||||
$D('sendTabButton').style.display = "inline";
|
||||
$D('sendEscButton').style.display = "inline";
|
||||
$D('showExtraKeysButton').className = "noVNC_status_button_selected";
|
||||
UI.extraKeysVisible = true;
|
||||
} else if(UI.extraKeysVisible === true) {
|
||||
$D('toggleCtrlButton').style.display = "";
|
||||
$D('toggleAltButton').style.display = "";
|
||||
$D('sendTabButton').style.display = "";
|
||||
$D('sendEscButton').style.display = "";
|
||||
$D('showExtraKeysButton').className = "noVNC_status_button";
|
||||
UI.extraKeysVisible = false;
|
||||
}
|
||||
},
|
||||
|
||||
toggleCtrl: function() {
|
||||
UI.keepKeyboard();
|
||||
if(UI.ctrlOn === false) {
|
||||
UI.rfb.sendKey(XK_Control_L, true);
|
||||
$D('toggleCtrlButton').className = "noVNC_status_button_selected";
|
||||
UI.ctrlOn = true;
|
||||
} else if(UI.ctrlOn === true) {
|
||||
UI.rfb.sendKey(XK_Control_L, false);
|
||||
$D('toggleCtrlButton').className = "noVNC_status_button";
|
||||
UI.ctrlOn = false;
|
||||
}
|
||||
},
|
||||
|
||||
toggleAlt: function() {
|
||||
UI.keepKeyboard();
|
||||
if(UI.altOn === false) {
|
||||
UI.rfb.sendKey(XK_Alt_L, true);
|
||||
$D('toggleAltButton').className = "noVNC_status_button_selected";
|
||||
UI.altOn = true;
|
||||
} else if(UI.altOn === true) {
|
||||
UI.rfb.sendKey(XK_Alt_L, false);
|
||||
$D('toggleAltButton').className = "noVNC_status_button";
|
||||
UI.altOn = false;
|
||||
}
|
||||
},
|
||||
|
||||
sendTab: function() {
|
||||
UI.keepKeyboard();
|
||||
UI.rfb.sendKey(XK_Tab);
|
||||
},
|
||||
|
||||
sendEsc: function() {
|
||||
UI.keepKeyboard();
|
||||
UI.rfb.sendKey(XK_Escape);
|
||||
},
|
||||
|
||||
setKeyboard: function() {
|
||||
|
67
src/sunstone/public/vendor/noVNC/util.js
vendored
67
src/sunstone/public/vendor/noVNC/util.js
vendored
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* noVNC: HTML5 VNC client
|
||||
* Copyright (C) 2012 Joel Martin
|
||||
* Licensed under LGPL-3 (see LICENSE.txt)
|
||||
* Licensed under MPL 2.0 (see LICENSE.txt)
|
||||
*
|
||||
* See README.md for usage and integration instructions.
|
||||
*/
|
||||
@ -207,6 +207,65 @@ Util.conf_defaults = function(cfg, api, defaults, arr) {
|
||||
* Cross-browser routines
|
||||
*/
|
||||
|
||||
|
||||
// Dynamically load scripts without using document.write()
|
||||
// Reference: http://unixpapa.com/js/dyna.html
|
||||
//
|
||||
// Handles the case where load_scripts is invoked from a script that
|
||||
// itself is loaded via load_scripts. Once all scripts are loaded the
|
||||
// window.onscriptsloaded handler is called (if set).
|
||||
Util.get_include_uri = function() {
|
||||
return (typeof INCLUDE_URI !== "undefined") ? INCLUDE_URI : "include/";
|
||||
}
|
||||
Util._loading_scripts = [];
|
||||
Util._pending_scripts = [];
|
||||
Util.load_scripts = function(files) {
|
||||
var head = document.getElementsByTagName('head')[0], script,
|
||||
ls = Util._loading_scripts, ps = Util._pending_scripts;
|
||||
for (var f=0; f<files.length; f++) {
|
||||
script = document.createElement('script');
|
||||
script.type = 'text/javascript';
|
||||
script.src = Util.get_include_uri() + files[f];
|
||||
//console.log("loading script: " + script.src);
|
||||
script.onload = script.onreadystatechange = function (e) {
|
||||
while (ls.length > 0 && (ls[0].readyState === 'loaded' ||
|
||||
ls[0].readyState === 'complete')) {
|
||||
// For IE, append the script to trigger execution
|
||||
var s = ls.shift();
|
||||
//console.log("loaded script: " + s.src);
|
||||
head.appendChild(s);
|
||||
}
|
||||
if (!this.readyState ||
|
||||
(Util.Engine.presto && this.readyState === 'loaded') ||
|
||||
this.readyState === 'complete') {
|
||||
if (ps.indexOf(this) >= 0) {
|
||||
this.onload = this.onreadystatechange = null;
|
||||
//console.log("completed script: " + this.src);
|
||||
ps.splice(ps.indexOf(this), 1);
|
||||
|
||||
// Call window.onscriptsload after last script loads
|
||||
if (ps.length === 0 && window.onscriptsload) {
|
||||
window.onscriptsload();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
// In-order script execution tricks
|
||||
if (Util.Engine.trident) {
|
||||
// For IE wait until readyState is 'loaded' before
|
||||
// appending it which will trigger execution
|
||||
// http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
|
||||
ls.push(script);
|
||||
} else {
|
||||
// For webkit and firefox set async=false and append now
|
||||
// https://developer.mozilla.org/en-US/docs/HTML/Element/script
|
||||
script.async = false;
|
||||
head.appendChild(script);
|
||||
}
|
||||
ps.push(script);
|
||||
}
|
||||
}
|
||||
|
||||
// Get DOM element position on page
|
||||
Util.getPosition = function (obj) {
|
||||
var x = 0, y = 0;
|
||||
@ -239,7 +298,11 @@ Util.getEventPosition = function (e, obj, scale) {
|
||||
if (typeof scale === "undefined") {
|
||||
scale = 1;
|
||||
}
|
||||
return {'x': (docX - pos.x) / scale, 'y': (docY - pos.y) / scale};
|
||||
var realx = docX - pos.x;
|
||||
var realy = docY - pos.y;
|
||||
var x = Math.max(Math.min(realx, obj.width-1), 0);
|
||||
var y = Math.max(Math.min(realy, obj.height-1), 0);
|
||||
return {'x': x / scale, 'y': y / scale, 'realx': realx / scale, 'realy': realy / scale};
|
||||
};
|
||||
|
||||
|
||||
|
Binary file not shown.
@ -1,49 +1,69 @@
|
||||
// Copyright: Hiroshi Ichikawa <http://gimite.net/en/>
|
||||
// License: New BSD License
|
||||
// Reference: http://dev.w3.org/html5/websockets/
|
||||
// Reference: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol
|
||||
// Reference: http://tools.ietf.org/html/rfc6455
|
||||
|
||||
(function() {
|
||||
|
||||
if (window.WebSocket && !window.WEB_SOCKET_FORCE_FLASH) return;
|
||||
|
||||
var console = window.console;
|
||||
if (!console || !console.log || !console.error) {
|
||||
console = {log: function(){ }, error: function(){ }};
|
||||
if (window.WEB_SOCKET_FORCE_FLASH) {
|
||||
// Keeps going.
|
||||
} else if (window.WebSocket) {
|
||||
return;
|
||||
} else if (window.MozWebSocket) {
|
||||
// Firefox.
|
||||
window.WebSocket = MozWebSocket;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!swfobject.hasFlashPlayerVersion("10.0.0")) {
|
||||
console.error("Flash Player >= 10.0.0 is required.");
|
||||
var logger;
|
||||
if (window.WEB_SOCKET_LOGGER) {
|
||||
logger = WEB_SOCKET_LOGGER;
|
||||
} else if (window.console && window.console.log && window.console.error) {
|
||||
// In some environment, console is defined but console.log or console.error is missing.
|
||||
logger = window.console;
|
||||
} else {
|
||||
logger = {log: function(){ }, error: function(){ }};
|
||||
}
|
||||
|
||||
// swfobject.hasFlashPlayerVersion("10.0.0") doesn't work with Gnash.
|
||||
if (swfobject.getFlashPlayerVersion().major < 10) {
|
||||
logger.error("Flash Player >= 10.0.0 is required.");
|
||||
return;
|
||||
}
|
||||
if (location.protocol == "file:") {
|
||||
console.error(
|
||||
logger.error(
|
||||
"WARNING: web-socket-js doesn't work in file:///... URL " +
|
||||
"unless you set Flash Security Settings properly. " +
|
||||
"Open the page via Web server i.e. http://...");
|
||||
}
|
||||
|
||||
/**
|
||||
* This class represents a faux web socket.
|
||||
* Our own implementation of WebSocket class using Flash.
|
||||
* @param {string} url
|
||||
* @param {string} protocol
|
||||
* @param {array or string} protocols
|
||||
* @param {string} proxyHost
|
||||
* @param {int} proxyPort
|
||||
* @param {string} headers
|
||||
*/
|
||||
WebSocket = function(url, protocol, proxyHost, proxyPort, headers) {
|
||||
window.WebSocket = function(url, protocols, proxyHost, proxyPort, headers) {
|
||||
var self = this;
|
||||
self.__id = WebSocket.__nextId++;
|
||||
WebSocket.__instances[self.__id] = self;
|
||||
self.readyState = WebSocket.CONNECTING;
|
||||
self.bufferedAmount = 0;
|
||||
self.__events = {};
|
||||
if (!protocols) {
|
||||
protocols = [];
|
||||
} else if (typeof protocols == "string") {
|
||||
protocols = [protocols];
|
||||
}
|
||||
// Uses setTimeout() to make sure __createFlash() runs after the caller sets ws.onopen etc.
|
||||
// Otherwise, when onopen fires immediately, onopen is called before it is set.
|
||||
setTimeout(function() {
|
||||
self.__createTask = setTimeout(function() {
|
||||
WebSocket.__addTask(function() {
|
||||
self.__createTask = null;
|
||||
WebSocket.__flash.create(
|
||||
self.__id, url, protocol, proxyHost || null, proxyPort || 0, headers || null);
|
||||
self.__id, url, protocols, proxyHost || null, proxyPort || 0, headers || null);
|
||||
});
|
||||
}, 0);
|
||||
};
|
||||
@ -78,6 +98,12 @@
|
||||
* Close this web socket gracefully.
|
||||
*/
|
||||
WebSocket.prototype.close = function() {
|
||||
if (this.__createTask) {
|
||||
clearTimeout(this.__createTask);
|
||||
this.__createTask = null;
|
||||
this.readyState = WebSocket.CLOSED;
|
||||
return;
|
||||
}
|
||||
if (this.readyState == WebSocket.CLOSED || this.readyState == WebSocket.CLOSING) {
|
||||
return;
|
||||
}
|
||||
@ -131,7 +157,7 @@
|
||||
events[i](event);
|
||||
}
|
||||
var handler = this["on" + event.type];
|
||||
if (handler) handler(event);
|
||||
if (handler) handler.apply(this, [event]);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -139,16 +165,22 @@
|
||||
* @param {Object} flashEvent
|
||||
*/
|
||||
WebSocket.prototype.__handleEvent = function(flashEvent) {
|
||||
|
||||
if ("readyState" in flashEvent) {
|
||||
this.readyState = flashEvent.readyState;
|
||||
}
|
||||
if ("protocol" in flashEvent) {
|
||||
this.protocol = flashEvent.protocol;
|
||||
}
|
||||
|
||||
var jsEvent;
|
||||
if (flashEvent.type == "open" || flashEvent.type == "error") {
|
||||
jsEvent = this.__createSimpleEvent(flashEvent.type);
|
||||
} else if (flashEvent.type == "close") {
|
||||
// TODO implement jsEvent.wasClean
|
||||
jsEvent = this.__createSimpleEvent("close");
|
||||
jsEvent.wasClean = flashEvent.wasClean ? true : false;
|
||||
jsEvent.code = flashEvent.code;
|
||||
jsEvent.reason = flashEvent.reason;
|
||||
} else if (flashEvent.type == "message") {
|
||||
var data = decodeURIComponent(flashEvent.message);
|
||||
jsEvent = this.__createMessageEvent("message", data);
|
||||
@ -157,6 +189,7 @@
|
||||
}
|
||||
|
||||
this.dispatchEvent(jsEvent);
|
||||
|
||||
};
|
||||
|
||||
WebSocket.prototype.__createSimpleEvent = function(type) {
|
||||
@ -188,6 +221,9 @@
|
||||
WebSocket.CLOSING = 2;
|
||||
WebSocket.CLOSED = 3;
|
||||
|
||||
// Field to check implementation of WebSocket.
|
||||
WebSocket.__isFlashImplementation = true;
|
||||
WebSocket.__initialized = false;
|
||||
WebSocket.__flash = null;
|
||||
WebSocket.__instances = {};
|
||||
WebSocket.__tasks = [];
|
||||
@ -207,16 +243,31 @@
|
||||
* Loads WebSocketMain.swf and creates WebSocketMain object in Flash.
|
||||
*/
|
||||
WebSocket.__initialize = function() {
|
||||
if (WebSocket.__flash) return;
|
||||
|
||||
if (WebSocket.__initialized) return;
|
||||
WebSocket.__initialized = true;
|
||||
|
||||
if (WebSocket.__swfLocation) {
|
||||
// For backword compatibility.
|
||||
window.WEB_SOCKET_SWF_LOCATION = WebSocket.__swfLocation;
|
||||
}
|
||||
if (!window.WEB_SOCKET_SWF_LOCATION) {
|
||||
console.error("[WebSocket] set WEB_SOCKET_SWF_LOCATION to location of WebSocketMain.swf");
|
||||
logger.error("[WebSocket] set WEB_SOCKET_SWF_LOCATION to location of WebSocketMain.swf");
|
||||
return;
|
||||
}
|
||||
if (!window.WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR &&
|
||||
!WEB_SOCKET_SWF_LOCATION.match(/(^|\/)WebSocketMainInsecure\.swf(\?.*)?$/) &&
|
||||
WEB_SOCKET_SWF_LOCATION.match(/^\w+:\/\/([^\/]+)/)) {
|
||||
var swfHost = RegExp.$1;
|
||||
if (location.host != swfHost) {
|
||||
logger.error(
|
||||
"[WebSocket] You must host HTML and WebSocketMain.swf in the same host " +
|
||||
"('" + location.host + "' != '" + swfHost + "'). " +
|
||||
"See also 'How to host HTML file and SWF file in different domains' section " +
|
||||
"in README.md. If you use WebSocketMainInsecure.swf, you can suppress this message " +
|
||||
"by WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true;");
|
||||
}
|
||||
}
|
||||
var container = document.createElement("div");
|
||||
container.id = "webSocketContainer";
|
||||
// Hides Flash box. We cannot use display: none or visibility: hidden because it prevents
|
||||
@ -250,9 +301,11 @@
|
||||
null,
|
||||
function(e) {
|
||||
if (!e.success) {
|
||||
console.error("[WebSocket] swfobject.embedSWF failed");
|
||||
logger.error("[WebSocket] swfobject.embedSWF failed");
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@ -287,7 +340,7 @@
|
||||
WebSocket.__instances[events[i].webSocketId].__handleEvent(events[i]);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
logger.error(e);
|
||||
}
|
||||
}, 0);
|
||||
return true;
|
||||
@ -295,12 +348,12 @@
|
||||
|
||||
// Called by Flash.
|
||||
WebSocket.__log = function(message) {
|
||||
console.log(decodeURIComponent(message));
|
||||
logger.log(decodeURIComponent(message));
|
||||
};
|
||||
|
||||
// Called by Flash.
|
||||
WebSocket.__error = function(message) {
|
||||
console.error(decodeURIComponent(message));
|
||||
logger.error(decodeURIComponent(message));
|
||||
};
|
||||
|
||||
WebSocket.__addTask = function(task) {
|
||||
@ -327,15 +380,12 @@
|
||||
};
|
||||
|
||||
if (!window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION) {
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener("load", function(){
|
||||
WebSocket.__initialize();
|
||||
}, false);
|
||||
} else {
|
||||
window.attachEvent("onload", function(){
|
||||
WebSocket.__initialize();
|
||||
});
|
||||
}
|
||||
// NOTE:
|
||||
// This fires immediately if web_socket.js is dynamically loaded after
|
||||
// the document is loaded.
|
||||
swfobject.addDomLoadEvent(function() {
|
||||
WebSocket.__initialize();
|
||||
});
|
||||
}
|
||||
|
||||
})();
|
||||
|
116
src/sunstone/public/vendor/noVNC/websock.js
vendored
116
src/sunstone/public/vendor/noVNC/websock.js
vendored
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Websock: high-performance binary WebSockets
|
||||
* Copyright (C) 2012 Joel Martin
|
||||
* Licensed under LGPL-3 (see LICENSE.txt)
|
||||
* Licensed under MPL 2.0 (see LICENSE.txt)
|
||||
*
|
||||
* Websock is similar to the standard WebSocket object but Websock
|
||||
* enables communication with raw TCP sockets (i.e. the binary stream)
|
||||
@ -35,23 +35,14 @@ if (window.WebSocket && !window.WEB_SOCKET_FORCE_FLASH) {
|
||||
|
||||
Websock_native = false;
|
||||
(function () {
|
||||
function get_INCLUDE_URI() {
|
||||
return (typeof INCLUDE_URI !== "undefined") ?
|
||||
INCLUDE_URI : "include/";
|
||||
}
|
||||
|
||||
var start = "<script src='" + get_INCLUDE_URI(),
|
||||
end = "'><\/script>", extra = "";
|
||||
|
||||
window.WEB_SOCKET_SWF_LOCATION = get_INCLUDE_URI() +
|
||||
window.WEB_SOCKET_SWF_LOCATION = Util.get_include_uri() +
|
||||
"web-socket-js/WebSocketMain.swf";
|
||||
if (Util.Engine.trident) {
|
||||
Util.Debug("Forcing uncached load of WebSocketMain.swf");
|
||||
window.WEB_SOCKET_SWF_LOCATION += "?" + Math.random();
|
||||
}
|
||||
extra += start + "web-socket-js/swfobject.js" + end;
|
||||
extra += start + "web-socket-js/web_socket.js" + end;
|
||||
document.write(extra);
|
||||
Util.load_scripts(["web-socket-js/swfobject.js",
|
||||
"web-socket-js/web_socket.js"]);
|
||||
}());
|
||||
}
|
||||
|
||||
@ -61,6 +52,7 @@ function Websock() {
|
||||
|
||||
var api = {}, // Public API
|
||||
websocket = null, // WebSocket object
|
||||
mode = 'base64', // Current WebSocket mode: 'binary', 'base64'
|
||||
rQ = [], // Receive queue
|
||||
rQi = 0, // Receive queue index
|
||||
rQmax = 10000, // Max receive queue size before compacting
|
||||
@ -127,9 +119,7 @@ function rQshiftStr(len) {
|
||||
if (typeof(len) === 'undefined') { len = rQlen(); }
|
||||
var arr = rQ.slice(rQi, rQi + len);
|
||||
rQi += len;
|
||||
return arr.map(function (num) {
|
||||
return String.fromCharCode(num); } ).join('');
|
||||
|
||||
return String.fromCharCode.apply(null, arr);
|
||||
}
|
||||
function rQshiftBytes(len) {
|
||||
if (typeof(len) === 'undefined') { len = rQlen(); }
|
||||
@ -169,14 +159,27 @@ function rQwait(msg, num, goback) {
|
||||
//
|
||||
|
||||
function encode_message() {
|
||||
/* base64 encode */
|
||||
return Base64.encode(sQ);
|
||||
if (mode === 'binary') {
|
||||
// Put in a binary arraybuffer
|
||||
return (new Uint8Array(sQ)).buffer;
|
||||
} else {
|
||||
// base64 encode
|
||||
return Base64.encode(sQ);
|
||||
}
|
||||
}
|
||||
|
||||
function decode_message(data) {
|
||||
//Util.Debug(">> decode_message: " + data);
|
||||
/* base64 decode */
|
||||
rQ = rQ.concat(Base64.decode(data, 0));
|
||||
if (mode === 'binary') {
|
||||
// push arraybuffer values onto the end
|
||||
var u8 = new Uint8Array(data);
|
||||
for (var i = 0; i < u8.length; i++) {
|
||||
rQ.push(u8[i]);
|
||||
}
|
||||
} else {
|
||||
// base64 decode and concat to the end
|
||||
rQ = rQ.concat(Base64.decode(data, 0));
|
||||
}
|
||||
//Util.Debug(">> decode_message, rQ: " + rQ);
|
||||
}
|
||||
|
||||
@ -259,30 +262,88 @@ function on(evt, handler) {
|
||||
eventHandlers[evt] = handler;
|
||||
}
|
||||
|
||||
function init() {
|
||||
function init(protocols) {
|
||||
rQ = [];
|
||||
rQi = 0;
|
||||
sQ = [];
|
||||
websocket = null;
|
||||
|
||||
var bt = false,
|
||||
wsbt = false,
|
||||
try_binary = false;
|
||||
|
||||
// Check for full typed array support
|
||||
if (('Uint8Array' in window) &&
|
||||
('set' in Uint8Array.prototype)) {
|
||||
bt = true;
|
||||
}
|
||||
|
||||
// Check for full binary type support in WebSockets
|
||||
// TODO: this sucks, the property should exist on the prototype
|
||||
// but it does not.
|
||||
try {
|
||||
if (bt && ('binaryType' in (new WebSocket("ws://localhost:17523")))) {
|
||||
Util.Info("Detected binaryType support in WebSockets");
|
||||
wsbt = true;
|
||||
}
|
||||
} catch (exc) {
|
||||
// Just ignore failed test localhost connections
|
||||
}
|
||||
|
||||
// Default protocols if not specified
|
||||
if (typeof(protocols) === "undefined") {
|
||||
if (wsbt) {
|
||||
protocols = ['binary', 'base64'];
|
||||
} else {
|
||||
protocols = 'base64';
|
||||
}
|
||||
}
|
||||
|
||||
// If no binary support, make sure it was not requested
|
||||
if (!wsbt) {
|
||||
if (protocols === 'binary') {
|
||||
throw("WebSocket binary sub-protocol requested but not supported");
|
||||
}
|
||||
if (typeof(protocols) === "object") {
|
||||
var new_protocols = [];
|
||||
for (var i = 0; i < protocols.length; i++) {
|
||||
if (protocols[i] === 'binary') {
|
||||
Util.Error("Skipping unsupported WebSocket binary sub-protocol");
|
||||
} else {
|
||||
new_protocols.push(protocols[i]);
|
||||
}
|
||||
}
|
||||
if (new_protocols.length > 0) {
|
||||
protocols = new_protocols;
|
||||
} else {
|
||||
throw("Only WebSocket binary sub-protocol was requested and not supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return protocols;
|
||||
}
|
||||
|
||||
function open(uri) {
|
||||
init();
|
||||
function open(uri, protocols) {
|
||||
protocols = init(protocols);
|
||||
|
||||
if (test_mode) {
|
||||
websocket = {};
|
||||
} else {
|
||||
websocket = new WebSocket(uri, 'base64');
|
||||
// TODO: future native binary support
|
||||
//websocket = new WebSocket(uri, ['binary', 'base64']);
|
||||
websocket = new WebSocket(uri, protocols);
|
||||
if (protocols.indexOf('binary') >= 0) {
|
||||
websocket.binaryType = 'arraybuffer';
|
||||
}
|
||||
}
|
||||
|
||||
websocket.onmessage = recv_message;
|
||||
websocket.onopen = function() {
|
||||
Util.Debug(">> WebSock.onopen");
|
||||
if (websocket.protocol) {
|
||||
mode = websocket.protocol;
|
||||
Util.Info("Server chose sub-protocol: " + websocket.protocol);
|
||||
} else {
|
||||
mode = 'base64';
|
||||
Util.Error("Server select no sub-protocol!: " + websocket.protocol);
|
||||
}
|
||||
eventHandlers.open();
|
||||
@ -313,8 +374,9 @@ function close() {
|
||||
|
||||
// Override internal functions for testing
|
||||
// Takes a send function, returns reference to recv function
|
||||
function testMode(override_send) {
|
||||
function testMode(override_send, data_mode) {
|
||||
test_mode = true;
|
||||
mode = data_mode;
|
||||
api.send = override_send;
|
||||
api.close = function () {};
|
||||
return recv_message;
|
||||
|
99
src/sunstone/public/vendor/noVNC/webutil.js
vendored
99
src/sunstone/public/vendor/noVNC/webutil.js
vendored
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* noVNC: HTML5 VNC client
|
||||
* Copyright (C) 2012 Joel Martin
|
||||
* Licensed under LGPL-3 (see LICENSE.txt)
|
||||
* Copyright (C) 2013 NTT corp.
|
||||
* Licensed under MPL 2.0 (see LICENSE.txt)
|
||||
*
|
||||
* See README.md for usage and integration instructions.
|
||||
*/
|
||||
@ -37,14 +38,16 @@ if (!window.$D) {
|
||||
*/
|
||||
|
||||
// init log level reading the logging HTTP param
|
||||
WebUtil.init_logging = function() {
|
||||
Util._log_level = (document.location.href.match(
|
||||
/logging=([A-Za-z0-9\._\-]*)/) ||
|
||||
['', Util._log_level])[1];
|
||||
|
||||
WebUtil.init_logging = function(level) {
|
||||
if (typeof level !== "undefined") {
|
||||
Util._log_level = level;
|
||||
} else {
|
||||
Util._log_level = (document.location.href.match(
|
||||
/logging=([A-Za-z0-9\._\-]*)/) ||
|
||||
['', Util._log_level])[1];
|
||||
}
|
||||
Util.init_logging();
|
||||
};
|
||||
WebUtil.init_logging();
|
||||
|
||||
|
||||
WebUtil.dirObj = function (obj, depth, parent) {
|
||||
@ -75,9 +78,14 @@ WebUtil.dirObj = function (obj, depth, parent) {
|
||||
|
||||
// Read a query string variable
|
||||
WebUtil.getQueryVar = function(name, defVal) {
|
||||
var re = new RegExp('[?][^#]*' + name + '=([^&#]*)');
|
||||
var re = new RegExp('[?][^#]*' + name + '=([^&#]*)'),
|
||||
match = document.location.href.match(re);
|
||||
if (typeof defVal === 'undefined') { defVal = null; }
|
||||
return (document.location.href.match(re) || ['',defVal])[1];
|
||||
if (match) {
|
||||
return decodeURIComponent(match[1]);
|
||||
} else {
|
||||
return defVal;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -87,16 +95,20 @@ WebUtil.getQueryVar = function(name, defVal) {
|
||||
|
||||
// No days means only for this browser session
|
||||
WebUtil.createCookie = function(name,value,days) {
|
||||
var date, expires;
|
||||
var date, expires, secure;
|
||||
if (days) {
|
||||
date = new Date();
|
||||
date.setTime(date.getTime()+(days*24*60*60*1000));
|
||||
expires = "; expires="+date.toGMTString();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
expires = "";
|
||||
}
|
||||
document.cookie = name+"="+value+expires+"; path=/";
|
||||
if (document.location.protocol === "https:") {
|
||||
secure = "; secure";
|
||||
} else {
|
||||
secure = "";
|
||||
}
|
||||
document.cookie = name+"="+value+expires+"; path=/"+secure;
|
||||
};
|
||||
|
||||
WebUtil.readCookie = function(name, defaultValue) {
|
||||
@ -113,6 +125,67 @@ WebUtil.eraseCookie = function(name) {
|
||||
WebUtil.createCookie(name,"",-1);
|
||||
};
|
||||
|
||||
/*
|
||||
* Setting handling.
|
||||
*/
|
||||
|
||||
WebUtil.initSettings = function(callback) {
|
||||
var callbackArgs = Array.prototype.slice.call(arguments, 1);
|
||||
if (window.chrome && window.chrome.storage) {
|
||||
window.chrome.storage.sync.get(function (cfg) {
|
||||
WebUtil.settings = cfg;
|
||||
console.log(WebUtil.settings);
|
||||
if (callback) {
|
||||
callback.apply(this, callbackArgs);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// No-op
|
||||
if (callback) {
|
||||
callback.apply(this, callbackArgs);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// No days means only for this browser session
|
||||
WebUtil.writeSetting = function(name, value) {
|
||||
if (window.chrome && window.chrome.storage) {
|
||||
//console.log("writeSetting:", name, value);
|
||||
if (WebUtil.settings[name] !== value) {
|
||||
WebUtil.settings[name] = value;
|
||||
window.chrome.storage.sync.set(WebUtil.settings);
|
||||
}
|
||||
} else {
|
||||
localStorage.setItem(name, value);
|
||||
}
|
||||
};
|
||||
|
||||
WebUtil.readSetting = function(name, defaultValue) {
|
||||
var value;
|
||||
if (window.chrome && window.chrome.storage) {
|
||||
value = WebUtil.settings[name];
|
||||
} else {
|
||||
value = localStorage.getItem(name);
|
||||
}
|
||||
if (typeof value === "undefined") {
|
||||
value = null;
|
||||
}
|
||||
if (value === null && typeof defaultValue !== undefined) {
|
||||
return defaultValue;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
WebUtil.eraseSetting = function(name) {
|
||||
if (window.chrome && window.chrome.storage) {
|
||||
window.chrome.storage.sync.remove(name);
|
||||
delete WebUtil.settings[name];
|
||||
} else {
|
||||
localStorage.removeItem(name);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Alternate stylesheet selection
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user