@novnc/novnc 1.3.0-gcdfb336 → 1.3.0-gd8b3ec9

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 (53) hide show
  1. package/core/display.js +12 -0
  2. package/core/input/keyboard.js +10 -0
  3. package/core/rfb.js +176 -84
  4. package/core/util/cursor.js +4 -0
  5. package/docs/API.md +61 -0
  6. package/lib/base64.js +19 -33
  7. package/lib/decoders/copyrect.js +4 -11
  8. package/lib/decoders/hextile.js +16 -46
  9. package/lib/decoders/jpeg.js +4 -43
  10. package/lib/decoders/raw.js +8 -21
  11. package/lib/decoders/rre.js +4 -15
  12. package/lib/decoders/tight.js +12 -78
  13. package/lib/decoders/tightpng.js +5 -25
  14. package/lib/decoders/zrle.js +6 -52
  15. package/lib/deflator.js +8 -22
  16. package/lib/des.js +23 -36
  17. package/lib/display.js +61 -107
  18. package/lib/encodings.js +1 -10
  19. package/lib/inflator.js +5 -18
  20. package/lib/input/domkeytable.js +77 -48
  21. package/lib/input/fixedkeys.js +8 -3
  22. package/lib/input/gesturehandler.js +85 -152
  23. package/lib/input/keyboard.js +61 -90
  24. package/lib/input/keysym.js +14 -270
  25. package/lib/input/keysymdef.js +5 -7
  26. package/lib/input/util.js +42 -84
  27. package/lib/input/vkeys.js +0 -3
  28. package/lib/input/xtscancodes.js +1 -168
  29. package/lib/ra2.js +41 -263
  30. package/lib/rfb.js +456 -1012
  31. package/lib/util/browser.js +16 -25
  32. package/lib/util/cursor.js +28 -65
  33. package/lib/util/element.js +3 -5
  34. package/lib/util/events.js +23 -30
  35. package/lib/util/eventtarget.js +4 -13
  36. package/lib/util/int.js +1 -2
  37. package/lib/util/logging.js +1 -19
  38. package/lib/util/md5.js +7 -27
  39. package/lib/util/strings.js +3 -5
  40. package/lib/vendor/pako/lib/utils/common.js +8 -17
  41. package/lib/vendor/pako/lib/zlib/adler32.js +3 -7
  42. package/lib/vendor/pako/lib/zlib/constants.js +2 -5
  43. package/lib/vendor/pako/lib/zlib/crc32.js +5 -12
  44. package/lib/vendor/pako/lib/zlib/deflate.js +212 -617
  45. package/lib/vendor/pako/lib/zlib/gzheader.js +1 -13
  46. package/lib/vendor/pako/lib/zlib/inffast.js +60 -176
  47. package/lib/vendor/pako/lib/zlib/inflate.js +397 -887
  48. package/lib/vendor/pako/lib/zlib/inftrees.js +62 -168
  49. package/lib/vendor/pako/lib/zlib/messages.js +1 -11
  50. package/lib/vendor/pako/lib/zlib/trees.js +245 -587
  51. package/lib/vendor/pako/lib/zlib/zstream.js +2 -18
  52. package/lib/websock.js +35 -86
  53. package/package.json +31 -31
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 */
@@ -402,7 +417,7 @@ export default class RFB extends EventTargetMixin {
402
417
 
403
418
  sendCredentials(creds) {
404
419
  this._rfbCredentials = creds;
405
- setTimeout(this._initMsg.bind(this), 0);
420
+ this._resumeAuthentication();
406
421
  }
407
422
 
408
423
  sendCtrlAltDel() {
@@ -475,16 +490,45 @@ export default class RFB extends EventTargetMixin {
475
490
  this._clipboardText = text;
476
491
  RFB.messages.extendedClipboardNotify(this._sock, [extendedClipboardFormatText]);
477
492
  } else {
478
- let data = new Uint8Array(text.length);
479
- for (let i = 0; i < text.length; i++) {
480
- // FIXME: text can have values outside of Latin1/Uint8
481
- 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;
482
514
  }
483
515
 
484
516
  RFB.messages.clientCutText(this._sock, data);
485
517
  }
486
518
  }
487
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
+
488
532
  // ===== PRIVATE METHODS =====
489
533
 
490
534
  _connect() {
@@ -922,8 +966,15 @@ export default class RFB extends EventTargetMixin {
922
966
  }
923
967
  }
924
968
  break;
969
+ case 'connecting':
970
+ while (this._rfbConnectionState === 'connecting') {
971
+ if (!this._initMsg()) {
972
+ break;
973
+ }
974
+ }
975
+ break;
925
976
  default:
926
- this._initMsg();
977
+ Log.Error("Got data while in an invalid state");
927
978
  break;
928
979
  }
