diff --git a/app/ui.js b/app/ui.js index 4803e9e6..c5231555 100644 --- a/app/ui.js +++ b/app/ui.js @@ -1087,20 +1087,12 @@ const UI = { }, clipboardReceive(e) { - if (UI.rfb.clipboardDown && UI.rfb.clipboardSeamless ) { + if (UI.rfb.clipboardDown) { var curvalue = document.getElementById('noVNC_clipboard_text').value; if (curvalue != e.detail.text) { Log.Debug(">> UI.clipboardReceive: " + e.detail.text.substr(0, 40) + "..."); document.getElementById('noVNC_clipboard_text').value = e.detail.text; Log.Debug("<< UI.clipboardReceive"); - if (navigator.clipboard && navigator.clipboard.writeText){ - navigator.clipboard.writeText(e.detail.text) - .then(function () { - //UI.popupMessage("Selection Copied"); - }, function () { - console.error("Failed to write system clipboard (trying to copy from NoVNC clipboard)") - }); - } } } }, @@ -1137,7 +1129,9 @@ const UI = { if (UI.rfb.clipboardBinary) { navigator.clipboard.read().then((data) => { - UI.rfb.clipboardPasteDataFrom(data); + if (UI.rfb) { + UI.rfb.clipboardPasteDataFrom(data); + } UI.needToCheckClipboardChange = false; }, (err) => { console.log("No data in clipboard"); diff --git a/core/rfb.js b/core/rfb.js index 4e2d7e2b..80746fb1 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -2474,27 +2474,40 @@ export default class RFB extends EventTargetMixin { _handleBinaryClipboard() { Log.Debug("HandleBinaryClipboard"); + if (this._sock.rQwait("Binary Clipboard header", 2, 1)) { return false; } + let num = this._sock.rQshift8(); // how many different mime types let mimes = []; let clipItemData = {}; - console.log('Clipboard items recieved.'); + let buffByteLen = 2; + console.log(num + ' Clipboard items recieved.'); + console.log('Client sockjs buffer size ' + this._sock.rQlen); + + for (let i = 0; i < num; i++) { + if (this._sock.rQwait("Binary Clipboard mimelen", 1, buffByteLen)) { return false; } + buffByteLen++; let mimelen = this._sock.rQshift8(); + + if (this._sock.rQwait("Binary Clipboard mime", Math.abs(mimelen), buffByteLen)) { return false; } + buffByteLen+=mimelen; let mime = this._sock.rQshiftStr(mimelen); + + if (this._sock.rQwait("Binary Clipboard data len", 4, buffByteLen)) { return false; } + buffByteLen+=4; let len = this._sock.rQshift32(); + + if (this._sock.rQwait("Binary Clipboard data", Math.abs(len), buffByteLen)) { return false; } let data = this._sock.rQshiftBytes(len); + buffByteLen+=len; switch(mime) { case "image/png": case "text/html": case "text/plain": - //if (mimes.includes(mime)){ - // continue; - //} mimes.push(mime); - if (!this.clipboardBinary) { if (mime == "text/plain") { let textdata = new TextDecoder().decode(data); @@ -2509,10 +2522,9 @@ export default class RFB extends EventTargetMixin { "clipboard", { detail: { text: textdata } }) ); - continue; } - continue; - } + + if (!this.clipboardBinary) { continue; } console.log("Mime " + mime + ", len ", len); console.log(data); @@ -2524,6 +2536,8 @@ export default class RFB extends EventTargetMixin { } } + console.log('Client sockjs buffer size ' + this._sock.rQlen); + if (Object.keys(clipItemData).length > 0) { if (this.clipboardBinary) { this._clipHash = 0; @@ -2679,8 +2693,7 @@ export default class RFB extends EventTargetMixin { return true; case 180: // KASM binary clipboard - this._handleBinaryClipboard(); - return true; + return this._handleBinaryClipboard(); case 248: // ServerFence return this._handleServerFenceMsg(); diff --git a/core/util/browser.js b/core/util/browser.js index 95a7ada7..0bff0d4d 100644 --- a/core/util/browser.js +++ b/core/util/browser.js @@ -102,6 +102,8 @@ export function isFirefox() { } export function supportsBinaryClipboard() { + //Safari does support the clipbaord API but has a lot of security restrictions + if (isSafari()) { return false; } return (typeof navigator.clipboard.read === "function"); }