@novnc/novnc 1.2.0 → 1.3.0-g0ef7582
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +0 -6
- package/README.md +16 -6
- package/core/decoders/copyrect.js +5 -0
- package/core/decoders/hextile.js +57 -3
- package/core/decoders/jpeg.js +141 -0
- package/core/decoders/raw.js +12 -2
- package/core/decoders/tight.js +24 -8
- package/core/decoders/zrle.js +185 -0
- package/core/display.js +21 -151
- package/core/encodings.js +4 -0
- package/core/input/domkeytable.js +25 -21
- package/core/input/keyboard.js +22 -127
- package/core/input/util.js +18 -35
- package/core/input/vkeys.js +0 -1
- package/core/input/xtscancodes.js +5 -3
- package/core/ra2.js +567 -0
- package/core/rfb.js +487 -171
- package/core/util/browser.js +0 -17
- package/core/util/cursor.js +1 -11
- package/core/util/events.js +0 -4
- package/core/util/md5.js +79 -0
- package/core/websock.js +76 -17
- package/docs/API.md +107 -6
- package/docs/LIBRARY.md +3 -7
- package/lib/base64.js +24 -38
- package/lib/decoders/copyrect.js +6 -11
- package/lib/decoders/hextile.js +68 -44
- package/lib/decoders/jpeg.js +146 -0
- package/lib/decoders/raw.js +14 -21
- package/lib/decoders/rre.js +3 -17
- package/lib/decoders/tight.js +43 -93
- package/lib/decoders/tightpng.js +11 -33
- package/lib/decoders/zrle.js +185 -0
- package/lib/deflator.js +9 -26
- package/lib/des.js +22 -38
- package/lib/display.js +100 -315
- package/lib/encodings.js +7 -8
- package/lib/inflator.js +6 -22
- package/lib/input/domkeytable.js +240 -208
- package/lib/input/fixedkeys.js +10 -5
- package/lib/input/gesturehandler.js +84 -154
- package/lib/input/keyboard.js +87 -238
- package/lib/input/keysym.js +16 -272
- package/lib/input/keysymdef.js +7 -9
- package/lib/input/util.js +69 -156
- package/lib/input/vkeys.js +2 -7
- package/lib/input/xtscancodes.js +10 -171
- package/lib/ra2.js +1033 -0
- package/lib/rfb.js +947 -1149
- package/lib/util/browser.js +25 -52
- package/lib/util/cursor.js +25 -81
- package/lib/util/element.js +3 -5
- package/lib/util/events.js +26 -35
- package/lib/util/eventtarget.js +4 -16
- package/lib/util/int.js +2 -3
- package/lib/util/logging.js +3 -21
- package/lib/util/md5.js +83 -0
- package/lib/util/strings.js +3 -5
- package/lib/vendor/pako/lib/utils/common.js +10 -19
- package/lib/vendor/pako/lib/zlib/adler32.js +4 -8
- package/lib/vendor/pako/lib/zlib/constants.js +4 -7
- package/lib/vendor/pako/lib/zlib/crc32.js +6 -13
- package/lib/vendor/pako/lib/zlib/deflate.js +304 -708
- package/lib/vendor/pako/lib/zlib/gzheader.js +2 -14
- package/lib/vendor/pako/lib/zlib/inffast.js +61 -177
- package/lib/vendor/pako/lib/zlib/inflate.js +421 -909
- package/lib/vendor/pako/lib/zlib/inftrees.js +66 -172
- package/lib/vendor/pako/lib/zlib/messages.js +3 -13
- package/lib/vendor/pako/lib/zlib/trees.js +250 -592
- package/lib/vendor/pako/lib/zlib/zstream.js +3 -19
- package/lib/websock.js +119 -111
- package/package.json +2 -10
- package/core/util/polyfill.js +0 -61
- package/lib/util/polyfill.js +0 -72
- package/lib/vendor/promise.js +0 -255
package/core/util/browser.js
CHANGED
|
@@ -45,15 +45,6 @@ try {
|
|
|
45
45
|
|
|
46
46
|
export const supportsCursorURIs = _supportsCursorURIs;
|
|
47
47
|
|
|
48
|
-
let _supportsImageMetadata = false;
|
|
49
|
-
try {
|
|
50
|
-
new ImageData(new Uint8ClampedArray(4), 1, 1);
|
|
51
|
-
_supportsImageMetadata = true;
|
|
52
|
-
} catch (ex) {
|
|
53
|
-
// ignore failure
|
|
54
|
-
}
|
|
55
|
-
export const supportsImageMetadata = _supportsImageMetadata;
|
|
56
|
-
|
|
57
48
|
let _hasScrollbarGutter = true;
|
|
58
49
|
try {
|
|
59
50
|
// Create invisible container
|
|
@@ -106,14 +97,6 @@ export function isSafari() {
|
|
|
106
97
|
navigator.userAgent.indexOf('Chrome') === -1);
|
|
107
98
|
}
|
|
108
99
|
|
|
109
|
-
export function isIE() {
|
|
110
|
-
return navigator && !!(/trident/i).exec(navigator.userAgent);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function isEdge() {
|
|
114
|
-
return navigator && !!(/edge/i).exec(navigator.userAgent);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
100
|
export function isFirefox() {
|
|
118
101
|
return navigator && !!(/firefox/i).exec(navigator.userAgent);
|
|
119
102
|
}
|
package/core/util/cursor.js
CHANGED
|
@@ -43,9 +43,6 @@ export default class Cursor {
|
|
|
43
43
|
if (useFallback) {
|
|
44
44
|
document.body.appendChild(this._canvas);
|
|
45
45
|
|
|
46
|
-
// FIXME: These don't fire properly except for mouse
|
|
47
|
-
/// movement in IE. We want to also capture element
|
|
48
|
-
// movement, size changes, visibility, etc.
|
|
49
46
|
const options = { capture: true, passive: true };
|
|
50
47
|
this._target.addEventListener('mouseover', this._eventHandlers.mouseover, options);
|
|
51
48
|
this._target.addEventListener('mouseleave', this._eventHandlers.mouseleave, options);
|
|
@@ -90,14 +87,7 @@ export default class Cursor {
|
|
|
90
87
|
this._canvas.width = w;
|
|
91
88
|
this._canvas.height = h;
|
|
92
89
|
|
|
93
|
-
let img;
|
|
94
|
-
try {
|
|
95
|
-
// IE doesn't support this
|
|
96
|
-
img = new ImageData(new Uint8ClampedArray(rgba), w, h);
|
|
97
|
-
} catch (ex) {
|
|
98
|
-
img = ctx.createImageData(w, h);
|
|
99
|
-
img.data.set(new Uint8ClampedArray(rgba));
|
|
100
|
-
}
|
|
90
|
+
let img = new ImageData(new Uint8ClampedArray(rgba), w, h);
|
|
101
91
|
ctx.clearRect(0, 0, w, h);
|
|
102
92
|
ctx.putImageData(img, 0, 0);
|
|
103
93
|
|
package/core/util/events.js
CHANGED
|
@@ -65,10 +65,6 @@ export function setCapture(target) {
|
|
|
65
65
|
|
|
66
66
|
target.setCapture();
|
|
67
67
|
document.captureElement = target;
|
|
68
|
-
|
|
69
|
-
// IE releases capture on 'click' events which might not trigger
|
|
70
|
-
target.addEventListener('mouseup', releaseCapture);
|
|
71
|
-
|
|
72
68
|
} else {
|
|
73
69
|
// Release any existing capture in case this method is
|
|
74
70
|
// called multiple times without coordination
|
package/core/util/md5.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* noVNC: HTML5 VNC client
|
|
3
|
+
* Copyright (C) 2021 The noVNC Authors
|
|
4
|
+
* Licensed under MPL 2.0 (see LICENSE.txt)
|
|
5
|
+
*
|
|
6
|
+
* See README.md for usage and integration instructions.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* Performs MD5 hashing on a string of binary characters, returns an array of bytes
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export function MD5(d) {
|
|
14
|
+
let r = M(V(Y(X(d), 8 * d.length)));
|
|
15
|
+
return r;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function M(d) {
|
|
19
|
+
let f = new Uint8Array(d.length);
|
|
20
|
+
for (let i=0;i<d.length;i++) {
|
|
21
|
+
f[i] = d.charCodeAt(i);
|
|
22
|
+
}
|
|
23
|
+
return f;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function X(d) {
|
|
27
|
+
let r = Array(d.length >> 2);
|
|
28
|
+
for (let m = 0; m < r.length; m++) r[m] = 0;
|
|
29
|
+
for (let m = 0; m < 8 * d.length; m += 8) r[m >> 5] |= (255 & d.charCodeAt(m / 8)) << m % 32;
|
|
30
|
+
return r;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function V(d) {
|
|
34
|
+
let r = "";
|
|
35
|
+
for (let m = 0; m < 32 * d.length; m += 8) r += String.fromCharCode(d[m >> 5] >>> m % 32 & 255);
|
|
36
|
+
return r;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function Y(d, g) {
|
|
40
|
+
d[g >> 5] |= 128 << g % 32, d[14 + (g + 64 >>> 9 << 4)] = g;
|
|
41
|
+
let m = 1732584193, f = -271733879, r = -1732584194, i = 271733878;
|
|
42
|
+
for (let n = 0; n < d.length; n += 16) {
|
|
43
|
+
let h = m,
|
|
44
|
+
t = f,
|
|
45
|
+
g = r,
|
|
46
|
+
e = i;
|
|
47
|
+
f = ii(f = ii(f = ii(f = ii(f = hh(f = hh(f = hh(f = hh(f = gg(f = gg(f = gg(f = gg(f = ff(f = ff(f = ff(f = ff(f, r = ff(r, i = ff(i, m = ff(m, f, r, i, d[n + 0], 7, -680876936), f, r, d[n + 1], 12, -389564586), m, f, d[n + 2], 17, 606105819), i, m, d[n + 3], 22, -1044525330), r = ff(r, i = ff(i, m = ff(m, f, r, i, d[n + 4], 7, -176418897), f, r, d[n + 5], 12, 1200080426), m, f, d[n + 6], 17, -1473231341), i, m, d[n + 7], 22, -45705983), r = ff(r, i = ff(i, m = ff(m, f, r, i, d[n + 8], 7, 1770035416), f, r, d[n + 9], 12, -1958414417), m, f, d[n + 10], 17, -42063), i, m, d[n + 11], 22, -1990404162), r = ff(r, i = ff(i, m = ff(m, f, r, i, d[n + 12], 7, 1804603682), f, r, d[n + 13], 12, -40341101), m, f, d[n + 14], 17, -1502002290), i, m, d[n + 15], 22, 1236535329), r = gg(r, i = gg(i, m = gg(m, f, r, i, d[n + 1], 5, -165796510), f, r, d[n + 6], 9, -1069501632), m, f, d[n + 11], 14, 643717713), i, m, d[n + 0], 20, -373897302), r = gg(r, i = gg(i, m = gg(m, f, r, i, d[n + 5], 5, -701558691), f, r, d[n + 10], 9, 38016083), m, f, d[n + 15], 14, -660478335), i, m, d[n + 4], 20, -405537848), r = gg(r, i = gg(i, m = gg(m, f, r, i, d[n + 9], 5, 568446438), f, r, d[n + 14], 9, -1019803690), m, f, d[n + 3], 14, -187363961), i, m, d[n + 8], 20, 1163531501), r = gg(r, i = gg(i, m = gg(m, f, r, i, d[n + 13], 5, -1444681467), f, r, d[n + 2], 9, -51403784), m, f, d[n + 7], 14, 1735328473), i, m, d[n + 12], 20, -1926607734), r = hh(r, i = hh(i, m = hh(m, f, r, i, d[n + 5], 4, -378558), f, r, d[n + 8], 11, -2022574463), m, f, d[n + 11], 16, 1839030562), i, m, d[n + 14], 23, -35309556), r = hh(r, i = hh(i, m = hh(m, f, r, i, d[n + 1], 4, -1530992060), f, r, d[n + 4], 11, 1272893353), m, f, d[n + 7], 16, -155497632), i, m, d[n + 10], 23, -1094730640), r = hh(r, i = hh(i, m = hh(m, f, r, i, d[n + 13], 4, 681279174), f, r, d[n + 0], 11, -358537222), m, f, d[n + 3], 16, -722521979), i, m, d[n + 6], 23, 76029189), r = hh(r, i = hh(i, m = hh(m, f, r, i, d[n + 9], 4, -640364487), f, r, d[n + 12], 11, -421815835), m, f, d[n + 15], 16, 530742520), i, m, d[n + 2], 23, -995338651), r = ii(r, i = ii(i, m = ii(m, f, r, i, d[n + 0], 6, -198630844), f, r, d[n + 7], 10, 1126891415), m, f, d[n + 14], 15, -1416354905), i, m, d[n + 5], 21, -57434055), r = ii(r, i = ii(i, m = ii(m, f, r, i, d[n + 12], 6, 1700485571), f, r, d[n + 3], 10, -1894986606), m, f, d[n + 10], 15, -1051523), i, m, d[n + 1], 21, -2054922799), r = ii(r, i = ii(i, m = ii(m, f, r, i, d[n + 8], 6, 1873313359), f, r, d[n + 15], 10, -30611744), m, f, d[n + 6], 15, -1560198380), i, m, d[n + 13], 21, 1309151649), r = ii(r, i = ii(i, m = ii(m, f, r, i, d[n + 4], 6, -145523070), f, r, d[n + 11], 10, -1120210379), m, f, d[n + 2], 15, 718787259), i, m, d[n + 9], 21, -343485551), m = add(m, h), f = add(f, t), r = add(r, g), i = add(i, e);
|
|
48
|
+
}
|
|
49
|
+
return Array(m, f, r, i);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function cmn(d, g, m, f, r, i) {
|
|
53
|
+
return add(rol(add(add(g, d), add(f, i)), r), m);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function ff(d, g, m, f, r, i, n) {
|
|
57
|
+
return cmn(g & m | ~g & f, d, g, r, i, n);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function gg(d, g, m, f, r, i, n) {
|
|
61
|
+
return cmn(g & f | m & ~f, d, g, r, i, n);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function hh(d, g, m, f, r, i, n) {
|
|
65
|
+
return cmn(g ^ m ^ f, d, g, r, i, n);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function ii(d, g, m, f, r, i, n) {
|
|
69
|
+
return cmn(m ^ (g | ~f), d, g, r, i, n);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function add(d, g) {
|
|
73
|
+
let m = (65535 & d) + (65535 & g);
|
|
74
|
+
return (d >> 16) + (g >> 16) + (m >> 16) << 16 | 65535 & m;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function rol(d, g) {
|
|
78
|
+
return d << g | d >>> 32 - g;
|
|
79
|
+
}
|
package/core/websock.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Websock: high-performance
|
|
2
|
+
* Websock: high-performance buffering wrapper
|
|
3
3
|
* Copyright (C) 2019 The noVNC Authors
|
|
4
4
|
* Licensed under MPL 2.0 (see LICENSE.txt)
|
|
5
5
|
*
|
|
6
|
-
* Websock is similar to the standard WebSocket
|
|
7
|
-
* buffer handling.
|
|
6
|
+
* Websock is similar to the standard WebSocket / RTCDataChannel object
|
|
7
|
+
* but with extra buffer handling.
|
|
8
8
|
*
|
|
9
9
|
* Websock has built-in receive queue buffering; the message event
|
|
10
10
|
* does not contain actual data but is simply a notification that
|
|
@@ -17,14 +17,39 @@ import * as Log from './util/logging.js';
|
|
|
17
17
|
// this has performance issues in some versions Chromium, and
|
|
18
18
|
// doesn't gain a tremendous amount of performance increase in Firefox
|
|
19
19
|
// at the moment. It may be valuable to turn it on in the future.
|
|
20
|
-
// Also copyWithin() for TypedArrays is not supported in IE 11 or
|
|
21
|
-
// Safari 13 (at the moment we want to support Safari 11).
|
|
22
|
-
const ENABLE_COPYWITHIN = false;
|
|
23
20
|
const MAX_RQ_GROW_SIZE = 40 * 1024 * 1024; // 40 MiB
|
|
24
21
|
|
|
22
|
+
// Constants pulled from RTCDataChannelState enum
|
|
23
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/readyState#RTCDataChannelState_enum
|
|
24
|
+
const DataChannel = {
|
|
25
|
+
CONNECTING: "connecting",
|
|
26
|
+
OPEN: "open",
|
|
27
|
+
CLOSING: "closing",
|
|
28
|
+
CLOSED: "closed"
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const ReadyStates = {
|
|
32
|
+
CONNECTING: [WebSocket.CONNECTING, DataChannel.CONNECTING],
|
|
33
|
+
OPEN: [WebSocket.OPEN, DataChannel.OPEN],
|
|
34
|
+
CLOSING: [WebSocket.CLOSING, DataChannel.CLOSING],
|
|
35
|
+
CLOSED: [WebSocket.CLOSED, DataChannel.CLOSED],
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Properties a raw channel must have, WebSocket and RTCDataChannel are two examples
|
|
39
|
+
const rawChannelProps = [
|
|
40
|
+
"send",
|
|
41
|
+
"close",
|
|
42
|
+
"binaryType",
|
|
43
|
+
"onerror",
|
|
44
|
+
"onmessage",
|
|
45
|
+
"onopen",
|
|
46
|
+
"protocol",
|
|
47
|
+
"readyState",
|
|
48
|
+
];
|
|
49
|
+
|
|
25
50
|
export default class Websock {
|
|
26
51
|
constructor() {
|
|
27
|
-
this._websocket = null; // WebSocket object
|
|
52
|
+
this._websocket = null; // WebSocket or RTCDataChannel object
|
|
28
53
|
|
|
29
54
|
this._rQi = 0; // Receive queue index
|
|
30
55
|
this._rQlen = 0; // Next write position in the receive queue
|
|
@@ -46,6 +71,29 @@ export default class Websock {
|
|
|
46
71
|
}
|
|
47
72
|
|
|
48
73
|
// Getters and Setters
|
|
74
|
+
|
|
75
|
+
get readyState() {
|
|
76
|
+
let subState;
|
|
77
|
+
|
|
78
|
+
if (this._websocket === null) {
|
|
79
|
+
return "unused";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
subState = this._websocket.readyState;
|
|
83
|
+
|
|
84
|
+
if (ReadyStates.CONNECTING.includes(subState)) {
|
|
85
|
+
return "connecting";
|
|
86
|
+
} else if (ReadyStates.OPEN.includes(subState)) {
|
|
87
|
+
return "open";
|
|
88
|
+
} else if (ReadyStates.CLOSING.includes(subState)) {
|
|
89
|
+
return "closing";
|
|
90
|
+
} else if (ReadyStates.CLOSED.includes(subState)) {
|
|
91
|
+
return "closed";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return "unknown";
|
|
95
|
+
}
|
|
96
|
+
|
|
49
97
|
get sQ() {
|
|
50
98
|
return this._sQ;
|
|
51
99
|
}
|
|
@@ -143,7 +191,7 @@ export default class Websock {
|
|
|
143
191
|
// Send Queue
|
|
144
192
|
|
|
145
193
|
flush() {
|
|
146
|
-
if (this._sQlen > 0 && this.
|
|
194
|
+
if (this._sQlen > 0 && this.readyState === 'open') {
|
|
147
195
|
this._websocket.send(this._encodeMessage());
|
|
148
196
|
this._sQlen = 0;
|
|
149
197
|
}
|
|
@@ -180,12 +228,25 @@ export default class Websock {
|
|
|
180
228
|
}
|
|
181
229
|
|
|
182
230
|
open(uri, protocols) {
|
|
231
|
+
this.attach(new WebSocket(uri, protocols));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
attach(rawChannel) {
|
|
183
235
|
this.init();
|
|
184
236
|
|
|
185
|
-
|
|
186
|
-
|
|
237
|
+
// Must get object and class methods to be compatible with the tests.
|
|
238
|
+
const channelProps = [...Object.keys(rawChannel), ...Object.getOwnPropertyNames(Object.getPrototypeOf(rawChannel))];
|
|
239
|
+
for (let i = 0; i < rawChannelProps.length; i++) {
|
|
240
|
+
const prop = rawChannelProps[i];
|
|
241
|
+
if (channelProps.indexOf(prop) < 0) {
|
|
242
|
+
throw new Error('Raw channel missing property: ' + prop);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
187
245
|
|
|
246
|
+
this._websocket = rawChannel;
|
|
247
|
+
this._websocket.binaryType = "arraybuffer";
|
|
188
248
|
this._websocket.onmessage = this._recvMessage.bind(this);
|
|
249
|
+
|
|
189
250
|
this._websocket.onopen = () => {
|
|
190
251
|
Log.Debug('>> WebSock.onopen');
|
|
191
252
|
if (this._websocket.protocol) {
|
|
@@ -195,11 +256,13 @@ export default class Websock {
|
|
|
195
256
|
this._eventHandlers.open();
|
|
196
257
|
Log.Debug("<< WebSock.onopen");
|
|
197
258
|
};
|
|
259
|
+
|
|
198
260
|
this._websocket.onclose = (e) => {
|
|
199
261
|
Log.Debug(">> WebSock.onclose");
|
|
200
262
|
this._eventHandlers.close(e);
|
|
201
263
|
Log.Debug("<< WebSock.onclose");
|
|
202
264
|
};
|
|
265
|
+
|
|
203
266
|
this._websocket.onerror = (e) => {
|
|
204
267
|
Log.Debug(">> WebSock.onerror: " + e);
|
|
205
268
|
this._eventHandlers.error(e);
|
|
@@ -209,8 +272,8 @@ export default class Websock {
|
|
|
209
272
|
|
|
210
273
|
close() {
|
|
211
274
|
if (this._websocket) {
|
|
212
|
-
if (
|
|
213
|
-
|
|
275
|
+
if (this.readyState === 'connecting' ||
|
|
276
|
+
this.readyState === 'open') {
|
|
214
277
|
Log.Info("Closing WebSocket connection");
|
|
215
278
|
this._websocket.close();
|
|
216
279
|
}
|
|
@@ -256,11 +319,7 @@ export default class Websock {
|
|
|
256
319
|
this._rQ = new Uint8Array(this._rQbufferSize);
|
|
257
320
|
this._rQ.set(new Uint8Array(oldRQbuffer, this._rQi, this._rQlen - this._rQi));
|
|
258
321
|
} else {
|
|
259
|
-
|
|
260
|
-
this._rQ.copyWithin(0, this._rQi, this._rQlen);
|
|
261
|
-
} else {
|
|
262
|
-
this._rQ.set(new Uint8Array(this._rQ.buffer, this._rQi, this._rQlen - this._rQi));
|
|
263
|
-
}
|
|
322
|
+
this._rQ.copyWithin(0, this._rQi, this._rQlen);
|
|
264
323
|
}
|
|
265
324
|
|
|
266
325
|
this._rQlen = this._rQlen - this._rQi;
|
package/docs/API.md
CHANGED
|
@@ -86,9 +86,13 @@ protocol stream.
|
|
|
86
86
|
- The `connect` event is fired when the `RFB` object has completed
|
|
87
87
|
the connection and handshaking with the server.
|
|
88
88
|
|
|
89
|
-
[`disconnect`](#
|
|
89
|
+
[`disconnect`](#disconnect)
|
|
90
90
|
- The `disconnect` event is fired when the `RFB` object disconnects.
|
|
91
91
|
|
|
92
|
+
[`serververification`](#serververification)
|
|
93
|
+
- The `serververification` event is fired when the server identity
|
|
94
|
+
must be confirmed by the user.
|
|
95
|
+
|
|
92
96
|
[`credentialsrequired`](#credentialsrequired)
|
|
93
97
|
- The `credentialsrequired` event is fired when more credentials must
|
|
94
98
|
be given to continue.
|
|
@@ -118,11 +122,16 @@ protocol stream.
|
|
|
118
122
|
[`RFB.disconnect()`](#rfbdisconnect)
|
|
119
123
|
- Disconnect from the server.
|
|
120
124
|
|
|
125
|
+
[`RFB.approveServer()`](#rfbapproveserver)
|
|
126
|
+
- Proceed connecting to the server. Should be called after the
|
|
127
|
+
[`serververification`](#serververification) event has fired and the
|
|
128
|
+
user has verified the identity of the server.
|
|
129
|
+
|
|
121
130
|
[`RFB.sendCredentials()`](#rfbsendcredentials)
|
|
122
131
|
- Send credentials to server. Should be called after the
|
|
123
132
|
[`credentialsrequired`](#credentialsrequired) event has fired.
|
|
124
133
|
|
|
125
|
-
[`RFB.sendKey()`](#
|
|
134
|
+
[`RFB.sendKey()`](#rfbsendkey)
|
|
126
135
|
- Send a key event.
|
|
127
136
|
|
|
128
137
|
[`RFB.sendCtrlAltDel()`](#rfbsendctrlaltdel)
|
|
@@ -143,9 +152,18 @@ protocol stream.
|
|
|
143
152
|
[`RFB.machineReset()`](#rfbmachinereset)
|
|
144
153
|
- Request a reset of the remote machine.
|
|
145
154
|
|
|
146
|
-
[`RFB.clipboardPasteFrom()`](#
|
|
155
|
+
[`RFB.clipboardPasteFrom()`](#rfbclipboardpastefrom)
|
|
147
156
|
- Send clipboard contents to server.
|
|
148
157
|
|
|
158
|
+
[`RFB.getImageData()`](#rfbgetimagedata)
|
|
159
|
+
- Return the current content of the screen as an ImageData array.
|
|
160
|
+
|
|
161
|
+
[`RFB.toDataURL()`](#rfbtodataurl)
|
|
162
|
+
- Return the current content of the screen as data-url encoded image file.
|
|
163
|
+
|
|
164
|
+
[`RFB.toBlob()`](#rfbtoblob)
|
|
165
|
+
- Return the current content of the screen as Blob encoded image file.
|
|
166
|
+
|
|
149
167
|
### Details
|
|
150
168
|
|
|
151
169
|
#### RFB()
|
|
@@ -165,9 +183,9 @@ connection to a specified VNC server.
|
|
|
165
183
|
existing contents of the `HTMLElement` will be untouched, but new
|
|
166
184
|
elements will be added during the lifetime of the `RFB` object.
|
|
167
185
|
|
|
168
|
-
**`
|
|
186
|
+
**`urlOrDataChannel`**
|
|
169
187
|
- A `DOMString` specifying the VNC server to connect to. This must be
|
|
170
|
-
a valid WebSocket URL.
|
|
188
|
+
a valid WebSocket URL. This can also be a `WebSocket` or `RTCDataChannel`.
|
|
171
189
|
|
|
172
190
|
**`options`** *Optional*
|
|
173
191
|
- An `Object` specifying extra details about how the connection
|
|
@@ -212,6 +230,20 @@ property `clean`. `clean` is a `boolean` indicating if the termination
|
|
|
212
230
|
was clean or not. In the event of an unexpected termination or an error
|
|
213
231
|
`clean` will be set to false.
|
|
214
232
|
|
|
233
|
+
#### serververification
|
|
234
|
+
|
|
235
|
+
The `serververification` event is fired when the server provides
|
|
236
|
+
information that allows the user to verify that it is the correct server
|
|
237
|
+
and protect against a man-in-the-middle attack. The `detail` property is
|
|
238
|
+
an `Object` containing the property `type` which is a `DOMString`
|
|
239
|
+
specifying which type of information the server has provided. Other
|
|
240
|
+
properties are also available, depending on the value of `type`:
|
|
241
|
+
|
|
242
|
+
`"RSA"`
|
|
243
|
+
- The server identity is verified using just a RSA key. The property
|
|
244
|
+
`publickey` is a `Uint8Array` containing the public key in a unsigned
|
|
245
|
+
big endian representation.
|
|
246
|
+
|
|
215
247
|
#### credentialsrequired
|
|
216
248
|
|
|
217
249
|
The `credentialsrequired` event is fired when the server requests more
|
|
@@ -271,6 +303,16 @@ connected server.
|
|
|
271
303
|
|
|
272
304
|
RFB.disconnect( );
|
|
273
305
|
|
|
306
|
+
#### RFB.approveServer()
|
|
307
|
+
|
|
308
|
+
The `RFB.approveServer()` method is used to signal that the user has
|
|
309
|
+
verified the server identity provided in a `serververification` event
|
|
310
|
+
and that the connection can continue.
|
|
311
|
+
|
|
312
|
+
##### Syntax
|
|
313
|
+
|
|
314
|
+
RFB.approveServer( );
|
|
315
|
+
|
|
274
316
|
#### RFB.sendCredentials()
|
|
275
317
|
|
|
276
318
|
The `RFB.sendCredentials()` method is used to provide the missing
|
|
@@ -328,7 +370,14 @@ Keyboard events will be sent to the remote server after this point.
|
|
|
328
370
|
|
|
329
371
|
##### Syntax
|
|
330
372
|
|
|
331
|
-
RFB.focus( );
|
|
373
|
+
RFB.focus( [options] );
|
|
374
|
+
|
|
375
|
+
###### Parameters
|
|
376
|
+
|
|
377
|
+
**`options`** *Optional*
|
|
378
|
+
- A `object` providing options to control how the focus will be
|
|
379
|
+
performed. Please see [`HTMLElement.focus()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus)
|
|
380
|
+
for available options.
|
|
332
381
|
|
|
333
382
|
#### RFB.blur()
|
|
334
383
|
|
|
@@ -383,3 +432,55 @@ to the remote server.
|
|
|
383
432
|
|
|
384
433
|
**`text`**
|
|
385
434
|
- A `DOMString` specifying the clipboard data to send.
|
|
435
|
+
|
|
436
|
+
#### RFB.getImageData()
|
|
437
|
+
|
|
438
|
+
The `RFB.getImageData()` method is used to return the current content of the
|
|
439
|
+
screen encoded as [`ImageData`](https://developer.mozilla.org/en-US/docs/Web/API/ImageData).
|
|
440
|
+
|
|
441
|
+
##### Syntax
|
|
442
|
+
|
|
443
|
+
RFB.getImageData();
|
|
444
|
+
|
|
445
|
+
#### RFB.toDataURL()
|
|
446
|
+
|
|
447
|
+
The `RFB.toDataURL()` method is used to return the current content of the
|
|
448
|
+
screen encoded as a data URL that could for example be put in the `src` attribute
|
|
449
|
+
of an `img` tag.
|
|
450
|
+
|
|
451
|
+
##### Syntax
|
|
452
|
+
|
|
453
|
+
RFB.toDataURL();
|
|
454
|
+
RFB.toDataURL(type);
|
|
455
|
+
RFB.toDataURL(type, encoderOptions);
|
|
456
|
+
|
|
457
|
+
###### Parameters
|
|
458
|
+
|
|
459
|
+
**`type`** *Optional*
|
|
460
|
+
- A string indicating the requested MIME type of the image
|
|
461
|
+
|
|
462
|
+
**`encoderOptions`** *Optional*
|
|
463
|
+
- A number between 0 and 1 indicating the image quality.
|
|
464
|
+
|
|
465
|
+
#### RFB.toBlob()
|
|
466
|
+
|
|
467
|
+
The `RFB.toBlob()` method is used to return the current content of the
|
|
468
|
+
screen encoded as [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob).
|
|
469
|
+
|
|
470
|
+
##### Syntax
|
|
471
|
+
|
|
472
|
+
RFB.toDataURL(callback);
|
|
473
|
+
RFB.toDataURL(callback, type);
|
|
474
|
+
RFB.toDataURL(callback, type, quality);
|
|
475
|
+
|
|
476
|
+
###### Parameters
|
|
477
|
+
|
|
478
|
+
**`callback`**
|
|
479
|
+
- A callback function which will receive the resulting [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
|
|
480
|
+
as the single argument
|
|
481
|
+
|
|
482
|
+
**`type`** *Optional*
|
|
483
|
+
- A string indicating the requested MIME type of the image
|
|
484
|
+
|
|
485
|
+
**`encoderOptions`** *Optional*
|
|
486
|
+
- A number between 0 and 1 indicating the image quality.
|
package/docs/LIBRARY.md
CHANGED
|
@@ -18,18 +18,14 @@ do things.
|
|
|
18
18
|
|
|
19
19
|
## Conversion of Modules
|
|
20
20
|
|
|
21
|
-
noVNC is written using ECMAScript 6 modules.
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
noVNC is written using ECMAScript 6 modules. This is not supported by older
|
|
22
|
+
versions of Node.js. To use noVNC with those older versions of Node.js the
|
|
23
|
+
library must first be converted.
|
|
24
24
|
|
|
25
25
|
Fortunately noVNC includes a script to handle this conversion. Please follow
|
|
26
26
|
the following steps:
|
|
27
27
|
|
|
28
28
|
1. Install Node.js
|
|
29
29
|
2. Run `npm install` in the noVNC directory
|
|
30
|
-
3. Run `./utils/use_require.js --as <module format>`
|
|
31
|
-
|
|
32
|
-
Several module formats are available. Please run
|
|
33
|
-
`./utils/use_require.js --help` to see them all.
|
|
34
30
|
|
|
35
31
|
The result of the conversion is available in the `lib/` directory.
|
package/lib/base64.js
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
function _typeof(obj) { "@babel/helpers - typeof";
|
|
4
|
-
|
|
3
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
5
4
|
Object.defineProperty(exports, "__esModule", {
|
|
6
5
|
value: true
|
|
7
6
|
});
|
|
8
|
-
exports
|
|
9
|
-
|
|
7
|
+
exports["default"] = void 0;
|
|
10
8
|
var Log = _interopRequireWildcard(require("./util/logging.js"));
|
|
11
|
-
|
|
12
|
-
function
|
|
13
|
-
|
|
14
|
-
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
15
|
-
|
|
9
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
10
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
16
11
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
17
12
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
18
13
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
@@ -26,18 +21,18 @@ var _default = {
|
|
|
26
21
|
|
|
27
22
|
var result = '';
|
|
28
23
|
var length = data.length;
|
|
29
|
-
var lengthpad = length % 3;
|
|
24
|
+
var lengthpad = length % 3;
|
|
25
|
+
// Convert every three bytes to 4 ascii characters.
|
|
30
26
|
|
|
31
27
|
for (var i = 0; i < length - 2; i += 3) {
|
|
32
28
|
result += this.toBase64Table[data[i] >> 2];
|
|
33
29
|
result += this.toBase64Table[((data[i] & 0x03) << 4) + (data[i + 1] >> 4)];
|
|
34
30
|
result += this.toBase64Table[((data[i + 1] & 0x0f) << 2) + (data[i + 2] >> 6)];
|
|
35
31
|
result += this.toBase64Table[data[i + 2] & 0x3f];
|
|
36
|
-
}
|
|
37
|
-
|
|
32
|
+
}
|
|
38
33
|
|
|
34
|
+
// Convert the remaining 1 or 2 bytes, pad out to 4 characters.
|
|
39
35
|
var j = length - lengthpad;
|
|
40
|
-
|
|
41
36
|
if (lengthpad === 2) {
|
|
42
37
|
result += this.toBase64Table[data[j] >> 2];
|
|
43
38
|
result += this.toBase64Table[((data[j] & 0x03) << 4) + (data[j + 1] >> 4)];
|
|
@@ -49,67 +44,58 @@ var _default = {
|
|
|
49
44
|
result += this.toBase64Table[64];
|
|
50
45
|
result += this.toBase64Table[64];
|
|
51
46
|
}
|
|
52
|
-
|
|
53
47
|
return result;
|
|
54
48
|
},
|
|
55
|
-
|
|
56
49
|
/* Convert Base64 data to a string */
|
|
57
|
-
|
|
58
50
|
/* eslint-disable comma-spacing */
|
|
59
51
|
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],
|
|
60
|
-
|
|
61
|
-
/* eslint-enable comma-spacing */
|
|
62
|
-
decode: function decode(data) {
|
|
52
|
+
/* eslint-enable comma-spacing */decode: function decode(data) {
|
|
63
53
|
var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
64
54
|
var dataLength = data.indexOf('=') - offset;
|
|
65
|
-
|
|
66
55
|
if (dataLength < 0) {
|
|
67
56
|
dataLength = data.length - offset;
|
|
68
57
|
}
|
|
69
|
-
/* Every four characters is 3 resulting numbers */
|
|
70
|
-
|
|
71
58
|
|
|
59
|
+
/* Every four characters is 3 resulting numbers */
|
|
72
60
|
var resultLength = (dataLength >> 2) * 3 + Math.floor(dataLength % 4 / 1.5);
|
|
73
|
-
var result = new Array(resultLength);
|
|
61
|
+
var result = new Array(resultLength);
|
|
74
62
|
|
|
75
|
-
|
|
63
|
+
// Convert one by one.
|
|
76
64
|
|
|
65
|
+
var leftbits = 0; // number of bits decoded, but yet to be appended
|
|
77
66
|
var leftdata = 0; // bits decoded, but yet to be appended
|
|
78
|
-
|
|
79
67
|
for (var idx = 0, i = offset; i < data.length; i++) {
|
|
80
68
|
var c = this.toBinaryTable[data.charCodeAt(i) & 0x7f];
|
|
81
|
-
var padding = data.charAt(i) === this.base64Pad;
|
|
82
|
-
|
|
69
|
+
var padding = data.charAt(i) === this.base64Pad;
|
|
70
|
+
// Skip illegal characters and whitespace
|
|
83
71
|
if (c === -1) {
|
|
84
72
|
Log.Error("Illegal character code " + data.charCodeAt(i) + " at position " + i);
|
|
85
73
|
continue;
|
|
86
|
-
}
|
|
87
|
-
|
|
74
|
+
}
|
|
88
75
|
|
|
76
|
+
// Collect data into leftdata, update bitcount
|
|
89
77
|
leftdata = leftdata << 6 | c;
|
|
90
|
-
leftbits += 6;
|
|
78
|
+
leftbits += 6;
|
|
91
79
|
|
|
80
|
+
// If we have 8 or more bits, append 8 bits to the result
|
|
92
81
|
if (leftbits >= 8) {
|
|
93
|
-
leftbits -= 8;
|
|
94
|
-
|
|
82
|
+
leftbits -= 8;
|
|
83
|
+
// Append if not padding.
|
|
95
84
|
if (!padding) {
|
|
96
85
|
result[idx++] = leftdata >> leftbits & 0xff;
|
|
97
86
|
}
|
|
98
|
-
|
|
99
87
|
leftdata &= (1 << leftbits) - 1;
|
|
100
88
|
}
|
|
101
|
-
}
|
|
102
|
-
|
|
89
|
+
}
|
|
103
90
|
|
|
91
|
+
// If there are any bits left, the base64 string was corrupted
|
|
104
92
|
if (leftbits) {
|
|
105
93
|
var err = new Error('Corrupted base64 string');
|
|
106
94
|
err.name = 'Base64-Error';
|
|
107
95
|
throw err;
|
|
108
96
|
}
|
|
109
|
-
|
|
110
97
|
return result;
|
|
111
98
|
}
|
|
112
99
|
};
|
|
113
100
|
/* End of Base64 namespace */
|
|
114
|
-
|
|
115
|
-
exports.default = _default;
|
|
101
|
+
exports["default"] = _default;
|