Removed old Java client, added new experimental PHP client.
@@ -1,11 +0,0 @@
|
|||||||
|
|
||||||
.PHONY: client clean
|
|
||||||
|
|
||||||
all: client
|
|
||||||
|
|
||||||
client:
|
|
||||||
ant war
|
|
||||||
|
|
||||||
clean:
|
|
||||||
ant clean
|
|
||||||
|
|
@@ -1,13 +0,0 @@
|
|||||||
servlet.api.jar=/usr/share/tomcat6/lib/servlet-api.jar
|
|
||||||
|
|
||||||
src.dir=src
|
|
||||||
web.dir=web
|
|
||||||
|
|
||||||
build.dir=build
|
|
||||||
dist.dir=dist
|
|
||||||
doc.dir=doc
|
|
||||||
|
|
||||||
guac.version=0.3.0rc1
|
|
||||||
tar.dir=guacamole-${guac.version}
|
|
||||||
tar.src.dir=guacamole-src
|
|
||||||
|
|
@@ -1,77 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
|
|
||||||
<project name="guacamole" default="compile" basedir=".">
|
|
||||||
|
|
||||||
<property file="ant/build.properties"/>
|
|
||||||
|
|
||||||
<target name="clean" description="Removes build and dist dirs.">
|
|
||||||
<delete dir="${build.dir}"/>
|
|
||||||
<delete dir="${dist.dir}"/>
|
|
||||||
<delete dir="${tar.dir}"/>
|
|
||||||
<delete dir="${tar.src.dir}"/>
|
|
||||||
<delete file="${tar.dir}.tar.gz"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="init" description="Creates build and dist dirs.">
|
|
||||||
<mkdir dir="${build.dir}"/>
|
|
||||||
<mkdir dir="${build.dir}/WEB-INF/classes"/>
|
|
||||||
<mkdir dir="${dist.dir}"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="compile" description="Compiles Guacamole."
|
|
||||||
depends="init">
|
|
||||||
<copy todir="${build.dir}">
|
|
||||||
<fileset dir="${web.dir}"/>
|
|
||||||
</copy>
|
|
||||||
|
|
||||||
<!-- Replace __GUAC_VERSION with declared version -->
|
|
||||||
<replace dir="${build.dir}" value="${guac.version}">
|
|
||||||
<include name="**/*.html"/>
|
|
||||||
<replacetoken><![CDATA[__GUAC_VERSION]]></replacetoken>
|
|
||||||
</replace>
|
|
||||||
|
|
||||||
<javac srcdir="${src.dir}" destdir="${build.dir}/WEB-INF/classes"
|
|
||||||
classpath="${servlet.api.jar}">
|
|
||||||
<compilerarg value="-Xlint:unchecked"/>
|
|
||||||
</javac>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="war" description="Builds Guacamole .war file."
|
|
||||||
depends="compile">
|
|
||||||
<war destfile="${dist.dir}/guacamole.war"
|
|
||||||
webxml="${build.dir}/WEB-INF/web.xml">
|
|
||||||
<fileset dir="${build.dir}">
|
|
||||||
<exclude name="META-INF/**"/>
|
|
||||||
</fileset>
|
|
||||||
</war>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="tar" description="Build distributable .tar.gz file"
|
|
||||||
depends="war">
|
|
||||||
<mkdir dir="${tar.dir}"/>
|
|
||||||
|
|
||||||
<mkdir dir="${tar.src.dir}"/>
|
|
||||||
<copy todir="${tar.src.dir}">
|
|
||||||
<fileset dir=".">
|
|
||||||
<exclude name=".git/**"/>
|
|
||||||
<exclude name="**/.svn"/>
|
|
||||||
<exclude name="${tar.dir}/**"/>
|
|
||||||
<exclude name="${tar.src.dir}/**"/>
|
|
||||||
<exclude name="${dist.dir}/**"/>
|
|
||||||
<exclude name="${build.dir}/**"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<tar basedir="." includes="${tar.src.dir}/**" destfile="${tar.dir}/${tar.src.dir}.tar" longfile="gnu"/>
|
|
||||||
<delete dir="${tar.src.dir}"/>
|
|
||||||
|
|
||||||
<copy todir="${tar.dir}">
|
|
||||||
<fileset file="${doc.dir}/example/guacamole.xml"/>
|
|
||||||
<fileset file="${doc.dir}/example/guacamole-users.xml"/>
|
|
||||||
<fileset file="${dist.dir}/guacamole.war"/>
|
|
||||||
<fileset file="LICENSE.txt"/>
|
|
||||||
</copy>
|
|
||||||
|
|
||||||
<tar basedir="." includes="${tar.dir}/**" destfile="${tar.dir}.tar.gz" compression="gzip" longfile="gnu"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
</project>
|
|
@@ -1,6 +0,0 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
|
||||||
|
|
||||||
<tomcat-users>
|
|
||||||
<role rolename="guacamole"/>
|
|
||||||
<user username="guacamole" password="changeme" roles="guacamole"/>
|
|
||||||
</tomcat-users>
|
|
@@ -1,75 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Guacamole - Pure JavaScript/HTML VNC Client
|
|
||||||
Copyright (C) 2010 Michael Jumper
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<Context antiJARLocking="true" path="/guacamole" docBase="/var/lib/guacamole/guacamole.war">
|
|
||||||
|
|
||||||
<!-- Change the lines below to match your VNC server -->
|
|
||||||
<Parameter name="host" value="localhost"/>
|
|
||||||
<Parameter name="port" value="5900"/>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Password (VNC Authentication)
|
|
||||||
|
|
||||||
Uncomment and change the line below if your VNC server is
|
|
||||||
password protected. -->
|
|
||||||
|
|
||||||
<!--
|
|
||||||
<Parameter name="password" value="PASSWORD"/>
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Bits-per-pixel
|
|
||||||
|
|
||||||
This parameter controls what color depth should be
|
|
||||||
requested from the VNC server.
|
|
||||||
|
|
||||||
Valid values are "8", "16", or "24". -->
|
|
||||||
|
|
||||||
<!--
|
|
||||||
<Parameter name="bpp" value="24"/>
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Output (to web client) bits-per-pixel.
|
|
||||||
|
|
||||||
This parameter controls what color depth will be used
|
|
||||||
in the images sent to the web-based client.
|
|
||||||
|
|
||||||
Valid values are "8" or "24". -->
|
|
||||||
|
|
||||||
<!--
|
|
||||||
<Parameter name="output-bpp" value="24"/>
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Swap red and blue components. Some VNC servers may not honor
|
|
||||||
the client's request for certain pixel formats, instead
|
|
||||||
returning RGB as BGR.
|
|
||||||
|
|
||||||
If colors look strange (blues look red or brown) when using
|
|
||||||
Guacamole, uncomment and set this parameter to true. -->
|
|
||||||
|
|
||||||
<!--
|
|
||||||
<Parameter name="swap-red-blue" value="false"/>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<Realm className="org.apache.catalina.realm.MemoryRealm" pathname="conf/guacamole-users.xml"/>
|
|
||||||
</Context>
|
|
||||||
|
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 208 B After Width: | Height: | Size: 208 B |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 766 B After Width: | Height: | Size: 766 B |
Before Width: | Height: | Size: 71 B After Width: | Height: | Size: 71 B |
Before Width: | Height: | Size: 72 B After Width: | Height: | Size: 72 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
@@ -186,38 +186,9 @@ function VNCClient(display) {
|
|||||||
|
|
||||||
// Add event to queue, restart send loop if finished.
|
// Add event to queue, restart send loop if finished.
|
||||||
outputMessageBuffer += message;
|
outputMessageBuffer += message;
|
||||||
if (sendingMessages == 0)
|
|
||||||
sendPendingMessages();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendPendingMessages() {
|
|
||||||
|
|
||||||
if (outputMessageBuffer.length > 0) {
|
|
||||||
|
|
||||||
sendingMessages = 1;
|
|
||||||
|
|
||||||
var message_xmlhttprequest = new XMLHttpRequest();
|
|
||||||
message_xmlhttprequest.open("POST", "inbound");
|
|
||||||
message_xmlhttprequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
|
||||||
message_xmlhttprequest.setRequestHeader("Content-length", outputMessageBuffer.length);
|
|
||||||
|
|
||||||
// Once response received, send next queued event.
|
|
||||||
message_xmlhttprequest.onreadystatechange = function() {
|
|
||||||
if (message_xmlhttprequest.readyState == 4)
|
|
||||||
sendPendingMessages();
|
|
||||||
}
|
|
||||||
|
|
||||||
message_xmlhttprequest.send(outputMessageBuffer);
|
|
||||||
outputMessageBuffer = ""; // Clear buffer
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sendingMessages = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
/*** Clipboard ***/
|
/*** Clipboard ***/
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
@@ -301,7 +272,7 @@ function VNCClient(display) {
|
|||||||
function parseResponse() {
|
function parseResponse() {
|
||||||
|
|
||||||
// Start next request as soon as possible
|
// Start next request as soon as possible
|
||||||
if (xmlhttprequest.readyState >= 2 && nextRequest == null)
|
if (xmlhttprequest.readyState >= 2 && nextRequest == null && uuid)
|
||||||
nextRequest = makeRequest();
|
nextRequest = makeRequest();
|
||||||
|
|
||||||
// Parse stream when data is received and when complete.
|
// Parse stream when data is received and when complete.
|
||||||
@@ -378,10 +349,19 @@ function VNCClient(display) {
|
|||||||
|
|
||||||
function makeRequest() {
|
function makeRequest() {
|
||||||
|
|
||||||
|
if (uuid)
|
||||||
|
outputMessageBuffer = "resume:" + uuid + ";" + outputMessageBuffer;
|
||||||
|
|
||||||
|
outputMessageBuffer += "pause;";
|
||||||
|
|
||||||
// Download self
|
// Download self
|
||||||
var xmlhttprequest = new XMLHttpRequest();
|
var xmlhttprequest = new XMLHttpRequest();
|
||||||
xmlhttprequest.open("POST", "instructions");
|
xmlhttprequest.open("POST", "tunnel.php");
|
||||||
xmlhttprequest.send(null);
|
xmlhttprequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||||
|
xmlhttprequest.setRequestHeader("Content-length", outputMessageBuffer.length);
|
||||||
|
|
||||||
|
xmlhttprequest.send(outputMessageBuffer);
|
||||||
|
outputMessageBuffer = "";
|
||||||
|
|
||||||
return xmlhttprequest;
|
return xmlhttprequest;
|
||||||
|
|
||||||
@@ -438,8 +418,14 @@ function VNCClient(display) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var uuid = null;
|
||||||
|
|
||||||
var instructionHandlers = {
|
var instructionHandlers = {
|
||||||
|
|
||||||
|
"uuid": function(parameters) {
|
||||||
|
uuid = parameters[0];
|
||||||
|
},
|
||||||
|
|
||||||
"error": function(parameters) {
|
"error": function(parameters) {
|
||||||
showError(unescapeGuacamoleString(parameters[0]));
|
showError(unescapeGuacamoleString(parameters[0]));
|
||||||
},
|
},
|
||||||
@@ -559,16 +545,8 @@ function VNCClient(display) {
|
|||||||
|
|
||||||
this.connect = function() {
|
this.connect = function() {
|
||||||
|
|
||||||
var message = "connect;";
|
|
||||||
|
|
||||||
setState(STATE_CONNECTING);
|
setState(STATE_CONNECTING);
|
||||||
|
sendMessage("connect;");
|
||||||
// Send connect message (synchronously... as necessary until handoff is implemented)
|
|
||||||
var connect_xmlhttprequest = new XMLHttpRequest();
|
|
||||||
connect_xmlhttprequest.open("POST", "inbound", false);
|
|
||||||
connect_xmlhttprequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
|
||||||
connect_xmlhttprequest.setRequestHeader("Content-length", message.length);
|
|
||||||
connect_xmlhttprequest.send(message);
|
|
||||||
|
|
||||||
// Start reading data
|
// Start reading data
|
||||||
setState(STATE_WAITING);
|
setState(STATE_WAITING);
|
||||||
@@ -583,15 +561,9 @@ function VNCClient(display) {
|
|||||||
if (currentState != STATE_DISCONNECTED
|
if (currentState != STATE_DISCONNECTED
|
||||||
&& currentState != STATE_DISCONNECTING) {
|
&& currentState != STATE_DISCONNECTING) {
|
||||||
|
|
||||||
var message = "disconnect;";
|
|
||||||
setState(STATE_DISCONNECTING);
|
setState(STATE_DISCONNECTING);
|
||||||
|
|
||||||
// Send disconnect message (synchronously... as necessary until handoff is implemented)
|
sendMessage("disconnect;");
|
||||||
var disconnect_xmlhttprequest = new XMLHttpRequest();
|
|
||||||
disconnect_xmlhttprequest.open("POST", "inbound", false);
|
|
||||||
disconnect_xmlhttprequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
|
||||||
disconnect_xmlhttprequest.setRequestHeader("Content-length", message.length);
|
|
||||||
disconnect_xmlhttprequest.send(message);
|
|
||||||
|
|
||||||
setState(STATE_DISCONNECTED);
|
setState(STATE_DISCONNECTED);
|
||||||
}
|
}
|
@@ -1,32 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import net.sourceforge.guacamole.GuacamoleException;
|
|
||||||
import net.sourceforge.guacamole.event.KeyEvent;
|
|
||||||
import net.sourceforge.guacamole.event.PointerEvent;
|
|
||||||
|
|
||||||
public abstract class Client {
|
|
||||||
|
|
||||||
public abstract void write(char[] chunk, int off, int len) throws GuacamoleException;
|
|
||||||
public abstract char[] read() throws GuacamoleException;
|
|
||||||
public abstract void disconnect() throws GuacamoleException;
|
|
||||||
|
|
||||||
}
|
|
@@ -1,133 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.Socket;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
|
|
||||||
import net.sourceforge.guacamole.GuacamoleException;
|
|
||||||
import net.sourceforge.guacamole.event.EventQueue;
|
|
||||||
import net.sourceforge.guacamole.event.EventHandler;
|
|
||||||
import net.sourceforge.guacamole.event.KeyEvent;
|
|
||||||
import net.sourceforge.guacamole.event.PointerEvent;
|
|
||||||
|
|
||||||
public class GuacamoleClient extends Client {
|
|
||||||
|
|
||||||
private Socket sock;
|
|
||||||
private Reader input;
|
|
||||||
private Writer output;
|
|
||||||
|
|
||||||
public GuacamoleClient(String hostname, int port) throws GuacamoleException {
|
|
||||||
|
|
||||||
try {
|
|
||||||
sock = new Socket(InetAddress.getByName(hostname), port);
|
|
||||||
input = new InputStreamReader(sock.getInputStream());
|
|
||||||
output = new OutputStreamWriter(sock.getOutputStream());
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new GuacamoleException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(char[] chunk, int off, int len) throws GuacamoleException {
|
|
||||||
try {
|
|
||||||
output.write(chunk, off, len);
|
|
||||||
output.flush();
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new GuacamoleException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disconnect() throws GuacamoleException {
|
|
||||||
try {
|
|
||||||
sock.close();
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new GuacamoleException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int usedLength = 0;
|
|
||||||
private char[] buffer = new char[20000];
|
|
||||||
|
|
||||||
public char[] read() throws GuacamoleException {
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
// While we're blocking, or input is available
|
|
||||||
for (;;) {
|
|
||||||
|
|
||||||
// If past threshold, resize buffer before reading
|
|
||||||
if (usedLength > buffer.length/2) {
|
|
||||||
char[] biggerBuffer = new char[buffer.length*2];
|
|
||||||
System.arraycopy(buffer, 0, biggerBuffer, 0, usedLength);
|
|
||||||
buffer = biggerBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to fill buffer
|
|
||||||
int numRead = input.read(buffer, usedLength, buffer.length - usedLength);
|
|
||||||
if (numRead == -1)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
int prevLength = usedLength;
|
|
||||||
usedLength += numRead;
|
|
||||||
|
|
||||||
for (int i=usedLength-1; i>=prevLength; i--) {
|
|
||||||
|
|
||||||
char readChar = buffer[i];
|
|
||||||
|
|
||||||
// If end of instruction, return it.
|
|
||||||
if (readChar == ';') {
|
|
||||||
|
|
||||||
// Get instruction
|
|
||||||
char[] chunk = new char[i+1];
|
|
||||||
System.arraycopy(buffer, 0, chunk, 0, i+1);
|
|
||||||
|
|
||||||
// Reset buffer
|
|
||||||
usedLength -= i+1;
|
|
||||||
System.arraycopy(buffer, i+1, buffer, 0, usedLength);
|
|
||||||
|
|
||||||
// Return instruction string
|
|
||||||
return chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End read loop
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new GuacamoleException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,36 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class GuacamoleException extends Exception {
|
|
||||||
|
|
||||||
public GuacamoleException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public GuacamoleException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public GuacamoleException(Throwable cause) {
|
|
||||||
super(cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,55 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.event;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public abstract class Event implements Comparable<Event> {
|
|
||||||
|
|
||||||
private long time;
|
|
||||||
private int index;
|
|
||||||
|
|
||||||
public Event(int index) {
|
|
||||||
this.time = System.currentTimeMillis();
|
|
||||||
this.index = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIndex() {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTime() {
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int hashCode() {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (o == null) return false;
|
|
||||||
if (getClass() != o.getClass()) return false;
|
|
||||||
return getIndex() == ((Event) o).getIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int compareTo(Event e) {
|
|
||||||
return getIndex() - e.getIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,28 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.event;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public interface EventHandler<E extends Event> {
|
|
||||||
|
|
||||||
public void handle(E e) throws IOException;
|
|
||||||
|
|
||||||
}
|
|
@@ -1,191 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.event;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.PriorityQueue;
|
|
||||||
|
|
||||||
public class EventQueue<E extends Event> {
|
|
||||||
|
|
||||||
private int nextIndex = 0;
|
|
||||||
private final PriorityQueue<E> queue = new PriorityQueue<E>();
|
|
||||||
private EventHandler<E> handler;
|
|
||||||
|
|
||||||
private final int deadline;
|
|
||||||
|
|
||||||
private AutoflushThread autoflush = new AutoflushThread();
|
|
||||||
|
|
||||||
private class AutoflushThread extends Thread {
|
|
||||||
|
|
||||||
private IOException error;
|
|
||||||
private long deadline;
|
|
||||||
private static final long ONE_YEAR = 31536000;
|
|
||||||
|
|
||||||
private boolean killed = false;
|
|
||||||
|
|
||||||
public AutoflushThread() {
|
|
||||||
this.deadline = ONE_YEAR;
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
while (!killed) {
|
|
||||||
try {
|
|
||||||
if (deadline > 0) sleep(deadline);
|
|
||||||
dropPendingEvents();
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
catch (InterruptedException e) {
|
|
||||||
// Interrupt indicates event handled, or thread killed
|
|
||||||
if (killed) return;
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
error = e;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeadline(long deadline) {
|
|
||||||
this.deadline = deadline;
|
|
||||||
interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkError() throws IOException {
|
|
||||||
if (error != null) throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void kill() {
|
|
||||||
killed = true;
|
|
||||||
interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
autoflush.kill();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Starts autoflush wait thread for any waiting events on the queue
|
|
||||||
private void startDeadlineAutoflush() {
|
|
||||||
synchronized (queue) {
|
|
||||||
|
|
||||||
// No need to autoflush if nothing waiting
|
|
||||||
if (queue.size() == 0) return;
|
|
||||||
|
|
||||||
// Get waiting event
|
|
||||||
E waiting = queue.peek();
|
|
||||||
|
|
||||||
if (waiting != null) {
|
|
||||||
long untilDeadline = deadline + waiting.getTime() - System.currentTimeMillis();
|
|
||||||
|
|
||||||
// Start autoflush thread which waits for time remaining until next
|
|
||||||
// event's deadline.
|
|
||||||
autoflush.setDeadline(untilDeadline);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
autoflush.setDeadline(AutoflushThread.ONE_YEAR);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public EventQueue(EventHandler<E> handler, int deadline) {
|
|
||||||
this.handler = handler;
|
|
||||||
this.deadline = deadline;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(E event) throws IOException {
|
|
||||||
synchronized (queue) {
|
|
||||||
|
|
||||||
autoflush.checkError();
|
|
||||||
|
|
||||||
if (event.getIndex() < nextIndex) {
|
|
||||||
//System.err.println("Past event dropped.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event == null)
|
|
||||||
throw new Error("Cannot add null event.");
|
|
||||||
|
|
||||||
queue.add(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
private E next() {
|
|
||||||
synchronized (queue) {
|
|
||||||
// If no events, return nothing.
|
|
||||||
if (queue.size() == 0) return null;
|
|
||||||
|
|
||||||
// If still waiting for true next event, return nothing.
|
|
||||||
E event = queue.peek();
|
|
||||||
if (event.getIndex() != nextIndex)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// If event found, expect next event, remove and return current.
|
|
||||||
queue.remove();
|
|
||||||
nextIndex++;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return number of waiting events
|
|
||||||
public int getWaiting() {
|
|
||||||
synchronized (queue) {
|
|
||||||
// If no events, then none waiting.
|
|
||||||
if (queue.size() == 0) return 0;
|
|
||||||
|
|
||||||
// If we have the next event, then none waiting.
|
|
||||||
E event = queue.peek();
|
|
||||||
if (event.getIndex() == nextIndex)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Otherwise, all events are waiting.
|
|
||||||
return queue.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop waiting for any unreceived events
|
|
||||||
private void dropPendingEvents() {
|
|
||||||
synchronized (queue) {
|
|
||||||
// If no events, nothing needs to be changed;
|
|
||||||
if (queue.size() == 0) return;
|
|
||||||
|
|
||||||
// Otherwise, update nextIndex to index of next event
|
|
||||||
E event = queue.peek();
|
|
||||||
nextIndex = event.getIndex();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempts to flush queue
|
|
||||||
// If any events remain, an autoflush thread is started.
|
|
||||||
private void flush() throws IOException {
|
|
||||||
synchronized (queue) {
|
|
||||||
E nextEvent;
|
|
||||||
while ((nextEvent = next()) != null)
|
|
||||||
handler.handle(nextEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start autoflush thread for any remaining events.
|
|
||||||
startDeadlineAutoflush();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,39 +0,0 @@
|
|||||||
package net.sourceforge.guacamole.event;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class KeyEvent extends Event {
|
|
||||||
|
|
||||||
private int keysym;
|
|
||||||
private boolean pressed;
|
|
||||||
|
|
||||||
public KeyEvent(int index, int keysym, boolean pressed) {
|
|
||||||
super(index);
|
|
||||||
this.keysym = keysym;
|
|
||||||
this.pressed = pressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getKeySym() {
|
|
||||||
return keysym;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getPressed() {
|
|
||||||
return pressed;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,69 +0,0 @@
|
|||||||
package net.sourceforge.guacamole.event;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class PointerEvent extends Event {
|
|
||||||
|
|
||||||
private boolean leftButtonPressed;
|
|
||||||
private boolean middleButtonPressed;
|
|
||||||
private boolean rightButtonPressed;
|
|
||||||
private boolean upButtonPressed;
|
|
||||||
private boolean downButtonPressed;
|
|
||||||
private int x;
|
|
||||||
private int y;
|
|
||||||
|
|
||||||
public PointerEvent(int index, boolean leftButtonPressed, boolean middleButtonPressed, boolean rightButtonPressed, boolean upButtonPressed, boolean downButtonPressed, int x, int y) {
|
|
||||||
super(index);
|
|
||||||
this.leftButtonPressed = leftButtonPressed;
|
|
||||||
this.middleButtonPressed = middleButtonPressed;
|
|
||||||
this.rightButtonPressed = rightButtonPressed;
|
|
||||||
this.upButtonPressed = upButtonPressed;
|
|
||||||
this.downButtonPressed = downButtonPressed;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLeftButtonPressed() {
|
|
||||||
return leftButtonPressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMiddleButtonPressed() {
|
|
||||||
return middleButtonPressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRightButtonPressed() {
|
|
||||||
return rightButtonPressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isUpButtonPressed() {
|
|
||||||
return upButtonPressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDownButtonPressed() {
|
|
||||||
return downButtonPressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getX() {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getY() {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,66 +0,0 @@
|
|||||||
package net.sourceforge.guacamole.net;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class Base64 {
|
|
||||||
|
|
||||||
private static String characters =
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
||||||
|
|
||||||
|
|
||||||
public static String toString(byte[] data) {
|
|
||||||
|
|
||||||
StringBuffer buff = new StringBuffer();
|
|
||||||
for (int i=0; i<data.length; i+=3) {
|
|
||||||
|
|
||||||
int a = data[i];
|
|
||||||
int b = 0; if (i+1 < data.length) b = data[i+1];
|
|
||||||
int c = 0; if (i+2 < data.length) c = data[i+2];
|
|
||||||
|
|
||||||
buff.append(characters.charAt(
|
|
||||||
(a & 0xFC) >> 2
|
|
||||||
));
|
|
||||||
|
|
||||||
buff.append(characters.charAt(
|
|
||||||
((a & 0x03) << 4) |
|
|
||||||
((b & 0xF0) >> 4)
|
|
||||||
));
|
|
||||||
|
|
||||||
if (i+1 < data.length)
|
|
||||||
buff.append(characters.charAt(
|
|
||||||
((b & 0x0F) << 2) |
|
|
||||||
((c & 0xC0) >> 6)
|
|
||||||
));
|
|
||||||
else
|
|
||||||
buff.append('=');
|
|
||||||
|
|
||||||
if (i+2 < data.length)
|
|
||||||
buff.append(characters.charAt(
|
|
||||||
(c & 0x3F)
|
|
||||||
));
|
|
||||||
else
|
|
||||||
buff.append('=');
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return buff.toString();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,130 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.net;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import net.sourceforge.guacamole.GuacamoleException;
|
|
||||||
|
|
||||||
public abstract class Configuration {
|
|
||||||
|
|
||||||
private ServletContext context;
|
|
||||||
|
|
||||||
protected String humanReadableList(Object... values) {
|
|
||||||
|
|
||||||
String list = "";
|
|
||||||
for (int i=0; i<values.length; i++) {
|
|
||||||
|
|
||||||
if (i >= 1)
|
|
||||||
list += ", ";
|
|
||||||
|
|
||||||
if (i == values.length -1)
|
|
||||||
list += " or ";
|
|
||||||
|
|
||||||
list += "\"" + values[i] + "\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String readParameter(String name, String defaultValue, String... allowedValues) throws GuacamoleException {
|
|
||||||
|
|
||||||
String value = context.getInitParameter(name);
|
|
||||||
|
|
||||||
// Use default if not specified
|
|
||||||
if (value == null) {
|
|
||||||
if (defaultValue == null)
|
|
||||||
throw new GuacamoleException("Parameter \"" + name + "\" is required.");
|
|
||||||
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not restricted to certain values, just return whatever is given.
|
|
||||||
if (allowedValues.length == 0)
|
|
||||||
return value;
|
|
||||||
|
|
||||||
// If restricted, only return value within given list
|
|
||||||
for (String allowedValue : allowedValues)
|
|
||||||
if (value.equals(allowedValue))
|
|
||||||
return value;
|
|
||||||
|
|
||||||
throw new GuacamoleException("Parameter \"" + name + "\" must be " + humanReadableList((Object) allowedValues));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean readBooleanParameter(String name, Boolean defaultValue) throws GuacamoleException {
|
|
||||||
|
|
||||||
String value = context.getInitParameter(name);
|
|
||||||
|
|
||||||
// Use default if not specified
|
|
||||||
if (value == null) {
|
|
||||||
if (defaultValue == null)
|
|
||||||
throw new GuacamoleException("Parameter \"" + name + "\" is required.");
|
|
||||||
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = value.trim();
|
|
||||||
if (value.equals("true"))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (value.equals("false"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
throw new GuacamoleException("Parameter \"" + name + "\" must be \"true\" or \"false\".");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int readIntParameter(String name, Integer defaultValue, Integer... allowedValues) throws GuacamoleException {
|
|
||||||
|
|
||||||
String parmString = context.getInitParameter(name);
|
|
||||||
|
|
||||||
// Use default if not specified
|
|
||||||
if (parmString== null) {
|
|
||||||
if (defaultValue == null)
|
|
||||||
throw new GuacamoleException("Parameter \"" + name + "\" is required.");
|
|
||||||
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
int value = Integer.parseInt(parmString);
|
|
||||||
|
|
||||||
// If not restricted to certain values, just return whatever is given.
|
|
||||||
if (allowedValues.length == 0)
|
|
||||||
return value;
|
|
||||||
|
|
||||||
// If restricted, only return value within given list
|
|
||||||
for (int allowedValue : allowedValues)
|
|
||||||
if (value == allowedValue)
|
|
||||||
return value;
|
|
||||||
|
|
||||||
throw new GuacamoleException("Parameter \"" + name + "\" must be " + humanReadableList((Object) allowedValues));
|
|
||||||
}
|
|
||||||
catch (NumberFormatException e) {
|
|
||||||
throw new GuacamoleException("Parameter \"" + name + "\" must be an integer.", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Configuration(ServletContext context) {
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,46 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.net;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import net.sourceforge.guacamole.GuacamoleException;
|
|
||||||
|
|
||||||
public class GuacamoleConfiguration extends Configuration {
|
|
||||||
|
|
||||||
private String hostname;
|
|
||||||
private int port;
|
|
||||||
|
|
||||||
public GuacamoleConfiguration(ServletContext context) throws GuacamoleException {
|
|
||||||
|
|
||||||
super(context);
|
|
||||||
|
|
||||||
hostname = context.getInitParameter("hostname");
|
|
||||||
port = readIntParameter("port", null);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPort() {
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getHostname() {
|
|
||||||
return hostname;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,62 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.net;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServlet;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import net.sourceforge.guacamole.GuacamoleException;
|
|
||||||
|
|
||||||
public abstract class GuacamoleServlet extends HttpServlet {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
|
||||||
try {
|
|
||||||
handleRequest(req, resp);
|
|
||||||
}
|
|
||||||
catch (GuacamoleException e) {
|
|
||||||
throw new ServletException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
|
||||||
try {
|
|
||||||
handleRequest(req, resp);
|
|
||||||
}
|
|
||||||
catch (GuacamoleException e) {
|
|
||||||
throw new ServletException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final void handleRequest(HttpServletRequest request, HttpServletResponse response) throws GuacamoleException {
|
|
||||||
GuacamoleSession session = new GuacamoleSession(request.getSession(shouldCreateSession()));
|
|
||||||
handleRequest(session, request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void handleRequest(GuacamoleSession session, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException;
|
|
||||||
|
|
||||||
protected boolean shouldCreateSession() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,147 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.net;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
import javax.servlet.http.HttpSessionBindingEvent;
|
|
||||||
import javax.servlet.http.HttpSessionBindingListener;
|
|
||||||
import net.sourceforge.guacamole.Client;
|
|
||||||
import net.sourceforge.guacamole.GuacamoleClient;
|
|
||||||
import net.sourceforge.guacamole.GuacamoleException;
|
|
||||||
import net.sourceforge.guacamole.event.KeyEvent;
|
|
||||||
import net.sourceforge.guacamole.event.PointerEvent;
|
|
||||||
|
|
||||||
public class GuacamoleSession {
|
|
||||||
|
|
||||||
private GuacamoleConfiguration config;
|
|
||||||
private final HttpSession session;
|
|
||||||
private Client client;
|
|
||||||
private ReentrantLock instructionStreamLock;
|
|
||||||
|
|
||||||
private class SessionClient extends Client implements HttpSessionBindingListener {
|
|
||||||
|
|
||||||
private Client client;
|
|
||||||
|
|
||||||
public SessionClient(Client client) {
|
|
||||||
this.client = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void valueBound(HttpSessionBindingEvent event) {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
public void valueUnbound(HttpSessionBindingEvent event) {
|
|
||||||
try {
|
|
||||||
disconnect();
|
|
||||||
}
|
|
||||||
catch (GuacamoleException e) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(char[] data, int off, int len) throws GuacamoleException {
|
|
||||||
client.write(data, off, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
public char[] read() throws GuacamoleException {
|
|
||||||
return client.read();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disconnect() throws GuacamoleException {
|
|
||||||
client.disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public GuacamoleSession(HttpSession session) throws GuacamoleException {
|
|
||||||
|
|
||||||
if (session == null)
|
|
||||||
throw new GuacamoleException("User has no session.");
|
|
||||||
|
|
||||||
this.session = session;
|
|
||||||
synchronized (session) {
|
|
||||||
|
|
||||||
// Read configuration parameters
|
|
||||||
ServletContext context = session.getServletContext();
|
|
||||||
config = new GuacamoleConfiguration(context);
|
|
||||||
|
|
||||||
client = (Client) session.getAttribute("CLIENT");
|
|
||||||
instructionStreamLock = (ReentrantLock) session.getAttribute("INSTRUCTION_STREAM_LOCK");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void connect() throws GuacamoleException {
|
|
||||||
synchronized (session) {
|
|
||||||
|
|
||||||
if (client != null)
|
|
||||||
client.disconnect();
|
|
||||||
|
|
||||||
|
|
||||||
client = new SessionClient(
|
|
||||||
new GuacamoleClient (
|
|
||||||
config.getHostname(),
|
|
||||||
config.getPort()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
session.setAttribute("CLIENT", client);
|
|
||||||
|
|
||||||
instructionStreamLock = new ReentrantLock();
|
|
||||||
session.setAttribute("INSTRUCTION_STREAM_LOCK", instructionStreamLock);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isConnected() {
|
|
||||||
synchronized (session) {
|
|
||||||
return client != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GuacamoleConfiguration getConfiguration() {
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Client getClient() {
|
|
||||||
synchronized (session) {
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void invalidate() {
|
|
||||||
session.invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disconnect() throws GuacamoleException {
|
|
||||||
if (client != null) {
|
|
||||||
client.disconnect();
|
|
||||||
|
|
||||||
session.removeAttribute("CLIENT");
|
|
||||||
client = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReentrantLock getInstructionStreamLock() {
|
|
||||||
return instructionStreamLock;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,132 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.net;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
|
||||||
import javax.xml.transform.OutputKeys;
|
|
||||||
import javax.xml.transform.Transformer;
|
|
||||||
import javax.xml.transform.TransformerConfigurationException;
|
|
||||||
import javax.xml.transform.TransformerException;
|
|
||||||
import javax.xml.transform.TransformerFactory;
|
|
||||||
import javax.xml.transform.dom.DOMSource;
|
|
||||||
import javax.xml.transform.stream.StreamResult;
|
|
||||||
import net.sourceforge.guacamole.Client;
|
|
||||||
import net.sourceforge.guacamole.GuacamoleException;
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
|
|
||||||
public abstract class XMLGuacamoleServlet extends GuacamoleServlet {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void handleRequest(GuacamoleSession session, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException {
|
|
||||||
|
|
||||||
response.setContentType("text/xml");
|
|
||||||
response.setHeader("Cache-Control", "no-store");
|
|
||||||
response.setHeader("Pragma", "no-cache");
|
|
||||||
response.setDateHeader("Expires", 0);
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
// Create document
|
|
||||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
|
||||||
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
|
|
||||||
Document document = documentBuilder.newDocument();
|
|
||||||
|
|
||||||
// Root element
|
|
||||||
Element root = document.createElement("guacamole");
|
|
||||||
document.appendChild(root);
|
|
||||||
|
|
||||||
try {
|
|
||||||
handleRequest(session, request, root);
|
|
||||||
}
|
|
||||||
catch (Throwable t) {
|
|
||||||
addFatalError(root, t.getMessage());
|
|
||||||
|
|
||||||
// FATAL error ... try to disconnect
|
|
||||||
if (session != null) {
|
|
||||||
Client client = session.getClient();
|
|
||||||
try {
|
|
||||||
if (client != null)
|
|
||||||
client.disconnect();
|
|
||||||
}
|
|
||||||
catch (GuacamoleException e) {
|
|
||||||
addFatalError(root, e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up transformer
|
|
||||||
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
|
||||||
Transformer transformer = transformerFactory.newTransformer();
|
|
||||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
|
||||||
//transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
|
||||||
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
|
|
||||||
|
|
||||||
// Write XML using transformer
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
||||||
StreamResult result = new StreamResult(bos);
|
|
||||||
DOMSource source = new DOMSource(document);
|
|
||||||
transformer.transform(source, result);
|
|
||||||
|
|
||||||
|
|
||||||
bos.flush();
|
|
||||||
|
|
||||||
byte[] xmlData = bos.toByteArray();
|
|
||||||
response.setContentLength(xmlData.length);
|
|
||||||
OutputStream outputStream = response.getOutputStream();
|
|
||||||
outputStream.write(xmlData);
|
|
||||||
|
|
||||||
// Close stream
|
|
||||||
outputStream.close();
|
|
||||||
}
|
|
||||||
catch (ParserConfigurationException e) {
|
|
||||||
throw new GuacamoleException(e);
|
|
||||||
}
|
|
||||||
catch (TransformerConfigurationException e) {
|
|
||||||
throw new GuacamoleException(e);
|
|
||||||
}
|
|
||||||
catch (TransformerException e) {
|
|
||||||
throw new GuacamoleException(e);
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new GuacamoleException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addFatalError(Element root, String message) {
|
|
||||||
Element error = root.getOwnerDocument().createElement("error");
|
|
||||||
error.setAttribute("type", "fatal");
|
|
||||||
error.setTextContent(message);
|
|
||||||
root.appendChild(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void handleRequest(GuacamoleSession session, ServletRequest request, Element root) throws GuacamoleException;
|
|
||||||
|
|
||||||
}
|
|
@@ -1,64 +0,0 @@
|
|||||||
package net.sourceforge.guacamole.net.input;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import net.sourceforge.guacamole.GuacamoleException;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import net.sourceforge.guacamole.net.GuacamoleSession;
|
|
||||||
import net.sourceforge.guacamole.net.XMLGuacamoleServlet;
|
|
||||||
|
|
||||||
public class Inbound extends XMLGuacamoleServlet {
|
|
||||||
|
|
||||||
protected boolean shouldCreateSession() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void handleRequest(GuacamoleSession session, ServletRequest request, Element root) throws GuacamoleException {
|
|
||||||
|
|
||||||
if (!session.isConnected())
|
|
||||||
session.connect();
|
|
||||||
|
|
||||||
// Send data
|
|
||||||
try {
|
|
||||||
|
|
||||||
Reader input = request.getReader();
|
|
||||||
char[] buffer = new char[8192];
|
|
||||||
|
|
||||||
int length;
|
|
||||||
while ((length = input.read(buffer, 0, buffer.length)) != -1)
|
|
||||||
session.getClient().write(buffer, 0, length);
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new GuacamoleException("I/O Error sending data to server: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
catch (GuacamoleException e) {
|
|
||||||
throw new GuacamoleException("Error sending data to server: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@@ -1,97 +0,0 @@
|
|||||||
package net.sourceforge.guacamole.net.output;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guacamole - Clientless Remote Desktop
|
|
||||||
* Copyright (C) 2010 Michael Jumper
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import net.sourceforge.guacamole.Client;
|
|
||||||
import net.sourceforge.guacamole.net.GuacamoleServlet;
|
|
||||||
import net.sourceforge.guacamole.GuacamoleException;
|
|
||||||
import net.sourceforge.guacamole.net.GuacamoleSession;
|
|
||||||
|
|
||||||
|
|
||||||
public class InstructionStream extends GuacamoleServlet {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void handleRequest(GuacamoleSession session, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException {
|
|
||||||
|
|
||||||
ReentrantLock instructionStreamLock = session.getInstructionStreamLock();
|
|
||||||
instructionStreamLock.lock();
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
response.setContentType("text/plain");
|
|
||||||
Writer out = response.getWriter();
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
// Query new update from server
|
|
||||||
Client client = session.getClient();
|
|
||||||
|
|
||||||
// For all messages, until another stream is ready (we send at least one message)
|
|
||||||
char[] message;
|
|
||||||
while ((message = client.read()) != null) {
|
|
||||||
|
|
||||||
// Get message output bytes
|
|
||||||
out.write(message, 0, message.length);
|
|
||||||
out.flush();
|
|
||||||
response.flushBuffer();
|
|
||||||
|
|
||||||
// No more messages another stream can take over
|
|
||||||
if (instructionStreamLock.hasQueuedThreads())
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message == null) {
|
|
||||||
session.disconnect();
|
|
||||||
throw new GuacamoleException("Disconnected.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (GuacamoleException e) {
|
|
||||||
out.write("error:" + e.getMessage() + ";");
|
|
||||||
out.flush();
|
|
||||||
response.flushBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
// End-of-instructions marker
|
|
||||||
out.write(';');
|
|
||||||
out.flush();
|
|
||||||
response.flushBuffer();
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (UnsupportedEncodingException e) {
|
|
||||||
throw new GuacamoleException("UTF-8 not supported by Java.", e);
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new GuacamoleException("I/O error writing to servlet output stream.", e);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
instructionStreamLock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
35
guacamole/client/tunnel.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
# End all output buffers
|
||||||
|
while (@ob_end_flush());
|
||||||
|
|
||||||
|
# Create socket
|
||||||
|
$socket = socket_create(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (!$socket) {
|
||||||
|
die("error:Could not create socket.;");
|
||||||
|
}
|
||||||
|
|
||||||
|
# Open connection
|
||||||
|
$result = socket_connect($socket, "localhost", 2222);
|
||||||
|
if (!$result) {
|
||||||
|
die("error:Could not connect: " . socket_strerror(socket_last_error()) . ";");
|
||||||
|
}
|
||||||
|
|
||||||
|
# Socket should block
|
||||||
|
socket_set_block($socket);
|
||||||
|
|
||||||
|
# Write all data sent here
|
||||||
|
socket_write($socket, file_get_contents("php://input"));
|
||||||
|
|
||||||
|
# Read until EOF
|
||||||
|
while (($buffer = socket_read($socket, 8192))) {
|
||||||
|
echo $buffer;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
echo ";";
|
||||||
|
|
||||||
|
# Close socket
|
||||||
|
socket_close($socket);
|
||||||
|
|
||||||
|
?>
|
@@ -1,68 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
Guacamole - Pure JavaScript/HTML VNC Client
|
|
||||||
Copyright (C) 2010 Michael Jumper
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
|
|
||||||
<!-- Basic config -->
|
|
||||||
<welcome-file-list>
|
|
||||||
<welcome-file>index.html</welcome-file>
|
|
||||||
</welcome-file-list>
|
|
||||||
<session-config>
|
|
||||||
<session-timeout>
|
|
||||||
30
|
|
||||||
</session-timeout>
|
|
||||||
</session-config>
|
|
||||||
<!-- Servlets -->
|
|
||||||
<servlet>
|
|
||||||
<description>Instruction stream servlet.</description>
|
|
||||||
<servlet-name>InstructionStream</servlet-name>
|
|
||||||
<servlet-class>net.sourceforge.guacamole.net.output.InstructionStream</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>InstructionStream</servlet-name>
|
|
||||||
<url-pattern>/instructions</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
<servlet>
|
|
||||||
<description>Input servlet.</description>
|
|
||||||
<servlet-name>Inbound</servlet-name>
|
|
||||||
<servlet-class>net.sourceforge.guacamole.net.input.Inbound</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>Inbound</servlet-name>
|
|
||||||
<url-pattern>/inbound</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
<security-constraint>
|
|
||||||
<display-name>Guacamole Access Restrictions</display-name>
|
|
||||||
<web-resource-collection>
|
|
||||||
<web-resource-name>Guacamole</web-resource-name>
|
|
||||||
<description>All servlets/pages within Guacamole.</description>
|
|
||||||
<url-pattern>/*</url-pattern>
|
|
||||||
</web-resource-collection>
|
|
||||||
<auth-constraint>
|
|
||||||
<description>Only allow Guacamole users access.</description>
|
|
||||||
<role-name>guacamole</role-name>
|
|
||||||
</auth-constraint>
|
|
||||||
</security-constraint>
|
|
||||||
<login-config>
|
|
||||||
<auth-method>BASIC</auth-method>
|
|
||||||
<realm-name>Guacamole</realm-name>
|
|
||||||
</login-config>
|
|
||||||
<security-role>
|
|
||||||
<description>Guacamole</description>
|
|
||||||
<role-name>guacamole</role-name>
|
|
||||||
</security-role>
|
|
||||||
</web-app>
|
|