929
980
  }
@@ -1332,6 +1383,21 @@ export default class RFB extends EventTargetMixin {
1332
1383
  this._rfbInitState = 'Security';
1333
1384
  }
1334
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
+
1335
1401
  _negotiateSecurity() {
1336
1402
  if (this._rfbVersion >= 3.7) {
1337
1403
  // Server sends supported list, client decides
@@ -1342,28 +1408,23 @@ export default class RFB extends EventTargetMixin {
1342
1408
  this._rfbInitState = "SecurityReason";
1343
1409
  this._securityContext = "no security types";
1344
1410
  this._securityStatus = 1;
1345
- return this._initMsg();
1411
+ return true;
1346
1412
  }
1347
1413
 
1348
1414
  const types = this._sock.rQshiftBytes(numTypes);
1349
1415
  Log.Debug("Server security types: " + types);
1350
1416
 
1351
- // Look for each auth in preferred order
1352
- if (types.includes(1)) {
1353
- this._rfbAuthScheme = 1; // None
1354
- } else if (types.includes(22)) {
1355
- this._rfbAuthScheme = 22; // XVP
1356
- } else if (types.includes(16)) {
1357
- this._rfbAuthScheme = 16; // Tight
1358
- } else if (types.includes(6)) {
1359
- this._rfbAuthScheme = 6; // RA2ne Auth
1360
- } else if (types.includes(2)) {
1361
- this._rfbAuthScheme = 2; // VNC Auth
1362
- } else if (types.includes(30)) {
1363
- this._rfbAuthScheme = 30; // ARD Auth
1364
- } else if (types.includes(19)) {
1365
- this._rfbAuthScheme = 19; // VeNCrypt Auth
1366
- } 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) {
1367
1428
  return this._fail("Unsupported security types (types: " + types + ")");
1368
1429
  }
1369
1430
 
@@ -1377,14 +1438,14 @@ export default class RFB extends EventTargetMixin {
1377
1438
  this._rfbInitState = "SecurityReason";
1378
1439
  this._securityContext = "authentication scheme";
1379
1440
  this._securityStatus = 1;
1380
- return this._initMsg();
1441
+ return true;
1381
1442
  }
1382
1443
  }
1383
1444
 
1384
1445
  this._rfbInitState = 'Authentication';
1385
1446
  Log.Debug('Authenticating using scheme: ' + this._rfbAuthScheme);
1386
1447
 
1387
- return this._initMsg(); // jump to authentication
1448
+ return true;
1388
1449
  }
1389
1450
 
1390
1451
  _handleSecurityReason() {
@@ -1434,7 +1495,7 @@ export default class RFB extends EventTargetMixin {
1434
1495
  this._rfbCredentials.username +
1435
1496
  this._rfbCredentials.target;
1436
1497
  this._sock.sendString(xvpAuthStr);
1437
- this._rfbAuthScheme = 2;
1498
+ this._rfbAuthScheme = securityTypeVNCAuth;
1438
1499
  return this._negotiateAuthentication();
1439
1500
  }
1440
1501
 
@@ -1492,49 +1553,66 @@ export default class RFB extends EventTargetMixin {
1492
1553
  subtypes.push(this._sock.rQshift32());
1493
1554
  }
1494
1555
 
1495
- // 256 = Plain subtype
1496
- if (subtypes.indexOf(256) != -1) {
1497
- // 0x100 = 256
1498
- this._sock.send([0, 0, 1, 0]);
1499
- this._rfbVeNCryptState = 4;
1500
- } else {
1501
- 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
+ }
1502
1569
  }
