From a97a978f150b3c64d85fcb7630687896394c7033 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Thu, 23 Feb 2023 09:50:19 +0100 Subject: [PATCH 1/5] noVNC: apply noVNC-v1.2.0-v1.4.0.patch 1. Create the patch by commands git clone -b v1.2.0 https://github.com/novnc/noVNC.git . git checkout v1.4.0 git diff v1.2.0 >noVNC-v1.2.0-v1.4.0.patch 2. Apply the patch by cd systemvm/agent/noVNC patch -p1 { - this._handleMessage(); - }); - this._sock.on('open', () => { - if ((this._rfbConnectionState === 'connecting') && - (this._rfbInitState === '')) { - this._rfbInitState = 'ProtocolVersion'; - Log.Debug("Starting VNC handshake"); - } else { - this._fail("Unexpected server connection while " + - this._rfbConnectionState); - } - }); - this._sock.on('close', (e) => { - Log.Debug("WebSocket on-close event"); - let msg = ""; - if (e.code) { - msg = "(code: " + e.code; - if (e.reason) { - msg += ", reason: " + e.reason; - } - msg += ")"; - } - switch (this._rfbConnectionState) { - case 'connecting': - this._fail("Connection closed " + msg); - break; - case 'connected': - // Handle disconnects that were initiated server-side - this._updateConnectionState('disconnecting'); - this._updateConnectionState('disconnected'); - break; - case 'disconnecting': - // Normal disconnection path - this._updateConnectionState('disconnected'); - break; - case 'disconnected': - this._fail("Unexpected server disconnect " + - "when already disconnected " + msg); - break; - default: - this._fail("Unexpected server disconnect before connecting " + - msg); - break; - } - this._sock.off('close'); - }); - this._sock.on('error', e => Log.Warn("WebSocket on-error event")); + this._sock.on('open', this._socketOpen.bind(this)); + this._sock.on('close', this._socketClose.bind(this)); + this._sock.on('message', this._handleMessage.bind(this)); + this._sock.on('error', this._socketError.bind(this)); + + this._expectedClientWidth = null; + this._expectedClientHeight = null; + this._resizeObserver = new ResizeObserver(this._eventHandlers.handleResize); - // Slight delay of the actual connection so that the caller has - // time to set up callbacks - setTimeout(this._updateConnectionState.bind(this, 'connecting')); + // All prepared, kick off the connection + this._updateConnectionState('connecting'); Log.Debug("<< RFB.constructor"); @@ -295,6 +288,7 @@ export default class RFB extends EventTargetMixin { this._viewOnly = false; this._clipViewport = false; + this._clippingViewport = false; this._scaleViewport = false; this._resizeSession = false; @@ -326,6 +320,16 @@ export default class RFB extends EventTargetMixin { get capabilities() { return this._capabilities; } + get clippingViewport() { return this._clippingViewport; } + _setClippingViewport(on) { + if (on === this._clippingViewport) { + return; + } + this._clippingViewport = on; + this.dispatchEvent(new CustomEvent("clippingviewport", + { detail: this._clippingViewport })); + } + get touchButton() { return 0; } set touchButton(button) { Log.Warn("Using old API!"); } @@ -413,11 +417,20 @@ export default class RFB extends EventTargetMixin { this._sock.off('error'); this._sock.off('message'); this._sock.off('open'); + if (this._rfbRSAAESAuthenticationState !== null) { + this._rfbRSAAESAuthenticationState.disconnect(); + } + } + + approveServer() { + if (this._rfbRSAAESAuthenticationState !== null) { + this._rfbRSAAESAuthenticationState.approveServer(); + } } sendCredentials(creds) { this._rfbCredentials = creds; - setTimeout(this._initMsg.bind(this), 0); + this._resumeAuthentication(); } sendText(text) { @@ -500,8 +513,8 @@ export default class RFB extends EventTargetMixin { } } - focus() { - this._canvas.focus(); + focus(options) { + this._canvas.focus(options); } blur() { @@ -517,31 +530,66 @@ export default class RFB extends EventTargetMixin { this._clipboardText = text; RFB.messages.extendedClipboardNotify(this._sock, [extendedClipboardFormatText]); } else { - let data = new Uint8Array(text.length); - for (let i = 0; i < text.length; i++) { - // FIXME: text can have values outside of Latin1/Uint8 - data[i] = text.charCodeAt(i); + let length, i; + let data; + + length = 0; + // eslint-disable-next-line no-unused-vars + for (let codePoint of text) { + length++; + } + + data = new Uint8Array(length); + + i = 0; + for (let codePoint of text) { + let code = codePoint.codePointAt(0); + + /* Only ISO 8859-1 is supported */ + if (code > 0xff) { + code = 0x3f; // '?' + } + + data[i++] = code; } RFB.messages.clientCutText(this._sock, data); } } + getImageData() { + return this._display.getImageData(); + } + + toDataURL(type, encoderOptions) { + return this._display.toDataURL(type, encoderOptions); + } + + toBlob(callback, type, quality) { + return this._display.toBlob(callback, type, quality); + } + // ===== PRIVATE METHODS ===== _connect() { Log.Debug(">> RFB.connect"); - Log.Info("connecting to " + this._url); - - try { - // WebSocket.onopen transitions to the RFB init states + if (this._url) { + Log.Info(`connecting to ${this._url}`); this._sock.open(this._url, this._wsProtocols); - } catch (e) { - if (e.name === 'SyntaxError') { - this._fail("Invalid host or port (" + e + ")"); - } else { - this._fail("Error when opening socket (" + e + ")"); + } else { + Log.Info(`attaching ${this._rawChannel} to Websock`); + this._sock.attach(this._rawChannel); + + if (this._sock.readyState === 'closed') { + throw Error("Cannot use already closed WebSocket/RTCDataChannel"); + } + + if (this._sock.readyState === 'open') { + // FIXME: _socketOpen() can in theory call _fail(), which + // isn't allowed this early, but I'm not sure that can + // happen without a bug messing up our state variables + this._socketOpen(); } } @@ -553,9 +601,8 @@ export default class RFB extends EventTargetMixin { this._cursor.attach(this._canvas); this._refreshCursor(); - // Monitor size changes of the screen - // FIXME: Use ResizeObserver, or hidden overflow - window.addEventListener('resize', this._eventHandlers.windowResize); + // Monitor size changes of the screen element + this._resizeObserver.observe(this._screen); // Always grab focus on some kind of click event this._canvas.addEventListener("mousedown", this._eventHandlers.focusCanvas); @@ -596,7 +643,7 @@ export default class RFB extends EventTargetMixin { this._canvas.removeEventListener('contextmenu', this._eventHandlers.handleMouse); this._canvas.removeEventListener("mousedown", this._eventHandlers.focusCanvas); this._canvas.removeEventListener("touchstart", this._eventHandlers.focusCanvas); - window.removeEventListener('resize', this._eventHandlers.windowResize); + this._resizeObserver.disconnect(); this._keyboard.ungrab(); this._gestures.detach(); this._sock.close(); @@ -615,12 +662,64 @@ export default class RFB extends EventTargetMixin { Log.Debug("<< RFB.disconnect"); } + _socketOpen() { + if ((this._rfbConnectionState === 'connecting') && + (this._rfbInitState === '')) { + this._rfbInitState = 'ProtocolVersion'; + Log.Debug("Starting VNC handshake"); + } else { + this._fail("Unexpected server connection while " + + this._rfbConnectionState); + } + } + + _socketClose(e) { + Log.Debug("WebSocket on-close event"); + let msg = ""; + if (e.code) { + msg = "(code: " + e.code; + if (e.reason) { + msg += ", reason: " + e.reason; + } + msg += ")"; + } + switch (this._rfbConnectionState) { + case 'connecting': + this._fail("Connection closed " + msg); + break; + case 'connected': + // Handle disconnects that were initiated server-side + this._updateConnectionState('disconnecting'); + this._updateConnectionState('disconnected'); + break; + case 'disconnecting': + // Normal disconnection path + this._updateConnectionState('disconnected'); + break; + case 'disconnected': + this._fail("Unexpected server disconnect " + + "when already disconnected " + msg); + break; + default: + this._fail("Unexpected server disconnect before connecting " + + msg); + break; + } + this._sock.off('close'); + // Delete reference to raw channel to allow cleanup. + this._rawChannel = null; + } + + _socketError(e) { + Log.Warn("WebSocket on-error event"); + } + _focusCanvas(event) { if (!this.focusOnClick) { return; } - this.focus(); + this.focus({ preventScroll: true }); } _setDesktopName(name) { @@ -630,7 +729,26 @@ export default class RFB extends EventTargetMixin { { detail: { name: this._fbName } })); } - _windowResize(event) { + _saveExpectedClientSize() { + this._expectedClientWidth = this._screen.clientWidth; + this._expectedClientHeight = this._screen.clientHeight; + } + + _currentClientSize() { + return [this._screen.clientWidth, this._screen.clientHeight]; + } + + _clientHasExpectedSize() { + const [currentWidth, currentHeight] = this._currentClientSize(); + return currentWidth == this._expectedClientWidth && + currentHeight == this._expectedClientHeight; + } + + _handleResize() { + // Don't change anything if the client size is already as expected + if (this._clientHasExpectedSize()) { + return; + } // If the window resized then our screen element might have // as well. Update the viewport dimensions. window.requestAnimationFrame(() => { @@ -670,6 +788,16 @@ export default class RFB extends EventTargetMixin { const size = this._screenSize(); this._display.viewportChangeSize(size.w, size.h); this._fixScrollbars(); + this._setClippingViewport(size.w < this._display.width || + size.h < this._display.height); + } else { + this._setClippingViewport(false); + } + + // When changing clipping we might show or hide scrollbars. + // This causes the expected client dimensions to change. + if (curClip !== newClip) { + this._saveExpectedClientSize(); } } @@ -695,6 +823,7 @@ export default class RFB extends EventTargetMixin { } const size = this._screenSize(); + RFB.messages.setDesktopSize(this._sock, Math.floor(size.w), Math.floor(size.h), this._screenID, this._screenFlags); @@ -710,12 +839,13 @@ export default class RFB extends EventTargetMixin { } _fixScrollbars() { - // This is a hack because Chrome screws up the calculation - // for when scrollbars are needed. So to fix it we temporarily - // toggle them off and on. + // This is a hack because Safari on macOS screws up the calculation + // for when scrollbars are needed. We get scrollbars when making the + // browser smaller, despite remote resize being enabled. So to fix it + // we temporarily toggle them off and on. const orig = this._screen.style.overflow; this._screen.style.overflow = 'hidden'; - // Force Chrome to recalculate the layout by asking for + // Force Safari to recalculate the layout by asking for // an element's dimensions this._screen.getBoundingClientRect(); this._screen.style.overflow = orig; @@ -880,8 +1010,15 @@ export default class RFB extends EventTargetMixin { } } break; + case 'connecting': + while (this._rfbConnectionState === 'connecting') { + if (!this._initMsg()) { + break; + } + } + break; default: - this._initMsg(); + Log.Error("Got data while in an invalid state"); break; } } @@ -1253,13 +1390,13 @@ export default class RFB extends EventTargetMixin { break; case "003.003": case "003.006": // UltraVNC - case "003.889": // Apple Remote Desktop this._rfbVersion = 3.3; break; case "003.007": this._rfbVersion = 3.7; break; case "003.008": + case "003.889": // Apple Remote Desktop case "004.000": // Intel AMT KVM case "004.001": // RealVNC 4.6 case "005.000": // RealVNC 5.3 @@ -1290,18 +1427,23 @@ export default class RFB extends EventTargetMixin { this._rfbInitState = 'Security'; } - _negotiateSecurity() { - // Polyfill since IE and PhantomJS doesn't have - // TypedArray.includes() - function includes(item, array) { - for (let i = 0; i < array.length; i++) { - if (array[i] === item) { - return true; - } - } - return false; - } + _isSupportedSecurityType(type) { + const clientTypes = [ + securityTypeNone, + securityTypeVNCAuth, + securityTypeRA2ne, + securityTypeTight, + securityTypeVeNCrypt, + securityTypeXVP, + securityTypeARD, + securityTypeMSLogonII, + securityTypePlain, + ]; + return clientTypes.includes(type); + } + + _negotiateSecurity() { if (this._rfbVersion >= 3.7) { // Server sends supported list, client decides const numTypes = this._sock.rQshift8(); @@ -1311,24 +1453,23 @@ export default class RFB extends EventTargetMixin { this._rfbInitState = "SecurityReason"; this._securityContext = "no security types"; this._securityStatus = 1; - return this._initMsg(); + return true; } const types = this._sock.rQshiftBytes(numTypes); Log.Debug("Server security types: " + types); - // Look for each auth in preferred order - if (includes(1, types)) { - this._rfbAuthScheme = 1; // None - } else if (includes(22, types)) { - this._rfbAuthScheme = 22; // XVP - } else if (includes(16, types)) { - this._rfbAuthScheme = 16; // Tight - } else if (includes(2, types)) { - this._rfbAuthScheme = 2; // VNC Auth - } else if (includes(19, types)) { - this._rfbAuthScheme = 19; // VeNCrypt Auth - } else { + // Look for a matching security type in the order that the + // server prefers + this._rfbAuthScheme = -1; + for (let type of types) { + if (this._isSupportedSecurityType(type)) { + this._rfbAuthScheme = type; + break; + } + } + + if (this._rfbAuthScheme === -1) { return this._fail("Unsupported security types (types: " + types + ")"); } @@ -1342,14 +1483,14 @@ export default class RFB extends EventTargetMixin { this._rfbInitState = "SecurityReason"; this._securityContext = "authentication scheme"; this._securityStatus = 1; - return this._initMsg(); + return true; } } this._rfbInitState = 'Authentication'; Log.Debug('Authenticating using scheme: ' + this._rfbAuthScheme); - return this._initMsg(); // jump to authentication + return true; } _handleSecurityReason() { @@ -1399,7 +1540,7 @@ export default class RFB extends EventTargetMixin { this._rfbCredentials.username + this._rfbCredentials.target; this._sock.sendString(xvpAuthStr); - this._rfbAuthScheme = 2; + this._rfbAuthScheme = securityTypeVNCAuth; return this._negotiateAuthentication(); } @@ -1457,40 +1598,66 @@ export default class RFB extends EventTargetMixin { subtypes.push(this._sock.rQshift32()); } - // 256 = Plain subtype - if (subtypes.indexOf(256) != -1) { - // 0x100 = 256 - this._sock.send([0, 0, 1, 0]); - this._rfbVeNCryptState = 4; - } else { - return this._fail("VeNCrypt Plain subtype not offered by server"); - } - } + // Look for a matching security type in the order that the + // server prefers + this._rfbAuthScheme = -1; + for (let type of subtypes) { + // Avoid getting in to a loop + if (type === securityTypeVeNCrypt) { + continue; + } - // negotiated Plain subtype, server waits for password - if (this._rfbVeNCryptState == 4) { - if (!this._rfbCredentials.username || - !this._rfbCredentials.password) { - this.dispatchEvent(new CustomEvent( - "credentialsrequired", - { detail: { types: ["username", "password"] } })); - return false; + if (this._isSupportedSecurityType(type)) { + this._rfbAuthScheme = type; + break; + } } - const user = encodeUTF8(this._rfbCredentials.username); - const pass = encodeUTF8(this._rfbCredentials.password); + if (this._rfbAuthScheme === -1) { + return this._fail("Unsupported security types (types: " + subtypes + ")"); + } - // XXX we assume lengths are <= 255 (should not be an issue in the real world) - this._sock.send([0, 0, 0, user.length]); - this._sock.send([0, 0, 0, pass.length]); - this._sock.sendString(user); - this._sock.sendString(pass); + this._sock.send([this._rfbAuthScheme >> 24, + this._rfbAuthScheme >> 16, + this._rfbAuthScheme >> 8, + this._rfbAuthScheme]); - this._rfbInitState = "SecurityResult"; + this._rfbVeNCryptState == 4; return true; } } + _negotiatePlainAuth() { + if (this._rfbCredentials.username === undefined || + this._rfbCredentials.password === undefined) { + this.dispatchEvent(new CustomEvent( + "credentialsrequired", + { detail: { types: ["username", "password"] } })); + return false; + } + + const user = encodeUTF8(this._rfbCredentials.username); + const pass = encodeUTF8(this._rfbCredentials.password); + + this._sock.send([ + (user.length >> 24) & 0xFF, + (user.length >> 16) & 0xFF, + (user.length >> 8) & 0xFF, + user.length & 0xFF + ]); + this._sock.send([ + (pass.length >> 24) & 0xFF, + (pass.length >> 16) & 0xFF, + (pass.length >> 8) & 0xFF, + pass.length & 0xFF + ]); + this._sock.sendString(user); + this._sock.sendString(pass); + + this._rfbInitState = "SecurityResult"; + return true; + } + _negotiateStdVNCAuth() { if (this._sock.rQwait("auth challenge", 16)) { return false; } @@ -1509,6 +1676,117 @@ export default class RFB extends EventTargetMixin { return true; } + _negotiateARDAuth() { + + if (this._rfbCredentials.username === undefined || + this._rfbCredentials.password === undefined) { + this.dispatchEvent(new CustomEvent( + "credentialsrequired", + { detail: { types: ["username", "password"] } })); + return false; + } + + if (this._rfbCredentials.ardPublicKey != undefined && + this._rfbCredentials.ardCredentials != undefined) { + // if the async web crypto is done return the results + this._sock.send(this._rfbCredentials.ardCredentials); + this._sock.send(this._rfbCredentials.ardPublicKey); + this._rfbCredentials.ardCredentials = null; + this._rfbCredentials.ardPublicKey = null; + this._rfbInitState = "SecurityResult"; + return true; + } + + if (this._sock.rQwait("read ard", 4)) { return false; } + + let generator = this._sock.rQshiftBytes(2); // DH base generator value + + let keyLength = this._sock.rQshift16(); + + if (this._sock.rQwait("read ard keylength", keyLength*2, 4)) { return false; } + + // read the server values + let prime = this._sock.rQshiftBytes(keyLength); // predetermined prime modulus + let serverPublicKey = this._sock.rQshiftBytes(keyLength); // other party's public key + + let clientPrivateKey = window.crypto.getRandomValues(new Uint8Array(keyLength)); + let padding = Array.from(window.crypto.getRandomValues(new Uint8Array(64)), byte => String.fromCharCode(65+byte%26)).join(''); + + this._negotiateARDAuthAsync(generator, keyLength, prime, serverPublicKey, clientPrivateKey, padding); + + return false; + } + + _modPow(base, exponent, modulus) { + + let baseHex = "0x"+Array.from(base, byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join(''); + let exponentHex = "0x"+Array.from(exponent, byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join(''); + let modulusHex = "0x"+Array.from(modulus, byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join(''); + + let b = BigInt(baseHex); + let e = BigInt(exponentHex); + let m = BigInt(modulusHex); + let r = 1n; + b = b % m; + while (e > 0) { + if (e % 2n === 1n) { + r = (r * b) % m; + } + e = e / 2n; + b = (b * b) % m; + } + let hexResult = r.toString(16); + + while (hexResult.length/2 String.fromCharCode(byte)).join(''); + let aesKey = await window.crypto.subtle.importKey("raw", MD5(keyString), {name: "AES-CBC"}, false, ["encrypt"]); + let data = new Uint8Array(string.length); + for (let i = 0; i < string.length; ++i) { + data[i] = string.charCodeAt(i); + } + let encrypted = new Uint8Array(data.length); + for (let i=0;i this._rfbCredentials); + this._rfbRSAAESAuthenticationState.addEventListener( + "serververification", this._eventHandlers.handleRSAAESServerVerification); + this._rfbRSAAESAuthenticationState.addEventListener( + "credentialsrequired", this._eventHandlers.handleRSAAESCredentialsRequired); + } + this._rfbRSAAESAuthenticationState.checkInternalEvents(); + if (!this._rfbRSAAESAuthenticationState.hasStarted) { + this._rfbRSAAESAuthenticationState.negotiateRA2neAuthAsync() + .catch((e) => { + if (e.message !== "disconnect normally") { + this._fail(e.message); + } + }).then(() => { + this.dispatchEvent(new CustomEvent('securityresult')); + this._rfbInitState = "SecurityResult"; + return true; + }).finally(() => { + this._rfbRSAAESAuthenticationState.removeEventListener( + "serververification", this._eventHandlers.handleRSAAESServerVerification); + this._rfbRSAAESAuthenticationState.removeEventListener( + "credentialsrequired", this._eventHandlers.handleRSAAESCredentialsRequired); + this._rfbRSAAESAuthenticationState = null; + }); + } + return false; + } + + _negotiateMSLogonIIAuth() { + if (this._sock.rQwait("mslogonii dh param", 24)) { return false; } + + if (this._rfbCredentials.username === undefined || + this._rfbCredentials.password === undefined) { + this.dispatchEvent(new CustomEvent( + "credentialsrequired", + { detail: { types: ["username", "password"] } })); + return false; + } + + const g = this._sock.rQshiftBytes(8); + const p = this._sock.rQshiftBytes(8); + const A = this._sock.rQshiftBytes(8); + const b = window.crypto.getRandomValues(new Uint8Array(8)); + const B = new Uint8Array(this._modPow(g, b, p)); + const secret = new Uint8Array(this._modPow(A, b, p)); + + const des = new DES(secret); + const username = encodeUTF8(this._rfbCredentials.username).substring(0, 255); + const password = encodeUTF8(this._rfbCredentials.password).substring(0, 63); + const usernameBytes = new Uint8Array(256); + const passwordBytes = new Uint8Array(64); + window.crypto.getRandomValues(usernameBytes); + window.crypto.getRandomValues(passwordBytes); + for (let i = 0; i < username.length; i++) { + usernameBytes[i] = username.charCodeAt(i); + } + usernameBytes[username.length] = 0; + for (let i = 0; i < password.length; i++) { + passwordBytes[i] = password.charCodeAt(i); + } + passwordBytes[password.length] = 0; + let x = new Uint8Array(secret); + for (let i = 0; i < 32; i++) { + for (let j = 0; j < 8; j++) { + x[j] ^= usernameBytes[i * 8 + j]; + } + x = des.enc8(x); + usernameBytes.set(x, i * 8); + } + x = new Uint8Array(secret); + for (let i = 0; i < 8; i++) { + for (let j = 0; j < 8; j++) { + x[j] ^= passwordBytes[i * 8 + j]; + } + x = des.enc8(x); + passwordBytes.set(x, i * 8); + } + this._sock.send(B); + this._sock.send(usernameBytes); + this._sock.send(passwordBytes); + this._rfbInitState = "SecurityResult"; + return true; + } + _negotiateAuthentication() { switch (this._rfbAuthScheme) { // Let CloudStack handle the authentication (RFB 3.8 requires the client to select the auth scheme) - case 1: // no auth - case 2: // VNC authentication - case 19: // VeNCrypt Security Type - if (this._rfbVersion >= 3.8) { - this._rfbInitState = 'SecurityResult'; - return true; - } - this._rfbInitState = 'ClientInitialisation'; - return this._initMsg(); + case securityTypeNone: + case securityTypeVNCAuth: + case securityTypeVeNCrypt: + this._rfbInitState = 'SecurityResult'; + return true; - case 22: // XVP auth + case securityTypeXVP: return this._negotiateXvpAuth(); - case 16: // TightVNC Security Type + case securityTypeARD: + return this._negotiateARDAuth(); + + case securityTypeTight: return this._negotiateTightAuth(); - case 129: // TightVNC UNIX Security Type + case securityTypePlain: + return this._negotiatePlainAuth(); + + case securityTypeUnixLogon: return this._negotiateTightUnixAuth(); + case securityTypeRA2ne: + return this._negotiateRA2neAuth(); + + case securityTypeMSLogonII: + return this._negotiateMSLogonIIAuth(); + default: return this._fail("Unsupported auth scheme (scheme: " + this._rfbAuthScheme + ")"); @@ -1661,6 +2041,13 @@ export default class RFB extends EventTargetMixin { } _handleSecurityResult() { + // There is no security choice, and hence no security result + // until RFB 3.7 + if (this._rfbVersion < 3.7) { + this._rfbInitState = 'ClientInitialisation'; + return true; + } + if (this._sock.rQwait('VNC auth response ', 4)) { return false; } const status = this._sock.rQshift32(); @@ -1668,13 +2055,13 @@ export default class RFB extends EventTargetMixin { if (status === 0) { // OK this._rfbInitState = 'ClientInitialisation'; Log.Debug('Authentication OK'); - return this._initMsg(); + return true; } else { if (this._rfbVersion >= 3.8) { this._rfbInitState = "SecurityReason"; this._securityContext = "security result"; this._securityStatus = status; - return this._initMsg(); + return true; } else { this.dispatchEvent(new CustomEvent( "securityfailure", @@ -1782,6 +2169,8 @@ export default class RFB extends EventTargetMixin { if (this._fbDepth == 24) { encs.push(encodings.encodingTight); encs.push(encodings.encodingTightPNG); + encs.push(encodings.encodingZRLE); + encs.push(encodings.encodingJPEG); encs.push(encodings.encodingHextile); encs.push(encodings.encodingRRE); } @@ -1848,6 +2237,14 @@ export default class RFB extends EventTargetMixin { } } + // Resume authentication handshake after it was paused for some + // reason, e.g. waiting for a password from the user + _resumeAuthentication() { + // We use setTimeout() so it's run in its own context, just like + // it originally did via the WebSocket's event handler + setTimeout(this._initMsg.bind(this), 0); + } + _handleSetColourMapMsg() { Log.Debug("SetColorMapEntries"); @@ -2208,15 +2605,7 @@ export default class RFB extends EventTargetMixin { return this._handleCursor(); case encodings.pseudoEncodingQEMUExtendedKeyEvent: - // Old Safari doesn't support creating keyboard events - try { - const keyboardEvent = document.createEvent("keyboardEvent"); - if (keyboardEvent.code !== undefined) { - this._qemuExtKeyEventSupported = true; - } - } catch (err) { - // Do nothing - } + this._qemuExtKeyEventSupported = true; return true; case encodings.pseudoEncodingDesktopName: @@ -2518,6 +2907,9 @@ export default class RFB extends EventTargetMixin { this._updateScale(); this._updateContinuousUpdates(); + + // Keep this size until browser client size changes + this._saveExpectedClientSize(); } _xvpOp(ver, op) { diff --git a/systemvm/agent/noVNC/vnc.html b/systemvm/agent/noVNC/vnc.html index 060dc736aa87..388ec71456b0 100644 --- a/systemvm/agent/noVNC/vnc.html +++ b/systemvm/agent/noVNC/vnc.html @@ -15,56 +15,37 @@ --> noVNC - - - - - - - - - - - - - - - - - - - - - - + - - - - - + + + + + + + + + + + + + + - - + + + + - - - - - - + - @@ -87,6 +68,8 @@

