@novnc/novnc 1.3.0-beta → 1.3.0-g1075cd8

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.
Files changed (43) hide show
  1. package/README.md +13 -3
  2. package/core/decoders/jpeg.js +141 -0
  3. package/core/decoders/raw.js +1 -1
  4. package/core/decoders/zrle.js +185 -0
  5. package/core/encodings.js +4 -0
  6. package/core/ra2.js +567 -0
  7. package/core/rfb.js +219 -8
  8. package/core/util/md5.js +79 -0
  9. package/docs/API.md +44 -4
  10. package/lib/base64.js +1 -1
  11. package/lib/decoders/copyrect.js +1 -1
  12. package/lib/decoders/hextile.js +2 -2
  13. package/lib/decoders/jpeg.js +188 -0
  14. package/lib/decoders/raw.js +2 -2
  15. package/lib/decoders/rre.js +1 -1
  16. package/lib/decoders/tight.js +2 -2
  17. package/lib/decoders/tightpng.js +3 -3
  18. package/lib/decoders/zrle.js +234 -0
  19. package/lib/deflator.js +1 -1
  20. package/lib/des.js +1 -1
  21. package/lib/display.js +2 -2
  22. package/lib/encodings.js +8 -0
  23. package/lib/inflator.js +1 -1
  24. package/lib/input/gesturehandler.js +1 -1
  25. package/lib/input/keyboard.js +2 -2
  26. package/lib/input/util.js +2 -2
  27. package/lib/ra2.js +1257 -0
  28. package/lib/rfb.js +373 -27
  29. package/lib/util/browser.js +10 -6
  30. package/lib/util/cursor.js +1 -1
  31. package/lib/util/events.js +2 -2
  32. package/lib/util/eventtarget.js +1 -1
  33. package/lib/util/int.js +1 -1
  34. package/lib/util/logging.js +2 -2
  35. package/lib/util/md5.js +103 -0
  36. package/lib/vendor/pako/lib/utils/common.js +2 -2
  37. package/lib/vendor/pako/lib/zlib/deflate.js +6 -5
  38. package/lib/vendor/pako/lib/zlib/inffast.js +6 -2
  39. package/lib/vendor/pako/lib/zlib/inflate.js +41 -18
  40. package/lib/vendor/pako/lib/zlib/inftrees.js +1 -1
  41. package/lib/vendor/pako/lib/zlib/trees.js +3 -3
  42. package/lib/websock.js +2 -2
  43. package/package.json +2 -7
package/core/rfb.js CHANGED
@@ -25,6 +25,8 @@ import DES from "./des.js";
25
25
  import KeyTable from "./input/keysym.js";
26
26
  import XtScancode from "./input/xtscancodes.js";
27
27
  import { encodings } from "./encodings.js";
28
+ import RSAAESAuthenticationState from "./ra2.js";
29
+ import { MD5 } from "./util/md5.js";
28
30
 
29
31
  import RawDecoder from "./decoders/raw.js";
30
32
  import CopyRectDecoder from "./decoders/copyrect.js";
@@ -32,6 +34,8 @@ import RREDecoder from "./decoders/rre.js";
32
34
  import HextileDecoder from "./decoders/hextile.js";
33
35
  import TightDecoder from "./decoders/tight.js";
34
36
  import TightPNGDecoder from "./decoders/tightpng.js";
37
+ import ZRLEDecoder from "./decoders/zrle.js";
38
+ import JPEGDecoder from "./decoders/jpeg.js";
35
39
 
36
40
  // How many seconds to wait for a disconnect to finish
37
41
  const DISCONNECT_TIMEOUT = 3;
