mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-23 21:55:52 -05:00
Improved WebRTC support
This commit is contained in:
parent
92aaf754fb
commit
4106b322d6
@ -44,7 +44,6 @@
|
||||
<Compile Include="swarmserver.js" />
|
||||
<Compile Include="multiserver.js" />
|
||||
<Compile Include="pass.js" />
|
||||
<Compile Include="public\relay.js" />
|
||||
<Compile Include="public\scripts\amt-0.2.0.js" />
|
||||
<Compile Include="public\scripts\agent-desktop-0.0.2.js" />
|
||||
<Compile Include="public\scripts\amt-desktop-0.0.2.js" />
|
||||
@ -58,7 +57,6 @@
|
||||
<Compile Include="public\scripts\amt-wsman-ws-0.2.0.js" />
|
||||
<Compile Include="public\scripts\common-0.0.1.js" />
|
||||
<Compile Include="public\scripts\filesaver.1.1.20151003.js" />
|
||||
<Compile Include="public\scripts\inflate.js" />
|
||||
<Compile Include="public\scripts\meshcentral.js" />
|
||||
<Compile Include="redirserver.js" />
|
||||
<Compile Include="webserver.js" />
|
||||
@ -119,8 +117,6 @@
|
||||
<Content Include="public\images\mapmarker.png" />
|
||||
<Content Include="public\images\meshicon50.png" />
|
||||
<Content Include="public\images\trash.png" />
|
||||
<Content Include="public\index.html" />
|
||||
<Content Include="public\relay.htm" />
|
||||
<Content Include="public\scriptblocks.txt" />
|
||||
<Content Include="public\sounds\chimes.mp3" />
|
||||
<Content Include="public\styles\font-awesome\css\font-awesome.min.css" />
|
||||
|
Binary file not shown.
Binary file not shown.
@ -36,6 +36,7 @@ function createMeshCore(agent) {
|
||||
var wifiScanner = null;
|
||||
var networkMonitor = null;
|
||||
var amtscanner = null;
|
||||
var nextTunnelIndex = 1;
|
||||
|
||||
/*
|
||||
var AMTScanner = require("AMTScanner");
|
||||
@ -337,7 +338,7 @@ function createMeshCore(agent) {
|
||||
if (xurl != null) {
|
||||
var woptions = http.parseUri(xurl);
|
||||
woptions.rejectUnauthorized = 0;
|
||||
sendConsoleText(JSON.stringify(woptions));
|
||||
//sendConsoleText(JSON.stringify(woptions));
|
||||
var tunnel = http.request(woptions);
|
||||
tunnel.upgrade = onTunnelUpgrade;
|
||||
tunnel.onerror = function (e) { sendConsoleText('ERROR: ' + JSON.stringify(e)); }
|
||||
@ -349,10 +350,8 @@ function createMeshCore(agent) {
|
||||
tunnel.tcpaddr = data.tcpaddr;
|
||||
tunnel.tcpport = data.tcpport;
|
||||
tunnel.end();
|
||||
sendConsoleText('tunnel.end() called');
|
||||
// Put the tunnel in the tunnels list
|
||||
var index = 1;
|
||||
while (tunnels[index]) { index++; }
|
||||
var index = nextTunnelIndex++;;
|
||||
tunnel.index = index;
|
||||
tunnels[index] = tunnel;
|
||||
|
||||
@ -443,6 +442,7 @@ function createMeshCore(agent) {
|
||||
this.s = s;
|
||||
s.httprequest = this;
|
||||
s.end = onTunnelClosed;
|
||||
s.tunnel = this;
|
||||
|
||||
if (this.tcpport != null) {
|
||||
// This is a TCP relay connection, pause now and try to connect to the target.
|
||||
@ -472,6 +472,7 @@ function createMeshCore(agent) {
|
||||
}
|
||||
|
||||
function onTunnelClosed() {
|
||||
if (tunnels[this.httprequest.index] == null) return; // Stop duplicate calls.
|
||||
sendConsoleText("Tunnel #" + this.httprequest.index + " closed.", this.httprequest.sessionid);
|
||||
delete tunnels[this.httprequest.index];
|
||||
|
||||
@ -487,6 +488,21 @@ function createMeshCore(agent) {
|
||||
// If there is a upload or download active on this connection, close the file
|
||||
if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; }
|
||||
if (this.httprequest.downloadFile) { fs.closeSync(this.httprequest.downloadFile); this.httprequest.downloadFile = undefined; }
|
||||
|
||||
// Clean up WebRTC
|
||||
if (this.webrtc != null) {
|
||||
if (this.webrtc.rtcchannel) { try { this.webrtc.rtcchannel.close(); } catch (e) { } this.webrtc.rtcchannel.removeAllListeners('data'); this.webrtc.rtcchannel.removeAllListeners('end'); delete this.webrtc.rtcchannel; }
|
||||
if (this.webrtc.websocket) { delete this.webrtc.websocket; }
|
||||
try { this.webrtc.close(); } catch (e) { }
|
||||
this.webrtc.removeAllListeners('connected');
|
||||
this.webrtc.removeAllListeners('disconnected');
|
||||
this.webrtc.removeAllListeners('dataChannel');
|
||||
delete this.webrtc;
|
||||
}
|
||||
|
||||
// Clean up WebSocket
|
||||
this.removeAllListeners('data');
|
||||
delete this;
|
||||
}
|
||||
function onTunnelSendOk() { sendConsoleText("Tunnel #" + this.index + " SendOK.", this.sessionid); }
|
||||
function onTunnelData(data) {
|
||||
@ -661,34 +677,71 @@ function createMeshCore(agent) {
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to setup and switch the tunnel over to WebRTC
|
||||
// Called when receiving control data on WebRTC
|
||||
function onTunnelWebRTCControlData(data) {
|
||||
if (typeof data != 'string') return;
|
||||
var obj;
|
||||
try { obj = JSON.parse(data); } catch (e) { sendConsoleText('Invalid control JSON on WebRTC'); return; }
|
||||
if (obj.type == 'close') {
|
||||
sendConsoleText('Tunnel #' + this.xrtc.websocket.tunnel.index + ' WebRTC control close');
|
||||
try { this.close(); } catch (e) { }
|
||||
try { this.xrtc.close(); } catch (e) { }
|
||||
}
|
||||
}
|
||||
|
||||
// Called when receiving control data on websocket
|
||||
function onTunnelControlData(data) {
|
||||
sendConsoleText('onTunnelControlData: ' + data);
|
||||
var obj = JSON.parse(data);
|
||||
if (obj.type == 'offer') {
|
||||
if (typeof data != 'string') return;
|
||||
//sendConsoleText('onTunnelControlData: ' + data);
|
||||
//console.log('onTunnelControlData: ' + data);
|
||||
|
||||
var obj;
|
||||
try { obj = JSON.parse(data); } catch (e) { sendConsoleText('Invalid control JSON'); return; }
|
||||
|
||||
if (obj.type == 'close') {
|
||||
// We received the close on the websocket
|
||||
sendConsoleText('Tunnel #' + this.tunnel.index + ' WebSocket control close');
|
||||
try { this.close(); } catch (e) { }
|
||||
} else if (obj.type == 'webrtc1') {
|
||||
this.write("{\"type\":\"webrtc2\"}"); // Indicates we will no longer get any data on websocket, switching to WebRTC at this point.
|
||||
if (this.httprequest.protocol == 1) { // Terminal
|
||||
// Switch the user input from websocket to webrtc at this point.
|
||||
this.unpipe(this.httprequest.process.stdin);
|
||||
this.rtcchannel.pipe(this.httprequest.process.stdin, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||
this.resume(); // Resume the websocket to keep receiving control data
|
||||
} else if (this.httprequest.protocol == 2) { // Desktop
|
||||
// Switch the user input from websocket to webrtc at this point.
|
||||
this.unpipe(this.httprequest.desktop.kvm);
|
||||
this.webrtc.rtcchannel.pipe(this.httprequest.desktop.kvm, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||
this.resume(); // Resume the websocket to keep receiving control data
|
||||
}
|
||||
} else if (obj.type == 'webrtc2') {
|
||||
// Other side received websocket end of data marker, start sending data on WebRTC channel
|
||||
if (this.httprequest.protocol == 1) { // Terminal
|
||||
this.httprequest.process.stdout.pipe(this.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
|
||||
} else if (this.httprequest.protocol == 2) { // Desktop
|
||||
this.httprequest.desktop.kvm.pipe(this.webrtc.rtcchannel, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||
}
|
||||
} else if (obj.type == 'offer') {
|
||||
// This is a WebRTC offer.
|
||||
this.webrtc = rtc.createConnection();
|
||||
this.webrtc.websocket = this;
|
||||
this.webrtc.on('connected', function () { sendConsoleText('WebRTC connected'); });
|
||||
this.webrtc.on('connected', function () { sendConsoleText('Tunnel #' + this.websocket.tunnel.index + ' WebRTC connected'); });
|
||||
this.webrtc.on('disconnected', function () { sendConsoleText('Tunnel #' + this.websocket.tunnel.index + ' WebRTC disconnected'); });
|
||||
this.webrtc.on('dataChannel', function (rtcchannel) {
|
||||
sendConsoleText('WebRTC Datachannel open, protocol: ' + this.websocket.httprequest.protocol);
|
||||
//sendConsoleText('WebRTC Datachannel open, protocol: ' + this.websocket.httprequest.protocol);
|
||||
rtcchannel.xrtc = this;
|
||||
this.rtcchannel = rtcchannel;
|
||||
this.rtcchannel.on('data', onTunnelWebRTCControlData);
|
||||
this.rtcchannel.on('end', function () { sendConsoleText('Tunnel #' + this.websocket.tunnel.index + ' WebRTC data channel closed'); });
|
||||
if (this.websocket.httprequest.protocol == 1) { // Terminal
|
||||
// This is a terminal data stream, re-setup the pipes
|
||||
// Un-pipe
|
||||
this.websocket.unpipe(this.websocket.httprequest.process.stdin);
|
||||
//this.websocket.httprequest.process.stdout.unpipe(this.websocket);
|
||||
// Re-pipe
|
||||
rtcchannel.pipe(this.websocket.httprequest.process.stdin, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||
//this.websocket.httprequest.process.stdout.pipe(this, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
|
||||
// This is a terminal data stream, unpipe the terminal now and indicate to the other side that terminal data will no longer be received over WebSocket
|
||||
this.websocket.httprequest.process.stdout.unpipe(this.websocket);
|
||||
this.websocket.write("{\"type\":\"webrtc1\"}"); // End of data marker
|
||||
} else if (this.websocket.httprequest.protocol == 2) { // Desktop
|
||||
// This is a KVM data stream, re-setup the pipes
|
||||
// Un-pipe
|
||||
this.websocket.unpipe(this.websocket.httprequest.desktop.kvm);
|
||||
//this.websocket.httprequest.desktop.kvm.unpipe(this.websocket);
|
||||
// Re-pipe
|
||||
rtcchannel.pipe(this.websocket.httprequest.desktop.kvm, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||
//this.websocket.httprequest.desktop.kvm.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||
// This is a KVM data stream, unpipe the KVM now and indicate to the other side that KVM data will no longer be received over WebSocket
|
||||
this.websocket.httprequest.desktop.kvm.unpipe(this.websocket);
|
||||
this.websocket.write("{\"type\":\"webrtc1\"}"); // End of data marker
|
||||
}
|
||||
/*
|
||||
else {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "meshcentral",
|
||||
"version": "0.1.2-t",
|
||||
"version": "0.1.2-u",
|
||||
"keywords": [
|
||||
"Remote Management",
|
||||
"Intel AMT",
|
||||
|
@ -1133,6 +1133,7 @@ var CreateAmtRedirect = function (module) {
|
||||
obj.user = null;
|
||||
obj.pass = null;
|
||||
obj.authuri = "/RedirectionService";
|
||||
obj.tlsv1only = 0;
|
||||
obj.connectstate = 0;
|
||||
obj.protocol = module.protocol; // 1 = SOL, 2 = KVM, 3 = IDER
|
||||
|
||||
@ -1152,7 +1153,7 @@ var CreateAmtRedirect = function (module) {
|
||||
obj.user = user;
|
||||
obj.pass = pass;
|
||||
obj.connectstate = 0;
|
||||
obj.socket = new WebSocket(window.location.protocol.replace("http", "ws") + "//" + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) + "/webrelay.ashx?p=2&host=" + host + "&port=" + port + "&tls=" + tls + ((user == '*') ? "&serverauth=1" : "") + ((typeof pass === "undefined") ? ("&serverauth=1&user=" + user) : "")); // The "p=2" indicates to the relay that this is a REDIRECTION session
|
||||
obj.socket = new WebSocket(window.location.protocol.replace("http", "ws") + "//" + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) + "/webrelay.ashx?p=2&host=" + host + "&port=" + port + "&tls=" + tls + ((user == '*') ? "&serverauth=1" : "") + ((typeof pass === "undefined") ? ("&serverauth=1&user=" + user) : "") + "&tls1only=" + obj.tlsv1only); // The "p=2" indicates to the relay that this is a REDIRECTION session
|
||||
obj.socket.onopen = obj.xxOnSocketConnected;
|
||||
obj.socket.onmessage = obj.xxOnMessage;
|
||||
obj.socket.onclose = obj.xxOnSocketClosed;
|
||||
@ -33060,7 +33061,7 @@ if (typeof module !== "undefined" && module.exports) {
|
||||
});
|
||||
}
|
||||
|
||||
var version = '0.5.7';
|
||||
var version = '0.5.8';
|
||||
var urlvars = null;
|
||||
var amtstack;
|
||||
var wsstack = null;
|
||||
|
10
public/samples/relay.htm
Normal file
10
public/samples/relay.htm
Normal file
@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript" src="relay.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
var relay = createMeshConnection('0D49FDEFFB778D40C062DD34A3E96113:1485387591408:b2970207326684b4de5375d097db23c85e64497eaa72013b56a8ecd8063fb9b3').connect();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
48
public/samples/relay.js
Normal file
48
public/samples/relay.js
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @fileoverview Dynamic interface to MeshCentral2
|
||||
* @author Ylian Saint-Hilaire
|
||||
* @version v0.0.1
|
||||
*/
|
||||
|
||||
var createMeshConnection = function (connectionId) {
|
||||
var obj = {};
|
||||
obj.connectionId = connectionId;
|
||||
obj.state = 0;
|
||||
obj.websocket = null;
|
||||
obj.onStateChanged = null;
|
||||
obj.onData = null;
|
||||
|
||||
obj.connect = function () {
|
||||
if (obj.state == 0) {
|
||||
obj.websocket = new WebSocket(window.location.protocol.replace('http', 'ws') + '//' + window.location.host + '/meshrelay.ashx?id=' + obj.connectionId);
|
||||
obj.websocket.binaryType = "arraybuffer";
|
||||
obj.websocket.onopen = function (e) { console.log('WebSocket Connected', e); };
|
||||
obj.websocket.onmessage = function (e) {
|
||||
console.log('WebSocket Message', e);
|
||||
if ((obj.state = 1) && (e.data == 'c')) {
|
||||
obj.state = 2;
|
||||
if (obj.onStateChanged) { onStateChanged(obj, 2); }
|
||||
console.log('WebSocket Peer Connection', e);
|
||||
obj.send('bob');
|
||||
} else {
|
||||
if (obj.onData != null) { obj.onData(obj, e.data); }
|
||||
}
|
||||
};
|
||||
obj.websocket.onclose = function (e) {
|
||||
console.log('WebSocket Closed', e);
|
||||
obj.state = 0;
|
||||
if (obj.onStateChanged) { onStateChanged(obj, 0); }
|
||||
};
|
||||
obj.websocket.onerror = function (e) { console.log('WebSocket Error', e); };
|
||||
obj.state = 1;
|
||||
if (obj.onStateChanged) { onStateChanged(obj, 1); }
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
obj.send = function (data) {
|
||||
if ((obj.state == 2) && (obj.websocket != null)) { obj.websocket.send(data); }
|
||||
};
|
||||
|
||||
return obj;
|
||||
}
|
@ -93,15 +93,18 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) {
|
||||
obj.ProcessPictureMsg = function (str, X, Y) {
|
||||
//if (obj.targetnode != null) obj.Debug("ProcessPictureMsg " + X + "," + Y + " - " + obj.targetnode.substring(0, 8));
|
||||
var tile = new Image();
|
||||
obj.tilesReceived++;
|
||||
tile.xcount = obj.tilesReceived++;
|
||||
//console.log('Tile #' + tile.xcount);
|
||||
var r = obj.tilesReceived;
|
||||
tile.src = "data:image/jpeg;base64," + btoa(str.substring(4, str.length));
|
||||
tile.onload = function () {
|
||||
//console.log('DecodeTile #' + this.xcount);
|
||||
if (obj.Canvas != null && obj.KillDraw < r && obj.State != 0) {
|
||||
obj.PendingOperations.push([r, 2, tile, X, Y]);
|
||||
while (obj.DoPendingOperations()) { }
|
||||
}
|
||||
}
|
||||
tile.error = function () { console.log('DecodeTileError'); }
|
||||
}
|
||||
|
||||
obj.DoPendingOperations = function () {
|
||||
|
@ -50,17 +50,25 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
|
||||
|
||||
// Called to pass websocket control messages
|
||||
obj.xxOnControlCommand = function (msg) {
|
||||
var controlMsg = JSON.parse(msg);
|
||||
if ((controlMsg.type == 'answer') && (obj.webrtc != null)) {
|
||||
//console.log('gotAnswer', JSON.stringify(controlMsg));
|
||||
obj.webrtc.setRemoteDescription(new RTCSessionDescription(controlMsg), function () { /*console.log('WebRTC remote ok');*/ }, obj.xxCloseWebRTC);
|
||||
var controlMsg;
|
||||
try { controlMsg = JSON.parse(msg); } catch (e) { return; }
|
||||
if (obj.webrtc != null) {
|
||||
if (controlMsg.type == 'answer') {
|
||||
obj.webrtc.setRemoteDescription(new RTCSessionDescription(controlMsg), function () { /*console.log('WebRTC remote ok');*/ }, obj.xxCloseWebRTC);
|
||||
} else if (controlMsg.type == 'webrtc1') {
|
||||
obj.socket.send("{\"type\":\"webrtc2\"}"); // Confirm we got end of data marker, indicates data will no longer be received on websocket.
|
||||
} else if (controlMsg.type == 'webrtc2') {
|
||||
// TODO: Resume/Start sending data over WebRTC
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close the WebRTC connection, should be called if a problem occurs during WebRTC setup.
|
||||
obj.xxCloseWebRTC = function () {
|
||||
if (obj.webchannel != null) { obj.webchannel.close(); obj.webchannel = null; }
|
||||
if (obj.webrtc != null) { obj.webrtc.close(); obj.webrtc = null; }
|
||||
try { obj.webchannel.send("{\"type\":\"close\"}"); } catch (e) { }
|
||||
if (obj.webchannel != null) { try { obj.webchannel.close(); } catch (e) { } obj.webchannel = null; }
|
||||
if (obj.webrtc != null) { try { obj.webrtc.close(); } catch (e) { } obj.webrtc = null; }
|
||||
obj.webRtcActive = false;
|
||||
}
|
||||
|
||||
obj.xxOnMessage = function (e) {
|
||||
@ -78,23 +86,22 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
|
||||
|
||||
if (obj.webrtc != null) {
|
||||
obj.webchannel = obj.webrtc.createDataChannel("DataChannel", {}); // { ordered: false, maxRetransmits: 2 }
|
||||
obj.webchannel.onmessage = function (event) { console.log("DataChannel - onmessage", event.data); obj.xxOnMessage(event.data); };
|
||||
obj.webchannel.onopen = function () { obj.webRtcActive = true; if (obj.onStateChanged != null) { obj.onStateChanged(obj, obj.State); } /*obj.webchannel.send("Browser WebRTC Hello!!!");*/ };
|
||||
obj.webchannel.onclose = function (event) { obj.Stop(); }
|
||||
obj.webchannel.onmessage = function (event) { obj.xxOnMessage({ data: event.data }); };
|
||||
obj.webchannel.onopen = function () {
|
||||
obj.webRtcActive = true;
|
||||
obj.socket.send("{\"type\":\"webrtc1\"}"); // Indicate to the other side that data traffic will no longer be sent over websocket.
|
||||
// TODO: Hold/Stop sending data over websocket
|
||||
if (obj.onStateChanged != null) { obj.onStateChanged(obj, obj.State); }
|
||||
};
|
||||
obj.webchannel.onclose = function (event) { console.log('WebRTC close'); obj.Stop(); }
|
||||
obj.webrtc.onicecandidate = function (e) {
|
||||
if (e.candidate == null) {
|
||||
//console.log('createOffer', JSON.stringify(obj.webrtcoffer));
|
||||
obj.socket.send(JSON.stringify(obj.webrtcoffer)); // End of candidates, send the offer
|
||||
} else {
|
||||
obj.webrtcoffer.sdp += ("a=" + e.candidate.candidate + "\r\n"); // New candidate, add it to the SDP
|
||||
}
|
||||
}
|
||||
obj.webrtc.oniceconnectionstatechange = function () {
|
||||
if (obj.webrtc != null) {
|
||||
//console.log('WebRTC ICE', obj.webrtc.iceConnectionState);
|
||||
if ((obj.webrtc.iceConnectionState == 'disconnected') || (obj.webrtc.iceConnectionState == 'failed')) { obj.xxCloseWebRTC(); }
|
||||
}
|
||||
}
|
||||
obj.webrtc.oniceconnectionstatechange = function () { if (obj.webrtc != null) { if ((obj.webrtc.iceConnectionState == 'disconnected') || (obj.webrtc.iceConnectionState == 'failed')) { obj.xxCloseWebRTC(); } } }
|
||||
obj.webrtc.createOffer(function (offer) {
|
||||
// Got the offer
|
||||
obj.webrtcoffer = offer;
|
||||
@ -189,13 +196,14 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
|
||||
obj.Stop = function (x) {
|
||||
if (obj.debugmode == 1) { console.log('stop', x); }
|
||||
//obj.debug("Agent Redir Socket Stopped");
|
||||
obj.webRtcActive = false;
|
||||
obj.webrtc = null;
|
||||
obj.webchannel = null;
|
||||
obj.xxStateChange(0);
|
||||
obj.connectstate = -1;
|
||||
obj.xxCloseWebRTC();
|
||||
if (obj.socket != null) { obj.socket.close(); obj.socket = null; }
|
||||
if (obj.socket != null) {
|
||||
try { obj.socket.send("{\"type\":\"close\"}"); } catch (e) { }
|
||||
try { obj.socket.close(); } catch (e) { }
|
||||
obj.socket = null;
|
||||
}
|
||||
obj.xxStateChange(0);
|
||||
}
|
||||
|
||||
return obj;
|
||||
|
@ -23,6 +23,8 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
obj.useZRLE = true;
|
||||
obj.showmouse = true;
|
||||
obj.buttonmask = 0;
|
||||
//obj.inbytes = 0;
|
||||
//obj.outbytes = 0;
|
||||
obj.spare = null;
|
||||
obj.sparew = 0;
|
||||
obj.spareh = 0;
|
||||
@ -33,9 +35,10 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
obj.onScreenSizeChange = null;
|
||||
obj.frameRateDelay = 0;
|
||||
// ###BEGIN###{DesktopRotation}
|
||||
obj.noMouseRotate = false;
|
||||
obj.rotation = 0;
|
||||
// ###END###{DesktopRotation}
|
||||
|
||||
|
||||
// ###BEGIN###{DesktopFocus}
|
||||
obj.mx = 0; // Last mouse x position
|
||||
obj.my = 0; // Last mouse y position
|
||||
@ -43,10 +46,13 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
obj.oy = -1; // Old mouse y position
|
||||
obj.focusmode = 0;
|
||||
// ###END###{DesktopFocus}
|
||||
|
||||
// ###BEGIN###{Inflate}
|
||||
obj.inflate = ZLIB.inflateInit(-15);
|
||||
// ###END###{Inflate}
|
||||
|
||||
// Private method
|
||||
obj.Debug = function (msg) { console.log(msg); }
|
||||
|
||||
|
||||
obj.xxStateChange = function (newstate) {
|
||||
if (newstate == 0) {
|
||||
obj.canvas.fillStyle = '#000000';
|
||||
@ -58,10 +64,12 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
if (!obj.showmouse) { QS(obj.canvasid).cursor = 'none'; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
obj.ProcessData = function (data) {
|
||||
if (!data) return;
|
||||
// obj.Debug("KRecv(" + data.length + "): " + rstr2hex(data));
|
||||
//obj.inbytes += data.length;
|
||||
//obj.Debug("KRecv(" + obj.inbytes + ")");
|
||||
obj.acc += data;
|
||||
while (obj.acc.length > 0) {
|
||||
//obj.Debug("KAcc(" + obj.acc.length + "): " + rstr2hex(obj.acc));
|
||||
@ -90,12 +98,15 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
}
|
||||
else if (obj.state == 3 && obj.acc.length >= 24) {
|
||||
// Getting server init
|
||||
// ###BEGIN###{DesktopRotation}
|
||||
obj.rotation = 0; // We don't currently support screen init while rotated.
|
||||
// ###END###{DesktopRotation}
|
||||
var namelen = ReadInt(obj.acc, 20);
|
||||
if (obj.acc.length < 24 + namelen) return;
|
||||
cmdsize = 24 + namelen;
|
||||
obj.canvas.canvas.width = obj.rwidth = obj.width = obj.ScreenWidth = ReadShort(obj.acc, 0);
|
||||
obj.canvas.canvas.height = obj.rheight = obj.height = obj.ScreenHeight = ReadShort(obj.acc, 2);
|
||||
|
||||
|
||||
// These are all values we don't really need, we are going to only run in RGB565 or RGB332 and not use the flexibility provided by these settings.
|
||||
// Makes the javascript code smaller and maybe a bit faster.
|
||||
/*
|
||||
@ -126,22 +137,22 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
var supportedEncodings = '';
|
||||
if (obj.useZRLE) supportedEncodings += IntToStr(16);
|
||||
supportedEncodings += IntToStr(0);
|
||||
|
||||
|
||||
obj.Send(String.fromCharCode(2, 0) + ShortToStr((supportedEncodings.length / 4) + 1) + supportedEncodings + IntToStr(-223)); // Supported Encodings + Desktop Size
|
||||
|
||||
|
||||
// Set the pixel encoding to something much smaller
|
||||
// obj.Send(String.fromCharCode(0, 0, 0, 0, 16, 16, 0, 1) + ShortToStr(31) + ShortToStr(63) + ShortToStr(31) + String.fromCharCode(11, 5, 0, 0, 0, 0)); // Setup 16 bit color RGB565 (This is the default, so we don't need to set it)
|
||||
if (obj.bpp == 1) obj.Send(String.fromCharCode(0, 0, 0, 0, 8, 8, 0, 1) + ShortToStr(7) + ShortToStr(7) + ShortToStr(3) + String.fromCharCode(5, 2, 0, 0, 0, 0)); // Setup 8 bit color RGB332
|
||||
|
||||
|
||||
obj.state = 4;
|
||||
obj.parent.xxStateChange(3);
|
||||
_SendRefresh();
|
||||
//obj.timer = setInterval(obj.xxOnTimer, 50);
|
||||
|
||||
|
||||
// ###BEGIN###{DesktopFocus}
|
||||
obj.ox = -1; // Old mouse x position
|
||||
// ###END###{DesktopFocus}
|
||||
|
||||
|
||||
if (obj.onScreenSizeChange != null) { obj.onScreenSizeChange(obj, obj.ScreenWidth, obj.ScreenHeight); }
|
||||
}
|
||||
else if (obj.state == 4) {
|
||||
@ -161,10 +172,10 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
height = ReadShort(obj.acc, 6),
|
||||
s = width * height,
|
||||
encoding = ReadInt(obj.acc, 8);
|
||||
|
||||
|
||||
if (encoding < 17) {
|
||||
if (width < 1 || width > 64 || height < 1 || height > 64) { console.log("Invalid tile size (" + width + "," + height + "), disconnecting."); return obj.Stop(); }
|
||||
|
||||
|
||||
// Set the spare bitmap to the rigth size if it's not already. This allows us to recycle the spare most if not all the time.
|
||||
if (obj.sparew != width || obj.spareh != height) {
|
||||
obj.sparew = obj.sparew2 = width;
|
||||
@ -178,7 +189,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (encoding == 0xFFFFFF21) {
|
||||
// Desktop Size (0xFFFFFF21, -223)
|
||||
obj.canvas.canvas.width = obj.rwidth = obj.width = width;
|
||||
@ -193,7 +204,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
var ptr = 12, cs = 12 + (s * obj.bpp);
|
||||
if (obj.acc.length < cs) return; // Check we have all the data needed and we can only draw 64x64 tiles.
|
||||
cmdsize = cs;
|
||||
|
||||
|
||||
// CRITICAL LOOP, optimize this as much as possible
|
||||
for (var i = 0; i < s; i++) { _setPixel(obj.acc.charCodeAt(ptr++) + ((obj.bpp == 2) ? (obj.acc.charCodeAt(ptr++) << 8) : 0), i); }
|
||||
_putImage(obj.spare, x, y);
|
||||
@ -205,23 +216,22 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
if (obj.acc.length < (16 + datalen)) return;
|
||||
//obj.Debug("RECT ZRLE (" + x + "," + y + "," + width + "," + height + ") LEN = " + datalen);
|
||||
//obj.Debug("RECT ZRLE LEN: " + ReadShortX(obj.acc, 17) + ", DATA: " + rstr2hex(obj.acc.substring(16)));
|
||||
|
||||
|
||||
// Process the ZLib header if this is the first block
|
||||
var ptr = 16, delta = 5, dx = 0;
|
||||
if (obj.ZRLEfirst == 1) { obj.ZRLEfirst = 0; ptr += 2; delta = 7; dx = 2; } // Skip the ZLib header
|
||||
|
||||
|
||||
if (datalen > 5 && obj.acc.charCodeAt(ptr) == 0 && ReadShortX(obj.acc, ptr + 1) == (datalen - delta)) {
|
||||
// This is an uncompressed ZLib data block
|
||||
_decodeLRE(obj.acc, ptr + 5, x, y, width, height, s, datalen);
|
||||
}
|
||||
// ###BEGIN###{Inflate}
|
||||
// ###BEGIN###{Inflate}
|
||||
else {
|
||||
// This is compressed ZLib data, decompress and process it.
|
||||
var arr = inflate(obj.acc.substring(ptr, ptr + datalen - dx));
|
||||
if (arr.length > 0) { _decodeLRE(String.fromCharCode.apply(null, new Uint8Array(arr)), 0, x, y, width, height, s, arr.length); } else { obj.Debug("Invalid deflate data"); }
|
||||
var arr = obj.inflate.inflate(obj.acc.substring(ptr, ptr + datalen - dx));
|
||||
if (arr.length > 0) { _decodeLRE(arr, 0, x, y, width, height, s, arr.length); } else { obj.Debug("Invalid deflate data"); }
|
||||
}
|
||||
// ###END###{Inflate}
|
||||
|
||||
|
||||
cmdsize = 16 + datalen;
|
||||
}
|
||||
else {
|
||||
@ -237,12 +247,12 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (cmdsize == 0) return;
|
||||
obj.acc = obj.acc.substring(cmdsize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _decodeLRE(data, ptr, x, y, width, height, s, datalen) {
|
||||
var subencoding = data.charCodeAt(ptr++), index, v, runlengthdecode, palette = {}, rlecount = 0, runlength = 0, i;
|
||||
// obj.Debug("RECT RLE (" + (datalen - 5) + ", " + subencoding + "):" + rstr2hex(data.substring(21, 21 + (datalen - 5))));
|
||||
@ -255,23 +265,23 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
// Solid color tile
|
||||
v = data.charCodeAt(ptr++) + ((obj.bpp == 2) ? (data.charCodeAt(ptr++) << 8) : 0);
|
||||
obj.canvas.fillStyle = 'rgb(' + ((obj.bpp == 1) ? ((v & 224) + ',' + ((v & 28) << 3) + ',' + _fixColor((v & 3) << 6)) : (((v >> 8) & 248) + ',' + ((v >> 3) & 252) + ',' + ((v & 31) << 3))) + ')';
|
||||
|
||||
|
||||
// ###BEGIN###{DesktopRotation}
|
||||
var xx = _rotX(x, y);
|
||||
y = _rotY(x, y);
|
||||
x = xx;
|
||||
// ###END###{DesktopRotation}
|
||||
|
||||
|
||||
obj.canvas.fillRect(x, y, width, height);
|
||||
}
|
||||
else if (subencoding > 1 && subencoding < 17) { // Packed palette encoded tile
|
||||
// Read the palette
|
||||
var br = 4, bm = 15; // br is BitRead and bm is BitMask. By adjusting these two we can support all the variations in this encoding.
|
||||
for (i = 0; i < subencoding; i++) { palette[i] = data.charCodeAt(ptr++) + ((obj.bpp == 2) ? (data.charCodeAt(ptr++) << 8) : 0); }
|
||||
|
||||
|
||||
// Compute bits to read & bit mark
|
||||
if (subencoding == 2) { br = 1; bm = 1; } else if (subencoding <= 4) { br = 2; bm = 3; }
|
||||
|
||||
|
||||
// Display all the bits
|
||||
while (rlecount < s && ptr < data.length) { v = data.charCodeAt(ptr++); for (i = (8 - br) ; i >= 0; i -= br) { _setPixel(palette[(v >> i) & bm], rlecount++); } }
|
||||
_putImage(obj.spare, x, y);
|
||||
@ -280,10 +290,10 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
while (rlecount < s && ptr < data.length) {
|
||||
// Get the run color
|
||||
v = data.charCodeAt(ptr++) + ((obj.bpp == 2) ? (data.charCodeAt(ptr++) << 8) : 0);
|
||||
|
||||
|
||||
// Decode the run length. This is the fastest and most compact way I found to do this.
|
||||
runlength = 1; do { runlength += (runlengthdecode = data.charCodeAt(ptr++)); } while (runlengthdecode == 255);
|
||||
|
||||
|
||||
// Draw a run
|
||||
while (--runlength >= 0) { _setPixel(v, rlecount++); }
|
||||
}
|
||||
@ -292,22 +302,22 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
else if (subencoding > 129) { // Palette RLE encoded tile
|
||||
// Read the palette
|
||||
for (i = 0; i < (subencoding - 128) ; i++) { palette[i] = data.charCodeAt(ptr++) + ((obj.bpp == 2) ? (data.charCodeAt(ptr++) << 8) : 0); }
|
||||
|
||||
|
||||
// Decode RLE on palette
|
||||
while (rlecount < s && ptr < data.length) {
|
||||
// Setup the run, get the color index and get the color from the palette.
|
||||
runlength = 1; index = data.charCodeAt(ptr++); v = palette[index % 128];
|
||||
|
||||
|
||||
// If the index starts with high order bit 1, this is a run and decode the run length.
|
||||
if (index > 127) { do { runlength += (runlengthdecode = data.charCodeAt(ptr++)); } while (runlengthdecode == 255); }
|
||||
|
||||
|
||||
// Draw a run
|
||||
while (--runlength >= 0) { _setPixel(v, rlecount++); }
|
||||
}
|
||||
_putImage(obj.spare, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _putImage(i, x, y) {
|
||||
// ###BEGIN###{DesktopRotation}
|
||||
var xx = _arotX(x, y);
|
||||
@ -316,10 +326,10 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
// ###END###{DesktopRotation}
|
||||
obj.canvas.putImageData(i, x, y);
|
||||
}
|
||||
|
||||
|
||||
function _setPixel(v, p) {
|
||||
var pp = p * 4;
|
||||
|
||||
|
||||
// ###BEGIN###{DesktopRotation}
|
||||
if (obj.rotation > 0) {
|
||||
if (obj.rotation == 1) {
|
||||
@ -337,7 +347,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
}
|
||||
}
|
||||
// ###END###{DesktopRotation}
|
||||
|
||||
|
||||
if (obj.bpp == 1) {
|
||||
// Set 8bit color RGB332
|
||||
obj.spare.data[pp++] = v & 224;
|
||||
@ -351,7 +361,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
}
|
||||
obj.spare.data[pp] = 0xFF; // Set alpha channel to opaque.
|
||||
}
|
||||
|
||||
|
||||
// ###BEGIN###{DesktopRotation}
|
||||
function _arotX(x, y) {
|
||||
if (obj.rotation == 0) return x;
|
||||
@ -360,7 +370,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
if (obj.rotation == 3) return y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function _arotY(x, y) {
|
||||
if (obj.rotation == 0) return y;
|
||||
if (obj.rotation == 1) return x;
|
||||
@ -368,7 +378,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
if (obj.rotation == 3) return obj.canvas.canvas.height - obj.spareh - x;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function _crotX(x, y) {
|
||||
if (obj.rotation == 0) return x;
|
||||
if (obj.rotation == 1) return y;
|
||||
@ -376,7 +386,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
if (obj.rotation == 3) return obj.canvas.canvas.height - y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function _crotY(x, y) {
|
||||
if (obj.rotation == 0) return y;
|
||||
if (obj.rotation == 1) return obj.canvas.canvas.width - x;
|
||||
@ -384,7 +394,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
if (obj.rotation == 3) return x;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function _rotX(x, y) {
|
||||
if (obj.rotation == 0) return x;
|
||||
if (obj.rotation == 1) return x;
|
||||
@ -392,7 +402,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
if (obj.rotation == 3) return x - obj.canvas.canvas.height;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function _rotY(x, y) {
|
||||
if (obj.rotation == 0) return y;
|
||||
if (obj.rotation == 1) return y - obj.canvas.canvas.width;
|
||||
@ -400,7 +410,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
if (obj.rotation == 3) return y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
obj.tcanvas = null;
|
||||
obj.setRotation = function (x) {
|
||||
while (x < 0) { x += 4; }
|
||||
@ -409,7 +419,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
var rw = obj.canvas.canvas.width;
|
||||
var rh = obj.canvas.canvas.height;
|
||||
if (obj.rotation == 1 || obj.rotation == 3) { rw = obj.canvas.canvas.height; rh = obj.canvas.canvas.width; }
|
||||
|
||||
|
||||
// Copy the canvas, put it back in the correct direction
|
||||
if (obj.tcanvas == null) obj.tcanvas = document.createElement('canvas');
|
||||
var tcanvasctx = obj.tcanvas.getContext('2d');
|
||||
@ -421,7 +431,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
if (obj.rotation == 1) tcanvasctx.drawImage(obj.canvas.canvas, -obj.canvas.canvas.width, 0);
|
||||
if (obj.rotation == 2) tcanvasctx.drawImage(obj.canvas.canvas, -obj.canvas.canvas.width, -obj.canvas.canvas.height);
|
||||
if (obj.rotation == 3) tcanvasctx.drawImage(obj.canvas.canvas, 0, -obj.canvas.canvas.height);
|
||||
|
||||
|
||||
// Change the size and orientation and copy the canvas back into the rotation
|
||||
if (obj.rotation == 0 || obj.rotation == 2) { obj.canvas.canvas.height = rw; obj.canvas.canvas.width = rh; }
|
||||
if (obj.rotation == 1 || obj.rotation == 3) { obj.canvas.canvas.height = rh; obj.canvas.canvas.width = rw; }
|
||||
@ -429,16 +439,16 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
obj.canvas.rotate((newrotation * 90) * Math.PI / 180);
|
||||
obj.rotation = newrotation;
|
||||
obj.canvas.drawImage(obj.tcanvas, _rotX(0, 0), _rotY(0, 0));
|
||||
|
||||
|
||||
obj.width = obj.canvas.canvas.width;
|
||||
obj.height = obj.canvas.canvas.height;
|
||||
if (obj.onScreenResize != null) obj.onScreenResize(obj, obj.width, obj.height, obj.CanvasId);
|
||||
return true;
|
||||
}
|
||||
// ###END###{DesktopRotation}
|
||||
|
||||
|
||||
function _fixColor(c) { return (c > 127) ? (c + 32) : c; }
|
||||
|
||||
|
||||
function _SendRefresh() {
|
||||
// ###BEGIN###{DesktopFocus}
|
||||
if (obj.focusmode > 0) {
|
||||
@ -447,34 +457,40 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
obj.Send(String.fromCharCode(3, 1) + ShortToStr(Math.max(Math.min(obj.ox, obj.mx) - obj.focusmode, 0)) + ShortToStr(Math.max(Math.min(obj.oy, obj.my) - obj.focusmode, 0)) + ShortToStr(df + Math.abs(obj.ox - obj.mx)) + ShortToStr(df + Math.abs(obj.oy - obj.my))); // FramebufferUpdateRequest
|
||||
obj.ox = obj.mx;
|
||||
obj.oy = obj.my;
|
||||
} else
|
||||
// ###END###{DesktopFocus} {
|
||||
} else {
|
||||
// ###END###{DesktopFocus}
|
||||
// Request the entire screen
|
||||
obj.Send(String.fromCharCode(3, 1, 0, 0, 0, 0) + ShortToStr(obj.rwidth) + ShortToStr(obj.rheight)); // FramebufferUpdateRequest
|
||||
// ###BEGIN###{DesktopFocus}
|
||||
}
|
||||
// ###END###{DesktopFocus}
|
||||
}
|
||||
|
||||
|
||||
obj.Start = function () {
|
||||
//obj.Debug("KVM-Start");
|
||||
obj.state = 0;
|
||||
obj.acc = "";
|
||||
obj.ZRLEfirst = 1;
|
||||
//obj.inbytes = 0;
|
||||
//obj.outbytes = 0;
|
||||
// ###BEGIN###{Inflate}
|
||||
inflate_start();
|
||||
obj.inflate.inflateReset();
|
||||
// ###END###{Inflate}
|
||||
for (var i in obj.sparecache) { delete obj.sparecache[i]; }
|
||||
}
|
||||
|
||||
|
||||
obj.Stop = function () {
|
||||
obj.UnGrabMouseInput();
|
||||
obj.UnGrabKeyInput();
|
||||
obj.parent.Stop();
|
||||
}
|
||||
|
||||
|
||||
obj.Send = function (x) {
|
||||
//obj.Debug("KSend(" + x.length + "): " + rstr2hex(x));
|
||||
//obj.outbytes += x.length;
|
||||
obj.parent.Send(x);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Intel AMT only recognizes a small subset of keysym characters defined in the keysymdef.h so you don’t need to
|
||||
implement all the languages (this is taken care by the USB Scancode Extension in RFB4.0 protocol).
|
||||
@ -535,9 +551,9 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
obj.sendkey(kk, d);
|
||||
return obj.haltEvent(e);
|
||||
}
|
||||
|
||||
|
||||
obj.sendkey = function (k, d) { obj.Send(String.fromCharCode(4, d, 0, 0) + IntToStr(k)); }
|
||||
|
||||
|
||||
obj.SendCtrlAltDelMsg = function () { obj.sendcad(); }
|
||||
obj.sendcad = function () {
|
||||
obj.sendkey(0xFFE3, 1); // Control
|
||||
@ -547,10 +563,10 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
obj.sendkey(0xFFE9, 0); // Alt
|
||||
obj.sendkey(0xFFE3, 0); // Control
|
||||
}
|
||||
|
||||
|
||||
var _MouseInputGrab = false;
|
||||
var _KeyInputGrab = false;
|
||||
|
||||
|
||||
obj.GrabMouseInput = function () {
|
||||
if (_MouseInputGrab == true) return;
|
||||
var c = obj.canvas.canvas;
|
||||
@ -560,7 +576,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
//if (navigator.userAgent.match(/mozilla/i)) c.DOMMouseScroll = obj.xxDOMMouseScroll; else c.onmousewheel = obj.xxMouseWheel;
|
||||
_MouseInputGrab = true;
|
||||
}
|
||||
|
||||
|
||||
obj.UnGrabMouseInput = function () {
|
||||
if (_MouseInputGrab == false) return;
|
||||
var c = obj.canvas.canvas;
|
||||
@ -570,7 +586,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
//if (navigator.userAgent.match(/mozilla/i)) c.DOMMouseScroll = null; else c.onmousewheel = null;
|
||||
_MouseInputGrab = false;
|
||||
}
|
||||
|
||||
|
||||
obj.GrabKeyInput = function () {
|
||||
if (_KeyInputGrab == true) return;
|
||||
document.onkeyup = obj.handleKeyUp;
|
||||
@ -578,7 +594,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
document.onkeypress = obj.handleKeys;
|
||||
_KeyInputGrab = true;
|
||||
}
|
||||
|
||||
|
||||
obj.UnGrabKeyInput = function () {
|
||||
if (_KeyInputGrab == false) return;
|
||||
document.onkeyup = null;
|
||||
@ -586,12 +602,12 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
document.onkeypress = null;
|
||||
_KeyInputGrab = false;
|
||||
}
|
||||
|
||||
|
||||
obj.handleKeys = function (e) { return obj.haltEvent(e); }
|
||||
obj.handleKeyUp = function (e) { return _keyevent(0, e); }
|
||||
obj.handleKeyDown = function (e) { return _keyevent(1, e); }
|
||||
obj.haltEvent = function (e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
|
||||
|
||||
|
||||
// RFB "PointerEvent" and mouse handlers
|
||||
obj.mousedown = function (e) { obj.buttonmask |= (1 << e.button); return obj.mousemove(e); }
|
||||
obj.mouseup = function (e) { obj.buttonmask &= (0xFFFF - (1 << e.button)); return obj.mousemove(e); }
|
||||
@ -600,15 +616,17 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
var pos = obj.getPositionOfControl(Q(obj.canvasid));
|
||||
obj.mx = (e.pageX - pos[0]) * (obj.canvas.canvas.height / Q(obj.canvasid).offsetHeight);
|
||||
obj.my = ((e.pageY - pos[1] + (scrolldiv ? scrolldiv.scrollTop : 0)) * (obj.canvas.canvas.width / Q(obj.canvasid).offsetWidth));
|
||||
|
||||
|
||||
// ###BEGIN###{DesktopRotation}
|
||||
obj.mx2 = _crotX(obj.mx, obj.my);
|
||||
obj.my = _crotY(obj.mx, obj.my);
|
||||
obj.mx = obj.mx2;
|
||||
if (obj.noMouseRotate != true) {
|
||||
obj.mx2 = _crotX(obj.mx, obj.my);
|
||||
obj.my = _crotY(obj.mx, obj.my);
|
||||
obj.mx = obj.mx2;
|
||||
}
|
||||
// ###END###{DesktopRotation}
|
||||
|
||||
|
||||
obj.Send(String.fromCharCode(5, obj.buttonmask) + ShortToStr(obj.mx) + ShortToStr(obj.my));
|
||||
|
||||
|
||||
// ###BEGIN###{DesktopFocus}
|
||||
// Update focus area if we are in focus mode
|
||||
QV('DeskFocus', obj.focusmode);
|
||||
@ -627,11 +645,10 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
q.height = ((df * qx) - 6) + 'px';
|
||||
}
|
||||
// ###END###{DesktopFocus}
|
||||
|
||||
|
||||
return obj.haltEvent(e);
|
||||
}
|
||||
obj.mousewheel = function (e) { }
|
||||
|
||||
|
||||
obj.getPositionOfControl = function (Control) {
|
||||
var Position = Array(2);
|
||||
Position[0] = Position[1] = 0;
|
||||
@ -642,6 +659,6 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
}
|
||||
return Position;
|
||||
}
|
||||
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
279
public/scripts/zlib-adler32.js
Normal file
279
public/scripts/zlib-adler32.js
Normal file
@ -0,0 +1,279 @@
|
||||
/* zlib-adler32.js -- JavaScript implementation for the zlib adler32.
|
||||
Version: 0.2.0
|
||||
LastModified: Apr 12 2012
|
||||
Copyright (C) 2012 Masanao Izumo <iz@onicos.co.jp>
|
||||
|
||||
API documentation
|
||||
==============================================================================
|
||||
Usage: adler = ZLIB.adler32(adler, buf, offset, len);
|
||||
|
||||
Update a running Adler-32 checksum with the bytes buf[offset..offset+len-1] and
|
||||
return the updated checksum. If buf is null, this function returns the
|
||||
required initial value for the checksum.
|
||||
|
||||
An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
|
||||
much faster.
|
||||
|
||||
Usage example:
|
||||
|
||||
var adler = ZLIB.adler32(0, null, 0, 0);
|
||||
|
||||
while (read_buffer(buffer, length) != EOF) {
|
||||
adler = ZLIB.adler32(adler, buffer, 0, length);
|
||||
}
|
||||
if (adler != original_adler) error();
|
||||
|
||||
==============================================================================
|
||||
Usage: adler = ZLIB.adler32_combine(adler1, adler2, len2);
|
||||
|
||||
Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
|
||||
and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
|
||||
each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
|
||||
seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note
|
||||
that the z_off_t type (like off_t) is a signed integer. If len2 is
|
||||
negative, the result has no meaning or utility.
|
||||
*/
|
||||
|
||||
if( typeof ZLIB === 'undefined' ) {
|
||||
alert('ZLIB is not defined. SRC zlib.js before zlib-adler32.js')
|
||||
}
|
||||
|
||||
(function() {
|
||||
|
||||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2011 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
var BASE = 65521; /* largest prime smaller than 65536 */
|
||||
var NMAX = 5552;
|
||||
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||
|
||||
/* ========================================================================= */
|
||||
function adler32_string(adler, buf, offset, len)
|
||||
{
|
||||
var sum2;
|
||||
var n;
|
||||
|
||||
/* split Adler-32 into component sums */
|
||||
sum2 = (adler >>> 16) & 0xffff;
|
||||
adler &= 0xffff;
|
||||
|
||||
/* in case user likes doing a byte at a time, keep it fast */
|
||||
if (len == 1) {
|
||||
adler += buf.charCodeAt(offset) & 0xff;
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 += adler;
|
||||
if (sum2 >= BASE)
|
||||
sum2 -= BASE;
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* initial Adler-32 value (deferred check for len == 1 speed) */
|
||||
if (buf === null)
|
||||
return 1;
|
||||
|
||||
/* in case short lengths are provided, keep it somewhat fast */
|
||||
if (len < 16) {
|
||||
while (len--) {
|
||||
adler += buf.charCodeAt(offset++) & 0xff;
|
||||
sum2 += adler;
|
||||
}
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 %= BASE; /* only added so many BASE's */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* do length NMAX blocks -- requires just one modulo operation */
|
||||
while (len >= NMAX) {
|
||||
len -= NMAX;
|
||||
n = NMAX >> 4; /* NMAX is divisible by 16 */
|
||||
do {
|
||||
/* 16 sums unrolled */
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
} while (--n);
|
||||
adler %= BASE;
|
||||
sum2 %= BASE;
|
||||
}
|
||||
|
||||
/* do remaining bytes (less than NMAX, still just one modulo) */
|
||||
if (len) { /* avoid modulos if none remaining */
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
}
|
||||
while (len--) {
|
||||
adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
|
||||
}
|
||||
adler %= BASE;
|
||||
sum2 %= BASE;
|
||||
}
|
||||
|
||||
/* return recombined sums */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
function adler32_array(adler, buf, offset, len)
|
||||
{
|
||||
var sum2;
|
||||
var n;
|
||||
|
||||
/* split Adler-32 into component sums */
|
||||
sum2 = (adler >>> 16) & 0xffff;
|
||||
adler &= 0xffff;
|
||||
|
||||
/* in case user likes doing a byte at a time, keep it fast */
|
||||
if (len == 1) {
|
||||
adler += buf[offset];
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 += adler;
|
||||
if (sum2 >= BASE)
|
||||
sum2 -= BASE;
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* initial Adler-32 value (deferred check for len == 1 speed) */
|
||||
if (buf === null)
|
||||
return 1;
|
||||
|
||||
/* in case short lengths are provided, keep it somewhat fast */
|
||||
if (len < 16) {
|
||||
while (len--) {
|
||||
adler += buf[offset++];
|
||||
sum2 += adler;
|
||||
}
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 %= BASE; /* only added so many BASE's */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* do length NMAX blocks -- requires just one modulo operation */
|
||||
while (len >= NMAX) {
|
||||
len -= NMAX;
|
||||
n = NMAX >> 4; /* NMAX is divisible by 16 */
|
||||
do {
|
||||
/* 16 sums unrolled */
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
} while (--n);
|
||||
adler %= BASE;
|
||||
sum2 %= BASE;
|
||||
}
|
||||
|
||||
/* do remaining bytes (less than NMAX, still just one modulo) */
|
||||
if (len) { /* avoid modulos if none remaining */
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
}
|
||||
while (len--) {
|
||||
adler += buf[offset++]; sum2 += adler;
|
||||
}
|
||||
adler %= BASE;
|
||||
sum2 %= BASE;
|
||||
}
|
||||
|
||||
/* return recombined sums */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
ZLIB.adler32 = function(adler, buf, offset, len)
|
||||
{
|
||||
if(typeof buf === 'string') {
|
||||
return adler32_string(adler, buf, offset, len);
|
||||
} else {
|
||||
return adler32_array(adler, buf, offset, len);
|
||||
}
|
||||
};
|
||||
|
||||
ZLIB.adler32_combine = function(adler1, adler2, len2)
|
||||
{
|
||||
var sum1;
|
||||
var sum2;
|
||||
var rem;
|
||||
|
||||
/* for negative len, return invalid adler32 as a clue for debugging */
|
||||
if (len2 < 0)
|
||||
return 0xffffffff;
|
||||
|
||||
/* the derivation of this formula is left as an exercise for the reader */
|
||||
len2 %= BASE; /* assumes len2 >= 0 */
|
||||
rem = len2;
|
||||
sum1 = adler1 & 0xffff;
|
||||
sum2 = rem * sum1;
|
||||
sum2 %= BASE;
|
||||
sum1 += (adler2 & 0xffff) + BASE - 1;
|
||||
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
|
||||
if (sum1 >= BASE) sum1 -= BASE;
|
||||
if (sum1 >= BASE) sum1 -= BASE;
|
||||
if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
|
||||
if (sum2 >= BASE) sum2 -= BASE;
|
||||
return sum1 | (sum2 << 16);
|
||||
}
|
||||
|
||||
}());
|
246
public/scripts/zlib-crc32.js
Normal file
246
public/scripts/zlib-crc32.js
Normal file
@ -0,0 +1,246 @@
|
||||
/* zlib-adler32.js -- JavaScript implementation for the zlib crc32.
|
||||
Version: 0.2.0
|
||||
LastModified: Apr 12 2012
|
||||
Copyright (C) 2012 Masanao Izumo <iz@onicos.co.jp>
|
||||
|
||||
API documentation
|
||||
==============================================================================
|
||||
Usage: crc = ZLIB.crc32(crc, buf, offset, len);
|
||||
|
||||
Update a running CRC-32 with the bytes buf[offset..offset+len-1] and return the
|
||||
updated CRC-32. If buf is null, this function returns the required
|
||||
initial value for the for the crc. Pre- and post-conditioning (one's
|
||||
complement) is performed within this function so it shouldn't be done by the
|
||||
application.
|
||||
|
||||
Usage example:
|
||||
|
||||
var crc = ZLIB.crc32(0, null, 0, 0);
|
||||
|
||||
while (read_buffer(buffer, length) != EOF) {
|
||||
crc = ZLIB.crc32(crc, buffer, 0, length);
|
||||
}
|
||||
if (crc != original_crc) error();
|
||||
|
||||
==============================================================================
|
||||
Usage: crc = crc32_combine(crc1, crc2, len2);
|
||||
|
||||
Combine two CRC-32 check values into one. For two sequences of bytes,
|
||||
seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
|
||||
calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
|
||||
check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
|
||||
len2.
|
||||
*/
|
||||
|
||||
if( typeof ZLIB === 'undefined' ) {
|
||||
alert('ZLIB is not defined. SRC zlib.js before zlib-crc32.js')
|
||||
}
|
||||
|
||||
(function() {
|
||||
|
||||
/* crc32.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-2006, 2010, 2011 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
|
||||
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
|
||||
* tables for updating the shift register in one step with three exclusive-ors
|
||||
* instead of four steps with four exclusive-ors. This results in about a
|
||||
* factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
|
||||
*/
|
||||
|
||||
var crc_table = [
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
|
||||
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
|
||||
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
|
||||
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
|
||||
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
|
||||
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
|
||||
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
|
||||
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
|
||||
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
|
||||
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
|
||||
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
|
||||
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
|
||||
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
|
||||
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
|
||||
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
|
||||
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
|
||||
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
|
||||
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
|
||||
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
|
||||
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
|
||||
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
|
||||
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
|
||||
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
|
||||
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
|
||||
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
|
||||
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
|
||||
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
|
||||
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
|
||||
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
|
||||
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
|
||||
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
|
||||
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
|
||||
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
|
||||
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
|
||||
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
|
||||
0x2d02ef8d ];
|
||||
|
||||
/* ========================================================================= */
|
||||
function crc32_string(crc, buf, offset, len)
|
||||
{
|
||||
if (buf == null) return 0;
|
||||
|
||||
crc = crc ^ 0xffffffff;
|
||||
while (len >= 8) {
|
||||
crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
|
||||
crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
|
||||
crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
|
||||
crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
|
||||
crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
|
||||
crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
|
||||
crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
|
||||
crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
|
||||
len -= 8;
|
||||
}
|
||||
if (len) do {
|
||||
crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
|
||||
} while (--len);
|
||||
return crc ^ 0xffffffff;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
function crc32_array(crc, buf, offset, len)
|
||||
{
|
||||
if (buf == null) return 0;
|
||||
|
||||
crc = crc ^ 0xffffffff;
|
||||
while (len >= 8) {
|
||||
crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
|
||||
crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
|
||||
crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
|
||||
crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
|
||||
crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
|
||||
crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
|
||||
crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
|
||||
crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
|
||||
len -= 8;
|
||||
}
|
||||
if (len) do {
|
||||
crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
|
||||
} while (--len);
|
||||
return crc ^ 0xffffffff;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
ZLIB.crc32 = function(crc, buf, offset, len)
|
||||
{
|
||||
if(typeof buf === 'string') {
|
||||
return crc32_string(crc, buf, offset, len);
|
||||
} else {
|
||||
return crc32_array(crc, buf, offset, len);
|
||||
}
|
||||
};
|
||||
|
||||
/* ========================================================================= */
|
||||
var GF2_DIM = 32; /* dimension of GF(2) vectors (length of CRC) */
|
||||
|
||||
/* ========================================================================= */
|
||||
function gf2_matrix_times(mat, vec)
|
||||
{
|
||||
var sum;
|
||||
var mat_i = 0;
|
||||
|
||||
sum = 0;
|
||||
while (vec) {
|
||||
if (vec & 1)
|
||||
sum ^= mat[mat_i];
|
||||
vec >>= 1;
|
||||
mat_i++;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
function gf2_matrix_square(square, mat)
|
||||
{
|
||||
var n;
|
||||
|
||||
for (n = 0; n < GF2_DIM; n++)
|
||||
square[n] = gf2_matrix_times(mat, mat[n]);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
ZLIB.crc32_combine = function(crc1, crc2, len2)
|
||||
{
|
||||
var n;
|
||||
var row;
|
||||
var even; /* even-power-of-two zeros operator */
|
||||
var odd; /* odd-power-of-two zeros operator */
|
||||
|
||||
/* degenerate case (also disallow negative lengths) */
|
||||
if (len2 <= 0)
|
||||
return crc1;
|
||||
|
||||
even = new Array(GF2_DIM);
|
||||
odd = new Array(GF2_DIM);
|
||||
|
||||
/* put operator for one zero bit in odd */
|
||||
odd[0] = 0xedb88320; /* CRC-32 polynomial */
|
||||
row = 1;
|
||||
for (n = 1; n < GF2_DIM; n++) {
|
||||
odd[n] = row;
|
||||
row <<= 1;
|
||||
}
|
||||
|
||||
/* put operator for two zero bits in even */
|
||||
gf2_matrix_square(even, odd);
|
||||
|
||||
/* put operator for four zero bits in odd */
|
||||
gf2_matrix_square(odd, even);
|
||||
|
||||
/* apply len2 zeros to crc1 (first square will put the operator for one
|
||||
zero byte, eight zero bits, in even) */
|
||||
do {
|
||||
/* apply zeros operator for this bit of len2 */
|
||||
gf2_matrix_square(even, odd);
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(even, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
if (len2 == 0)
|
||||
break;
|
||||
|
||||
/* another iteration of the loop with odd and even swapped */
|
||||
gf2_matrix_square(odd, even);
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(odd, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
} while (len2 != 0);
|
||||
|
||||
/* return combined crc */
|
||||
crc1 ^= crc2;
|
||||
return crc1;
|
||||
};
|
||||
|
||||
}());
|
1950
public/scripts/zlib-inflate.js
Normal file
1950
public/scripts/zlib-inflate.js
Normal file
File diff suppressed because one or more lines are too long
111
public/scripts/zlib.js
Normal file
111
public/scripts/zlib.js
Normal file
@ -0,0 +1,111 @@
|
||||
/* zlib.js -- JavaScript implementation for the zlib.
|
||||
Version: 0.2.0
|
||||
LastModified: Apr 12 2012
|
||||
Copyright (C) 2012 Masanao Izumo <iz@onicos.co.jp>
|
||||
|
||||
The original copyright notice (zlib 1.2.6):
|
||||
|
||||
Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
|
||||
The data format used by the zlib library is described by RFCs (Request for
|
||||
Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
|
||||
(zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
|
||||
*/
|
||||
|
||||
var ZLIB = ( ZLIB || {} ); // ZLIB namespace initialization
|
||||
|
||||
// common definitions
|
||||
if(typeof ZLIB.common_initialized === 'undefined') {
|
||||
ZLIB.Z_NO_FLUSH = 0;
|
||||
ZLIB.Z_PARTIAL_FLUSH = 1;
|
||||
ZLIB.Z_SYNC_FLUSH = 2;
|
||||
ZLIB.Z_FULL_FLUSH = 3;
|
||||
ZLIB.Z_FINISH = 4;
|
||||
ZLIB.Z_BLOCK = 5;
|
||||
ZLIB.Z_TREES = 6;
|
||||
/* Allowed flush values; see deflate() and inflate() below for details */
|
||||
|
||||
ZLIB.Z_OK = 0;
|
||||
ZLIB.Z_STREAM_END = 1;
|
||||
ZLIB.Z_NEED_DICT = 2;
|
||||
ZLIB.Z_ERRNO = (-1);
|
||||
ZLIB.Z_STREAM_ERROR = (-2);
|
||||
ZLIB.Z_DATA_ERROR = (-3);
|
||||
ZLIB.Z_MEM_ERROR = (-4);
|
||||
ZLIB.Z_BUF_ERROR = (-5);
|
||||
ZLIB.Z_VERSION_ERROR = (-6);
|
||||
/* Return codes for the compression/decompression functions. Negative values
|
||||
* are errors, positive values are used for special but normal events.
|
||||
*/
|
||||
|
||||
ZLIB.Z_DEFLATED = 8; /* The deflate compression method (the only one supported in this version) */
|
||||
|
||||
/**
|
||||
* z_stream constructor
|
||||
* @constructor
|
||||
*/
|
||||
ZLIB.z_stream = function() {
|
||||
this.next_in = 0; /* next input byte */
|
||||
this.avail_in = 0; /* number of bytes available in input_data */
|
||||
this.total_in = 0; /* total number of input bytes read so far */
|
||||
|
||||
this.next_out = 0; /* next output byte */
|
||||
this.avail_out = 0; /* remaining free space at next_out */
|
||||
this.total_out = 0; /* total number of bytes output so far */
|
||||
|
||||
this.msg = null; /* last error message, null if no error */
|
||||
this.state = null; /* not visible by applications */
|
||||
|
||||
this.data_type = 0; /* best guess about the data type: binary or text */
|
||||
this.adler = 0; /* TODO: adler32 value of the uncompressed data */
|
||||
|
||||
// zlib.js
|
||||
this.input_data = ''; /* input data */
|
||||
this.output_data = ''; /* output data */
|
||||
this.error = 0; /* error code */
|
||||
this.checksum_function = null; /* crc32(for gzip) or adler32(for zlib) */
|
||||
};
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @constructor
|
||||
*/
|
||||
ZLIB.gz_header = function() {
|
||||
this.text = 0; /* true if compressed data believed to be text */
|
||||
this.time = 0; /* modification time */
|
||||
this.xflags = 0; /* extra flags (not used when writing a gzip file) */
|
||||
this.os = 0xff; /* operating system */
|
||||
this.extra = null; /* extra field string or null if none */
|
||||
this.extra_len = 0; /* this.extra.length (only when reading header) */
|
||||
this.extra_max = 0; /* space at extra (only when reading header) */
|
||||
this.name = null; /* file name string or null if none */
|
||||
this.name_max = 0; /* space at name (only when reading header) */
|
||||
this.comment = null; /* comment string or null if none */
|
||||
this.comm_max = 0; /* space at comment (only when reading header) */
|
||||
this.hcrc = 0; /* true if there was or will be a header crc */
|
||||
this.done = 0; /* true when done reading gzip header (not used
|
||||
when writing a gzip file) */
|
||||
};
|
||||
|
||||
ZLIB.common_initialized = true;
|
||||
} // common definitions
|
@ -15,7 +15,10 @@
|
||||
<script type="text/javascript" src="scripts/amt-wsman-0.2.0.js"></script>
|
||||
<script type="text/javascript" src="scripts/amt-desktop-0.0.2.js"></script>
|
||||
<script type="text/javascript" src="scripts/amt-terminal-0.0.2.js"></script>
|
||||
<script type="text/javascript" src="scripts/inflate.js"></script>
|
||||
<script type="text/javascript" src="scripts/zlib.js"></script>
|
||||
<script type="text/javascript" src="scripts/zlib-inflate.js"></script>
|
||||
<script type="text/javascript" src="scripts/zlib-adler32.js"></script>
|
||||
<script type="text/javascript" src="scripts/zlib-crc32.js"></script>
|
||||
<script type="text/javascript" src="scripts/amt-redir-ws-0.1.0.js"></script>
|
||||
<script type="text/javascript" src="scripts/amt-wsman-ws-0.2.0.js"></script>
|
||||
<script type="text/javascript" src="scripts/agent-redir-ws-0.1.0.js"></script>
|
||||
@ -660,6 +663,7 @@
|
||||
// Check if we are in debug mode
|
||||
args = parseUriArgs();
|
||||
debugmode = (args.debug == 1);
|
||||
attemptWebRTC = (args.webrtc == 1);
|
||||
QV('p13AutoConnect', debugmode); // Files
|
||||
QV('autoconnectbutton2', debugmode); // Terminal
|
||||
QV('autoconnectbutton1', debugmode); // Desktop
|
||||
|
Loading…
Reference in New Issue
Block a user