From 5e886490af6641bec0ace12724efdaa118f7718a Mon Sep 17 00:00:00 2001 From: Malcolm Scott Date: Sat, 28 Sep 2013 17:32:37 +0100 Subject: [PATCH 1/6] Implement XVP auth --- include/rfb.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/include/rfb.js b/include/rfb.js index 5258f09d..7a4aa07f 100644 --- a/include/rfb.js +++ b/include/rfb.js @@ -139,6 +139,7 @@ Util.conf_defaults(conf, that, defaults, [ ['local_cursor', 'rw', 'bool', false, 'Request locally rendered cursor'], ['shared', 'rw', 'bool', true, 'Request shared mode'], ['view_only', 'rw', 'bool', false, 'Disable client mouse/keyboard'], + ['xvp_password_sep', 'rw', 'str', '@', 'Separator for XVP password fields'], ['connectTimeout', 'rw', 'int', def_con_timeout, 'Time (s) to wait for connection'], ['disconnectTimeout', 'rw', 'int', 3, 'Time (s) to wait for disconnection'], @@ -671,7 +672,8 @@ init_msg = function() { var strlen, reason, length, sversion, cversion, repeaterID, i, types, num_types, challenge, response, bpp, depth, big_endian, red_max, green_max, blue_max, red_shift, - green_shift, blue_shift, true_color, name_length, is_repeater; + green_shift, blue_shift, true_color, name_length, is_repeater, + xvp_sep, xvp_auth, xvp_auth_str; //Util.Debug("ws.rQ (" + ws.rQlen() + ") " + ws.rQslice(0)); switch (rfb_state) { @@ -736,7 +738,7 @@ init_msg = function() { types = ws.rQshiftBytes(num_types); Util.Debug("Server security types: " + types); for (i=0; i < types.length; i+=1) { - if ((types[i] > rfb_auth_scheme) && (types[i] < 3)) { + if ((types[i] > rfb_auth_scheme) && (types[i] < 3 || types[i] == 22)) { rfb_auth_scheme = types[i]; } } @@ -771,6 +773,23 @@ init_msg = function() { } // Fall through to ClientInitialisation break; + case 22: // XVP authentication + xvp_sep = conf.xvp_password_sep; + xvp_auth = rfb_password.split(xvp_sep); + if (xvp_auth.length < 3) { + updateState('password', "XVP credentials required (user" + xvp_sep + + "target" + xvp_sep + "password) -- got only " + rfb_password); + conf.onPasswordRequired(that); + return; + } + xvp_auth_str = String.fromCharCode(xvp_auth[0].length) + + String.fromCharCode(xvp_auth[1].length) + + xvp_auth[0] + + xvp_auth[1]; + ws.send_string(xvp_auth_str); + rfb_password = xvp_auth.slice(2).join(xvp_sep); + rfb_auth_scheme = 2; + // Fall through to standard VNC authentication with remaining part of password case 2: // VNC authentication if (rfb_password.length === 0) { // Notify via both callbacks since it is kind of From b67a101d9e70054413357ea0fec4b331f8c41e32 Mon Sep 17 00:00:00 2001 From: Malcolm Scott Date: Sat, 28 Sep 2013 19:24:54 +0100 Subject: [PATCH 2/6] Implement XVP extension (shutdown/reboot/reset) --- include/rfb.js | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/include/rfb.js b/include/rfb.js index 7a4aa07f..e5d05896 100644 --- a/include/rfb.js +++ b/include/rfb.js @@ -46,6 +46,8 @@ var that = {}, // Public API methods rfb_max_version= 3.8, rfb_auth_scheme= '', + rfb_xvp_ver = 0, + // In preference order encodings = [ @@ -64,7 +66,8 @@ var that = {}, // Public API methods //['JPEG_quality_hi', -23 ], //['compress_lo', -255 ], ['compress_hi', -247 ], - ['last_rect', -224 ] + ['last_rect', -224 ], + ['xvp', -309 ] ], encHandlers = {}, @@ -169,6 +172,8 @@ Util.conf_defaults(conf, that, defaults, [ 'onFBResize(rfb, width, height): frame buffer resized'], ['onDesktopName', 'rw', 'func', function() { }, 'onDesktopName(rfb, name): desktop name received'], + ['onXvpInit', 'rw', 'func', function() { }, + 'onXvpInit(version): XVP extensions active for this connection'], // These callback names are deprecated ['updateState', 'rw', 'func', function() { }, @@ -943,7 +948,8 @@ normal_msg = function() { //Util.Debug(">> normal_msg"); var ret = true, msg_type, length, text, - c, first_colour, num_colours, red, green, blue; + c, first_colour, num_colours, red, green, blue, + xvp_ver, xvp_msg; if (FBU.rects > 0) { msg_type = 0; @@ -989,6 +995,24 @@ normal_msg = function() { conf.clipboardReceive(that, text); // Obsolete conf.onClipboard(that, text); break; + case 250: // XVP + ws.rQshift8(); // Padding + xvp_ver = ws.rQshift8(); + xvp_msg = ws.rQshift8(); + switch (xvp_msg) { + case 0: // XVP_FAIL + updateState(rfb_state, "Operation failed"); + break; + case 1: // XVP_INIT + rfb_xvp_ver = xvp_ver; + Util.Info("XVP extensions enabled (version " + rfb_xvp_ver + ")"); + conf.onXvpInit(rfb_xvp_ver); + break; + default: + fail("Disconnected: illegal server XVP message " + xvp_msg); + break; + } + break; default: fail("Disconnected: illegal server message type " + msg_type); Util.Debug("ws.rQslice(0,30):" + ws.rQslice(0,30)); @@ -1846,6 +1870,25 @@ that.sendCtrlAltDel = function() { ws.send(arr); }; +that.xvpOp = function(ver, op) { + if (rfb_xvp_ver < ver) { return false; } + Util.Info("Sending XVP operation " + op + " (version " + ver + ")") + ws.send_string("\xFA\x00" + String.fromCharCode(ver) + String.fromCharCode(op)); + return true; +}; + +that.xvpShutdown = function() { + return that.xvpOp(1, 2); +}; + +that.xvpReboot = function() { + return that.xvpOp(1, 3); +}; + +that.xvpReset = function() { + return that.xvpOp(1, 4); +}; + // Send a key press. If 'down' is not specified then send a down key // followed by an up key. that.sendKey = function(code, down) { From a5753460b5790e1ac8723a8f14297439496c7ba9 Mon Sep 17 00:00:00 2001 From: Malcolm Scott Date: Sat, 28 Sep 2013 19:25:15 +0100 Subject: [PATCH 3/6] Implement basic UI in vnc_auto.html --- vnc_auto.html | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/vnc_auto.html b/vnc_auto.html index 2aa21889..5f393769 100644 --- a/vnc_auto.html +++ b/vnc_auto.html @@ -50,9 +50,17 @@
Loading
-
+
+
@@ -90,6 +98,18 @@ rfb.sendCtrlAltDel(); return false; } + function xvpShutdown() { + rfb.xvpShutdown(); + return false; + } + function xvpReboot() { + rfb.xvpReboot(); + return false; + } + function xvpReset() { + rfb.xvpReset(); + return false; + } function updateState(rfb, state, oldstate, msg) { var s, sb, cad, level; s = $D('noVNC_status'); @@ -104,8 +124,12 @@ default: level = "warn"; break; } - if (state === "normal") { cad.disabled = false; } - else { cad.disabled = true; } + if (state === "normal") { + cad.disabled = false; + } else { + cad.disabled = true; + xvpInit(0); + } if (typeof(msg) !== 'undefined') { sb.setAttribute("class", "noVNC_status_" + level); @@ -113,11 +137,24 @@ } } + function xvpInit(ver) { + var xvpbuttons; + xvpbuttons = $D('xvp_buttons'); + if (ver >= 1) { + xvpbuttons.style.display = 'inline'; + } else { + xvpbuttons.style.display = 'none'; + } + } + window.onscriptsload = function () { var host, port, password, path, token; $D('sendCtrlAltDelButton').style.display = "inline"; $D('sendCtrlAltDelButton').onclick = sendCtrlAltDel; + $D('xvpShutdownButton').onclick = xvpShutdown; + $D('xvpRebootButton').onclick = xvpReboot; + $D('xvpResetButton').onclick = xvpReset; WebUtil.init_logging(WebUtil.getQueryVar('logging', 'warn')); document.title = unescape(WebUtil.getQueryVar('title', 'noVNC')); @@ -161,6 +198,7 @@ 'shared': WebUtil.getQueryVar('shared', true), 'view_only': WebUtil.getQueryVar('view_only', false), 'updateState': updateState, + 'onXvpInit': xvpInit, 'onPasswordRequired': passwordRequired}); rfb.connect(host, port, password, path); }; From 73e602939402995253bad4ba4059904853cf9d43 Mon Sep 17 00:00:00 2001 From: Malcolm Scott Date: Sat, 28 Sep 2013 19:25:52 +0100 Subject: [PATCH 4/6] Implement XVP extension UI --- images/power.png | Bin 0 -> 390 bytes include/base.css | 10 +++++++ include/ui.js | 76 +++++++++++++++++++++++++++++++++++++++++++++++ vnc.html | 14 ++++++++- 4 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 images/power.png diff --git a/images/power.png b/images/power.png new file mode 100644 index 0000000000000000000000000000000000000000..f68fd0813c02a625f3fb5097353b7825f287939f GIT binary patch literal 390 zcmeAS@N?(olHy`uVBq!ia0vp^k|4~%1|*NXY)uAIY)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP)r;MP5p&nmUBLf4Yu&0Y-h{y4#VS!wS40wF6uK&wz zeJ1b0dp`q-xCQJ1W&L*#{jK6yZ}@>J>(2+?q>Rf`4Fzff;%=K%nq(i6F}{53M#?;U zLBZzq!>RXNprLZ*hUsB!Gewso}{}^ zyS5zqsqt+q$3eS=bG3syL}aJxswlO({ZMz^<8@I+aHiGz+=bUm8NM^#j@;<7{?FO# zrb}1(?6I-+nz%_ndc~vpE9T2SE8eKOh+S~6fqC~wzI*9n-{OAGRx&S`su`qNAN+(V z&&XBkX?|VBYQH4q-F|DjwzF)~vb(lB%jUA~j<{R9onkH8Tw^2Zl+T|DXQ^pge?vdW h@Q(gJk3Tz4NXMlvaGP>8%>o!=44$rjF6*2UngBV_o1g#y literal 0 HcmV?d00001 diff --git a/include/base.css b/include/base.css index 0578619e..228032ba 100644 --- a/include/base.css +++ b/include/base.css @@ -191,6 +191,16 @@ html { border-radius:10px; } +#noVNC_xvp { + display:none; + margin-top:73px; + right:30px; + position:fixed; +} +#noVNC_xvp.top:after { + right:125px; +} + #noVNC_clipboard { display:none; margin-top:73px; diff --git a/include/ui.js b/include/ui.js index b933d312..ce81b23b 100644 --- a/include/ui.js +++ b/include/ui.js @@ -84,6 +84,7 @@ start: function(callback) { UI.rfb = RFB({'target': $D('noVNC_canvas'), 'onUpdateState': UI.updateState, + 'onXvpInit': UI.updateXvpVisualState, 'onClipboard': UI.clipReceive, 'onDesktopName': UI.updateDocumentTitle}); UI.updateVisualState(); @@ -159,8 +160,12 @@ addMouseHandlers: function() { $D("keyboardinput").onblur = UI.keyInputBlur; $D("sendCtrlAltDelButton").onclick = UI.sendCtrlAltDel; + $D("xvpShutdownButton").onclick = UI.xvpShutdown; + $D("xvpRebootButton").onclick = UI.xvpReboot; + $D("xvpResetButton").onclick = UI.xvpReset; $D("noVNC_status").onclick = UI.togglePopupStatusPanel; $D("noVNC_popup_status_panel").onclick = UI.togglePopupStatusPanel; + $D("xvpButton").onclick = UI.toggleXvpPanel; $D("clipboardButton").onclick = UI.toggleClipboardPanel; $D("settingsButton").onclick = UI.toggleSettingsPanel; $D("connectButton").onclick = UI.toggleConnectPanel; @@ -277,6 +282,39 @@ togglePopupStatusPanel: function() { } }, +// Show the XVP panel +toggleXvpPanel: function() { + // Close the description panel + $D('noVNC_description').style.display = "none"; + // Close settings if open + if (UI.settingsOpen === true) { + UI.settingsApply(); + UI.closeSettingsMenu(); + } + // Close connection settings if open + if (UI.connSettingsOpen === true) { + UI.toggleConnectPanel(); + } + // Close popup status panel if open + if (UI.popupStatusOpen === true) { + UI.togglePopupStatusPanel(); + } + // Close clipboard panel if open + if (UI.clipboardOpen === true) { + UI.toggleClipboardPanel(); + } + // Toggle XVP panel + if (UI.xvpOpen === true) { + $D('noVNC_xvp').style.display = "none"; + $D('xvpButton').className = "noVNC_status_button"; + UI.xvpOpen = false; + } else { + $D('noVNC_xvp').style.display = "block"; + $D('xvpButton').className = "noVNC_status_button_selected"; + UI.xvpOpen = true; + } +}, + // Show the clipboard panel toggleClipboardPanel: function() { // Close the description panel @@ -294,6 +332,10 @@ toggleClipboardPanel: function() { if (UI.popupStatusOpen === true) { UI.togglePopupStatusPanel(); } + // Close XVP panel if open + if (UI.xvpOpen === true) { + UI.toggleXvpPanel(); + } // Toggle Clipboard Panel if (UI.clipboardOpen === true) { $D('noVNC_clipboard').style.display = "none"; @@ -324,6 +366,10 @@ toggleConnectPanel: function() { if (UI.popupStatusOpen === true) { UI.togglePopupStatusPanel(); } + // Close XVP panel if open + if (UI.xvpOpen === true) { + UI.toggleXvpPanel(); + } // Toggle Connection Panel if (UI.connSettingsOpen === true) { @@ -388,6 +434,10 @@ openSettingsMenu: function() { if (UI.popupStatusOpen === true) { UI.togglePopupStatusPanel(); } + // Close XVP panel if open + if (UI.xvpOpen === true) { + UI.toggleXvpPanel(); + } $D('noVNC_settings').style.display = "block"; $D('settingsButton').className = "noVNC_status_button_selected"; UI.settingsOpen = true; @@ -441,6 +491,18 @@ sendCtrlAltDel: function() { UI.rfb.sendCtrlAltDel(); }, +xvpShutdown: function() { + UI.rfb.xvpShutdown(); +}, + +xvpReboot: function() { + UI.rfb.xvpReboot(); +}, + +xvpReset: function() { + UI.rfb.xvpReset(); +}, + setMouseButton: function(num) { var b, blist = [0, 1,2,4], button; @@ -538,6 +600,7 @@ updateVisualState: function() { $D('clipboardButton').style.display = "none"; $D('showKeyboard').style.display = "none"; $D('sendCtrlAltDelButton').style.display = "none"; + UI.updateXvpVisualState(0); } // State change disables viewport dragging. // It is enabled (toggled) by direct click on the button @@ -560,6 +623,19 @@ updateVisualState: function() { //Util.Debug("<< updateVisualState"); }, +// Disable/enable XVP button +updateXvpVisualState: function(ver) { + if (ver >= 1) { + $D('xvpButton').style.display = 'inline'; + } else { + $D('xvpButton').style.display = 'none'; + // Close XVP panel if open + if (UI.xvpOpen === true) { + UI.toggleXvpPanel(); + } + } +}, + // Display the desktop name in the document title updateDocumentTitle: function(rfb, name) { diff --git a/vnc.html b/vnc.html index 66b70259..f7536335 100644 --- a/vnc.html +++ b/vnc.html @@ -72,12 +72,15 @@
Loading
- +e
+ @@ -121,6 +124,15 @@ value="Clear">
+ +
+ + + + + +
+
From 3c65070e979bd14dacad9c2a05d64a427b0007ff Mon Sep 17 00:00:00 2001 From: Malcolm Scott Date: Sat, 28 Sep 2013 19:27:47 +0100 Subject: [PATCH 5/6] Typo escaped into previous commit --- vnc.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vnc.html b/vnc.html index f7536335..4aa292ed 100644 --- a/vnc.html +++ b/vnc.html @@ -72,7 +72,7 @@
Loading
-e +
Date: Sat, 28 Sep 2013 19:37:30 +0100 Subject: [PATCH 6/6] Neaten CSS for basic XVP UI --- include/base.css | 7 +++++++ vnc_auto.html | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/base.css b/include/base.css index 228032ba..a2aa5935 100644 --- a/include/base.css +++ b/include/base.css @@ -52,12 +52,19 @@ html { float:right; } +#noVNC_buttons { + white-space: nowrap; +} + #noVNC_view_drag_button { display: none; } #sendCtrlAltDelButton { display: none; } +#noVNC_xvp_buttons { + display: none; +} #noVNC_mobile_buttons { display: none; } diff --git a/vnc_auto.html b/vnc_auto.html index 5f393769..bb0ce51c 100644 --- a/vnc_auto.html +++ b/vnc_auto.html @@ -50,10 +50,10 @@
Loading
-
+
-