@@ -98,6 +102,7 @@ export default class RFB extends EventTargetMixin {
98
102
  this._rfbInitState = '';
99
103
  this._rfbAuthScheme = -1;
100
104
  this._rfbCleanDisconnect = true;
105
+ this._rfbRSAAESAuthenticationState = null;
101
106
 
102
107
  // Server capabilities
103
108
  this._rfbVersion = 0;
@@ -176,6 +181,8 @@ export default class RFB extends EventTargetMixin {
176
181
  handleMouse: this._handleMouse.bind(this),
177
182
  handleWheel: this._handleWheel.bind(this),
178
183
  handleGesture: this._handleGesture.bind(this),
184
+ handleRSAAESCredentialsRequired: this._handleRSAAESCredentialsRequired.bind(this),
185
+ handleRSAAESServerVerification: this._handleRSAAESServerVerification.bind(this),
179
186
  };
180
187
 
181
188
  // main setup
@@ -218,6 +225,8 @@ export default class RFB extends EventTargetMixin {
218
225
  this._decoders[encodings.encodingHextile] = new HextileDecoder();
219
226
  this._decoders[encodings.encodingTight] = new TightDecoder();
220
227
  this._decoders[encodings.encodingTightPNG] = new TightPNGDecoder();
228
+ this._decoders[encodings.encodingZRLE] = new ZRLEDecoder();
229
+ this._decoders[encodings.encodingJPEG] = new JPEGDecoder();
221
230
 
222
231
  // NB: nothing that needs explicit teardown should be done
223
232
  // before this point, since this can throw an exception
@@ -240,6 +249,8 @@ export default class RFB extends EventTargetMixin {
240
249
  this._sock.on('message', this._handleMessage.bind(this));
241
250
  this._sock.on('error', this._socketError.bind(this));
242
251
 
252
+ this._expectedClientWidth = null;
253
+ this._expectedClientHeight = null;
243
254
  this._resizeObserver = new ResizeObserver(this._eventHandlers.handleResize);
244
255
 
245
256
  // All prepared, kick off the connection
@@ -372,6 +383,15 @@ export default class RFB extends EventTargetMixin {
372
383
  this._sock.off('error');
373
384
  this._sock.off('message');
374
385
  this._sock.off('open');
386
+ if (this._rfbRSAAESAuthenticationState !== null) {
387
+ this._rfbRSAAESAuthenticationState.disconnect();
388
+ }
389
+ }
390
+
391
+ approveServer() {
392
+ if (this._rfbRSAAESAuthenticationState !== null) {
393
+ this._rfbRSAAESAuthenticationState.approveServer();
394
+ }
375
395
  }
376
396
 
377
397
  sendCredentials(creds) {
@@ -432,8 +452,8 @@ export default class RFB extends EventTargetMixin {
432
452
  }
433
453
  }
434
454
 
435
- focus() {
436
- this._canvas.focus();
455
+ focus(options) {
456
+ this._canvas.focus(options);
437
457
  }
438
458
 
439
459
  blur() {
@@ -609,7 +629,7 @@ export default class RFB extends EventTargetMixin {
609
629
  return;
610
630
  }
611
631
 
612
- this.focus();
632
+ this.focus({ preventScroll: true });
613
633
  }
614
634
 
615
635
  _setDesktopName(name) {
@@ -619,7 +639,26 @@ export default class RFB extends EventTargetMixin {
619
639
  { detail: { name: this._fbName } }));
620
640
  }
621
641
 
642
+ _saveExpectedClientSize() {
643
+ this._expectedClientWidth = this._screen.clientWidth;
644
+ this._expectedClientHeight = this._screen.clientHeight;
645
+ }
646
+
647
+ _currentClientSize() {
648
+ return [this._screen.clientWidth, this._screen.clientHeight];
649
+ }
650
+
651
+ _clientHasExpectedSize() {
652
+ const [currentWidth, currentHeight] = this._currentClientSize();
653
+ return currentWidth == this._expectedClientWidth &&
654
+ currentHeight == this._expectedClientHeight;
655
+ }
656
+
622
657
  _handleResize() {
658
+ // Don't change anything if the client size is already as expected
659
+ if (this._clientHasExpectedSize()) {
660
+ return;
661
+ }
623
662
  // If the window resized then our screen element might have
624
663
  // as well. Update the viewport dimensions.
625
664
  window.requestAnimationFrame(() => {
@@ -660,6 +699,12 @@ export default class RFB extends EventTargetMixin {
660
699
  this._display.viewportChangeSize(size.w, size.h);
661
700
  this._fixScrollbars();
662
701
  }
702
+
703
+ // When changing clipping we might show or hide scrollbars.
704
+ // This causes the expected client dimensions to change.
705
+ if (curClip !== newClip) {
706
+ this._saveExpectedClientSize();
707
+ }
663
708
  }
664
709
 
665
710
  _updateScale() {
@@ -684,6 +729,7 @@ export default class RFB extends EventTargetMixin {
684
729
  }
685
730
 
686
731
  const size = this._screenSize();
732
+
687
733
  RFB.messages.setDesktopSize(this._sock,
688
734
  Math.floor(size.w), Math.floor(size.h),
689
735
  this._screenID, this._screenFlags);
@@ -699,12 +745,13 @@ export default class RFB extends EventTargetMixin {
699
745
  }
700
746
 
701
747
  _fixScrollbars() {
702
- // This is a hack because Chrome screws up the calculation
703
- // for when scrollbars are needed. So to fix it we temporarily
704
- // toggle them off and on.
748
+ // This is a hack because Safari on macOS screws up the calculation
749
+ // for when scrollbars are needed. We get scrollbars when making the
750
+ // browser smaller, despite remote resize being enabled. So to fix it
751
+ // we temporarily toggle them off and on.
705
752
  const orig = this._screen.style.overflow;
706
753
  this._screen.style.overflow = 'hidden';
707
- // Force Chrome to recalculate the layout by asking for
754
+ // Force Safari to recalculate the layout by asking for
708
755
  // an element's dimensions
709
756
  this._screen.getBoundingClientRect();
710
757
  this._screen.style.overflow = orig;
@@ -1242,13 +1289,13 @@ export default class RFB extends EventTargetMixin {
1242
1289
  break;
1243
1290
  case "003.003":
1244
1291
  case "003.006": // UltraVNC
1245
- case "003.889": // Apple Remote Desktop
1246
1292
  this._rfbVersion = 3.3;
1247
1293
  break;
1248
1294
  case "003.007":
1249
1295
  this._rfbVersion = 3.7;
1250
1296
  break;
1251
1297
  case "003.008":
1298
+ case "003.889": // Apple Remote Desktop
1252
1299
  case "004.000": // Intel AMT KVM
1253
1300
  case "004.001": // RealVNC 4.6
1254
1301
  case "005.000": // RealVNC 5.3
@@ -1302,8 +1349,12 @@ export default class RFB extends EventTargetMixin {
1302
1349
  this._rfbAuthScheme = 22; // XVP
1303
1350
  } else if (types.includes(16)) {
1304
1351
  this._rfbAuthScheme = 16; // Tight
1352
+ } else if (types.includes(6)) {
1353
+ this._rfbAuthScheme = 6; // RA2ne Auth
1305
1354
  } else if (types.includes(2)) {
1306
1355
  this._rfbAuthScheme = 2; // VNC Auth
1356
+ } else if (types.includes(30)) {
1357
+ this._rfbAuthScheme = 30; // ARD Auth
1307
1358
  } else if (types.includes(19)) {
1308
1359
  this._rfbAuthScheme = 19; // VeNCrypt Auth
1309
1360
  } else {
@@ -1496,6 +1547,117 @@ export default class RFB extends EventTargetMixin {
1496
1547
  return true;
1497
1548
  }
1498
1549
 
1550
+ _negotiateARDAuth() {
1551
+
1552
+ if (this._rfbCredentials.username === undefined ||
1553
+ this._rfbCredentials.password === undefined) {
1554
+ this.dispatchEvent(new CustomEvent(
1555
+ "credentialsrequired",
1556
+ { detail: { types: ["username", "password"] } }));
1557
+ return false;
1558
+ }
1559
+
1560
+ if (this._rfbCredentials.ardPublicKey != undefined &&
1561
+ this._rfbCredentials.ardCredentials != undefined) {
1562
+ // if the async web crypto is done return the results
1563
+ this._sock.send(this._rfbCredentials.ardCredentials);
1564
+ this._sock.send(this._rfbCredentials.ardPublicKey);
1565
+ this._rfbCredentials.ardCredentials = null;
1566
+ this._rfbCredentials.ardPublicKey = null;
1567
+ this._rfbInitState = "SecurityResult";
1568
+ return true;
1569
+ }
1570
+
1571
+ if (this._sock.rQwait("read ard", 4)) { return false; }
1572
+
1573
+ let generator = this._sock.rQshiftBytes(2); // DH base generator value
1574
+
1575
+ let keyLength = this._sock.rQshift16();
1576
+
1577
+ if (this._sock.rQwait("read ard keylength", keyLength*2, 4)) { return false; }
1578
+
1579
+ // read the server values
1580
+ let prime = this._sock.rQshiftBytes(keyLength); // predetermined prime modulus
1581
+ let serverPublicKey = this._sock.rQshiftBytes(keyLength); // other party's public key
1582
+
1583
+ let clientPrivateKey = window.crypto.getRandomValues(new Uint8Array(keyLength));
1584
+ let padding = Array.from(window.crypto.getRandomValues(new Uint8Array(64)), byte => String.fromCharCode(65+byte%26)).join('');
1585
+
1586
+ this._negotiateARDAuthAsync(generator, keyLength, prime, serverPublicKey, clientPrivateKey, padding);
1587
+
1588
+ return false;
1589
+ }
1590
+
1591
+ _modPow(base, exponent, modulus) {
1592
+
1593
+ let baseHex = "0x"+Array.from(base, byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join('');
1594
+ let exponentHex = "0x"+Array.from(exponent, byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join('');
1595
+ let modulusHex = "0x"+Array.from(modulus, byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join('');
1596
+
1597
+ let b = BigInt(baseHex);
1598
+ let e = BigInt(exponentHex);
1599
+ let m = BigInt(modulusHex);
1600
+ let r = 1n;
1601
+ b = b % m;
1602
+ while (e > 0) {
1603
+ if (e % 2n === 1n) {
1604
+ r = (r * b) % m;
1605
+ }
1606
+ e = e / 2n;
1607
+ b = (b * b) % m;
1608
+ }
1609
+ let hexResult = r.toString(16);
1610
+
1611
+ while (hexResult.length/2<exponent.length || (hexResult.length%2 != 0)) {
1612
+ hexResult = "0"+hexResult;
1613
+ }
1614
+
1615
+ let bytesResult = [];
1616
+ for (let c = 0; c < hexResult.length; c += 2) {
1617
+ bytesResult.push(parseInt(hexResult.substr(c, 2), 16));
1618
+ }
1619
+ return bytesResult;
1620
+ }
1621
+
1622
+ async _aesEcbEncrypt(string, key) {
1623
+ // perform AES-ECB blocks
1624
+ let keyString = Array.from(key, byte => String.fromCharCode(byte)).join('');
1625
+ let aesKey = await window.crypto.subtle.importKey("raw", MD5(keyString), {name: "AES-CBC"}, false, ["encrypt"]);
1626
+ let data = new Uint8Array(string.length);
1627
+ for (let i = 0; i < string.length; ++i) {
1628
+ data[i] = string.charCodeAt(i);
1629
+ }
1630
+ let encrypted = new Uint8Array(data.length);
1631
+ for (let i=0;i<data.length;i+=16) {
1632
+ let block = data.slice(i, i+16);
1633
+ let encryptedBlock = await window.crypto.subtle.encrypt({name: "AES-CBC", iv: block},
1634
+ aesKey, new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
1635
+ );
1636
+ encrypted.set((new Uint8Array(encryptedBlock)).slice(0, 16), i);
1637
+ }
1638
+ return encrypted;
1639
+ }
1640
+
1641
+ async _negotiateARDAuthAsync(generator, keyLength, prime, serverPublicKey, clientPrivateKey, padding) {
1642
+ // calculate the DH keys
1643
+ let clientPublicKey = this._modPow(generator, clientPrivateKey, prime);
1644
+ let sharedKey = this._modPow(serverPublicKey, clientPrivateKey, prime);
1645
+
1646
+ let username = encodeUTF8(this._rfbCredentials.username).substring(0, 63);
1647
+ let password = encodeUTF8(this._rfbCredentials.password).substring(0, 63);
1648
+
1649
+ let paddedUsername = username + '\0' + padding.substring(0, 63);
1650
+ let paddedPassword = password + '\0' + padding.substring(0, 63);
1651
+ let credentials = paddedUsername.substring(0, 64) + paddedPassword.substring(0, 64);
1652
+
1653
+ let encrypted = await this._aesEcbEncrypt(credentials, sharedKey);
1654
+
1655
+ this._rfbCredentials.ardCredentials = encrypted;
1656
+ this._rfbCredentials.ardPublicKey = clientPublicKey;
1657
+
1658
+ setTimeout(this._initMsg.bind(this), 0);
1659
+ }
1660
+
1499
1661
  _negotiateTightUnixAuth() {
1500
1662
  if (this._rfbCredentials.username === undefined ||
1501
1663
  this._rfbCredentials.password === undefined) {
@@ -1619,6 +1781,44 @@ export default class RFB extends EventTargetMixin {
1619
1781
  return this._fail("No supported sub-auth types!");
1620
1782
  }
1621
1783
 
1784
+ _handleRSAAESCredentialsRequired(event) {
1785
+ this.dispatchEvent(event);
1786
+ }
1787
+
1788
+ _handleRSAAESServerVerification(event) {
1789
+ this.dispatchEvent(event);
1790
+ }
1791
+
1792
+ _negotiateRA2neAuth() {
1793
+ if (this._rfbRSAAESAuthenticationState === null) {
1794
+ this._rfbRSAAESAuthenticationState = new RSAAESAuthenticationState(this._sock, () => this._rfbCredentials);
1795
+ this._rfbRSAAESAuthenticationState.addEventListener(
1796
+ "serververification", this._eventHandlers.handleRSAAESServerVerification);
1797
+ this._rfbRSAAESAuthenticationState.addEventListener(
1798
+ "credentialsrequired", this._eventHandlers.handleRSAAESCredentialsRequired);
1799
+ }
1800
+ this._rfbRSAAESAuthenticationState.checkInternalEvents();
1801
+ if (!this._rfbRSAAESAuthenticationState.hasStarted) {
1802
+ this._rfbRSAAESAuthenticationState.negotiateRA2neAuthAsync()
1803
+ .catch((e) => {
1804
+ if (e.message !== "disconnect normally") {
1805
+ this._fail(e.message);
1806
+ }
1807
+ }).then(() => {
1808
+ this.dispatchEvent(new CustomEvent('securityresult'));
1809
+ this._rfbInitState = "SecurityResult";
1810
+ this._initMsg();
1811
+ }).finally(() => {
1812
+ this._rfbRSAAESAuthenticationState.removeEventListener(
1813
+ "serververification", this._eventHandlers.handleRSAAESServerVerification);
1814
+ this._rfbRSAAESAuthenticationState.removeEventListener(
1815
+ "credentialsrequired", this._eventHandlers.handleRSAAESCredentialsRequired);
1816
+ this._rfbRSAAESAuthenticationState = null;
1817
+ });
1818
+ }
1819
+ return false;
1820
+ }
1821
+
1622
1822
  _negotiateAuthentication() {
1623
1823
  switch (this._rfbAuthScheme) {
1624
1824
  case 1: // no auth
@@ -1632,6 +1832,9 @@ export default class RFB extends EventTargetMixin {
1632
1832
  case 22: // XVP auth
1633
1833
  return this._negotiateXvpAuth();
1634
1834
 
1835
+ case 30: // ARD auth
1836
+ return this._negotiateARDAuth();
1837
+
1635
1838
  case 2: // VNC authentication
1636
1839
  return this._negotiateStdVNCAuth();
1637
1840
 
@@ -1644,6 +1847,9 @@ export default class RFB extends EventTargetMixin {
1644
1847
  case 129: // TightVNC UNIX Security Type
1645
1848
  return this._negotiateTightUnixAuth();
1646
1849
 
1850
+ case 6: // RA2ne Security Type
1851
+ return this._negotiateRA2neAuth();
1852
+
1647
1853
  default:
1648
1854
  return this._fail("Unsupported auth scheme (scheme: " +
1649
1855
  this._rfbAuthScheme + ")");
@@ -1772,6 +1978,8 @@ export default class RFB extends EventTargetMixin {
1772
1978
  if (this._fbDepth == 24) {
1773
1979
  encs.push(encodings.encodingTight);
1774
1980
  encs.push(encodings.encodingTightPNG);
1981
+ encs.push(encodings.encodingZRLE);
1982
+ encs.push(encodings.encodingJPEG);
1775
1983
  encs.push(encodings.encodingHextile);
1776
1984
  encs.push(encodings.encodingRRE);
1777
1985
  }
@@ -2500,6 +2708,9 @@ export default class RFB extends EventTargetMixin {
2500
2708
  this._updateScale();
2501
2709
 
2502
2710
  this._updateContinuousUpdates();
2711
+
2712
+ // Keep this size until browser client size changes
2713
+ this._saveExpectedClientSize();
2503
2714
  }
2504
2715
 
2505
2716
  _xvpOp(ver, op) {
@@ -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/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`](#disconnected)
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()`](#rfbsendKey)
134
+ [`RFB.sendKey()`](#rfbsendkey)
126
135
  - Send a key event.
127
136
 
128
137
  [`RFB.sendCtrlAltDel()`](#rfbsendctrlaltdel)
@@ -143,7 +152,7 @@ protocol stream.
143
152
  [`RFB.machineReset()`](#rfbmachinereset)
144
153
  - Request a reset of the remote machine.
145
154
 
146
- [`RFB.clipboardPasteFrom()`](#rfbclipboardPasteFrom)
155
+ [`RFB.clipboardPasteFrom()`](#rfbclipboardpastefrom)
147
156
  - Send clipboard contents to server.
148
157
 
149
158
  ### Details
@@ -212,6 +221,20 @@ property `clean`. `clean` is a `boolean` indicating if the termination
212
221
  was clean or not. In the event of an unexpected termination or an error
213
222
  `clean` will be set to false.
214
223
 
224
+ #### serververification
225
+
226
+ The `serververification` event is fired when the server provides
227
+ information that allows the user to verify that it is the correct server
228
+ and protect against a man-in-the-middle attack. The `detail` property is
229
+ an `Object` containing the property `type` which is a `DOMString`
230
+ specifying which type of information the server has provided. Other
231
+ properties are also available, depending on the value of `type`:
232
+
233
+ `"RSA"`
234
+ - The server identity is verified using just a RSA key. The property
235
+ `publickey` is a `Uint8Array` containing the public key in a unsigned
236
+ big endian representation.
237
+
215
238
  #### credentialsrequired
216
239
 
217
240
  The `credentialsrequired` event is fired when the server requests more
@@ -271,6 +294,16 @@ connected server.
271
294
 
272
295
  RFB.disconnect( );
273
296
 
297
+ #### RFB.approveServer()
298
+
299
+ The `RFB.approveServer()` method is used to signal that the user has
300
+ verified the server identity provided in a `serververification` event
301
+ and that the connection can continue.
302
+
303
+ ##### Syntax
304
+
305
+ RFB.approveServer( );
306
+
274
307
  #### RFB.sendCredentials()
275
308
 
276
309
  The `RFB.sendCredentials()` method is used to provide the missing
@@ -328,7 +361,14 @@ Keyboard events will be sent to the remote server after this point.
328
361
 
329
362
  ##### Syntax
330
363
 
331
- RFB.focus( );
364
+ RFB.focus( [options] );
365
+
366
+ ###### Parameters
367
+
368
+ **`options`** *Optional*
369
+ - A `object` providing options to control how the focus will be
370
+ performed. Please see [`HTMLElement.focus()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus)
371
+ for available options.
332
372
 
333
373
  #### RFB.blur()
334
374
 
package/lib/base64.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
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); }
4
4
 
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
@@ -9,7 +9,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
9
9
 
10
10
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
11
11
 
12
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
12
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
13
13
 
14
14
  /*
15
15
  * noVNC: HTML5 VNC client
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
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); }
4
4
 
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
@@ -17,7 +17,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
17
17
 
18
18
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
19
19
 
20
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
20
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
21
21
 
22
22
  var HextileDecoder = /*#__PURE__*/function () {
23
23
  function HextileDecoder() {