1503
- }
1504
1570
 
1505
- // negotiated Plain subtype, server waits for password
1506
- if (this._rfbVeNCryptState == 4) {
1507
- if (this._rfbCredentials.username === undefined ||
1508
- this._rfbCredentials.password === undefined) {
1509
- this.dispatchEvent(new CustomEvent(
1510
- "credentialsrequired",
1511
- { detail: { types: ["username", "password"] } }));
1512
- return false;
1571
+ if (this._rfbAuthScheme === -1) {
1572
+ return this._fail("Unsupported security types (types: " + subtypes + ")");
1513
1573
  }
1514
1574
 
1515
- const user = encodeUTF8(this._rfbCredentials.username);
1516
- const pass = encodeUTF8(this._rfbCredentials.password);
1517
-
1518
- this._sock.send([
1519
- (user.length >> 24) & 0xFF,
1520
- (user.length >> 16) & 0xFF,
1521
- (user.length >> 8) & 0xFF,
1522
- user.length & 0xFF
1523
- ]);
1524
- this._sock.send([
1525
- (pass.length >> 24) & 0xFF,
1526
- (pass.length >> 16) & 0xFF,
1527
- (pass.length >> 8) & 0xFF,
1528
- pass.length & 0xFF
1529
- ]);
1530
- this._sock.sendString(user);
1531
- this._sock.sendString(pass);
1575
+ this._sock.send([this._rfbAuthScheme >> 24,
1576
+ this._rfbAuthScheme >> 16,
1577
+ this._rfbAuthScheme >> 8,
1578
+ this._rfbAuthScheme]);
1532
1579
 
1533
- this._rfbInitState = "SecurityResult";
1580
+ this._rfbVeNCryptState == 4;
1534
1581
  return true;
1535
1582
  }
1536
1583
  }
