Initial work on desktop sharing.

Ylian Saint-Hilaire committed Aug 6, 2020 at 16:05 UTC cc78d0aac58754b6f6238855f0a29800d7b460f4
9 files changed +1333 -99
MeshCentralServer.njsproj
+1
@@ -565,6 +565,7 @@
565 <Content Include="views\agentinvite.handlebars" />
566 <Content Include="views\default-mobile.handlebars" />
567 <Content Include="views\default.handlebars" />
568 + <Content Include="views\desktop.handlebars" />
569 <Content Include="views\download.handlebars" />
570 <Content Include="views\error404-mobile.handlebars" />
571 <Content Include="views\error404.handlebars" />
meshdesktopmultiplex.js
+1 -1
@@ -787,7 +787,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
787
788 // Get node information
789 parent.db.Get(nodeid, function (err, nodes) {
790 - if ((err != null) || (nodes.length != 1)) { func(null); }
790 + if ((err != null) || (nodes.length != 1)) { func(null); return; }
791 obj.meshid = nodes[0].meshid;
792 obj.icon = nodes[0].icon;
793 obj.name = nodes[0].name;
public/scripts/agent-redir-ws-0.1.1-min.js
+1 -1
@@ -1 +1 @@
1 -var CreateAgentRedirect=function(e,t,n,o,a,c){var s={};function l(){1==s.webSwitchOk&&1==s.webRtcActive&&(s.latency.current=-1,s.sendCtrlMsg('{"ctrlChannel":"102938","type":"webrtc0"}'),s.sendCtrlMsg('{"ctrlChannel":"102938","type":"webrtc1"}'),null!=s.onStateChanged&&s.onStateChanged(s,s.State))}((s.m=t).parent=s).meshserver=e,s.authCookie=o,s.rauthCookie=a,s.State=0,s.nodeid=null,s.options=null,s.socket=null,s.connectstate=-1,s.tunnelid=Math.random().toString(36).substring(2),s.protocol=t.protocol,s.onStateChanged=null,s.ctrlMsgAllowed=!0,s.attemptWebRTC=!1,s.webRtcActive=!1,s.webSwitchOk=!1,s.webchannel=null,s.webrtc=null,s.debugmode=0,s.serverIsRecording=!1,s.latency={lastSend:null,current:-1,callback:null},null==c&&(c="/"),s.consoleMessage=null,s.onConsoleMessageChange=null,s.metadata=null,s.onMetadataChange=null,s.Start=function(e){var t=window.location.protocol.replace("http","ws")+"//"+window.location.host+window.location.pathname.substring(0,window.location.pathname.lastIndexOf("/"))+"/meshrelay.ashx?browser=1&p="+s.protocol+"&nodeid="+e+"&id="+s.tunnelid;null!=o&&""!=o&&(t+="&auth="+o),null!=urlargs&&null!=urlargs.slowrelay&&(t+="&slowrelay="+urlargs.slowrelay),s.nodeid=e,s.connectstate=0,s.socket=new WebSocket(t),s.socket.binaryType="arraybuffer",s.socket.onopen=s.xxOnSocketConnected,s.socket.onmessage=s.xxOnMessage,s.socket.onerror=function(e){},s.socket.onclose=s.xxOnSocketClosed,s.xxStateChange(1);var n="*"+c+"meshrelay.ashx?p="+s.protocol+"&nodeid="+e+"&id="+s.tunnelid;null!=a&&""!=a&&(n+="&rauth="+a),s.meshserver.send({action:"msg",type:"tunnel",nodeid:s.nodeid,value:n,usage:s.protocol})},s.xxOnSocketConnected=function(){1==s.debugmode&&console.log("onSocketConnected"),s.xxStateChange(2)},s.xxOnControlCommand=function(e){var t;try{t=JSON.parse(e)}catch(e){return}"102938"==t.ctrlChannel?("undefined"!=typeof args&&args.redirtrace&&console.log("RedirRecv",t),"console"==t.type?s.setConsoleMessage(t.msg,t.msgid,t.msgargs,t.timeout):"metadata"==t.type?(s.metadata=t,s.onMetadataChange&&s.onMetadataChange(s.metadata)):"rtt"==t.type&&"number"==typeof t.time?(s.latency.current=(new Date).getTime()-t.time,null!=s.latency.callbacks&&s.latency.callback(s.latency.current)):null!=s.webrtc&&("answer"==t.type?s.webrtc.setRemoteDescription(new RTCSessionDescription(t),function(){},s.xxCloseWebRTC):"webrtc0"==t.type?(s.webSwitchOk=!0,l()):"webrtc1"==t.type?s.sendCtrlMsg('{"ctrlChannel":"102938","type":"webrtc2"}'):t.type)):s.m.ProcessData(e)},s.setConsoleMessage=function(e,t,n,o){s.consoleMessage!=e&&(s.consoleMessage=e,s.consoleMessageId=t,s.consoleMessageArgs=n,s.consoleMessageTimeout=o,s.onConsoleMessageChange&&s.onConsoleMessageChange(s,s.consoleMessage,s.consoleMessageId))},s.sendCtrlMsg=function(e){if(1==s.ctrlMsgAllowed){"undefined"!=typeof args&&args.redirtrace&&console.log("RedirSend",typeof e,e);try{s.socket.send(e)}catch(e){}}},s.xxOnMessage=function(e){if(s.State<3&&("c"==e.data||"cr"==e.data)){if("cr"==e.data&&(s.serverIsRecording=!0),null!=s.options){delete s.options.action,s.options.type="options";try{s.sendCtrlMsg(JSON.stringify(s.options))}catch(e){}}try{s.socket.send(s.protocol)}catch(e){}if(s.xxStateChange(3),1==s.attemptWebRTC){"undefined"!=typeof RTCPeerConnection?s.webrtc=new RTCPeerConnection(null):"undefined"!=typeof webkitRTCPeerConnection&&(s.webrtc=new webkitRTCPeerConnection(null)),null!=s.webrtc&&s.webrtc.createDataChannel&&(s.webchannel=s.webrtc.createDataChannel("DataChannel",{}),s.webchannel.binaryType="arraybuffer",s.webchannel.onmessage=s.xxOnMessage,s.webchannel.onopen=function(){s.webRtcActive=!0,l()},s.webchannel.onclose=function(e){s.webRtcActive&&s.Stop()},s.webrtc.onicecandidate=function(e){if(null==e.candidate)try{s.sendCtrlMsg(JSON.stringify(s.webrtcoffer))}catch(e){}else s.webrtcoffer.sdp+="a="+e.candidate.candidate+"\r\n"},s.webrtc.oniceconnectionstatechange=function(){null!=s.webrtc&&("disconnected"==s.webrtc.iceConnectionState?1==s.webRtcActive?s.Stop():s.xxCloseWebRTC():"failed"==s.webrtc.iceConnectionState&&s.xxCloseWebRTC())},s.webrtc.createOffer(function(e){s.webrtcoffer=e,s.webrtc.setLocalDescription(e,function(){},s.xxCloseWebRTC)},s.xxCloseWebRTC,{mandatory:{OfferToReceiveAudio:!1,OfferToReceiveVideo:!1}}))}}else if("string"==typeof e.data)s.xxOnControlCommand(e.data);else if(s.m.ProcessBinaryCommand)if(0!=u){var t=new Uint8Array(e.data);if(g.push(t),u+=t.byteLength,d<=u){var n=new Uint8Array(u),o=0;for(var a in g)n.set(g[a],o),o+=g[a].byteLength;s.m.ProcessBinaryCommand(i,d,n),u=d=i=0,g=[]}}else{var c=((t=new Uint8Array(e.data))[0]<<8)+t[1],r=(t[2]<<8)+t[3];27==c&&8==r&&(c=(t[8]<<8)+t[9],r=(t[5]<<16)+(t[6]<<8)+t[7],t=t.slice(8)),r!=t.byteLength?(i=c,d=r,u=t.byteLength,g=[t]):s.m.ProcessBinaryCommand(c,r,t)}else s.m.ProcessBinaryData?s.m.ProcessBinaryData(new Uint8Array(e.data)):s.m.ProcessData(String.fromCharCode.apply(null,new Uint8Array(e.data)))};var i=0,d=0,u=0,g=[];return s.sendText=function(e){"string"!=typeof e&&(e=JSON.stringify(e)),s.send(encode_utf8(e))},s.send=function(e){"undefined"!=typeof args&&args.redirtrace&&console.log("RedirSend",typeof e,e.length,"{"==e[0]?e:rstr2hex(e).substring(0,64));try{if(null!=s.socket&&s.socket.readyState==WebSocket.OPEN)if("string"==typeof e)if(1==s.debugmode){for(var t=new Uint8Array(e.length),n=[],o=0;o<e.length;++o)t[o]=e.charCodeAt(o),n.push(e.charCodeAt(o));1==s.webRtcActive?s.webchannel.send(t.buffer):s.socket.send(t.buffer)}else{for(t=new Uint8Array(e.length),o=0;o<e.length;++o)t[o]=e.charCodeAt(o);1==s.webRtcActive?s.webchannel.send(t.buffer):s.socket.send(t.buffer)}else 1==s.webRtcActive?s.webchannel.send(e):s.socket.send(e)}catch(e){}},s.xxOnSocketClosed=function(){s.Stop(1)},s.xxStateChange=function(e){s.State!=e&&(s.State=e,s.m.xxStateChange(s.State),null!=s.onStateChanged&&s.onStateChanged(s,s.State))},s.xxCloseWebRTC=function(){if(null!=s.webchannel){try{s.webchannel.close()}catch(e){}s.webchannel=null}if(null!=s.webrtc){try{s.webrtc.close()}catch(e){}s.webrtc=null}s.webRtcActive=!1},s.Stop=function(e){if(1==s.debugmode&&console.log("stop",e),s.xxCloseWebRTC(),s.connectstate=-1,null!=s.socket){try{1==s.socket.readyState&&(s.sendCtrlMsg('{"ctrlChannel":"102938","type":"close"}'),s.socket.close())}catch(e){}s.socket=null}s.xxStateChange(0)},s}
\ No newline at end of file
1 +var CreateAgentRedirect=function(e,t,n,o,a,c){var s={};function l(){1==s.webSwitchOk&&1==s.webRtcActive&&(s.latency.current=-1,s.sendCtrlMsg('{"ctrlChannel":"102938","type":"webrtc0"}'),s.sendCtrlMsg('{"ctrlChannel":"102938","type":"webrtc1"}'),null!=s.onStateChanged&&s.onStateChanged(s,s.State))}((s.m=t).parent=s).meshserver=e,s.authCookie=o,s.rauthCookie=a,s.State=0,s.nodeid=null,s.options=null,s.socket=null,s.connectstate=-1,s.tunnelid=Math.random().toString(36).substring(2),s.protocol=t.protocol,s.onStateChanged=null,s.ctrlMsgAllowed=!0,s.attemptWebRTC=!1,s.webRtcActive=!1,s.webSwitchOk=!1,s.webchannel=null,s.webrtc=null,s.debugmode=0,s.serverIsRecording=!1,s.latency={lastSend:null,current:-1,callback:null},null==c&&(c="/"),s.consoleMessage=null,s.onConsoleMessageChange=null,s.metadata=null,s.onMetadataChange=null,s.Start=function(e){var t=window.location.protocol.replace("http","ws")+"//"+window.location.host+window.location.pathname.substring(0,window.location.pathname.lastIndexOf("/"))+"/meshrelay.ashx?browser=1&p="+s.protocol+"&nodeid="+e+"&id="+s.tunnelid;if(null!=o&&""!=o&&(t+="&auth="+o),null!=urlargs&&null!=urlargs.slowrelay&&(t+="&slowrelay="+urlargs.slowrelay),s.nodeid=e,s.connectstate=0,s.socket=new WebSocket(t),s.socket.binaryType="arraybuffer",s.socket.onopen=s.xxOnSocketConnected,s.socket.onmessage=s.xxOnMessage,s.socket.onerror=function(e){},s.socket.onclose=s.xxOnSocketClosed,s.xxStateChange(1),null!=s.meshserver){var n="*"+c+"meshrelay.ashx?p="+s.protocol+"&nodeid="+e+"&id="+s.tunnelid;null!=a&&""!=a&&(n+="&rauth="+a),s.meshserver.send({action:"msg",type:"tunnel",nodeid:s.nodeid,value:n,usage:s.protocol})}},s.xxOnSocketConnected=function(){1==s.debugmode&&console.log("onSocketConnected"),s.xxStateChange(2)},s.xxOnControlCommand=function(e){var t;try{t=JSON.parse(e)}catch(e){return}"102938"==t.ctrlChannel?("undefined"!=typeof args&&args.redirtrace&&console.log("RedirRecv",t),"console"==t.type?s.setConsoleMessage(t.msg,t.msgid,t.msgargs,t.timeout):"metadata"==t.type?(s.metadata=t,s.onMetadataChange&&s.onMetadataChange(s.metadata)):"rtt"==t.type&&"number"==typeof t.time?(s.latency.current=(new Date).getTime()-t.time,null!=s.latency.callbacks&&s.latency.callback(s.latency.current)):null!=s.webrtc&&("answer"==t.type?s.webrtc.setRemoteDescription(new RTCSessionDescription(t),function(){},s.xxCloseWebRTC):"webrtc0"==t.type?(s.webSwitchOk=!0,l()):"webrtc1"==t.type?s.sendCtrlMsg('{"ctrlChannel":"102938","type":"webrtc2"}'):t.type)):s.m.ProcessData(e)},s.setConsoleMessage=function(e,t,n,o){s.consoleMessage!=e&&(s.consoleMessage=e,s.consoleMessageId=t,s.consoleMessageArgs=n,s.consoleMessageTimeout=o,s.onConsoleMessageChange&&s.onConsoleMessageChange(s,s.consoleMessage,s.consoleMessageId))},s.sendCtrlMsg=function(e){if(1==s.ctrlMsgAllowed){"undefined"!=typeof args&&args.redirtrace&&console.log("RedirSend",typeof e,e);try{s.socket.send(e)}catch(e){}}},s.xxOnMessage=function(e){if(s.State<3&&("c"==e.data||"cr"==e.data)){if("cr"==e.data&&(s.serverIsRecording=!0),null!=s.options){delete s.options.action,s.options.type="options";try{s.sendCtrlMsg(JSON.stringify(s.options))}catch(e){}}try{s.socket.send(s.protocol)}catch(e){}if(s.xxStateChange(3),1==s.attemptWebRTC){"undefined"!=typeof RTCPeerConnection?s.webrtc=new RTCPeerConnection(null):"undefined"!=typeof webkitRTCPeerConnection&&(s.webrtc=new webkitRTCPeerConnection(null)),null!=s.webrtc&&s.webrtc.createDataChannel&&(s.webchannel=s.webrtc.createDataChannel("DataChannel",{}),s.webchannel.binaryType="arraybuffer",s.webchannel.onmessage=s.xxOnMessage,s.webchannel.onopen=function(){s.webRtcActive=!0,l()},s.webchannel.onclose=function(e){s.webRtcActive&&s.Stop()},s.webrtc.onicecandidate=function(e){if(null==e.candidate)try{s.sendCtrlMsg(JSON.stringify(s.webrtcoffer))}catch(e){}else s.webrtcoffer.sdp+="a="+e.candidate.candidate+"\r\n"},s.webrtc.oniceconnectionstatechange=function(){null!=s.webrtc&&("disconnected"==s.webrtc.iceConnectionState?1==s.webRtcActive?s.Stop():s.xxCloseWebRTC():"failed"==s.webrtc.iceConnectionState&&s.xxCloseWebRTC())},s.webrtc.createOffer(function(e){s.webrtcoffer=e,s.webrtc.setLocalDescription(e,function(){},s.xxCloseWebRTC)},s.xxCloseWebRTC,{mandatory:{OfferToReceiveAudio:!1,OfferToReceiveVideo:!1}}))}}else if("string"==typeof e.data)s.xxOnControlCommand(e.data);else if(s.m.ProcessBinaryCommand)if(0!=u){var t=new Uint8Array(e.data);if(g.push(t),u+=t.byteLength,d<=u){var n=new Uint8Array(u),o=0;for(var a in g)n.set(g[a],o),o+=g[a].byteLength;s.m.ProcessBinaryCommand(i,d,n),u=d=i=0,g=[]}}else{var c=((t=new Uint8Array(e.data))[0]<<8)+t[1],r=(t[2]<<8)+t[3];27==c&&8==r&&(c=(t[8]<<8)+t[9],r=(t[5]<<16)+(t[6]<<8)+t[7],t=t.slice(8)),r!=t.byteLength?(i=c,d=r,u=t.byteLength,g=[t]):s.m.ProcessBinaryCommand(c,r,t)}else s.m.ProcessBinaryData?s.m.ProcessBinaryData(new Uint8Array(e.data)):s.m.ProcessData(String.fromCharCode.apply(null,new Uint8Array(e.data)))};var i=0,d=0,u=0,g=[];return s.sendText=function(e){"string"!=typeof e&&(e=JSON.stringify(e)),s.send(encode_utf8(e))},s.send=function(e){"undefined"!=typeof args&&args.redirtrace&&console.log("RedirSend",typeof e,e.length,"{"==e[0]?e:rstr2hex(e).substring(0,64));try{if(null!=s.socket&&s.socket.readyState==WebSocket.OPEN)if("string"==typeof e)if(1==s.debugmode){for(var t=new Uint8Array(e.length),n=[],o=0;o<e.length;++o)t[o]=e.charCodeAt(o),n.push(e.charCodeAt(o));1==s.webRtcActive?s.webchannel.send(t.buffer):s.socket.send(t.buffer)}else{for(t=new Uint8Array(e.length),o=0;o<e.length;++o)t[o]=e.charCodeAt(o);1==s.webRtcActive?s.webchannel.send(t.buffer):s.socket.send(t.buffer)}else 1==s.webRtcActive?s.webchannel.send(e):s.socket.send(e)}catch(e){}},s.xxOnSocketClosed=function(){s.Stop(1)},s.xxStateChange=function(e){s.State!=e&&(s.State=e,s.m.xxStateChange(s.State),null!=s.onStateChanged&&s.onStateChanged(s,s.State))},s.xxCloseWebRTC=function(){if(null!=s.webchannel){try{s.webchannel.close()}catch(e){}s.webchannel=null}if(null!=s.webrtc){try{s.webrtc.close()}catch(e){}s.webrtc=null}s.webRtcActive=!1},s.Stop=function(e){if(1==s.debugmode&&console.log("stop",e),s.xxCloseWebRTC(),s.connectstate=-1,null!=s.socket){try{1==s.socket.readyState&&(s.sendCtrlMsg('{"ctrlChannel":"102938","type":"close"}'),s.socket.close())}catch(e){}s.socket=null}s.xxStateChange(0)},s}
\ No newline at end of file
public/scripts/agent-redir-ws-0.1.1.js
+6 -5
@@ -57,11 +57,12 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort, au
57 obj.socket.onerror = function (e) { /* console.error(e); */ }
58 obj.socket.onclose = obj.xxOnSocketClosed;
59 obj.xxStateChange(1);
60 - //obj.meshserver.send({ action: 'msg', type: 'tunnel', nodeid: obj.nodeid, value: url2 });
61 - var rurl = '*' + domainUrl + 'meshrelay.ashx?p=' + obj.protocol + '&nodeid=' + nodeid + '&id=' + obj.tunnelid;
62 - if ((rauthCookie != null) && (rauthCookie != '')) { rurl += ('&rauth=' + rauthCookie); }
63 - obj.meshserver.send({ action: 'msg', type: 'tunnel', nodeid: obj.nodeid, value: rurl, usage: obj.protocol });
64 - //obj.debug('Agent Redir Start: ' + url);
60 + if (obj.meshserver != null) {
61 + var rurl = '*' + domainUrl + 'meshrelay.ashx?p=' + obj.protocol + '&nodeid=' + nodeid + '&id=' + obj.tunnelid;
62 + if ((rauthCookie != null) && (rauthCookie != '')) { rurl += ('&rauth=' + rauthCookie); }
63 + obj.meshserver.send({ action: 'msg', type: 'tunnel', nodeid: obj.nodeid, value: rurl, usage: obj.protocol });
64 + //obj.debug('Agent Redir Start: ' + url);
65 + }
66 }
67
68 obj.xxOnSocketConnected = function () {
public/scripts/amt-wsman-0.2.0-min.js
+1 -1
@@ -1 +1 @@
1 -var WsmanStackCreateService=function(e,s,r,a,o,t){var p={};function l(e){if(!e)return"";var s=" ";for(var r in e)e.hasOwnProperty(r)&&0===r.indexOf("@")&&(s+=r.substring(1)+'="'+e[r]+'" ');return s}function w(e){if(!e)return"";if("string"==typeof e)return e;if(e.InstanceID)return'<w:SelectorSet><w:Selector Name="InstanceID">'+e.InstanceID+"</w:Selector></w:SelectorSet>";var s="<w:SelectorSet>";for(var r in e)if(e.hasOwnProperty(r)){if(s+='<w:Selector Name="'+r+'">',e[r].ReferenceParameters){s+="<a:EndpointReference>",s+="<a:Address>"+e[r].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+e[r].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var a=e[r].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(a))for(var o=0;o<a.length;o++)s+="<w:Selector"+l(a[o])+">"+a[o].Value+"</w:Selector>";else s+="<w:Selector"+l(a)+">"+a.Value+"</w:Selector>";s+="</w:SelectorSet></a:ReferenceParameters></a:EndpointReference>"}else s+=e[r];s+="</w:Selector>"}return s+="</w:SelectorSet>"}return p.NextMessageId=1,p.Address="/wsman",p.comm=CreateWsmanComm(e,s,r,a,o,t),p.PerformAjax=function(e,o,s,r,a){null==a&&(a=""),p.comm.PerformAjax('<?xml version=\"1.0\" encoding=\"utf-8\"?><Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns="http://www.w3.org/2003/05/soap-envelope" '+a+"><Header><a:Action>"+e,function(e,s,r){if(200==s){var a=p.ParseWsman(e);a&&null!=a?o(p,a.Header.ResourceURI,a,200,r):o(p,null,{Header:{HttpError:s}},601,r)}else o(p,null,{Header:{HttpError:s}},s,r)},s,r)},p.CancelAllQueries=function(e){p.comm.CancelAllQueries(e)},p.GetNameFromUrl=function(e){var s=e.lastIndexOf("/");return-1==s?e:e.substring(s+1)},p.ExecSubscribe=function(e,s,r,a,o,t,n,l,c,d){var m="",i="";null!=c&&null!=d&&(m="<t:IssuedTokens><t:RequestSecurityTokenResponse><t:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</t:TokenType><t:RequestedSecurityToken><se:UsernameToken><se:Username>"+c+'</se:Username><se:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd#PasswordText">'+d+"</se:Password></se:UsernameToken></t:RequestedSecurityToken></t:RequestSecurityTokenResponse></t:IssuedTokens>",i='<Auth Profile="http://schemas.xmlsoap.org/ws/2004/08/eventing/DeliveryModes/secprofile/http/digest"/>'),l=null!=l&&null!=l?"<a:ReferenceParameters>"+l+"</a:ReferenceParameters>":"";var u="http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(n)+m+'</Header><Body><e:Subscribe><e:Delivery Mode="http://schemas.dmtf.org/wbem/wsman/1/wsman/'+s+'"><e:NotifyTo><a:Address>'+r+"</a:Address></e:NotifyTo>"+i+"</e:Delivery><e:Expires>PT0.000000S</e:Expires></e:Subscribe>";p.PerformAjax(u+"</Body></Envelope>",a,o,t,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:se="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:m="http://x.com"')},p.ExecUnSubscribe=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(o)+"</Header><Body><e:Unsubscribe/>";p.PerformAjax(t+"</Body></Envelope>",s,r,a,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"')},p.ExecPut=function(e,s,r,a,o,t){var n="http://schemas.xmlsoap.org/ws/2004/09/transfer/Put</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout>"+w(t)+"</Header><Body>"+function(e,s){if(!e||null==s)return"";var r=p.GetNameFromUrl(e),a="<r:"+r+' xmlns:r="'+e+'">';for(var o in s)if(s.hasOwnProperty(o)&&0!==o.indexOf("__")&&0!==o.indexOf("@")&&void 0!==s[o]&&null!==s[o]&&"function"!=typeof s[o])if("object"==typeof s[o]&&s[o].ReferenceParameters){a+="<r:"+o+"><a:Address>"+s[o].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+s[o].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var t=s[o].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(t))for(var n=0;n<t.length;n++)a+="<w:Selector"+l(t[n])+">"+t[n].Value+"</w:Selector>";else a+="<w:Selector"+l(t)+">"+t.Value+"</w:Selector>";a+="</w:SelectorSet></a:ReferenceParameters></r:"+o+">"}else if(Array.isArray(s[o]))for(n=0;n<s[o].length;n++)a+="<r:"+o+">"+s[o][n].toString()+"</r:"+o+">";else a+="<r:"+o+">"+s[o].toString()+"</r:"+o+">";return a+="</r:"+r+">"}(e,s);p.PerformAjax(n+"</Body></Envelope>",r,a,o)},p.ExecCreate=function(e,s,r,a,o,t){var n=p.GetNameFromUrl(e),l="http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(t)+"</Header><Body><g:"+n+' xmlns:g="'+e+'">';for(var c in s)l+="<g:"+c+">"+s[c]+"</g:"+c+">";p.PerformAjax(l+"</g:"+n+"></Body></Envelope>",r,a,o)},p.ExecCreateXml=function(e,s,r,a,o){var t=p.GetNameFromUrl(e);p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout></Header><Body><r:"+t+' xmlns:r="'+e+'">'+s+"</r:"+t+"></Body></Envelope>",r,a,o)},p.ExecDelete=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(s)+"</Header><Body /></Envelope>";p.PerformAjax(t,r,a,o)},p.ExecGet=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body /></Envelope>",s,r,a)},p.ExecMethod=function(e,s,r,a,o,t,n){var l="";for(var c in r)if(null!=r[c])if(Array.isArray(r[c]))for(var d in r[c])l+="<r:"+c+">"+r[c][d]+"</r:"+c+">";else l+="<r:"+c+">"+r[c]+"</r:"+c+">";p.ExecMethodXml(e,s,l,a,o,t,n)},p.ExecMethodXml=function(e,s,r,a,o,t,n){p.PerformAjax(e+"/"+s+"</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(n)+"</Header><Body><r:"+s+'_INPUT xmlns:r="'+e+'">'+r+"</r:"+s+"_INPUT></Body></Envelope>",a,o,t)},p.ExecEnum=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Enumerate xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration" /></Body></Envelope>',s,r,a)},p.ExecPull=function(e,s,r,a,o){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Pull xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration"><EnumerationContext>'+s+"</EnumerationContext><MaxElements>999</MaxElements><MaxCharacters>99999</MaxCharacters></Pull></Body></Envelope>",r,a,o)},p.ParseWsman=function(s){try{s.childNodes||(s=function(e){{if(window.DOMParser)return(new DOMParser).parseFromString(e,"text/xml");var s=new ActiveXObject("Microsoft.XMLDOM");return s.async=!1,s.loadXML(e),s}}(s));var e,r={Header:{}},a=s.getElementsByTagName("Header")[0];if(!(a=a||s.getElementsByTagName("a:Header")[0]))return null;for(var o=0;o<a.childNodes.length;o++){var t=a.childNodes[o];r.Header[t.localName]=t.textContent}var n=s.getElementsByTagName("Body")[0];return(n=n||s.getElementsByTagName("a:Body")[0])?(0<n.childNodes.length&&((e=n.childNodes[0].localName).indexOf("_OUTPUT")==e.length-7&&(e=e.substring(0,e.length-7)),r.Header.Method=e,r.Body=function e(s){var r,a={};for(var o=0;o<s.childNodes.length;o++){var t=s.childNodes[o];"true"==(r=0==t.childElementCount?t.textContent:e(t))&&(r=!0),"false"==r&&(r=!1);var n=r;if(0<t.attributes.length){n={Value:r};for(var l=0;l<t.attributes.length;l++)n["@"+t.attributes[l].name]=t.attributes[l].value}a[t.localName]instanceof Array?a[t.localName].push(n):null==a[t.localName]?a[t.localName]=n:a[t.localName]=[a[t.localName],n]}return a}(n.childNodes[0])),r):null}catch(e){return console.log("Unable to parse XML: "+s),null}},p}
\ No newline at end of file
1 +var WsmanStackCreateService=function(e,s,r,a,o,t){var p={};function l(e){if(!e)return"";var s=" ";for(var r in e)e.hasOwnProperty(r)&&0===r.indexOf("@")&&(s+=r.substring(1)+'="'+e[r]+'" ');return s}function w(e){if(!e)return"";if("string"==typeof e)return e;if(e.InstanceID)return'<w:SelectorSet><w:Selector Name="InstanceID">'+e.InstanceID+"</w:Selector></w:SelectorSet>";var s="<w:SelectorSet>";for(var r in e)if(e.hasOwnProperty(r)){if(s+='<w:Selector Name="'+r+'">',e[r].ReferenceParameters){s+="<a:EndpointReference>",s+="<a:Address>"+e[r].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+e[r].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var a=e[r].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(a))for(var o=0;o<a.length;o++)s+="<w:Selector"+l(a[o])+">"+a[o].Value+"</w:Selector>";else s+="<w:Selector"+l(a)+">"+a.Value+"</w:Selector>";s+="</w:SelectorSet></a:ReferenceParameters></a:EndpointReference>"}else s+=e[r];s+="</w:Selector>"}return s+="</w:SelectorSet>"}return p.NextMessageId=1,p.Address="/wsman",p.comm=CreateWsmanComm(e,s,r,a,o,t),p.PerformAjax=function(e,o,s,r,a){null==a&&(a=""),p.comm.PerformAjax('<?xml version=\"1.0\" encoding=\"utf-8\"?><Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns="http://www.w3.org/2003/05/soap-envelope" '+a+"><Header><a:Action>"+e,function(e,s,r){if(200==s){var a=p.ParseWsman(e);a&&null!=a?o(p,a.Header.ResourceURI,a,200,r):o(p,null,{Header:{HttpError:s}},601,r)}else o(p,null,{Header:{HttpError:s}},s,r)},s,r)},p.CancelAllQueries=function(e){p.comm.CancelAllQueries(e)},p.GetNameFromUrl=function(e){var s=e.lastIndexOf("/");return-1==s?e:e.substring(s+1)},p.ExecSubscribe=function(e,s,r,a,o,t,n,l,d,c){var m="",i="";null!=d&&null!=c&&(m="<t:IssuedTokens><t:RequestSecurityTokenResponse><t:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</t:TokenType><t:RequestedSecurityToken><se:UsernameToken><se:Username>"+d+'</se:Username><se:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd#PasswordText">'+c+"</se:Password></se:UsernameToken></t:RequestedSecurityToken></t:RequestSecurityTokenResponse></t:IssuedTokens>",i='<Auth Profile="http://schemas.xmlsoap.org/ws/2004/08/eventing/DeliveryModes/secprofile/http/digest"/>'),l=null!=l&&null!=l?"<a:ReferenceParameters>"+l+"</a:ReferenceParameters>":"";var u="http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(n)+m+'</Header><Body><e:Subscribe><e:Delivery Mode="http://schemas.dmtf.org/wbem/wsman/1/wsman/'+s+'"><e:NotifyTo><a:Address>'+r+"</a:Address></e:NotifyTo>"+i+"</e:Delivery><e:Expires>PT0.000000S</e:Expires></e:Subscribe>";p.PerformAjax(u+"</Body></Envelope>",a,o,t,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:se="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:m="http://x.com"')},p.ExecUnSubscribe=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(o)+"</Header><Body><e:Unsubscribe/>";p.PerformAjax(t+"</Body></Envelope>",s,r,a,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"')},p.ExecPut=function(e,s,r,a,o,t){var n="http://schemas.xmlsoap.org/ws/2004/09/transfer/Put</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout>"+w(t)+"</Header><Body>"+function(e,s){if(!e||null==s)return"";var r=p.GetNameFromUrl(e),a="<r:"+r+' xmlns:r="'+e+'">';for(var o in s)if(s.hasOwnProperty(o)&&0!==o.indexOf("__")&&0!==o.indexOf("@")&&void 0!==s[o]&&null!==s[o]&&"function"!=typeof s[o])if("object"==typeof s[o]&&s[o].ReferenceParameters){a+="<r:"+o+"><a:Address>"+s[o].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+s[o].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var t=s[o].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(t))for(var n=0;n<t.length;n++)a+="<w:Selector"+l(t[n])+">"+t[n].Value+"</w:Selector>";else a+="<w:Selector"+l(t)+">"+t.Value+"</w:Selector>";a+="</w:SelectorSet></a:ReferenceParameters></r:"+o+">"}else if(Array.isArray(s[o]))for(n=0;n<s[o].length;n++)a+="<r:"+o+">"+s[o][n].toString()+"</r:"+o+">";else a+="<r:"+o+">"+s[o].toString()+"</r:"+o+">";return a+="</r:"+r+">"}(e,s);p.PerformAjax(n+"</Body></Envelope>",r,a,o)},p.ExecCreate=function(e,s,r,a,o,t){var n=p.GetNameFromUrl(e),l="http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(t)+"</Header><Body><g:"+n+' xmlns:g="'+e+'">';for(var d in s)l+="<g:"+d+">"+s[d]+"</g:"+d+">";p.PerformAjax(l+"</g:"+n+"></Body></Envelope>",r,a,o)},p.ExecCreateXml=function(e,s,r,a,o){var t=p.GetNameFromUrl(e);p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout></Header><Body><r:"+t+' xmlns:r="'+e+'">'+s+"</r:"+t+"></Body></Envelope>",r,a,o)},p.ExecDelete=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(s)+"</Header><Body /></Envelope>";p.PerformAjax(t,r,a,o)},p.ExecGet=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body /></Envelope>",s,r,a)},p.ExecMethod=function(e,s,r,a,o,t,n){var l="";for(var d in r)if(null!=r[d])if(Array.isArray(r[d]))for(var c in r[d])l+="<r:"+d+">"+r[d][c]+"</r:"+d+">";else l+="<r:"+d+">"+r[d]+"</r:"+d+">";p.ExecMethodXml(e,s,l,a,o,t,n)},p.ExecMethodXml=function(e,s,r,a,o,t,n){p.PerformAjax(e+"/"+s+"</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(n)+"</Header><Body><r:"+s+'_INPUT xmlns:r="'+e+'">'+r+"</r:"+s+"_INPUT></Body></Envelope>",a,o,t)},p.ExecEnum=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Enumerate xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration" /></Body></Envelope>',s,r,a)},p.ExecPull=function(e,s,r,a,o){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Pull xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration"><EnumerationContext>'+s+"</EnumerationContext><MaxElements>999</MaxElements><MaxCharacters>99999</MaxCharacters></Pull></Body></Envelope>",r,a,o)},p.ParseWsman=function(s){try{s.childNodes||(s=function(e){{if(window.DOMParser)return(new DOMParser).parseFromString(e,"text/xml");var s=new ActiveXObject("Microsoft.XMLDOM");return s.async=!1,s.loadXML(e),s}}(s));var e,r={Header:{}},a=s.getElementsByTagName("Header")[0];if(!(a=a||s.getElementsByTagName("a:Header")[0]))return null;for(var o=0;o<a.childNodes.length;o++){var t=a.childNodes[o];r.Header[t.localName]=t.textContent}var n=s.getElementsByTagName("Body")[0];return(n=n||s.getElementsByTagName("a:Body")[0])?(0<n.childNodes.length&&((e=n.childNodes[0].localName).indexOf("_OUTPUT")==e.length-7&&(e=e.substring(0,e.length-7)),r.Header.Method=e,r.Body=function e(s){var r,a={};for(var o=0;o<s.childNodes.length;o++){var t=s.childNodes[o];"true"==(r=0==t.childElementCount?t.textContent:e(t))&&(r=!0),"false"==r&&(r=!1);var n=r;if(0<t.attributes.length){n={Value:r};for(var l=0;l<t.attributes.length;l++)n["@"+t.attributes[l].name]=t.attributes[l].value}a[t.localName]instanceof Array?a[t.localName].push(n):null==a[t.localName]?a[t.localName]=n:a[t.localName]=[a[t.localName],n]}return a}(n.childNodes[0])),r):null}catch(e){return console.log("Unable to parse XML: "+s),null}},p}
\ No newline at end of file
translate/translate.js
+1
@@ -33,6 +33,7 @@ var meshCentralSourceFiles = [
33 "../views/message.handlebars",
34 "../views/messenger.handlebars",
35 "../views/player.handlebars",
36 + "../views/desktop.handlebars",
37 "../views/mstsc.handlebars",
38 "../emails/account-check.html",
39 "../emails/account-invite.html",
translate/translate.json
+199 -90
@@ -481,7 +481,8 @@
481 "ru": ", Soft-KVM",
482 "zh-chs": ",軟KVM",
483 "xloc": [
484 - "default.handlebars->27->769"
484 + "default.handlebars->27->769",
485 + "desktop.handlebars->3->12"
486 ]
487 },
488 {
@@ -503,6 +504,7 @@
504 "default.handlebars->27->776",
505 "default.handlebars->27->809",
506 "default.handlebars->27->821",
507 + "desktop.handlebars->3->19",
508 "xterm.handlebars->9->6"
509 ]
510 },
@@ -583,7 +585,8 @@
585 "en": ", {0} watching",
586 "nl": ", {0} kijken",
587 "xloc": [
586 - "default.handlebars->27->770"
588 + "default.handlebars->27->770",
589 + "desktop.handlebars->3->13"
590 ]
591 },
592 {
@@ -717,7 +720,8 @@
720 "en": "1 connection",
721 "nl": "1 verbinding",
722 "xloc": [
720 - "default.handlebars->27->772"
723 + "default.handlebars->27->772",
724 + "desktop.handlebars->3->15"
725 ]
726 },
727 {
@@ -997,7 +1001,8 @@
1001 "zh-chs": "100%",
1002 "xloc": [
1003 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->1",
1000 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->1"
1004 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->1",
1005 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->1"
1006 ]
1007 },
1008 {
@@ -1049,7 +1054,8 @@
1054 "zh-chs": "12.5%",
1055 "xloc": [
1056 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->15",
1052 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->15"
1057 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->15",
1058 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->15"
1059 ]
1060 },
1061 {
@@ -1139,7 +1145,8 @@
1145 "zh-chs": "25%",
1146 "xloc": [
1147 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->13",
1142 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->13"
1148 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->13",
1149 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->13"
1150 ]
1151 },
1152 {
@@ -1285,7 +1292,8 @@
1292 "zh-chs": "37.5%",
1293 "xloc": [
1294 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->11",
1288 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->11"
1295 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->11",
1296 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->11"
1297 ]
1298 },
1299 {
@@ -1409,7 +1417,8 @@
1417 "zh-chs": "50%",
1418 "xloc": [
1419 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->9",
1412 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->9"
1420 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->9",
1421 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->9"
1422 ]
1423 },
1424 {
@@ -1463,7 +1472,8 @@
1472 "zh-chs": "62.5%",
1473 "xloc": [
1474 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->7",
1466 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->7"
1475 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->7",
1476 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->7"
1477 ]
1478 },
1479 {
@@ -1572,7 +1582,8 @@
1582 "zh-chs": "75%",
1583 "xloc": [
1584 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->5",
1575 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->5"
1585 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->5",
1586 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->5"
1587 ]
1588 },
1589 {
@@ -1625,7 +1636,8 @@
1636 "zh-chs": "87.5%",
1637 "xloc": [
1638 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->3",
1628 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->3"
1639 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->3",
1640 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->3"
1641 ]
1642 },
1643 {
@@ -3096,7 +3108,8 @@
3108 "zh-chs": "代理遠程桌面",
3109 "xloc": [
3110 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->1",
3099 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->1"
3111 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->1",
3112 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->1"
3113 ]
3114 },
3115 {
@@ -3371,7 +3384,8 @@
3384 "zh-chs": "Alt-F4",
3385 "xloc": [
3386 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->19",
3374 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->17"
3387 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->17",
3388 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->17"
3389 ]
3390 },
3391 {
@@ -3389,7 +3403,8 @@
3403 "zh-chs": "Alt-Tab",
3404 "xloc": [
3405 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->23",
3392 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->21"
3406 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->21",
3407 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->21"
3408 ]
3409 },
3410 {
@@ -4279,7 +4294,8 @@
4294 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->0->1->3",
4295 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3",
4296 "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3",
4282 - "default.handlebars->container->column_l->p13->p13toolbar->1->0->1->3"
4297 + "default.handlebars->container->column_l->p13->p13toolbar->1->0->1->3",
4298 + "desktop.handlebars->p11->deskarea0->deskarea1->3"
4299 ]
4300 },
4301 {
@@ -4977,6 +4993,7 @@
4993 "default-mobile.handlebars->dialog->idx_dlgButtonBar",
4994 "default.handlebars->27->1226",
4995 "default.handlebars->container->dialog->idx_dlgButtonBar",
4996 + "desktop.handlebars->p11->dialog->idx_dlgButtonBar",
4997 "login-mobile.handlebars->dialog->idx_dlgButtonBar",
4998 "login.handlebars->dialog->idx_dlgButtonBar",
4999 "player.handlebars->p11->dialog->idx_dlgButtonBar",
@@ -5902,7 +5919,8 @@
5919 "ru": "Буфер обмена",
5920 "zh-chs": "剪貼板",
5921 "xloc": [
5905 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3"
5922 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3",
5923 + "desktop.handlebars->p11->deskarea0->deskarea4->3"
5924 ]
5925 },
5926 {
@@ -5922,7 +5940,8 @@
5940 "default-mobile.handlebars->9->57",
5941 "default.handlebars->27->137",
5942 "default.handlebars->27->145",
5925 - "default.handlebars->27->798"
5943 + "default.handlebars->27->798",
5944 + "desktop.handlebars->3->36"
5945 ]
5946 },
5947 {
@@ -6420,6 +6439,7 @@
6439 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->connectbutton1span",
6440 "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->connectbutton2span",
6441 "default.handlebars->container->column_l->p13->p13toolbar->1->0->1->3",
6442 + "desktop.handlebars->p11->deskarea0->deskarea1->3->connectbutton1span",
6443 "mstsc.handlebars->main->1->3->1->8->1->0",
6444 "xterm.handlebars->p11->deskarea0->deskarea1->3"
6445 ]
@@ -6492,7 +6512,8 @@
6512 "zh-chs": "使用Intel AMT硬件KVM連接",
6513 "xloc": [
6514 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->connectbutton1hspan",
6495 - "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->connectbutton2hspan"
6515 + "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->connectbutton2hspan",
6516 + "desktop.handlebars->p11->deskarea0->deskarea1->3->connectbutton1hspan"
6517 ]
6518 },
6519 {
@@ -6511,6 +6532,7 @@
6532 "xloc": [
6533 "default-mobile.handlebars->9->4",
6534 "default.handlebars->27->11",
6535 + "desktop.handlebars->3->4",
6536 "xterm.handlebars->9->4"
6537 ]
6538 },
@@ -6605,6 +6627,7 @@
6627 "default.handlebars->27->251",
6628 "default.handlebars->27->860",
6629 "default.handlebars->27->9",
6630 + "desktop.handlebars->3->2",
6631 "xterm.handlebars->9->2"
6632 ]
6633 },
@@ -7363,7 +7386,8 @@
7386 "zh-chs": "Ctrl + Alt + Del",
7387 "xloc": [
7388 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->1",
7366 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->1"
7389 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->1",
7390 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->1"
7391 ]
7392 },
7393 {
@@ -7381,7 +7405,8 @@
7405 "zh-chs": "Ctrl-W",
7406 "xloc": [
7407 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->21",
7384 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->19"
7408 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->19",
7409 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->19"
7410 ]
7411 },
7412 {
@@ -7486,7 +7511,8 @@
7511 "ru": "DataChannel",
7512 "zh-chs": "數據通道",
7513 "xloc": [
7489 - "default.handlebars->27->768"
7514 + "default.handlebars->27->768",
7515 + "desktop.handlebars->3->11"
7516 ]
7517 },
7518 {
@@ -7594,6 +7620,7 @@
7620 "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3",
7621 "default.handlebars->container->dialog->idx_dlgButtonBar->5",
7622 "default.handlebars->filesContextMenu->5",
7623 + "desktop.handlebars->p11->dialog->idx_dlgButtonBar->5",
7624 "player.handlebars->p11->dialog->idx_dlgButtonBar->5",
7625 "xterm.handlebars->p11->dialog->idx_dlgButtonBar->5"
7626 ]
@@ -7920,7 +7947,8 @@
7947 "ko": "거부",
7948 "zh-chs": "被拒绝",
7949 "xloc": [
7923 - "default.handlebars->27->764"
7950 + "default.handlebars->27->764",
7951 + "desktop.handlebars->3->7"
7952 ]
7953 },
7954 {
@@ -8054,7 +8082,8 @@
8082 "default.handlebars->27->502",
8083 "default.handlebars->27->804",
8084 "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevDesktop",
8057 - "default.handlebars->contextMenu->cxdesktop"
8085 + "default.handlebars->contextMenu->cxdesktop",
8086 + "desktop.handlebars->3->41"
8087 ]
8088 },
8089 {
@@ -8142,7 +8171,8 @@
8171 "nl": "Desktop sessie wachttijd",
8172 "zh-chs": "桌面会话延迟",
8173 "xloc": [
8145 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1"
8174 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1",
8175 + "desktop.handlebars->p11->deskarea0->deskarea4->1"
8176 ]
8177 },
8178 {
@@ -8825,6 +8855,7 @@
8855 "default.handlebars->27->820",
8856 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->disconnectbutton1span",
8857 "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->disconnectbutton2span",
8858 + "desktop.handlebars->p11->deskarea0->deskarea1->3->disconnectbutton1span",
8859 "xterm.handlebars->p11->deskarea0->deskarea1->3"
8860 ]
8861 },
@@ -8870,6 +8901,8 @@
8901 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->deskstatus",
8902 "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->termstatus",
8903 "default.handlebars->container->column_l->p13->p13toolbar->1->0->1->3->p13Status",
8904 + "desktop.handlebars->3->1",
8905 + "desktop.handlebars->p11->deskarea0->deskarea1->3->deskstatus",
8906 "xterm.handlebars->9->1"
8907 ]
8908 },
@@ -8937,7 +8970,8 @@
8970 "ru": "Отображаемое имя",
8971 "zh-chs": "顯示名稱",
8972 "xloc": [
8940 - "default.handlebars->27->789"
8973 + "default.handlebars->27->789",
8974 + "desktop.handlebars->3->27"
8975 ]
8976 },
8977 {
@@ -10028,7 +10062,8 @@
10062 "ru": "Редактировать настройки удаленного рабочего стола",
10063 "zh-chs": "編輯遠程桌面設置",
10064 "xloc": [
10031 - "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1"
10065 + "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1",
10066 + "desktop.handlebars->p11->deskarea0->deskarea1->1"
10067 ]
10068 },
10069 {
@@ -10689,7 +10724,8 @@
10724 "ru": "Для удаленного набора введите текст, используя английскую раскладку и нажмите OK. Перед продолжением убедитесь, что курсор на удаленном компьютере установлен в правильное положение.",
10725 "zh-chs": "輸入文本,然後單擊“確定”以使用美式英語鍵盤遠程輸入文本。在繼續操作之前,請確保將遠程光標放置在正確的位置。",
10726 "xloc": [
10692 - "default.handlebars->27->783"
10727 + "default.handlebars->27->783",
10728 + "desktop.handlebars->3->21"
10729 ]
10730 },
10731 {
@@ -11033,7 +11069,8 @@
11069 "ko": "원격 터미널 세션을 시작하지 못했습니다 : {0} ({1})",
11070 "zh-chs": "无法启动远程终端会话{0}({1})",
11071 "xloc": [
11036 - "default.handlebars->27->765"
11072 + "default.handlebars->27->765",
11073 + "desktop.handlebars->3->8"
11074 ]
11075 },
11076 {
@@ -11068,7 +11105,8 @@
11105 "zh-chs": "快速",
11106 "xloc": [
11107 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->7->d7framelimiter->1",
11071 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->1"
11108 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->1",
11109 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->1"
11110 ]
11111 },
11112 {
@@ -11155,7 +11193,8 @@
11193 "ru": "Драйвер файловой системы",
11194 "zh-chs": "FileSystemDriver",
11195 "xloc": [
11158 - "default.handlebars->27->792"
11196 + "default.handlebars->27->792",
11197 + "desktop.handlebars->3->30"
11198 ]
11199 },
11200 {
@@ -11470,7 +11509,8 @@
11509 "ru": "Частота кадров",
11510 "zh-chs": "影格速率",
11511 "xloc": [
11473 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->1"
11512 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->1",
11513 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->7->1"
11514 ]
11515 },
11516 {
@@ -12353,7 +12393,8 @@
12393 "xloc": [
12394 "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea1->1->3",
12395 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->connectbutton1hspan",
12356 - "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->connectbutton2hspan"
12396 + "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->connectbutton2hspan",
12397 + "desktop.handlebars->p11->deskarea0->deskarea1->3->connectbutton1hspan"
12398 ]
12399 },
12400 {
@@ -13034,7 +13075,8 @@
13075 "ru": "Кодировка изображения",
13076 "zh-chs": "圖像編碼",
13077 "xloc": [
13037 - "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->1"
13078 + "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->1",
13079 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->3->1"
13080 ]
13081 },
13082 {
@@ -13137,7 +13179,8 @@
13179 "zh-chs": "輸入值",
13180 "xloc": [
13181 "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea4->1->3->13->DeskControlSpan",
13140 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->9->DeskControlSpan"
13182 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->9->DeskControlSpan",
13183 + "desktop.handlebars->p11->deskarea0->deskarea4->3->9->DeskControlSpan"
13184 ]
13185 },
13186 {
@@ -13525,6 +13568,7 @@
13568 "xloc": [
13569 "default-mobile.handlebars->9->5",
13570 "default.handlebars->27->12",
13571 + "desktop.handlebars->3->5",
13572 "xterm.handlebars->9->5"
13573 ]
13574 },
@@ -13901,7 +13945,8 @@
13945 "zh-chs": "英特爾®AMT硬件KVM",
13946 "xloc": [
13947 "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->1",
13904 - "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->1"
13948 + "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->1",
13949 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->1"
13950 ]
13951 },
13952 {
@@ -13953,7 +13998,8 @@
13998 "ru": "Интерактивный",
13999 "zh-chs": "互動",
14000 "xloc": [
13956 - "default.handlebars->27->793"
14001 + "default.handlebars->27->793",
14002 + "desktop.handlebars->3->31"
14003 ]
14004 },
14005 {
@@ -14531,7 +14577,8 @@
14577 "ru": "Драйвер ядра",
14578 "zh-chs": "內核驅動程序",
14579 "xloc": [
14534 - "default.handlebars->27->794"
14580 + "default.handlebars->27->794",
14581 + "desktop.handlebars->3->32"
14582 ]
14583 },
14584 {
@@ -15731,7 +15778,8 @@
15778 "ru": "Раскладка локальной клавиатуры",
15779 "zh-chs": "本地鍵盤圖",
15780 "xloc": [
15734 - "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->5"
15781 + "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->5",
15782 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->5"
15783 ]
15784 },
15785 {
@@ -16837,7 +16885,8 @@
16885 "xloc": [
16886 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->7->d7framelimiter->3",
16887 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSize->sizeselect->3",
16840 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->3"
16888 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->3",
16889 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->3"
16890 ]
16891 },
16892 {
@@ -17905,7 +17954,8 @@
17954 "default.handlebars->27->919",
17955 "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsArea->DeskToolsProcessTab->deskToolsHeader->3",
17956 "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsArea->DeskToolsServiceTab->deskToolsServiceHeader->3",
17908 - "default.handlebars->container->column_l->p42->p42tbl->1->0->2"
17957 + "default.handlebars->container->column_l->p42->p42tbl->1->0->2",
17958 + "desktop.handlebars->3->26"
17959 ]
17960 },
17961 {
@@ -19388,6 +19438,7 @@
19438 "default.handlebars->27->1227",
19439 "default.handlebars->27->567",
19440 "default.handlebars->container->dialog->idx_dlgButtonBar",
19441 + "desktop.handlebars->p11->dialog->idx_dlgButtonBar",
19442 "login-mobile.handlebars->dialog->idx_dlgButtonBar",
19443 "login.handlebars->dialog->idx_dlgButtonBar",
19444 "player.handlebars->p11->dialog->idx_dlgButtonBar",
@@ -19784,7 +19835,8 @@
19835 "ru": "Другие настройки",
19836 "zh-chs": "其他設定",
19837 "xloc": [
19787 - "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->1"
19838 + "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->1",
19839 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->5->1"
19840 ]
19841 },
19842 {
@@ -19818,7 +19870,8 @@
19870 "ru": "Собственный процесс",
19871 "zh-chs": "自己的過程",
19872 "xloc": [
19821 - "default.handlebars->27->795"
19873 + "default.handlebars->27->795",
19874 + "desktop.handlebars->3->33"
19875 ]
19876 },
19877 {
@@ -19837,7 +19890,8 @@
19890 "xloc": [
19891 "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea3->deskarea3x->DeskTools->5->1->0",
19892 "default.handlebars->27->791",
19840 - "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsArea->DeskToolsProcessTab->deskToolsHeader->1"
19893 + "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsArea->DeskToolsProcessTab->deskToolsHeader->1",
19894 + "desktop.handlebars->3->29"
19895 ]
19896 },
19897 {
@@ -20962,7 +21016,8 @@
21016 "zh-chs": "過程控制",
21017 "xloc": [
21018 "default-mobile.handlebars->9->289",
20965 - "default.handlebars->27->805"
21019 + "default.handlebars->27->805",
21020 + "desktop.handlebars->3->42"
21021 ]
21022 },
21023 {
@@ -21153,7 +21208,8 @@
21208 "zh-chs": "質量",
21209 "xloc": [
21210 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->3",
21156 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->3->1"
21211 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->3->1",
21212 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->3->1"
21213 ]
21214 },
21215 {
@@ -21188,7 +21244,8 @@
21244 "zh-chs": "RAW16,非常慢",
21245 "xloc": [
21246 "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->3->d7desktopmode->7",
21191 - "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->7"
21247 + "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->7",
21248 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->7"
21249 ]
21250 },
21251 {
@@ -21206,7 +21263,8 @@
21263 "zh-chs": "RAW8,慢",
21264 "xloc": [
21265 "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->3->d7desktopmode->5",
21209 - "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->5"
21266 + "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->5",
21267 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->5"
21268 ]
21269 },
21270 {
@@ -21289,7 +21347,8 @@
21347 "zh-chs": "RLE16,推薦",
21348 "xloc": [
21349 "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->3->d7desktopmode->3",
21292 - "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->3"
21350 + "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->3",
21351 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->3"
21352 ]
21353 },
21354 {
@@ -21307,7 +21366,8 @@
21366 "zh-chs": "RLE8,最快",
21367 "xloc": [
21368 "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->3->d7desktopmode->1",
21310 - "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->1"
21369 + "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->1",
21370 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->1"
21371 ]
21372 },
21373 {
@@ -21408,7 +21468,8 @@
21468 "en": "Received invalid network data",
21469 "nl": "Ongeldige netwerkgegevens ontvangen",
21470 "xloc": [
21411 - "default.handlebars->27->767"
21471 + "default.handlebars->27->767",
21472 + "desktop.handlebars->3->10"
21473 ]
21474 },
21475 {
@@ -21698,7 +21759,8 @@
21759 "ru": "Удаленный буфер обмена",
21760 "zh-chs": "遠程剪貼板",
21761 "xloc": [
21701 - "default.handlebars->27->786"
21762 + "default.handlebars->27->786",
21763 + "desktop.handlebars->3->24"
21764 ]
21765 },
21766 {
@@ -21747,7 +21809,8 @@
21809 "xloc": [
21810 "default-mobile.handlebars->9->285",
21811 "default.handlebars->27->253",
21750 - "default.handlebars->27->778"
21812 + "default.handlebars->27->778",
21813 + "desktop.handlebars->3->20"
21814 ]
21815 },
21816 {
@@ -21764,7 +21827,8 @@
21827 "ru": "Ввод с удаленной клавиатуры",
21828 "zh-chs": "遠程鍵盤輸入",
21829 "xloc": [
21767 - "default.handlebars->27->784"
21830 + "default.handlebars->27->784",
21831 + "desktop.handlebars->3->22"
21832 ]
21833 },
21834 {
@@ -21832,7 +21896,8 @@
21896 "ru": "Удаленный буфер обмена действителен в течении 60 секунд.",
21897 "zh-chs": "遠程剪貼板的有效期為60秒。",
21898 "xloc": [
21835 - "default.handlebars->27->785"
21899 + "default.handlebars->27->785",
21900 + "desktop.handlebars->3->23"
21901 ]
21902 },
21903 {
@@ -22438,6 +22503,7 @@
22503 "zh-chs": "重新開始",
22504 "xloc": [
22505 "default.handlebars->27->801",
22506 + "desktop.handlebars->3->39",
22507 "player.handlebars->p11->deskarea0->deskarea4->3"
22508 ]
22509 },
@@ -22648,7 +22714,8 @@
22714 "ru": "Повернуть влево",
22715 "zh-chs": "向左旋轉",
22716 "xloc": [
22651 - "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1"
22717 + "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1",
22718 + "desktop.handlebars->p11->deskarea0->deskarea1->1"
22719 ]
22720 },
22721 {
@@ -22665,7 +22732,8 @@
22732 "ru": "Повернуть вправо",
22733 "zh-chs": "右旋",
22734 "xloc": [
22668 - "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1"
22735 + "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1",
22736 + "desktop.handlebars->p11->deskarea0->deskarea1->1"
22737 ]
22738 },
22739 {
@@ -22926,7 +22994,8 @@
22994 "ru": "Сохранить снимок экрана удаленного рабочего стола",
22995 "zh-chs": "保存遠程桌面的屏幕截圖",
22996 "xloc": [
22929 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1"
22997 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1",
22998 + "desktop.handlebars->p11->deskarea0->deskarea4->1"
22999 ]
23000 },
23001 {
@@ -22982,7 +23051,8 @@
23051 "zh-chs": "縮放比例",
23052 "xloc": [
23053 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->3",
22985 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->1"
23054 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->1",
23055 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->1"
23056 ]
23057 },
23058 {
@@ -23437,6 +23507,7 @@
23507 "xloc": [
23508 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3",
23509 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->specialKeyDropDown",
23510 + "desktop.handlebars->p11->deskarea0->deskarea4->3",
23511 "messenger.handlebars->xbottom"
23512 ]
23513 },
@@ -24048,7 +24119,8 @@
24119 "ru": "Детали службы",
24120 "zh-chs": "服務詳情",
24121 "xloc": [
24051 - "default.handlebars->27->802"
24122 + "default.handlebars->27->802",
24123 + "desktop.handlebars->3->40"
24124 ]
24125 },
24126 {
@@ -24079,7 +24151,8 @@
24151 "en": "Session Information",
24152 "nl": "Sessie informatie",
24153 "xloc": [
24082 - "default.handlebars->27->775"
24154 + "default.handlebars->27->775",
24155 + "desktop.handlebars->3->18"
24156 ]
24157 },
24158 {
@@ -24097,7 +24170,8 @@
24170 "zh-chs": "上課時間",
24171 "xloc": [
24172 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1",
24100 - "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1"
24173 + "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1",
24174 + "desktop.handlebars->p11->deskarea0->deskarea4->1"
24175 ]
24176 },
24177 {
@@ -24181,7 +24255,8 @@
24255 "ru": "Настройки...",
24256 "zh-chs": "設定...",
24257 "xloc": [
24184 - "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1"
24258 + "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1",
24259 + "desktop.handlebars->p11->deskarea0->deskarea1->1"
24260 ]
24261 },
24262 {
@@ -24237,6 +24312,7 @@
24312 "default.handlebars->27->223",
24313 "default.handlebars->27->226",
24314 "default.handlebars->27->252",
24315 + "desktop.handlebars->3->3",
24316 "xterm.handlebars->9->3"
24317 ]
24318 },
@@ -24271,7 +24347,8 @@
24347 "ru": "Общий процесс",
24348 "zh-chs": "共享過程",
24349 "xloc": [
24274 - "default.handlebars->27->796"
24350 + "default.handlebars->27->796",
24351 + "desktop.handlebars->3->34"
24352 ]
24353 },
24354 {
@@ -24289,7 +24366,8 @@
24366 "zh-chs": "Shift + Win + M",
24367 "xloc": [
24368 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->15",
24292 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->13"
24369 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->13",
24370 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->13"
24371 ]
24372 },
24373 {
@@ -24334,7 +24412,8 @@
24412 "zh-chs": "顯示焦點工具",
24413 "xloc": [
24414 "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->5->1->1",
24337 - "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->1"
24415 + "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->1",
24416 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->1"
24417 ]
24418 },
24419 {
@@ -24370,7 +24449,8 @@
24449 "zh-chs": "顯示本地鼠標光標",
24450 "xloc": [
24451 "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->5->1->4",
24373 - "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->3"
24452 + "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->3",
24453 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->3"
24454 ]
24455 },
24456 {
@@ -24840,7 +24920,8 @@
24920 "zh-chs": "慢",
24921 "xloc": [
24922 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->7->d7framelimiter->5",
24843 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->5"
24923 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->5",
24924 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->5"
24925 ]
24926 },
24927 {
@@ -25462,7 +25543,8 @@
25543 "ru": "Старт",
25544 "zh-chs": "開始",
25545 "xloc": [
25465 - "default.handlebars->27->799"
25546 + "default.handlebars->27->799",
25547 + "desktop.handlebars->3->37"
25548 ]
25549 },
25550 {
@@ -25475,7 +25557,8 @@
25557 "xloc": [
25558 "default.handlebars->27->1813",
25559 "default.handlebars->27->1832",
25478 - "default.handlebars->27->771"
25560 + "default.handlebars->27->771",
25561 + "desktop.handlebars->3->14"
25562 ]
25563 },
25564 {
@@ -25493,7 +25576,8 @@
25576 "zh-chs": "州",
25577 "xloc": [
25578 "default.handlebars->27->790",
25496 - "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsArea->DeskToolsServiceTab->deskToolsServiceHeader->1"
25579 + "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsArea->DeskToolsServiceTab->deskToolsServiceHeader->1",
25580 + "desktop.handlebars->3->28"
25581 ]
25582 },
25583 {
@@ -25546,7 +25630,8 @@
25630 "ru": "Стоп",
25631 "zh-chs": "停止",
25632 "xloc": [
25549 - "default.handlebars->27->800"
25633 + "default.handlebars->27->800",
25634 + "desktop.handlebars->3->38"
25635 ]
25636 },
25637 {
@@ -25562,7 +25647,8 @@
25647 "ru": "Остановить процесс",
25648 "zh-chs": "停止程序",
25649 "xloc": [
25565 - "default.handlebars->27->787"
25650 + "default.handlebars->27->787",
25651 + "desktop.handlebars->3->25"
25652 ]
25653 },
25654 {
@@ -25580,7 +25666,8 @@
25666 "zh-chs": "停止進程#{0} \\“ {1} \\”?",
25667 "xloc": [
25668 "default-mobile.handlebars->9->290",
25583 - "default.handlebars->27->806"
25669 + "default.handlebars->27->806",
25670 + "desktop.handlebars->3->43"
25671 ]
25672 },
25673 {
@@ -26593,7 +26680,8 @@
26680 "en": "Timeout",
26681 "nl": "Time-out",
26682 "xloc": [
26596 - "default.handlebars->27->766"
26683 + "default.handlebars->27->766",
26684 + "desktop.handlebars->3->9"
26685 ]
26686 },
26687 {
@@ -26871,6 +26959,7 @@
26959 "zh-chs": "切換查看模式",
26960 "xloc": [
26961 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1",
26962 + "desktop.handlebars->p11->deskarea0->deskarea1->1",
26963 "player.handlebars->p11->deskarea0->deskarea1->1"
26964 ]
26965 },
@@ -26922,7 +27011,8 @@
27011 "ru": "Разрешить мышь и ввод с клавиатуры",
27012 "zh-chs": "切換鼠標和鍵盤輸入",
27013 "xloc": [
26925 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->9"
27014 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->9",
27015 + "desktop.handlebars->p11->deskarea0->deskarea4->3->9"
27016 ]
27017 },
27018 {
@@ -27245,7 +27335,9 @@
27335 "default.handlebars->27->1295",
27336 "default.handlebars->27->1298",
27337 "default.handlebars->27->797",
27248 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3"
27338 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3",
27339 + "desktop.handlebars->3->35",
27340 + "desktop.handlebars->p11->deskarea0->deskarea4->3"
27341 ]
27342 },
27343 {
@@ -28402,7 +28494,8 @@
28494 "en": "User \\\"{0}\\\"",
28495 "nl": "Gebuiker \\\"{0}\\\"",
28496 "xloc": [
28405 - "default.handlebars->27->774"
28497 + "default.handlebars->27->774",
28498 + "desktop.handlebars->3->17"
28499 ]
28500 },
28501 {
@@ -28773,7 +28866,8 @@
28866 "zh-chs": "非常慢",
28867 "xloc": [
28868 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->7->d7framelimiter->7",
28776 - "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->7"
28869 + "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->7",
28870 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->7"
28871 ]
28872 },
28873 {
@@ -28939,7 +29033,8 @@
29033 "ko": "사용자가 액세스 권한을 부여하기를 기다리는 중 ...",
29034 "zh-chs": "正在等待用户授予访问权限...",
29035 "xloc": [
28942 - "default.handlebars->27->763"
29036 + "default.handlebars->27->763",
29037 + "desktop.handlebars->3->6"
29038 ]
29039 },
29040 {
@@ -29247,7 +29342,8 @@
29342 "zh-chs": "贏得",
29343 "xloc": [
29344 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->5",
29250 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->3"
29345 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->3",
29346 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->3"
29347 ]
29348 },
29349 {
@@ -29265,7 +29361,8 @@
29361 "zh-chs": "勝負",
29362 "xloc": [
29363 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->7",
29268 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->5"
29364 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->5",
29365 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->5"
29366 ]
29367 },
29368 {
@@ -29283,7 +29380,8 @@
29380 "zh-chs": "贏+ L",
29381 "xloc": [
29382 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->11",
29286 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->9"
29383 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->9",
29384 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->9"
29385 ]
29386 },
29387 {
@@ -29300,7 +29398,8 @@
29398 "ru": "Win+Влево",
29399 "zh-chs": "贏+左",
29400 "xloc": [
29303 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->23"
29401 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->23",
29402 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->23"
29403 ]
29404 },
29405 {
@@ -29318,7 +29417,8 @@
29417 "zh-chs": "Win + M",
29418 "xloc": [
29419 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->13",
29321 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->11"
29420 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->11",
29421 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->11"
29422 ]
29423 },
29424 {
@@ -29336,7 +29436,8 @@
29436 "zh-chs": "Win + R",
29437 "xloc": [
29438 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->17",
29339 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->15"
29439 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->15",
29440 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->15"
29441 ]
29442 },
29443 {
@@ -29353,7 +29454,8 @@
29454 "ru": "Win+Вправо",
29455 "zh-chs": "贏+右",
29456 "xloc": [
29356 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->25"
29457 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->25",
29458 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->25"
29459 ]
29460 },
29461 {
@@ -29371,7 +29473,8 @@
29473 "zh-chs": "勝+勝",
29474 "xloc": [
29475 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->9",
29374 - "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->7"
29476 + "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->7",
29477 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->7"
29478 ]
29479 },
29480 {
@@ -31356,7 +31459,8 @@
31459 "en": "{0} connections",
31460 "nl": "{0} verbindingen",
31461 "xloc": [
31359 - "default.handlebars->27->773"
31462 + "default.handlebars->27->773",
31463 + "desktop.handlebars->3->16"
31464 ]
31465 },
31466 {
@@ -31837,7 +31941,8 @@
31941 "ru": "↺",
31942 "ko": "↺",
31943 "xloc": [
31840 - "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1->5"
31944 + "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1->5",
31945 + "desktop.handlebars->p11->deskarea0->deskarea1->1->5"
31946 ]
31947 },
31948 {
@@ -31852,7 +31957,8 @@
31957 "ru": "↻",
31958 "ko": "↻",
31959 "xloc": [
31855 - "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1->7"
31960 + "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1->7",
31961 + "desktop.handlebars->p11->deskarea0->deskarea1->1->7"
31962 ]
31963 },
31964 {
@@ -31868,6 +31974,7 @@
31974 "ko": "⇲",
31975 "xloc": [
31976 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1->3",
31977 + "desktop.handlebars->p11->deskarea0->deskarea1->1->3",
31978 "player.handlebars->p11->deskarea0->deskarea1->1->1"
31979 ]
31980 },
@@ -31951,6 +32058,8 @@
32058 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->idx_deskFullBtn2",
32059 "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->idx_termFullBtn2",
32060 "default.handlebars->container->dialog->dialogHeader->id_dialogclose",
32061 + "desktop.handlebars->p11->deskarea0->deskarea1->3->idx_deskFullBtn2",
32062 + "desktop.handlebars->p11->dialog->dialogHeader->id_dialogclose",
32063 "player.handlebars->p11->dialog->dialogHeader->id_dialogclose",
32064 "xterm.handlebars->p11->dialog->dialogHeader->id_dialogclose"
32065 ]
views/desktop.handlebars new
+1110
@@ -0,0 +1,1110 @@
1 +<!DOCTYPE html>
2 +<html lang="en" dir="ltr" xmlns="http://www.w3.org/1999/xhtml">
3 +<head>
4 + <meta http-equiv="X-UA-Compatible" content="IE=edge" />
5 + <meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
6 + <meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0" />
7 + <meta name="apple-mobile-web-app-capable" content="yes" />
8 + <meta name="format-detection" content="telephone=no" />
9 + <link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS" />
10 + <script type="text/javascript" src="scripts/common-0.0.1{{min}}.js"></script>
11 + <script type="text/javascript" src="scripts/amt-redir-ws-0.1.0{{{min}}}.js"></script>
12 + <script type="text/javascript" src="scripts/amt-wsman-ws-0.2.0{{{min}}}.js"></script>
13 + <script type="text/javascript" src="scripts/agent-redir-ws-0.1.1{{{min}}}.js"></script>
14 + <script type="text/javascript" src="scripts/agent-redir-rtc-0.1.0{{{min}}}.js"></script>
15 + <script type="text/javascript" src="scripts/agent-desktop-0.0.2{{min}}.js"></script>
16 + <script type="text/javascript" src="scripts/amt-desktop-0.0.2{{min}}.js"></script>
17 + <script type="text/javascript" src="scripts/amt-terminal-0.0.2{{min}}.js"></script>
18 + <script type="text/javascript" src="scripts/zlib{{min}}.js"></script>
19 + <script type="text/javascript" src="scripts/zlib-inflate{{min}}.js"></script>
20 + <script type="text/javascript" src="scripts/zlib-adler32{{min}}.js"></script>
21 + <script type="text/javascript" src="scripts/zlib-crc32{{min}}.js"></script>
22 +</head>
23 +<body style="overflow:hidden;background-color:black">
24 + <div id=p11 class="noselect" style="overflow:hidden">
25 + <div id=deskarea0>
26 + <div id=deskarea1 class="areaHead">
27 + <div class="toright2">
28 + <span id="p11power"></span>&nbsp;
29 + <div class='deskareaicon' title="Toggle View Mode" onclick="toggleAspectRatio(1)">&#8690;</div>
30 + <div class='deskareaicon' title="Rotate Left" onclick="drotate(-1)">&olarr;</div>
31 + <div class='deskareaicon' title="Rotate Right" onclick="drotate(1)">&orarr;</div>
32 + <input id="deskActionsSettings" type="button" value="Settings..." title="Edit remote desktop settings" onkeypress="return false" onkeydown="return false" onclick="showDesktopSettings()" class="mR" />
33 + <div id="desktopCustomUiButtons" style="float:left"></div>
34 + </div>
35 + <div>
36 + <div id="idx_deskFullBtn2" onclick=deskToggleFull(event)>&nbsp;&#x2716;</div>
37 + <input type="button" id="autoconnectbutton1" value="AutoConnect" onclick=autoConnectDesktop(event) onkeypress="return false" onkeydown="return false" style="display:none" />
38 + <span id=connectbutton1span><input type=button id=connectbutton1 cmenu="deskConnectButton" value="Connect" onclick=connectDesktop(event,3) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span>
39 + <span id=connectbutton1hspan>&nbsp;<input type=button id=connectbutton1h value="HW Connect" title="Connect using Intel AMT hardware KVM" onclick=connectDesktop(event,2) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span>
40 + <span id=disconnectbutton1span>&nbsp;<input type=button id=disconnectbutton1 value="Disconnect" onclick=connectDesktop(event,0) onkeypress="return false" onkeydown="return false" /></span>
41 + &nbsp;<span id="deskstatus">Disconnected</span><span id="deskmetadata"></span>
42 + </div>
43 + </div>
44 + <div id=deskarea3x style="max-height:calc(100vh - 54px);height:calc(100vh - 54px);">
45 + <div id=DeskFocus oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></div>
46 + <div id=DeskParent>
47 + <canvas id=Desk width=640 height=480 oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event) onmousewheel=dmousewheel(event)></canvas>
48 + </div>
49 + <div id=p11DeskConsoleMsg style="display:none;cursor:pointer;position:absolute;left:30px;top:17px;color:yellow;background-color:rgba(0,0,0,0.6);padding:10px;border-radius:5px" onclick=clearConsoleMsg()></div>
50 + </div>
51 + <div id=deskarea4 class="areaFoot">
52 + <div class="toright2">
53 + <span id="DeskLatency" title="Desktop Session Latency"></span>
54 + <span id="DeskTimer" title="Session time"></span>&nbsp;
55 + <select id=termdisplays style="display:none" onchange=deskSetDisplay(event) onkeypress="return false" onkeydown="return false"></select>&nbsp;
56 + <span id=DeskSaveImageButton title="Save a screenshot of the remote desktop"><img src='images/icon-camera.png' onclick=deskSaveImage() height=16 width=16 style=padding-top:2px /></span>
57 + </div>
58 + <div>
59 + <select id="deskkeys">
60 + <option value=10>Ctrl+Alt+Del</option>
61 + <option value=5>Win</option>
62 + <option value=0>Win+Down</option>
63 + <option value=1>Win+Up</option>
64 + <option value=2>Win+L</option>
65 + <option value=3>Win+M</option>
66 + <option value=4>Shift+Win+M</option>
67 + <option value=6>Win+R</option>
68 + <option value=7>Alt-F4</option>
69 + <option value=8>Ctrl-W</option>
70 + <option value=9>Alt-Tab</option>
71 + <option value=11>Win+Left</option>
72 + <option value=12>Win+Right</option>
73 + </select>
74 + <input id="DeskWD" type=button value="Send" onkeypress="return false" onkeydown="return false" onclick="deskSendKeys()" />
75 + <input id="DeskClip" style="" type="button" value="Clipboard" onkeypress="return false" onkeydown="return false" onclick="showDeskClip()" />
76 + <input id="DeskType" style="" type="button" value="Type" onkeypress="return false" onkeydown="return false" onclick="showDeskType()" />
77 + <label><span id="DeskControlSpan" title="Toggle mouse and keyboard input"><input id="DeskControl" type="checkbox" onkeypress="return false" onkeydown="return false" onclick="toggleKvmControl()" />Input</span></label>&nbsp;
78 + </div>
79 + </div>
80 + </div>
81 + <div id=dialog class="noselect" style="display:none">
82 + <div id=dialogHeader>
83 + <div tabindex=0 id=id_dialogclose onclick=setDialogMode() onkeypress="if (event.key == 'Enter') setDialogMode()">&#x2716;</div>
84 + <div id=id_dialogtitle></div>
85 + </div>
86 + <div id=dialogBody>
87 + <div id=dialog1>
88 + <div id=id_dialogMessage style=""></div>
89 + </div>
90 + <div id=dialog2 style="">
91 + <div id=id_dialogOptions></div>
92 + </div>
93 + <div id=dialog7 style="">
94 + <div id="d7meshkvm">
95 + <h4>Agent Remote Desktop</h4>
96 + <div>
97 + <div>Quality</div>
98 + <select id="d7bitmapquality" dir="rtl"></select>
99 + </div>
100 + <div>
101 + <div>Scaling</div>
102 + <select id="d7bitmapscaling" style="" dir="rtl">
103 + <option selected=selected value=1024>100%</option>
104 + <option value=896>87.5%</option>
105 + <option value=768>75%</option>
106 + <option value=640>62.5%</option>
107 + <option value=512>50%</option>
108 + <option value=384>37.5%</option>
109 + <option value=256>25%</option>
110 + <option value=128>12.5%</option>
111 + </select>
112 + </div>
113 + <div>
114 + <div>Frame rate</div>
115 + <select id="d7framelimiter" dir="rtl">
116 + <option selected=selected value=50>Fast</option>
117 + <option value=100>Medium</option>
118 + <option value=400>Slow</option>
119 + <option value=1000>Very slow</option>
120 + </select>
121 + </div>
122 + </div>
123 + <div id="d7amtkvm">
124 + <h4>Intel&reg; AMT Hardware KVM</h4>
125 + <div>
126 + <div>Image Encoding</div>
127 + <select id="d7desktopmode">
128 + <option value="1">RLE8, Fastest</option>
129 + <option value="2">RLE16, Recommended</option>
130 + <option value="3">RAW8, Slow</option>
131 + <option value="4">RAW16, Very Slow</option>
132 + </select>
133 + </div>
134 + <div>
135 + <div>Other Settings</div>
136 + <div id="d7otherset" style="display:block">
137 + <label style="display:block"><input type="checkbox" id="d7showfocus" />Show Focus Tool</label>
138 + <label style="display:block"><input type="checkbox" id="d7showcursor" />Show Local Mouse Cursor</label>
139 + <label style="display:block"><input type="checkbox" id="d7localKeyMap" />Local Keyboard Map</label>
140 + </div>
141 + </div>
142 + </div>
143 + </div>
144 + </div>
145 + <div id="idx_dlgButtonBar">
146 + <input id="idx_dlgCancelButton" type="button" value="Cancel" style="" onclick="dialogclose(0)">
147 + <input id="idx_dlgOkButton" type="button" value="OK" style="" onclick="dialogclose(1)">
148 + <div><input id="idx_dlgDeleteButton" type="button" value="Delete" style="display:none" onclick="dialogclose(2)"></div>
149 + </div>
150 + </div>
151 + </div>
152 + <script>
153 + var sessionActivity = null;
154 + var desktop = null;
155 + var agentPresent = true;
156 + var intelAmtPresent = false;
157 + var deskAspectRatio = 0;
158 + var desktopsettings = { encoding: 2, showfocus: false, showmouse: true, showcad: true, quality: 40, scaling: 1024, framerate: 50, localkeymap: false };
159 + var p11DeskConsoleMsgTimer = null;
160 + var serverPublicNamePort = '{{{serverDnsName}}}:{{{serverPublicPort}}}';
161 + var domain = '{{{domain}}}';
162 + var domainUrl = '{{{domainurl}}}';
163 + var authCookie = '{{{authCookie}}}';
164 + var authRelayCookie = '{{{authRelayCookie}}}';
165 + var desktopNodeId = '{nodeid}';
166 + var urlargs = parseUriArgs();
167 + var debugmode = urlargs.debug;
168 + var attemptWebRTC = false;
169 + var StatusStrs = ["Disconnected", "Connecting...", "Setup...", "Connected", "Intel&reg; AMT Connected"];
170 +
171 + function start() {
172 + window.onresize = deskAdjust;
173 + setupDesktop();
174 + }
175 +
176 + function clearConsoleMsg() { QH('p11DeskConsoleMsg', ''); }
177 +
178 + // Toggle the web page to full screen
179 + function toggleAspectRatio(toggle) {
180 + if (toggle === 1) { deskAspectRatio = ((deskAspectRatio + 1) % 3); }
181 + deskAdjust();
182 + }
183 +
184 + function deskAdjust() {
185 + var parentH = Q('DeskParent').clientHeight, parentW = Q('DeskParent').clientWidth;
186 + var deskH = Q('Desk').height, deskW = Q('Desk').width;
187 +
188 + if (deskAspectRatio == 2) {
189 + // Scale mode
190 + QS('Desk')['margin-top'] = null;
191 + QS('Desk').height = '100%';
192 + QS('Desk').width = '100%';
193 + QS('DeskParent').overflow = 'hidden';
194 + } else if (deskAspectRatio == 1) {
195 + // Zoomed mode
196 + QS('Desk')['margin-top'] = '0px';
197 + //QS('Desk')['margin-left'] = '0px';
198 + QS('Desk').height = deskH + 'px';
199 + QS('Desk').width = deskW + 'px';
200 + QS('DeskParent').overflow = 'scroll';
201 + } else {
202 + // Fixed aspect ratio
203 + if ((parentH / parentW) > (deskH / deskW)) {
204 + var hNew = ((deskH * parentW) / deskW) + 'px';
205 + //if (webPageFullScreen || fullscreen) {
206 + //QS('deskarea3x').height = null;
207 + //} else {
208 + // QS('deskarea3x').height = hNew;
209 + //QS('deskarea3x').height = null;
210 + //}
211 + QS('Desk').height = hNew;
212 + QS('Desk').width = '100%';
213 + } else {
214 + var wNew = ((deskW * parentH) / deskH) + 'px';
215 + //if (webPageFullScreen || fullscreen) {
216 + //QS('Desk').height = null;
217 + //} else {
218 + QS('Desk').height = '100%';
219 + //}
220 + QS('Desk').width = wNew;
221 + }
222 + QS('Desk')['margin-top'] = null;
223 + QS('DeskParent').overflow = 'hidden';
224 + }
225 + }
226 +
227 + //
228 + // DESKTOP
229 + //
230 +
231 + function setupDesktop() {
232 + // Setup the remote desktop
233 + if (desktop != null) { desktop.Stop(); desktop = null; }
234 +
235 + // If the device desktop is already connected in multi-desktop, use that.
236 + if (desktop == null) {
237 + // Device is not already connected, just setup a blank canvas
238 + QH('DeskParent', '<canvas id=Desk oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></canvas>');
239 +
240 + // Setup the mouse wheel
241 + Q('Desk').addEventListener('DOMMouseScroll', function (e) { return dmousewheel(e); });
242 + Q('Desk').addEventListener('mousewheel', function (e) { return dmousewheel(e); });
243 + }
244 + updateDesktopButtons();
245 + deskAdjust();
246 + updateMetadata(desktop, 'deskmetadata');
247 + }
248 +
249 + // Show and enable the right buttons
250 + function updateDesktopButtons() {
251 + var deskState = 0;
252 + if (desktop != null) { deskState = desktop.State; }
253 +
254 + // Show the right buttons
255 + QV('disconnectbutton1span', (deskState != 0));
256 + QV('connectbutton1span', (deskState == 0) && (agentPresent));
257 + QV('connectbutton1hspan', (deskState == 0) && (intelAmtPresent));
258 +
259 + // Show the right settings
260 + QV('d7meshkvm', agentPresent && ((deskState == 0) || (desktop.contype == 1)));
261 + QV('d7amtkvm', intelAmtPresent && ((deskState == 0) || (desktop.contype == 2)));
262 +
263 + // Enable buttons
264 + var inputAllowed = true; // TODO
265 + QE('connectbutton1', agentPresent);
266 + QE('connectbutton1h', intelAmtPresent);
267 + QV('DeskClip', agentPresent && ((desktop == null) || (desktop.contype != 2))); // Clipboard not supported on macOS
268 + QE('DeskClip', deskState == 3);
269 + QE('DeskType', deskState == 3);
270 + QV('DeskWD', inputAllowed);
271 + QE('DeskWD', deskState == 3);
272 + QV('deskkeys', inputAllowed);
273 + QE('deskkeys', deskState == 3);
274 +
275 + // Display this only if we have Chat & Notify permissions
276 + QV('DeskSaveImageButton', (deskState == 3) && (Q('Desk')['toBlob'] != null));
277 + QV('DeskControlSpan', inputAllowed)
278 + QV('deskActionsBtn', (browserfullscreen == false));
279 + QV('deskActionsSettings', (browserfullscreen == false));
280 + Q('DeskControl').checked = true;
281 + QS('DeskControlSpan').color = Q('DeskControl').checked ? null : 'red';
282 + }
283 +
284 + // Debug
285 + var autoConnectDesktopTimer = null;
286 + function autoConnectDesktop(e) { if (autoConnectDesktopTimer == null) { autoConnectDesktopTimer = setInterval(function () { connectDesktop(null, 1) }, 1000); } else { clearInterval(autoConnectDesktopTimer); autoConnectDesktopTimer = null; } }
287 +
288 + // Used to translate incoming agent console messages
289 + var agentConsoleMessages = ['', "Waiting for user to grant access...", "Denied", "Failed to start remote terminal session, {0} ({1})", "Timeout", "Received invalid network data"];
290 + function formatAgentConsoleMessage(msg, msgid, msgargs) {
291 + var r;
292 + if (msgargs == null) { msgargs = []; }
293 + while (msgargs.length < 3) { msgargs.push(''); } // We need to call the format function in a way that works with older browsers and minifier, can't use apply() or ...
294 + if (msgid && (msgid < agentConsoleMessages.length)) { r = EscapeHtml(format(agentConsoleMessages[msgid], (msgargs[0]), (msgargs[1]), (msgargs[2]))); } else { r = EscapeHtml(msg); }
295 + return r.split('\n').join('<br />') + '<br /><br />';
296 + }
297 +
298 + function connectDesktop(e, contype, tsid, consent) {
299 + if (xxdialogMode) return;
300 + if ((e != null) && (e.shiftKey != false) && (contype == 3)) { contype = 1; } // If the shift key is not pressed, don't try to ask for session list.
301 + QV('p11DeskSessionSelector', false);
302 + p11clearConsoleMsg();
303 + if (desktop == null) {
304 + if (contype == 2) {
305 + // Setup the Intel AMT remote desktop
306 + //if ((desktopNode.intelamt.user == null) || (desktopNode.intelamt.user == '')) { editDeviceAmtSettings(desktopNode._id, connectDesktop, 2); return; }
307 + desktop = CreateAmtRedirect(CreateAmtRemoteDesktop('Desk'), authCookie);
308 + desktop.debugmode = debugmode;
309 + desktop.onStateChanged = onDesktopStateChange;
310 + desktop.m.bpp = (desktopsettings.encoding == 1 || desktopsettings.encoding == 3) ? 1 : 2;
311 + desktop.m.useZRLE = (desktopsettings.encoding < 3);
312 + desktop.m.localKeyMap = desktopsettings.localkeymap;
313 + desktop.m.showmouse = desktopsettings.showmouse;
314 + desktop.m.onScreenSizeChange = deskAdjust;
315 + desktop.m.onKvmData = function (x) {
316 + //console.log('onKvmData (' + x.length + '): ' + x);
317 + // Send the presense probe only once if needed.
318 + if (x.length == 0) { if (!desktop.m._sentPresence) { desktop.m._sentPresence = true; desktop.m.sendKvmData(JSON.stringify({ action: 'present', ver: 1 })); } return; }
319 + var data = null;
320 + try { data = JSON.parse(x); } catch (e) { }
321 + if ((data != null) && (data.action != null)) {
322 + if (data.action == 'restart') {
323 + // Clear WebRTC channel
324 + webRtcDesktopReset();
325 + desktop.m.sendKvmData(JSON.stringify({ action: 'present', ver: 1 }));
326 + } else if ((data.action == 'present') && (webRtcDesktop == null)) {
327 + // Setup WebRTC channel
328 + webRtcDesktop = { platform: data.platform };
329 + var configuration = null; //{ "iceServers": [ { 'urls': 'stun:stun.services.mozilla.com' }, { 'urls': 'stun:stun.l.google.com:19302' } ] };
330 + if (typeof RTCPeerConnection !== 'undefined') { webRtcDesktop.webrtc = new RTCPeerConnection(configuration); }
331 + else if (typeof webkitRTCPeerConnection !== 'undefined') { webRtcDesktop.webrtc = new webkitRTCPeerConnection(configuration); }
332 +
333 + webRtcDesktop.webchannel = webRtcDesktop.webrtc.createDataChannel("DataChannel", {}); // { ordered: false, maxRetransmits: 2 }
334 + webRtcDesktop.webchannel.onopen = function () {
335 + // Switch to software KVM
336 + //if (urlvars && urlvars['kvmdatatrace']) { console.log('WebRTC Data Channel Open'); }
337 + console.log('WebRTC Data Channel Open');
338 + Q('deskstatus').textContent = StatusStrs[desktop.State] + ", Soft-KVM";
339 + desktop.m.hold(true);
340 + webRtcDesktop.webRtcActive = true;
341 + webRtcDesktop.softdesktop = CreateKvmDataChannel(webRtcDesktop.webchannel, CreateAgentRemoteDesktop('Desk', Q('id_mainarea')), desktop.m);
342 + webRtcDesktop.softdesktop.m.setRotation(desktop.m.rotation);
343 + webRtcDesktop.softdesktop.m.onScreenSizeChange = deskAdjust;
344 + if (desktopsettings.quality) { webRtcDesktop.softdesktop.m.CompressionLevel = desktopsettings.quality; } // Number from 1 to 100. 50 or less is best.
345 + if (desktopsettings.scaling) { webRtcDesktop.softdesktop.m.ScalingLevel = desktopsettings.scaling; }
346 + webRtcDesktop.softdesktop.Start();
347 +
348 + // Check if we can get remote file access
349 + // ###BEGIN###{DesktopInbandFiles}
350 + /*
351 + QV('go24', true); // Files
352 + downloadFile = null;
353 + p24files = webRtcDesktop.softdesktop;
354 + p24targetpath = '';
355 + webRtcDesktop.softdesktop.onControlMsg = onFilesControlData;
356 + webRtcDesktop.softdesktop.sendCtrlMsg(JSON.stringify({ action: 'ls', reqid: 1, path: '' })); // Ask for the root folder
357 + */
358 + // ###END###{DesktopInbandFiles}
359 + }
360 + webRtcDesktop.webchannel.onclose = function (event) {
361 + //if (urlvars['kvmdatatrace']) { console.log('WebRTC Data Channel Closed'); }
362 + console.log('WebRTC Data Channel Closed');
363 + webRtcDesktopReset();
364 + }
365 + webRtcDesktop.webrtc.onicecandidate = function (e) {
366 + if (e.candidate == null) {
367 + desktop.m.sendKvmData(JSON.stringify({ action: 'offer', ver: 1, sdp: webRtcDesktop.webrtcoffer.sdp }));
368 + } else {
369 + webRtcDesktop.webrtcoffer.sdp += ('a=' + e.candidate.candidate + '\r\n'); // New candidate, add it to the SDP
370 + }
371 + }
372 + webRtcDesktop.webrtc.oniceconnectionstatechange = function () {
373 + if ((webRtcDesktop != null) && (webRtcDesktop.webrtc != null) && ((webRtcDesktop.webrtc.iceConnectionState == 'disconnected') || (webRtcDesktop.webrtc.iceConnectionState == 'failed'))) { /*console.log('WebRTC ICE Failed');*/ webRtcDesktopReset(); }
374 + }
375 + webRtcDesktop.webrtc.createOffer(function (offer) {
376 + // Got the offer
377 + webRtcDesktop.webrtcoffer = offer;
378 + webRtcDesktop.webrtc.setLocalDescription(offer, function () { }, webRtcDesktopReset);
379 + }, webRtcDesktopReset, { mandatory: { OfferToReceiveAudio: false, OfferToReceiveVideo: false } });
380 + } else if ((data.action == 'answer') && (webRtcDesktop != null)) {
381 + // Complete the WebRTC channel
382 + webRtcDesktop.webrtc.setRemoteDescription(new RTCSessionDescription({ type: 'answer', sdp: data.sdp }), function () { }, webRtcDesktopReset);
383 + }
384 + }
385 + };
386 + desktop.Start(desktopNodeId, 16994, '*', '*', 0);
387 + desktop.contype = 2;
388 + } else if ((contype == null) || (contype == 1) || (contype == 3)) {
389 + // Setup the Mesh Agent remote desktop
390 + var meshserver = null;
391 + desktop = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('Desk'), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
392 + desktop.m.mouseCursorActive(xxcurrentView == 11);
393 + desktop.debugmode = debugmode;
394 + desktop.m.debugmode = debugmode;
395 + desktop.attemptWebRTC = attemptWebRTC;
396 + desktop.options = {};
397 + if (tsid != null) { desktop.options.tsid = tsid; }
398 + if (consent != null) { desktop.options.consent = consent; }
399 + desktop.onStateChanged = onDesktopStateChange;
400 + desktop.onConsoleMessageChange = function () {
401 + if (desktop.consoleMessage) {
402 + Q('p11DeskConsoleMsg').innerHTML += formatAgentConsoleMessage(desktop.consoleMessage, desktop.consoleMessageId, desktop.consoleMessageArgs);
403 + QV('p11DeskConsoleMsg', true);
404 + if (p11DeskConsoleMsgTimer != null) { clearTimeout(p11DeskConsoleMsgTimer); }
405 + if (desktop.consoleMessageTimeout) { p11DeskConsoleMsgTimer = setTimeout(p11clearConsoleMsg, desktop.consoleMessageTimeout * 1000); }
406 + } else {
407 + p11clearConsoleMsg();
408 + }
409 + }
410 + desktop.onMetadataChange = function (metadata) { updateMetadata(desktop, 'deskmetadata'); }
411 + desktop.m.CompressionLevel = desktopsettings.quality; // Number from 1 to 100. 50 or less is best.
412 + desktop.m.ScalingLevel = desktopsettings.scaling;
413 + if (desktopsettings.framerate) { desktop.m.FrameRateTimer = desktopsettings.framerate; }
414 + desktop.m.onDisplayinfo = deskDisplayInfo;
415 + desktop.m.onScreenSizeChange = deskAdjust;
416 + desktop.Start(desktopNodeId);
417 + desktop.latency.callback = function (ms) { console.log('latency', ms); updateSessionTime(); };
418 + desktop.contype = 1;
419 + }
420 + } else {
421 + // Disconnect and clean up the remote desktop
422 + desktop.Stop();
423 + webRtcDesktopReset();
424 + desktop = null;
425 + if (pluginHandler != null) { pluginHandler.callHook('onDesktopDisconnect'); }
426 + }
427 + }
428 +
429 + function updateMetadata(conn, elementid) {
430 + var str = '', viewerCount = 0;
431 + if (conn && (conn.State == 3)) {
432 + if (conn.metadata && conn.metadata.users) { for (var i in conn.metadata.users) { viewerCount += conn.metadata.users[i]; } }
433 + if (viewerCount > 1) { str = '<span onclick=showSessionMetadata(1) style=cursor:pointer>' + format(", {0} watching", viewerCount) + '</span>'; }
434 + }
435 + QH('deskmetadata', str);
436 + if ((conn == desktop) && (xxdialogTag == ('sessionMetadata1'))) { showSessionMetadata(1); }
437 + }
438 +
439 + function showSessionMetadata(cid) {
440 + if (xxdialogMode && (xxdialogTag != ('sessionMetadata' + cid))) return;
441 + if (xxdialogMode) { setDialogMode(0); }
442 + var conn = null;
443 + if (cid == 1) { conn = desktop; }
444 + if (conn && conn.metadata) {
445 + var x = '';
446 + if (conn.metadata.startTime) { x += addHtmlValue4("Start Time", printDateTime(new Date(conn.metadata.startTime))); }
447 + if (conn.metadata.users) {
448 + for (var i in conn.metadata.users) {
449 + var val = (conn.metadata.users[i] == 1) ? "1 connection" : format("{0} connections", conn.metadata.users[i]);
450 + var username = i.split('/')[2];
451 + if ((users != null) && (users[i] != null)) { username = users[i].name; }
452 + x += addHtmlValue4(format("User \"{0}\"", username), val);
453 + }
454 + }
455 + setDialogMode(2, "Session Information", 1, null, x, 'sessionMetadata' + cid);
456 + }
457 + }
458 +
459 + function p11clearConsoleMsg() { QH('p11DeskConsoleMsg', ''); QV('p11DeskConsoleMsg', false); if (p11DeskConsoleMsgTimer) { clearTimeout(p11DeskConsoleMsgTimer); p11DeskConsoleMsgTimer = null; } }
460 +
461 + var webRtcDesktop = null;
462 + function webRtcDesktopReset() {
463 + if (webRtcDesktop == null) return;
464 + if (webRtcDesktop.softdesktop != null) { webRtcDesktop.softdesktop.Stop(); webRtcDesktop.softdesktop = null; }
465 + if (webRtcDesktop.webchannel != null) { try { webRtcDesktop.webchannel.close(); } catch (e) { } webRtcDesktop.webchannel = null; }
466 + if (webRtcDesktop.webrtc != null) { try { webRtcDesktop.webrtc.close(); } catch (e) { } webRtcDesktop.webrtc = null; }
467 + webRtcDesktop = null;
468 + // Switch back to hardware KVM
469 + if (desktop && desktop.m) {
470 + desktop.m.hold(false);
471 + Q('deskstatus').textContent = StatusStrs[desktop.State];
472 + }
473 + // ###BEGIN###{DesktopInbandFiles}
474 + /*
475 + p24files = null;
476 + p24downloadFileCancel() // If any downloads are in process, cancel them.
477 + p24uploadFileCancel(); // If any uploads are in process, cancel them.
478 + QV('go24', false); // Files
479 + if (currentView == 24) { go(14); }
480 + */
481 + // ###END###{DesktopInbandFiles}
482 + }
483 +
484 + function onDesktopStateChange(xdesktop, state) {
485 + var xstate = state;
486 + if ((xstate == 3) && (xdesktop.contype == 2)) { xstate++; }
487 + var str = StatusStrs[xstate];
488 + if ((desktop != null) && (desktop.webRtcActive == true)) { str += ", WebRTC"; }
489 + //if (desktop.m.stopInput == true) { str += ', Loopback'; }
490 + QH('deskstatus', str);
491 + switch (state) {
492 + case 0:
493 + // Stop recording
494 + if (desktop.m.recordedData != null) { deskRecordSession(); }
495 +
496 + // Disconnect and clean up the remote desktop
497 + desktop.Stop();
498 + desktop = null;
499 + QV('DeskFocus', false);
500 + QV('termdisplays', false);
501 + QV('deskRecordIcon', false);
502 + if (fullscreen == true) { deskToggleFull(); }
503 + webRtcDesktopReset();
504 + deskPreferedStickyDisplay = 0;
505 + break;
506 + case 2:
507 + break;
508 + case 3:
509 + if (desktop && (desktop.serverIsRecording == true)) { QV('deskRecordIcon', true); }
510 + desktop.startTime = new Date();
511 + if (updateSessionTimer == null) { updateSessionTimer = setInterval(updateSessionTime, 1000); }
512 + break;
513 + default:
514 + //console.log('Unknown onDesktopStateChange state', state);
515 + break;
516 + }
517 + updateDesktopButtons();
518 + deskAdjust();
519 + setTimeout(deskAdjust, 50);
520 + updateMetadata(desktop, 'deskmetadata');
521 + }
522 +
523 + function updateSessionTime() {
524 + // Desktop
525 + var latencyStr = '', seconds = 0;
526 + if (desktop && desktop.startTime) {
527 + if (desktop.latency && (desktop.latency.current >= 0)) { latencyStr = format('{0} ms, ', desktop.latency.current); }
528 + seconds = Math.floor((new Date() - desktop.startTime) / 1000);
529 + QH('DeskTimer', latencyStr + zeroPad(Math.floor(seconds / 3600), 2) + ':' + zeroPad((Math.floor(seconds / 60) % 60), 2) + ':' + zeroPad((seconds % 60), 2));
530 + } else {
531 + QH('DeskTimer', '');
532 + }
533 +
534 + // Terminal
535 + seconds = 0;
536 + if (terminal && terminal.startTime) {
537 + if (terminal.latency && (terminal.latency.current >= 0)) { latencyStr = format('{0} ms, ', terminal.latency.current); }
538 + seconds = Math.floor((new Date() - terminal.startTime) / 1000);
539 + QH('TermTimer', latencyStr + zeroPad(Math.floor(seconds / 3600), 2) + ':' + zeroPad((Math.floor(seconds / 60) % 60), 2) + ':' + zeroPad((seconds % 60), 2));
540 + } else {
541 + QH('TermTimer', '');
542 + }
543 +
544 + if ((desktop == null) && (terminal == null)) { clearInterval(updateSessionTimer); updateSessionTimer = null; }
545 + }
546 +
547 + function showDesktopSettings() {
548 + if (xxdialogMode) return;
549 + applyDesktopSettings();
550 + updateDesktopButtons();
551 + setDialogMode(7, "Remote Desktop Settings", 3, showDesktopSettingsChanged);
552 + }
553 +
554 + function showDesktopSettingsChanged() {
555 + desktopsettings.encoding = d7desktopmode.value;
556 + desktopsettings.showfocus = d7showfocus.checked;
557 + desktopsettings.showmouse = d7showcursor.checked;
558 + desktopsettings.quality = d7bitmapquality.value;
559 + desktopsettings.scaling = d7bitmapscaling.value;
560 + desktopsettings.framerate = d7framelimiter.value;
561 + desktopsettings.localkeymap = d7localKeyMap.checked;
562 + localStorage.setItem('desktopsettings', JSON.stringify(desktopsettings));
563 + applyDesktopSettings();
564 + if (desktop) {
565 + if (desktop.contype == 1) {
566 + if (desktop.State != 0) {
567 + desktop.m.SendCompressionLevel(1, desktopsettings.quality, desktopsettings.scaling, desktopsettings.framerate);
568 + }
569 + }
570 + if (desktop.contype == 2) {
571 + if (desktop.State != 0) { desktop.Stop(); setTimeout(function () { connectDesktop(null, 2); }, 50); }
572 + }
573 + }
574 + }
575 +
576 + function applyDesktopSettings() {
577 + var r = '', ops = [60, 50, 40, 30, 20, 10, 5, 1];
578 + for (var i in ops) { r += '<option value=' + ops[i] + '>' + ops[i] + '%</option>'; }
579 + QH('d7bitmapquality', r);
580 + d7desktopmode.value = desktopsettings.encoding;
581 + d7showfocus.checked = desktopsettings.showfocus;
582 + d7showcursor.checked = desktopsettings.showmouse;
583 + d7bitmapquality.value = 40; // Default value
584 + if (ops.indexOf(parseInt(desktopsettings.quality)) >= 0) { d7bitmapquality.value = desktopsettings.quality; }
585 + d7bitmapscaling.value = desktopsettings.scaling;
586 + if (desktopsettings.framerate) { d7framelimiter.value = desktopsettings.framerate; } else { d7framelimiter.value = 100; }
587 + if (desktopsettings.localkeymap) { d7localKeyMap.checked = desktopsettings.localkeymap; }
588 + }
589 +
590 + // Enter browser fullscreen
591 + function enterBrowserFullscreen(elem) {
592 + if (elem.requestFullscreen) { elem.requestFullscreen(); }
593 + else if (elem.msRequestFullscreen) { elem.msRequestFullscreen(); }
594 + else if (elem.mozRequestFullScreen) { elem.mozRequestFullScreen(); }
595 + else if (elem.webkitRequestFullscreen) { elem.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); }
596 + }
597 +
598 + // Exit browser fullscreen
599 + function exitBrowserFullscreen() {
600 + if (document.exitFullscreen) { document.exitFullscreen(); }
601 + else if (document.msExitFullscreen) { document.msExitFullscreen(); }
602 + else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); }
603 + else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); }
604 + }
605 +
606 + // Return true if the browser is fullscreen. This is a delayed method that will return true/false late. Not very useful.
607 + function isBrowserFullscreen() {
608 + if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) { return false; } else { return true; }
609 + }
610 +
611 + var fullscreen = false;
612 + var browserfullscreen = false;
613 + function deskToggleFull(e) {
614 + var xtermActive = !((urlargs.xterm === 0) || ((terminal != null) && (xterm == null)));
615 + fullscreen = !fullscreen;
616 + if (fullscreen) {
617 + QC('body').add('fulldesk');
618 + QS('deskarea3x')['height'] = '100%';
619 + QS('deskarea3x')['max-height'] = '100%';
620 + if (xtermActive) {
621 + // XTerm terminal
622 + QS('termTable')['position'] = 'absolute';
623 + QS('termTable')['top'] = QS('termTable')['bottom'] = QS('termTable')['left'] = QS('termTable')['right'] = '0';
624 + } else {
625 + // Legacy terminal
626 + QS('termTable')['height'] = '100%';
627 + QS('termTable')['max-height'] = '100%';
628 + }
629 +
630 + // If shift is pressed, enter browser full screen.
631 + if (e.shiftKey == true) {
632 + enterBrowserFullscreen(Q('container'));
633 + browserfullscreen = true;
634 + }
635 + } else {
636 + QC('body').remove('fulldesk');
637 + var hide = urlargs.hide;
638 + if (footerBar == false) { hide |= 4; }
639 + var xh = (((hide & 1) ? 0 : 66) + ((hide & 2) ? 0 : 24) + ((hide & 4) ? 0 : 45) + ((hide & 8) ? 0 : 60)); // 0 to 195
640 + QS('deskarea3x')['height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
641 + QS('deskarea3x')['max-height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
642 + if (xtermActive) {
643 + // XTerm terminal
644 + QS('termTable')['position'] = null;
645 + QS('termTable')['top'] = QS('termTable')['bottom'] = QS('termTable')['left'] = QS('termTable')['right'] = null;
646 + } else {
647 + // Legacy terminal
648 + QS('termTable')['height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
649 + QS('termTable')['max-height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
650 + }
651 + if (browserfullscreen == true) { exitBrowserFullscreen(); browserfullscreen = false; }
652 + }
653 + deskAdjust();
654 + updateDesktopButtons();
655 + adjustPanels();
656 + //setTimeout(adjustPanels, 10);
657 + //setTimeout(function() { xtermfit.fit(); }, 10);
658 + if (xterm != null) { if (xxcurrentView == 12) { xtermfit.fit(); xterm.focus(); } }
659 + }
660 +
661 + function deskAdjust() {
662 + var parentH = Q('DeskParent').clientHeight, parentW = Q('DeskParent').clientWidth;
663 + var deskH = Q('Desk').height, deskW = Q('Desk').width;
664 +
665 + if (deskAspectRatio == 2) {
666 + // Scale mode
667 + QS('Desk')['margin-top'] = null;
668 + QS('Desk').height = '100%';
669 + QS('Desk').width = '100%';
670 + //QS('deskarea3x').height = null;
671 + QS('DeskParent').overflow = 'hidden';
672 + } else if (deskAspectRatio == 1) {
673 + // Zoomed mode
674 + QS('Desk')['margin-top'] = '0px';
675 + QS('Desk').height = deskH + 'px';
676 + QS('Desk').width = deskW + 'px';
677 + QS('DeskParent').overflow = 'scroll';
678 + } else {
679 + // Fixed aspect ratio
680 + if ((parentH / parentW) > (deskH / deskW)) {
681 + var hNew = ((deskH * parentW) / deskW) + 'px';
682 + //if (webPageFullScreen || fullscreen) {
683 + //QS('deskarea3x').height = null;
684 + //} else {
685 + // QS('deskarea3x').height = hNew;
686 + //QS('deskarea3x').height = null;
687 + //}
688 + QS('Desk').height = hNew;
689 + QS('Desk').width = '100%';
690 + } else {
691 + var wNew = ((deskW * parentH) / deskH) + 'px';
692 + if (webPageFullScreen || fullscreen) {
693 + QS('Desk').height = null;
694 + } else {
695 + QS('Desk').height = '100%';
696 + }
697 + QS('Desk').width = wNew;
698 + }
699 + QS('Desk')['margin-top'] = null;
700 + QS('DeskParent').overflow = 'hidden';
701 + }
702 + }
703 +
704 + function mdeskAdjust(mod, sw, sh, cv) {
705 + if (!mod || !sw || !sh || !cv) return;
706 +
707 + // Check if we are in single desktop mode
708 + if (cv.id == 'Desk') { deskAdjust(); return; }
709 +
710 + // Figure out and adjust the size to fill the width of the div
711 + var vsize = [{ x: 180, y: 101 }, { x: 302, y: 169 }, { x: 454, y: 255 }][Q('sizeselect').selectedIndex];
712 + var realw = vsize.x + 2, tw = Q('xdevices').clientWidth - 30, xw = Math.floor(tw / realw);
713 + xw = realw + Math.floor((tw - (xw * realw)) / xw);
714 + vsize.y = vsize.y * (xw / vsize.x);
715 + vsize.x = xw;
716 + var mh = vsize.y, mw = vsize.x;
717 + if (mod.State != 0) { mh = vsize.y; mw = (sw / sh) * vsize.y; }
718 + QS(cv.id)['max-height'] = mh + 'px';
719 + QS(cv.id)['max-width'] = mw + 'px';
720 + QS(cv.id)['margin-top'] = '0';
721 + QS(cv.id)['margin-bottom'] = '0';
722 + }
723 +
724 + // Remote desktop special key combos for Windows
725 + function deskSendKeys() {
726 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
727 + var ks = Q('deskkeys').value;
728 + if (ks == 0) { // WIN+Down arrow
729 + if (desktop.contype == 2) {
730 + desktop.m.sendkey([[0xffe7, 1], [0xff54, 1], [0xff54, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Down arrow press, Down arrow release, Meta-left release
731 + } else {
732 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 40], [desktop.m.KeyAction.UP, 40], [desktop.m.KeyAction.EXUP, 0x5B]]); // Agent: L-Winkey press, Down arrow press, Down arrow release, L-Winkey release
733 + }
734 + } else if (ks == 1) { // WIN+Up arrow
735 + if (desktop.contype == 2) {
736 + desktop.m.sendkey([[0xffe7, 1], [0xff52, 1], [0xff52, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Up arrow press, Up arrow release, Meta-left release
737 + } else {
738 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 38], [desktop.m.KeyAction.UP, 38], [desktop.m.KeyAction.EXUP, 0x5B]]); // MeshAgent: L-Winkey press, Up arrow press, Up arrow release, L-Winkey release
739 + }
740 + } else if (ks == 2) { // WIN+L arrow
741 + if (desktop.contype == 2) {
742 + desktop.m.sendkey([[0xffe7, 1], [0x6c, 1], [0x6c, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, 'l' press, 'l' release, Meta-left release
743 + } else {
744 + desktop.sendCtrlMsg('{"action":"lock"}');
745 + //desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,76],[desktop.m.KeyAction.UP,76],[desktop.m.KeyAction.EXUP,0x5B]]); // MeshAgent: L-Winkey press, 'L' press, 'L' release, L-Winkey release
746 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.EXDOWN, 0x5B);
747 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.DOWN, 76);
748 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.UP, 76);
749 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.EXUP, 0x5B);
750 + }
751 + } else if (ks == 3) { // WIN+M arrow
752 + if (desktop.contype == 2) {
753 + desktop.m.sendkey([[0xffe7, 1], [0x6d, 1], [0x6d, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, 'm' press, 'm' release, Meta-left release
754 + } else {
755 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 77], [desktop.m.KeyAction.UP, 77], [desktop.m.KeyAction.EXUP, 0x5B]]); // MeshAgent: L-Winkey press, 'M' press, 'M' release, L-Winkey release
756 + }
757 + } else if (ks == 4) { // Shift+WIN+M arrow
758 + if (desktop.contype == 2) {
759 + desktop.m.sendkey([[0xffe1, 1], [0xffe7, 1], [0x6d, 1], [0x6d, 0], [0xffe7, 0], [0xffe1, 0]]); // Intel AMT: Shift-left down, Meta-left down, 'm' press, 'm' release, Meta-left release, Shift-left release
760 + } else {
761 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.DOWN, 16], [desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 77], [desktop.m.KeyAction.UP, 77], [desktop.m.KeyAction.EXUP, 0x5B], [desktop.m.KeyAction.UP, 16]]); // MeshAgent: L-shift press, L-Winkey press, 'M' press, 'M' release, L-Winkey release, L-shift release
762 + }
763 + } else if (ks == 5) { // WIN
764 + if (desktop.contype == 2) {
765 + desktop.m.sendkey([[0xffe7, 1], [0xffe7, 0]]); // Intel AMT: Meta-left down, Meta-left release
766 + } else {
767 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.EXUP, 0x5B]]); // MeshAgent: L-Winkey press, L-Winkey release
768 + }
769 + } else if (ks == 6) { // WIN+R
770 + if (desktop.contype == 2) {
771 + desktop.m.sendkey([[0xffe7, 1], [0x72, 1], [0x72, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, 'r' press, 'r' release, Meta-left release
772 + } else {
773 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 82], [desktop.m.KeyAction.UP, 82], [desktop.m.KeyAction.EXUP, 0x5B]]); // MeshAgent: L-Winkey press, 'R' press, 'R' release, L-Winkey release
774 + }
775 + } else if (ks == 7) { // ALT-F4
776 + if (desktop.contype == 2) {
777 + desktop.m.sendkey([[0xffe9, 1], [0xffc1, 1], [0xffc1, 0], [0xffe9, 0]]); // Intel AMT: Alt down, 'F4' press, 'F4' release, Alt release
778 + } else {
779 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 18], [desktop.m.KeyAction.DOWN, 115], [desktop.m.KeyAction.UP, 115], [desktop.m.KeyAction.EXUP, 18]]); // MeshAgent: Alt press, 'F4' press, 'F4' release, Alt release
780 + }
781 + } else if (ks == 8) { // CTRL-W
782 + if (desktop.contype == 2) {
783 + desktop.m.sendkey([[0xffe3, 1], [0x77, 1], [0x77, 0], [0xffe3, 0]]); // Intel AMT: Ctrl down, 'w' press, 'w' release, Ctrl release
784 + } else {
785 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 17], [desktop.m.KeyAction.DOWN, 87], [desktop.m.KeyAction.UP, 87], [desktop.m.KeyAction.EXUP, 17]]); // MeshAgent: Ctrl press, 'W' press, 'W' release, Ctrl release
786 + }
787 + } else if (ks == 9) { // ALT-TAB
788 + if (desktop.contype == 2) {
789 + desktop.m.sendkey([[0xffe9, 1], [0xff09, 1], [0xff09, 0], [0xffe9, 0]]); // Intel AMT: Alt down, 'TAB' press, 'TAB' release, Alt release
790 + } else {
791 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 18], [desktop.m.KeyAction.DOWN, 9], [desktop.m.KeyAction.UP, 9], [desktop.m.KeyAction.EXUP, 18]]); // MeshAgent: Alt press, 'TAB' press, 'TAB' release, Alt release
792 + }
793 + } else if (ks == 10) { // CTRL-ALT-DEL
794 + desktop.m.sendcad();
795 + } else if (ks == 11) { // WIN-LEFT
796 + if (desktop.contype == 2) {
797 + desktop.m.sendkey([[0xffe7, 1], [0xff51, 1], [0xff51, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Left arrow press, Left arrow release, Meta-left release
798 + } else {
799 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 37], [desktop.m.KeyAction.UP, 37], [desktop.m.KeyAction.EXUP, 0x5B]]);
800 + }
801 + } else if (ks == 12) { // WIN-RIGHT
802 + if (desktop.contype == 2) {
803 + desktop.m.sendkey([[0xffe7, 1], [0xff53, 1], [0xff53, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Right arrow press, Right arrow release, Meta-left release
804 + } else {
805 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 39], [desktop.m.KeyAction.UP, 39], [desktop.m.KeyAction.EXUP, 0x5B]]);
806 + }
807 + }
808 + }
809 +
810 + // Remote desktop typing
811 + function showDeskType() {
812 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
813 + Q('DeskType').blur();
814 + var x = '<div>' + "Enter text and click OK to remotely type it using a US english keyboard. Make sure to place the remote cursor at the correct position before proceeding." + '<div>';
815 + x += '<textarea id=d2typeText style="margin-top:5px;width:100%;height:184px;resize:none" maxlength=2000></textarea>';
816 + setDialogMode(2, "Remote Keyboard Entry", 3, showDeskTypeEx, x);
817 + Q('d2typeText').focus();
818 + }
819 +
820 + var AmtDeskTypeTimer = null;
821 + var AmtDeskTypeContent = null;
822 + var DeskTypeTranslate = { 39: 222, 42: 106, 43: 107, 44: 188, 45: 189, 46: 190, 47: 191, 59: 186, 61: 187, 91: 219, 92: 220, 93: 221, 96: 192, 191: 111 };
823 + var DeskTypeShiftTranslate = { 33: 49, 34: 222, 35: 51, 36: 52, 37: 53, 38: 55, 40: 57, 41: 48, 58: 186, 60: 188, 62: 190, 63: 191, 64: 50, 94: 54, 95: 189, 106: 56, 107: 187, 123: 219, 124: 220, 125: 221, 126: 192 };
824 + function showDeskTypeEx() {
825 + var txt = Q('d2typeText').value, ltxt = Q('d2typeText').value.toUpperCase(), x = [], shift = false;
826 + if (desktop.contype == 2) {
827 + // Intel AMT
828 + for (var i in txt) { var a = txt.charCodeAt(i); x.push([a, 1], [a, 0]); }
829 + AmtDeskTypeContent = x;
830 + AmtDeskTypeTimer = setInterval(function () {
831 + var key = AmtDeskTypeContent.shift();
832 + if (desktop) { desktop.m.sendkey(key[0], key[1]); }
833 + if ((desktop == null) || (AmtDeskTypeContent.length == 0)) { clearInterval(AmtDeskTypeTimer); AmtDeskTypeContent = null; }
834 + }, 10);
835 + } else {
836 + // MeshAgent
837 + for (var i in txt) {
838 + var a = txt.charCodeAt(i), b = ltxt.charCodeAt(i);
839 + if (((a >= 65) && (a <= 90)) || ((a >= 97) && (a <= 122))) {
840 + if ((a == b) && (shift == false)) { x.push([desktop.m.KeyAction.DOWN, 16]); shift = true; } // LShift down
841 + if ((a != b) && (shift == true)) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // LShift up
842 + } else if ((a >= 48) && (a <= 57)) {
843 + if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
844 + } else if (DeskTypeTranslate[a]) {
845 + if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
846 + b = DeskTypeTranslate[a];
847 + } else if (DeskTypeShiftTranslate[a]) {
848 + if (shift == false) { x.push([desktop.m.KeyAction.DOWN, 16]); shift = true; } // LShift down
849 + b = DeskTypeShiftTranslate[a];
850 + }
851 + x.push([desktop.m.KeyAction.DOWN, b], [desktop.m.KeyAction.UP, b]);
852 + }
853 + if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
854 + desktop.m.SendKeyMsgKC(x);
855 + }
856 + }
857 +
858 + // Show clipboard dialog
859 + function showDeskClip() {
860 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
861 + Q('DeskClip').blur();
862 + var x = '';
863 + x += '<input id=dlgClipGet type=button value="Get Clipboard" style=width:120px onclick=showDeskClipGet()>';
864 + x += '<input id=dlgClipSet type=button value="Set Clipboard" style=width:120px onclick=showDeskClipSet()>';
865 + x += '<div id=dlgClipStatus style="display:inline-block;margin-left:8px" ></div>';
866 + x += '<textarea id=d2clipText style="width:100%;height:184px;resize:none" maxlength=65535></textarea>';
867 + x += '<input type=button value="Close" style=width:80px;float:right onclick=dialogclose(0)><div style=height:26px;margin-top:3px><span id=linuxClipWarn style=display:none>' + "Remote clipboard is valid for 60 seconds." + '</span>&nbsp;</div><div></div>';
868 + setDialogMode(2, "Remote Clipboard", 8, null, x, 'clipboard');
869 + Q('d2clipText').focus();
870 + }
871 +
872 + function showDeskClipGet() {
873 + if (desktop == null || desktop.State != 3) return;
874 + meshserver.send({ action: 'msg', type: 'getclip', nodeid: currentNode._id });
875 + }
876 +
877 + function showDeskClipSet() {
878 + if (desktop == null || desktop.State != 3) return;
879 + meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: Q('d2clipText').value });
880 + QV('linuxClipWarn', currentNode && currentNode.agent && (currentNode.agent.id > 4) && (currentNode.agent.id != 21) && (currentNode.agent.id != 22));
881 + }
882 +
883 + // Send CTRL-ALT-DEL
884 + function sendCAD() {
885 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
886 + desktop.m.sendcad();
887 + }
888 +
889 + // Show process dialogs
890 + function toggleDeskTools() {
891 + if (xxdialogMode) return;
892 + if (QS('DeskTools').display == 'none') {
893 + QV('DeskTools', true);
894 + Q('DeskTools').nodeid = currentNode._id;
895 + QH('DeskToolsProcesses', '');
896 + QH('DeskToolsServices', '');
897 + QV('deskToolsTopTabService', false);
898 + changeDeskToolTab(0)
899 + refreshDeskTools(0);
900 + refreshDeskTools(1);
901 + } else {
902 + QV('DeskTools', false);
903 + }
904 + }
905 +
906 + var deskToolTabSelection = 0;
907 + function changeDeskToolTab(tabnum) {
908 + deskToolTabSelection = tabnum;
909 + QV('DeskToolsProcessTab', tabnum == 0);
910 + QV('DeskToolsServiceTab', tabnum == 1);
911 + QS('deskToolsTopTabProcess')['bottom'] = (tabnum == 0) ? '0px' : '3px';
912 + QS('deskToolsTopTabService')['bottom'] = (tabnum == 1) ? '0px' : '3px';
913 + QS('deskToolsTopTabProcess')['color'] = (tabnum == 0) ? 'black' : 'gray';
914 + QS('deskToolsTopTabService')['color'] = (tabnum == 1) ? 'black' : 'gray';
915 + }
916 +
917 + // Refresh all of the desktop tool panels
918 + function refreshDeskTools(x) {
919 + var sel = (x == null) ? deskToolTabSelection : x;
920 + QV('DeskToolsRefreshButton', false);
921 + setTimeout(refreshDeskToolsEx, 500);
922 + if (sel == 0) meshserver.send({ action: 'msg', type: 'ps', nodeid: currentNode._id });
923 + if (sel == 1) meshserver.send({ action: 'msg', type: 'services', nodeid: currentNode._id });
924 + }
925 + function refreshDeskToolsEx() { QV('DeskToolsRefreshButton', true); }
926 + var deskTools = { sort: 1, ssort: 1, msg: null, smsg: null };
927 + function sortProcess(sort) { deskTools.sort = sort; showDeskToolsProcesses(deskTools.msg); }
928 + function sortService(sort) { deskTools.ssort = sort; showDeskToolsServices(deskTools.smsg); }
929 + function sortProcessPid(a, b) { if (a.p > b.p) return 1; if (a.p < b.p) return (-1); return sortProcessName(a, b); }
930 + function sortProcessName(a, b) { if (a.d > b.d) return 1; if (a.d < b.d) return (-1); return 0; }
931 + function showDeskToolsProcesses(message) {
932 + deskTools.msg = message;
933 + if (message == null) { QH('DeskToolsProcesses', ''); return; }
934 + if (Q('DeskTools').nodeid != message.nodeid) return;
935 + var p = [], processes = null;
936 + try { processes = JSON.parse(message.value); } catch (e) { }
937 + if (processes != null) {
938 + for (var pid in processes) { p.push({ p: parseInt(pid), c: processes[pid].cmd, d: processes[pid].cmd.toLowerCase(), u: processes[pid].user }); }
939 + if (deskTools.sort == 0) { p.sort(sortProcessPid); } else if (deskTools.sort == 1) { p.sort(sortProcessName); }
940 + var x = '';
941 + for (var i in p) {
942 + if (p[i].p != 0) {
943 + var c = p[i].c;
944 + if (c.length > 30) { c = '<span title="' + EscapeHtml(c) + '">' + EscapeHtml(c.substring(0, 30)) + '...</span>' } else { c = EscapeHtml(c); }
945 + x += '<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>' + EscapeHtml(p[i].p) + '</div><a href=# style=float:right;padding-right:5px;cursor:pointer title="' + "Stop process" + '" onclick=\'return stopProcess(' + EscapeHtml(p[i].p) + ',"' + EscapeHtml(p[i].c) + '")\'><img width=10 height=10 src="images/trash.png"></a><div style=float:right;padding-right:5px>' + (p[i].u ? EscapeHtml(p[i].u) : '') + '</div><div>' + c + '</div></div>';
946 + }
947 + }
948 + QH('DeskToolsProcesses', x);
949 + }
950 + }
951 + function showDeskToolsServices(message) {
952 + deskTools.smsg = message;
953 + if (message == null) { QH('DeskToolsProcesses', ''); return; }
954 + if (Q('DeskTools').nodeid != message.nodeid) return;
955 + QV('deskToolsTopTabService', true);
956 + var s = [], services = null;
957 + try { services = JSON.parse(message.value); } catch (e) { }
958 + deskTools.services = services;
959 + if (services != null) {
960 + for (var i in services) {
961 + if (services[i].status) {
962 + // Windows
963 + s.push({ p: capitalizeFirstLetter(services[i].status.state.toLowerCase()), d: services[i].displayName, i: i });
964 + } else if (services[i].serviceType) {
965 + // Linux (TODO: This the service status is not displayed, not sure start/stop/restart will work).
966 + s.push({ p: services[i].serviceType, d: services[i].name, i: i });
967 + }
968 + }
969 + if (deskTools.ssort == 0) { s.sort(sortProcessPid); } else if (deskTools.ssort == 1) { s.sort(sortProcessName); }
970 + var x = '';
971 + for (var i in s) {
972 + if (s[i].p != 0) {
973 + var c = s[i].d;
974 + if (c.length > 30) { c = '<span title="' + c + '">' + c.substring(0, 30) + '...</span>' } else { c = EscapeHtml(c); }
975 + x += '<div onclick=showServiceDetailsDialog(' + s[i].i + ') class=deskToolsBar><div style=width:70px;float:left;padding-right:5px>' + EscapeHtml(s[i].p) + '</div><div>' + c + '</div></div>';
976 + }
977 + }
978 + QH('DeskToolsServices', x);
979 + }
980 + }
981 +
982 + function showServiceDetailsDialog(index) {
983 + if (xxdialogMode) return;
984 + var service = deskTools.services[index];
985 + if (service != null) {
986 + var x = '';
987 + if (service.name) { x += addHtmlValue("Name", service.name); }
988 + if (service.displayName) { x += addHtmlValue("Display name", service.displayName); }
989 + if (service.status) {
990 + if (service.status.state) { x += addHtmlValue("State", capitalizeFirstLetter(service.status.state.toLowerCase())); }
991 + if (service.status.pid) { x += addHtmlValue("PID", service.status.pid); }
992 + var serviceTypes = [];
993 + if (service.status.isFileSystemDriver === true) { serviceTypes.push("FileSystemDriver"); }
994 + if (service.status.isInteractive === true) { serviceTypes.push("Interactive"); }
995 + if (service.status.isKernelDriver === true) { serviceTypes.push("KernelDriver"); }
996 + if (service.status.isOwnProcess === true) { serviceTypes.push("OwnProcess"); }
997 + if (service.status.isSharedProcess === true) { serviceTypes.push("SharedProcess"); }
998 + if (serviceTypes.length > 0) { x += addHtmlValue("Type", serviceTypes.join(', ')); }
999 + }
1000 + x += '<br/><div style=float:right;margin-bottom:12px><input type=button value="' + "Close" + '" onclick=showServiceDetailsDialogEx(0,' + index + ')></div><div style=margin-bottom:12px><input type=button value="' + "Start" + '" onclick=showServiceDetailsDialogEx(1,' + index + ')><input type=button value="' + "Stop" + '" onclick=showServiceDetailsDialogEx(2,' + index + ')><input type=button value="' + "Restart" + '" onclick=showServiceDetailsDialogEx(3,' + index + ')></div>';
1001 + setDialogMode(2, "Service Details", 8, null, x, name);
1002 + }
1003 + }
1004 +
1005 + function showServiceDetailsDialogEx(action, index) {
1006 + setDialogMode(0);
1007 + if (action == 0) return;
1008 + var service = deskTools.services[index];
1009 + if (service != null) {
1010 + if (action == 1) { meshserver.send({ action: 'msg', type: 'serviceStart', nodeid: currentNode._id, serviceName: service.name }); }
1011 + if (action == 2) { meshserver.send({ action: 'msg', type: 'serviceStop', nodeid: currentNode._id, serviceName: service.name }); }
1012 + if (action == 3) { meshserver.send({ action: 'msg', type: 'serviceRestart', nodeid: currentNode._id, serviceName: service.name }); }
1013 + setTimeout(function () { refreshDeskTools(1) }, 1000);
1014 + }
1015 + }
1016 +
1017 + // Toggle mouse and keyboard input
1018 + function toggleKvmControl() { QS('DeskControlSpan').color = Q('DeskControl').checked ? null : 'red'; }
1019 +
1020 + // Save the desktop image to file
1021 + function deskSaveImage() {
1022 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
1023 + var d = new Date(), n = "Desktop" + '-' + currentNode.name + '-' + d.getFullYear() + '-' + ('0' + (d.getMonth() + 1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);
1024 + Q('Desk')['toBlob'](function (blob) { saveAs(blob, n + '.png'); });
1025 + }
1026 +
1027 + function deskDisplayInfo(sender, displays, selDisplay) {
1028 + var displayCount = 0, displaySelector = '';
1029 + for (var i in displays) {
1030 + displayCount++;
1031 + displaySelector += '<option' + ((selDisplay == i) ? ' selected' : '') + ' value=' + i + '>' + displays[i] + '</option>';
1032 + if ((deskPreferedStickyDisplay == i) && (selDisplay != deskPreferedStickyDisplay)) { desktop.m.SetDisplay(i); }
1033 + deskPreferedStickyDisplay = -1;
1034 + }
1035 + QH('termdisplays', displaySelector);
1036 + QV('termdisplays', displayCount > 1);
1037 + }
1038 +
1039 + function deskGetDisplayNumbers(e) { desktop.m.GetDisplayNumbers(); }
1040 + var deskPreferedStickyDisplay = -1;
1041 + function deskSetDisplay(e) { desktop.m.SetDisplay(deskPreferedStickyDisplay = parseInt(Q('termdisplays').value)); Q('termdisplays').blur(); }
1042 +
1043 + // Double click detection. This is important for macOS.
1044 + var dblClickDetectArgs = { t: 0, x: 0, y: 0 };
1045 + function dblClickDetect(e) {
1046 + if (e.buttons != 1) return;
1047 + var t = Date.now();
1048 + if (((t - dblClickDetectArgs.t) < 250) && (Math.abs(e.clientX - dblClickDetectArgs.x) < 2) && (Math.abs(e.clientY - dblClickDetectArgs.y) < 2)) {
1049 + if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousedblclick(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousedblclick(e); } }
1050 + }
1051 + dblClickDetectArgs.t = t;
1052 + dblClickDetectArgs.x = e.clientX;
1053 + dblClickDetectArgs.y = e.clientY;
1054 + }
1055 +
1056 + function dmousedown(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousedown(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousedown(e); } } dblClickDetect(e); }
1057 + function dmouseup(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mouseup(e); desktop.m.sendKeepAlive(); } else { desktop.m.mouseup(e); } }
1058 + function dmousemove(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousemove(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousemove(e); } } }
1059 + function dmousewheel(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousewheel(e); desktop.m.sendKeepAlive(); } else { if (desktop.m.mousewheel) { desktop.m.mousewheel(e); } } haltEvent(e); return true; } return false; }
1060 + function drotate(x) { if (!xxdialogMode && desktop != null) { desktop.m.setRotation(desktop.m.rotation + x); deskAdjust(); deskAdjust(); } }
1061 + function stopProcess(id, name) { setDialogMode(2, "Process Control", 3, stopProcessEx, format("Stop process #{0} \"{1}\"?", id, name), id); return false; }
1062 + function stopProcessEx(buttons, tag) { meshserver.send({ action: 'msg', type: 'pskill', nodeid: currentNode._id, value: tag }); setTimeout(refreshDeskTools, 300); }
1063 +
1064 + //
1065 + // POPUP DIALOG
1066 + //
1067 +
1068 + // null = Hidden, 1 = Generic Message
1069 + var xxdialogMode;
1070 + var xxdialogFunc;
1071 + var xxdialogButtons;
1072 + var xxdialogTag;
1073 + var xxcurrentView = -1;
1074 +
1075 + // Display a dialog box
1076 + // Parameters: Dialog Mode (0 = none), Dialog Title, Buttons (1 = OK, 2 = Cancel, 3 = OK & Cancel), Call back function(0 = Cancel, 1 = OK), Dialog Content (Mode 2 only)
1077 + function setDialogMode(x, y, b, f, c, tag) {
1078 + xxdialogMode = x;
1079 + xxdialogFunc = f;
1080 + xxdialogButtons = b;
1081 + xxdialogTag = tag;
1082 + QE('idx_dlgOkButton', true);
1083 + QV('idx_dlgOkButton', b & 1);
1084 + QV('idx_dlgCancelButton', b & 2);
1085 + QV('id_dialogclose', (b & 2) || (b & 8));
1086 + QV('idx_dlgDeleteButton', b & 4);
1087 + QV('idx_dlgButtonBar', b & 7);
1088 + if (y) QH('id_dialogtitle', y);
1089 + for (var i = 1; i < 3; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
1090 + QV('dialog', x);
1091 + if (c) { if (x == 2) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } }
1092 + }
1093 +
1094 + function dialogclose(x) {
1095 + var f = xxdialogFunc, b = xxdialogButtons, t = xxdialogTag;
1096 + setDialogMode();
1097 + if (((b & 8) || x) && f) f(x, t);
1098 + }
1099 +
1100 + function messagebox(t, m) { setSessionActivity(); QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
1101 + function statusbox(t, m) { setSessionActivity(); QH('id_dialogMessage', m); setDialogMode(1, t); }
1102 + function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
1103 + function pad2(num) { var s = '00' + num; return s.substr(s.length - 2); }
1104 + function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
1105 + function setSessionActivity() { sessionActivity = Date.now(); /*QH('idleTimeoutNotify', '');*/ }
1106 +
1107 + start();
1108 + </script>
1109 +</body>
1110 +</html>
\ No newline at end of file
webserver.js
+13 -1
@@ -2863,7 +2863,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2863 try { res.sendFile(obj.path.join(recordingsPath, req.query.file)); } catch (ex) { res.sendStatus(404); }
2864 }
2865
2866 - // Server the player page
2866 + // Serve the player page
2867 function handlePlayerRequest(req, res) {
2868 const domain = checkUserIpAddress(req, res);
2869 if (domain == null) { return; }
@@ -2873,6 +2873,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2873 render(req, res, getRenderPage('player', req, domain), getRenderArgs({}, req, domain));
2874 }
2875
2876 + // Serve the guest desktop page
2877 + function handleDesktopRequest(req, res) {
2878 + const domain = checkUserIpAddress(req, res);
2879 + if (domain == null) { return; }
2880 +
2881 + var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
2882 + parent.debug('web', 'handleDesktopRequest: sending guest desktop page');
2883 + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' });
2884 + render(req, res, getRenderPage('desktop', req, domain), getRenderArgs({ domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27'), serverDnsName: obj.getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort }, req, domain));
2885 + }
2886 +
2887 // Handle domain redirection
2888 obj.handleDomainRedirect = function (req, res) {
2889 const domain = checkUserIpAddress(req, res);
@@ -4574,6 +4585,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4585 obj.app.get(url + 'recordings.ashx', handleGetRecordings);
4586 obj.app.get(url + 'player.htm', handlePlayerRequest);
4587 obj.app.get(url + 'player', handlePlayerRequest);
4588 + obj.app.get(url + 'desktop', handleDesktopRequest);
4589 obj.app.ws(url + 'amtactivate', handleAmtActivateWebSocket);
4590 obj.app.ws(url + 'agenttransfer.ashx', handleAgentFileTransfer); // Setup agent to/from server file transfer handler
4591 obj.app.ws(url + 'meshrelay.ashx', function (ws, req) {