@novnc/novnc 1.3.0-g1d148a8 → 1.3.0-g1ff2ecd
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/core/des.js +1 -1
- package/core/display.js +12 -0
- package/core/input/keyboard.js +10 -0
- package/core/rfb.js +109 -4
- package/core/util/browser.js +56 -7
- package/core/util/cursor.js +4 -0
- package/docs/API.md +255 -179
- package/lib/base64.js +19 -33
- package/lib/decoders/copyrect.js +4 -11
- package/lib/decoders/hextile.js +16 -46
- package/lib/decoders/jpeg.js +4 -43
- package/lib/decoders/raw.js +8 -21
- package/lib/decoders/rre.js +4 -15
- package/lib/decoders/tight.js +12 -78
- package/lib/decoders/tightpng.js +3 -23
- package/lib/decoders/zrle.js +6 -52
- package/lib/deflator.js +8 -22
- package/lib/des.js +23 -36
- package/lib/display.js +61 -107
- package/lib/encodings.js +1 -10
- package/lib/inflator.js +5 -18
- package/lib/input/domkeytable.js +77 -48
- package/lib/input/fixedkeys.js +8 -3
- package/lib/input/gesturehandler.js +85 -152
- package/lib/input/keyboard.js +61 -90
- package/lib/input/keysym.js +14 -270
- package/lib/input/keysymdef.js +5 -7
- package/lib/input/util.js +42 -84
- package/lib/input/vkeys.js +0 -3
- package/lib/input/xtscancodes.js +1 -168
- package/lib/ra2.js +501 -755
- package/lib/rfb.js +477 -1016
- package/lib/util/browser.js +65 -28
- package/lib/util/cursor.js +28 -65
- package/lib/util/element.js +3 -5
- package/lib/util/events.js +23 -30
- package/lib/util/eventtarget.js +4 -13
- package/lib/util/int.js +1 -2
- package/lib/util/logging.js +1 -19
- package/lib/util/md5.js +10 -36
- package/lib/util/strings.js +3 -5
- package/lib/vendor/pako/lib/utils/common.js +8 -17
- package/lib/vendor/pako/lib/zlib/adler32.js +3 -7
- package/lib/vendor/pako/lib/zlib/constants.js +2 -5
- package/lib/vendor/pako/lib/zlib/crc32.js +5 -12
- package/lib/vendor/pako/lib/zlib/deflate.js +212 -617
- package/lib/vendor/pako/lib/zlib/gzheader.js +1 -13
- package/lib/vendor/pako/lib/zlib/inffast.js +60 -176
- package/lib/vendor/pako/lib/zlib/inflate.js +397 -887
- package/lib/vendor/pako/lib/zlib/inftrees.js +62 -168
- package/lib/vendor/pako/lib/zlib/messages.js +1 -11
- package/lib/vendor/pako/lib/zlib/trees.js +245 -587
- package/lib/vendor/pako/lib/zlib/zstream.js +2 -18
- package/lib/websock.js +36 -87
- package/package.json +31 -31
package/core/des.js
CHANGED
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
const PC2 = [13,16,10,23, 0, 4, 2,27,14, 5,20, 9,22,18,11, 3,
|
|
82
82
|
25, 7,15, 6,26,19,12, 1,40,51,30,36,46,54,29,39,
|
|
83
83
|
50,44,32,47,43,48,38,55,33,52,45,41,49,35,28,31 ],
|
|
84
|
-
|
|
84
|
+
totrot = [ 1, 2, 4, 6, 8,10,12,14,15,17,19,21,23,25,27,28];
|
|
85
85
|
|
|
86
86
|
const z = 0x0;
|
|
87
87
|
let a,b,c,d,e,f;
|
package/core/display.js
CHANGED
|
@@ -224,6 +224,18 @@ export default class Display {
|
|
|
224
224
|
this.viewportChangePos(0, 0);
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
+
getImageData() {
|
|
228
|
+
return this._drawCtx.getImageData(0, 0, this.width, this.height);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
toDataURL(type, encoderOptions) {
|
|
232
|
+
return this._backbuffer.toDataURL(type, encoderOptions);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
toBlob(callback, type, quality) {
|
|
236
|
+
return this._backbuffer.toBlob(callback, type, quality);
|
|
237
|
+
}
|
|
238
|
+
|
|
227
239
|
// Track what parts of the visible canvas that need updating
|
|
228
240
|
_damage(x, y, w, h) {
|
|
229
241
|
if (x < this._damageBounds.left) {
|
package/core/input/keyboard.js
CHANGED
|
@@ -153,6 +153,16 @@ export default class Keyboard {
|
|
|
153
153
|
keysym = this._keyDownList[code];
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
// macOS doesn't send proper key releases if a key is pressed
|
|
157
|
+
// while meta is held down
|
|
158
|
+
if ((browser.isMac() || browser.isIOS()) &&
|
|
159
|
+
(e.metaKey && code !== 'MetaLeft' && code !== 'MetaRight')) {
|
|
160
|
+
this._sendKeyEvent(keysym, code, true);
|
|
161
|
+
this._sendKeyEvent(keysym, code, false);
|
|
162
|
+
stopEvent(e);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
156
166
|
// macOS doesn't send proper key events for modifiers, only
|
|
157
167
|
// state change events. That gets extra confusing for CapsLock
|
|
158
168
|
// which toggles on each press, but not on release. So pretend
|
package/core/rfb.js
CHANGED
|
@@ -62,6 +62,7 @@ const securityTypeTight = 16;
|
|
|
62
62
|
const securityTypeVeNCrypt = 19;
|
|
63
63
|
const securityTypeXVP = 22;
|
|
64
64
|
const securityTypeARD = 30;
|
|
65
|
+
const securityTypeMSLogonII = 113;
|
|
65
66
|
|
|
66
67
|
// Special Tight security types
|
|
67
68
|
const securityTypeUnixLogon = 129;
|
|
@@ -286,6 +287,7 @@ export default class RFB extends EventTargetMixin {
|
|
|
286
287
|
|
|
287
288
|
this._viewOnly = false;
|
|
288
289
|
this._clipViewport = false;
|
|
290
|
+
this._clippingViewport = false;
|
|
289
291
|
this._scaleViewport = false;
|
|
290
292
|
this._resizeSession = false;
|
|
291
293
|
|
|
@@ -317,6 +319,16 @@ export default class RFB extends EventTargetMixin {
|
|
|
317
319
|
|
|
318
320
|
get capabilities() { return this._capabilities; }
|
|
319
321
|
|
|
322
|
+
get clippingViewport() { return this._clippingViewport; }
|
|
323
|
+
_setClippingViewport(on) {
|
|
324
|
+
if (on === this._clippingViewport) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
this._clippingViewport = on;
|
|
328
|
+
this.dispatchEvent(new CustomEvent("clippingviewport",
|
|
329
|
+
{ detail: this._clippingViewport }));
|
|
330
|
+
}
|
|
331
|
+
|
|
320
332
|
get touchButton() { return 0; }
|
|
321
333
|
set touchButton(button) { Log.Warn("Using old API!"); }
|
|
322
334
|
|
|
@@ -490,16 +502,45 @@ export default class RFB extends EventTargetMixin {
|
|
|
490
502
|
this._clipboardText = text;
|
|
491
503
|
RFB.messages.extendedClipboardNotify(this._sock, [extendedClipboardFormatText]);
|
|
492
504
|
} else {
|
|
493
|
-
let
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
505
|
+
let length, i;
|
|
506
|
+
let data;
|
|
507
|
+
|
|
508
|
+
length = 0;
|
|
509
|
+
// eslint-disable-next-line no-unused-vars
|
|
510
|
+
for (let codePoint of text) {
|
|
511
|
+
length++;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
data = new Uint8Array(length);
|
|
515
|
+
|
|
516
|
+
i = 0;
|
|
517
|
+
for (let codePoint of text) {
|
|
518
|
+
let code = codePoint.codePointAt(0);
|
|
519
|
+
|
|
520
|
+
/* Only ISO 8859-1 is supported */
|
|
521
|
+
if (code > 0xff) {
|
|
522
|
+
code = 0x3f; // '?'
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
data[i++] = code;
|
|
497
526
|
}
|
|
498
527
|
|
|
499
528
|
RFB.messages.clientCutText(this._sock, data);
|
|
500
529
|
}
|
|
501
530
|
}
|
|
502
531
|
|
|
532
|
+
getImageData() {
|
|
533
|
+
return this._display.getImageData();
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
toDataURL(type, encoderOptions) {
|
|
537
|
+
return this._display.toDataURL(type, encoderOptions);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
toBlob(callback, type, quality) {
|
|
541
|
+
return this._display.toBlob(callback, type, quality);
|
|
542
|
+
}
|
|
543
|
+
|
|
503
544
|
// ===== PRIVATE METHODS =====
|
|
504
545
|
|
|
505
546
|
_connect() {
|
|
@@ -719,6 +760,10 @@ export default class RFB extends EventTargetMixin {
|
|
|
719
760
|
const size = this._screenSize();
|
|
720
761
|
this._display.viewportChangeSize(size.w, size.h);
|
|
721
762
|
this._fixScrollbars();
|
|
763
|
+
this._setClippingViewport(size.w < this._display.width ||
|
|
764
|
+
size.h < this._display.height);
|
|
765
|
+
} else {
|
|
766
|
+
this._setClippingViewport(false);
|
|
722
767
|
}
|
|
723
768
|
|
|
724
769
|
// When changing clipping we might show or hide scrollbars.
|
|
@@ -1363,6 +1408,7 @@ export default class RFB extends EventTargetMixin {
|
|
|
1363
1408
|
securityTypeVeNCrypt,
|
|
1364
1409
|
securityTypeXVP,
|
|
1365
1410
|
securityTypeARD,
|
|
1411
|
+
securityTypeMSLogonII,
|
|
1366
1412
|
securityTypePlain,
|
|
1367
1413
|
];
|
|
1368
1414
|
|
|
@@ -1874,6 +1920,62 @@ export default class RFB extends EventTargetMixin {
|
|
|
1874
1920
|
return false;
|
|
1875
1921
|
}
|
|
1876
1922
|
|
|
1923
|
+
_negotiateMSLogonIIAuth() {
|
|
1924
|
+
if (this._sock.rQwait("mslogonii dh param", 24)) { return false; }
|
|
1925
|
+
|
|
1926
|
+
if (this._rfbCredentials.username === undefined ||
|
|
1927
|
+
this._rfbCredentials.password === undefined) {
|
|
1928
|
+
this.dispatchEvent(new CustomEvent(
|
|
1929
|
+
"credentialsrequired",
|
|
1930
|
+
{ detail: { types: ["username", "password"] } }));
|
|
1931
|
+
return false;
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
const g = this._sock.rQshiftBytes(8);
|
|
1935
|
+
const p = this._sock.rQshiftBytes(8);
|
|
1936
|
+
const A = this._sock.rQshiftBytes(8);
|
|
1937
|
+
const b = window.crypto.getRandomValues(new Uint8Array(8));
|
|
1938
|
+
const B = new Uint8Array(this._modPow(g, b, p));
|
|
1939
|
+
const secret = new Uint8Array(this._modPow(A, b, p));
|
|
1940
|
+
|
|
1941
|
+
const des = new DES(secret);
|
|
1942
|
+
const username = encodeUTF8(this._rfbCredentials.username).substring(0, 255);
|
|
1943
|
+
const password = encodeUTF8(this._rfbCredentials.password).substring(0, 63);
|
|
1944
|
+
const usernameBytes = new Uint8Array(256);
|
|
1945
|
+
const passwordBytes = new Uint8Array(64);
|
|
1946
|
+
window.crypto.getRandomValues(usernameBytes);
|
|
1947
|
+
window.crypto.getRandomValues(passwordBytes);
|
|
1948
|
+
for (let i = 0; i < username.length; i++) {
|
|
1949
|
+
usernameBytes[i] = username.charCodeAt(i);
|
|
1950
|
+
}
|
|
1951
|
+
usernameBytes[username.length] = 0;
|
|
1952
|
+
for (let i = 0; i < password.length; i++) {
|
|
1953
|
+
passwordBytes[i] = password.charCodeAt(i);
|
|
1954
|
+
}
|
|
1955
|
+
passwordBytes[password.length] = 0;
|
|
1956
|
+
let x = new Uint8Array(secret);
|
|
1957
|
+
for (let i = 0; i < 32; i++) {
|
|
1958
|
+
for (let j = 0; j < 8; j++) {
|
|
1959
|
+
x[j] ^= usernameBytes[i * 8 + j];
|
|
1960
|
+
}
|
|
1961
|
+
x = des.enc8(x);
|
|
1962
|
+
usernameBytes.set(x, i * 8);
|
|
1963
|
+
}
|
|
1964
|
+
x = new Uint8Array(secret);
|
|
1965
|
+
for (let i = 0; i < 8; i++) {
|
|
1966
|
+
for (let j = 0; j < 8; j++) {
|
|
1967
|
+
x[j] ^= passwordBytes[i * 8 + j];
|
|
1968
|
+
}
|
|
1969
|
+
x = des.enc8(x);
|
|
1970
|
+
passwordBytes.set(x, i * 8);
|
|
1971
|
+
}
|
|
1972
|
+
this._sock.send(B);
|
|
1973
|
+
this._sock.send(usernameBytes);
|
|
1974
|
+
this._sock.send(passwordBytes);
|
|
1975
|
+
this._rfbInitState = "SecurityResult";
|
|
1976
|
+
return true;
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1877
1979
|
_negotiateAuthentication() {
|
|
1878
1980
|
switch (this._rfbAuthScheme) {
|
|
1879
1981
|
case securityTypeNone:
|
|
@@ -1904,6 +2006,9 @@ export default class RFB extends EventTargetMixin {
|
|
|
1904
2006
|
case securityTypeRA2ne:
|
|
1905
2007
|
return this._negotiateRA2neAuth();
|
|
1906
2008
|
|
|
2009
|
+
case securityTypeMSLogonII:
|
|
2010
|
+
return this._negotiateMSLogonIIAuth();
|
|
2011
|
+
|
|
1907
2012
|
default:
|
|
1908
2013
|
return this._fail("Unsupported auth scheme (scheme: " +
|
|
1909
2014
|
this._rfbAuthScheme + ")");
|
package/core/util/browser.js
CHANGED
|
@@ -77,27 +77,76 @@ export const hasScrollbarGutter = _hasScrollbarGutter;
|
|
|
77
77
|
* It's better to use feature detection than platform detection.
|
|
78
78
|
*/
|
|
79
79
|
|
|
80
|
+
/* OS */
|
|
81
|
+
|
|
80
82
|
export function isMac() {
|
|
81
|
-
return
|
|
83
|
+
return !!(/mac/i).exec(navigator.platform);
|
|
82
84
|
}
|
|
83
85
|
|
|
84
86
|
export function isWindows() {
|
|
85
|
-
return
|
|
87
|
+
return !!(/win/i).exec(navigator.platform);
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
export function isIOS() {
|
|
89
|
-
return navigator
|
|
90
|
-
(!!(/ipad/i).exec(navigator.platform) ||
|
|
91
|
+
return (!!(/ipad/i).exec(navigator.platform) ||
|
|
91
92
|
!!(/iphone/i).exec(navigator.platform) ||
|
|
92
93
|
!!(/ipod/i).exec(navigator.platform));
|
|
93
94
|
}
|
|
94
95
|
|
|
96
|
+
export function isAndroid() {
|
|
97
|
+
/* Android sets navigator.platform to Linux :/ */
|
|
98
|
+
return !!navigator.userAgent.match('Android ');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function isChromeOS() {
|
|
102
|
+
/* ChromeOS sets navigator.platform to Linux :/ */
|
|
103
|
+
return !!navigator.userAgent.match(' CrOS ');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* Browser */
|
|
107
|
+
|
|
95
108
|
export function isSafari() {
|
|
96
|
-
return navigator
|
|
97
|
-
|
|
109
|
+
return !!navigator.userAgent.match('Safari/...') &&
|
|
110
|
+
!navigator.userAgent.match('Chrome/...') &&
|
|
111
|
+
!navigator.userAgent.match('Chromium/...') &&
|
|
112
|
+
!navigator.userAgent.match('Epiphany/...');
|
|
98
113
|
}
|
|
99
114
|
|
|
100
115
|
export function isFirefox() {
|
|
101
|
-
return
|
|
116
|
+
return !!navigator.userAgent.match('Firefox/...') &&
|
|
117
|
+
!navigator.userAgent.match('Seamonkey/...');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function isChrome() {
|
|
121
|
+
return !!navigator.userAgent.match('Chrome/...') &&
|
|
122
|
+
!navigator.userAgent.match('Chromium/...') &&
|
|
123
|
+
!navigator.userAgent.match('Edg/...') &&
|
|
124
|
+
!navigator.userAgent.match('OPR/...');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function isChromium() {
|
|
128
|
+
return !!navigator.userAgent.match('Chromium/...');
|
|
102
129
|
}
|
|
103
130
|
|
|
131
|
+
export function isOpera() {
|
|
132
|
+
return !!navigator.userAgent.match('OPR/...');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function isEdge() {
|
|
136
|
+
return !!navigator.userAgent.match('Edg/...');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* Engine */
|
|
140
|
+
|
|
141
|
+
export function isGecko() {
|
|
142
|
+
return !!navigator.userAgent.match('Gecko/...');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function isWebKit() {
|
|
146
|
+
return !!navigator.userAgent.match('AppleWebKit/...') &&
|
|
147
|
+
!navigator.userAgent.match('Chrome/...');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function isBlink() {
|
|
151
|
+
return !!navigator.userAgent.match('Chrome/...');
|
|
152
|
+
}
|
package/core/util/cursor.js
CHANGED
|
@@ -18,6 +18,10 @@ export default class Cursor {
|
|
|
18
18
|
this._canvas.style.position = 'fixed';
|
|
19
19
|
this._canvas.style.zIndex = '65535';
|
|
20
20
|
this._canvas.style.pointerEvents = 'none';
|
|
21
|
+
// Safari on iOS can select the cursor image
|
|
22
|
+
// https://bugs.webkit.org/show_bug.cgi?id=249223
|
|
23
|
+
this._canvas.style.userSelect = 'none';
|
|
24
|
+
this._canvas.style.WebkitUserSelect = 'none';
|
|
21
25
|
// Can't use "display" because of Firefox bug #1445997
|
|
22
26
|
this._canvas.style.visibility = 'hidden';
|
|
23
27
|
}
|