This commit is contained in:
Malcolm Scott 2014-01-30 14:31:33 -08:00
commit 9e041e314d
6 changed files with 211 additions and 6 deletions

BIN
images/power.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 B

View File

@ -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;
}
@ -199,6 +206,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;

View File

@ -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 = {},
@ -138,6 +141,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'],
@ -164,6 +168,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() { },
@ -644,7 +650,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) {
@ -709,7 +716,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];
}
}
@ -744,6 +751,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
@ -896,7 +920,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;
@ -946,6 +971,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));
@ -1800,6 +1843,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) {

View File

@ -92,6 +92,7 @@ start: function(callback) {
UI.rfb = RFB({'target': $D('noVNC_canvas'),
'onUpdateState': UI.updateState,
'onXvpInit': UI.updateXvpVisualState,
'onClipboard': UI.clipReceive,
'onDesktopName': UI.updateDocumentTitle});
@ -185,8 +186,12 @@ addMouseHandlers: function() {
$D("sendEscButton").onclick = UI.sendEsc;
$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;
@ -303,6 +308,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
@ -320,6 +358,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";
@ -350,6 +392,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) {
@ -414,6 +460,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;
@ -467,6 +517,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;
@ -566,6 +628,7 @@ updateVisualState: function() {
$D('showKeyboard').style.display = "none";
$D('noVNC_extra_keys').style.display = "none";
$D('sendCtrlAltDelButton').style.display = "none";
UI.updateXvpVisualState(0);
}
// State change disables viewport dragging.
@ -589,6 +652,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) {

View File

@ -95,6 +95,9 @@
<input type="image" src="images/ctrlaltdel.png"
id="sendCtrlAltDelButton" class="noVNC_status_button"
title="Send Ctrl-Alt-Del" />
<input type="image" src="images/power.png"
id="xvpButton" class="noVNC_status_button"
title="Shutdown/Reboot..." />
<input type="image" src="images/clipboard.png"
id="clipboardButton" class="noVNC_status_button"
title="Clipboard" />
@ -138,6 +141,15 @@
value="Clear">
</div>
<!-- XVP Shutdown/Reboot Panel -->
<div id="noVNC_xvp" class="triangle-right top">
<span id="noVNC_xvp_menu">
<input type="button" id="xvpShutdownButton" value="Shutdown" />
<input type="button" id="xvpRebootButton" value="Reboot" />
<input type="button" id="xvpResetButton" value="Reset" />
</span>
</div>
<!-- Settings Panel -->
<div id="noVNC_settings" class="triangle-right top">
<span id="noVNC_settings_menu">

View File

@ -53,6 +53,14 @@
<td width="1%"><div id="noVNC_buttons">
<input type=button value="Send CtrlAltDel"
id="sendCtrlAltDelButton">
<span id="noVNC_xvp_buttons">
<input type=button value="Shutdown"
id="xvpShutdownButton">
<input type=button value="Reboot"
id="xvpRebootButton">
<input type=button value="Reset"
id="xvpResetButton">
</span>
</div></td>
</tr></table>
</div>
@ -91,6 +99,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');
@ -105,8 +125,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);
@ -114,11 +138,24 @@
}
}
function xvpInit(ver) {
var xvpbuttons;
xvpbuttons = $D('noVNC_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'));
@ -162,6 +199,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);
};