Revision a69735ae
Added by UXabre over 5 years ago
README.md | ||
---|---|---|
* lib/tasks/convert.rake is (c) 2008, Matson Systems, Inc. under Revised BSD license.
|
||
* extras/noVNC/websockify is (c) 2011, Joel Martin under LGPL v3 license.
|
||
* vendor/assets/fonts/ is (c) 2011-2016, Red Hat Inc. under SIL Open Font License v1.1 or LGPL v2.1 licenses.
|
||
* vendor/assets/javascripts/noVNC/ is (c) 1999 AT&T Laboratories Cambridge, (c) 1996 Widget Workshop, Inc., (c) 1996 Jef Poskanzer <jef@acme.com>, (c) 2011 Joel Martin, (c) Hiroshi Ichikawa <http://gimite.net/en/>, (c) Martijn Pieters <mj@digicool.com>, Samuel Sieb <samuel@sieb.net> under (MPL 1.1 or GPL v2+ or LGPL v2.1+) and LGPL v3 and LGPL v2+ and MIT and Revised BSD licenses.
|
||
* vendor/assets/javascripts/jquery.flot.axislabels.js is (c) 2010 Xuan Luo under MIT license.
|
||
* app/assets/images/RancherOS.png is (c) 2018 Rancher Labs, Inc.
|
||
|
app/assets/javascripts/noVNC.js | ||
---|---|---|
"use strict";
|
||
var rfb;
|
||
|
||
function sendCtrlAltDel() {
|
||
rfb.sendCtrlAltDel();
|
||
return false;
|
||
}
|
||
|
||
function updateState(rfb, state, oldstate, msg) {
|
||
var s, sb, cad, level;
|
||
s = $D('noVNC_status');
|
||
sb = $D('noVNC_status');
|
||
cad = $D('sendCtrlAltDelButton');
|
||
switch (state) {
|
||
case 'failed': level = "danger"; break;
|
||
case 'fatal': level = "danger"; break;
|
||
case 'normal': level = "success"; break;
|
||
case 'disconnected': level = "default"; break;
|
||
case 'loaded': level = "success"; break;
|
||
default: level = "warning"; break;
|
||
}
|
||
|
||
cad.disabled = state !== "normal";
|
||
|
||
if (typeof(msg) !== 'undefined') {
|
||
sb.setAttribute("class", "col-md-12 label label-" + level);
|
||
s.innerHTML = msg;
|
||
}
|
||
}
|
||
|
||
$(function() {
|
||
$D('sendCtrlAltDelButton').style.display = "inline";
|
||
$D('sendCtrlAltDelButton').onclick = sendCtrlAltDel;
|
||
|
||
var host = window.location.hostname;
|
||
var port = $('#vnc').attr('data-port');
|
||
var password = $('#vnc').attr('data-password');
|
||
var path = "";
|
||
rfb = new RFB({'target': $D('noVNC_canvas'),
|
||
'encrypt': $('#vnc').data('encrypt'),
|
||
'true_color': true,
|
||
'local_cursor': true,
|
||
'shared': true,
|
||
'view_only': false,
|
||
'updateState': updateState});
|
||
rfb.connect(host, port, password, path);
|
||
});
|
app/views/hosts/console/vnc.html.erb | ||
---|---|---|
<%= javascript("noVNC/util", "noVNC/webutil", "noVNC/base64", "noVNC/websock",
|
||
"noVNC/des", "noVNC/input", "noVNC/display", "noVNC/rfb",
|
||
"noVNC/jsunzip", "noVNC/ui", "noVNC") %>
|
||
|
||
<% title "#{@console[:name]}" %>
|
||
<%= title_actions(
|
||
button_group(link_to("Ctrl-Alt-Del", "#", :id => "sendCtrlAltDelButton", :class => "btn btn-default"),
|
||
... | ... | |
<div id="noVNC_status" class="col-md-12 label">Loading ...</div>
|
||
</div>
|
||
|
||
<canvas id="noVNC_canvas" class="console-screen">
|
||
<%= _('Canvas not supported.') %>
|
||
</canvas>
|
||
<div id="noVNC_screen" class="console-screen"></div>
|
||
</div>
|
config/initializers/assets.rb | ||
---|---|---|
host_edit_interfaces
|
||
hosts
|
||
host_checkbox
|
||
noVNC/base64
|
||
noVNC/des
|
||
noVNC/display
|
||
noVNC/input
|
||
noVNC/jsunzip
|
||
noVNC/logo
|
||
noVNC/playback
|
||
noVNC/rfb
|
||
noVNC/ui
|
||
noVNC/util
|
||
noVNC/websock
|
||
noVNC/webutil
|
||
noVNC
|
||
reports
|
||
spice
|
||
charts
|
config/webpack.config.js | ||
---|---|---|
rules: [
|
||
{
|
||
test: /\.js$/,
|
||
exclude: /node_modules/,
|
||
// Include novnc in webpack, transpiling is needed for phantomjs (which does not support ES6) to run tests
|
||
exclude: /node_modules(?!\/@novnc)/,
|
||
loader: 'babel-loader',
|
||
options: {
|
||
'presets': [
|
config/webpack.vendor.js | ||
---|---|---|
'jstz',
|
||
'urijs',
|
||
'uuid',
|
||
'@novnc/novnc/core/rfb.js',
|
||
];
|
package.json | ||
---|---|---|
"phantomjs-prebuilt": "^2.1.0"
|
||
},
|
||
"dependencies": {
|
||
"@novnc/novnc": "^1.0.0",
|
||
"axios": "^0.17.1",
|
||
"babel-polyfill": "^6.26.0",
|
||
"bootstrap-sass": "^3.3.7",
|
vendor/assets/javascripts/noVNC/base64.js | ||
---|---|---|
/*
|
||
* Modified from:
|
||
* http://lxr.mozilla.org/mozilla/source/extensions/xml-rpc/src/nsXmlRpcClient.js#956
|
||
*/
|
||
|
||
/* ***** 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 ***** */
|
||
|
||
/*jslint white: false, bitwise: false, plusplus: false */
|
||
/*global console */
|
||
|
||
var Base64 = {
|
||
|
||
/* Convert data (an array of integers) to a Base64 string. */
|
||
toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
|
||
base64Pad : '=',
|
||
|
||
encode: function (data) {
|
||
"use strict";
|
||
var result = '',
|
||
chrTable = Base64.toBase64Table.split(''),
|
||
pad = Base64.base64Pad,
|
||
length = data.length,
|
||
i;
|
||
// Convert every three bytes to 4 ascii characters.
|
||
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];
|
||
}
|
||
|
||
// 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;
|
||
}
|
||
}
|
||
|
||
return result;
|
||
},
|
||
|
||
/* Convert Base64 data to a string */
|
||
toBinaryTable : [
|
||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
|
||
52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
|
||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
|
||
15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
|
||
-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
|
||
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
|
||
],
|
||
|
||
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;
|
||
|
||
if (data_length < 0) { data_length = data.length - offset; }
|
||
|
||
/* Every four characters is 3 resulting numbers */
|
||
result_length = (data_length >> 2) * 3 + Math.floor((data_length%4)/1.5);
|
||
result = new Array(result_length);
|
||
|
||
// Convert one by one.
|
||
for (idx = 0, i = offset; i < data.length; i++) {
|
||
c = binTable[data.charCodeAt(i) & 0x7f];
|
||
padding = (data.charAt(i) === pad);
|
||
// Skip illegal characters and whitespace
|
||
if (c === -1) {
|
||
console.error("Illegal character code " + data.charCodeAt(i) + " at position " + i);
|
||
continue;
|
||
}
|
||
|
||
// Collect data into leftdata, update bitcount
|
||
leftdata = (leftdata << 6) | c;
|
||
leftbits += 6;
|
||
|
||
// If we have 8 or more bits, append 8 bits to the result
|
||
if (leftbits >= 8) {
|
||
leftbits -= 8;
|
||
// Append if not padding.
|
||
if (!padding) {
|
||
result[idx++] = (leftdata >> leftbits) & 0xff;
|
||
}
|
||
leftdata &= (1 << leftbits) - 1;
|
||
}
|
||
}
|
||
|
||
// If there are any bits left, the base64 string was corrupted
|
||
if (leftbits) {
|
||
throw {name: 'Base64-Error',
|
||
message: 'Corrupted base64 string'};
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
}; /* End of Base64 namespace */
|
vendor/assets/javascripts/noVNC/des.js | ||
---|---|---|
/*
|
||
* Ported from Flashlight VNC ActionScript implementation:
|
||
* http://www.wizhelp.com/flashlight-vnc/
|
||
*
|
||
* Full attribution follows:
|
||
*
|
||
* -------------------------------------------------------------------------
|
||
*
|
||
* This DES class has been extracted from package Acme.Crypto for use in VNC.
|
||
* The unnecessary odd parity code has been removed.
|
||
*
|
||
* These changes are:
|
||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||
*
|
||
* This software is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||
*
|
||
|
||
* DesCipher - the DES encryption method
|
||
*
|
||
* The meat of this code is by Dave Zimmerman <dzimm@widget.com>, and is:
|
||
*
|
||
* Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved.
|
||
*
|
||
* Permission to use, copy, modify, and distribute this software
|
||
* and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
|
||
* without fee is hereby granted, provided that this copyright notice is kept
|
||
* intact.
|
||
*
|
||
* WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
|
||
* OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE LIABLE
|
||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
|
||
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
|
||
*
|
||
* THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
|
||
* CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
|
||
* PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
|
||
* NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
|
||
* SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
|
||
* SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
|
||
* PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). WIDGET WORKSHOP
|
||
* SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
|
||
* HIGH RISK ACTIVITIES.
|
||
*
|
||
*
|
||
* The rest is:
|
||
*
|
||
* Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. All rights reserved.
|
||
*
|
||
* Redistribution and use in source and binary forms, with or without
|
||
* modification, are permitted provided that the following conditions
|
||
* are met:
|
||
* 1. Redistributions of source code must retain the above copyright
|
||
* notice, this list of conditions and the following disclaimer.
|
||
* 2. Redistributions in binary form must reproduce the above copyright
|
||
* notice, this list of conditions and the following disclaimer in the
|
||
* documentation and/or other materials provided with the distribution.
|
||
*
|
||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||
* SUCH DAMAGE.
|
||
*
|
||
* Visit the ACME Labs Java page for up-to-date versions of this and other
|
||
* fine Java utilities: http://www.acme.com/java/
|
||
*/
|
||
|
||
"use strict";
|
||
/*jslint white: false, bitwise: false, plusplus: false */
|
||
|
||
function DES(passwd) {
|
||
|
||
// Tables, permutations, S-boxes, etc.
|
||
var PC2 = [13,16,10,23, 0, 4, 2,27,14, 5,20, 9,22,18,11, 3,
|
||
25, 7,15, 6,26,19,12, 1,40,51,30,36,46,54,29,39,
|
||
50,44,32,47,43,48,38,55,33,52,45,41,49,35,28,31 ],
|
||
totrot = [ 1, 2, 4, 6, 8,10,12,14,15,17,19,21,23,25,27,28],
|
||
z = 0x0, a,b,c,d,e,f, SP1,SP2,SP3,SP4,SP5,SP6,SP7,SP8,
|
||
keys = [];
|
||
|
||
a=1<<16; b=1<<24; c=a|b; d=1<<2; e=1<<10; f=d|e;
|
||
SP1 = [c|e,z|z,a|z,c|f,c|d,a|f,z|d,a|z,z|e,c|e,c|f,z|e,b|f,c|d,b|z,z|d,
|
||
z|f,b|e,b|e,a|e,a|e,c|z,c|z,b|f,a|d,b|d,b|d,a|d,z|z,z|f,a|f,b|z,
|
||
a|z,c|f,z|d,c|z,c|e,b|z,b|z,z|e,c|d,a|z,a|e,b|d,z|e,z|d,b|f,a|f,
|
||
c|f,a|d,c|z,b|f,b|d,z|f,a|f,c|e,z|f,b|e,b|e,z|z,a|d,a|e,z|z,c|d];
|
||
a=1<<20; b=1<<31; c=a|b; d=1<<5; e=1<<15; f=d|e;
|
||
SP2 = [c|f,b|e,z|e,a|f,a|z,z|d,c|d,b|f,b|d,c|f,c|e,b|z,b|e,a|z,z|d,c|d,
|
||
a|e,a|d,b|f,z|z,b|z,z|e,a|f,c|z,a|d,b|d,z|z,a|e,z|f,c|e,c|z,z|f,
|
||
z|z,a|f,c|d,a|z,b|f,c|z,c|e,z|e,c|z,b|e,z|d,c|f,a|f,z|d,z|e,b|z,
|
||
z|f,c|e,a|z,b|d,a|d,b|f,b|d,a|d,a|e,z|z,b|e,z|f,b|z,c|d,c|f,a|e];
|
||
a=1<<17; b=1<<27; c=a|b; d=1<<3; e=1<<9; f=d|e;
|
||
SP3 = [z|f,c|e,z|z,c|d,b|e,z|z,a|f,b|e,a|d,b|d,b|d,a|z,c|f,a|d,c|z,z|f,
|
||
b|z,z|d,c|e,z|e,a|e,c|z,c|d,a|f,b|f,a|e,a|z,b|f,z|d,c|f,z|e,b|z,
|
||
c|e,b|z,a|d,z|f,a|z,c|e,b|e,z|z,z|e,a|d,c|f,b|e,b|d,z|e,z|z,c|d,
|
||
b|f,a|z,b|z,c|f,z|d,a|f,a|e,b|d,c|z,b|f,z|f,c|z,a|f,z|d,c|d,a|e];
|
||
a=1<<13; b=1<<23; c=a|b; d=1<<0; e=1<<7; f=d|e;
|
||
SP4 = [c|d,a|f,a|f,z|e,c|e,b|f,b|d,a|d,z|z,c|z,c|z,c|f,z|f,z|z,b|e,b|d,
|
||
z|d,a|z,b|z,c|d,z|e,b|z,a|d,a|e,b|f,z|d,a|e,b|e,a|z,c|e,c|f,z|f,
|
||
b|e,b|d,c|z,c|f,z|f,z|z,z|z,c|z,a|e,b|e,b|f,z|d,c|d,a|f,a|f,z|e,
|
||
c|f,z|f,z|d,a|z,b|d,a|d,c|e,b|f,a|d,a|e,b|z,c|d,z|e,b|z,a|z,c|e];
|
||
a=1<<25; b=1<<30; c=a|b; d=1<<8; e=1<<19; f=d|e;
|
||
SP5 = [z|d,a|f,a|e,c|d,z|e,z|d,b|z,a|e,b|f,z|e,a|d,b|f,c|d,c|e,z|f,b|z,
|
||
a|z,b|e,b|e,z|z,b|d,c|f,c|f,a|d,c|e,b|d,z|z,c|z,a|f,a|z,c|z,z|f,
|
||
z|e,c|d,z|d,a|z,b|z,a|e,c|d,b|f,a|d,b|z,c|e,a|f,b|f,z|d,a|z,c|e,
|
||
c|f,z|f,c|z,c|f,a|e,z|z,b|e,c|z,z|f,a|d,b|d,z|e,z|z,b|e,a|f,b|d];
|
||
a=1<<22; b=1<<29; c=a|b; d=1<<4; e=1<<14; f=d|e;
|
||
SP6 = [b|d,c|z,z|e,c|f,c|z,z|d,c|f,a|z,b|e,a|f,a|z,b|d,a|d,b|e,b|z,z|f,
|
||
z|z,a|d,b|f,z|e,a|e,b|f,z|d,c|d,c|d,z|z,a|f,c|e,z|f,a|e,c|e,b|z,
|
||
b|e,z|d,c|d,a|e,c|f,a|z,z|f,b|d,a|z,b|e,b|z,z|f,b|d,c|f,a|e,c|z,
|
||
a|f,c|e,z|z,c|d,z|d,z|e,c|z,a|f,z|e,a|d,b|f,z|z,c|e,b|z,a|d,b|f];
|
||
a=1<<21; b=1<<26; c=a|b; d=1<<1; e=1<<11; f=d|e;
|
||
SP7 = [a|z,c|d,b|f,z|z,z|e,b|f,a|f,c|e,c|f,a|z,z|z,b|d,z|d,b|z,c|d,z|f,
|
||
b|e,a|f,a|d,b|e,b|d,c|z,c|e,a|d,c|z,z|e,z|f,c|f,a|e,z|d,b|z,a|e,
|
||
b|z,a|e,a|z,b|f,b|f,c|d,c|d,z|d,a|d,b|z,b|e,a|z,c|e,z|f,a|f,c|e,
|
||
z|f,b|d,c|f,c|z,a|e,z|z,z|d,c|f,z|z,a|f,c|z,z|e,b|d,b|e,z|e,a|d];
|
||
a=1<<18; b=1<<28; c=a|b; d=1<<6; e=1<<12; f=d|e;
|
||
SP8 = [b|f,z|e,a|z,c|f,b|z,b|f,z|d,b|z,a|d,c|z,c|f,a|e,c|e,a|f,z|e,z|d,
|
||
c|z,b|d,b|e,z|f,a|e,a|d,c|d,c|e,z|f,z|z,z|z,c|d,b|d,b|e,a|f,a|z,
|
||
a|f,a|z,c|e,z|e,z|d,c|d,z|e,a|f,b|e,z|d,b|d,c|z,c|d,b|z,a|z,b|f,
|
||
z|z,c|f,a|d,b|d,c|z,b|e,b|f,z|z,c|f,a|e,a|e,z|f,z|f,a|d,b|z,c|e];
|
||
|
||
// Set the key.
|
||
function setKeys(keyBlock) {
|
||
var i, j, l, m, n, o, pc1m = [], pcr = [], kn = [],
|
||
raw0, raw1, rawi, KnLi;
|
||
|
||
for (j = 0, l = 56; j < 56; ++j, l-=8) {
|
||
l += l<-5 ? 65 : l<-3 ? 31 : l<-1 ? 63 : l===27 ? 35 : 0; // PC1
|
||
m = l & 0x7;
|
||
pc1m[j] = ((keyBlock[l >>> 3] & (1<<m)) !== 0) ? 1: 0;
|
||
}
|
||
|
||
for (i = 0; i < 16; ++i) {
|
||
m = i << 1;
|
||
n = m + 1;
|
||
kn[m] = kn[n] = 0;
|
||
for (o=28; o<59; o+=28) {
|
||
for (j = o-28; j < o; ++j) {
|
||
l = j + totrot[i];
|
||
if (l < o) {
|
||
pcr[j] = pc1m[l];
|
||
} else {
|
||
pcr[j] = pc1m[l - 28];
|
||
}
|
||
}
|
||
}
|
||
for (j = 0; j < 24; ++j) {
|
||
if (pcr[PC2[j]] !== 0) {
|
||
kn[m] |= 1<<(23-j);
|
||
}
|
||
if (pcr[PC2[j + 24]] !== 0) {
|
||
kn[n] |= 1<<(23-j);
|
||
}
|
||
}
|
||
}
|
||
|
||
// cookey
|
||
for (i = 0, rawi = 0, KnLi = 0; i < 16; ++i) {
|
||
raw0 = kn[rawi++];
|
||
raw1 = kn[rawi++];
|
||
keys[KnLi] = (raw0 & 0x00fc0000) << 6;
|
||
keys[KnLi] |= (raw0 & 0x00000fc0) << 10;
|
||
keys[KnLi] |= (raw1 & 0x00fc0000) >>> 10;
|
||
keys[KnLi] |= (raw1 & 0x00000fc0) >>> 6;
|
||
++KnLi;
|
||
keys[KnLi] = (raw0 & 0x0003f000) << 12;
|
||
keys[KnLi] |= (raw0 & 0x0000003f) << 16;
|
||
keys[KnLi] |= (raw1 & 0x0003f000) >>> 4;
|
||
keys[KnLi] |= (raw1 & 0x0000003f);
|
||
++KnLi;
|
||
}
|
||
}
|
||
|
||
// Encrypt 8 bytes of text
|
||
function enc8(text) {
|
||
var i = 0, b = text.slice(), fval, keysi = 0,
|
||
l, r, x; // left, right, accumulator
|
||
|
||
// Squash 8 bytes to 2 ints
|
||
l = b[i++]<<24 | b[i++]<<16 | b[i++]<<8 | b[i++];
|
||
r = b[i++]<<24 | b[i++]<<16 | b[i++]<<8 | b[i++];
|
||
|
||
x = ((l >>> 4) ^ r) & 0x0f0f0f0f;
|
||
r ^= x;
|
||
l ^= (x << 4);
|
||
x = ((l >>> 16) ^ r) & 0x0000ffff;
|
||
r ^= x;
|
||
l ^= (x << 16);
|
||
x = ((r >>> 2) ^ l) & 0x33333333;
|
||
l ^= x;
|
||
r ^= (x << 2);
|
||
x = ((r >>> 8) ^ l) & 0x00ff00ff;
|
||
l ^= x;
|
||
r ^= (x << 8);
|
||
r = (r << 1) | ((r >>> 31) & 1);
|
||
x = (l ^ r) & 0xaaaaaaaa;
|
||
l ^= x;
|
||
r ^= x;
|
||
l = (l << 1) | ((l >>> 31) & 1);
|
||
|
||
for (i = 0; i < 8; ++i) {
|
||
x = (r << 28) | (r >>> 4);
|
||
x ^= keys[keysi++];
|
||
fval = SP7[x & 0x3f];
|
||
fval |= SP5[(x >>> 8) & 0x3f];
|
||
fval |= SP3[(x >>> 16) & 0x3f];
|
||
fval |= SP1[(x >>> 24) & 0x3f];
|
||
x = r ^ keys[keysi++];
|
||
fval |= SP8[x & 0x3f];
|
||
fval |= SP6[(x >>> 8) & 0x3f];
|
||
fval |= SP4[(x >>> 16) & 0x3f];
|
||
fval |= SP2[(x >>> 24) & 0x3f];
|
||
l ^= fval;
|
||
x = (l << 28) | (l >>> 4);
|
||
x ^= keys[keysi++];
|
||
fval = SP7[x & 0x3f];
|
||
fval |= SP5[(x >>> 8) & 0x3f];
|
||
fval |= SP3[(x >>> 16) & 0x3f];
|
||
fval |= SP1[(x >>> 24) & 0x3f];
|
||
x = l ^ keys[keysi++];
|
||
fval |= SP8[x & 0x0000003f];
|
||
fval |= SP6[(x >>> 8) & 0x3f];
|
||
fval |= SP4[(x >>> 16) & 0x3f];
|
||
fval |= SP2[(x >>> 24) & 0x3f];
|
||
r ^= fval;
|
||
}
|
||
|
||
r = (r << 31) | (r >>> 1);
|
||
x = (l ^ r) & 0xaaaaaaaa;
|
||
l ^= x;
|
||
r ^= x;
|
||
l = (l << 31) | (l >>> 1);
|
||
x = ((l >>> 8) ^ r) & 0x00ff00ff;
|
||
r ^= x;
|
||
l ^= (x << 8);
|
||
x = ((l >>> 2) ^ r) & 0x33333333;
|
||
r ^= x;
|
||
l ^= (x << 2);
|
||
x = ((r >>> 16) ^ l) & 0x0000ffff;
|
||
l ^= x;
|
||
r ^= (x << 16);
|
||
x = ((r >>> 4) ^ l) & 0x0f0f0f0f;
|
||
l ^= x;
|
||
r ^= (x << 4);
|
||
|
||
// Spread ints to bytes
|
||
x = [r, l];
|
||
for (i = 0; i < 8; i++) {
|
||
b[i] = (x[i>>>2] >>> (8*(3 - (i%4)))) % 256;
|
||
if (b[i] < 0) { b[i] += 256; } // unsigned
|
||
}
|
||
return b;
|
||
}
|
||
|
||
// Encrypt 16 bytes of text using passwd as key
|
||
function encrypt(t) {
|
||
return enc8(t.slice(0,8)).concat(enc8(t.slice(8,16)));
|
||
}
|
||
|
||
setKeys(passwd); // Setup keys
|
||
return {'encrypt': encrypt}; // Public interface
|
||
|
||
} // function DES
|
vendor/assets/javascripts/noVNC/display.js | ||
---|---|---|
/*
|
||
* noVNC: HTML5 VNC client
|
||
* Copyright (C) 2011 Joel Martin
|
||
* Licensed under LGPL-3 (see LICENSE.txt)
|
||
*
|
||
* See README.md for usage and integration instructions.
|
||
*/
|
||
|
||
/*jslint browser: true, white: false, bitwise: false */
|
||
/*global Util, Base64, changeCursor */
|
||
|
||
function Display(defaults) {
|
||
"use strict";
|
||
|
||
var that = {}, // Public API methods
|
||
conf = {}, // Configuration attributes
|
||
|
||
// Private Display namespace variables
|
||
c_ctx = null,
|
||
c_forceCanvas = false,
|
||
|
||
// Predefine function variables (jslint)
|
||
imageDataGet, rgbImageData, bgrxImageData, cmapImageData,
|
||
setFillColor, rescale,
|
||
|
||
// The full frame buffer (logical canvas) size
|
||
fb_width = 0,
|
||
fb_height = 0,
|
||
// The visible "physical canvas" viewport
|
||
viewport = {'x': 0, 'y': 0, 'w' : 0, 'h' : 0 },
|
||
cleanRect = {'x1': 0, 'y1': 0, 'x2': -1, 'y2': -1},
|
||
|
||
c_prevStyle = "",
|
||
tile = null,
|
||
tile16x16 = null,
|
||
tile_x = 0,
|
||
tile_y = 0;
|
||
|
||
|
||
// Configuration attributes
|
||
Util.conf_defaults(conf, that, defaults, [
|
||
['target', 'wo', 'dom', null, 'Canvas element for rendering'],
|
||
['context', 'ro', 'raw', null, 'Canvas 2D context for rendering (read-only)'],
|
||
['logo', 'rw', 'raw', null, 'Logo to display when cleared: {"width": width, "height": height, "data": data}'],
|
||
['true_color', 'rw', 'bool', true, 'Use true-color pixel data'],
|
||
['colourMap', 'rw', 'arr', [], 'Colour map array (when not true-color)'],
|
||
['scale', 'rw', 'float', 1.0, 'Display area scale factor 0.0 - 1.0'],
|
||
['viewport', 'rw', 'bool', false, 'Use a viewport set with viewportChange()'],
|
||
['width', 'rw', 'int', null, 'Display area width'],
|
||
['height', 'rw', 'int', null, 'Display area height'],
|
||
|
||
['render_mode', 'ro', 'str', '', 'Canvas rendering mode (read-only)'],
|
||
|
||
['prefer_js', 'rw', 'str', null, 'Prefer Javascript over canvas methods'],
|
||
['cursor_uri', 'rw', 'raw', null, 'Can we render cursor using data URI']
|
||
]);
|
||
|
||
// Override some specific getters/setters
|
||
that.get_context = function () { return c_ctx; };
|
||
|
||
that.set_scale = function(scale) { rescale(scale); };
|
||
|
||
that.set_width = function (val) { that.resize(val, fb_height); };
|
||
that.get_width = function() { return fb_width; };
|
||
|
||
that.set_height = function (val) { that.resize(fb_width, val); };
|
||
that.get_height = function() { return fb_height; };
|
||
|
||
|
||
|
||
//
|
||
// Private functions
|
||
//
|
||
|
||
// Create the public API interface
|
||
function constructor() {
|
||
Util.Debug(">> Display.constructor");
|
||
|
||
var c, func, i, curDat, curSave,
|
||
has_imageData = false, UE = Util.Engine;
|
||
|
||
if (! conf.target) { throw("target must be set"); }
|
||
|
||
if (typeof conf.target === 'string') {
|
||
throw("target must be a DOM element");
|
||
}
|
||
|
||
c = conf.target;
|
||
|
||
if (! c.getContext) { throw("no getContext method"); }
|
||
|
||
if (! c_ctx) { c_ctx = c.getContext('2d'); }
|
||
|
||
Util.Debug("User Agent: " + navigator.userAgent);
|
||
if (UE.gecko) { Util.Debug("Browser: gecko " + UE.gecko); }
|
||
if (UE.webkit) { Util.Debug("Browser: webkit " + UE.webkit); }
|
||
if (UE.trident) { Util.Debug("Browser: trident " + UE.trident); }
|
||
if (UE.presto) { Util.Debug("Browser: presto " + UE.presto); }
|
||
|
||
that.clear();
|
||
|
||
// Check canvas features
|
||
if ('createImageData' in c_ctx) {
|
||
conf.render_mode = "canvas rendering";
|
||
} else {
|
||
throw("Canvas does not support createImageData");
|
||
}
|
||
if (conf.prefer_js === null) {
|
||
Util.Info("Prefering javascript operations");
|
||
conf.prefer_js = true;
|
||
}
|
||
|
||
// Initialize cached tile imageData
|
||
tile16x16 = c_ctx.createImageData(16, 16);
|
||
|
||
/*
|
||
* Determine browser support for setting the cursor via data URI
|
||
* scheme
|
||
*/
|
||
curDat = [];
|
||
for (i=0; i < 8 * 8 * 4; i += 1) {
|
||
curDat.push(255);
|
||
}
|
||
try {
|
||
curSave = c.style.cursor;
|
||
changeCursor(conf.target, curDat, curDat, 2, 2, 8, 8);
|
||
if (c.style.cursor) {
|
||
if (conf.cursor_uri === null) {
|
||
conf.cursor_uri = true;
|
||
}
|
||
Util.Info("Data URI scheme cursor supported");
|
||
} else {
|
||
if (conf.cursor_uri === null) {
|
||
conf.cursor_uri = false;
|
||
}
|
||
Util.Warn("Data URI scheme cursor not supported");
|
||
}
|
||
c.style.cursor = curSave;
|
||
} catch (exc2) {
|
||
Util.Error("Data URI scheme cursor test exception: " + exc2);
|
||
conf.cursor_uri = false;
|
||
}
|
||
|
||
Util.Debug("<< Display.constructor");
|
||
return that ;
|
||
}
|
||
|
||
rescale = function(factor) {
|
||
var c, tp, x, y,
|
||
properties = ['transform', 'WebkitTransform', 'MozTransform', null];
|
||
c = conf.target;
|
||
tp = properties.shift();
|
||
while (tp) {
|
||
if (typeof c.style[tp] !== 'undefined') {
|
||
break;
|
||
}
|
||
tp = properties.shift();
|
||
}
|
||
|
||
if (tp === null) {
|
||
Util.Debug("No scaling support");
|
||
return;
|
||
}
|
||
|
||
|
||
if (typeof(factor) === "undefined") {
|
||
factor = conf.scale;
|
||
} else if (factor > 1.0) {
|
||
factor = 1.0;
|
||
} else if (factor < 0.1) {
|
||
factor = 0.1;
|
||
}
|
||
|
||
if (conf.scale === factor) {
|
||
//Util.Debug("Display already scaled to '" + factor + "'");
|
||
return;
|
||
}
|
||
|
||
conf.scale = factor;
|
||
x = c.width - c.width * factor;
|
||
y = c.height - c.height * factor;
|
||
c.style[tp] = "scale(" + conf.scale + ") translate(-" + x + "px, -" + y + "px)";
|
||
};
|
||
|
||
setFillColor = function(color) {
|
||
var bgr, newStyle;
|
||
if (conf.true_color) {
|
||
bgr = color;
|
||
} else {
|
||
bgr = conf.colourMap[color[0]];
|
||
}
|
||
newStyle = "rgb(" + bgr[2] + "," + bgr[1] + "," + bgr[0] + ")";
|
||
if (newStyle !== c_prevStyle) {
|
||
c_ctx.fillStyle = newStyle;
|
||
c_prevStyle = newStyle;
|
||
}
|
||
};
|
||
|
||
|
||
//
|
||
// Public API interface functions
|
||
//
|
||
|
||
// Shift and/or resize the visible viewport
|
||
that.viewportChange = function(deltaX, deltaY, width, height) {
|
||
var c = conf.target, v = viewport, cr = cleanRect,
|
||
saveImg = null, saveStyle, x1, y1, vx2, vy2, w, h;
|
||
|
||
if (!conf.viewport) {
|
||
Util.Debug("Setting viewport to full display region");
|
||
deltaX = -v.w; // Clamped later if out of bounds
|
||
deltaY = -v.h; // Clamped later if out of bounds
|
||
width = fb_width;
|
||
height = fb_height;
|
||
}
|
||
|
||
if (typeof(deltaX) === "undefined") { deltaX = 0; }
|
||
if (typeof(deltaY) === "undefined") { deltaY = 0; }
|
||
if (typeof(width) === "undefined") { width = v.w; }
|
||
if (typeof(height) === "undefined") { height = v.h; }
|
||
|
||
// Size change
|
||
|
||
if (width > fb_width) { width = fb_width; }
|
||
if (height > fb_height) { height = fb_height; }
|
||
|
||
if ((v.w !== width) || (v.h !== height)) {
|
||
// Change width
|
||
if ((width < v.w) && (cr.x2 > v.x + width -1)) {
|
||
cr.x2 = v.x + width - 1;
|
||
}
|
||
v.w = width;
|
||
|
||
// Change height
|
||
if ((height < v.h) && (cr.y2 > v.y + height -1)) {
|
||
cr.y2 = v.y + height - 1;
|
||
}
|
||
v.h = height;
|
||
|
||
|
||
if (v.w > 0 && v.h > 0 && c.width > 0 && c.height > 0) {
|
||
saveImg = c_ctx.getImageData(0, 0,
|
||
(c.width < v.w) ? c.width : v.w,
|
||
(c.height < v.h) ? c.height : v.h);
|
||
}
|
||
|
||
c.width = v.w;
|
||
c.height = v.h;
|
||
|
||
if (saveImg) {
|
||
c_ctx.putImageData(saveImg, 0, 0);
|
||
}
|
||
}
|
||
|
||
vx2 = v.x + v.w - 1;
|
||
vy2 = v.y + v.h - 1;
|
||
|
||
|
||
// Position change
|
||
|
||
if ((deltaX < 0) && ((v.x + deltaX) < 0)) {
|
||
deltaX = - v.x;
|
||
}
|
||
if ((vx2 + deltaX) >= fb_width) {
|
||
deltaX -= ((vx2 + deltaX) - fb_width + 1);
|
||
}
|
||
|
||
if ((v.y + deltaY) < 0) {
|
||
deltaY = - v.y;
|
||
}
|
||
if ((vy2 + deltaY) >= fb_height) {
|
||
deltaY -= ((vy2 + deltaY) - fb_height + 1);
|
||
}
|
||
|
||
if ((deltaX === 0) && (deltaY === 0)) {
|
||
//Util.Debug("skipping viewport change");
|
||
return;
|
||
}
|
||
Util.Debug("viewportChange deltaX: " + deltaX + ", deltaY: " + deltaY);
|
||
|
||
v.x += deltaX;
|
||
vx2 += deltaX;
|
||
v.y += deltaY;
|
||
vy2 += deltaY;
|
||
|
||
// Update the clean rectangle
|
||
if (v.x > cr.x1) {
|
||
cr.x1 = v.x;
|
||
}
|
||
if (vx2 < cr.x2) {
|
||
cr.x2 = vx2;
|
||
}
|
||
if (v.y > cr.y1) {
|
||
cr.y1 = v.y;
|
||
}
|
||
if (vy2 < cr.y2) {
|
||
cr.y2 = vy2;
|
||
}
|
||
|
||
if (deltaX < 0) {
|
||
// Shift viewport left, redraw left section
|
||
x1 = 0;
|
||
w = - deltaX;
|
||
} else {
|
||
// Shift viewport right, redraw right section
|
||
x1 = v.w - deltaX;
|
||
w = deltaX;
|
||
}
|
||
if (deltaY < 0) {
|
||
// Shift viewport up, redraw top section
|
||
y1 = 0;
|
||
h = - deltaY;
|
||
} else {
|
||
// Shift viewport down, redraw bottom section
|
||
y1 = v.h - deltaY;
|
||
h = deltaY;
|
||
}
|
||
|
||
// Copy the valid part of the viewport to the shifted location
|
||
saveStyle = c_ctx.fillStyle;
|
||
c_ctx.fillStyle = "rgb(255,255,255)";
|
||
if (deltaX !== 0) {
|
||
//that.copyImage(0, 0, -deltaX, 0, v.w, v.h);
|
||
//that.fillRect(x1, 0, w, v.h, [255,255,255]);
|
||
c_ctx.drawImage(c, 0, 0, v.w, v.h, -deltaX, 0, v.w, v.h);
|
||
c_ctx.fillRect(x1, 0, w, v.h);
|
||
}
|
||
if (deltaY !== 0) {
|
||
//that.copyImage(0, 0, 0, -deltaY, v.w, v.h);
|
||
//that.fillRect(0, y1, v.w, h, [255,255,255]);
|
||
c_ctx.drawImage(c, 0, 0, v.w, v.h, 0, -deltaY, v.w, v.h);
|
||
c_ctx.fillRect(0, y1, v.w, h);
|
||
}
|
||
c_ctx.fillStyle = saveStyle;
|
||
};
|
||
|
||
|
||
// Return a map of clean and dirty areas of the viewport and reset the
|
||
// tracking of clean and dirty areas.
|
||
//
|
||
// Returns: {'cleanBox': {'x': x, 'y': y, 'w': w, 'h': h},
|
||
// 'dirtyBoxes': [{'x': x, 'y': y, 'w': w, 'h': h}, ...]}
|
||
that.getCleanDirtyReset = function() {
|
||
var v = viewport, c = cleanRect, cleanBox, dirtyBoxes = [],
|
||
vx2 = v.x + v.w - 1, vy2 = v.y + v.h - 1;
|
||
|
||
|
||
// Copy the cleanRect
|
||
cleanBox = {'x': c.x1, 'y': c.y1,
|
||
'w': c.x2 - c.x1 + 1, 'h': c.y2 - c.y1 + 1};
|
||
|
||
if ((c.x1 >= c.x2) || (c.y1 >= c.y2)) {
|
||
// Whole viewport is dirty
|
||
dirtyBoxes.push({'x': v.x, 'y': v.y, 'w': v.w, 'h': v.h});
|
||
} else {
|
||
// Redraw dirty regions
|
||
if (v.x < c.x1) {
|
||
// left side dirty region
|
||
dirtyBoxes.push({'x': v.x, 'y': v.y,
|
||
'w': c.x1 - v.x + 1, 'h': v.h});
|
||
}
|
||
if (vx2 > c.x2) {
|
||
// right side dirty region
|
||
dirtyBoxes.push({'x': c.x2 + 1, 'y': v.y,
|
||
'w': vx2 - c.x2, 'h': v.h});
|
||
}
|
||
if (v.y < c.y1) {
|
||
// top/middle dirty region
|
||
dirtyBoxes.push({'x': c.x1, 'y': v.y,
|
||
'w': c.x2 - c.x1 + 1, 'h': c.y1 - v.y});
|
||
}
|
||
if (vy2 > c.y2) {
|
||
// bottom/middle dirty region
|
||
dirtyBoxes.push({'x': c.x1, 'y': c.y2 + 1,
|
||
'w': c.x2 - c.x1 + 1, 'h': vy2 - c.y2});
|
||
}
|
||
}
|
||
|
||
// Reset the cleanRect to the whole viewport
|
||
cleanRect = {'x1': v.x, 'y1': v.y,
|
||
'x2': v.x + v.w - 1, 'y2': v.y + v.h - 1};
|
||
|
||
return {'cleanBox': cleanBox, 'dirtyBoxes': dirtyBoxes};
|
||
};
|
||
|
||
// Translate viewport coordinates to absolute coordinates
|
||
that.absX = function(x) {
|
||
return x + viewport.x;
|
||
};
|
||
that.absY = function(y) {
|
||
return y + viewport.y;
|
||
};
|
||
|
||
|
||
that.resize = function(width, height) {
|
||
c_prevStyle = "";
|
||
|
||
fb_width = width;
|
||
fb_height = height;
|
||
|
||
rescale(conf.scale);
|
||
that.viewportChange();
|
||
};
|
||
|
||
that.clear = function() {
|
||
|
||
if (conf.logo) {
|
||
that.resize(conf.logo.width, conf.logo.height);
|
||
that.blitStringImage(conf.logo.data, 0, 0);
|
||
} else {
|
||
that.resize(640, 20);
|
||
c_ctx.clearRect(0, 0, viewport.w, viewport.h);
|
||
}
|
||
|
||
// No benefit over default ("source-over") in Chrome and firefox
|
||
//c_ctx.globalCompositeOperation = "copy";
|
||
};
|
||
|
||
that.fillRect = function(x, y, width, height, color) {
|
||
setFillColor(color);
|
||
c_ctx.fillRect(x - viewport.x, y - viewport.y, width, height);
|
||
};
|
||
|
||
that.copyImage = function(old_x, old_y, new_x, new_y, w, h) {
|
||
var x1 = old_x - viewport.x, y1 = old_y - viewport.y,
|
||
x2 = new_x - viewport.x, y2 = new_y - viewport.y;
|
||
c_ctx.drawImage(conf.target, x1, y1, w, h, x2, y2, w, h);
|
||
};
|
||
|
||
|
||
// Start updating a tile
|
||
that.startTile = function(x, y, width, height, color) {
|
||
var data, bgr, red, green, blue, i;
|
||
tile_x = x;
|
||
tile_y = y;
|
||
if ((width === 16) && (height === 16)) {
|
||
tile = tile16x16;
|
||
} else {
|
||
tile = c_ctx.createImageData(width, height);
|
||
}
|
||
data = tile.data;
|
||
if (conf.prefer_js) {
|
||
if (conf.true_color) {
|
||
bgr = color;
|
||
} else {
|
||
bgr = conf.colourMap[color[0]];
|
||
}
|
||
red = bgr[2];
|
||
green = bgr[1];
|
||
blue = bgr[0];
|
||
for (i = 0; i < (width * height * 4); i+=4) {
|
||
data[i ] = red;
|
||
data[i + 1] = green;
|
||
data[i + 2] = blue;
|
||
data[i + 3] = 255;
|
||
}
|
||
} else {
|
||
that.fillRect(x, y, width, height, color);
|
||
}
|
||
};
|
||
|
||
// Update sub-rectangle of the current tile
|
||
that.subTile = function(x, y, w, h, color) {
|
||
var data, p, bgr, red, green, blue, width, j, i, xend, yend;
|
||
if (conf.prefer_js) {
|
||
data = tile.data;
|
||
width = tile.width;
|
||
if (conf.true_color) {
|
||
bgr = color;
|
||
} else {
|
||
bgr = conf.colourMap[color[0]];
|
||
}
|
||
red = bgr[2];
|
||
green = bgr[1];
|
||
blue = bgr[0];
|
||
xend = x + w;
|
||
yend = y + h;
|
||
for (j = y; j < yend; j += 1) {
|
||
for (i = x; i < xend; i += 1) {
|
||
p = (i + (j * width) ) * 4;
|
||
data[p ] = red;
|
||
data[p + 1] = green;
|
||
data[p + 2] = blue;
|
||
data[p + 3] = 255;
|
||
}
|
||
}
|
||
} else {
|
||
that.fillRect(tile_x + x, tile_y + y, w, h, color);
|
||
}
|
||
};
|
||
|
||
// Draw the current tile to the screen
|
||
that.finishTile = function() {
|
||
if (conf.prefer_js) {
|
||
c_ctx.putImageData(tile, tile_x - viewport.x, tile_y - viewport.y);
|
||
}
|
||
// 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;
|
||
/*
|
||
if ((x - v.x >= v.w) || (y - v.y >= v.h) ||
|
||
(x - v.x + width < 0) || (y - v.y + height < 0)) {
|
||
// Skipping because outside of viewport
|
||
return;
|
||
}
|
||
*/
|
||
img = c_ctx.createImageData(width, height);
|
||
data = img.data;
|
||
for (i=0, j=offset; i < (width * height * 4); i=i+4, j=j+3) {
|
||
data[i ] = arr[j ];
|
||
data[i + 1] = arr[j + 1];
|
||
data[i + 2] = arr[j + 2];
|
||
data[i + 3] = 255; // Set Alpha
|
||
}
|
||
c_ctx.putImageData(img, x - v.x, y - v.y);
|
||
};
|
||
|
||
bgrxImageData = function(x, y, width, height, arr, offset) {
|
||
var img, i, j, data, v = viewport;
|
||
/*
|
||
if ((x - v.x >= v.w) || (y - v.y >= v.h) ||
|
||
(x - v.x + width < 0) || (y - v.y + height < 0)) {
|
||
// Skipping because outside of viewport
|
||
return;
|
||
}
|
||
*/
|
||
img = c_ctx.createImageData(width, height);
|
||
data = img.data;
|
||
for (i=0, j=offset; i < (width * height * 4); i=i+4, j=j+4) {
|
||
data[i ] = arr[j + 2];
|
||
data[i + 1] = arr[j + 1];
|
||
data[i + 2] = arr[j ];
|
||
data[i + 3] = 255; // Set Alpha
|
||
}
|
||
c_ctx.putImageData(img, x - v.x, y - v.y);
|
||
};
|
||
|
||
cmapImageData = function(x, y, width, height, arr, offset) {
|
||
var img, i, j, data, bgr, cmap;
|
||
img = c_ctx.createImageData(width, height);
|
||
data = img.data;
|
||
cmap = conf.colourMap;
|
||
for (i=0, j=offset; i < (width * height * 4); i+=4, j+=1) {
|
||
bgr = cmap[arr[j]];
|
||
data[i ] = bgr[2];
|
||
data[i + 1] = bgr[1];
|
||
data[i + 2] = bgr[0];
|
||
data[i + 3] = 255; // Set Alpha
|
||
}
|
||
c_ctx.putImageData(img, x - viewport.x, y - viewport.y);
|
||
};
|
||
|
||
that.blitImage = function(x, y, width, height, arr, offset) {
|
||
if (conf.true_color) {
|
||
bgrxImageData(x, y, width, height, arr, offset);
|
||
} else {
|
||
cmapImageData(x, 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);
|
||
} else {
|
||
// prolly wrong...
|
||
cmapImageData(x, y, width, height, arr, offset);
|
||
}
|
||
};
|
||
|
||
that.blitStringImage = function(str, x, y) {
|
||
var img = new Image();
|
||
img.onload = function () {
|
||
c_ctx.drawImage(img, x - viewport.x, y - viewport.y);
|
||
};
|
||
img.src = str;
|
||
};
|
||
|
||
that.changeCursor = function(pixels, mask, hotx, hoty, w, h) {
|
||
if (conf.cursor_uri === false) {
|
||
Util.Warn("changeCursor called but no cursor data URI support");
|
||
return;
|
||
}
|
||
|
||
if (conf.true_color) {
|
||
changeCursor(conf.target, pixels, mask, hotx, hoty, w, h);
|
||
} else {
|
||
changeCursor(conf.target, pixels, mask, hotx, hoty, w, h, conf.colourMap);
|
||
}
|
||
};
|
||
|
||
that.defaultCursor = function() {
|
||
conf.target.style.cursor = "default";
|
||
};
|
||
|
||
return constructor(); // Return the public API interface
|
||
|
||
} // End of Display()
|
||
|
||
|
||
/* Set CSS cursor property using data URI encoded cursor file */
|
||
function changeCursor(target, pixels, mask, hotx, hoty, w, h, 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);
|
||
|
||
// Push multi-byte little-endian values
|
||
cur.push16le = function (num) {
|
||
this.push((num ) & 0xFF,
|
||
(num >> 8) & 0xFF );
|
||
};
|
||
cur.push32le = function (num) {
|
||
this.push((num ) & 0xFF,
|
||
(num >> 8) & 0xFF,
|
||
(num >> 16) & 0xFF,
|
||
(num >> 24) & 0xFF );
|
||
};
|
||
|
||
IHDRsz = 40;
|
||
RGBsz = w * h * 4;
|
||
XORsz = Math.ceil( (w * h) / 8.0 );
|
||
ANDsz = Math.ceil( (w * h) / 8.0 );
|
||
|
||
// Main header
|
||
cur.push16le(0); // 0: Reserved
|
||
cur.push16le(2); // 2: .CUR type
|
||
cur.push16le(1); // 4: Number of images, 1 for non-animated ico
|
||
|
||
// Cursor #1 header (ICONDIRENTRY)
|
||
cur.push(w); // 6: width
|
||
cur.push(h); // 7: height
|
||
cur.push(0); // 8: colors, 0 -> true-color
|
||
cur.push(0); // 9: reserved
|
||
cur.push16le(hotx); // 10: hotspot x coordinate
|
||
cur.push16le(hoty); // 12: hotspot y coordinate
|
||
cur.push32le(IHDRsz + RGBsz + XORsz + ANDsz);
|
||
// 14: cursor data byte size
|
||
cur.push32le(22); // 18: offset of cursor data in the file
|
||
|
||
|
||
// Cursor #1 InfoHeader (ICONIMAGE/BITMAPINFO)
|
||
cur.push32le(IHDRsz); // 22: Infoheader size
|
||
cur.push32le(w); // 26: Cursor width
|
||
cur.push32le(h*2); // 30: XOR+AND height
|
||
cur.push16le(1); // 34: number of planes
|
||
cur.push16le(32); // 36: bits per pixel
|
||
cur.push32le(0); // 38: Type of compression
|
||
|
||
cur.push32le(XORsz + ANDsz); // 43: Size of Image
|
||
// Gimp leaves this as 0
|
||
|
||
cur.push32le(0); // 46: reserved
|
||
cur.push32le(0); // 50: reserved
|
||
cur.push32le(0); // 54: reserved
|
||
cur.push32le(0); // 58: reserved
|
||
|
||
// 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
|
||
} 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
|
||
}
|
||
}
|
||
}
|
||
|
||
// XOR/bitmask data (BYTE icXOR[])
|
||
// (ignored, just needs to be right size)
|
||
for (y = 0; y < h; y += 1) {
|
||
for (x = 0; x < Math.ceil(w / 8); x += 1) {
|
||
cur.push(0x00);
|
||
}
|
||
}
|
||
|
||
// AND/bitmask data (BYTE icAND[])
|
||
// (ignored, just needs to be right size)
|
||
for (y = 0; y < h; y += 1) {
|
||
for (x = 0; x < Math.ceil(w / 8); x += 1) {
|
||
cur.push(0x00);
|
||
}
|
||
}
|
||
|
||
url = "data:image/x-icon;base64," + Base64.encode(cur);
|
||
target.style.cursor = "url(" + url + ") " + hotx + " " + hoty + ", default";
|
||
//Util.Debug("<< changeCursor, cur.length: " + cur.length);
|
||
}
|
vendor/assets/javascripts/noVNC/input.js | ||
---|---|---|
/*
|
||
* noVNC: HTML5 VNC client
|
||
* Copyright (C) 2011 Joel Martin
|
||
* Licensed under LGPL-2 or any later version (see LICENSE.txt)
|
||
*/
|
||
|
||
/*jslint browser: true, white: false, bitwise: false */
|
||
/*global window, Util */
|
||
|
||
|
||
//
|
||
// Keyboard event handler
|
||
//
|
||
|
||
function Keyboard(defaults) {
|
||
"use strict";
|
||
|
||
var that = {}, // Public API methods
|
||
conf = {}, // Configuration attributes
|
||
|
||
keyDownList = []; // List of depressed keys
|
||
// (even if they are happy)
|
||
|
||
// Configuration attributes
|
||
Util.conf_defaults(conf, that, defaults, [
|
||
['target', 'wo', 'dom', document, 'DOM element that captures keyboard input'],
|
||
['focused', 'rw', 'bool', true, 'Capture and send key events'],
|
||
|
||
['onKeyPress', 'rw', 'func', null, 'Handler for key press/release']
|
||
]);
|
||
|
||
|
||
//
|
||
// Private functions
|
||
//
|
||
|
||
// From the event keyCode return the keysym value for keys that need
|
||
// to be suppressed otherwise they may trigger unintended browser
|
||
// actions
|
||
function getKeysymSpecial(evt) {
|
||
var keysym = null;
|
||
|
||
switch ( evt.keyCode ) {
|
||
// These generate a keyDown and keyPress in Firefox and Opera
|
||
case 8 : keysym = 0xFF08; break; // BACKSPACE
|
||
case 13 : keysym = 0xFF0D; break; // ENTER
|
||
|
||
// This generates a keyDown and keyPress in Opera
|
||
case 9 : keysym = 0xFF09; break; // TAB
|
||
default : break;
|
||
}
|
||
|
||
if (evt.type === 'keydown') {
|
||
switch ( evt.keyCode ) {
|
||
case 27 : keysym = 0xFF1B; break; // ESCAPE
|
||
case 46 : keysym = 0xFFFF; break; // DELETE
|
||
|
||
case 36 : keysym = 0xFF50; break; // HOME
|
||
case 35 : keysym = 0xFF57; break; // END
|
||
case 33 : keysym = 0xFF55; break; // PAGE_UP
|
||
case 34 : keysym = 0xFF56; break; // PAGE_DOWN
|
||
case 45 : keysym = 0xFF63; break; // INSERT
|
||
// '-' during keyPress
|
||
case 37 : keysym = 0xFF51; break; // LEFT
|
||
case 38 : keysym = 0xFF52; break; // UP
|
||
case 39 : keysym = 0xFF53; break; // RIGHT
|
||
case 40 : keysym = 0xFF54; break; // DOWN
|
||
case 16 : keysym = 0xFFE1; break; // SHIFT
|
||
case 17 : keysym = 0xFFE3; break; // CONTROL
|
||
//case 18 : keysym = 0xFFE7; break; // Left Meta (Mac Option)
|
||
case 18 : keysym = 0xFFE9; break; // Left ALT (Mac Command)
|
||
|
||
case 112 : keysym = 0xFFBE; break; // F1
|
||
case 113 : keysym = 0xFFBF; break; // F2
|
||
case 114 : keysym = 0xFFC0; break; // F3
|
||
case 115 : keysym = 0xFFC1; break; // F4
|
||
case 116 : keysym = 0xFFC2; break; // F5
|
||
case 117 : keysym = 0xFFC3; break; // F6
|
||
case 118 : keysym = 0xFFC4; break; // F7
|
||
case 119 : keysym = 0xFFC5; break; // F8
|
||
case 120 : keysym = 0xFFC6; break; // F9
|
||
case 121 : keysym = 0xFFC7; break; // F10
|
||
case 122 : keysym = 0xFFC8; break; // F11
|
||
case 123 : keysym = 0xFFC9; break; // F12
|
||
|
||
default : break;
|
||
}
|
||
}
|
||
|
||
if ((!keysym) && (evt.ctrlKey || evt.altKey)) {
|
||
if ((typeof(evt.which) !== "undefined") && (evt.which > 0)) {
|
||
keysym = evt.which;
|
||
} else {
|
||
// IE9 always
|
||
// Firefox and Opera when ctrl/alt + special
|
||
Util.Warn("which not set, using keyCode");
|
||
keysym = evt.keyCode;
|
||
}
|
||
|
||
/* Remap symbols */
|
||
switch (keysym) {
|
||
case 186 : keysym = 59; break; // ; (IE)
|
||
case 187 : keysym = 61; break; // = (IE)
|
||
case 188 : keysym = 44; break; // , (Mozilla, IE)
|
||
case 109 : // - (Mozilla, Opera)
|
||
if (Util.Engine.gecko || Util.Engine.presto) {
|
||
keysym = 45; }
|
||
break;
|
||
case 189 : keysym = 45; break; // - (IE)
|
||
case 190 : keysym = 46; break; // . (Mozilla, IE)
|
||
case 191 : keysym = 47; break; // / (Mozilla, IE)
|
||
case 192 : keysym = 96; break; // ` (Mozilla, IE)
|
||
case 219 : keysym = 91; break; // [ (Mozilla, IE)
|
||
case 220 : keysym = 92; break; // \ (Mozilla, IE)
|
||
case 221 : keysym = 93; break; // ] (Mozilla, IE)
|
||
case 222 : keysym = 39; break; // ' (Mozilla, IE)
|
||
}
|
||
|
||
/* Remap shifted and unshifted keys */
|
||
if (!!evt.shiftKey) {
|
||
switch (keysym) {
|
||
case 48 : keysym = 41 ; break; // ) (shifted 0)
|
||
case 49 : keysym = 33 ; break; // ! (shifted 1)
|
||
case 50 : keysym = 64 ; break; // @ (shifted 2)
|
||
case 51 : keysym = 35 ; break; // # (shifted 3)
|
||
case 52 : keysym = 36 ; break; // $ (shifted 4)
|
||
case 53 : keysym = 37 ; break; // % (shifted 5)
|
||
case 54 : keysym = 94 ; break; // ^ (shifted 6)
|
||
case 55 : keysym = 38 ; break; // & (shifted 7)
|
||
case 56 : keysym = 42 ; break; // * (shifted 8)
|
||
case 57 : keysym = 40 ; break; // ( (shifted 9)
|
||
|
||
case 59 : keysym = 58 ; break; // : (shifted `)
|
||
case 61 : keysym = 43 ; break; // + (shifted ;)
|
||
case 44 : keysym = 60 ; break; // < (shifted ,)
|
||
case 45 : keysym = 95 ; break; // _ (shifted -)
|
||
case 46 : keysym = 62 ; break; // > (shifted .)
|
||
case 47 : keysym = 63 ; break; // ? (shifted /)
|
||
case 96 : keysym = 126; break; // ~ (shifted `)
|
||
case 91 : keysym = 123; break; // { (shifted [)
|
||
case 92 : keysym = 124; break; // | (shifted \)
|
||
case 93 : keysym = 125; break; // } (shifted ])
|
||
case 39 : keysym = 34 ; break; // " (shifted ')
|
||
}
|
||
} else if ((keysym >= 65) && (keysym <=90)) {
|
||
/* Remap unshifted A-Z */
|
||
keysym += 32;
|
||
} else if (evt.keyLocation === 3) {
|
||
// numpad keys
|
||
switch (keysym) {
|
||
case 96 : keysym = 48; break; // 0
|
||
case 97 : keysym = 49; break; // 1
|
||
case 98 : keysym = 50; break; // 2
|
||
case 99 : keysym = 51; break; // 3
|
||
case 100: keysym = 52; break; // 4
|
||
case 101: keysym = 53; break; // 5
|
||
case 102: keysym = 54; break; // 6
|
||
case 103: keysym = 55; break; // 7
|
||
case 104: keysym = 56; break; // 8
|
||
case 105: keysym = 57; break; // 9
|
||
case 109: keysym = 45; break; // -
|
||
case 110: keysym = 46; break; // .
|
||
case 111: keysym = 47; break; // /
|
||
}
|
||
}
|
||
}
|
||
|
||
return keysym;
|
||
}
|
||
|
||
/* Translate DOM keyPress event to keysym value */
|
||
function getKeysym(evt) {
|
||
var keysym, msg;
|
||
|
||
if (typeof(evt.which) !== "undefined") {
|
||
// WebKit, Firefox, Opera
|
||
keysym = evt.which;
|
||
} else {
|
||
// IE9
|
||
Util.Warn("which not set, using keyCode");
|
||
keysym = evt.keyCode;
|
||
}
|
||
|
||
if ((keysym > 255) && (keysym < 0xFF00)) {
|
||
msg = "Mapping character code " + keysym;
|
||
// Map Unicode outside Latin 1 to X11 keysyms
|
||
keysym = unicodeTable[keysym];
|
||
if (typeof(keysym) === 'undefined') {
|
||
keysym = 0;
|
||
}
|
||
Util.Debug(msg + " to " + keysym);
|
||
}
|
||
|
||
return keysym;
|
||
}
|
||
|
||
function show_keyDownList(kind) {
|
||
var c;
|
||
var msg = "keyDownList (" + kind + "):\n";
|
||
for (c = 0; c < keyDownList.length; c++) {
|
||
msg = msg + " " + c + " - keyCode: " + keyDownList[c].keyCode +
|
||
" - which: " + keyDownList[c].which + "\n";
|
||
}
|
||
Util.Debug(msg);
|
||
}
|
Also available in: Unified diff
Fixes #16294 - Remove noVNC from vendors