1537
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
+
1538
1616
  _negotiateStdVNCAuth() {
1539
1617
  if (this._sock.rQwait("auth challenge", 16)) { return false; }
1540
1618
 
@@ -1661,7 +1739,7 @@ export default class RFB extends EventTargetMixin {
1661
1739
  this._rfbCredentials.ardCredentials = encrypted;
1662
1740
  this._rfbCredentials.ardPublicKey = clientPublicKey;
1663
1741
 
1664
- setTimeout(this._initMsg.bind(this), 0);
1742
+ this._resumeAuthentication();
1665
1743
  }
1666
1744
 
1667
1745
  _negotiateTightUnixAuth() {
@@ -1771,12 +1849,12 @@ export default class RFB extends EventTargetMixin {
1771
1849
  case 'STDVNOAUTH__': // no auth
1772
1850
  this._rfbInitState = 'SecurityResult';
1773
1851
  return true;
1774
- case 'STDVVNCAUTH_': // VNC auth
1775
- this._rfbAuthScheme = 2;
1776
- return this._initMsg();
1777
- case 'TGHTULGNAUTH': // UNIX auth
1778
- this._rfbAuthScheme = 129;
1779
- return this._initMsg();
1852
+ case 'STDVVNCAUTH_':
1853
+ this._rfbAuthScheme = securityTypeVNCAuth;
1854
+ return true;
1855
+ case 'TGHTULGNAUTH':
1856
+ this._rfbAuthScheme = securityTypeUnixLogon;
1857
+ return true;
1780
1858
  default:
1781
1859
  return this._fail("Unsupported tiny auth scheme " +
1782
1860
  "(scheme: " + authType + ")");
@@ -1813,7 +1891,7 @@ export default class RFB extends EventTargetMixin {
1813
1891
  }).then(() => {
1814
1892
  this.dispatchEvent(new CustomEvent('securityresult'));
1815
1893
  this._rfbInitState = "SecurityResult";
1816
- this._initMsg();
1894
+ return true;
1817
1895
  }).finally(() => {
1818
1896
  this._rfbRSAAESAuthenticationState.removeEventListener(
1819
1897
  "serververification", this._eventHandlers.handleRSAAESServerVerification);
@@ -1827,33 +1905,32 @@ export default class RFB extends EventTargetMixin {
1827
1905
 
1828
1906
  _negotiateAuthentication() {
1829
1907
  switch (this._rfbAuthScheme) {
1830
- case 1: // no auth
1831
- if (this._rfbVersion >= 3.8) {
1832
- this._rfbInitState = 'SecurityResult';
1833
- return true;
1834
- }
1835
- this._rfbInitState = 'ClientInitialisation';
1836
- return this._initMsg();
1908
+ case securityTypeNone:
1909
+ this._rfbInitState = 'SecurityResult';
1910
+ return true;
1837
1911
 
1838
- case 22: // XVP auth
1912
+ case securityTypeXVP:
1839
1913
  return this._negotiateXvpAuth();
1840
1914
 
1841
- case 30: // ARD auth
1915
+ case securityTypeARD:
1842
1916
  return this._negotiateARDAuth();
1843
1917
 
1844
- case 2: // VNC authentication
1918
+ case securityTypeVNCAuth:
1845
1919
  return this._negotiateStdVNCAuth();
1846
1920
 
1847
- case 16: // TightVNC Security Type
1921
+ case securityTypeTight:
1848
1922
  return this._negotiateTightAuth();
1849
1923
 
1850
- case 19: // VeNCrypt Security Type
1924
+ case securityTypeVeNCrypt:
1851
1925
  return this._negotiateVeNCryptAuth();
1852
1926
 
1853
- case 129: // TightVNC UNIX Security Type
1927
+ case securityTypePlain:
1928
+ return this._negotiatePlainAuth();
1929
+
1930
+ case securityTypeUnixLogon:
1854
1931
  return this._negotiateTightUnixAuth();
1855
1932
 
1856
- case 6: // RA2ne Security Type
1933
+ case securityTypeRA2ne:
1857
1934
  return this._negotiateRA2neAuth();
1858
1935
 
1859
1936
  default:
@@ -1863,6 +1940,13 @@ export default class RFB extends EventTargetMixin {
1863
1940
  }
1864
1941
 
1865
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
+
1866
1950
  if (this._sock.rQwait('VNC auth response ', 4)) { return false; }
1867
1951
 
1868
1952
  const status = this._sock.rQshift32();
@@ -1870,13 +1954,13 @@ export default class RFB extends EventTargetMixin {
1870
1954
  if (status === 0) { // OK
1871
1955
  this._rfbInitState = 'ClientInitialisation';
1872
1956
  Log.Debug('Authentication OK');
1873
- return this._initMsg();
1957
+ return true;
1874
1958
  } else {
1875
1959
  if (this._rfbVersion >= 3.8) {
1876
1960
  this._rfbInitState = "SecurityReason";
1877
1961
  this._securityContext = "security result";
1878
1962
  this._securityStatus = status;
1879
- return this._initMsg();
1963
+ return true;
1880
1964
  } else {
1881
1965
  this.dispatchEvent(new CustomEvent(
1882
1966
  "securityfailure",
@@ -2052,6 +2136,14 @@ export default class RFB extends EventTargetMixin {
2052
2136
  }
2053
2137
  }
2054
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
+
2055
2147
  _handleSetColourMapMsg() {
2056
2148
  Log.Debug("SetColorMapEntries");
2057
2149
 
@@ -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
  }
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;