@novnc/novnc 1.3.0-g1075cd8 → 1.3.0-g138df46

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 (52) hide show
  1. package/core/display.js +12 -0
  2. package/core/input/keyboard.js +10 -0
  3. package/core/rfb.js +182 -84
  4. package/docs/API.md +61 -0
  5. package/lib/base64.js +19 -33
  6. package/lib/decoders/copyrect.js +0 -10
  7. package/lib/decoders/hextile.js +12 -44
  8. package/lib/decoders/jpeg.js +0 -42
  9. package/lib/decoders/raw.js +4 -20
  10. package/lib/decoders/rre.js +0 -14
  11. package/lib/decoders/tight.js +8 -76
  12. package/lib/decoders/tightpng.js +2 -24
  13. package/lib/decoders/zrle.js +2 -51
  14. package/lib/deflator.js +4 -21
  15. package/lib/des.js +19 -35
  16. package/lib/display.js +57 -105
  17. package/lib/encodings.js +1 -10
  18. package/lib/inflator.js +1 -17
  19. package/lib/input/domkeytable.js +77 -48
  20. package/lib/input/fixedkeys.js +8 -3
  21. package/lib/input/gesturehandler.js +81 -151
  22. package/lib/input/keyboard.js +57 -88
  23. package/lib/input/keysym.js +14 -270
  24. package/lib/input/keysymdef.js +5 -7
  25. package/lib/input/util.js +42 -84
  26. package/lib/input/vkeys.js +0 -3
  27. package/lib/input/xtscancodes.js +1 -168
  28. package/lib/ra2.js +37 -261
  29. package/lib/rfb.js +453 -1005
  30. package/lib/util/browser.js +16 -25
  31. package/lib/util/cursor.js +20 -64
  32. package/lib/util/element.js +3 -5
  33. package/lib/util/events.js +23 -30
  34. package/lib/util/eventtarget.js +0 -12
  35. package/lib/util/int.js +1 -2
  36. package/lib/util/logging.js +1 -19
  37. package/lib/util/md5.js +7 -27
  38. package/lib/util/strings.js +3 -5
  39. package/lib/vendor/pako/lib/utils/common.js +8 -17
  40. package/lib/vendor/pako/lib/zlib/adler32.js +3 -7
  41. package/lib/vendor/pako/lib/zlib/constants.js +2 -5
  42. package/lib/vendor/pako/lib/zlib/crc32.js +5 -12
  43. package/lib/vendor/pako/lib/zlib/deflate.js +212 -617
  44. package/lib/vendor/pako/lib/zlib/gzheader.js +1 -13
  45. package/lib/vendor/pako/lib/zlib/inffast.js +60 -176
  46. package/lib/vendor/pako/lib/zlib/inflate.js +397 -887
  47. package/lib/vendor/pako/lib/zlib/inftrees.js +62 -168
  48. package/lib/vendor/pako/lib/zlib/messages.js +1 -11
  49. package/lib/vendor/pako/lib/zlib/trees.js +245 -587
  50. package/lib/vendor/pako/lib/zlib/zstream.js +2 -18
  51. package/lib/websock.js +31 -84
  52. package/package.json +1 -1
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) {
@@ -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
@@ -54,6 +54,21 @@ const GESTURE_SCRLSENS = 50;
54
54
  const DOUBLE_TAP_TIMEOUT = 1000;
55
55
  const DOUBLE_TAP_THRESHOLD = 50;
56
56
 
57
+ // Security types
58
+ const securityTypeNone = 1;
59
+ const securityTypeVNCAuth = 2;
60
+ const securityTypeRA2ne = 6;
61
+ const securityTypeTight = 16;
62
+ const securityTypeVeNCrypt = 19;
63
+ const securityTypeXVP = 22;
64
+ const securityTypeARD = 30;
65
+
66
+ // Special Tight security types
67
+ const securityTypeUnixLogon = 129;
68
+
69
+ // VeNCrypt security types
70
+ const securityTypePlain = 256;
71
+
57
72
  // Extended clipboard pseudo-encoding formats
58
73
  const extendedClipboardFormatText = 1;
59
74
  /*eslint-disable no-unused-vars */
@@ -79,6 +94,12 @@ export default class RFB extends EventTargetMixin {
79
94
  throw new Error("Must specify URL, WebSocket or RTCDataChannel");
80
95
  }
81
96
 
97
+ // We rely on modern APIs which might not be available in an
98
+ // insecure context
99
+ if (!window.isSecureContext) {
100
+ Log.Error("noVNC requires a secure context (TLS). Expect crashes!");
101
+ }
102
+
82
103
  super();
83
104
 
84
105
  this._target = target;
@@ -396,7 +417,7 @@ export default class RFB extends EventTargetMixin {
396
417
 
397
418
  sendCredentials(creds) {
398
419
  this._rfbCredentials = creds;
399
- setTimeout(this._initMsg.bind(this), 0);
420
+ this._resumeAuthentication();
400
421
  }
401
422
 
402
423
  sendCtrlAltDel() {
@@ -469,16 +490,45 @@ export default class RFB extends EventTargetMixin {
469
490
  this._clipboardText = text;
470
491
  RFB.messages.extendedClipboardNotify(this._sock, [extendedClipboardFormatText]);
471
492
  } else {
472
- let data = new Uint8Array(text.length);
473
- for (let i = 0; i < text.length; i++) {
474
- // FIXME: text can have values outside of Latin1/Uint8
475
- data[i] = text.charCodeAt(i);
493
+ let length, i;
494
+ let data;
495
+
496
+ length = 0;
497
+ // eslint-disable-next-line no-unused-vars
498
+ for (let codePoint of text) {
499
+ length++;
500
+ }
501
+
502
+ data = new Uint8Array(length);
503
+
504
+ i = 0;
505
+ for (let codePoint of text) {
506
+ let code = codePoint.codePointAt(0);
507
+
508
+ /* Only ISO 8859-1 is supported */
509
+ if (code > 0xff) {
510
+ code = 0x3f; // '?'
511
+ }
512
+
513
+ data[i++] = code;
476
514
  }
477
515
 
478
516
  RFB.messages.clientCutText(this._sock, data);
479
517
  }
480
518
  }
481
519
 
520
+ getImageData() {
521
+ return this._display.getImageData();
522
+ }
523
+
524
+ toDataURL(type, encoderOptions) {
525
+ return this._display.toDataURL(type, encoderOptions);
526
+ }
527
+
528
+ toBlob(callback, type, quality) {
529
+ return this._display.toBlob(callback, type, quality);
530
+ }
531
+
482
532
  // ===== PRIVATE METHODS =====
483
533
 
484
534
  _connect() {
@@ -916,8 +966,15 @@ export default class RFB extends EventTargetMixin {
916
966
  }
917
967
  }
918
968
  break;
969
+ case 'connecting':
970
+ while (this._rfbConnectionState === 'connecting') {
971
+ if (!this._initMsg()) {
972
+ break;
973
+ }
974
+ }
975
+ break;
919
976
  default:
920
- this._initMsg();
977
+ Log.Error("Got data while in an invalid state");
921
978
  break;
922
979
  }
923
980
  }
@@ -1326,6 +1383,21 @@ export default class RFB extends EventTargetMixin {
1326
1383
  this._rfbInitState = 'Security';
1327
1384
  }
1328
1385
 
1386
+ _isSupportedSecurityType(type) {
1387
+ const clientTypes = [
1388
+ securityTypeNone,
1389
+ securityTypeVNCAuth,
1390
+ securityTypeRA2ne,
1391
+ securityTypeTight,
1392
+ securityTypeVeNCrypt,
1393
+ securityTypeXVP,
1394
+ securityTypeARD,
1395
+ securityTypePlain,
1396
+ ];
1397
+
1398
+ return clientTypes.includes(type);
1399
+ }
1400
+
1329
1401
  _negotiateSecurity() {
1330
1402
  if (this._rfbVersion >= 3.7) {
1331
1403
  // Server sends supported list, client decides
@@ -1336,28 +1408,23 @@ export default class RFB extends EventTargetMixin {
1336
1408
  this._rfbInitState = "SecurityReason";
1337
1409
  this._securityContext = "no security types";
1338
1410
  this._securityStatus = 1;
1339
- return this._initMsg();
1411
+ return true;
1340
1412
  }
1341
1413
 
1342
1414
  const types = this._sock.rQshiftBytes(numTypes);
1343
1415
  Log.Debug("Server security types: " + types);
1344
1416
 
1345
- // Look for each auth in preferred order
1346
- if (types.includes(1)) {
1347
- this._rfbAuthScheme = 1; // None
1348
- } else if (types.includes(22)) {
1349
- this._rfbAuthScheme = 22; // XVP
1350
- } else if (types.includes(16)) {
1351
- this._rfbAuthScheme = 16; // Tight
1352
- } else if (types.includes(6)) {
1353
- this._rfbAuthScheme = 6; // RA2ne Auth
1354
- } else if (types.includes(2)) {
1355
- this._rfbAuthScheme = 2; // VNC Auth
1356
- } else if (types.includes(30)) {
1357
- this._rfbAuthScheme = 30; // ARD Auth
1358
- } else if (types.includes(19)) {
1359
- this._rfbAuthScheme = 19; // VeNCrypt Auth
1360
- } else {
1417
+ // Look for a matching security type in the order that the
1418
+ // server prefers
1419
+ this._rfbAuthScheme = -1;
1420
+ for (let type of types) {
1421
+ if (this._isSupportedSecurityType(type)) {
1422
+ this._rfbAuthScheme = type;
1423
+ break;
1424
+ }
1425
+ }
1426
+
1427
+ if (this._rfbAuthScheme === -1) {
1361
1428
  return this._fail("Unsupported security types (types: " + types + ")");
1362
1429
  }
1363
1430
 
@@ -1371,14 +1438,14 @@ export default class RFB extends EventTargetMixin {
1371
1438
  this._rfbInitState = "SecurityReason";
1372
1439
  this._securityContext = "authentication scheme";
1373
1440
  this._securityStatus = 1;
1374
- return this._initMsg();
1441
+ return true;
1375
1442
  }
1376
1443
  }
1377
1444
 
1378
1445
  this._rfbInitState = 'Authentication';
1379
1446
  Log.Debug('Authenticating using scheme: ' + this._rfbAuthScheme);
1380
1447
 
1381
- return this._initMsg(); // jump to authentication
1448
+ return true;
1382
1449
  }
1383
1450
 
1384
1451
  _handleSecurityReason() {
@@ -1428,7 +1495,7 @@ export default class RFB extends EventTargetMixin {
1428
1495
  this._rfbCredentials.username +
1429
1496
  this._rfbCredentials.target;
1430
1497
  this._sock.sendString(xvpAuthStr);
1431
- this._rfbAuthScheme = 2;
1498
+ this._rfbAuthScheme = securityTypeVNCAuth;
1432
1499
  return this._negotiateAuthentication();
1433
1500
  }
1434
1501
 
@@ -1486,49 +1553,66 @@ export default class RFB extends EventTargetMixin {
1486
1553
  subtypes.push(this._sock.rQshift32());
1487
1554
  }
1488
1555
 
1489
- // 256 = Plain subtype
1490
- if (subtypes.indexOf(256) != -1) {
1491
- // 0x100 = 256
1492
- this._sock.send([0, 0, 1, 0]);
1493
- this._rfbVeNCryptState = 4;
1494
- } else {
1495
- return this._fail("VeNCrypt Plain subtype not offered by server");
1556
+ // Look for a matching security type in the order that the
1557
+ // server prefers
1558
+ this._rfbAuthScheme = -1;
1559
+ for (let type of subtypes) {
1560
+ // Avoid getting in to a loop
1561
+ if (type === securityTypeVeNCrypt) {
1562
+ continue;
1563
+ }
1564
+
1565
+ if (this._isSupportedSecurityType(type)) {
1566
+ this._rfbAuthScheme = type;
1567
+ break;
1568
+ }
1496
1569
  }
1497
- }
1498
1570
 
1499
- // negotiated Plain subtype, server waits for password
1500
- if (this._rfbVeNCryptState == 4) {
1501
- if (this._rfbCredentials.username === undefined ||
1502
- this._rfbCredentials.password === undefined) {
1503
- this.dispatchEvent(new CustomEvent(
1504
- "credentialsrequired",
1505
- { detail: { types: ["username", "password"] } }));
1506
- return false;
1571
+ if (this._rfbAuthScheme === -1) {
1572
+ return this._fail("Unsupported security types (types: " + subtypes + ")");
1507
1573
  }
1508
1574
 
1509
- const user = encodeUTF8(this._rfbCredentials.username);
1510
- const pass = encodeUTF8(this._rfbCredentials.password);
1511
-
1512
- this._sock.send([
1513
- (user.length >> 24) & 0xFF,
1514
- (user.length >> 16) & 0xFF,
1515
- (user.length >> 8) & 0xFF,
1516
- user.length & 0xFF
1517
- ]);
1518
- this._sock.send([
1519
- (pass.length >> 24) & 0xFF,
1520
- (pass.length >> 16) & 0xFF,
1521
- (pass.length >> 8) & 0xFF,
1522
- pass.length & 0xFF
1523
- ]);
1524
- this._sock.sendString(user);
1525
- this._sock.sendString(pass);
1575
+ this._sock.send([this._rfbAuthScheme >> 24,
1576
+ this._rfbAuthScheme >> 16,
1577
+ this._rfbAuthScheme >> 8,
1578
+ this._rfbAuthScheme]);
1526
1579
 
1527
- this._rfbInitState = "SecurityResult";
1580
+ this._rfbVeNCryptState == 4;
1528
1581
  return true;
1529
1582
  }
1530
1583
  }
1531
1584
 
1585
+ _negotiatePlainAuth() {
1586
+ if (this._rfbCredentials.username === undefined ||
1587
+ this._rfbCredentials.password === undefined) {
1588
+ this.dispatchEvent(new CustomEvent(
1589
+ "credentialsrequired",
1590
+ { detail: { types: ["username", "password"] } }));
1591
+ return false;
1592
+ }
1593
+
1594
+ const user = encodeUTF8(this._rfbCredentials.username);
1595
+ const pass = encodeUTF8(this._rfbCredentials.password);
1596
+
1597
+ this._sock.send([
1598
+ (user.length >> 24) & 0xFF,
1599
+ (user.length >> 16) & 0xFF,
1600
+ (user.length >> 8) & 0xFF,
1601
+ user.length & 0xFF
1602
+ ]);
1603
+ this._sock.send([
1604
+ (pass.length >> 24) & 0xFF,
1605
+ (pass.length >> 16) & 0xFF,
1606
+ (pass.length >> 8) & 0xFF,
1607
+ pass.length & 0xFF
1608
+ ]);
1609
+ this._sock.sendString(user);
1610
+ this._sock.sendString(pass);
1611
+
1612
+ this._rfbInitState = "SecurityResult";
1613
+ return true;
1614
+ }
1615
+
1532
1616
  _negotiateStdVNCAuth() {
1533
1617
  if (this._sock.rQwait("auth challenge", 16)) { return false; }
1534
1618
 
@@ -1655,7 +1739,7 @@ export default class RFB extends EventTargetMixin {
1655
1739
  this._rfbCredentials.ardCredentials = encrypted;
1656
1740
  this._rfbCredentials.ardPublicKey = clientPublicKey;
1657
1741
 
1658
- setTimeout(this._initMsg.bind(this), 0);
1742
+ this._resumeAuthentication();
1659
1743
  }
1660
1744
 
1661
1745
  _negotiateTightUnixAuth() {
@@ -1765,12 +1849,12 @@ export default class RFB extends EventTargetMixin {
1765
1849
  case 'STDVNOAUTH__': // no auth
1766
1850
  this._rfbInitState = 'SecurityResult';
1767
1851
  return true;
1768
- case 'STDVVNCAUTH_': // VNC auth
1769
- this._rfbAuthScheme = 2;
1770
- return this._initMsg();
1771
- case 'TGHTULGNAUTH': // UNIX auth
1772
- this._rfbAuthScheme = 129;
1773
- return this._initMsg();
1852
+ case 'STDVVNCAUTH_':
1853
+ this._rfbAuthScheme = securityTypeVNCAuth;
1854
+ return true;
1855
+ case 'TGHTULGNAUTH':
1856
+ this._rfbAuthScheme = securityTypeUnixLogon;
1857
+ return true;
1774
1858
  default:
1775
1859
  return this._fail("Unsupported tiny auth scheme " +
1776
1860
  "(scheme: " + authType + ")");
@@ -1807,7 +1891,7 @@ export default class RFB extends EventTargetMixin {
1807
1891
  }).then(() => {
1808
1892
  this.dispatchEvent(new CustomEvent('securityresult'));
1809
1893
  this._rfbInitState = "SecurityResult";
1810
- this._initMsg();
1894
+ return true;
1811
1895
  }).finally(() => {
1812
1896
  this._rfbRSAAESAuthenticationState.removeEventListener(
1813
1897
  "serververification", this._eventHandlers.handleRSAAESServerVerification);
@@ -1821,33 +1905,32 @@ export default class RFB extends EventTargetMixin {
1821
1905
 
1822
1906
  _negotiateAuthentication() {
1823
1907
  switch (this._rfbAuthScheme) {
1824
- case 1: // no auth
1825
- if (this._rfbVersion >= 3.8) {
1826
- this._rfbInitState = 'SecurityResult';
1827
- return true;
1828
- }
1829
- this._rfbInitState = 'ClientInitialisation';
1830
- return this._initMsg();
1908
+ case securityTypeNone:
1909
+ this._rfbInitState = 'SecurityResult';
1910
+ return true;
1831
1911
 
1832
- case 22: // XVP auth
1912
+ case securityTypeXVP:
1833
1913
  return this._negotiateXvpAuth();
1834
1914
 
1835
- case 30: // ARD auth
1915
+ case securityTypeARD:
1836
1916
  return this._negotiateARDAuth();
1837
1917
 
1838
- case 2: // VNC authentication
1918
+ case securityTypeVNCAuth:
1839
1919
  return this._negotiateStdVNCAuth();
1840
1920
 
1841
- case 16: // TightVNC Security Type
1921
+ case securityTypeTight:
1842
1922
  return this._negotiateTightAuth();
1843
1923
 
1844
- case 19: // VeNCrypt Security Type
1924
+ case securityTypeVeNCrypt:
1845
1925
  return this._negotiateVeNCryptAuth();
1846
1926
 
1847
- case 129: // TightVNC UNIX Security Type
1927
+ case securityTypePlain:
1928
+ return this._negotiatePlainAuth();
1929
+
1930
+ case securityTypeUnixLogon:
1848
1931
  return this._negotiateTightUnixAuth();
1849
1932
 
1850
- case 6: // RA2ne Security Type
1933
+ case securityTypeRA2ne:
1851
1934
  return this._negotiateRA2neAuth();
1852
1935
 
1853
1936
  default:
@@ -1857,6 +1940,13 @@ export default class RFB extends EventTargetMixin {
1857
1940
  }
1858
1941
 
1859
1942
  _handleSecurityResult() {
1943
+ // There is no security choice, and hence no security result
1944
+ // until RFB 3.7
1945
+ if (this._rfbVersion < 3.7) {
1946
+ this._rfbInitState = 'ClientInitialisation';
1947
+ return true;
1948
+ }
1949
+
1860
1950
  if (this._sock.rQwait('VNC auth response ', 4)) { return false; }
1861
1951
 
1862
1952
  const status = this._sock.rQshift32();
@@ -1864,13 +1954,13 @@ export default class RFB extends EventTargetMixin {
1864
1954
  if (status === 0) { // OK
1865
1955
  this._rfbInitState = 'ClientInitialisation';
1866
1956
  Log.Debug('Authentication OK');
1867
- return this._initMsg();
1957
+ return true;
1868
1958
  } else {
1869
1959
  if (this._rfbVersion >= 3.8) {
1870
1960
  this._rfbInitState = "SecurityReason";
1871
1961
  this._securityContext = "security result";
1872
1962
  this._securityStatus = status;
1873
- return this._initMsg();
1963
+ return true;
1874
1964
  } else {
1875
1965
  this.dispatchEvent(new CustomEvent(
1876
1966
  "securityfailure",
@@ -2046,6 +2136,14 @@ export default class RFB extends EventTargetMixin {
2046
2136
  }
2047
2137
  }
2048
2138
 
2139
+ // Resume authentication handshake after it was paused for some
2140
+ // reason, e.g. waiting for a password from the user
2141
+ _resumeAuthentication() {
2142
+ // We use setTimeout() so it's run in its own context, just like
2143
+ // it originally did via the WebSocket's event handler
2144
+ setTimeout(this._initMsg.bind(this), 0);
2145
+ }
2146
+
2049
2147
  _handleSetColourMapMsg() {
2050
2148
  Log.Debug("SetColorMapEntries");
2051
2149
 
package/docs/API.md CHANGED
@@ -155,6 +155,15 @@ protocol stream.
155
155
  [`RFB.clipboardPasteFrom()`](#rfbclipboardpastefrom)
156
156
  - Send clipboard contents to server.
157
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
+
158
167
  ### Details
159
168
 
160
169
  #### RFB()
@@ -423,3 +432,55 @@ to the remote server.
423
432
 
424
433
  **`text`**
425
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/lib/base64.js CHANGED
@@ -1,18 +1,13 @@
1
1
  "use strict";
2
2
 
3
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
-
5
4
  Object.defineProperty(exports, "__esModule", {
6
5
  value: true
7
6
  });
8
7
  exports["default"] = void 0;
9
-
10
8
  var Log = _interopRequireWildcard(require("./util/logging.js"));
11
-
12
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); }
13
-
14
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; }
15
-
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; // Convert every three bytes to 4 ascii characters.
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
- } // Convert the remaining 1 or 2 bytes, pad out to 4 characters.
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); // Convert one by one.
61
+ var result = new Array(resultLength);
74
62
 
75
- var leftbits = 0; // number of bits decoded, but yet to be appended
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; // Skip illegal characters and whitespace
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
- } // Collect data into leftdata, update bitcount
87
-
74
+ }
88
75
 
76
+ // Collect data into leftdata, update bitcount
89
77
  leftdata = leftdata << 6 | c;
90
- leftbits += 6; // If we have 8 or more bits, append 8 bits to the result
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; // Append if not padding.
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
- } // If there are any bits left, the base64 string was corrupted
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
101
  exports["default"] = _default;