web-common-resource/terminal/smartxKs/rfb.js

14 lines
34 KiB
JavaScript

/*
* noVNC: HTML5 VNC client
* Copyright (C) 2012 Joel Martin
* Copyright (C) 2013 Samuel Mannehed for Cendio AB
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*
* TIGHT decoder portion:
* (c) 2012 Michael Tinglof, Joe Balaz, Les Piech (Mercuri.ca)
*/
var RFB;!function(){"use strict";RFB=function(t){t||(t={}),this._rfb_host="",this._rfb_port=5900,this._rfb_password="",this._rfb_path="",this._rfb_state="disconnected",this._rfb_version=0,this._rfb_max_version=3.8,this._rfb_auth_scheme="",this._rfb_tightvnc=!1,this._rfb_xvp_ver=0,this._encodings=[["COPYRECT",1],["TIGHT",7],["TIGHT_PNG",-260],["HEXTILE",5],["RRE",2],["RAW",0],["DesktopSize",-223],["Cursor",-239],["JPEG_quality_med",-26],["compress_hi",-247],["last_rect",-224],["xvp",-309],["ExtendedDesktopSize",-308]],this._encHandlers={},this._encNames={},this._encStats={},this._sock=null,this._display=null,this._keyboard=null,this._mouse=null,this._sendTimer=null,this._disconnTimer=null,this._msgTimer=null,this._FBU={rects:0,subrects:0,lines:0,tiles:0,bytes:0,x:0,y:0,width:0,height:0,encoding:0,subencoding:-1,background:null,zlib:[]},this._fb_Bpp=4,this._fb_depth=3,this._fb_width=0,this._fb_height=0,this._fb_name="",this._destBuff=null,this._paletteBuff=new Uint8Array(1024),this._rre_chunk_sz=100,this._timing={last_fbu:0,fbu_total:0,fbu_total_cnt:0,full_fbu_total:0,full_fbu_cnt:0,fbu_rt_start:0,fbu_rt_total:0,fbu_rt_cnt:0,pixels:0},this._supportsSetDesktopSize=!1,this._screen_id=0,this._screen_flags=0,this._mouse_buttonMask=0,this._mouse_arr=[],this._viewportDragging=!1,this._viewportDragPos={},this._viewportHasMoved=!1,Util.set_defaults(this,t,{target:"null",focusContainer:document,encrypt:!1,true_color:!0,local_cursor:!1,shared:!0,view_only:!1,xvp_password_sep:"@",disconnectTimeout:3,wsProtocols:["binary"],repeaterID:"",viewportDrag:!1,onUpdateState:function(){},onPasswordRequired:function(){},onClipboard:function(){},onBell:function(){},onFBUReceive:function(){},onFBUComplete:function(){},onFBResize:function(){},onDesktopName:function(){},onXvpInit:function(){}}),Util.Debug(">> RFB.constructor"),Object.keys(RFB.encodingHandlers).forEach(function(t){this._encHandlers[t]=RFB.encodingHandlers[t].bind(this)}.bind(this));for(var s=0;s<this._encodings.length;s++)this._encHandlers[this._encodings[s][1]]=this._encHandlers[this._encodings[s][0]],this._encNames[this._encodings[s][1]]=this._encodings[s][0],this._encStats[this._encodings[s][1]]=[0,0];try{this._display=new Display({target:this._target})}catch(t){throw Util.Error("Display exception: "+t),t}this._keyboard=new Keyboard({target:this._focusContainer,onKeyPress:this._handleKeyPress.bind(this)}),this._mouse=new Mouse({target:this._target,onMouseButton:this._handleMouseButton.bind(this),onMouseMove:this._handleMouseMove.bind(this),notify:this._keyboard.sync.bind(this._keyboard)}),this._sock=new Websock,this._sock.on("message",this._handle_message.bind(this)),this._sock.on("open",function(){"connect"===this._rfb_state?this._updateState("ProtocolVersion","Starting VNC handshake"):this._fail("Got unexpected WebSocket connection")}.bind(this)),this._sock.on("close",function(t){Util.Warn("WebSocket on-close event");var s="";t.code&&(s=" (code: "+t.code,t.reason&&(s+=", reason: "+t.reason),s+=")"),"disconnect"===this._rfb_state?this._updateState("disconnected","VNC disconnected"+s):"ProtocolVersion"===this._rfb_state?this._fail("Failed to connect to server"+s):this._rfb_state in{failed:1,disconnected:1}?Util.Error("Received onclose while disconnected"+s):this._fail("Server disconnected"+s),this._sock.off("close")}.bind(this)),this._sock.on("error",function(t){Util.Warn("WebSocket on-error event")}),this._init_vars();var i=this._display.get_render_mode();if(!Websock_native)throw this._cleanupSocket("fatal"),new Error("WebSocket support is required to use noVNC");Util.Info("Using native WebSockets"),this._updateState("loaded","noVNC ready: native WebSockets, "+i),Util.Debug("<< RFB.constructor")},RFB.prototype={connect:function(t,s,i,e){if(this._rfb_host=t,this._rfb_port=s,this._rfb_password=void 0!==i?i:"",this._rfb_path=void 0!==e?e:"",!this._rfb_host||!this._rfb_port)return this._fail("Must set host and port");this._updateState("connect")},disconnect:function(){this._updateState("disconnect","Disconnecting"),this._sock.off("error"),this._sock.off("message"),this._sock.off("open")},sendPassword:function(t){this._rfb_password=t,this._rfb_state="Authentication",setTimeout(this._init_msg.bind(this),1)},sendCtrlAltDel:function(){if("normal"!==this._rfb_state||this._view_only)return!1;Util.Info("Sending Ctrl-Alt-Del"),RFB.messages.keyEvent(this._sock,XK_Control_L,1),RFB.messages.keyEvent(this._sock,XK_Alt_L,1),RFB.messages.keyEvent(this._sock,XK_Delete,1),RFB.messages.keyEvent(this._sock,XK_Delete,0),RFB.messages.keyEvent(this._sock,XK_Alt_L,0),RFB.messages.keyEvent(this._sock,XK_Control_L,0),this._sock.flush()},xvpOp:function(t,s){return!(this._rfb_xvp_ver<t)&&(Util.Info("Sending XVP operation "+s+" (version "+t+")"),this._sock.send_string("ú\0"+String.fromCharCode(t)+String.fromCharCode(s)),!0)},xvpShutdown:function(){return this.xvpOp(1,2)},xvpReboot:function(){return this.xvpOp(1,3)},xvpReset:function(){return this.xvpOp(1,4)},sendKey:function(t,s){if("normal"!==this._rfb_state||this._view_only)return!1;void 0!==s?(Util.Info("Sending key code ("+(s?"down":"up")+"): "+t),RFB.messages.keyEvent(this._sock,t,s?1:0)):(Util.Info("Sending key code (down + up): "+t),RFB.messages.keyEvent(this._sock,t,1),RFB.messages.keyEvent(this._sock,t,0)),this._sock.flush()},clipboardPasteFrom:function(t){"normal"===this._rfb_state&&(RFB.messages.clientCutText(this._sock,t),this._sock.flush())},requestDesktopSize:function(t,s){"normal"===this._rfb_state&&this._supportsSetDesktopSize&&(RFB.messages.setDesktopSize(this._sock,t,s,this._screen_id,this._screen_flags),this._sock.flush())},_connect:function(){Util.Debug(">> RFB.connect");var t;t="undefined"!=typeof UsingSocketIO?"http":this._encrypt?"wss":"ws",t+="://"+this._rfb_host+":"+this._rfb_port+"/"+this._rfb_path,Util.Info("connecting to "+t),this._sock.open(t,this._wsProtocols),Util.Debug("<< RFB.connect")},_init_vars:function(){this._FBU.rects=0,this._FBU.subrects=0,this._FBU.lines=0,this._FBU.tiles=0,this._FBU.zlibs=[],this._mouse_buttonMask=0,this._mouse_arr=[],this._rfb_tightvnc=!1;var t;for(t=0;t<this._encodings.length;t++)this._encStats[this._encodings[t][1]][0]=0;for(t=0;t<4;t++)this._FBU.zlibs[t]=new inflator.Inflate},_print_stats:function(){Util.Info("Encoding stats for this connection:");var t,s;for(t=0;t<this._encodings.length;t++)s=this._encStats[this._encodings[t][1]],s[0]+s[1]>0&&Util.Info(" "+this._encodings[t][0]+": "+s[0]+" rects");for(Util.Info("Encoding stats since page load:"),t=0;t<this._encodings.length;t++)s=this._encStats[this._encodings[t][1]],Util.Info(" "+this._encodings[t][0]+": "+s[1]+" rects")},_cleanupSocket:function(t){this._sendTimer&&(clearInterval(this._sendTimer),this._sendTimer=null),this._msgTimer&&(clearInterval(this._msgTimer),this._msgTimer=null),this._display&&this._display.get_context()&&(this._keyboard.ungrab(),this._mouse.ungrab(),"connect"!==t&&"loaded"!==t&&this._display.defaultCursor(),"debug"===Util.get_logging()&&"loaded"!==t||this._display.clear()),this._sock.close()},_updateState:function(t,s){var i=this._rfb_state;t===i&&Util.Debug("Already in state '"+t+"', ignoring"),t in{disconnected:1,loaded:1,connect:1,disconnect:1,failed:1,fatal:1}&&this._cleanupSocket(t),"fatal"===i&&Util.Error("Fatal error, cannot continue");var e=void 0!==s?" Msg: "+s:"";switch("failed"===t||"fatal"===t?Util.Error(e):Util.Warn(e),this._rfb_state="failed"===i&&"disconnected"===t?"failed":t,this._disconnTimer&&"disconnect"!==this._rfb_state&&(Util.Debug("Clearing disconnect timer"),clearTimeout(this._disconnTimer),this._disconnTimer=null,this._sock.off("close")),t){case"normal":"disconnected"!==i&&"failed"!==i||Util.Error("Invalid transition from 'disconnected' or 'failed' to 'normal'");break;case"connect":this._init_vars(),this._connect();break;case"disconnect":this._disconnTimer=setTimeout(function(){this._fail("Disconnect timeout")}.bind(this),1e3*this._disconnectTimeout),this._print_stats();break;case"failed":"disconnected"===i?Util.Error("Invalid transition from 'disconnected' to 'failed'"):"normal"===i?Util.Error("Error while connected."):"init"===i&&Util.Error("Error while initializing."),setTimeout(function(){this._updateState("disconnected")}.bind(this),50)}"failed"===i&&"disconnected"===t?this._onUpdateState(this,t,i):this._onUpdateState(this,t,i,s)},_fail:function(t){return this._updateState("failed",t),!1},_handle_message:function(){if(0===this._sock.rQlen())return void Util.Warn("handle_message called on an empty receive queue");switch(this._rfb_state){case"disconnected":case"failed":Util.Error("Got data while disconnected");break;case"normal":this._normal_msg()&&this._sock.rQlen()>0&&(null===this._msgTimer?(Util.Debug("More data to process, creating timer"),this._msgTimer=setTimeout(function(){this._msgTimer=null,this._handle_message()}.bind(this),10)):Util.Debug("More data to process, existing timer"));break;default:this._init_msg()}},_handleKeyPress:function(t,s){this._view_only||(RFB.messages.keyEvent(this._sock,t,s),this._sock.flush())},_handleMouseButton:function(t,s,i,e){if(i?this._mouse_buttonMask|=e:this._mouse_buttonMask^=e,this._viewportDrag){if(i&&!this._viewportDragging)return this._viewportDragging=!0,void(this._viewportDragPos={x:t,y:s});this._viewportDragging=!1,this._viewportHasMoved||this._view_only||RFB.messages.pointerEvent(this._sock,this._display.absX(t),this._display.absY(s),e),this._viewportHasMoved=!1}this._view_only||"normal"===this._rfb_state&&RFB.messages.pointerEvent(this._sock,this._display.absX(t),this._display.absY(s),this._mouse_buttonMask)},_handleMouseMove:function(t,s){if(this._viewportDragging){var i=this._viewportDragPos.x-t,e=this._viewportDragPos.y-s,r=10*(window.devicePixelRatio||1);return void((this._viewportHasMoved||Math.abs(i)>r||Math.abs(e)>r)&&(this._viewportHasMoved=!0,this._viewportDragPos={x:t,y:s},this._display.viewportChangePos(i,e)))}this._view_only||"normal"===this._rfb_state&&RFB.messages.pointerEvent(this._sock,this._display.absX(t),this._display.absY(s),this._mouse_buttonMask)},_negotiate_protocol_version:function(){if(this._sock.rQlen()<12)return this._fail("Incomplete protocol version");var t=this._sock.rQshiftStr(12).substr(4,7);Util.Info("Server ProtocolVersion: "+t);var s=0;switch(t){case"000.000":s=1;break;case"003.003":case"003.006":case"003.889":this._rfb_version=3.3;break;case"003.007":this._rfb_version=3.7;break;case"003.008":case"004.000":case"004.001":this._rfb_version=3.8;break;default:return this._fail("Invalid server version "+t)}if(s){for(var i=this._repeaterID;i.length<250;)i+="\0";return this._sock.send_string(i),!0}this._rfb_version>this._rfb_max_version&&(this._rfb_version=this._rfb_max_version),this._sendTimer=setInterval(this._sock.flush.bind(this._sock),50);var e="00"+parseInt(this._rfb_version,10)+".00"+10*this._rfb_version%10;this._sock.send_string("RFB "+e+"\n"),this._updateState("Security","Sent ProtocolVersion: "+e)},_negotiate_security:function(){if(this._rfb_version>=3.7){var t=this._sock.rQshift8();if(this._sock.rQwait("security type",t,1))return!1;if(0===t){var s=this._sock.rQshift32(),i=this._sock.rQshiftStr(s);return this._fail("Security failure: "+i)}this._rfb_auth_scheme=0;var e=this._sock.rQshiftBytes(t);Util.Debug("Server security types: "+e);for(var r=0;r<e.length;r++)e[r]>this._rfb_auth_scheme&&(e[r]<=16||22==e[r])&&(this._rfb_auth_scheme=e[r]);if(0===this._rfb_auth_scheme)return this._fail("Unsupported security types: "+e);this._sock.send([this._rfb_auth_scheme])}else{if(this._sock.rQwait("security scheme",4))return!1;this._rfb_auth_scheme=this._sock.rQshift32()}return this._updateState("Authentication","Authenticating using scheme: "+this._rfb_auth_scheme),this._init_msg()},_negotiate_xvp_auth:function(){var t=this._xvp_password_sep,s=this._rfb_password.split(t);if(s.length<3)return this._updateState("password","XVP credentials required (user"+t+"target"+t+"password) -- got only "+this._rfb_password),this._onPasswordRequired(this),!1;var i=String.fromCharCode(s[0].length)+String.fromCharCode(s[1].length)+s[0]+s[1];return this._sock.send_string(i),this._rfb_password=s.slice(2).join(t),this._rfb_auth_scheme=2,this._negotiate_authentication()},_negotiate_std_vnc_auth:function(){if(0===this._rfb_password.length)return this._updateState("password","Password Required"),this._onPasswordRequired(this),!1;if(this._sock.rQwait("auth challenge",16))return!1;var t=Array.prototype.slice.call(this._sock.rQshiftBytes(16)),s=RFB.genDES(this._rfb_password,t);return this._sock.send(s),this._updateState("SecurityResult"),!0},_negotiate_tight_tunnels:function(t){for(var s={0:{vendor:"TGHT",signature:"NOTUNNEL"}},i={},e=0;e<t;e++){var r=this._sock.rQshift32(),_=this._sock.rQshiftStr(4),h=this._sock.rQshiftStr(8);i[r]={vendor:_,signature:h}}return i[0]?i[0].vendor!=s[0].vendor||i[0].signature!=s[0].signature?this._fail("Client's tunnel type had the incorrect vendor or signature"):(this._sock.send([0,0,0,0]),!1):this._fail("Server wanted tunnels, but doesn't support the notunnel type")},_negotiate_tight_auth:function(){if(!this._rfb_tightvnc){if(this._sock.rQwait("num tunnels",4))return!1;var t=this._sock.rQshift32();if(t>0&&this._sock.rQwait("tunnel capabilities",16*t,4))return!1;if(this._rfb_tightvnc=!0,t>0)return this._negotiate_tight_tunnels(t),!1}if(this._sock.rQwait("sub auth count",4))return!1;var s=this._sock.rQshift32();if(this._sock.rQwait("sub auth capabilities",16*s,4))return!1;for(var i={STDVNOAUTH__:1,STDVVNCAUTH_:2},e=[],r=0;r<s;r++){var _=(this._sock.rQshift32(),this._sock.rQshiftStr(12));e.push(_)}for(var h in i)if(-1!=e.indexOf(h))switch(this._sock.send([0,0,0,i[h]]),h){case"STDVNOAUTH__":return this._updateState("SecurityResult"),!0;case"STDVVNCAUTH_":return this._rfb_auth_scheme=2,this._init_msg();default:return this._fail("Unsupported tiny auth scheme: "+h)}this._fail("No supported sub-auth types!")},_negotiate_authentication:function(){switch(this._rfb_auth_scheme){case 0:if(this._sock.rQwait("auth reason",4))return!1;var t=this._sock.rQshift32(),s=this._sock.rQshiftStr(t);return this._fail("Auth failure: "+s);case 1:return this._rfb_version>=3.8?(this._updateState("SecurityResult"),!0):(this._updateState("ClientInitialisation","No auth required"),this._init_msg());case 22:return this._negotiate_xvp_auth();case 2:return this._negotiate_std_vnc_auth();case 16:return this._negotiate_tight_auth();default:return this._fail("Unsupported auth scheme: "+this._rfb_auth_scheme)}},_handle_security_result:function(){if(this._sock.rQwait("VNC auth response ",4))return!1;switch(this._sock.rQshift32()){case 0:return this._updateState("ClientInitialisation","Authentication OK"),this._init_msg();case 1:if(this._rfb_version>=3.8){var t=this._sock.rQshift32();if(this._sock.rQwait("SecurityResult reason",t,8))return!1;var s=this._sock.rQshiftStr(t);return this._fail(s)}return this._fail("Authentication failure");case 2:return this._fail("Too many auth attempts")}},_negotiate_server_init:function(){if(this._sock.rQwait("server initialization",24))return!1;this._fb_width=this._sock.rQshift16(),this._fb_height=this._sock.rQshift16(),this._destBuff=new Uint8Array(this._fb_width*this._fb_height*4);var t=this._sock.rQshift8(),s=this._sock.rQshift8(),i=this._sock.rQshift8(),e=this._sock.rQshift8(),r=this._sock.rQshift16(),_=this._sock.rQshift16(),h=this._sock.rQshift16(),n=this._sock.rQshift8(),o=this._sock.rQshift8(),a=this._sock.rQshift8();this._sock.rQskipBytes(3);var c=this._sock.rQshift32();if(this._sock.rQwait("server init name",c,24))return!1;if(this._fb_name=Util.decodeUTF8(this._sock.rQshiftStr(c)),this._rfb_tightvnc){if(this._sock.rQwait("TightVNC extended server init header",8,24+c))return!1;var l=this._sock.rQshift16(),f=this._sock.rQshift16(),u=this._sock.rQshift16();this._sock.rQskipBytes(2);var d=16*(l+f+u);if(this._sock.rQwait("TightVNC extended server init header",d,32+c))return!1;this._sock.rQskipBytes(16*l),this._sock.rQskipBytes(16*f),this._sock.rQskipBytes(16*u)}Util.Info("Screen: "+this._fb_width+"x"+this._fb_height+", bpp: "+t+", depth: "+s+", big_endian: "+i+", true_color: "+e+", red_max: "+r+", green_max: "+_+", blue_max: "+h+", red_shift: "+n+", green_shift: "+o+", blue_shift: "+a),0!==i&&Util.Warn("Server native endian is not little endian"),16!==n&&Util.Warn("Server native red-shift is not 16"),0!==a&&Util.Warn("Server native blue-shift is not 0"),this._onDesktopName(this,this._fb_name),this._true_color&&"Intel(r) AMT KVM"===this._fb_name&&(Util.Warn("Intel AMT KVM only supports 8/16 bit depths. Disabling true color"),this._true_color=!1),this._display.set_true_color(this._true_color),this._display.resize(this._fb_width,this._fb_height),this._onFBResize(this,this._fb_width,this._fb_height),this._keyboard.grab(),this._mouse.grab(),this._true_color?(this._fb_Bpp=4,this._fb_depth=3):(this._fb_Bpp=1,this._fb_depth=1),RFB.messages.pixelFormat(this._sock,this._fb_Bpp,this._fb_depth,this._true_color),RFB.messages.clientEncodings(this._sock,this._encodings,this._local_cursor,this._true_color),RFB.messages.fbUpdateRequests(this._sock,this._display.getCleanDirtyReset(),this._fb_width,this._fb_height),this._timing.fbu_rt_start=(new Date).getTime(),this._timing.pixels=0,this._sock.flush(),this._encrypt?this._updateState("normal","Connected (encrypted) to: "+this._fb_name):this._updateState("normal","Connected (unencrypted) to: "+this._fb_name)},_init_msg:function(){switch(this._rfb_state){case"ProtocolVersion":return this._negotiate_protocol_version();case"Security":return this._negotiate_security();case"Authentication":return this._negotiate_authentication();case"SecurityResult":return this._handle_security_result();case"ClientInitialisation":return this._sock.send([this._shared?1:0]),this._updateState("ServerInitialisation","Authentication OK"),!0;case"ServerInitialisation":return this._negotiate_server_init()}},_handle_set_colour_map_msg:function(){Util.Debug("SetColorMapEntries"),this._sock.rQskip8();var t=this._sock.rQshift16(),s=this._sock.rQshift16();if(this._sock.rQwait("SetColorMapEntries",6*s,6))return!1;for(var i=0;i<s;i++){var e=parseInt(this._sock.rQshift16()/256,10),r=parseInt(this._sock.rQshift16()/256,10),_=parseInt(this._sock.rQshift16()/256,10);this._display.set_colourMap([_,r,e],t+i)}return Util.Debug("colourMap: "+this._display.get_colourMap()),Util.Info("Registered "+s+" colourMap entries"),!0},_handle_server_cut_text:function(){if(Util.Debug("ServerCutText"),this._sock.rQwait("ServerCutText header",7,1))return!1;this._sock.rQskipBytes(3);var t=this._sock.rQshift32();if(this._sock.rQwait("ServerCutText",t,8))return!1;var s=this._sock.rQshiftStr(t);return this._onClipboard(this,s),!0},_handle_xvp_msg:function(){if(this._sock.rQwait("XVP version and message",3,1))return!1;this._sock.rQskip8();var t=this._sock.rQshift8(),s=this._sock.rQshift8();switch(s){case 0:this._updateState(this._rfb_state,"Operation Failed");break;case 1:this._rfb_xvp_ver=t,Util.Info("XVP extensions enabled (version "+this._rfb_xvp_ver+")"),this._onXvpInit(this._rfb_xvp_ver);break;default:this._fail("Disconnected: illegal server XVP message "+s)}return!0},_normal_msg:function(){var t;switch(t=this._FBU.rects>0?0:this._sock.rQshift8()){case 0:var s=this._framebufferUpdate();return s&&(RFB.messages.fbUpdateRequests(this._sock,this._display.getCleanDirtyReset(),this._fb_width,this._fb_height),this._sock.flush()),s;case 1:return this._handle_set_colour_map_msg();case 2:return Util.Debug("Bell"),this._onBell(this),!0;case 3:return this._handle_server_cut_text();case 250:return this._handle_xvp_msg();default:return this._fail("Disconnected: illegal server message type "+t),Util.Debug("sock.rQslice(0, 30): "+this._sock.rQslice(0,30)),!0}},_framebufferUpdate:function(){var t,s=!0;if(0===this._FBU.rects){if(this._sock.rQwait("FBU header",3,1))return!1;this._sock.rQskip8(),this._FBU.rects=this._sock.rQshift16(),this._FBU.bytes=0,this._timing.cur_fbu=0,this._timing.fbu_rt_start>0&&(t=(new Date).getTime(),Util.Info("First FBU latency: "+(t-this._timing.fbu_rt_start)))}for(;this._FBU.rects>0;){if("normal"!==this._rfb_state)return!1;if(this._sock.rQwait("FBU",this._FBU.bytes))return!1;if(0===this._FBU.bytes){if(this._sock.rQwait("rect header",12))return!1;var i=this._sock.rQshiftBytes(12);if(this._FBU.x=(i[0]<<8)+i[1],this._FBU.y=(i[2]<<8)+i[3],this._FBU.width=(i[4]<<8)+i[5],this._FBU.height=(i[6]<<8)+i[7],this._FBU.encoding=parseInt((i[8]<<24)+(i[9]<<16)+(i[10]<<8)+i[11],10),this._onFBUReceive(this,{x:this._FBU.x,y:this._FBU.y,width:this._FBU.width,height:this._FBU.height,encoding:this._FBU.encoding,encodingName:this._encNames[this._FBU.encoding]}),!this._encNames[this._FBU.encoding])return this._fail("Disconnected: unsupported encoding "+this._FBU.encoding),!1}this._timing.last_fbu=(new Date).getTime();var e=this._encHandlers[this._FBU.encoding];try{s=e()}catch(t){console.log("missed "+this._FBU.encoding+": "+e),s=this._encHandlers[this._FBU.encoding]()}if(t=(new Date).getTime(),this._timing.cur_fbu+=t-this._timing.last_fbu,s&&(this._encStats[this._FBU.encoding][0]++,this._encStats[this._FBU.encoding][1]++,this._timing.pixels+=this._FBU.width*this._FBU.height),this._timing.pixels>=this._fb_width*this._fb_height&&((this._FBU.width===this._fb_width&&this._FBU.height===this._fb_height||this._timing.fbu_rt_start>0)&&(this._timing.full_fbu_total+=this._timing.cur_fbu,this._timing.full_fbu_cnt++,Util.Info("Timing of full FBU, curr: "+this._timing.cur_fbu+", total: "+this._timing.full_fbu_total+", cnt: "+this._timing.full_fbu_cnt+", avg: "+this._timing.full_fbu_total/this._timing.full_fbu_cnt)),this._timing.fbu_rt_start>0)){var r=t-this._timing.fbu_rt_start;this._timing.fbu_rt_total+=r,this._timing.fbu_rt_cnt++,Util.Info("full FBU round-trip, cur: "+r+", total: "+this._timing.fbu_rt_total+", cnt: "+this._timing.fbu_rt_cnt+", avg: "+this._timing.fbu_rt_total/this._timing.fbu_rt_cnt),this._timing.fbu_rt_start=0}if(!s)return s}return this._onFBUComplete(this,{x:this._FBU.x,y:this._FBU.y,width:this._FBU.width,height:this._FBU.height,encoding:this._FBU.encoding,encodingName:this._encNames[this._FBU.encoding]}),!0}},Util.make_properties(RFB,[["target","wo","dom"],["focusContainer","wo","dom"],["encrypt","rw","bool"],["true_color","rw","bool"],["local_cursor","rw","bool"],["shared","rw","bool"],["view_only","rw","bool"],["xvp_password_sep","rw","str"],["disconnectTimeout","rw","int"],["wsProtocols","rw","arr"],["repeaterID","rw","str"],["viewportDrag","rw","bool"],["onUpdateState","rw","func"],["onPasswordRequired","rw","func"],["onClipboard","rw","func"],["onBell","rw","func"],["onFBUReceive","rw","func"],["onFBUComplete","rw","func"],["onFBResize","rw","func"],["onDesktopName","rw","func"],["onXvpInit","rw","func"]]),RFB.prototype.set_local_cursor=function(t){!t||t in{0:1,no:1,false:1}?(this._local_cursor=!1,this._display.disableLocalCursor()):this._display.get_cursor_uri()?this._local_cursor=!0:(Util.Warn("Browser does not support local cursor"),this._display.disableLocalCursor())},RFB.prototype.get_display=function(){return this._display},RFB.prototype.get_keyboard=function(){return this._keyboard},RFB.prototype.get_mouse=function(){return this._mouse},RFB.messages={keyEvent:function(t,s,i){var e=t._sQ,r=t._sQlen;e[r]=4,e[r+1]=i,e[r+2]=0,e[r+3]=0,e[r+4]=s>>24,e[r+5]=s>>16,e[r+6]=s>>8,e[r+7]=s,t._sQlen+=8},pointerEvent:function(t,s,i,e){var r=t._sQ,_=t._sQlen;r[_]=5,r[_+1]=e,r[_+2]=s>>8,r[_+3]=s,r[_+4]=i>>8,r[_+5]=i,t._sQlen+=6},clientCutText:function(t,s){var i=t._sQ,e=t._sQlen;i[e]=6,i[e+1]=0,i[e+2]=0,i[e+3]=0;var r=s.length;i[e+4]=r>>24,i[e+5]=r>>16,i[e+6]=r>>8,i[e+7]=r;for(var _=0;_<r;_++)i[e+8+_]=s.charCodeAt(_);t._sQlen+=8+r},setDesktopSize:function(t,s,i,e,r){var _=t._sQ,h=t._sQlen;_[h]=251,_[h+1]=0,_[h+2]=s>>8,_[h+3]=s,_[h+4]=i>>8,_[h+5]=i,_[h+6]=1,_[h+7]=0,_[h+8]=e>>24,_[h+9]=e>>16,_[h+10]=e>>8,_[h+11]=e,_[h+12]=0,_[h+13]=0,_[h+14]=0,_[h+15]=0,_[h+16]=s>>8,_[h+17]=s,_[h+18]=i>>8,_[h+19]=i,_[h+20]=r>>24,_[h+21]=r>>16,_[h+22]=r>>8,_[h+23]=r,t._sQlen+=24},pixelFormat:function(t,s,i,e){var r=t._sQ,_=t._sQlen;r[_]=0,r[_+1]=0,r[_+2]=0,r[_+3]=0,r[_+4]=8*s,r[_+5]=8*i,r[_+6]=0,r[_+7]=e?1:0,r[_+8]=0,r[_+9]=255,r[_+10]=0,r[_+11]=255,r[_+12]=0,r[_+13]=255,r[_+14]=16,r[_+15]=8,r[_+16]=0,r[_+17]=0,r[_+18]=0,r[_+19]=0,t._sQlen+=20},clientEncodings:function(t,s,i,e){var r=t._sQ,_=t._sQlen;r[_]=2,r[_+1]=0;var h,n=_+4,o=0;for(h=0;h<s.length;h++)if("Cursor"!==s[h][0]||i)if("TIGHT"!==s[h][0]||e){var a=s[h][1];r[n]=a>>24,r[n+1]=a>>16,r[n+2]=a>>8,r[n+3]=a,n+=4,o++}else Util.Warn("Skipping tight as it is only supported with true color");else Util.Debug("Skipping Cursor pseudo-encoding");r[_+2]=o>>8,r[_+3]=o,t._sQlen+=n-_},fbUpdateRequests:function(t,s,i,e){var r,_,h=s.cleanBox;h.w>0&&h.h>0&&(r=void 0===h.w?i:h.w,_=void 0===h.h?e:h.h,RFB.messages.fbUpdateRequest(t,1,h.x,h.y,r,_));for(var n=0;n<s.dirtyBoxes.length;n++){var o=s.dirtyBoxes[n];r=void 0===o.w?i:o.w,_=void 0===o.h?e:o.h,RFB.messages.fbUpdateRequest(t,0,o.x,o.y,r,_)}},fbUpdateRequest:function(t,s,i,e,r,_){var h=t._sQ,n=t._sQlen;void 0===i&&(i=0),void 0===e&&(e=0),h[n]=3,h[n+1]=s,h[n+2]=i>>8&255,h[n+3]=255&i,h[n+4]=e>>8&255,h[n+5]=255&e,h[n+6]=r>>8&255,h[n+7]=255&r,h[n+8]=_>>8&255,h[n+9]=255&_,t._sQlen+=10}},RFB.genDES=function(t,s){for(var i=[],e=0;e<t.length;e++)i.push(t.charCodeAt(e));return new DES(i).encrypt(s)},RFB.extract_data_uri=function(t){return";base64,"+Base64.encode(t)},RFB.encodingHandlers={RAW:function(){if(0===this._FBU.lines&&(this._FBU.lines=this._FBU.height),this._FBU.bytes=this._FBU.width*this._fb_Bpp,this._sock.rQwait("RAW",this._FBU.bytes))return!1;var t=this._FBU.y+(this._FBU.height-this._FBU.lines),s=Math.min(this._FBU.lines,Math.floor(this._sock.rQlen()/(this._FBU.width*this._fb_Bpp)));return this._display.blitImage(this._FBU.x,t,this._FBU.width,s,this._sock.get_rQ(),this._sock.get_rQi()),this._sock.rQskipBytes(this._FBU.width*s*this._fb_Bpp),this._FBU.lines-=s,this._FBU.lines>0?this._FBU.bytes=this._FBU.width*this._fb_Bpp:(this._FBU.rects--,this._FBU.bytes=0),!0},COPYRECT:function(){return this._FBU.bytes=4,!this._sock.rQwait("COPYRECT",4)&&(this._display.copyImage(this._sock.rQshift16(),this._sock.rQshift16(),this._FBU.x,this._FBU.y,this._FBU.width,this._FBU.height),this._FBU.rects--,this._FBU.bytes=0,!0)},RRE:function(){var t;if(0===this._FBU.subrects){if(this._FBU.bytes=4+this._fb_Bpp,this._sock.rQwait("RRE",4+this._fb_Bpp))return!1;this._FBU.subrects=this._sock.rQshift32(),t=this._sock.rQshiftBytes(this._fb_Bpp),this._display.fillRect(this._FBU.x,this._FBU.y,this._FBU.width,this._FBU.height,t)}for(;this._FBU.subrects>0&&this._sock.rQlen()>=this._fb_Bpp+8;){t=this._sock.rQshiftBytes(this._fb_Bpp);var s=this._sock.rQshift16(),i=this._sock.rQshift16(),e=this._sock.rQshift16(),r=this._sock.rQshift16();this._display.fillRect(this._FBU.x+s,this._FBU.y+i,e,r,t),this._FBU.subrects--}if(this._FBU.subrects>0){var _=Math.min(this._rre_chunk_sz,this._FBU.subrects);this._FBU.bytes=(this._fb_Bpp+8)*_}else this._FBU.rects--,this._FBU.bytes=0;return!0},HEXTILE:function(){var t=this._sock.get_rQ(),s=this._sock.get_rQi();for(0===this._FBU.tiles&&(this._FBU.tiles_x=Math.ceil(this._FBU.width/16),this._FBU.tiles_y=Math.ceil(this._FBU.height/16),this._FBU.total_tiles=this._FBU.tiles_x*this._FBU.tiles_y,this._FBU.tiles=this._FBU.total_tiles);this._FBU.tiles>0;){if(this._FBU.bytes=1,this._sock.rQwait("HEXTILE subencoding",this._FBU.bytes))return!1;var i=t[s];if(i>30)return this._fail("Disconnected: illegal hextile subencoding "+i),!1;var e=0,r=this._FBU.total_tiles-this._FBU.tiles,_=r%this._FBU.tiles_x,h=Math.floor(r/this._FBU.tiles_x),n=this._FBU.x+16*_,o=this._FBU.y+16*h,a=Math.min(16,this._FBU.x+this._FBU.width-n),c=Math.min(16,this._FBU.y+this._FBU.height-o);if(1&i)this._FBU.bytes+=a*c*this._fb_Bpp;else if(2&i&&(this._FBU.bytes+=this._fb_Bpp),4&i&&(this._FBU.bytes+=this._fb_Bpp),8&i){if(this._FBU.bytes++,this._sock.rQwait("hextile subrects header",this._FBU.bytes))return!1;e=t[s+this._FBU.bytes-1],this._FBU.bytes+=16&i?e*(this._fb_Bpp+2):2*e}if(this._sock.rQwait("hextile",this._FBU.bytes))return!1;if(this._FBU.subencoding=t[s],s++,0===this._FBU.subencoding)1&this._FBU.lastsubencoding?Util.Debug(" Ignoring blank after RAW"):this._display.fillRect(n,o,a,c,this._FBU.background);else if(1&this._FBU.subencoding)this._display.blitImage(n,o,a,c,t,s),s+=this._FBU.bytes-1;else{if(2&this._FBU.subencoding&&(1==this._fb_Bpp?this._FBU.background=t[s]:this._FBU.background=[t[s],t[s+1],t[s+2],t[s+3]],s+=this._fb_Bpp),4&this._FBU.subencoding&&(1==this._fb_Bpp?this._FBU.foreground=t[s]:this._FBU.foreground=[t[s],t[s+1],t[s+2],t[s+3]],s+=this._fb_Bpp),this._display.startTile(n,o,a,c,this._FBU.background),8&this._FBU.subencoding){e=t[s],s++;for(var l=0;l<e;l++){var f;16&this._FBU.subencoding?(f=1===this._fb_Bpp?t[s]:[t[s],t[s+1],t[s+2],t[s+3]],s+=this._fb_Bpp):f=this._FBU.foreground;var u=t[s];s++;var d=u>>4,p=15&u,b=t[s];s++;var g=1+(b>>4),B=1+(15&b);this._display.subTile(d,p,g,B,f)}}this._display.finishTile()}this._sock.set_rQi(s),this._FBU.lastsubencoding=this._FBU.subencoding,this._FBU.bytes=0,this._FBU.tiles--}return 0===this._FBU.tiles&&this._FBU.rects--,!0},getTightCLength:function(t){var s=1,i=0;return i+=127&t[0],128&t[0]&&(s++,i+=(127&t[1])<<7,128&t[1]&&(s++,i+=t[2]<<14)),[s,i]},display_tight:function(t){if(1===this._fb_depth&&this._fail("Tight protocol handler only implements true color mode"),this._FBU.bytes=1,this._sock.rQwait("TIGHT compression-control",this._FBU.bytes))return!1;var s,i,e,r,_=0,h=-1,n=function(t,s){for(var i=0;i<4;i++)_>>i&1&&(this._FBU.zlibs[i].reset(),console.debug("RESET!"),Util.Info("Reset zlib stream "+i));return this._FBU.zlibs[h].inflate(t,!0,s)}.bind(this),o=function(t,s,i,e){for(var r=this._destBuff,_=Math.floor((i+7)/8),h=Math.floor(i/8),n=0;n<e;n++){var o,a,c,l;for(a=0;a<h;a++)for(o=7;o>=0;o--)c=4*(n*i+8*a+7-o),l=3*(t[n*_+a]>>o&1),r[c]=s[l],r[c+1]=s[l+1],r[c+2]=s[l+2],r[c+3]=255;for(o=7;o>=8-i%8;o--)c=4*(n*i+8*a+7-o),l=3*(t[n*_+a]>>o&1),r[c]=s[l],r[c+1]=s[l+1],r[c+2]=s[l+2],r[c+3]=255}return r}.bind(this),a=function(t,s,i,e){for(var r=this._destBuff,_=i*e*4,h=0,n=0;h<_;h+=4,n++){var o=3*t[n];r[h]=s[o],r[h+1]=s[o+1],r[h+2]=s[o+2],r[h+3]=255}return r}.bind(this),c=this._sock.get_rQi(),l=this._sock.rQwhole(),f=function(){var t=l[c+2]+1,_=t*this._fb_depth;if(this._FBU.bytes+=_,this._sock.rQwait("TIGHT palette "+s,this._FBU.bytes))return!1;var h=t<=2?1:8,f=Math.floor((this._FBU.width*h+7)/8),u=!1;if(f*this._FBU.height<12)u=!0,e=0,r=f*this._FBU.height;else{var d=c+3+_;e=1,r=0,r+=127&l[d],128&l[d]&&(e++,r+=(127&l[d+1])<<7,128&l[d+1]&&(e++,r+=l[d+2]<<14))}if(this._FBU.bytes+=e+r,this._sock.rQwait("TIGHT "+s,this._FBU.bytes))return!1;this._sock.rQskipBytes(3),this._sock.rQshiftTo(this._paletteBuff,_),this._sock.rQskipBytes(e),i=u?this._sock.rQshiftBytes(r):n(this._sock.rQshiftBytes(r),f*this._FBU.height);var p;return 2==t?(p=o(i,this._paletteBuff,this._FBU.width,this._FBU.height),this._display.blitRgbxImage(this._FBU.x,this._FBU.y,this._FBU.width,this._FBU.height,p,0,!1)):(p=a(i,this._paletteBuff,this._FBU.width,this._FBU.height),this._display.blitRgbxImage(this._FBU.x,this._FBU.y,this._FBU.width,this._FBU.height,p,0,!1)),!0}.bind(this),u=function(){var t=!1,_=this._FBU.width*this._FBU.height*this._fb_depth;if(_<12)t=!0,e=0,r=_;else{var h=c+1;e=1,r=0,r+=127&l[h],128&l[h]&&(e++,r+=(127&l[h+1])<<7,128&l[h+1]&&(e++,r+=l[h+2]<<14))}return this._FBU.bytes=1+e+r,!this._sock.rQwait("TIGHT "+s,this._FBU.bytes)&&(this._sock.rQshiftBytes(1+e),i=t?this._sock.rQshiftBytes(r):n(this._sock.rQshiftBytes(r),_),this._display.blitRgbImage(this._FBU.x,this._FBU.y,this._FBU.width,this._FBU.height,i,0,!1),!0)}.bind(this),d=this._sock.rQpeek8();if(_=15&d,d>>=4,h=3&d,8===d)s="fill";else if(9===d)s="jpeg";else if(10===d)s="png";else if(4&d)s="filter";else{if(!(d<4))return this._fail("Illegal tight compression received, ctl: "+d);s="copy"}if(t&&("filter"===s||"copy"===s))return this._fail("filter/copy received in tightPNG mode");switch(s){case"fill":
this._FBU.bytes+=this._fb_depth;break;case"jpeg":case"png":this._FBU.bytes+=3;break;case"filter":this._FBU.bytes+=2}if(this._sock.rQwait("TIGHT "+s,this._FBU.bytes))return!1;switch(s){case"fill":this._display.fillRect(this._FBU.x,this._FBU.y,this._FBU.width,this._FBU.height,[l[c+3],l[c+2],l[c+1]],!1),this._sock.rQskipBytes(4);break;case"png":case"jpeg":var p=c+1;if(e=1,r=0,r+=127&l[p],128&l[p]&&(e++,r+=(127&l[p+1])<<7,128&l[p+1]&&(e++,r+=l[p+2]<<14)),this._FBU.bytes=1+e+r,this._sock.rQwait("TIGHT "+s,this._FBU.bytes))return!1;this._sock.rQskipBytes(1+e);var b=new Image;b.src="data: image/"+s+RFB.extract_data_uri(this._sock.rQshiftBytes(r)),this._display.renderQ_push({type:"img",img:b,x:this._FBU.x,y:this._FBU.y}),b=null;break;case"filter":var g=l[c+1];if(1!==g)throw new Error("Unsupported tight subencoding received, filter: "+g);if(!f())return!1;break;case"copy":if(!u())return!1}return this._FBU.bytes=0,this._FBU.rects--,!0},TIGHT:function(){return this._encHandlers.display_tight(!1)},TIGHT_PNG:function(){return this._encHandlers.display_tight(!0)},last_rect:function(){return this._FBU.rects=0,!0},handle_FB_resize:function(){return this._fb_width=this._FBU.width,this._fb_height=this._FBU.height,this._destBuff=new Uint8Array(this._fb_width*this._fb_height*4),this._display.resize(this._fb_width,this._fb_height),this._onFBResize(this,this._fb_width,this._fb_height),this._timing.fbu_rt_start=(new Date).getTime(),this._FBU.bytes=0,this._FBU.rects-=1,!0},ExtendedDesktopSize:function(){if(this._FBU.bytes=1,this._sock.rQwait("ExtendedDesktopSize",this._FBU.bytes))return!1;this._supportsSetDesktopSize=!0;var t=this._sock.rQpeek8();if(this._FBU.bytes=4+16*t,this._sock.rQwait("ExtendedDesktopSize",this._FBU.bytes))return!1;this._sock.rQskipBytes(1),this._sock.rQskipBytes(3);for(var s=0;s<t;s+=1)0===s?(this._screen_id=this._sock.rQshiftBytes(4),this._sock.rQskipBytes(2),this._sock.rQskipBytes(2),this._sock.rQskipBytes(2),this._sock.rQskipBytes(2),this._screen_flags=this._sock.rQshiftBytes(4)):this._sock.rQskipBytes(16);if(1===this._FBU.x&&0!==this._FBU.y){var i="";switch(this._FBU.y){case 1:i="Resize is administratively prohibited";break;case 2:i="Out of resources";break;case 3:i="Invalid screen layout";break;default:i="Unknown reason"}return Util.Info("Server did not accept the resize request: "+i),!0}return this._encHandlers.handle_FB_resize(),!0},DesktopSize:function(){return this._encHandlers.handle_FB_resize(),!0},Cursor:function(){Util.Debug(">> set_cursor");var t=this._FBU.x,s=this._FBU.y,i=this._FBU.width,e=this._FBU.height,r=i*e*this._fb_Bpp,_=Math.floor((i+7)/8)*e;return this._FBU.bytes=r+_,!this._sock.rQwait("cursor encoding",this._FBU.bytes)&&(this._display.changeCursor(this._sock.rQshiftBytes(r),this._sock.rQshiftBytes(_),t,s,i,e),this._FBU.bytes=0,this._FBU.rects--,Util.Debug("<< set_cursor"),!0)},JPEG_quality_lo:function(){Util.Error("Server sent jpeg_quality pseudo-encoding")},compress_lo:function(){Util.Error("Server sent compress level pseudo-encoding")}}}();