no
VNC

+
+ no
Clipboard
+

+ Edit clipboard content in the textarea below. +


no
- + title="Full Screen"> @@ -173,10 +159,10 @@

no
title="Settings">
+
+ Settings +
    -
  • - Settings -
  • @@ -280,39 +266,69 @@

    no

-
- +
+
+
+
+
+ + +
+
+
+ Server identity
+
+ The server has provided the following identifying information: +
+
+ Fingerprint: + +
+
+ Please verify that the information is correct and press + "Approve". Otherwise press "Reject". +
+
+ + +
+
-
    -
  • - - -
  • -
  • - - -
  • -
  • - -
  • -
+
+ Credentials +
+
+ + +
+
+ + +
+
+ +
diff --git a/systemvm/agent/noVNC/vnc_lite.html b/systemvm/agent/noVNC/vnc_lite.html index 0be2b53845fd..1eea46022224 100644 --- a/systemvm/agent/noVNC/vnc_lite.html +++ b/systemvm/agent/noVNC/vnc_lite.html @@ -16,12 +16,6 @@ --> noVNC - - - - - - - - - - - - @@ -160,7 +160,7 @@

no
- Settings + Settings
  • @@ -282,7 +282,7 @@

    no

From 9d4c91f15dede1300ad5eb97d8c820f8e2fd1064 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Wed, 5 Apr 2023 09:47:31 +0200 Subject: [PATCH 4/5] noVNC: remove systemvm/agent/noVNC/tests/ --- systemvm/agent/noVNC/tests/test.browser.js | 244 ------------ systemvm/agent/noVNC/tests/test.copyrect.js | 83 ----- systemvm/agent/noVNC/tests/test.hextile.js | 232 ------------ systemvm/agent/noVNC/tests/test.inflator.js | 113 ------ systemvm/agent/noVNC/tests/test.jpeg.js | 288 -------------- systemvm/agent/noVNC/tests/test.ra2.js | 357 ------------------ systemvm/agent/noVNC/tests/test.raw.js | 129 ------- systemvm/agent/noVNC/tests/test.rre.js | 107 ------ systemvm/agent/noVNC/tests/test.tight.js | 394 -------------------- systemvm/agent/noVNC/tests/test.tightpng.js | 144 ------- systemvm/agent/noVNC/tests/test.zrle.js | 124 ------ 11 files changed, 2215 deletions(-) delete mode 100644 systemvm/agent/noVNC/tests/test.browser.js delete mode 100644 systemvm/agent/noVNC/tests/test.copyrect.js delete mode 100644 systemvm/agent/noVNC/tests/test.hextile.js delete mode 100644 systemvm/agent/noVNC/tests/test.inflator.js delete mode 100644 systemvm/agent/noVNC/tests/test.jpeg.js delete mode 100644 systemvm/agent/noVNC/tests/test.ra2.js delete mode 100644 systemvm/agent/noVNC/tests/test.raw.js delete mode 100644 systemvm/agent/noVNC/tests/test.rre.js delete mode 100644 systemvm/agent/noVNC/tests/test.tight.js delete mode 100644 systemvm/agent/noVNC/tests/test.tightpng.js delete mode 100644 systemvm/agent/noVNC/tests/test.zrle.js diff --git a/systemvm/agent/noVNC/tests/test.browser.js b/systemvm/agent/noVNC/tests/test.browser.js deleted file mode 100644 index 3b2299f636d5..000000000000 --- a/systemvm/agent/noVNC/tests/test.browser.js +++ /dev/null @@ -1,244 +0,0 @@ -/* eslint-disable no-console */ -const expect = chai.expect; - -import { isMac, isWindows, isIOS, isAndroid, isChromeOS, - isSafari, isFirefox, isChrome, isChromium, isOpera, isEdge, - isGecko, isWebKit, isBlink } from '../core/util/browser.js'; - -describe('OS detection', function () { - let origNavigator; - beforeEach(function () { - // window.navigator is a protected read-only property in many - // environments, so we need to redefine it whilst running these - // tests. - origNavigator = Object.getOwnPropertyDescriptor(window, "navigator"); - - Object.defineProperty(window, "navigator", {value: {}}); - }); - - afterEach(function () { - Object.defineProperty(window, "navigator", origNavigator); - }); - - it('should handle macOS', function () { - const platforms = [ - "MacIntel", - "MacPPC", - ]; - - navigator.userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6 Safari/605.1.15"; - platforms.forEach((platform) => { - navigator.platform = platform; - expect(isMac()).to.be.true; - expect(isWindows()).to.be.false; - expect(isIOS()).to.be.false; - expect(isAndroid()).to.be.false; - expect(isChromeOS()).to.be.false; - }); - }); - - it('should handle Windows', function () { - const platforms = [ - "Win32", - "Win64", - ]; - - navigator.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36"; - platforms.forEach((platform) => { - navigator.platform = platform; - expect(isMac()).to.be.false; - expect(isWindows()).to.be.true; - expect(isIOS()).to.be.false; - expect(isAndroid()).to.be.false; - expect(isChromeOS()).to.be.false; - }); - }); - - it('should handle iOS', function () { - const platforms = [ - "iPhone", - "iPod", - "iPad", - ]; - - navigator.userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Mobile/15E148 Safari/604.1"; - platforms.forEach((platform) => { - navigator.platform = platform; - expect(isMac()).to.be.false; - expect(isWindows()).to.be.false; - expect(isIOS()).to.be.true; - expect(isAndroid()).to.be.false; - expect(isChromeOS()).to.be.false; - }); - }); - - it('should handle Android', function () { - let userAgents = [ - "Mozilla/5.0 (Linux; Android 13; SM-G960U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.128 Mobile Safari/537.36", - "Mozilla/5.0 (Android 13; Mobile; LG-M255; rv:108.0) Gecko/108.0 Firefox/108.0", - ]; - - navigator.platform = "Linux x86_64"; - userAgents.forEach((ua) => { - navigator.userAgent = ua; - expect(isMac()).to.be.false; - expect(isWindows()).to.be.false; - expect(isIOS()).to.be.false; - expect(isAndroid()).to.be.true; - expect(isChromeOS()).to.be.false; - }); - }); - - it('should handle ChromeOS', function () { - let userAgents = [ - "Mozilla/5.0 (X11; CrOS x86_64 15183.59.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.75 Safari/537.36", - "Mozilla/5.0 (X11; CrOS aarch64 15183.59.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.75 Safari/537.36", - ]; - - navigator.platform = "Linux x86_64"; - userAgents.forEach((ua) => { - navigator.userAgent = ua; - expect(isMac()).to.be.false; - expect(isWindows()).to.be.false; - expect(isIOS()).to.be.false; - expect(isAndroid()).to.be.false; - expect(isChromeOS()).to.be.true; - }); - }); -}); - -describe('Browser detection', function () { - let origNavigator; - beforeEach(function () { - // window.navigator is a protected read-only property in many - // environments, so we need to redefine it whilst running these - // tests. - origNavigator = Object.getOwnPropertyDescriptor(window, "navigator"); - - Object.defineProperty(window, "navigator", {value: {}}); - }); - - afterEach(function () { - Object.defineProperty(window, "navigator", origNavigator); - }); - - it('should handle Chrome', function () { - navigator.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36"; - - expect(isSafari()).to.be.false; - expect(isFirefox()).to.be.false; - expect(isChrome()).to.be.true; - expect(isChromium()).to.be.false; - expect(isOpera()).to.be.false; - expect(isEdge()).to.be.false; - - expect(isGecko()).to.be.false; - expect(isWebKit()).to.be.false; - expect(isBlink()).to.be.true; - }); - - it('should handle Chromium', function () { - navigator.userAgent = "Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Raspbian Chromium/74.0.3729.157 Chrome/74.0.3729.157 Safari/537.36"; - - expect(isSafari()).to.be.false; - expect(isFirefox()).to.be.false; - expect(isChrome()).to.be.false; - expect(isChromium()).to.be.true; - expect(isOpera()).to.be.false; - expect(isEdge()).to.be.false; - - expect(isGecko()).to.be.false; - expect(isWebKit()).to.be.false; - expect(isBlink()).to.be.true; - }); - - it('should handle Firefox', function () { - navigator.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0"; - - expect(isSafari()).to.be.false; - expect(isFirefox()).to.be.true; - expect(isChrome()).to.be.false; - expect(isChromium()).to.be.false; - expect(isOpera()).to.be.false; - expect(isEdge()).to.be.false; - - expect(isGecko()).to.be.true; - expect(isWebKit()).to.be.false; - expect(isBlink()).to.be.false; - }); - - it('should handle Seamonkey', function () { - navigator.userAgent = "Mozilla/5.0 (Windows NT 6.1; rv:36.0) Gecko/20100101 Firefox/36.0 Seamonkey/2.33.1"; - - expect(isSafari()).to.be.false; - expect(isFirefox()).to.be.false; - expect(isChrome()).to.be.false; - expect(isChromium()).to.be.false; - expect(isOpera()).to.be.false; - expect(isEdge()).to.be.false; - - expect(isGecko()).to.be.true; - expect(isWebKit()).to.be.false; - expect(isBlink()).to.be.false; - }); - - it('should handle Safari', function () { - navigator.userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6 Safari/605.1.15"; - - expect(isSafari()).to.be.true; - expect(isFirefox()).to.be.false; - expect(isChrome()).to.be.false; - expect(isChromium()).to.be.false; - expect(isOpera()).to.be.false; - expect(isEdge()).to.be.false; - - expect(isGecko()).to.be.false; - expect(isWebKit()).to.be.true; - expect(isBlink()).to.be.false; - }); - - it('should handle Edge', function () { - navigator.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.34"; - - expect(isSafari()).to.be.false; - expect(isFirefox()).to.be.false; - expect(isChrome()).to.be.false; - expect(isChromium()).to.be.false; - expect(isOpera()).to.be.false; - expect(isEdge()).to.be.true; - - expect(isGecko()).to.be.false; - expect(isWebKit()).to.be.false; - expect(isBlink()).to.be.true; - }); - - it('should handle Opera', function () { - navigator.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 OPR/91.0.4516.20"; - - expect(isSafari()).to.be.false; - expect(isFirefox()).to.be.false; - expect(isChrome()).to.be.false; - expect(isChromium()).to.be.false; - expect(isOpera()).to.be.true; - expect(isEdge()).to.be.false; - - expect(isGecko()).to.be.false; - expect(isWebKit()).to.be.false; - expect(isBlink()).to.be.true; - }); - - it('should handle Epiphany', function () { - navigator.userAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Safari/605.1.15 Epiphany/605.1.15"; - - expect(isSafari()).to.be.false; - expect(isFirefox()).to.be.false; - expect(isChrome()).to.be.false; - expect(isChromium()).to.be.false; - expect(isOpera()).to.be.false; - expect(isEdge()).to.be.false; - - expect(isGecko()).to.be.false; - expect(isWebKit()).to.be.true; - expect(isBlink()).to.be.false; - }); -}); diff --git a/systemvm/agent/noVNC/tests/test.copyrect.js b/systemvm/agent/noVNC/tests/test.copyrect.js deleted file mode 100644 index 90ba0c68319c..000000000000 --- a/systemvm/agent/noVNC/tests/test.copyrect.js +++ /dev/null @@ -1,83 +0,0 @@ -const expect = chai.expect; - -import Websock from '../core/websock.js'; -import Display from '../core/display.js'; - -import CopyRectDecoder from '../core/decoders/copyrect.js'; - -import FakeWebSocket from './fake.websocket.js'; - -function testDecodeRect(decoder, x, y, width, height, data, display, depth) { - let sock; - - sock = new Websock; - sock.open("ws://example.com"); - - sock.on('message', () => { - decoder.decodeRect(x, y, width, height, sock, display, depth); - }); - - // Empty messages are filtered at multiple layers, so we need to - // do a direct call - if (data.length === 0) { - decoder.decodeRect(x, y, width, height, sock, display, depth); - } else { - sock._websocket._receiveData(new Uint8Array(data)); - } - - display.flip(); -} - -describe('CopyRect Decoder', function () { - let decoder; - let display; - - before(FakeWebSocket.replace); - after(FakeWebSocket.restore); - - beforeEach(function () { - decoder = new CopyRectDecoder(); - display = new Display(document.createElement('canvas')); - display.resize(4, 4); - }); - - it('should handle the CopyRect encoding', function () { - // seed some initial data to copy - display.fillRect(0, 0, 4, 4, [ 0x11, 0x22, 0x33 ]); - display.fillRect(0, 0, 2, 2, [ 0x00, 0x00, 0xff ]); - display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]); - - testDecodeRect(decoder, 0, 2, 2, 2, - [0x00, 0x02, 0x00, 0x00], - display, 24); - testDecodeRect(decoder, 2, 2, 2, 2, - [0x00, 0x00, 0x00, 0x00], - display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle empty rects', function () { - display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]); - display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]); - display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]); - - testDecodeRect(decoder, 1, 2, 0, 0, [0x00, 0x00, 0x00, 0x00], display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); -}); diff --git a/systemvm/agent/noVNC/tests/test.hextile.js b/systemvm/agent/noVNC/tests/test.hextile.js deleted file mode 100644 index a7034f058beb..000000000000 --- a/systemvm/agent/noVNC/tests/test.hextile.js +++ /dev/null @@ -1,232 +0,0 @@ -const expect = chai.expect; - -import Websock from '../core/websock.js'; -import Display from '../core/display.js'; - -import HextileDecoder from '../core/decoders/hextile.js'; - -import FakeWebSocket from './fake.websocket.js'; - -function testDecodeRect(decoder, x, y, width, height, data, display, depth) { - let sock; - - sock = new Websock; - sock.open("ws://example.com"); - - sock.on('message', () => { - decoder.decodeRect(x, y, width, height, sock, display, depth); - }); - - // Empty messages are filtered at multiple layers, so we need to - // do a direct call - if (data.length === 0) { - decoder.decodeRect(x, y, width, height, sock, display, depth); - } else { - sock._websocket._receiveData(new Uint8Array(data)); - } - - display.flip(); -} - -function push32(arr, num) { - arr.push((num >> 24) & 0xFF, - (num >> 16) & 0xFF, - (num >> 8) & 0xFF, - num & 0xFF); -} - -describe('Hextile Decoder', function () { - let decoder; - let display; - - before(FakeWebSocket.replace); - after(FakeWebSocket.restore); - - beforeEach(function () { - decoder = new HextileDecoder(); - display = new Display(document.createElement('canvas')); - display.resize(4, 4); - }); - - it('should handle a tile with fg, bg specified, normal subrects', function () { - let data = []; - data.push(0x02 | 0x04 | 0x08); // bg spec, fg spec, anysubrects - push32(data, 0x00ff0000); // becomes 00ff0000 --> #00FF00 bg color - data.push(0x00); // becomes 0000ff00 --> #0000FF fg color - data.push(0x00); - data.push(0xff); - data.push(0x00); - data.push(2); // 2 subrects - data.push(0); // x: 0, y: 0 - data.push(1 | (1 << 4)); // width: 2, height: 2 - data.push(2 | (2 << 4)); // x: 2, y: 2 - data.push(1 | (1 << 4)); // width: 2, height: 2 - - testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle a raw tile', function () { - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - let data = []; - data.push(0x01); // raw - for (let i = 0; i < targetData.length; i += 4) { - data.push(targetData[i]); - data.push(targetData[i + 1]); - data.push(targetData[i + 2]); - // Last byte zero to test correct alpha handling - data.push(0); - } - - testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle a tile with only bg specified (solid bg)', function () { - let data = []; - data.push(0x02); - push32(data, 0x00ff0000); // becomes 00ff0000 --> #00FF00 bg color - - testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24); - - let expected = []; - for (let i = 0; i < 16; i++) { - push32(expected, 0x00ff00ff); - } - - expect(display).to.have.displayed(new Uint8Array(expected)); - }); - - it('should handle a tile with only bg specified and an empty frame afterwards', function () { - // set the width so we can have two tiles - display.resize(8, 4); - - let data = []; - - // send a bg frame - data.push(0x02); - push32(data, 0x00ff0000); // becomes 00ff0000 --> #00FF00 bg color - - // send an empty frame - data.push(0x00); - - testDecodeRect(decoder, 0, 0, 32, 4, data, display, 24); - - let expected = []; - for (let i = 0; i < 16; i++) { - push32(expected, 0x00ff00ff); // rect 1: solid - } - for (let i = 0; i < 16; i++) { - push32(expected, 0x00ff00ff); // rect 2: same bkground color - } - - expect(display).to.have.displayed(new Uint8Array(expected)); - }); - - it('should handle a tile with bg and coloured subrects', function () { - let data = []; - data.push(0x02 | 0x08 | 0x10); // bg spec, anysubrects, colouredsubrects - push32(data, 0x00ff0000); // becomes 00ff0000 --> #00FF00 bg color - data.push(2); // 2 subrects - data.push(0x00); // becomes 0000ff00 --> #0000FF fg color - data.push(0x00); - data.push(0xff); - data.push(0x00); - data.push(0); // x: 0, y: 0 - data.push(1 | (1 << 4)); // width: 2, height: 2 - data.push(0x00); // becomes 0000ff00 --> #0000FF fg color - data.push(0x00); - data.push(0xff); - data.push(0x00); - data.push(2 | (2 << 4)); // x: 2, y: 2 - data.push(1 | (1 << 4)); // width: 2, height: 2 - - testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should carry over fg and bg colors from the previous tile if not specified', function () { - display.resize(4, 17); - - let data = []; - data.push(0x02 | 0x04 | 0x08); // bg spec, fg spec, anysubrects - push32(data, 0xff00ff); // becomes 00ff00ff --> #00FF00 bg color - data.push(0x00); // becomes 0000ffff --> #0000FF fg color - data.push(0x00); - data.push(0xff); - data.push(0xff); - data.push(8); // 8 subrects - for (let i = 0; i < 4; i++) { - data.push((0 << 4) | (i * 4)); // x: 0, y: i*4 - data.push(1 | (1 << 4)); // width: 2, height: 2 - data.push((2 << 4) | (i * 4 + 2)); // x: 2, y: i * 4 + 2 - data.push(1 | (1 << 4)); // width: 2, height: 2 - } - data.push(0x08); // anysubrects - data.push(1); // 1 subrect - data.push(0); // x: 0, y: 0 - data.push(1 | (1 << 4)); // width: 2, height: 2 - - testDecodeRect(decoder, 0, 0, 4, 17, data, display, 24); - - let targetData = [ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]; - - let expected = []; - for (let i = 0; i < 4; i++) { - expected = expected.concat(targetData); - } - expected = expected.concat(targetData.slice(0, 16)); - - expect(display).to.have.displayed(new Uint8Array(expected)); - }); - - it('should fail on an invalid subencoding', function () { - let data = [45]; // an invalid subencoding - expect(() => testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24)).to.throw(); - }); - - it('should handle empty rects', function () { - display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]); - display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]); - display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]); - - testDecodeRect(decoder, 1, 2, 0, 0, [], display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); -}); diff --git a/systemvm/agent/noVNC/tests/test.inflator.js b/systemvm/agent/noVNC/tests/test.inflator.js deleted file mode 100644 index 533bcd865d9c..000000000000 --- a/systemvm/agent/noVNC/tests/test.inflator.js +++ /dev/null @@ -1,113 +0,0 @@ -/* eslint-disable no-console */ -const expect = chai.expect; - -import { deflateInit, deflate, Z_FULL_FLUSH } from "../vendor/pako/lib/zlib/deflate.js"; -import ZStream from "../vendor/pako/lib/zlib/zstream.js"; -import Inflator from "../core/inflator.js"; - -function _deflator(data) { - let strm = new ZStream(); - - deflateInit(strm, 5); - - /* eslint-disable camelcase */ - strm.input = data; - strm.avail_in = strm.input.length; - strm.next_in = 0; - /* eslint-enable camelcase */ - - let chunks = []; - let totalLen = 0; - while (strm.avail_in > 0) { - /* eslint-disable camelcase */ - strm.output = new Uint8Array(1024 * 10 * 10); - strm.avail_out = strm.output.length; - strm.next_out = 0; - /* eslint-enable camelcase */ - - let ret = deflate(strm, Z_FULL_FLUSH); - - // Check that return code is not an error - expect(ret).to.be.greaterThan(-1); - - let chunk = new Uint8Array(strm.output.buffer, 0, strm.next_out); - totalLen += chunk.length; - chunks.push(chunk); - } - - // Combine chunks into a single data - - let outData = new Uint8Array(totalLen); - let offset = 0; - - for (let i = 0; i < chunks.length; i++) { - outData.set(chunks[i], offset); - offset += chunks[i].length; - } - - return outData; -} - -describe('Inflate data', function () { - - it('should be able to inflate messages', function () { - let inflator = new Inflator(); - - let text = "123asdf"; - let preText = new Uint8Array(text.length); - for (let i = 0; i < preText.length; i++) { - preText[i] = text.charCodeAt(i); - } - - let compText = _deflator(preText); - - inflator.setInput(compText); - let inflatedText = inflator.inflate(preText.length); - - expect(inflatedText).to.array.equal(preText); - - }); - - it('should be able to inflate large messages', function () { - let inflator = new Inflator(); - - /* Generate a big string with random characters. Used because - repetition of letters might be deflated more effectively than - random ones. */ - let text = ""; - let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for (let i = 0; i < 300000; i++) { - text += characters.charAt(Math.floor(Math.random() * characters.length)); - } - - let preText = new Uint8Array(text.length); - for (let i = 0; i < preText.length; i++) { - preText[i] = text.charCodeAt(i); - } - - let compText = _deflator(preText); - - //Check that the compressed size is expected size - expect(compText.length).to.be.greaterThan((1024 * 10 * 10) * 2); - - inflator.setInput(compText); - let inflatedText = inflator.inflate(preText.length); - - expect(inflatedText).to.array.equal(preText); - }); - - it('should throw an error on insufficient data', function () { - let inflator = new Inflator(); - - let text = "123asdf"; - let preText = new Uint8Array(text.length); - for (let i = 0; i < preText.length; i++) { - preText[i] = text.charCodeAt(i); - } - - let compText = _deflator(preText); - - inflator.setInput(compText); - expect(() => inflator.inflate(preText.length * 2)).to.throw(); - }); -}); diff --git a/systemvm/agent/noVNC/tests/test.jpeg.js b/systemvm/agent/noVNC/tests/test.jpeg.js deleted file mode 100644 index 6834f03d4ea3..000000000000 --- a/systemvm/agent/noVNC/tests/test.jpeg.js +++ /dev/null @@ -1,288 +0,0 @@ -const expect = chai.expect; - -import Websock from '../core/websock.js'; -import Display from '../core/display.js'; - -import JPEGDecoder from '../core/decoders/jpeg.js'; - -import FakeWebSocket from './fake.websocket.js'; - -function testDecodeRect(decoder, x, y, width, height, data, display, depth) { - let sock; - - sock = new Websock; - sock.open("ws://example.com"); - - sock.on('message', () => { - decoder.decodeRect(x, y, width, height, sock, display, depth); - }); - - // Empty messages are filtered at multiple layers, so we need to - // do a direct call - if (data.length === 0) { - decoder.decodeRect(x, y, width, height, sock, display, depth); - } else { - sock._websocket._receiveData(new Uint8Array(data)); - } - - display.flip(); -} - -describe('JPEG Decoder', function () { - let decoder; - let display; - - before(FakeWebSocket.replace); - after(FakeWebSocket.restore); - - beforeEach(function () { - decoder = new JPEGDecoder(); - display = new Display(document.createElement('canvas')); - display.resize(4, 4); - }); - - it('should handle JPEG rects', function (done) { - let data = [ - // JPEG data - 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, - 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x01, 0x2c, - 0x01, 0x2c, 0x00, 0x42, 0xff, 0xdb, 0x00, 0x43, - 0x00, 0x03, 0x02, 0x02, 0x03, 0x02, 0x02, 0x03, - 0x03, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x05, - 0x08, 0x05, 0x05, 0x04, 0x04, 0x05, 0x0a, 0x07, - 0x07, 0x06, 0x08, 0x0c, 0x0a, 0x0c, 0x0c, 0x0b, - 0x0a, 0x0b, 0x0b, 0x0d, 0x0e, 0x12, 0x10, 0x0d, - 0x0e, 0x11, 0x0e, 0x0b, 0x0b, 0x10, 0x16, 0x10, - 0x11, 0x13, 0x14, 0x15, 0x15, 0x15, 0x0c, 0x0f, - 0x17, 0x18, 0x16, 0x14, 0x18, 0x12, 0x14, 0x15, - 0x14, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x03, 0x04, - 0x04, 0x05, 0x04, 0x05, 0x09, 0x05, 0x05, 0x09, - 0x14, 0x0d, 0x0b, 0x0d, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xff, 0xc0, - 0x00, 0x11, 0x08, 0x00, 0x04, 0x00, 0x04, 0x03, - 0x01, 0x11, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, - 0x01, 0xff, 0xc4, 0x00, 0x1f, 0x00, 0x00, 0x01, - 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x0a, 0x0b, 0xff, 0xc4, 0x00, 0xb5, 0x10, 0x00, - 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, - 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, - 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, - 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, - 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, - 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, - 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, - 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, - 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, - 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, - 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, - 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, - 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, - 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, - 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, - 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, - 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, - 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, - 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, - 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, - 0xfa, 0xff, 0xc4, 0x00, 0x1f, 0x01, 0x00, 0x03, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x0a, 0x0b, 0xff, 0xc4, 0x00, 0xb5, 0x11, 0x00, - 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, - 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, - 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, - 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, - 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, - 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, - 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, - 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, - 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, - 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, - 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, - 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, - 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, - 0xfa, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, - 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0xf9, - 0xf7, 0xfb, 0x67, 0x56, 0xff, 0x00, 0x9f, 0xf8, - 0x3f, 0xf0, 0x51, 0xa7, 0xff, 0x00, 0xf2, 0x3d, - 0x7e, 0x6f, 0xfd, 0xab, 0x94, 0x7f, 0xd0, 0x9a, - 0x8f, 0xfe, 0x0d, 0xc7, 0x7f, 0xf3, 0x61, 0xfd, - 0xa7, 0xff, 0x00, 0x10, 0x77, 0x0d, 0xff, 0x00, - 0x43, 0xec, 0xcf, 0xff, 0x00, 0x0b, 0xab, 0x1f, - 0xff, 0xd9, - ]; - - testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24); - - let targetData = new Uint8Array([ - 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255 - ]); - - // Browsers have rounding errors, so we need an approximate - // comparing function - function almost(a, b) { - let diff = Math.abs(a - b); - return diff < 5; - } - - display.onflush = () => { - expect(display).to.have.displayed(targetData, almost); - done(); - }; - display.flush(); - }); - - it('should handle JPEG rects without Huffman and quantification tables', function (done) { - let data1 = [ - // JPEG data - 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, - 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x01, 0x2c, - 0x01, 0x2c, 0x00, 0x42, 0xff, 0xdb, 0x00, 0x43, - 0x00, 0x03, 0x02, 0x02, 0x03, 0x02, 0x02, 0x03, - 0x03, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x05, - 0x08, 0x05, 0x05, 0x04, 0x04, 0x05, 0x0a, 0x07, - 0x07, 0x06, 0x08, 0x0c, 0x0a, 0x0c, 0x0c, 0x0b, - 0x0a, 0x0b, 0x0b, 0x0d, 0x0e, 0x12, 0x10, 0x0d, - 0x0e, 0x11, 0x0e, 0x0b, 0x0b, 0x10, 0x16, 0x10, - 0x11, 0x13, 0x14, 0x15, 0x15, 0x15, 0x0c, 0x0f, - 0x17, 0x18, 0x16, 0x14, 0x18, 0x12, 0x14, 0x15, - 0x14, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x03, 0x04, - 0x04, 0x05, 0x04, 0x05, 0x09, 0x05, 0x05, 0x09, - 0x14, 0x0d, 0x0b, 0x0d, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xff, 0xc0, - 0x00, 0x11, 0x08, 0x00, 0x04, 0x00, 0x04, 0x03, - 0x01, 0x11, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, - 0x01, 0xff, 0xc4, 0x00, 0x1f, 0x00, 0x00, 0x01, - 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x0a, 0x0b, 0xff, 0xc4, 0x00, 0xb5, 0x10, 0x00, - 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, - 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, - 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, - 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, - 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, - 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, - 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, - 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, - 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, - 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, - 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, - 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, - 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, - 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, - 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, - 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, - 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, - 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, - 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, - 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, - 0xfa, 0xff, 0xc4, 0x00, 0x1f, 0x01, 0x00, 0x03, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x0a, 0x0b, 0xff, 0xc4, 0x00, 0xb5, 0x11, 0x00, - 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, - 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, - 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, - 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, - 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, - 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, - 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, - 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, - 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, - 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, - 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, - 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, - 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, - 0xfa, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, - 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0xf9, - 0xf7, 0xfb, 0x67, 0x56, 0xff, 0x00, 0x9f, 0xf8, - 0x3f, 0xf0, 0x51, 0xa7, 0xff, 0x00, 0xf2, 0x3d, - 0x7e, 0x6f, 0xfd, 0xab, 0x94, 0x7f, 0xd0, 0x9a, - 0x8f, 0xfe, 0x0d, 0xc7, 0x7f, 0xf3, 0x61, 0xfd, - 0xa7, 0xff, 0x00, 0x10, 0x77, 0x0d, 0xff, 0x00, - 0x43, 0xec, 0xcf, 0xff, 0x00, 0x0b, 0xab, 0x1f, - 0xff, 0xd9, - ]; - - testDecodeRect(decoder, 0, 0, 4, 4, data1, display, 24); - - let data2 = [ - // JPEG data - 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, - 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x01, 0x2c, - 0x01, 0x2c, 0x00, 0x73, 0xff, 0xc0, 0x00, 0x11, - 0x08, 0x00, 0x04, 0x00, 0x04, 0x03, 0x01, 0x11, - 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, - 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, - 0x03, 0x11, 0x00, 0x3f, 0x00, 0xf9, 0xf7, 0xfb, - 0x67, 0x56, 0xff, 0x00, 0x9f, 0xf8, 0x3f, 0xf0, - 0x51, 0xa7, 0xff, 0x00, 0xf2, 0x3d, 0x7e, 0x6f, - 0xfd, 0xab, 0x94, 0x7f, 0xd0, 0x9a, 0x8f, 0xfe, - 0x0d, 0xc7, 0x7f, 0xf3, 0x61, 0xfd, 0xa7, 0xff, - 0x00, 0x10, 0x77, 0x0d, 0xff, 0x00, 0x43, 0xec, - 0xcf, 0xff, 0x00, 0x0b, 0xab, 0x1f, 0xff, 0xd9, - ]; - - testDecodeRect(decoder, 0, 0, 4, 4, data2, display, 24); - - let targetData = new Uint8Array([ - 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255 - ]); - - // Browsers have rounding errors, so we need an approximate - // comparing function - function almost(a, b) { - let diff = Math.abs(a - b); - return diff < 5; - } - - display.onflush = () => { - expect(display).to.have.displayed(targetData, almost); - done(); - }; - display.flush(); - }); -}); diff --git a/systemvm/agent/noVNC/tests/test.ra2.js b/systemvm/agent/noVNC/tests/test.ra2.js deleted file mode 100644 index cc505b1fe144..000000000000 --- a/systemvm/agent/noVNC/tests/test.ra2.js +++ /dev/null @@ -1,357 +0,0 @@ -const expect = chai.expect; - -import RFB from '../core/rfb.js'; - -import FakeWebSocket from './fake.websocket.js'; - -function fakeGetRandomValues(arr) { - if (arr.length === 16) { - arr.set(new Uint8Array([ - 0x1c, 0x08, 0xfe, 0x21, 0x78, 0xef, 0x4e, 0xf9, - 0x3f, 0x05, 0xec, 0xea, 0xd4, 0x6b, 0xa5, 0xd5, - ])); - } else { - arr.set(new Uint8Array([ - 0xee, 0xe2, 0xf1, 0x5a, 0x3c, 0xa7, 0xbe, 0x95, - 0x6f, 0x2a, 0x75, 0xfd, 0x62, 0x01, 0xcb, 0xbf, - 0x43, 0x74, 0xca, 0x47, 0x4d, 0xfb, 0x0f, 0xcf, - 0x3a, 0x6d, 0x55, 0x6b, 0x59, 0x3a, 0xf6, 0x87, - 0xcb, 0x03, 0xb7, 0x28, 0x35, 0x7b, 0x15, 0x8e, - 0xb6, 0xc8, 0x8f, 0x2d, 0x5e, 0x7b, 0x1c, 0x9a, - 0x32, 0x55, 0xe7, 0x64, 0x36, 0x25, 0x7b, 0xa3, - 0xe9, 0x4f, 0x6f, 0x97, 0xdc, 0xa4, 0xd4, 0x62, - 0x6d, 0x7f, 0xab, 0x02, 0x6b, 0x13, 0x56, 0x69, - 0xfb, 0xd0, 0xd4, 0x13, 0x76, 0xcd, 0x0d, 0xd0, - 0x1f, 0xd1, 0x0c, 0x63, 0x3a, 0x34, 0x20, 0x6c, - 0xbb, 0x60, 0x45, 0x82, 0x23, 0xfd, 0x7c, 0x77, - 0x6d, 0xcc, 0x5e, 0xaa, 0xc3, 0x0c, 0x43, 0xb7, - 0x8d, 0xc0, 0x27, 0x6e, 0xeb, 0x1d, 0x6c, 0x5f, - 0xd8, 0x1c, 0x3c, 0x1c, 0x60, 0x2e, 0x82, 0x15, - 0xfd, 0x2e, 0x5f, 0x3a, 0x15, 0x53, 0x14, 0x70, - 0x4f, 0xe1, 0x65, 0x68, 0x35, 0x6d, 0xc7, 0x64, - 0xdb, 0xdd, 0x09, 0x31, 0x4f, 0x7b, 0x6d, 0x6c, - 0x77, 0x59, 0x5e, 0x1e, 0xfa, 0x4b, 0x06, 0x14, - 0xbe, 0xdc, 0x9c, 0x3d, 0x7b, 0xed, 0xf3, 0x2b, - 0x19, 0x26, 0x11, 0x8e, 0x3f, 0xab, 0x73, 0x9a, - 0x0a, 0x3a, 0xaa, 0x85, 0x06, 0xd5, 0xca, 0x3f, - 0xc3, 0xe2, 0x33, 0x7f, 0x97, 0x74, 0x98, 0x8f, - 0x2f, 0xa5, 0xfc, 0x7e, 0xb1, 0x77, 0x71, 0x58, - 0xf0, 0xbc, 0x04, 0x59, 0xbb, 0xb4, 0xc6, 0xcc, - 0x0f, 0x06, 0xcd, 0xa2, 0xd5, 0x01, 0x2f, 0xb2, - 0x22, 0x0b, 0xfc, 0x1e, 0x59, 0x9f, 0xd3, 0x4f, - 0x30, 0x95, 0xc6, 0x80, 0x0f, 0x69, 0xf3, 0x4a, - 0xd4, 0x36, 0xb6, 0x5a, 0x0b, 0x16, 0x0d, 0x81, - 0x31, 0xb0, 0x69, 0xd4, 0x4e, - ])); - } -} - -async function fakeGeneratekey() { - let key = JSON.parse('{"alg":"RSA-OAEP-256","d":"B7QR2yI8sXjo8vQhJpX9odqqR\ -6wIuPrTM1B1JJEKVeSrr7OYcc1FRJ52Vap9LIAU-ezigs9QDvWMxknB8motLnG69Wck37nt9_z4s8l\ -FQp0nROA-oaR92HW34KNL1b2fEVWGI0N86h730MvTJC5O2cmKeMezIG-oNqbbfFyP8AW-WLdDlgZm1\ -1-FjzhbVpb0Bc7nRSgBPSV-EY6Sl-LuglxDx4LaTdQW7QE_WXoRUt-GYGfTseuFQQK5WeoyX3yBtQy\ -dpauW6rrgyWdtP4hDFIoZsX6w1i-UMWMMwlIB5FdnUSi26igVGADGpV_vGMP36bv-EHp0bY-Qp0gpI\ -fLfgQ","dp":"Z1v5UceFfV2bhmbG19eGYb30jFxqoRBq36PKNY7IunMs1keYy0FpLbyGhtgMZ1Ymm\ -c8wEzGYsCPEP-ykcun_rlyu7YxmcnyC9YQqTqLyqvO-7rUqDvk9TMfdqWFP6heADRhKZmEbmcau6_m\ -2MwwK9kOkMKWvpqp8_TpJMnAH7zE","dq":"OBacRE15aY3NtCR4cvP5os3sT70JbDdDLHT3IHZM6r\ -E35CYNpLDia2chm_wnMcYvKFW9zC2ajRZ15i9c_VXQzS7ZlTaQYBFyMt7kVhxMEMFsPv1crD6t3uEI\ -j0LNuNYyy0jkon_LPZKQFK654CiL-L2YaNXOH4HbHP02dWeVQIE","e":"AQAB","ext":true,"ke\ -y_ops":["decrypt"],"kty":"RSA","n":"m1c92ZFk9ZI6l_O4YFiNxbv0Ng94SB3yThy1P_mcqr\ -GDQkRiGVdcTxAk38T9PgLztmspF-6U5TAHO-gSmmW88AC9m6f1Mspps6r7zl-M_OG-TwvGzf3BDz8z\ -Eg1FPbZV7whO1M4TCAZ0PqwG7qCc6nK1WiAhaKrSpzuPdL1igfNBsX7qu5wgw4ZTTGSLbVC_LfULQ5\ -FADgFTRXUSaxm1F8C_Lwy6a2e4nTcXilmtN2IHUjHegzm-Tq2HizmR3ARdWJpESYIW5-AXoiqj29tD\ -rqCmu2WPkB2psVp83IzZfaQNQzjNfvA8GpimkcDCkP5VMRrtKCcG4ZAFnO-A3NBX_Q","p":"2Q_lN\ -L7vCOBzAppYzCZo3WSh0hX-MOZyPUznks5U2TjmfdNZoL6_FJRiGyyLvwSiZFdEAAvpAyESFfFigng\ -AqMLSf448nPg15VUGj533CotsEM0WpoEr1JCgqdUbgDAfJQIBcwOmegBqd7lWm7uzEnRCvouB70ybk\ -JfpdprhkVE","q":"tzTt-F3g2u_3Ctj26Ho9iN_wC_W0lXGzslLt5nLmss8JqdLoDDrijjU-gjeRh\ -7lgiuHdUc3dorfFKbaMNOjoW3QKqt9oZ1JM0HKeRw0X2PnWW_0WK6DK5ASWDTXbMq2sUZqJvYEyL74\ -H2Zrt0RPAux7XQLEVgND6ROdXnMJ70O0","qi":"qfl4cXQkz4BNqa2De0-PfdU-8d1w3onnaGqx1D\ -s2fHzD_SJ4cNghn2TksoT9Qo64b3pUjH9igi2pyEjomk6D12N6FG0e10u7vFKv3W5YqUOgTpYdbcWH\ -dZ2qZWJU0XQZIrF8jLGTOO4GYP6_9sJ5R7Wk_0MdqQy8qvixWD4zLcY"}'); - key = await window.crypto.subtle.importKey("jwk", key, { - name: "RSA-OAEP", - hash: {name: "SHA-256"} - }, true, ["decrypt"]); - return {privateKey: key}; -} - -const receiveData = new Uint8Array([ - // server public key - 0x00, 0x00, 0x08, 0x00, 0xac, 0x1a, 0xbc, 0x42, - 0x8a, 0x2a, 0x69, 0x65, 0x54, 0xf8, 0x9a, 0xe6, - 0x43, 0xaa, 0xf7, 0x27, 0xf6, 0x2a, 0xf8, 0x8f, - 0x36, 0xd4, 0xae, 0x54, 0x0f, 0x16, 0x28, 0x08, - 0xc2, 0x5b, 0xca, 0x23, 0xdc, 0x27, 0x88, 0x1a, - 0x12, 0x82, 0xa8, 0x54, 0xea, 0x00, 0x99, 0x8d, - 0x02, 0x1d, 0x77, 0x4a, 0xeb, 0xd0, 0x93, 0x40, - 0x79, 0x86, 0xcb, 0x37, 0xd4, 0xb2, 0xc7, 0xcd, - 0x93, 0xe1, 0x00, 0x4d, 0x86, 0xff, 0x97, 0x33, - 0x0c, 0xad, 0x51, 0x47, 0x45, 0x85, 0x56, 0x07, - 0x65, 0x21, 0x7c, 0x57, 0x6d, 0x68, 0x7d, 0xd7, - 0x00, 0x43, 0x0c, 0x9d, 0x3b, 0xa1, 0x5a, 0x11, - 0xed, 0x51, 0x77, 0xf9, 0xd1, 0x5b, 0x33, 0xd7, - 0x1a, 0xeb, 0x65, 0x57, 0xc0, 0x01, 0x51, 0xff, - 0x9b, 0x82, 0xb3, 0xeb, 0x82, 0xc2, 0x1f, 0xca, - 0x47, 0xc0, 0x6a, 0x09, 0xe0, 0xf7, 0xda, 0x39, - 0x85, 0x12, 0xe7, 0x45, 0x8d, 0xb4, 0x1a, 0xda, - 0xcb, 0x86, 0x58, 0x52, 0x37, 0x66, 0x9d, 0x8a, - 0xce, 0xf2, 0x18, 0x78, 0x7d, 0x7f, 0xf0, 0x07, - 0x94, 0x8e, 0x6b, 0x17, 0xd9, 0x00, 0x2a, 0x3a, - 0xb9, 0xd4, 0x77, 0xde, 0x70, 0x85, 0xc4, 0x3a, - 0x62, 0x10, 0x02, 0xee, 0xba, 0xd8, 0xc0, 0x62, - 0xd0, 0x8e, 0xc1, 0x98, 0x19, 0x8e, 0x39, 0x0f, - 0x3e, 0x1d, 0x61, 0xb1, 0x93, 0x13, 0x59, 0x39, - 0xcb, 0x96, 0xf2, 0x17, 0xc9, 0xe1, 0x41, 0xd3, - 0x20, 0xdd, 0x62, 0x5e, 0x7d, 0x53, 0xd6, 0xb7, - 0x1d, 0xfe, 0x02, 0x18, 0x1f, 0xe0, 0xef, 0x3d, - 0x94, 0xe3, 0x0a, 0x9c, 0x59, 0x54, 0xd8, 0x98, - 0x16, 0x9c, 0x31, 0xda, 0x41, 0x0f, 0x2e, 0x71, - 0x68, 0xe0, 0xa2, 0x62, 0x3e, 0xe5, 0x25, 0x31, - 0xcf, 0xfc, 0x67, 0x63, 0xc3, 0xb0, 0xda, 0x3f, - 0x7b, 0x59, 0xbe, 0x7e, 0x9e, 0xa8, 0xd0, 0x01, - 0x4f, 0x43, 0x7f, 0x8d, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x01, - // server random - 0x01, 0x00, 0x5b, 0x58, 0x2a, 0x96, 0x2d, 0xbb, - 0x88, 0xec, 0xc3, 0x54, 0x00, 0xf3, 0xbb, 0xbe, - 0x17, 0xa3, 0x84, 0xd3, 0xef, 0xd8, 0x4a, 0x31, - 0x09, 0x20, 0xdd, 0xbc, 0x16, 0x9d, 0xc9, 0x5b, - 0x99, 0x62, 0x86, 0xfe, 0x0b, 0x28, 0x4b, 0xfe, - 0x5b, 0x56, 0x2d, 0xcb, 0x6e, 0x6f, 0xec, 0xf0, - 0x53, 0x0c, 0x33, 0x84, 0x93, 0xc9, 0xbf, 0x79, - 0xde, 0xb3, 0xb9, 0x29, 0x60, 0x78, 0xde, 0xe6, - 0x1d, 0xa7, 0x89, 0x48, 0x3f, 0xd1, 0x58, 0x66, - 0x27, 0x9c, 0xd4, 0x6e, 0x72, 0x9c, 0x6e, 0x4a, - 0xc0, 0x69, 0x79, 0x6f, 0x79, 0x0f, 0x13, 0xc4, - 0x20, 0xcf, 0xa6, 0xbb, 0xce, 0x18, 0x6d, 0xd5, - 0x9e, 0xd9, 0x67, 0xbe, 0x61, 0x43, 0x67, 0x11, - 0x76, 0x2f, 0xfd, 0x78, 0x75, 0x2b, 0x89, 0x35, - 0xdd, 0x0f, 0x13, 0x7f, 0xee, 0x78, 0xad, 0x32, - 0x56, 0x21, 0x81, 0x08, 0x1f, 0xcf, 0x4c, 0x29, - 0xa3, 0xeb, 0x89, 0x2d, 0xbe, 0xba, 0x8d, 0xe4, - 0x69, 0x28, 0xba, 0x53, 0x82, 0xce, 0x5c, 0xf6, - 0x5e, 0x5e, 0xa5, 0xb3, 0x88, 0xd8, 0x3d, 0xab, - 0xf4, 0x24, 0x9e, 0x3f, 0x04, 0xaf, 0xdc, 0x48, - 0x90, 0x53, 0x37, 0xe6, 0x82, 0x1d, 0xe0, 0x15, - 0x91, 0xa1, 0xc6, 0xa9, 0x54, 0xe5, 0x2a, 0xb5, - 0x64, 0x2d, 0x93, 0xc0, 0xc0, 0xe1, 0x0f, 0x6a, - 0x4b, 0xdb, 0x77, 0xf8, 0x4a, 0x0f, 0x83, 0x36, - 0xdd, 0x5e, 0x1e, 0xdd, 0x39, 0x65, 0xa2, 0x11, - 0xc2, 0xcf, 0x56, 0x1e, 0xa1, 0x29, 0xae, 0x11, - 0x9f, 0x3a, 0x82, 0xc7, 0xbd, 0x89, 0x6e, 0x59, - 0xb8, 0x59, 0x17, 0xcb, 0x65, 0xa0, 0x4b, 0x4d, - 0xbe, 0x33, 0x32, 0x85, 0x9c, 0xca, 0x5e, 0x95, - 0xc2, 0x5a, 0xd0, 0xc9, 0x8b, 0xf1, 0xf5, 0x14, - 0xcf, 0x76, 0x80, 0xc2, 0x24, 0x0a, 0x39, 0x7e, - 0x60, 0x64, 0xce, 0xd9, 0xb8, 0xad, 0x24, 0xa8, - 0xdf, 0xcb, - // server hash - 0x00, 0x14, 0x39, 0x30, 0x66, 0xb5, 0x66, 0x8a, - 0xcd, 0xb9, 0xda, 0xe0, 0xde, 0xcb, 0xf6, 0x47, - 0x5f, 0x54, 0x66, 0xe0, 0xbc, 0x49, 0x37, 0x01, - 0xf2, 0x9e, 0xef, 0xcc, 0xcd, 0x4d, 0x6c, 0x0e, - 0xc6, 0xab, 0x28, 0xd4, 0x7b, 0x13, - // subtype - 0x00, 0x01, 0x30, 0x2a, 0xc3, 0x0b, 0xc2, 0x1c, - 0xeb, 0x02, 0x44, 0x92, 0x5d, 0xfd, 0xf9, 0xa7, - 0x94, 0xd0, 0x19, -]); - -const sendData = new Uint8Array([ - // client public key - 0x00, 0x00, 0x08, 0x00, 0x9b, 0x57, 0x3d, 0xd9, - 0x91, 0x64, 0xf5, 0x92, 0x3a, 0x97, 0xf3, 0xb8, - 0x60, 0x58, 0x8d, 0xc5, 0xbb, 0xf4, 0x36, 0x0f, - 0x78, 0x48, 0x1d, 0xf2, 0x4e, 0x1c, 0xb5, 0x3f, - 0xf9, 0x9c, 0xaa, 0xb1, 0x83, 0x42, 0x44, 0x62, - 0x19, 0x57, 0x5c, 0x4f, 0x10, 0x24, 0xdf, 0xc4, - 0xfd, 0x3e, 0x02, 0xf3, 0xb6, 0x6b, 0x29, 0x17, - 0xee, 0x94, 0xe5, 0x30, 0x07, 0x3b, 0xe8, 0x12, - 0x9a, 0x65, 0xbc, 0xf0, 0x00, 0xbd, 0x9b, 0xa7, - 0xf5, 0x32, 0xca, 0x69, 0xb3, 0xaa, 0xfb, 0xce, - 0x5f, 0x8c, 0xfc, 0xe1, 0xbe, 0x4f, 0x0b, 0xc6, - 0xcd, 0xfd, 0xc1, 0x0f, 0x3f, 0x33, 0x12, 0x0d, - 0x45, 0x3d, 0xb6, 0x55, 0xef, 0x08, 0x4e, 0xd4, - 0xce, 0x13, 0x08, 0x06, 0x74, 0x3e, 0xac, 0x06, - 0xee, 0xa0, 0x9c, 0xea, 0x72, 0xb5, 0x5a, 0x20, - 0x21, 0x68, 0xaa, 0xd2, 0xa7, 0x3b, 0x8f, 0x74, - 0xbd, 0x62, 0x81, 0xf3, 0x41, 0xb1, 0x7e, 0xea, - 0xbb, 0x9c, 0x20, 0xc3, 0x86, 0x53, 0x4c, 0x64, - 0x8b, 0x6d, 0x50, 0xbf, 0x2d, 0xf5, 0x0b, 0x43, - 0x91, 0x40, 0x0e, 0x01, 0x53, 0x45, 0x75, 0x12, - 0x6b, 0x19, 0xb5, 0x17, 0xc0, 0xbf, 0x2f, 0x0c, - 0xba, 0x6b, 0x67, 0xb8, 0x9d, 0x37, 0x17, 0x8a, - 0x59, 0xad, 0x37, 0x62, 0x07, 0x52, 0x31, 0xde, - 0x83, 0x39, 0xbe, 0x4e, 0xad, 0x87, 0x8b, 0x39, - 0x91, 0xdc, 0x04, 0x5d, 0x58, 0x9a, 0x44, 0x49, - 0x82, 0x16, 0xe7, 0xe0, 0x17, 0xa2, 0x2a, 0xa3, - 0xdb, 0xdb, 0x43, 0xae, 0xa0, 0xa6, 0xbb, 0x65, - 0x8f, 0x90, 0x1d, 0xa9, 0xb1, 0x5a, 0x7c, 0xdc, - 0x8c, 0xd9, 0x7d, 0xa4, 0x0d, 0x43, 0x38, 0xcd, - 0x7e, 0xf0, 0x3c, 0x1a, 0x98, 0xa6, 0x91, 0xc0, - 0xc2, 0x90, 0xfe, 0x55, 0x31, 0x1a, 0xed, 0x28, - 0x27, 0x06, 0xe1, 0x90, 0x05, 0x9c, 0xef, 0x80, - 0xdc, 0xd0, 0x57, 0xfd, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x01, - // client random - 0x01, 0x00, 0x84, 0x7f, 0x26, 0x54, 0x74, 0xf6, - 0x47, 0xaf, 0x33, 0x64, 0x0d, 0xa6, 0xe5, 0x30, - 0xba, 0xe6, 0xe4, 0x8e, 0x50, 0x40, 0x71, 0x1c, - 0x0e, 0x06, 0x63, 0xf5, 0x07, 0x2a, 0x26, 0x68, - 0xd6, 0xcf, 0xa6, 0x80, 0x84, 0x5e, 0x64, 0xd4, - 0x5e, 0x62, 0x31, 0xfe, 0x44, 0x51, 0x0b, 0x7c, - 0x4d, 0x55, 0xc5, 0x4a, 0x7e, 0x0d, 0x4d, 0x9b, - 0x84, 0xb4, 0x32, 0x2b, 0x4d, 0x8a, 0x34, 0x8d, - 0xc8, 0xcf, 0x19, 0x3b, 0x64, 0x82, 0x27, 0x9e, - 0xa7, 0x70, 0x2a, 0xc1, 0xb8, 0xf3, 0x6a, 0x3a, - 0xf2, 0x75, 0x6e, 0x1d, 0xeb, 0xb6, 0x70, 0x7a, - 0x15, 0x18, 0x38, 0x00, 0xb4, 0x4f, 0x55, 0xb5, - 0xd8, 0x03, 0x4e, 0xb8, 0x53, 0xff, 0x80, 0x62, - 0xf1, 0x9d, 0x27, 0xe8, 0x2a, 0x3d, 0x98, 0x19, - 0x32, 0x09, 0x7e, 0x9a, 0xb0, 0xc7, 0x46, 0x23, - 0x10, 0x85, 0x35, 0x00, 0x96, 0xce, 0xb3, 0x2c, - 0x84, 0x8d, 0xf4, 0x9e, 0xa8, 0x42, 0x67, 0xed, - 0x09, 0xa6, 0x09, 0x97, 0xb3, 0x64, 0x26, 0xfb, - 0x71, 0x11, 0x9b, 0x3f, 0xbb, 0x57, 0xb8, 0x5b, - 0x2e, 0xc5, 0x2d, 0x8c, 0x5c, 0xf7, 0xef, 0x27, - 0x25, 0x88, 0x42, 0x45, 0x43, 0xa4, 0xe7, 0xde, - 0xea, 0xf9, 0x15, 0x7b, 0x5d, 0x66, 0x24, 0xce, - 0xf7, 0xc8, 0x2f, 0xc5, 0xc0, 0x3d, 0xcd, 0xf2, - 0x62, 0xfc, 0x1a, 0x5e, 0xec, 0xff, 0xf1, 0x1b, - 0xc8, 0xdb, 0xc1, 0x0f, 0x54, 0x66, 0x9e, 0xfd, - 0x99, 0x9b, 0x23, 0x70, 0x62, 0x37, 0x80, 0xad, - 0x91, 0x6b, 0x84, 0x85, 0x6a, 0x4c, 0x80, 0x9e, - 0x60, 0x8a, 0x93, 0xa3, 0xc8, 0x8e, 0xc4, 0x4b, - 0x4d, 0xb4, 0x8e, 0x3e, 0xaf, 0xce, 0xcd, 0x83, - 0xe5, 0x21, 0x90, 0x95, 0x20, 0x3c, 0x82, 0xb4, - 0x7c, 0xab, 0x63, 0x9c, 0xae, 0xc3, 0xc9, 0x71, - 0x1a, 0xec, 0x34, 0x18, 0x47, 0xec, 0x5c, 0x4d, - 0xed, 0x84, - // client hash - 0x00, 0x14, 0x9c, 0x91, 0x9e, 0x76, 0xcf, 0x1e, - 0x66, 0x87, 0x5e, 0x29, 0xf1, 0x13, 0x80, 0xea, - 0x7d, 0xec, 0xae, 0xf9, 0x60, 0x01, 0xd3, 0x6f, - 0xb7, 0x9e, 0xb2, 0xcd, 0x2d, 0xc8, 0xf8, 0x84, - 0xb2, 0x9f, 0xc3, 0x7e, 0xb4, 0xbe, - // credentials - 0x00, 0x08, 0x9d, 0xc8, 0x3a, 0xb8, 0x80, 0x4f, - 0xe3, 0x52, 0xdb, 0x62, 0x9e, 0x97, 0x64, 0x82, - 0xa8, 0xa1, 0x6b, 0x7e, 0x4d, 0x68, 0x8c, 0x29, - 0x91, 0x38, -]); - -describe('RA2 handshake', function () { - let sock; - let rfb; - let sentData; - - before(() => { - FakeWebSocket.replace(); - sinon.stub(window.crypto, "getRandomValues").callsFake(fakeGetRandomValues); - sinon.stub(window.crypto.subtle, "generateKey").callsFake(fakeGeneratekey); - }); - after(() => { - FakeWebSocket.restore(); - window.crypto.getRandomValues.restore(); - window.crypto.subtle.generateKey.restore(); - }); - - it('should fire the serververification event', function (done) { - sentData = new Uint8Array(); - rfb = new RFB(document.createElement('div'), "ws://example.com"); - sock = rfb._sock; - sock.send = (data) => { - let res = new Uint8Array(sentData.length + data.length); - res.set(sentData); - res.set(data, sentData.length); - sentData = res; - }; - rfb._rfbInitState = "Security"; - rfb._rfbVersion = 3.8; - sock._websocket._receiveData(new Uint8Array([1, 6])); - rfb.addEventListener("serververification", (e) => { - expect(e.detail.publickey).to.eql(receiveData.slice(0, 516)); - done(); - }); - sock._websocket._receiveData(receiveData); - }); - - it('should handle approveServer and fire the credentialsrequired event', function (done) { - rfb.addEventListener("credentialsrequired", (e) => { - expect(e.detail.types).to.eql(["password"]); - done(); - }); - rfb.approveServer(); - }); - - it('should match sendData after sending credentials', function (done) { - rfb.addEventListener("securityresult", (event) => { - expect(sentData.slice(1)).to.eql(sendData); - done(); - }); - rfb.sendCredentials({ "password": "123456" }); - }); -}); diff --git a/systemvm/agent/noVNC/tests/test.raw.js b/systemvm/agent/noVNC/tests/test.raw.js deleted file mode 100644 index bc7adc78e10f..000000000000 --- a/systemvm/agent/noVNC/tests/test.raw.js +++ /dev/null @@ -1,129 +0,0 @@ -const expect = chai.expect; - -import Websock from '../core/websock.js'; -import Display from '../core/display.js'; - -import RawDecoder from '../core/decoders/raw.js'; - -import FakeWebSocket from './fake.websocket.js'; - -function testDecodeRect(decoder, x, y, width, height, data, display, depth) { - let sock; - - sock = new Websock; - sock.open("ws://example.com"); - - sock.on('message', () => { - decoder.decodeRect(x, y, width, height, sock, display, depth); - }); - - // Empty messages are filtered at multiple layers, so we need to - // do a direct call - if (data.length === 0) { - decoder.decodeRect(x, y, width, height, sock, display, depth); - } else { - sock._websocket._receiveData(new Uint8Array(data)); - } - - display.flip(); -} - -describe('Raw Decoder', function () { - let decoder; - let display; - - before(FakeWebSocket.replace); - after(FakeWebSocket.restore); - - beforeEach(function () { - decoder = new RawDecoder(); - display = new Display(document.createElement('canvas')); - display.resize(4, 4); - }); - - it('should handle the Raw encoding', function () { - testDecodeRect(decoder, 0, 0, 2, 2, - [0xff, 0x00, 0x00, 0, 0x00, 0xff, 0x00, 0, - 0x00, 0xff, 0x00, 0, 0xff, 0x00, 0x00, 0], - display, 24); - testDecodeRect(decoder, 2, 0, 2, 2, - [0x00, 0x00, 0xff, 0, 0x00, 0x00, 0xff, 0, - 0x00, 0x00, 0xff, 0, 0x00, 0x00, 0xff, 0], - display, 24); - testDecodeRect(decoder, 0, 2, 4, 1, - [0xee, 0x00, 0xff, 0, 0x00, 0xee, 0xff, 0, - 0xaa, 0xee, 0xff, 0, 0xab, 0xee, 0xff, 0], - display, 24); - testDecodeRect(decoder, 0, 3, 4, 1, - [0xee, 0x00, 0xff, 0, 0x00, 0xee, 0xff, 0, - 0xaa, 0xee, 0xff, 0, 0xab, 0xee, 0xff, 0], - display, 24); - - let targetData = new Uint8Array([ - 0xff, 0x00, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0xff, 0x00, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0xee, 0x00, 0xff, 255, 0x00, 0xee, 0xff, 255, 0xaa, 0xee, 0xff, 255, 0xab, 0xee, 0xff, 255, - 0xee, 0x00, 0xff, 255, 0x00, 0xee, 0xff, 255, 0xaa, 0xee, 0xff, 255, 0xab, 0xee, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle the Raw encoding in low colour mode', function () { - testDecodeRect(decoder, 0, 0, 2, 2, - [0x30, 0x30, 0x30, 0x30], - display, 8); - testDecodeRect(decoder, 2, 0, 2, 2, - [0x0c, 0x0c, 0x0c, 0x0c], - display, 8); - testDecodeRect(decoder, 0, 2, 4, 1, - [0x0c, 0x0c, 0x30, 0x30], - display, 8); - testDecodeRect(decoder, 0, 3, 4, 1, - [0x0c, 0x0c, 0x30, 0x30], - display, 8); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle empty rects', function () { - display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]); - display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]); - display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]); - - testDecodeRect(decoder, 1, 2, 0, 0, [], display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle empty rects in low colour mode', function () { - display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]); - display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]); - display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]); - - testDecodeRect(decoder, 1, 2, 0, 0, [], display, 8); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); -}); diff --git a/systemvm/agent/noVNC/tests/test.rre.js b/systemvm/agent/noVNC/tests/test.rre.js deleted file mode 100644 index 8e006f87763b..000000000000 --- a/systemvm/agent/noVNC/tests/test.rre.js +++ /dev/null @@ -1,107 +0,0 @@ -const expect = chai.expect; - -import Websock from '../core/websock.js'; -import Display from '../core/display.js'; - -import RREDecoder from '../core/decoders/rre.js'; - -import FakeWebSocket from './fake.websocket.js'; - -function testDecodeRect(decoder, x, y, width, height, data, display, depth) { - let sock; - - sock = new Websock; - sock.open("ws://example.com"); - - sock.on('message', () => { - decoder.decodeRect(x, y, width, height, sock, display, depth); - }); - - // Empty messages are filtered at multiple layers, so we need to - // do a direct call - if (data.length === 0) { - decoder.decodeRect(x, y, width, height, sock, display, depth); - } else { - sock._websocket._receiveData(new Uint8Array(data)); - } - - display.flip(); -} - -function push16(arr, num) { - arr.push((num >> 8) & 0xFF, - num & 0xFF); -} - -function push32(arr, num) { - arr.push((num >> 24) & 0xFF, - (num >> 16) & 0xFF, - (num >> 8) & 0xFF, - num & 0xFF); -} - -describe('RRE Decoder', function () { - let decoder; - let display; - - before(FakeWebSocket.replace); - after(FakeWebSocket.restore); - - beforeEach(function () { - decoder = new RREDecoder(); - display = new Display(document.createElement('canvas')); - display.resize(4, 4); - }); - - // TODO(directxman12): test rre_chunk_sz? - - it('should handle the RRE encoding', function () { - let data = []; - push32(data, 2); // 2 subrects - push32(data, 0x00ff0000); // becomes 00ff0000 --> #00FF00 bg color - data.push(0x00); // becomes 0000ff00 --> #0000FF fg color - data.push(0x00); - data.push(0xff); - data.push(0x00); - push16(data, 0); // x: 0 - push16(data, 0); // y: 0 - push16(data, 2); // width: 2 - push16(data, 2); // height: 2 - data.push(0x00); // becomes 0000ff00 --> #0000FF fg color - data.push(0x00); - data.push(0xff); - data.push(0x00); - push16(data, 2); // x: 2 - push16(data, 2); // y: 2 - push16(data, 2); // width: 2 - push16(data, 2); // height: 2 - - testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle empty rects', function () { - display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]); - display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]); - display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]); - - testDecodeRect(decoder, 1, 2, 0, 0, [ 0x00, 0xff, 0xff, 0xff, 0xff ], display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); -}); diff --git a/systemvm/agent/noVNC/tests/test.tight.js b/systemvm/agent/noVNC/tests/test.tight.js deleted file mode 100644 index cc5db36b5d39..000000000000 --- a/systemvm/agent/noVNC/tests/test.tight.js +++ /dev/null @@ -1,394 +0,0 @@ -const expect = chai.expect; - -import Websock from '../core/websock.js'; -import Display from '../core/display.js'; - -import TightDecoder from '../core/decoders/tight.js'; - -import FakeWebSocket from './fake.websocket.js'; - -function testDecodeRect(decoder, x, y, width, height, data, display, depth) { - let sock; - - sock = new Websock; - sock.open("ws://example.com"); - - sock.on('message', () => { - decoder.decodeRect(x, y, width, height, sock, display, depth); - }); - - // Empty messages are filtered at multiple layers, so we need to - // do a direct call - if (data.length === 0) { - decoder.decodeRect(x, y, width, height, sock, display, depth); - } else { - sock._websocket._receiveData(new Uint8Array(data)); - } - - display.flip(); -} - -describe('Tight Decoder', function () { - let decoder; - let display; - - before(FakeWebSocket.replace); - after(FakeWebSocket.restore); - - beforeEach(function () { - decoder = new TightDecoder(); - display = new Display(document.createElement('canvas')); - display.resize(4, 4); - }); - - it('should handle fill rects', function () { - testDecodeRect(decoder, 0, 0, 4, 4, - [0x80, 0xff, 0x88, 0x44], - display, 24); - - let targetData = new Uint8Array([ - 0xff, 0x88, 0x44, 255, 0xff, 0x88, 0x44, 255, 0xff, 0x88, 0x44, 255, 0xff, 0x88, 0x44, 255, - 0xff, 0x88, 0x44, 255, 0xff, 0x88, 0x44, 255, 0xff, 0x88, 0x44, 255, 0xff, 0x88, 0x44, 255, - 0xff, 0x88, 0x44, 255, 0xff, 0x88, 0x44, 255, 0xff, 0x88, 0x44, 255, 0xff, 0x88, 0x44, 255, - 0xff, 0x88, 0x44, 255, 0xff, 0x88, 0x44, 255, 0xff, 0x88, 0x44, 255, 0xff, 0x88, 0x44, 255, - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle uncompressed copy rects', function () { - let blueData = [ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff ]; - let greenData = [ 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00 ]; - - testDecodeRect(decoder, 0, 0, 2, 1, blueData, display, 24); - testDecodeRect(decoder, 0, 1, 2, 1, blueData, display, 24); - testDecodeRect(decoder, 2, 0, 2, 1, greenData, display, 24); - testDecodeRect(decoder, 2, 1, 2, 1, greenData, display, 24); - testDecodeRect(decoder, 0, 2, 2, 1, greenData, display, 24); - testDecodeRect(decoder, 0, 3, 2, 1, greenData, display, 24); - testDecodeRect(decoder, 2, 2, 2, 1, blueData, display, 24); - testDecodeRect(decoder, 2, 3, 2, 1, blueData, display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle compressed copy rects', function () { - let data = [ - // Control byte - 0x00, - // Pixels (compressed) - 0x15, - 0x78, 0x9c, 0x63, 0x60, 0xf8, 0xcf, 0x00, 0x44, - 0x60, 0x82, 0x01, 0x99, 0x8d, 0x29, 0x02, 0xa6, - 0x00, 0x7e, 0xbf, 0x0f, 0xf1 ]; - - testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle uncompressed mono rects', function () { - let data = [ - // Control bytes - 0x40, 0x01, - // Palette - 0x01, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, - // Pixels - 0x30, 0x30, 0xc0, 0xc0 ]; - - testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle compressed mono rects', function () { - display.resize(4, 12); - - let data = [ - // Control bytes - 0x40, 0x01, - // Palette - 0x01, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, - // Pixels (compressed) - 0x0e, - 0x78, 0x9c, 0x33, 0x30, 0x38, 0x70, 0xc0, 0x00, - 0x8a, 0x01, 0x21, 0x3c, 0x05, 0xa1 ]; - - testDecodeRect(decoder, 0, 0, 4, 12, data, display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle uncompressed palette rects', function () { - let data1 = [ - // Control bytes - 0x40, 0x01, - // Palette - 0x02, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - // Pixels - 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01 ]; - let data2 = [ - // Control bytes - 0x40, 0x01, - // Palette - 0x02, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - // Pixels - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00 ]; - - testDecodeRect(decoder, 0, 0, 4, 2, data1, display, 24); - testDecodeRect(decoder, 0, 2, 4, 2, data2, display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle compressed palette rects', function () { - let data = [ - // Control bytes - 0x40, 0x01, - // Palette - 0x02, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - // Pixels (compressed) - 0x12, - 0x78, 0x9c, 0x63, 0x60, 0x60, 0x64, 0x64, 0x00, - 0x62, 0x08, 0xc9, 0xc0, 0x00, 0x00, 0x00, 0x54, - 0x00, 0x09 ]; - - testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it.skip('should handle uncompressed gradient rects', function () { - // Not implemented yet - }); - - it.skip('should handle compressed gradient rects', function () { - // Not implemented yet - }); - - it('should handle empty copy rects', function () { - display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]); - display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]); - display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]); - - testDecodeRect(decoder, 1, 2, 0, 0, [ 0x00 ], display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle empty palette rects', function () { - display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]); - display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]); - display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]); - - testDecodeRect(decoder, 1, 2, 0, 0, - [ 0x40, 0x01, 0x01, - 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff ], display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle empty fill rects', function () { - display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]); - display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]); - display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]); - - testDecodeRect(decoder, 1, 2, 0, 0, - [ 0x80, 0xff, 0xff, 0xff ], display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle JPEG rects', function (done) { - let data = [ - // Control bytes - 0x90, 0xd6, 0x05, - // JPEG data - 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, - 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x48, - 0x00, 0x48, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x13, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, - 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, - 0x50, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xff, 0xdb, - 0x00, 0x43, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0xff, 0xc2, 0x00, 0x11, 0x08, - 0x00, 0x04, 0x00, 0x04, 0x03, 0x01, 0x11, 0x00, - 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, - 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x07, 0xff, 0xc4, 0x00, 0x14, - 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x08, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, - 0x00, 0x02, 0x10, 0x03, 0x10, 0x00, 0x00, 0x01, - 0x1e, 0x0a, 0xa7, 0x7f, 0xff, 0xc4, 0x00, 0x14, - 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x05, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, - 0x00, 0x01, 0x05, 0x02, 0x5d, 0x74, 0x41, 0x47, - 0xff, 0xc4, 0x00, 0x1f, 0x11, 0x00, 0x01, 0x04, - 0x02, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x05, - 0x07, 0x08, 0x14, 0x16, 0x03, 0x15, 0x17, 0x25, - 0x26, 0xff, 0xda, 0x00, 0x08, 0x01, 0x03, 0x01, - 0x01, 0x3f, 0x01, 0xad, 0x35, 0xa6, 0x13, 0xb8, - 0x10, 0x98, 0x5d, 0x8a, 0xb1, 0x41, 0x7e, 0x43, - 0x99, 0x24, 0x3d, 0x8f, 0x70, 0x30, 0xd8, 0xcb, - 0x44, 0xbb, 0x7d, 0x48, 0xb5, 0xf8, 0x18, 0x7f, - 0xe7, 0xc1, 0x9f, 0x86, 0x45, 0x9b, 0xfa, 0xf1, - 0x61, 0x96, 0x46, 0xbf, 0x56, 0xc8, 0x8b, 0x2b, - 0x0b, 0x35, 0x6e, 0x4b, 0x8a, 0x95, 0x6a, 0xf9, - 0xff, 0x00, 0xff, 0xc4, 0x00, 0x1f, 0x11, 0x00, - 0x01, 0x04, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x02, 0x04, 0x05, 0x12, 0x13, 0x14, 0x01, 0x06, - 0x11, 0x22, 0x23, 0xff, 0xda, 0x00, 0x08, 0x01, - 0x02, 0x01, 0x01, 0x3f, 0x01, 0x85, 0x85, 0x8c, - 0xec, 0x31, 0x8d, 0xa6, 0x26, 0x1b, 0x6e, 0x48, - 0xbc, 0xcd, 0xb0, 0xe3, 0x33, 0x86, 0xf9, 0x35, - 0xdc, 0x15, 0xa8, 0xbe, 0x4d, 0x4a, 0x10, 0x22, - 0x80, 0x00, 0x91, 0xe8, 0x24, 0xda, 0xb6, 0x57, - 0x95, 0xf2, 0xa5, 0x73, 0xff, 0xc4, 0x00, 0x1e, - 0x10, 0x00, 0x01, 0x04, 0x03, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x02, 0x04, 0x12, 0x05, 0x11, - 0x13, 0x14, 0x22, 0x23, 0xff, 0xda, 0x00, 0x08, - 0x01, 0x01, 0x00, 0x06, 0x3f, 0x02, 0x91, 0x89, - 0xc4, 0xc8, 0xf1, 0x60, 0x45, 0xe5, 0xc0, 0x1c, - 0x80, 0x7a, 0x77, 0x00, 0xe4, 0x97, 0xeb, 0x24, - 0x66, 0x33, 0xac, 0x63, 0x11, 0xfe, 0xe4, 0x76, - 0xad, 0x56, 0xe9, 0xa8, 0x88, 0x9f, 0xff, 0xc4, - 0x00, 0x14, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xda, 0x00, 0x08, - 0x01, 0x01, 0x00, 0x01, 0x3f, 0x21, 0x68, 0x3f, - 0x92, 0x17, 0x81, 0x1f, 0x7f, 0xff, 0xda, 0x00, - 0x0c, 0x03, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x10, 0x5f, 0xff, 0xc4, 0x00, 0x14, - 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xda, 0x00, 0x08, 0x01, 0x03, - 0x01, 0x01, 0x3f, 0x10, 0x03, 0xeb, 0x11, 0xe4, - 0xa7, 0xe3, 0xff, 0x00, 0xff, 0xc4, 0x00, 0x14, - 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xda, 0x00, 0x08, 0x01, 0x02, - 0x01, 0x01, 0x3f, 0x10, 0x6b, 0xd3, 0x02, 0xdc, - 0x9a, 0xf4, 0xff, 0x00, 0xff, 0xc4, 0x00, 0x14, - 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, - 0x00, 0x01, 0x3f, 0x10, 0x62, 0x7b, 0x3a, 0xd0, - 0x3f, 0xeb, 0xff, 0x00, 0xff, 0xd9, - ]; - - testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24); - - let targetData = new Uint8Array([ - 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255 - ]); - - // Browsers have rounding errors, so we need an approximate - // comparing function - function almost(a, b) { - let diff = Math.abs(a - b); - return diff < 5; - } - - display.onflush = () => { - expect(display).to.have.displayed(targetData, almost); - done(); - }; - display.flush(); - }); -}); diff --git a/systemvm/agent/noVNC/tests/test.tightpng.js b/systemvm/agent/noVNC/tests/test.tightpng.js deleted file mode 100644 index 253400b878b6..000000000000 --- a/systemvm/agent/noVNC/tests/test.tightpng.js +++ /dev/null @@ -1,144 +0,0 @@ -const expect = chai.expect; - -import Websock from '../core/websock.js'; -import Display from '../core/display.js'; - -import TightPngDecoder from '../core/decoders/tightpng.js'; - -import FakeWebSocket from './fake.websocket.js'; - -function testDecodeRect(decoder, x, y, width, height, data, display, depth) { - let sock; - - sock = new Websock; - sock.open("ws://example.com"); - - sock.on('message', () => { - decoder.decodeRect(x, y, width, height, sock, display, depth); - }); - - // Empty messages are filtered at multiple layers, so we need to - // do a direct call - if (data.length === 0) { - decoder.decodeRect(x, y, width, height, sock, display, depth); - } else { - sock._websocket._receiveData(new Uint8Array(data)); - } - - display.flip(); -} - -describe('TightPng Decoder', function () { - let decoder; - let display; - - before(FakeWebSocket.replace); - after(FakeWebSocket.restore); - - beforeEach(function () { - decoder = new TightPngDecoder(); - display = new Display(document.createElement('canvas')); - display.resize(4, 4); - }); - - it('should handle the TightPng encoding', function (done) { - let data = [ - // Control bytes - 0xa0, 0xb4, 0x04, - // PNG data - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, - 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, - 0x08, 0x02, 0x00, 0x00, 0x00, 0x26, 0x93, 0x09, - 0x29, 0x00, 0x00, 0x01, 0x84, 0x69, 0x43, 0x43, - 0x50, 0x49, 0x43, 0x43, 0x20, 0x70, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x28, 0x91, - 0x7d, 0x91, 0x3d, 0x48, 0xc3, 0x40, 0x18, 0x86, - 0xdf, 0xa6, 0x6a, 0x45, 0x2a, 0x0e, 0x76, 0x10, - 0x71, 0x08, 0x52, 0x9d, 0x2c, 0x88, 0x8a, 0x38, - 0x6a, 0x15, 0x8a, 0x50, 0x21, 0xd4, 0x0a, 0xad, - 0x3a, 0x98, 0x5c, 0xfa, 0x07, 0x4d, 0x1a, 0x92, - 0x14, 0x17, 0x47, 0xc1, 0xb5, 0xe0, 0xe0, 0xcf, - 0x62, 0xd5, 0xc1, 0xc5, 0x59, 0x57, 0x07, 0x57, - 0x41, 0x10, 0xfc, 0x01, 0x71, 0x72, 0x74, 0x52, - 0x74, 0x91, 0x12, 0xbf, 0x4b, 0x0a, 0x2d, 0x62, - 0xbc, 0xe3, 0xb8, 0x87, 0xf7, 0xbe, 0xf7, 0xe5, - 0xee, 0x3b, 0x40, 0xa8, 0x97, 0x99, 0x66, 0x75, - 0x8c, 0x03, 0x9a, 0x6e, 0x9b, 0xa9, 0x44, 0x5c, - 0xcc, 0x64, 0x57, 0xc5, 0xd0, 0x2b, 0xba, 0x68, - 0x86, 0x31, 0x8c, 0x2e, 0x99, 0x59, 0xc6, 0x9c, - 0x24, 0x25, 0xe1, 0x3b, 0xbe, 0xee, 0x11, 0xe0, - 0xfb, 0x5d, 0x8c, 0x67, 0xf9, 0xd7, 0xfd, 0x39, - 0x7a, 0xd5, 0x9c, 0xc5, 0x80, 0x80, 0x48, 0x3c, - 0xcb, 0x0c, 0xd3, 0x26, 0xde, 0x20, 0x9e, 0xde, - 0xb4, 0x0d, 0xce, 0xfb, 0xc4, 0x11, 0x56, 0x94, - 0x55, 0xe2, 0x73, 0xe2, 0x31, 0x93, 0x2e, 0x48, - 0xfc, 0xc8, 0x75, 0xc5, 0xe3, 0x37, 0xce, 0x05, - 0x97, 0x05, 0x9e, 0x19, 0x31, 0xd3, 0xa9, 0x79, - 0xe2, 0x08, 0xb1, 0x58, 0x68, 0x63, 0xa5, 0x8d, - 0x59, 0xd1, 0xd4, 0x88, 0xa7, 0x88, 0xa3, 0xaa, - 0xa6, 0x53, 0xbe, 0x90, 0xf1, 0x58, 0xe5, 0xbc, - 0xc5, 0x59, 0x2b, 0x57, 0x59, 0xf3, 0x9e, 0xfc, - 0x85, 0xe1, 0x9c, 0xbe, 0xb2, 0xcc, 0x75, 0x5a, - 0x43, 0x48, 0x60, 0x11, 0x4b, 0x90, 0x20, 0x42, - 0x41, 0x15, 0x25, 0x94, 0x61, 0x23, 0x46, 0xbb, - 0x4e, 0x8a, 0x85, 0x14, 0x9d, 0xc7, 0x7d, 0xfc, - 0x83, 0xae, 0x5f, 0x22, 0x97, 0x42, 0xae, 0x12, - 0x18, 0x39, 0x16, 0x50, 0x81, 0x06, 0xd9, 0xf5, - 0x83, 0xff, 0xc1, 0xef, 0xde, 0x5a, 0xf9, 0xc9, - 0x09, 0x2f, 0x29, 0x1c, 0x07, 0x3a, 0x5f, 0x1c, - 0xe7, 0x63, 0x04, 0x08, 0xed, 0x02, 0x8d, 0x9a, - 0xe3, 0x7c, 0x1f, 0x3b, 0x4e, 0xe3, 0x04, 0x08, - 0x3e, 0x03, 0x57, 0x7a, 0xcb, 0x5f, 0xa9, 0x03, - 0x33, 0x9f, 0xa4, 0xd7, 0x5a, 0x5a, 0xf4, 0x08, - 0xe8, 0xdb, 0x06, 0x2e, 0xae, 0x5b, 0x9a, 0xb2, - 0x07, 0x5c, 0xee, 0x00, 0x03, 0x4f, 0x86, 0x6c, - 0xca, 0xae, 0x14, 0xa4, 0x25, 0xe4, 0xf3, 0xc0, - 0xfb, 0x19, 0x7d, 0x53, 0x16, 0xe8, 0xbf, 0x05, - 0x7a, 0xd6, 0xbc, 0xbe, 0x35, 0xcf, 0x71, 0xfa, - 0x00, 0xa4, 0xa9, 0x57, 0xc9, 0x1b, 0xe0, 0xe0, - 0x10, 0x18, 0x2d, 0x50, 0xf6, 0xba, 0xcf, 0xbb, - 0xbb, 0xdb, 0xfb, 0xf6, 0x6f, 0x4d, 0xb3, 0x7f, - 0x3f, 0x0a, 0x27, 0x72, 0x7d, 0x49, 0x29, 0x8b, - 0xbb, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, - 0x73, 0x00, 0x00, 0x2e, 0x23, 0x00, 0x00, 0x2e, - 0x23, 0x01, 0x78, 0xa5, 0x3f, 0x76, 0x00, 0x00, - 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xe4, - 0x06, 0x06, 0x0c, 0x23, 0x1d, 0x3f, 0x9f, 0xbb, - 0x94, 0x00, 0x00, 0x00, 0x19, 0x74, 0x45, 0x58, - 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, - 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, - 0x4d, 0x50, 0x57, 0x81, 0x0e, 0x17, 0x00, 0x00, - 0x00, 0x1e, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, - 0x65, 0xc9, 0xb1, 0x0d, 0x00, 0x00, 0x08, 0x03, - 0x20, 0xea, 0xff, 0x3f, 0xd7, 0xd5, 0x44, 0x56, - 0x52, 0x90, 0xc2, 0x38, 0xa2, 0xd0, 0xbc, 0x59, - 0x8a, 0x9f, 0x04, 0x05, 0x6b, 0x38, 0x7b, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, - 0xae, 0x42, 0x60, 0x82, - ]; - - testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24); - - let targetData = new Uint8Array([ - 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255, - 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0xff, 0x00, 0x00, 255, 0xff, 0x00, 0x00, 255 - ]); - - // Firefox currently has some very odd rounding bug: - // https://bugzilla.mozilla.org/show_bug.cgi?id=1667747 - function almost(a, b) { - let diff = Math.abs(a - b); - return diff < 30; - } - - display.onflush = () => { - expect(display).to.have.displayed(targetData, almost); - done(); - }; - display.flush(); - }); -}); diff --git a/systemvm/agent/noVNC/tests/test.zrle.js b/systemvm/agent/noVNC/tests/test.zrle.js deleted file mode 100644 index e09d208da965..000000000000 --- a/systemvm/agent/noVNC/tests/test.zrle.js +++ /dev/null @@ -1,124 +0,0 @@ -const expect = chai.expect; - -import Websock from '../core/websock.js'; -import Display from '../core/display.js'; - -import ZRLEDecoder from '../core/decoders/zrle.js'; - -import FakeWebSocket from './fake.websocket.js'; - -function testDecodeRect(decoder, x, y, width, height, data, display, depth) { - let sock; - - sock = new Websock; - sock.open("ws://example.com"); - - sock.on('message', () => { - decoder.decodeRect(x, y, width, height, sock, display, depth); - }); - - // Empty messages are filtered at multiple layers, so we need to - // do a direct call - if (data.length === 0) { - decoder.decodeRect(x, y, width, height, sock, display, depth); - } else { - sock._websocket._receiveData(new Uint8Array(data)); - } - - display.flip(); -} - -describe('ZRLE Decoder', function () { - let decoder; - let display; - - before(FakeWebSocket.replace); - after(FakeWebSocket.restore); - - beforeEach(function () { - decoder = new ZRLEDecoder(); - display = new Display(document.createElement('canvas')); - display.resize(4, 4); - }); - - it('should handle the Raw subencoding', function () { - testDecodeRect(decoder, 0, 0, 4, 4, - [0x00, 0x00, 0x00, 0x0e, 0x78, 0x5e, 0x62, 0x60, 0x60, 0xf8, 0x4f, 0x12, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff], - display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle the Solid subencoding', function () { - testDecodeRect(decoder, 0, 0, 4, 4, - [0x00, 0x00, 0x00, 0x0c, 0x78, 0x5e, 0x62, 0x64, 0x60, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0xff, 0xff], - display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff - ]); - - expect(display).to.have.displayed(targetData); - }); - - - it('should handle the Palette Tile subencoding', function () { - testDecodeRect(decoder, 0, 0, 4, 4, - [0x00, 0x00, 0x00, 0x12, 0x78, 0x5E, 0x62, 0x62, 0x60, 248, 0xff, 0x9F, 0x01, 0x08, 0x3E, 0x7C, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff], - display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle the RLE Tile subencoding', function () { - testDecodeRect(decoder, 0, 0, 4, 4, - [0x00, 0x00, 0x00, 0x0d, 0x78, 0x5e, 0x6a, 0x60, 0x60, 0xf8, 0x2f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff], - display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should handle the RLE Palette Tile subencoding', function () { - testDecodeRect(decoder, 0, 0, 4, 4, - [0x00, 0x00, 0x00, 0x11, 0x78, 0x5e, 0x6a, 0x62, 0x60, 0xf8, 0xff, 0x9f, 0x81, 0xa1, 0x81, 0x1f, 0x00, 0x00, 0x00, 0xff, 0xff], - display, 24); - - let targetData = new Uint8Array([ - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff - ]); - - expect(display).to.have.displayed(targetData); - }); - - it('should fail on an invalid subencoding', function () { - let data = [0x00, 0x00, 0x00, 0x0c, 0x78, 0x5e, 0x6a, 0x64, 0x60, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0xff, 0xff]; - expect(() => testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24)).to.throw(); - }); -}); From 73078d84fb62a90a0262e2e698563b1131dd0eb1 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Wed, 5 Apr 2023 09:47:43 +0200 Subject: [PATCH 5/5] noVNC: remove systemvm/agent/noVNC/.github/ --- .../agent/noVNC/.github/ISSUE_TEMPLATE/config.yml | 5 ----- .../agent/noVNC/.github/workflows/translate.yml | 15 --------------- 2 files changed, 20 deletions(-) delete mode 100644 systemvm/agent/noVNC/.github/ISSUE_TEMPLATE/config.yml delete mode 100644 systemvm/agent/noVNC/.github/workflows/translate.yml diff --git a/systemvm/agent/noVNC/.github/ISSUE_TEMPLATE/config.yml b/systemvm/agent/noVNC/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index cbd35aa752b2..000000000000 --- a/systemvm/agent/noVNC/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,5 +0,0 @@ -blank_issues_enabled: false -contact_links: - - name: Question or discussion - url: https://groups.google.com/forum/?fromgroups#!forum/novnc - about: Ask a question or start a discussion diff --git a/systemvm/agent/noVNC/.github/workflows/translate.yml b/systemvm/agent/noVNC/.github/workflows/translate.yml deleted file mode 100644 index ea6e6bb36b5f..000000000000 --- a/systemvm/agent/noVNC/.github/workflows/translate.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Translate - -on: [push, pull_request] - -jobs: - translate: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - - run: npm update - - run: sudo apt-get install gettext - - run: make -C po update-pot - - run: make -C po update-po - - run: make -C po update-js