Handle sending large clipboards
Pasting clipboard texts that were larger than 10240 bytes didnt work and caused a crash in noVNC. This commit fixes the crash and adds handling for sending large clipboard texts. Fixes issue #1065.
This commit is contained in:
parent
43bbaa8d6e
commit
2bb8b28d78
43
core/rfb.js
43
core/rfb.js
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* noVNC: HTML5 VNC client
|
* noVNC: HTML5 VNC client
|
||||||
* Copyright (C) 2012 Joel Martin
|
* Copyright (C) 2012 Joel Martin
|
||||||
* Copyright (C) 2017 Samuel Mannehed for Cendio AB
|
* Copyright (C) 2018 Samuel Mannehed for Cendio AB
|
||||||
* Licensed under MPL 2.0 (see LICENSE.txt)
|
* Licensed under MPL 2.0 (see LICENSE.txt)
|
||||||
*
|
*
|
||||||
* See README.md for usage and integration instructions.
|
* See README.md for usage and integration instructions.
|
||||||
|
@ -1688,19 +1688,40 @@ RFB.messages = {
|
||||||
buff[offset + 2] = 0; // padding
|
buff[offset + 2] = 0; // padding
|
||||||
buff[offset + 3] = 0; // padding
|
buff[offset + 3] = 0; // padding
|
||||||
|
|
||||||
var n = text.length;
|
let length = text.length;
|
||||||
|
|
||||||
buff[offset + 4] = n >> 24;
|
buff[offset + 4] = length >> 24;
|
||||||
buff[offset + 5] = n >> 16;
|
buff[offset + 5] = length >> 16;
|
||||||
buff[offset + 6] = n >> 8;
|
buff[offset + 6] = length >> 8;
|
||||||
buff[offset + 7] = n;
|
buff[offset + 7] = length;
|
||||||
|
|
||||||
for (var i = 0; i < n; i++) {
|
sock._sQlen += 8;
|
||||||
buff[offset + 8 + i] = text.charCodeAt(i);
|
|
||||||
|
// We have to keep track of from where in the text we begin creating the
|
||||||
|
// buffer for the flush in the next iteration.
|
||||||
|
let textOffset = 0;
|
||||||
|
|
||||||
|
let remaining = length;
|
||||||
|
while (remaining > 0) {
|
||||||
|
|
||||||
|
let flushSize = Math.min(remaining, (sock._sQbufferSize - sock._sQlen));
|
||||||
|
if (flushSize <= 0) {
|
||||||
|
this._fail("Clipboard contents could not be sent");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = sock._sQlen;
|
||||||
|
|
||||||
|
for (let i = 0; i < flushSize; i++) {
|
||||||
|
buff[offset + i] = text.charCodeAt(textOffset + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
sock._sQlen += flushSize;
|
||||||
|
sock.flush();
|
||||||
|
|
||||||
|
remaining -= flushSize;
|
||||||
|
textOffset += flushSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
sock._sQlen += 8 + n;
|
|
||||||
sock.flush();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setDesktopSize: function (sock, width, height, id, flags) {
|
setDesktopSize: function (sock, width, height, id, flags) {
|
||||||
|
|
|
@ -287,12 +287,23 @@ describe('Remote Frame Buffer Protocol Client', function() {
|
||||||
|
|
||||||
describe('#clipboardPasteFrom', function () {
|
describe('#clipboardPasteFrom', function () {
|
||||||
it('should send the given text in a paste event', function () {
|
it('should send the given text in a paste event', function () {
|
||||||
var expected = {_sQ: new Uint8Array(11), _sQlen: 0, flush: function () {}};
|
var expected = {_sQ: new Uint8Array(11), _sQlen: 0,
|
||||||
|
_sQbufferSize: 11, flush: function () {}};
|
||||||
RFB.messages.clientCutText(expected, 'abc');
|
RFB.messages.clientCutText(expected, 'abc');
|
||||||
client.clipboardPasteFrom('abc');
|
client.clipboardPasteFrom('abc');
|
||||||
expect(client._sock).to.have.sent(expected._sQ);
|
expect(client._sock).to.have.sent(expected._sQ);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should flush multiple times for large clipboards', function () {
|
||||||
|
sinon.spy(client._sock, 'flush');
|
||||||
|
let long_text = "";
|
||||||
|
for (let i = 0; i < client._sock._sQbufferSize + 100; i++) {
|
||||||
|
long_text += 'a';
|
||||||
|
}
|
||||||
|
client.clipboardPasteFrom(long_text);
|
||||||
|
expect(client._sock.flush).to.have.been.calledTwice;
|
||||||
|
});
|
||||||
|
|
||||||
it('should not send the text if we are not in a normal state', function () {
|
it('should not send the text if we are not in a normal state', function () {
|
||||||
sinon.spy(client._sock, 'flush');
|
sinon.spy(client._sock, 'flush');
|
||||||
client._rfb_connection_state = "connecting";
|
client._rfb_connection_state = "connecting";
|
||||||
|
|
Loading…
Reference in New Issue