Fix noVNC: utiliser la version ESM (core/) au lieu du CommonJS lib/ (erreur can find variable export)
76 changed files +11,181 −8,814
modified
public/app.js
+1 −1
@@ -80,7 +80,7 @@ | ||
| 80 | 80 | statusEl.textContent = 'connexion…'; |
| 81 | 81 | try { |
| 82 | 82 | const pw = await (await fetch('/api/social/vncpw')).json(); |
| 83 | − const { default: RFB } = await import('/vendor/novnc/rfb.js'); | |
| 83 | + const { default: RFB } = await import('/vendor/novnc/core/rfb.js'); | |
| 84 | 84 | const url = (location.protocol === 'https:' ? 'wss://' : 'ws://') + location.host + '/vncws'; |
| 85 | 85 | panel.style.display = 'block'; |
| 86 | 86 | _rfb = new RFB(panel, url, { credentials: { password: pw.password } }); |
deleted
public/vendor/novnc/base64.js
+0 −100
@@ -1,100 +0,0 @@ | ||
| 1 | −"use strict"; | |
| 2 | − | |
| 3 | −function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } | |
| 4 | −Object.defineProperty(exports, "__esModule", { | |
| 5 | − value: true | |
| 6 | −}); | |
| 7 | −exports["default"] = void 0; | |
| 8 | −var Log = _interopRequireWildcard(require("./util/logging.js")); | |
| 9 | −function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } | |
| 10 | −function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; } | |
| 11 | −/* This Source Code Form is subject to the terms of the Mozilla Public | |
| 12 | − * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| 13 | − * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| 14 | −// From: http://hg.mozilla.org/mozilla-central/raw-file/ec10630b1a54/js/src/devtools/jint/sunspider/string-base64.js | |
| 15 | −var _default = exports["default"] = { | |
| 16 | − /* Convert data (an array of integers) to a Base64 string. */ | |
| 17 | − toBase64Table: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''), | |
| 18 | − base64Pad: '=', | |
| 19 | − encode: function encode(data) { | |
| 20 | − "use strict"; | |
| 21 | − | |
| 22 | − var result = ''; | |
| 23 | − var length = data.length; | |
| 24 | − var lengthpad = length % 3; | |
| 25 | − // Convert every three bytes to 4 ascii characters. | |
| 26 | − | |
| 27 | − for (var i = 0; i < length - 2; i += 3) { | |
| 28 | − result += this.toBase64Table[data[i] >> 2]; | |
| 29 | − result += this.toBase64Table[((data[i] & 0x03) << 4) + (data[i + 1] >> 4)]; | |
| 30 | − result += this.toBase64Table[((data[i + 1] & 0x0f) << 2) + (data[i + 2] >> 6)]; | |
| 31 | − result += this.toBase64Table[data[i + 2] & 0x3f]; | |
| 32 | − } | |
| 33 | − | |
| 34 | − // Convert the remaining 1 or 2 bytes, pad out to 4 characters. | |
| 35 | − var j = length - lengthpad; | |
| 36 | − if (lengthpad === 2) { | |
| 37 | − result += this.toBase64Table[data[j] >> 2]; | |
| 38 | − result += this.toBase64Table[((data[j] & 0x03) << 4) + (data[j + 1] >> 4)]; | |
| 39 | − result += this.toBase64Table[(data[j + 1] & 0x0f) << 2]; | |
| 40 | − result += this.toBase64Table[64]; | |
| 41 | − } else if (lengthpad === 1) { | |
| 42 | − result += this.toBase64Table[data[j] >> 2]; | |
| 43 | − result += this.toBase64Table[(data[j] & 0x03) << 4]; | |
| 44 | − result += this.toBase64Table[64]; | |
| 45 | − result += this.toBase64Table[64]; | |
| 46 | − } | |
| 47 | − return result; | |
| 48 | − }, | |
| 49 | − /* Convert Base64 data to a string */ | |
| 50 | − /* eslint-disable comma-spacing */ | |
| 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], | |
| 52 | − /* eslint-enable comma-spacing */decode: function decode(data) { | |
| 53 | − var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; | |
| 54 | − var dataLength = data.indexOf('=') - offset; | |
| 55 | − if (dataLength < 0) { | |
| 56 | − dataLength = data.length - offset; | |
| 57 | − } | |
| 58 | − | |
| 59 | − /* Every four characters is 3 resulting numbers */ | |
| 60 | − var resultLength = (dataLength >> 2) * 3 + Math.floor(dataLength % 4 / 1.5); | |
| 61 | − var result = new Array(resultLength); | |
| 62 | − | |
| 63 | − // Convert one by one. | |
| 64 | − | |
| 65 | − var leftbits = 0; // number of bits decoded, but yet to be appended | |
| 66 | − var leftdata = 0; // bits decoded, but yet to be appended | |
| 67 | − for (var idx = 0, i = offset; i < data.length; i++) { | |
| 68 | − var c = this.toBinaryTable[data.charCodeAt(i) & 0x7f]; | |
| 69 | − var padding = data.charAt(i) === this.base64Pad; | |
| 70 | − // Skip illegal characters and whitespace | |
| 71 | − if (c === -1) { | |
| 72 | − Log.Error("Illegal character code " + data.charCodeAt(i) + " at position " + i); | |
| 73 | − continue; | |
| 74 | − } | |
| 75 | − | |
| 76 | − // Collect data into leftdata, update bitcount | |
| 77 | − leftdata = leftdata << 6 | c; | |
| 78 | − leftbits += 6; | |
| 79 | − | |
| 80 | − // If we have 8 or more bits, append 8 bits to the result | |
| 81 | − if (leftbits >= 8) { | |
| 82 | − leftbits -= 8; | |
| 83 | − // Append if not padding. | |
| 84 | − if (!padding) { | |
| 85 | − result[idx++] = leftdata >> leftbits & 0xff; | |
| 86 | − } | |
| 87 | − leftdata &= (1 << leftbits) - 1; | |
| 88 | − } | |
| 89 | − } | |
| 90 | − | |
| 91 | − // If there are any bits left, the base64 string was corrupted | |
| 92 | − if (leftbits) { | |
| 93 | − var err = new Error('Corrupted base64 string'); | |
| 94 | − err.name = 'Base64-Error'; | |
| 95 | − throw err; | |
| 96 | − } | |
| 97 | − return result; | |
| 98 | − } | |
| 99 | −}; | |
| 100 | −/* End of Base64 namespace */ | |
| \ No newline at end of file | ||
added
public/vendor/novnc/core/base64.js
+104 −0
@@ -0,0 +1,104 @@ | ||
| 1 | +/* This Source Code Form is subject to the terms of the Mozilla Public | |
| 2 | + * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| 3 | + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| 4 | + | |
| 5 | +// From: http://hg.mozilla.org/mozilla-central/raw-file/ec10630b1a54/js/src/devtools/jint/sunspider/string-base64.js | |
| 6 | + | |
| 7 | +import * as Log from './util/logging.js'; | |
| 8 | + | |
| 9 | +export default { | |
| 10 | + /* Convert data (an array of integers) to a Base64 string. */ | |
| 11 | + toBase64Table: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''), | |
| 12 | + base64Pad: '=', | |
| 13 | + | |
| 14 | + encode(data) { | |
| 15 | + "use strict"; | |
| 16 | + let result = ''; | |
| 17 | + const length = data.length; | |
| 18 | + const lengthpad = (length % 3); | |
| 19 | + // Convert every three bytes to 4 ascii characters. | |
| 20 | + | |
| 21 | + for (let i = 0; i < (length - 2); i += 3) { | |
| 22 | + result += this.toBase64Table[data[i] >> 2]; | |
| 23 | + result += this.toBase64Table[((data[i] & 0x03) << 4) + (data[i + 1] >> 4)]; | |
| 24 | + result += this.toBase64Table[((data[i + 1] & 0x0f) << 2) + (data[i + 2] >> 6)]; | |
| 25 | + result += this.toBase64Table[data[i + 2] & 0x3f]; | |
| 26 | + } | |
| 27 | + | |
| 28 | + // Convert the remaining 1 or 2 bytes, pad out to 4 characters. | |
| 29 | + const j = length - lengthpad; | |
| 30 | + if (lengthpad === 2) { | |
| 31 | + result += this.toBase64Table[data[j] >> 2]; | |
| 32 | + result += this.toBase64Table[((data[j] & 0x03) << 4) + (data[j + 1] >> 4)]; | |
| 33 | + result += this.toBase64Table[(data[j + 1] & 0x0f) << 2]; | |
| 34 | + result += this.toBase64Table[64]; | |
| 35 | + } else if (lengthpad === 1) { | |
| 36 | + result += this.toBase64Table[data[j] >> 2]; | |
| 37 | + result += this.toBase64Table[(data[j] & 0x03) << 4]; | |
| 38 | + result += this.toBase64Table[64]; | |
| 39 | + result += this.toBase64Table[64]; | |
| 40 | + } | |
| 41 | + | |
| 42 | + return result; | |
| 43 | + }, | |
| 44 | + | |
| 45 | + /* Convert Base64 data to a string */ | |
| 46 | + /* eslint-disable comma-spacing */ | |
| 47 | + toBinaryTable: [ | |
| 48 | + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | |
| 49 | + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | |
| 50 | + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, | |
| 51 | + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1, | |
| 52 | + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, | |
| 53 | + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, | |
| 54 | + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, | |
| 55 | + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 | |
| 56 | + ], | |
| 57 | + /* eslint-enable comma-spacing */ | |
| 58 | + | |
| 59 | + decode(data, offset = 0) { | |
| 60 | + let dataLength = data.indexOf('=') - offset; | |
| 61 | + if (dataLength < 0) { dataLength = data.length - offset; } | |
| 62 | + | |
| 63 | + /* Every four characters is 3 resulting numbers */ | |
| 64 | + const resultLength = (dataLength >> 2) * 3 + Math.floor((dataLength % 4) / 1.5); | |
| 65 | + const result = new Array(resultLength); | |
| 66 | + | |
| 67 | + // Convert one by one. | |
| 68 | + | |
| 69 | + let leftbits = 0; // number of bits decoded, but yet to be appended | |
| 70 | + let leftdata = 0; // bits decoded, but yet to be appended | |
| 71 | + for (let idx = 0, i = offset; i < data.length; i++) { | |
| 72 | + const c = this.toBinaryTable[data.charCodeAt(i) & 0x7f]; | |
| 73 | + const padding = (data.charAt(i) === this.base64Pad); | |
| 74 | + // Skip illegal characters and whitespace | |
| 75 | + if (c === -1) { | |
| 76 | + Log.Error("Illegal character code " + data.charCodeAt(i) + " at position " + i); | |
| 77 | + continue; | |
| 78 | + } | |
| 79 | + | |
| 80 | + // Collect data into leftdata, update bitcount | |
| 81 | + leftdata = (leftdata << 6) | c; | |
| 82 | + leftbits += 6; | |
| 83 | + | |
| 84 | + // If we have 8 or more bits, append 8 bits to the result | |
| 85 | + if (leftbits >= 8) { | |
| 86 | + leftbits -= 8; | |
| 87 | + // Append if not padding. | |
| 88 | + if (!padding) { | |
| 89 | + result[idx++] = (leftdata >> leftbits) & 0xff; | |
| 90 | + } | |
| 91 | + leftdata &= (1 << leftbits) - 1; | |
| 92 | + } | |
| 93 | + } | |
| 94 | + | |
| 95 | + // If there are any bits left, the base64 string was corrupted | |
| 96 | + if (leftbits) { | |
| 97 | + const err = new Error('Corrupted base64 string'); | |
| 98 | + err.name = 'Base64-Error'; | |
| 99 | + throw err; | |
| 100 | + } | |
| 101 | + | |
| 102 | + return result; | |
| 103 | + } | |
| 104 | +}; /* End of Base64 namespace */ | |
added
public/vendor/novnc/core/crypto/aes.js
+178 −0
@@ -0,0 +1,178 @@ | ||
| 1 | +export class AESECBCipher { | |
| 2 | + constructor() { | |
| 3 | + this._key = null; | |
| 4 | + } | |
| 5 | + | |
| 6 | + get algorithm() { | |
| 7 | + return { name: "AES-ECB" }; | |
| 8 | + } | |
| 9 | + | |
| 10 | + static async importKey(key, _algorithm, extractable, keyUsages) { | |
| 11 | + const cipher = new AESECBCipher; | |
| 12 | + await cipher._importKey(key, extractable, keyUsages); | |
| 13 | + return cipher; | |
| 14 | + } | |
| 15 | + | |
| 16 | + async _importKey(key, extractable, keyUsages) { | |
| 17 | + this._key = await window.crypto.subtle.importKey( | |
| 18 | + "raw", key, {name: "AES-CBC"}, extractable, keyUsages); | |
| 19 | + } | |
| 20 | + | |
| 21 | + async encrypt(_algorithm, plaintext) { | |
| 22 | + const x = new Uint8Array(plaintext); | |
| 23 | + if (x.length % 16 !== 0 || this._key === null) { | |
| 24 | + return null; | |
| 25 | + } | |
| 26 | + const n = x.length / 16; | |
| 27 | + for (let i = 0; i < n; i++) { | |
| 28 | + const y = new Uint8Array(await window.crypto.subtle.encrypt({ | |
| 29 | + name: "AES-CBC", | |
| 30 | + iv: new Uint8Array(16), | |
| 31 | + }, this._key, x.slice(i * 16, i * 16 + 16))).slice(0, 16); | |
| 32 | + x.set(y, i * 16); | |
| 33 | + } | |
| 34 | + return x; | |
| 35 | + } | |
| 36 | +} | |
| 37 | + | |
| 38 | +export class AESEAXCipher { | |
| 39 | + constructor() { | |
| 40 | + this._rawKey = null; | |
| 41 | + this._ctrKey = null; | |
| 42 | + this._cbcKey = null; | |
| 43 | + this._zeroBlock = new Uint8Array(16); | |
| 44 | + this._prefixBlock0 = this._zeroBlock; | |
| 45 | + this._prefixBlock1 = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); | |
| 46 | + this._prefixBlock2 = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]); | |
| 47 | + } | |
| 48 | + | |
| 49 | + get algorithm() { | |
| 50 | + return { name: "AES-EAX" }; | |
| 51 | + } | |
| 52 | + | |
| 53 | + async _encryptBlock(block) { | |
| 54 | + const encrypted = await window.crypto.subtle.encrypt({ | |
| 55 | + name: "AES-CBC", | |
| 56 | + iv: this._zeroBlock, | |
| 57 | + }, this._cbcKey, block); | |
| 58 | + return new Uint8Array(encrypted).slice(0, 16); | |
| 59 | + } | |
| 60 | + | |
| 61 | + async _initCMAC() { | |
| 62 | + const k1 = await this._encryptBlock(this._zeroBlock); | |
| 63 | + const k2 = new Uint8Array(16); | |
| 64 | + const v = k1[0] >>> 6; | |
| 65 | + for (let i = 0; i < 15; i++) { | |
| 66 | + k2[i] = (k1[i + 1] >> 6) | (k1[i] << 2); | |
| 67 | + k1[i] = (k1[i + 1] >> 7) | (k1[i] << 1); | |
| 68 | + } | |
| 69 | + const lut = [0x0, 0x87, 0x0e, 0x89]; | |
| 70 | + k2[14] ^= v >>> 1; | |
| 71 | + k2[15] = (k1[15] << 2) ^ lut[v]; | |
| 72 | + k1[15] = (k1[15] << 1) ^ lut[v >> 1]; | |
| 73 | + this._k1 = k1; | |
| 74 | + this._k2 = k2; | |
| 75 | + } | |
| 76 | + | |
| 77 | + async _encryptCTR(data, counter) { | |
| 78 | + const encrypted = await window.crypto.subtle.encrypt({ | |
| 79 | + name: "AES-CTR", | |
| 80 | + counter: counter, | |
| 81 | + length: 128 | |
| 82 | + }, this._ctrKey, data); | |
| 83 | + return new Uint8Array(encrypted); | |
| 84 | + } | |
| 85 | + | |
| 86 | + async _decryptCTR(data, counter) { | |
| 87 | + const decrypted = await window.crypto.subtle.decrypt({ | |
| 88 | + name: "AES-CTR", | |
| 89 | + counter: counter, | |
| 90 | + length: 128 | |
| 91 | + }, this._ctrKey, data); | |
| 92 | + return new Uint8Array(decrypted); | |
| 93 | + } | |
| 94 | + | |
| 95 | + async _computeCMAC(data, prefixBlock) { | |
| 96 | + if (prefixBlock.length !== 16) { | |
| 97 | + return null; | |
| 98 | + } | |
| 99 | + const n = Math.floor(data.length / 16); | |
| 100 | + const m = Math.ceil(data.length / 16); | |
| 101 | + const r = data.length - n * 16; | |
| 102 | + const cbcData = new Uint8Array((m + 1) * 16); | |
| 103 | + cbcData.set(prefixBlock); | |
| 104 | + cbcData.set(data, 16); | |
| 105 | + if (r === 0) { | |
| 106 | + for (let i = 0; i < 16; i++) { | |
| 107 | + cbcData[n * 16 + i] ^= this._k1[i]; | |
| 108 | + } | |
| 109 | + } else { | |
| 110 | + cbcData[(n + 1) * 16 + r] = 0x80; | |
| 111 | + for (let i = 0; i < 16; i++) { | |
| 112 | + cbcData[(n + 1) * 16 + i] ^= this._k2[i]; | |
| 113 | + } | |
| 114 | + } | |
| 115 | + let cbcEncrypted = await window.crypto.subtle.encrypt({ | |
| 116 | + name: "AES-CBC", | |
| 117 | + iv: this._zeroBlock, | |
| 118 | + }, this._cbcKey, cbcData); | |
| 119 | + | |
| 120 | + cbcEncrypted = new Uint8Array(cbcEncrypted); | |
| 121 | + const mac = cbcEncrypted.slice(cbcEncrypted.length - 32, cbcEncrypted.length - 16); | |
| 122 | + return mac; | |
| 123 | + } | |
| 124 | + | |
| 125 | + static async importKey(key, _algorithm, _extractable, _keyUsages) { | |
| 126 | + const cipher = new AESEAXCipher; | |
| 127 | + await cipher._importKey(key); | |
| 128 | + return cipher; | |
| 129 | + } | |
| 130 | + | |
| 131 | + async _importKey(key) { | |
| 132 | + this._rawKey = key; | |
| 133 | + this._ctrKey = await window.crypto.subtle.importKey( | |
| 134 | + "raw", key, {name: "AES-CTR"}, false, ["encrypt", "decrypt"]); | |
| 135 | + this._cbcKey = await window.crypto.subtle.importKey( | |
| 136 | + "raw", key, {name: "AES-CBC"}, false, ["encrypt"]); | |
| 137 | + await this._initCMAC(); | |
| 138 | + } | |
| 139 | + | |
| 140 | + async encrypt(algorithm, message) { | |
| 141 | + const ad = algorithm.additionalData; | |
| 142 | + const nonce = algorithm.iv; | |
| 143 | + const nCMAC = await this._computeCMAC(nonce, this._prefixBlock0); | |
| 144 | + const encrypted = await this._encryptCTR(message, nCMAC); | |
| 145 | + const adCMAC = await this._computeCMAC(ad, this._prefixBlock1); | |
| 146 | + const mac = await this._computeCMAC(encrypted, this._prefixBlock2); | |
| 147 | + for (let i = 0; i < 16; i++) { | |
| 148 | + mac[i] ^= nCMAC[i] ^ adCMAC[i]; | |
| 149 | + } | |
| 150 | + const res = new Uint8Array(16 + encrypted.length); | |
| 151 | + res.set(encrypted); | |
| 152 | + res.set(mac, encrypted.length); | |
| 153 | + return res; | |
| 154 | + } | |
| 155 | + | |
| 156 | + async decrypt(algorithm, data) { | |
| 157 | + const encrypted = data.slice(0, data.length - 16); | |
| 158 | + const ad = algorithm.additionalData; | |
| 159 | + const nonce = algorithm.iv; | |
| 160 | + const mac = data.slice(data.length - 16); | |
| 161 | + const nCMAC = await this._computeCMAC(nonce, this._prefixBlock0); | |
| 162 | + const adCMAC = await this._computeCMAC(ad, this._prefixBlock1); | |
| 163 | + const computedMac = await this._computeCMAC(encrypted, this._prefixBlock2); | |
| 164 | + for (let i = 0; i < 16; i++) { | |
| 165 | + computedMac[i] ^= nCMAC[i] ^ adCMAC[i]; | |
| 166 | + } | |
| 167 | + if (computedMac.length !== mac.length) { | |
| 168 | + return null; | |
| 169 | + } | |
| 170 | + for (let i = 0; i < mac.length; i++) { | |
| 171 | + if (computedMac[i] !== mac[i]) { | |
| 172 | + return null; | |
| 173 | + } | |
| 174 | + } | |
| 175 | + const res = await this._decryptCTR(encrypted, nCMAC); | |
| 176 | + return res; | |
| 177 | + } | |
| 178 | +} | |
added
public/vendor/novnc/core/crypto/bigint.js
+34 −0
@@ -0,0 +1,34 @@ | ||
| 1 | +export function modPow(b, e, m) { | |
| 2 | + let r = 1n; | |
| 3 | + b = b % m; | |
| 4 | + while (e > 0n) { | |
| 5 | + if ((e & 1n) === 1n) { | |
| 6 | + r = (r * b) % m; | |
| 7 | + } | |
| 8 | + e = e >> 1n; | |
| 9 | + b = (b * b) % m; | |
| 10 | + } | |
| 11 | + return r; | |
| 12 | +} | |
| 13 | + | |
| 14 | +export function bigIntToU8Array(bigint, padLength=0) { | |
| 15 | + let hex = bigint.toString(16); | |
| 16 | + if (padLength === 0) { | |
| 17 | + padLength = Math.ceil(hex.length / 2); | |
| 18 | + } | |
| 19 | + hex = hex.padStart(padLength * 2, '0'); | |
| 20 | + const length = hex.length / 2; | |
| 21 | + const arr = new Uint8Array(length); | |
| 22 | + for (let i = 0; i < length; i++) { | |
| 23 | + arr[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16); | |
| 24 | + } | |
| 25 | + return arr; | |
| 26 | +} | |
| 27 | + | |
| 28 | +export function u8ArrayToBigInt(arr) { | |
| 29 | + let hex = '0x'; | |
| 30 | + for (let i = 0; i < arr.length; i++) { | |
| 31 | + hex += arr[i].toString(16).padStart(2, '0'); | |
| 32 | + } | |
| 33 | + return BigInt(hex); | |
| 34 | +} | |
added
public/vendor/novnc/core/crypto/crypto.js
+90 −0
@@ -0,0 +1,90 @@ | ||
| 1 | +import { AESECBCipher, AESEAXCipher } from "./aes.js"; | |
| 2 | +import { DESCBCCipher, DESECBCipher } from "./des.js"; | |
| 3 | +import { RSACipher } from "./rsa.js"; | |
| 4 | +import { DHCipher } from "./dh.js"; | |
| 5 | +import { MD5 } from "./md5.js"; | |
| 6 | + | |
| 7 | +// A single interface for the cryptographic algorithms not supported by SubtleCrypto. | |
| 8 | +// Both synchronous and asynchronous implmentations are allowed. | |
| 9 | +class LegacyCrypto { | |
| 10 | + constructor() { | |
| 11 | + this._algorithms = { | |
| 12 | + "AES-ECB": AESECBCipher, | |
| 13 | + "AES-EAX": AESEAXCipher, | |
| 14 | + "DES-ECB": DESECBCipher, | |
| 15 | + "DES-CBC": DESCBCCipher, | |
| 16 | + "RSA-PKCS1-v1_5": RSACipher, | |
| 17 | + "DH": DHCipher, | |
| 18 | + "MD5": MD5, | |
| 19 | + }; | |
| 20 | + } | |
| 21 | + | |
| 22 | + encrypt(algorithm, key, data) { | |
| 23 | + if (key.algorithm.name !== algorithm.name) { | |
| 24 | + throw new Error("algorithm does not match"); | |
| 25 | + } | |
| 26 | + if (typeof key.encrypt !== "function") { | |
| 27 | + throw new Error("key does not support encryption"); | |
| 28 | + } | |
| 29 | + return key.encrypt(algorithm, data); | |
| 30 | + } | |
| 31 | + | |
| 32 | + decrypt(algorithm, key, data) { | |
| 33 | + if (key.algorithm.name !== algorithm.name) { | |
| 34 | + throw new Error("algorithm does not match"); | |
| 35 | + } | |
| 36 | + if (typeof key.decrypt !== "function") { | |
| 37 | + throw new Error("key does not support encryption"); | |
| 38 | + } | |
| 39 | + return key.decrypt(algorithm, data); | |
| 40 | + } | |
| 41 | + | |
| 42 | + importKey(format, keyData, algorithm, extractable, keyUsages) { | |
| 43 | + if (format !== "raw") { | |
| 44 | + throw new Error("key format is not supported"); | |
| 45 | + } | |
| 46 | + const alg = this._algorithms[algorithm.name]; | |
| 47 | + if (typeof alg === "undefined" || typeof alg.importKey !== "function") { | |
| 48 | + throw new Error("algorithm is not supported"); | |
| 49 | + } | |
| 50 | + return alg.importKey(keyData, algorithm, extractable, keyUsages); | |
| 51 | + } | |
| 52 | + | |
| 53 | + generateKey(algorithm, extractable, keyUsages) { | |
| 54 | + const alg = this._algorithms[algorithm.name]; | |
| 55 | + if (typeof alg === "undefined" || typeof alg.generateKey !== "function") { | |
| 56 | + throw new Error("algorithm is not supported"); | |
| 57 | + } | |
| 58 | + return alg.generateKey(algorithm, extractable, keyUsages); | |
| 59 | + } | |
| 60 | + | |
| 61 | + exportKey(format, key) { | |
| 62 | + if (format !== "raw") { | |
| 63 | + throw new Error("key format is not supported"); | |
| 64 | + } | |
| 65 | + if (typeof key.exportKey !== "function") { | |
| 66 | + throw new Error("key does not support exportKey"); | |
| 67 | + } | |
| 68 | + return key.exportKey(); | |
| 69 | + } | |
| 70 | + | |
| 71 | + digest(algorithm, data) { | |
| 72 | + const alg = this._algorithms[algorithm]; | |
| 73 | + if (typeof alg !== "function") { | |
| 74 | + throw new Error("algorithm is not supported"); | |
| 75 | + } | |
| 76 | + return alg(data); | |
| 77 | + } | |
| 78 | + | |
| 79 | + deriveBits(algorithm, key, length) { | |
| 80 | + if (key.algorithm.name !== algorithm.name) { | |
| 81 | + throw new Error("algorithm does not match"); | |
| 82 | + } | |
| 83 | + if (typeof key.deriveBits !== "function") { | |
| 84 | + throw new Error("key does not support deriveBits"); | |
| 85 | + } | |
| 86 | + return key.deriveBits(algorithm, length); | |
| 87 | + } | |
| 88 | +} | |
| 89 | + | |
| 90 | +export default new LegacyCrypto; | |
added
public/vendor/novnc/core/crypto/des.js
+330 −0
@@ -0,0 +1,330 @@ | ||
| 1 | +/* | |
| 2 | + * Ported from Flashlight VNC ActionScript implementation: | |
| 3 | + * http://www.wizhelp.com/flashlight-vnc/ | |
| 4 | + * | |
| 5 | + * Full attribution follows: | |
| 6 | + * | |
| 7 | + * ------------------------------------------------------------------------- | |
| 8 | + * | |
| 9 | + * This DES class has been extracted from package Acme.Crypto for use in VNC. | |
| 10 | + * The unnecessary odd parity code has been removed. | |
| 11 | + * | |
| 12 | + * These changes are: | |
| 13 | + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. | |
| 14 | + * | |
| 15 | + * This software is distributed in the hope that it will be useful, | |
| 16 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
| 18 | + * | |
| 19 | + | |
| 20 | + * DesCipher - the DES encryption method | |
| 21 | + * | |
| 22 | + * The meat of this code is by Dave Zimmerman <dzimm@widget.com>, and is: | |
| 23 | + * | |
| 24 | + * Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved. | |
| 25 | + * | |
| 26 | + * Permission to use, copy, modify, and distribute this software | |
| 27 | + * and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and | |
| 28 | + * without fee is hereby granted, provided that this copyright notice is kept | |
| 29 | + * intact. | |
| 30 | + * | |
| 31 | + * WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY | |
| 32 | + * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED | |
| 33 | + * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
| 34 | + * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE LIABLE | |
| 35 | + * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
| 36 | + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. | |
| 37 | + * | |
| 38 | + * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE | |
| 39 | + * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE | |
| 40 | + * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT | |
| 41 | + * NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE | |
| 42 | + * SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE | |
| 43 | + * SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE | |
| 44 | + * PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). WIDGET WORKSHOP | |
| 45 | + * SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR | |
| 46 | + * HIGH RISK ACTIVITIES. | |
| 47 | + * | |
| 48 | + * | |
| 49 | + * The rest is: | |
| 50 | + * | |
| 51 | + * Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. All rights reserved. | |
| 52 | + * | |
| 53 | + * Redistribution and use in source and binary forms, with or without | |
| 54 | + * modification, are permitted provided that the following conditions | |
| 55 | + * are met: | |
| 56 | + * 1. Redistributions of source code must retain the above copyright | |
| 57 | + * notice, this list of conditions and the following disclaimer. | |
| 58 | + * 2. Redistributions in binary form must reproduce the above copyright | |
| 59 | + * notice, this list of conditions and the following disclaimer in the | |
| 60 | + * documentation and/or other materials provided with the distribution. | |
| 61 | + * | |
| 62 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
| 63 | + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 64 | + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 65 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
| 66 | + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 67 | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 68 | + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 69 | + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 70 | + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 71 | + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 72 | + * SUCH DAMAGE. | |
| 73 | + * | |
| 74 | + * Visit the ACME Labs Java page for up-to-date versions of this and other | |
| 75 | + * fine Java utilities: http://www.acme.com/java/ | |
| 76 | + */ | |
| 77 | + | |
| 78 | +/* eslint-disable comma-spacing */ | |
| 79 | + | |
| 80 | +// Tables, permutations, S-boxes, etc. | |
| 81 | +const PC2 = [13,16,10,23, 0, 4, 2,27,14, 5,20, 9,22,18,11, 3, | |
| 82 | + 25, 7,15, 6,26,19,12, 1,40,51,30,36,46,54,29,39, | |
| 83 | + 50,44,32,47,43,48,38,55,33,52,45,41,49,35,28,31 ], | |
| 84 | + totrot = [ 1, 2, 4, 6, 8,10,12,14,15,17,19,21,23,25,27,28]; | |
| 85 | + | |
| 86 | +const z = 0x0; | |
| 87 | +let a,b,c,d,e,f; | |
| 88 | +a=1<<16; b=1<<24; c=a|b; d=1<<2; e=1<<10; f=d|e; | |
| 89 | +const SP1 = [c|e,z|z,a|z,c|f,c|d,a|f,z|d,a|z,z|e,c|e,c|f,z|e,b|f,c|d,b|z,z|d, | |
| 90 | + z|f,b|e,b|e,a|e,a|e,c|z,c|z,b|f,a|d,b|d,b|d,a|d,z|z,z|f,a|f,b|z, | |
| 91 | + a|z,c|f,z|d,c|z,c|e,b|z,b|z,z|e,c|d,a|z,a|e,b|d,z|e,z|d,b|f,a|f, | |
| 92 | + c|f,a|d,c|z,b|f,b|d,z|f,a|f,c|e,z|f,b|e,b|e,z|z,a|d,a|e,z|z,c|d]; | |
| 93 | +a=1<<20; b=1<<31; c=a|b; d=1<<5; e=1<<15; f=d|e; | |
| 94 | +const SP2 = [c|f,b|e,z|e,a|f,a|z,z|d,c|d,b|f,b|d,c|f,c|e,b|z,b|e,a|z,z|d,c|d, | |
| 95 | + a|e,a|d,b|f,z|z,b|z,z|e,a|f,c|z,a|d,b|d,z|z,a|e,z|f,c|e,c|z,z|f, | |
| 96 | + z|z,a|f,c|d,a|z,b|f,c|z,c|e,z|e,c|z,b|e,z|d,c|f,a|f,z|d,z|e,b|z, | |
| 97 | + z|f,c|e,a|z,b|d,a|d,b|f,b|d,a|d,a|e,z|z,b|e,z|f,b|z,c|d,c|f,a|e]; | |
| 98 | +a=1<<17; b=1<<27; c=a|b; d=1<<3; e=1<<9; f=d|e; | |
| 99 | +const SP3 = [z|f,c|e,z|z,c|d,b|e,z|z,a|f,b|e,a|d,b|d,b|d,a|z,c|f,a|d,c|z,z|f, | |
| 100 | + b|z,z|d,c|e,z|e,a|e,c|z,c|d,a|f,b|f,a|e,a|z,b|f,z|d,c|f,z|e,b|z, | |
| 101 | + c|e,b|z,a|d,z|f,a|z,c|e,b|e,z|z,z|e,a|d,c|f,b|e,b|d,z|e,z|z,c|d, | |
| 102 | + b|f,a|z,b|z,c|f,z|d,a|f,a|e,b|d,c|z,b|f,z|f,c|z,a|f,z|d,c|d,a|e]; | |
| 103 | +a=1<<13; b=1<<23; c=a|b; d=1<<0; e=1<<7; f=d|e; | |
| 104 | +const SP4 = [c|d,a|f,a|f,z|e,c|e,b|f,b|d,a|d,z|z,c|z,c|z,c|f,z|f,z|z,b|e,b|d, | |
| 105 | + z|d,a|z,b|z,c|d,z|e,b|z,a|d,a|e,b|f,z|d,a|e,b|e,a|z,c|e,c|f,z|f, | |
| 106 | + b|e,b|d,c|z,c|f,z|f,z|z,z|z,c|z,a|e,b|e,b|f,z|d,c|d,a|f,a|f,z|e, | |
| 107 | + c|f,z|f,z|d,a|z,b|d,a|d,c|e,b|f,a|d,a|e,b|z,c|d,z|e,b|z,a|z,c|e]; | |
| 108 | +a=1<<25; b=1<<30; c=a|b; d=1<<8; e=1<<19; f=d|e; | |
| 109 | +const SP5 = [z|d,a|f,a|e,c|d,z|e,z|d,b|z,a|e,b|f,z|e,a|d,b|f,c|d,c|e,z|f,b|z, | |
| 110 | + a|z,b|e,b|e,z|z,b|d,c|f,c|f,a|d,c|e,b|d,z|z,c|z,a|f,a|z,c|z,z|f, | |
| 111 | + z|e,c|d,z|d,a|z,b|z,a|e,c|d,b|f,a|d,b|z,c|e,a|f,b|f,z|d,a|z,c|e, | |
| 112 | + c|f,z|f,c|z,c|f,a|e,z|z,b|e,c|z,z|f,a|d,b|d,z|e,z|z,b|e,a|f,b|d]; | |
| 113 | +a=1<<22; b=1<<29; c=a|b; d=1<<4; e=1<<14; f=d|e; | |
| 114 | +const SP6 = [b|d,c|z,z|e,c|f,c|z,z|d,c|f,a|z,b|e,a|f,a|z,b|d,a|d,b|e,b|z,z|f, | |
| 115 | + z|z,a|d,b|f,z|e,a|e,b|f,z|d,c|d,c|d,z|z,a|f,c|e,z|f,a|e,c|e,b|z, | |
| 116 | + b|e,z|d,c|d,a|e,c|f,a|z,z|f,b|d,a|z,b|e,b|z,z|f,b|d,c|f,a|e,c|z, | |
| 117 | + a|f,c|e,z|z,c|d,z|d,z|e,c|z,a|f,z|e,a|d,b|f,z|z,c|e,b|z,a|d,b|f]; | |
| 118 | +a=1<<21; b=1<<26; c=a|b; d=1<<1; e=1<<11; f=d|e; | |
| 119 | +const SP7 = [a|z,c|d,b|f,z|z,z|e,b|f,a|f,c|e,c|f,a|z,z|z,b|d,z|d,b|z,c|d,z|f, | |
| 120 | + b|e,a|f,a|d,b|e,b|d,c|z,c|e,a|d,c|z,z|e,z|f,c|f,a|e,z|d,b|z,a|e, | |
| 121 | + b|z,a|e,a|z,b|f,b|f,c|d,c|d,z|d,a|d,b|z,b|e,a|z,c|e,z|f,a|f,c|e, | |
| 122 | + z|f,b|d,c|f,c|z,a|e,z|z,z|d,c|f,z|z,a|f,c|z,z|e,b|d,b|e,z|e,a|d]; | |
| 123 | +a=1<<18; b=1<<28; c=a|b; d=1<<6; e=1<<12; f=d|e; | |
| 124 | +const SP8 = [b|f,z|e,a|z,c|f,b|z,b|f,z|d,b|z,a|d,c|z,c|f,a|e,c|e,a|f,z|e,z|d, | |
| 125 | + c|z,b|d,b|e,z|f,a|e,a|d,c|d,c|e,z|f,z|z,z|z,c|d,b|d,b|e,a|f,a|z, | |
| 126 | + a|f,a|z,c|e,z|e,z|d,c|d,z|e,a|f,b|e,z|d,b|d,c|z,c|d,b|z,a|z,b|f, | |
| 127 | + z|z,c|f,a|d,b|d,c|z,b|e,b|f,z|z,c|f,a|e,a|e,z|f,z|f,a|d,b|z,c|e]; | |
| 128 | + | |
| 129 | +/* eslint-enable comma-spacing */ | |
| 130 | + | |
| 131 | +class DES { | |
| 132 | + constructor(password) { | |
| 133 | + this.keys = []; | |
| 134 | + | |
| 135 | + // Set the key. | |
| 136 | + const pc1m = [], pcr = [], kn = []; | |
| 137 | + | |
| 138 | + for (let j = 0, l = 56; j < 56; ++j, l -= 8) { | |
| 139 | + l += l < -5 ? 65 : l < -3 ? 31 : l < -1 ? 63 : l === 27 ? 35 : 0; // PC1 | |
| 140 | + const m = l & 0x7; | |
| 141 | + pc1m[j] = ((password[l >>> 3] & (1<<m)) !== 0) ? 1: 0; | |
| 142 | + } | |
| 143 | + | |
| 144 | + for (let i = 0; i < 16; ++i) { | |
| 145 | + const m = i << 1; | |
| 146 | + const n = m + 1; | |
| 147 | + kn[m] = kn[n] = 0; | |
| 148 | + for (let o = 28; o < 59; o += 28) { | |
| 149 | + for (let j = o - 28; j < o; ++j) { | |
| 150 | + const l = j + totrot[i]; | |
| 151 | + pcr[j] = l < o ? pc1m[l] : pc1m[l - 28]; | |
| 152 | + } | |
| 153 | + } | |
| 154 | + for (let j = 0; j < 24; ++j) { | |
| 155 | + if (pcr[PC2[j]] !== 0) { | |
| 156 | + kn[m] |= 1 << (23 - j); | |
| 157 | + } | |
| 158 | + if (pcr[PC2[j + 24]] !== 0) { | |
| 159 | + kn[n] |= 1 << (23 - j); | |
| 160 | + } | |
| 161 | + } | |
| 162 | + } | |
| 163 | + | |
| 164 | + // cookey | |
| 165 | + for (let i = 0, rawi = 0, KnLi = 0; i < 16; ++i) { | |
| 166 | + const raw0 = kn[rawi++]; | |
| 167 | + const raw1 = kn[rawi++]; | |
| 168 | + this.keys[KnLi] = (raw0 & 0x00fc0000) << 6; | |
| 169 | + this.keys[KnLi] |= (raw0 & 0x00000fc0) << 10; | |
| 170 | + this.keys[KnLi] |= (raw1 & 0x00fc0000) >>> 10; | |
| 171 | + this.keys[KnLi] |= (raw1 & 0x00000fc0) >>> 6; | |
| 172 | + ++KnLi; | |
| 173 | + this.keys[KnLi] = (raw0 & 0x0003f000) << 12; | |
| 174 | + this.keys[KnLi] |= (raw0 & 0x0000003f) << 16; | |
| 175 | + this.keys[KnLi] |= (raw1 & 0x0003f000) >>> 4; | |
| 176 | + this.keys[KnLi] |= (raw1 & 0x0000003f); | |
| 177 | + ++KnLi; | |
| 178 | + } | |
| 179 | + } | |
| 180 | + | |
| 181 | + // Encrypt 8 bytes of text | |
| 182 | + enc8(text) { | |
| 183 | + const b = text.slice(); | |
| 184 | + let i = 0, l, r, x; // left, right, accumulator | |
| 185 | + | |
| 186 | + // Squash 8 bytes to 2 ints | |
| 187 | + l = b[i++]<<24 | b[i++]<<16 | b[i++]<<8 | b[i++]; | |
| 188 | + r = b[i++]<<24 | b[i++]<<16 | b[i++]<<8 | b[i++]; | |
| 189 | + | |
| 190 | + x = ((l >>> 4) ^ r) & 0x0f0f0f0f; | |
| 191 | + r ^= x; | |
| 192 | + l ^= (x << 4); | |
| 193 | + x = ((l >>> 16) ^ r) & 0x0000ffff; | |
| 194 | + r ^= x; | |
| 195 | + l ^= (x << 16); | |
| 196 | + x = ((r >>> 2) ^ l) & 0x33333333; | |
| 197 | + l ^= x; | |
| 198 | + r ^= (x << 2); | |
| 199 | + x = ((r >>> 8) ^ l) & 0x00ff00ff; | |
| 200 | + l ^= x; | |
| 201 | + r ^= (x << 8); | |
| 202 | + r = (r << 1) | ((r >>> 31) & 1); | |
| 203 | + x = (l ^ r) & 0xaaaaaaaa; | |
| 204 | + l ^= x; | |
| 205 | + r ^= x; | |
| 206 | + l = (l << 1) | ((l >>> 31) & 1); | |
| 207 | + | |
| 208 | + for (let i = 0, keysi = 0; i < 8; ++i) { | |
| 209 | + x = (r << 28) | (r >>> 4); | |
| 210 | + x ^= this.keys[keysi++]; | |
| 211 | + let fval = SP7[x & 0x3f]; | |
| 212 | + fval |= SP5[(x >>> 8) & 0x3f]; | |
| 213 | + fval |= SP3[(x >>> 16) & 0x3f]; | |
| 214 | + fval |= SP1[(x >>> 24) & 0x3f]; | |
| 215 | + x = r ^ this.keys[keysi++]; | |
| 216 | + fval |= SP8[x & 0x3f]; | |
| 217 | + fval |= SP6[(x >>> 8) & 0x3f]; | |
| 218 | + fval |= SP4[(x >>> 16) & 0x3f]; | |
| 219 | + fval |= SP2[(x >>> 24) & 0x3f]; | |
| 220 | + l ^= fval; | |
| 221 | + x = (l << 28) | (l >>> 4); | |
| 222 | + x ^= this.keys[keysi++]; | |
| 223 | + fval = SP7[x & 0x3f]; | |
| 224 | + fval |= SP5[(x >>> 8) & 0x3f]; | |
| 225 | + fval |= SP3[(x >>> 16) & 0x3f]; | |
| 226 | + fval |= SP1[(x >>> 24) & 0x3f]; | |
| 227 | + x = l ^ this.keys[keysi++]; | |
| 228 | + fval |= SP8[x & 0x0000003f]; | |
| 229 | + fval |= SP6[(x >>> 8) & 0x3f]; | |
| 230 | + fval |= SP4[(x >>> 16) & 0x3f]; | |
| 231 | + fval |= SP2[(x >>> 24) & 0x3f]; | |
| 232 | + r ^= fval; | |
| 233 | + } | |
| 234 | + | |
| 235 | + r = (r << 31) | (r >>> 1); | |
| 236 | + x = (l ^ r) & 0xaaaaaaaa; | |
| 237 | + l ^= x; | |
| 238 | + r ^= x; | |
| 239 | + l = (l << 31) | (l >>> 1); | |
| 240 | + x = ((l >>> 8) ^ r) & 0x00ff00ff; | |
| 241 | + r ^= x; | |
| 242 | + l ^= (x << 8); | |
| 243 | + x = ((l >>> 2) ^ r) & 0x33333333; | |
| 244 | + r ^= x; | |
| 245 | + l ^= (x << 2); | |
| 246 | + x = ((r >>> 16) ^ l) & 0x0000ffff; | |
| 247 | + l ^= x; | |
| 248 | + r ^= (x << 16); | |
| 249 | + x = ((r >>> 4) ^ l) & 0x0f0f0f0f; | |
| 250 | + l ^= x; | |
| 251 | + r ^= (x << 4); | |
| 252 | + | |
| 253 | + // Spread ints to bytes | |
| 254 | + x = [r, l]; | |
| 255 | + for (i = 0; i < 8; i++) { | |
| 256 | + b[i] = (x[i>>>2] >>> (8 * (3 - (i % 4)))) % 256; | |
| 257 | + if (b[i] < 0) { b[i] += 256; } // unsigned | |
| 258 | + } | |
| 259 | + return b; | |
| 260 | + } | |
| 261 | +} | |
| 262 | + | |
| 263 | +export class DESECBCipher { | |
| 264 | + constructor() { | |
| 265 | + this._cipher = null; | |
| 266 | + } | |
| 267 | + | |
| 268 | + get algorithm() { | |
| 269 | + return { name: "DES-ECB" }; | |
| 270 | + } | |
| 271 | + | |
| 272 | + static importKey(key, _algorithm, _extractable, _keyUsages) { | |
| 273 | + const cipher = new DESECBCipher; | |
| 274 | + cipher._importKey(key); | |
| 275 | + return cipher; | |
| 276 | + } | |
| 277 | + | |
| 278 | + _importKey(key, _extractable, _keyUsages) { | |
| 279 | + this._cipher = new DES(key); | |
| 280 | + } | |
| 281 | + | |
| 282 | + encrypt(_algorithm, plaintext) { | |
| 283 | + const x = new Uint8Array(plaintext); | |
| 284 | + if (x.length % 8 !== 0 || this._cipher === null) { | |
| 285 | + return null; | |
| 286 | + } | |
| 287 | + const n = x.length / 8; | |
| 288 | + for (let i = 0; i < n; i++) { | |
| 289 | + x.set(this._cipher.enc8(x.slice(i * 8, i * 8 + 8)), i * 8); | |
| 290 | + } | |
| 291 | + return x; | |
| 292 | + } | |
| 293 | +} | |
| 294 | + | |
| 295 | +export class DESCBCCipher { | |
| 296 | + constructor() { | |
| 297 | + this._cipher = null; | |
| 298 | + } | |
| 299 | + | |
| 300 | + get algorithm() { | |
| 301 | + return { name: "DES-CBC" }; | |
| 302 | + } | |
| 303 | + | |
| 304 | + static importKey(key, _algorithm, _extractable, _keyUsages) { | |
| 305 | + const cipher = new DESCBCCipher; | |
| 306 | + cipher._importKey(key); | |
| 307 | + return cipher; | |
| 308 | + } | |
| 309 | + | |
| 310 | + _importKey(key) { | |
| 311 | + this._cipher = new DES(key); | |
| 312 | + } | |
| 313 | + | |
| 314 | + encrypt(algorithm, plaintext) { | |
| 315 | + const x = new Uint8Array(plaintext); | |
| 316 | + let y = new Uint8Array(algorithm.iv); | |
| 317 | + if (x.length % 8 !== 0 || this._cipher === null) { | |
| 318 | + return null; | |
| 319 | + } | |
| 320 | + const n = x.length / 8; | |
| 321 | + for (let i = 0; i < n; i++) { | |
| 322 | + for (let j = 0; j < 8; j++) { | |
| 323 | + y[j] ^= plaintext[i * 8 + j]; | |
| 324 | + } | |
| 325 | + y = this._cipher.enc8(y); | |
| 326 | + x.set(y, i * 8); | |
| 327 | + } | |
| 328 | + return x; | |
| 329 | + } | |
| 330 | +} | |
added
public/vendor/novnc/core/crypto/dh.js
+55 −0
@@ -0,0 +1,55 @@ | ||
| 1 | +import { modPow, bigIntToU8Array, u8ArrayToBigInt } from "./bigint.js"; | |
| 2 | + | |
| 3 | +class DHPublicKey { | |
| 4 | + constructor(key) { | |
| 5 | + this._key = key; | |
| 6 | + } | |
| 7 | + | |
| 8 | + get algorithm() { | |
| 9 | + return { name: "DH" }; | |
| 10 | + } | |
| 11 | + | |
| 12 | + exportKey() { | |
| 13 | + return this._key; | |
| 14 | + } | |
| 15 | +} | |
| 16 | + | |
| 17 | +export class DHCipher { | |
| 18 | + constructor() { | |
| 19 | + this._g = null; | |
| 20 | + this._p = null; | |
| 21 | + this._gBigInt = null; | |
| 22 | + this._pBigInt = null; | |
| 23 | + this._privateKey = null; | |
| 24 | + } | |
| 25 | + | |
| 26 | + get algorithm() { | |
| 27 | + return { name: "DH" }; | |
| 28 | + } | |
| 29 | + | |
| 30 | + static generateKey(algorithm, _extractable) { | |
| 31 | + const cipher = new DHCipher; | |
| 32 | + cipher._generateKey(algorithm); | |
| 33 | + return { privateKey: cipher, publicKey: new DHPublicKey(cipher._publicKey) }; | |
| 34 | + } | |
| 35 | + | |
| 36 | + _generateKey(algorithm) { | |
| 37 | + const g = algorithm.g; | |
| 38 | + const p = algorithm.p; | |
| 39 | + this._keyBytes = p.length; | |
| 40 | + this._gBigInt = u8ArrayToBigInt(g); | |
| 41 | + this._pBigInt = u8ArrayToBigInt(p); | |
| 42 | + this._privateKey = window.crypto.getRandomValues(new Uint8Array(this._keyBytes)); | |
| 43 | + this._privateKeyBigInt = u8ArrayToBigInt(this._privateKey); | |
| 44 | + this._publicKey = bigIntToU8Array(modPow( | |
| 45 | + this._gBigInt, this._privateKeyBigInt, this._pBigInt), this._keyBytes); | |
| 46 | + } | |
| 47 | + | |
| 48 | + deriveBits(algorithm, length) { | |
| 49 | + const bytes = Math.ceil(length / 8); | |
| 50 | + const pkey = new Uint8Array(algorithm.public); | |
| 51 | + const len = bytes > this._keyBytes ? bytes : this._keyBytes; | |
| 52 | + const secret = modPow(u8ArrayToBigInt(pkey), this._privateKeyBigInt, this._pBigInt); | |
| 53 | + return bigIntToU8Array(secret, len).slice(0, len); | |
| 54 | + } | |
| 55 | +} | |
added
public/vendor/novnc/core/crypto/md5.js
+82 −0
@@ -0,0 +1,82 @@ | ||
| 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 an array of bytes, returns an array of bytes | |
| 11 | + */ | |
| 12 | + | |
| 13 | +export async function MD5(d) { | |
| 14 | + let s = ""; | |
| 15 | + for (let i = 0; i < d.length; i++) { | |
| 16 | + s += String.fromCharCode(d[i]); | |
| 17 | + } | |
| 18 | + return M(V(Y(X(s), 8 * s.length))); | |
| 19 | +} | |
| 20 | + | |
| 21 | +function M(d) { | |
| 22 | + let f = new Uint8Array(d.length); | |
| 23 | + for (let i=0;i<d.length;i++) { | |
| 24 | + f[i] = d.charCodeAt(i); | |
| 25 | + } | |
| 26 | + return f; | |
| 27 | +} | |
| 28 | + | |
| 29 | +function X(d) { | |
| 30 | + let r = Array(d.length >> 2); | |
| 31 | + for (let m = 0; m < r.length; m++) r[m] = 0; | |
| 32 | + for (let m = 0; m < 8 * d.length; m += 8) r[m >> 5] |= (255 & d.charCodeAt(m / 8)) << m % 32; | |
| 33 | + return r; | |
| 34 | +} | |
| 35 | + | |
| 36 | +function V(d) { | |
| 37 | + let r = ""; | |
| 38 | + for (let m = 0; m < 32 * d.length; m += 8) r += String.fromCharCode(d[m >> 5] >>> m % 32 & 255); | |
| 39 | + return r; | |
| 40 | +} | |
| 41 | + | |
| 42 | +function Y(d, g) { | |
| 43 | + d[g >> 5] |= 128 << g % 32, d[14 + (g + 64 >>> 9 << 4)] = g; | |
| 44 | + let m = 1732584193, f = -271733879, r = -1732584194, i = 271733878; | |
| 45 | + for (let n = 0; n < d.length; n += 16) { | |
| 46 | + let h = m, | |
| 47 | + t = f, | |
| 48 | + g = r, | |
| 49 | + e = i; | |
| 50 | + 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); | |
| 51 | + } | |
| 52 | + return Array(m, f, r, i); | |
| 53 | +} | |
| 54 | + | |
| 55 | +function cmn(d, g, m, f, r, i) { | |
| 56 | + return add(rol(add(add(g, d), add(f, i)), r), m); | |
| 57 | +} | |
| 58 | + | |
| 59 | +function ff(d, g, m, f, r, i, n) { | |
| 60 | + return cmn(g & m | ~g & f, d, g, r, i, n); | |
| 61 | +} | |
| 62 | + | |
| 63 | +function gg(d, g, m, f, r, i, n) { | |
| 64 | + return cmn(g & f | m & ~f, d, g, r, i, n); | |
| 65 | +} | |
| 66 | + | |
| 67 | +function hh(d, g, m, f, r, i, n) { | |
| 68 | + return cmn(g ^ m ^ f, d, g, r, i, n); | |
| 69 | +} | |
| 70 | + | |
| 71 | +function ii(d, g, m, f, r, i, n) { | |
| 72 | + return cmn(m ^ (g | ~f), d, g, r, i, n); | |
| 73 | +} | |
| 74 | + | |
| 75 | +function add(d, g) { | |
| 76 | + let m = (65535 & d) + (65535 & g); | |
| 77 | + return (d >> 16) + (g >> 16) + (m >> 16) << 16 | 65535 & m; | |
| 78 | +} | |
| 79 | + | |
| 80 | +function rol(d, g) { | |
| 81 | + return d << g | d >>> 32 - g; | |
| 82 | +} | |
added
public/vendor/novnc/core/crypto/rsa.js
+132 −0
@@ -0,0 +1,132 @@ | ||
| 1 | +import Base64 from "../base64.js"; | |
| 2 | +import { modPow, bigIntToU8Array, u8ArrayToBigInt } from "./bigint.js"; | |
| 3 | + | |
| 4 | +export class RSACipher { | |
| 5 | + constructor() { | |
| 6 | + this._keyLength = 0; | |
| 7 | + this._keyBytes = 0; | |
| 8 | + this._n = null; | |
| 9 | + this._e = null; | |
| 10 | + this._d = null; | |
| 11 | + this._nBigInt = null; | |
| 12 | + this._eBigInt = null; | |
| 13 | + this._dBigInt = null; | |
| 14 | + this._extractable = false; | |
| 15 | + } | |
| 16 | + | |
| 17 | + get algorithm() { | |
| 18 | + return { name: "RSA-PKCS1-v1_5" }; | |
| 19 | + } | |
| 20 | + | |
| 21 | + _base64urlDecode(data) { | |
| 22 | + data = data.replace(/-/g, "+").replace(/_/g, "/"); | |
| 23 | + data = data.padEnd(Math.ceil(data.length / 4) * 4, "="); | |
| 24 | + return Base64.decode(data); | |
| 25 | + } | |
| 26 | + | |
| 27 | + _padArray(arr, length) { | |
| 28 | + const res = new Uint8Array(length); | |
| 29 | + res.set(arr, length - arr.length); | |
| 30 | + return res; | |
| 31 | + } | |
| 32 | + | |
| 33 | + static async generateKey(algorithm, extractable, _keyUsages) { | |
| 34 | + const cipher = new RSACipher; | |
| 35 | + await cipher._generateKey(algorithm, extractable); | |
| 36 | + return { privateKey: cipher }; | |
| 37 | + } | |
| 38 | + | |
| 39 | + async _generateKey(algorithm, extractable) { | |
| 40 | + this._keyLength = algorithm.modulusLength; | |
| 41 | + this._keyBytes = Math.ceil(this._keyLength / 8); | |
| 42 | + const key = await window.crypto.subtle.generateKey( | |
| 43 | + { | |
| 44 | + name: "RSA-OAEP", | |
| 45 | + modulusLength: algorithm.modulusLength, | |
| 46 | + publicExponent: algorithm.publicExponent, | |
| 47 | + hash: {name: "SHA-256"}, | |
| 48 | + }, | |
| 49 | + true, ["encrypt", "decrypt"]); | |
| 50 | + const privateKey = await window.crypto.subtle.exportKey("jwk", key.privateKey); | |
| 51 | + this._n = this._padArray(this._base64urlDecode(privateKey.n), this._keyBytes); | |
| 52 | + this._nBigInt = u8ArrayToBigInt(this._n); | |
| 53 | + this._e = this._padArray(this._base64urlDecode(privateKey.e), this._keyBytes); | |
| 54 | + this._eBigInt = u8ArrayToBigInt(this._e); | |
| 55 | + this._d = this._padArray(this._base64urlDecode(privateKey.d), this._keyBytes); | |
| 56 | + this._dBigInt = u8ArrayToBigInt(this._d); | |
| 57 | + this._extractable = extractable; | |
| 58 | + } | |
| 59 | + | |
| 60 | + static async importKey(key, _algorithm, extractable, keyUsages) { | |
| 61 | + if (keyUsages.length !== 1 || keyUsages[0] !== "encrypt") { | |
| 62 | + throw new Error("only support importing RSA public key"); | |
| 63 | + } | |
| 64 | + const cipher = new RSACipher; | |
| 65 | + await cipher._importKey(key, extractable); | |
| 66 | + return cipher; | |
| 67 | + } | |
| 68 | + | |
| 69 | + async _importKey(key, extractable) { | |
| 70 | + const n = key.n; | |
| 71 | + const e = key.e; | |
| 72 | + if (n.length !== e.length) { | |
| 73 | + throw new Error("the sizes of modulus and public exponent do not match"); | |
| 74 | + } | |
| 75 | + this._keyBytes = n.length; | |
| 76 | + this._keyLength = this._keyBytes * 8; | |
| 77 | + this._n = new Uint8Array(this._keyBytes); | |
| 78 | + this._e = new Uint8Array(this._keyBytes); | |
| 79 | + this._n.set(n); | |
| 80 | + this._e.set(e); | |
| 81 | + this._nBigInt = u8ArrayToBigInt(this._n); | |
| 82 | + this._eBigInt = u8ArrayToBigInt(this._e); | |
| 83 | + this._extractable = extractable; | |
| 84 | + } | |
| 85 | + | |
| 86 | + async encrypt(_algorithm, message) { | |
| 87 | + if (message.length > this._keyBytes - 11) { | |
| 88 | + return null; | |
| 89 | + } | |
| 90 | + const ps = new Uint8Array(this._keyBytes - message.length - 3); | |
| 91 | + window.crypto.getRandomValues(ps); | |
| 92 | + for (let i = 0; i < ps.length; i++) { | |
| 93 | + ps[i] = Math.floor(ps[i] * 254 / 255 + 1); | |
| 94 | + } | |
| 95 | + const em = new Uint8Array(this._keyBytes); | |
| 96 | + em[1] = 0x02; | |
| 97 | + em.set(ps, 2); | |
| 98 | + em.set(message, ps.length + 3); | |
| 99 | + const emBigInt = u8ArrayToBigInt(em); | |
| 100 | + const c = modPow(emBigInt, this._eBigInt, this._nBigInt); | |
| 101 | + return bigIntToU8Array(c, this._keyBytes); | |
| 102 | + } | |
| 103 | + | |
| 104 | + async decrypt(_algorithm, message) { | |
| 105 | + if (message.length !== this._keyBytes) { | |
| 106 | + return null; | |
| 107 | + } | |
| 108 | + const msgBigInt = u8ArrayToBigInt(message); | |
| 109 | + const emBigInt = modPow(msgBigInt, this._dBigInt, this._nBigInt); | |
| 110 | + const em = bigIntToU8Array(emBigInt, this._keyBytes); | |
| 111 | + if (em[0] !== 0x00 || em[1] !== 0x02) { | |
| 112 | + return null; | |
| 113 | + } | |
| 114 | + let i = 2; | |
| 115 | + for (; i < em.length; i++) { | |
| 116 | + if (em[i] === 0x00) { | |
| 117 | + break; | |
| 118 | + } | |
| 119 | + } | |
| 120 | + if (i === em.length) { | |
| 121 | + return null; | |
| 122 | + } | |
| 123 | + return em.slice(i + 1, em.length); | |
| 124 | + } | |
| 125 | + | |
| 126 | + async exportKey() { | |
| 127 | + if (!this._extractable) { | |
| 128 | + throw new Error("key is not extractable"); | |
| 129 | + } | |
| 130 | + return { n: this._n, e: this._e, d: this._d }; | |
| 131 | + } | |
| 132 | +} | |
added
public/vendor/novnc/core/decoders/copyrect.js
+27 −0
@@ -0,0 +1,27 @@ | ||
| 1 | +/* | |
| 2 | + * noVNC: HTML5 VNC client | |
| 3 | + * Copyright (C) 2019 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 | +export default class CopyRectDecoder { | |
| 11 | + decodeRect(x, y, width, height, sock, display, depth) { | |
| 12 | + if (sock.rQwait("COPYRECT", 4)) { | |
| 13 | + return false; | |
| 14 | + } | |
| 15 | + | |
| 16 | + let deltaX = sock.rQshift16(); | |
| 17 | + let deltaY = sock.rQshift16(); | |
| 18 | + | |
| 19 | + if ((width === 0) || (height === 0)) { | |
| 20 | + return true; | |
| 21 | + } | |
| 22 | + | |
| 23 | + display.copyImage(deltaX, deltaY, x, y, width, height); | |
| 24 | + | |
| 25 | + return true; | |
| 26 | + } | |
| 27 | +} | |
added
public/vendor/novnc/core/decoders/h264.js
+321 −0
@@ -0,0 +1,321 @@ | ||
| 1 | +/* | |
| 2 | + * noVNC: HTML5 VNC client | |
| 3 | + * Copyright (C) 2024 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 | +import * as Log from '../util/logging.js'; | |
| 11 | + | |
| 12 | +export class H264Parser { | |
| 13 | + constructor(data) { | |
| 14 | + this._data = data; | |
| 15 | + this._index = 0; | |
| 16 | + this.profileIdc = null; | |
| 17 | + this.constraintSet = null; | |
| 18 | + this.levelIdc = null; | |
| 19 | + } | |
| 20 | + | |
| 21 | + _getStartSequenceLen(index) { | |
| 22 | + let data = this._data; | |
| 23 | + if (data[index + 0] == 0 && data[index + 1] == 0 && data[index + 2] == 0 && data[index + 3] == 1) { | |
| 24 | + return 4; | |
| 25 | + } | |
| 26 | + if (data[index + 0] == 0 && data[index + 1] == 0 && data[index + 2] == 1) { | |
| 27 | + return 3; | |
| 28 | + } | |
| 29 | + return 0; | |
| 30 | + } | |
| 31 | + | |
| 32 | + _indexOfNextNalUnit(index) { | |
| 33 | + let data = this._data; | |
| 34 | + for (let i = index; i < data.length; ++i) { | |
| 35 | + if (this._getStartSequenceLen(i) != 0) { | |
| 36 | + return i; | |
| 37 | + } | |
| 38 | + } | |
| 39 | + return -1; | |
| 40 | + } | |
| 41 | + | |
| 42 | + _parseSps(index) { | |
| 43 | + this.profileIdc = this._data[index]; | |
| 44 | + this.constraintSet = this._data[index + 1]; | |
| 45 | + this.levelIdc = this._data[index + 2]; | |
| 46 | + } | |
| 47 | + | |
| 48 | + _parseNalUnit(index) { | |
| 49 | + const firstByte = this._data[index]; | |
| 50 | + if (firstByte & 0x80) { | |
| 51 | + throw new Error('H264 parsing sanity check failed, forbidden zero bit is set'); | |
| 52 | + } | |
| 53 | + const unitType = firstByte & 0x1f; | |
| 54 | + | |
| 55 | + switch (unitType) { | |
| 56 | + case 1: // coded slice, non-idr | |
| 57 | + return { slice: true }; | |
| 58 | + case 5: // coded slice, idr | |
| 59 | + return { slice: true, key: true }; | |
| 60 | + case 6: // sei | |
| 61 | + return {}; | |
| 62 | + case 7: // sps | |
| 63 | + this._parseSps(index + 1); | |
| 64 | + return {}; | |
| 65 | + case 8: // pps | |
| 66 | + return {}; | |
| 67 | + default: | |
| 68 | + Log.Warn("Unhandled unit type: ", unitType); | |
| 69 | + break; | |
| 70 | + } | |
| 71 | + return {}; | |
| 72 | + } | |
| 73 | + | |
| 74 | + parse() { | |
| 75 | + const startIndex = this._index; | |
| 76 | + let isKey = false; | |
| 77 | + | |
| 78 | + while (this._index < this._data.length) { | |
| 79 | + const startSequenceLen = this._getStartSequenceLen(this._index); | |
| 80 | + if (startSequenceLen == 0) { | |
| 81 | + throw new Error('Invalid start sequence in bit stream'); | |
| 82 | + } | |
| 83 | + | |
| 84 | + const { slice, key } = this._parseNalUnit(this._index + startSequenceLen); | |
| 85 | + | |
| 86 | + let nextIndex = this._indexOfNextNalUnit(this._index + startSequenceLen); | |
| 87 | + if (nextIndex == -1) { | |
| 88 | + this._index = this._data.length; | |
| 89 | + } else { | |
| 90 | + this._index = nextIndex; | |
| 91 | + } | |
| 92 | + | |
| 93 | + if (key) { | |
| 94 | + isKey = true; | |
| 95 | + } | |
| 96 | + if (slice) { | |
| 97 | + break; | |
| 98 | + } | |
| 99 | + } | |
| 100 | + | |
| 101 | + if (startIndex === this._index) { | |
| 102 | + return null; | |
| 103 | + } | |
| 104 | + | |
| 105 | + return { | |
| 106 | + frame: this._data.subarray(startIndex, this._index), | |
| 107 | + key: isKey, | |
| 108 | + }; | |
| 109 | + } | |
| 110 | +} | |
| 111 | + | |
| 112 | +export class H264Context { | |
| 113 | + constructor(width, height) { | |
| 114 | + this.lastUsed = 0; | |
| 115 | + this._width = width; | |
| 116 | + this._height = height; | |
| 117 | + this._profileIdc = null; | |
| 118 | + this._constraintSet = null; | |
| 119 | + this._levelIdc = null; | |
| 120 | + this._decoder = null; | |
| 121 | + this._pendingFrames = []; | |
| 122 | + } | |
| 123 | + | |
| 124 | + _handleFrame(frame) { | |
| 125 | + let pending = this._pendingFrames.shift(); | |
| 126 | + if (pending === undefined) { | |
| 127 | + throw new Error("Pending frame queue empty when receiving frame from decoder"); | |
| 128 | + } | |
| 129 | + | |
| 130 | + if (pending.timestamp != frame.timestamp) { | |
| 131 | + throw new Error("Video frame timestamp mismatch. Expected " + | |
| 132 | + frame.timestamp + " but but got " + pending.timestamp); | |
| 133 | + } | |
| 134 | + | |
| 135 | + pending.frame = frame; | |
| 136 | + pending.ready = true; | |
| 137 | + pending.resolve(); | |
| 138 | + | |
| 139 | + if (!pending.keep) { | |
| 140 | + frame.close(); | |
| 141 | + } | |
| 142 | + } | |
| 143 | + | |
| 144 | + _handleError(e) { | |
| 145 | + throw new Error("Failed to decode frame: " + e.message); | |
| 146 | + } | |
| 147 | + | |
| 148 | + _configureDecoder(profileIdc, constraintSet, levelIdc) { | |
| 149 | + if (this._decoder === null || this._decoder.state === 'closed') { | |
| 150 | + this._decoder = new VideoDecoder({ | |
| 151 | + output: frame => this._handleFrame(frame), | |
| 152 | + error: e => this._handleError(e), | |
| 153 | + }); | |
| 154 | + } | |
| 155 | + const codec = 'avc1.' + | |
| 156 | + profileIdc.toString(16).padStart(2, '0') + | |
| 157 | + constraintSet.toString(16).padStart(2, '0') + | |
| 158 | + levelIdc.toString(16).padStart(2, '0'); | |
| 159 | + this._decoder.configure({ | |
| 160 | + codec: codec, | |
| 161 | + codedWidth: this._width, | |
| 162 | + codedHeight: this._height, | |
| 163 | + optimizeForLatency: true, | |
| 164 | + }); | |
| 165 | + } | |
| 166 | + | |
| 167 | + _preparePendingFrame(timestamp) { | |
| 168 | + let pending = { | |
| 169 | + timestamp: timestamp, | |
| 170 | + promise: null, | |
| 171 | + resolve: null, | |
| 172 | + frame: null, | |
| 173 | + ready: false, | |
| 174 | + keep: false, | |
| 175 | + }; | |
| 176 | + pending.promise = new Promise((resolve) => { | |
| 177 | + pending.resolve = resolve; | |
| 178 | + }); | |
| 179 | + this._pendingFrames.push(pending); | |
| 180 | + | |
| 181 | + return pending; | |
| 182 | + } | |
| 183 | + | |
| 184 | + decode(payload) { | |
| 185 | + let parser = new H264Parser(payload); | |
| 186 | + let result = null; | |
| 187 | + | |
| 188 | + // Ideally, this timestamp should come from the server, but we'll just | |
| 189 | + // approximate it instead. | |
| 190 | + let timestamp = Math.round(window.performance.now() * 1e3); | |
| 191 | + | |
| 192 | + while (true) { | |
| 193 | + let encodedFrame = parser.parse(); | |
| 194 | + if (encodedFrame === null) { | |
| 195 | + break; | |
| 196 | + } | |
| 197 | + | |
| 198 | + if (parser.profileIdc !== null) { | |
| 199 | + self._profileIdc = parser.profileIdc; | |
| 200 | + self._constraintSet = parser.constraintSet; | |
| 201 | + self._levelIdc = parser.levelIdc; | |
| 202 | + } | |
| 203 | + | |
| 204 | + if (this._decoder === null || this._decoder.state !== 'configured') { | |
| 205 | + if (!encodedFrame.key) { | |
| 206 | + Log.Warn("Missing key frame. Can't decode until one arrives"); | |
| 207 | + continue; | |
| 208 | + } | |
| 209 | + if (self._profileIdc === null) { | |
| 210 | + Log.Warn('Cannot config decoder. Have not received SPS and PPS yet.'); | |
| 211 | + continue; | |
| 212 | + } | |
| 213 | + this._configureDecoder(self._profileIdc, self._constraintSet, | |
| 214 | + self._levelIdc); | |
| 215 | + } | |
| 216 | + | |
| 217 | + result = this._preparePendingFrame(timestamp); | |
| 218 | + | |
| 219 | + const chunk = new EncodedVideoChunk({ | |
| 220 | + timestamp: timestamp, | |
| 221 | + type: encodedFrame.key ? 'key' : 'delta', | |
| 222 | + data: encodedFrame.frame, | |
| 223 | + }); | |
| 224 | + | |
| 225 | + try { | |
| 226 | + this._decoder.decode(chunk); | |
| 227 | + } catch (e) { | |
| 228 | + Log.Warn("Failed to decode:", e); | |
| 229 | + } | |
| 230 | + } | |
| 231 | + | |
| 232 | + // We only keep last frame of each payload | |
| 233 | + if (result !== null) { | |
| 234 | + result.keep = true; | |
| 235 | + } | |
| 236 | + | |
| 237 | + return result; | |
| 238 | + } | |
| 239 | +} | |
| 240 | + | |
| 241 | +export default class H264Decoder { | |
| 242 | + constructor() { | |
| 243 | + this._tick = 0; | |
| 244 | + this._contexts = {}; | |
| 245 | + } | |
| 246 | + | |
| 247 | + _contextId(x, y, width, height) { | |
| 248 | + return [x, y, width, height].join(','); | |
| 249 | + } | |
| 250 | + | |
| 251 | + _findOldestContextId() { | |
| 252 | + let oldestTick = Number.MAX_VALUE; | |
| 253 | + let oldestKey = undefined; | |
| 254 | + for (const [key, value] of Object.entries(this._contexts)) { | |
| 255 | + if (value.lastUsed < oldestTick) { | |
| 256 | + oldestTick = value.lastUsed; | |
| 257 | + oldestKey = key; | |
| 258 | + } | |
| 259 | + } | |
| 260 | + return oldestKey; | |
| 261 | + } | |
| 262 | + | |
| 263 | + _createContext(x, y, width, height) { | |
| 264 | + const maxContexts = 64; | |
| 265 | + if (Object.keys(this._contexts).length >= maxContexts) { | |
| 266 | + let oldestContextId = this._findOldestContextId(); | |
| 267 | + delete this._contexts[oldestContextId]; | |
| 268 | + } | |
| 269 | + let context = new H264Context(width, height); | |
| 270 | + this._contexts[this._contextId(x, y, width, height)] = context; | |
| 271 | + return context; | |
| 272 | + } | |
| 273 | + | |
| 274 | + _getContext(x, y, width, height) { | |
| 275 | + let context = this._contexts[this._contextId(x, y, width, height)]; | |
| 276 | + return context !== undefined ? context : this._createContext(x, y, width, height); | |
| 277 | + } | |
| 278 | + | |
| 279 | + _resetContext(x, y, width, height) { | |
| 280 | + delete this._contexts[this._contextId(x, y, width, height)]; | |
| 281 | + } | |
| 282 | + | |
| 283 | + _resetAllContexts() { | |
| 284 | + this._contexts = {}; | |
| 285 | + } | |
| 286 | + | |
| 287 | + decodeRect(x, y, width, height, sock, display, depth) { | |
| 288 | + const resetContextFlag = 1; | |
| 289 | + const resetAllContextsFlag = 2; | |
| 290 | + | |
| 291 | + if (sock.rQwait("h264 header", 8)) { | |
| 292 | + return false; | |
| 293 | + } | |
| 294 | + | |
| 295 | + const length = sock.rQshift32(); | |
| 296 | + const flags = sock.rQshift32(); | |
| 297 | + | |
| 298 | + if (sock.rQwait("h264 payload", length, 8)) { | |
| 299 | + return false; | |
| 300 | + } | |
| 301 | + | |
| 302 | + if (flags & resetAllContextsFlag) { | |
| 303 | + this._resetAllContexts(); | |
| 304 | + } else if (flags & resetContextFlag) { | |
| 305 | + this._resetContext(x, y, width, height); | |
| 306 | + } | |
| 307 | + | |
| 308 | + let context = this._getContext(x, y, width, height); | |
| 309 | + context.lastUsed = this._tick++; | |
| 310 | + | |
| 311 | + if (length !== 0) { | |
| 312 | + let payload = sock.rQshiftBytes(length, false); | |
| 313 | + let frame = context.decode(payload); | |
| 314 | + if (frame !== null) { | |
| 315 | + display.videoFrame(x, y, width, height, frame); | |
| 316 | + } | |
| 317 | + } | |
| 318 | + | |
| 319 | + return true; | |
| 320 | + } | |
| 321 | +} | |
added
public/vendor/novnc/core/decoders/hextile.js
+181 −0
@@ -0,0 +1,181 @@ | ||
| 1 | +/* | |
| 2 | + * noVNC: HTML5 VNC client | |
| 3 | + * Copyright (C) 2019 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 | +import * as Log from '../util/logging.js'; | |
| 11 | + | |
| 12 | +export default class HextileDecoder { | |
| 13 | + constructor() { | |
| 14 | + this._tiles = 0; | |
| 15 | + this._lastsubencoding = 0; | |
| 16 | + this._tileBuffer = new Uint8Array(16 * 16 * 4); | |
| 17 | + } | |
| 18 | + | |
| 19 | + decodeRect(x, y, width, height, sock, display, depth) { | |
| 20 | + if (this._tiles === 0) { | |
| 21 | + this._tilesX = Math.ceil(width / 16); | |
| 22 | + this._tilesY = Math.ceil(height / 16); | |
| 23 | + this._totalTiles = this._tilesX * this._tilesY; | |
| 24 | + this._tiles = this._totalTiles; | |
| 25 | + } | |
| 26 | + | |
| 27 | + while (this._tiles > 0) { | |
| 28 | + let bytes = 1; | |
| 29 | + | |
| 30 | + if (sock.rQwait("HEXTILE", bytes)) { | |
| 31 | + return false; | |
| 32 | + } | |
| 33 | + | |
| 34 | + let subencoding = sock.rQpeek8(); | |
| 35 | + if (subencoding > 30) { // Raw | |
| 36 | + throw new Error("Illegal hextile subencoding (subencoding: " + | |
| 37 | + subencoding + ")"); | |
| 38 | + } | |
| 39 | + | |
| 40 | + const currTile = this._totalTiles - this._tiles; | |
| 41 | + const tileX = currTile % this._tilesX; | |
| 42 | + const tileY = Math.floor(currTile / this._tilesX); | |
| 43 | + const tx = x + tileX * 16; | |
| 44 | + const ty = y + tileY * 16; | |
| 45 | + const tw = Math.min(16, (x + width) - tx); | |
| 46 | + const th = Math.min(16, (y + height) - ty); | |
| 47 | + | |
| 48 | + // Figure out how much we are expecting | |
| 49 | + if (subencoding & 0x01) { // Raw | |
| 50 | + bytes += tw * th * 4; | |
| 51 | + } else { | |
| 52 | + if (subencoding & 0x02) { // Background | |
| 53 | + bytes += 4; | |
| 54 | + } | |
| 55 | + if (subencoding & 0x04) { // Foreground | |
| 56 | + bytes += 4; | |
| 57 | + } | |
| 58 | + if (subencoding & 0x08) { // AnySubrects | |
| 59 | + bytes++; // Since we aren't shifting it off | |
| 60 | + | |
| 61 | + if (sock.rQwait("HEXTILE", bytes)) { | |
| 62 | + return false; | |
| 63 | + } | |
| 64 | + | |
| 65 | + let subrects = sock.rQpeekBytes(bytes).at(-1); | |
| 66 | + if (subencoding & 0x10) { // SubrectsColoured | |
| 67 | + bytes += subrects * (4 + 2); | |
| 68 | + } else { | |
| 69 | + bytes += subrects * 2; | |
| 70 | + } | |
| 71 | + } | |
| 72 | + } | |
| 73 | + | |
| 74 | + if (sock.rQwait("HEXTILE", bytes)) { | |
| 75 | + return false; | |
| 76 | + } | |
| 77 | + | |
| 78 | + // We know the encoding and have a whole tile | |
| 79 | + sock.rQshift8(); | |
| 80 | + if (subencoding === 0) { | |
| 81 | + if (this._lastsubencoding & 0x01) { | |
| 82 | + // Weird: ignore blanks are RAW | |
| 83 | + Log.Debug(" Ignoring blank after RAW"); | |
| 84 | + } else { | |
| 85 | + display.fillRect(tx, ty, tw, th, this._background); | |
| 86 | + } | |
| 87 | + } else if (subencoding & 0x01) { // Raw | |
| 88 | + let pixels = tw * th; | |
| 89 | + let data = sock.rQshiftBytes(pixels * 4, false); | |
| 90 | + // Max sure the image is fully opaque | |
| 91 | + for (let i = 0;i < pixels;i++) { | |
| 92 | + data[i * 4 + 3] = 255; | |
| 93 | + } | |
| 94 | + display.blitImage(tx, ty, tw, th, data, 0); | |
| 95 | + } else { | |
| 96 | + if (subencoding & 0x02) { // Background | |
| 97 | + this._background = new Uint8Array(sock.rQshiftBytes(4)); | |
| 98 | + } | |
| 99 | + if (subencoding & 0x04) { // Foreground | |
| 100 | + this._foreground = new Uint8Array(sock.rQshiftBytes(4)); | |
| 101 | + } | |
| 102 | + | |
| 103 | + this._startTile(tx, ty, tw, th, this._background); | |
| 104 | + if (subencoding & 0x08) { // AnySubrects | |
| 105 | + let subrects = sock.rQshift8(); | |
| 106 | + | |
| 107 | + for (let s = 0; s < subrects; s++) { | |
| 108 | + let color; | |
| 109 | + if (subencoding & 0x10) { // SubrectsColoured | |
| 110 | + color = sock.rQshiftBytes(4); | |
| 111 | + } else { | |
| 112 | + color = this._foreground; | |
| 113 | + } | |
| 114 | + const xy = sock.rQshift8(); | |
| 115 | + const sx = (xy >> 4); | |
| 116 | + const sy = (xy & 0x0f); | |
| 117 | + | |
| 118 | + const wh = sock.rQshift8(); | |
| 119 | + const sw = (wh >> 4) + 1; | |
| 120 | + const sh = (wh & 0x0f) + 1; | |
| 121 | + | |
| 122 | + this._subTile(sx, sy, sw, sh, color); | |
| 123 | + } | |
| 124 | + } | |
| 125 | + this._finishTile(display); | |
| 126 | + } | |
| 127 | + this._lastsubencoding = subencoding; | |
| 128 | + this._tiles--; | |
| 129 | + } | |
| 130 | + | |
| 131 | + return true; | |
| 132 | + } | |
| 133 | + | |
| 134 | + // start updating a tile | |
| 135 | + _startTile(x, y, width, height, color) { | |
| 136 | + this._tileX = x; | |
| 137 | + this._tileY = y; | |
| 138 | + this._tileW = width; | |
| 139 | + this._tileH = height; | |
| 140 | + | |
| 141 | + const red = color[0]; | |
| 142 | + const green = color[1]; | |
| 143 | + const blue = color[2]; | |
| 144 | + | |
| 145 | + const data = this._tileBuffer; | |
| 146 | + for (let i = 0; i < width * height * 4; i += 4) { | |
| 147 | + data[i] = red; | |
| 148 | + data[i + 1] = green; | |
| 149 | + data[i + 2] = blue; | |
| 150 | + data[i + 3] = 255; | |
| 151 | + } | |
| 152 | + } | |
| 153 | + | |
| 154 | + // update sub-rectangle of the current tile | |
| 155 | + _subTile(x, y, w, h, color) { | |
| 156 | + const red = color[0]; | |
| 157 | + const green = color[1]; | |
| 158 | + const blue = color[2]; | |
| 159 | + const xend = x + w; | |
| 160 | + const yend = y + h; | |
| 161 | + | |
| 162 | + const data = this._tileBuffer; | |
| 163 | + const width = this._tileW; | |
| 164 | + for (let j = y; j < yend; j++) { | |
| 165 | + for (let i = x; i < xend; i++) { | |
| 166 | + const p = (i + (j * width)) * 4; | |
| 167 | + data[p] = red; | |
| 168 | + data[p + 1] = green; | |
| 169 | + data[p + 2] = blue; | |
| 170 | + data[p + 3] = 255; | |
| 171 | + } | |
| 172 | + } | |
| 173 | + } | |
| 174 | + | |
| 175 | + // draw the current tile to the screen | |
| 176 | + _finishTile(display) { | |
| 177 | + display.blitImage(this._tileX, this._tileY, | |
| 178 | + this._tileW, this._tileH, | |
| 179 | + this._tileBuffer, 0); | |
| 180 | + } | |
| 181 | +} | |
added
public/vendor/novnc/core/decoders/jpeg.js
+146 −0
Large diff (146 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/decoders/raw.js
+59 −0
Large diff (59 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/decoders/rre.js
+44 −0
Large diff (44 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/decoders/tight.js
+393 −0
Large diff (393 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/decoders/tightpng.js
+27 −0
Large diff (27 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/decoders/zlib.js
+51 −0
Large diff (51 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/decoders/zrle.js
+185 −0
Large diff (185 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/deflator.js
+84 −0
Large diff (84 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/display.js
+575 −0
Large diff (575 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/encodings.js
+54 −0
Large diff (54 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/inflator.js
+65 −0
Large diff (65 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/input/domkeytable.js
+311 −0
Large diff (311 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/input/fixedkeys.js
+129 −0
Large diff (129 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/input/gesturehandler.js
+567 −0
Large diff (567 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/input/keyboard.js
+294 −0
Large diff (294 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/input/keysym.js
+616 −0
Large diff (616 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/input/keysymdef.js
+688 −0
Large diff (688 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/input/util.js
+191 −0
Large diff (191 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/input/vkeys.js
+116 −0
Large diff (116 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/input/xtscancodes.js
+173 −0
Large diff (173 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/ra2.js
+312 −0
Large diff (312 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/rfb.js
+3415 −0
Large diff (3,415 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/util/browser.js
+233 −0
Large diff (233 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/util/cursor.js
+249 −0
Large diff (249 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/util/element.js
+32 −0
Large diff (32 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/util/events.js
+138 −0
Large diff (138 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/util/eventtarget.js
+35 −0
Large diff (35 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/util/int.js
+15 −0
Large diff (15 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/util/logging.js
+56 −0
Large diff (56 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/util/strings.js
+28 −0
Large diff (28 lines) is not loaded by default to keep the page fast.Load diff
added
public/vendor/novnc/core/websock.js
+365 −0
Large diff (365 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/crypto/aes.js
+0 −481
Large diff (482 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/crypto/bigint.js
+0 −41
Large diff (42 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/crypto/crypto.js
+0 −109
Large diff (110 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/crypto/des.js
+0 −374
Large diff (375 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/crypto/dh.js
+0 −81
Large diff (82 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/crypto/md5.js
+0 −97
Large diff (98 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/crypto/rsa.js
+0 −312
Large diff (313 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/decoders/copyrect.js
+0 −40
Large diff (41 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/decoders/h264.js
+0 −349
Large diff (350 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/decoders/hextile.js
+0 −195
Large diff (196 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/decoders/jpeg.js
+0 −175
Large diff (176 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/decoders/raw.js
+0 −66
Large diff (67 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/decoders/rre.js
+0 −52
Large diff (53 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/decoders/tight.js
+0 −363
Large diff (364 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/decoders/tightpng.js
+0 −51
Large diff (52 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/decoders/zlib.js
+0 −57
Large diff (58 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/decoders/zrle.js
+0 −192
Large diff (193 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/deflator.js
+0 −88
Large diff (89 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/display.js
+0 −588
Large diff (589 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/encodings.js
+0 −70
Large diff (71 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/inflator.js
+0 −77
Large diff (78 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/input/domkeytable.js
+0 −313
Large diff (314 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/input/fixedkeys.js
+0 −127
Large diff (128 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/input/gesturehandler.js
+0 −573
Large diff (574 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/input/keyboard.js
+0 −293
Large diff (294 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/input/keysym.js
+0 −878
Large diff (879 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/input/keysymdef.js
+0 −1351
Large diff (1,352 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/input/util.js
+0 −217
Large diff (218 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/input/vkeys.js
+0 −121
Large diff (122 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/input/xtscancodes.js
+0 −343
Large diff (344 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/ra2.js
+0 −535
Large diff (536 lines) is not loaded by default to keep the page fast.Load diff
deleted
public/vendor/novnc/rfb.js
+0 −104
Large diff (104 lines) is not loaded by default to keep the page fast.Load diff
Diff truncated — file too large.