mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 05:07:41 +00:00
Now using true inbound instruction stream ... no more event-specific servlets.
This commit is contained in:
@@ -19,17 +19,14 @@ package net.sourceforge.guacamole;
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import net.sourceforge.guacamole.instruction.Instruction;
|
|
||||||
import net.sourceforge.guacamole.GuacamoleException;
|
import net.sourceforge.guacamole.GuacamoleException;
|
||||||
import net.sourceforge.guacamole.event.KeyEvent;
|
import net.sourceforge.guacamole.event.KeyEvent;
|
||||||
import net.sourceforge.guacamole.event.PointerEvent;
|
import net.sourceforge.guacamole.event.PointerEvent;
|
||||||
|
|
||||||
public abstract class Client {
|
public abstract class Client {
|
||||||
|
|
||||||
public abstract void send(KeyEvent event) throws GuacamoleException;
|
public abstract void write(char[] chunk, int off, int len) throws GuacamoleException;
|
||||||
public abstract void send(PointerEvent event) throws GuacamoleException;
|
public abstract char[] read() throws GuacamoleException;
|
||||||
public abstract void setClipboard(String clipboard) throws GuacamoleException;
|
|
||||||
public abstract void disconnect() throws GuacamoleException;
|
public abstract void disconnect() throws GuacamoleException;
|
||||||
public abstract Instruction nextInstruction(boolean blocking) throws GuacamoleException;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -31,7 +31,6 @@ import java.io.OutputStream;
|
|||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
|
|
||||||
import net.sourceforge.guacamole.instruction.Instruction;
|
|
||||||
import net.sourceforge.guacamole.GuacamoleException;
|
import net.sourceforge.guacamole.GuacamoleException;
|
||||||
import net.sourceforge.guacamole.event.EventQueue;
|
import net.sourceforge.guacamole.event.EventQueue;
|
||||||
import net.sourceforge.guacamole.event.EventHandler;
|
import net.sourceforge.guacamole.event.EventHandler;
|
||||||
@@ -57,64 +56,9 @@ public class GuacamoleClient extends Client {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void write(char[] chunk, int off, int len) throws GuacamoleException {
|
||||||
private static final int EVENT_DEADLINE = 500;
|
|
||||||
|
|
||||||
private EventQueue<KeyEvent> keyEvents = new EventQueue<KeyEvent>(new EventHandler<KeyEvent>() {
|
|
||||||
|
|
||||||
public void handle(KeyEvent event) throws IOException {
|
|
||||||
int pressed = 0;
|
|
||||||
if (event.getPressed()) pressed = 1;
|
|
||||||
|
|
||||||
output.write("key:" + event.getKeySym() + "," + pressed + ";");
|
|
||||||
output.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
}, EVENT_DEADLINE);
|
|
||||||
|
|
||||||
private EventQueue<PointerEvent> pointerEvents = new EventQueue<PointerEvent>(new EventHandler<PointerEvent>() {
|
|
||||||
|
|
||||||
public void handle(PointerEvent event) throws IOException {
|
|
||||||
int mask = 0;
|
|
||||||
if (event.isLeftButtonPressed()) mask |= 1;
|
|
||||||
if (event.isMiddleButtonPressed()) mask |= 2;
|
|
||||||
if (event.isRightButtonPressed()) mask |= 4;
|
|
||||||
if (event.isUpButtonPressed()) mask |= 8;
|
|
||||||
if (event.isDownButtonPressed()) mask |= 16;
|
|
||||||
|
|
||||||
|
|
||||||
output.write("mouse:" + event.getX() + "," + event.getY() + "," + mask + ";");
|
|
||||||
output.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
}, EVENT_DEADLINE);
|
|
||||||
|
|
||||||
|
|
||||||
public void send(KeyEvent event) throws GuacamoleException {
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
keyEvents.add(event);
|
output.write(chunk, off, len);
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new GuacamoleException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void send(PointerEvent event) throws GuacamoleException {
|
|
||||||
|
|
||||||
try {
|
|
||||||
pointerEvents.add(event);
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new GuacamoleException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClipboard(String clipboard) throws GuacamoleException {
|
|
||||||
try {
|
|
||||||
output.write("clipboard:" + Instruction.escape(clipboard) + ";");
|
|
||||||
output.flush();
|
output.flush();
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
@@ -134,7 +78,7 @@ public class GuacamoleClient extends Client {
|
|||||||
private int usedLength = 0;
|
private int usedLength = 0;
|
||||||
private char[] buffer = new char[20000];
|
private char[] buffer = new char[20000];
|
||||||
|
|
||||||
public Instruction nextInstruction(boolean blocking) throws GuacamoleException {
|
public char[] read() throws GuacamoleException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
@@ -164,20 +108,15 @@ public class GuacamoleClient extends Client {
|
|||||||
if (readChar == ';') {
|
if (readChar == ';') {
|
||||||
|
|
||||||
// Get instruction
|
// Get instruction
|
||||||
final String instruction = new String(buffer, 0, i+1);
|
char[] chunk = new char[i+1];
|
||||||
|
System.arraycopy(buffer, 0, chunk, 0, i+1);
|
||||||
|
|
||||||
// Reset buffer
|
// Reset buffer
|
||||||
usedLength -= i+1;
|
usedLength -= i+1;
|
||||||
System.arraycopy(buffer, i+1, buffer, 0, usedLength);
|
System.arraycopy(buffer, i+1, buffer, 0, usedLength);
|
||||||
|
|
||||||
// Return instruction string wrapped in Instruction class
|
// Return instruction string
|
||||||
return new Instruction() {
|
return chunk;
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return instruction;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,39 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.instruction;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 ClipboardInstruction extends Instruction {
|
|
||||||
|
|
||||||
private String data;
|
|
||||||
|
|
||||||
public ClipboardInstruction(String data) {
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getData() {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "clipboard:" + escape(getData()) + ";";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,39 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.instruction;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 ErrorInstruction extends Instruction {
|
|
||||||
|
|
||||||
private String error;
|
|
||||||
|
|
||||||
public ErrorInstruction(String error) {
|
|
||||||
this.error = error;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getError() {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "error:" + escape(getError()) + ";";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,63 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.instruction;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 Instruction {
|
|
||||||
|
|
||||||
|
|
||||||
// All Instructions must provide a toString() implementation
|
|
||||||
// which returns the properly formatted instruction:
|
|
||||||
// OPCODE:parm1,parm2,...,parmN;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public abstract String toString();
|
|
||||||
|
|
||||||
public static String escape(String str) {
|
|
||||||
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
|
|
||||||
for (int i=0; i<str.length(); i++) {
|
|
||||||
|
|
||||||
char c = str.charAt(i);
|
|
||||||
|
|
||||||
switch (c) {
|
|
||||||
case ',':
|
|
||||||
sb.append("\\c");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ';':
|
|
||||||
sb.append("\\s");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\\':
|
|
||||||
sb.append("\\\\");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
sb.append(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,39 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.instruction;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 NameInstruction extends Instruction {
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
public NameInstruction(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "name:" + escape(getName()) + ";";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,47 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.instruction;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 SizeInstruction extends Instruction {
|
|
||||||
|
|
||||||
private int width;
|
|
||||||
private int height;
|
|
||||||
|
|
||||||
public SizeInstruction(int width, int height) {
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWidth() {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeight() {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "size:"
|
|
||||||
+ getWidth() + ","
|
|
||||||
+ getHeight() + ";";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,78 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.instruction.framebuffer;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.instruction.Instruction;
|
|
||||||
|
|
||||||
public class CopyRectInstruction extends Instruction {
|
|
||||||
|
|
||||||
private final int x;
|
|
||||||
private final int y;
|
|
||||||
private final int width;
|
|
||||||
private final int height;
|
|
||||||
|
|
||||||
private final int srcX;
|
|
||||||
private final int srcY;
|
|
||||||
|
|
||||||
public CopyRectInstruction(int x, int y, int width, int height, int srcX, int srcY) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.srcX = srcX;
|
|
||||||
this.srcY = srcY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getX() {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getY() {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWidth() {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeight() {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSrcX() {
|
|
||||||
return srcX;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSrcY() {
|
|
||||||
return srcY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "copy:"
|
|
||||||
+ getSrcX() + ","
|
|
||||||
+ getSrcY() + ","
|
|
||||||
+ getWidth() + ","
|
|
||||||
+ getHeight() + ","
|
|
||||||
+ getX() + ","
|
|
||||||
+ getY() + ";";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,66 +0,0 @@
|
|||||||
package net.sourceforge.guacamole.instruction.framebuffer;
|
|
||||||
|
|
||||||
import net.sourceforge.guacamole.net.Base64;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.instruction.Instruction;
|
|
||||||
|
|
||||||
public class CursorInstruction extends Instruction {
|
|
||||||
|
|
||||||
private int x;
|
|
||||||
private int y;
|
|
||||||
private PNGImage image;
|
|
||||||
|
|
||||||
public CursorInstruction(int x, int y, PNGImage image) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.image = image;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getX() {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getY() {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PNGImage getImage() {
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWidth() {
|
|
||||||
return getImage().getWidth();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeight() {
|
|
||||||
return getImage().getHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "cursor:"
|
|
||||||
+ getX() + ","
|
|
||||||
+ getY() + ","
|
|
||||||
+ Base64.toString(getImage().getData()) + ";";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@@ -1,72 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.instruction.framebuffer;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.instruction.Instruction;
|
|
||||||
|
|
||||||
public class DrawRectInstruction extends Instruction {
|
|
||||||
|
|
||||||
private final int x;
|
|
||||||
private final int y;
|
|
||||||
private final int width;
|
|
||||||
private final int height;
|
|
||||||
private final int color;
|
|
||||||
|
|
||||||
public DrawRectInstruction(int x, int y, int width, int height, int color) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getX() {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getY() {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWidth() {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeight() {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getColor() {
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
|
|
||||||
return "rect:"
|
|
||||||
+ getX() + ","
|
|
||||||
+ getY() + ","
|
|
||||||
+ getWidth() + ","
|
|
||||||
+ getHeight() + ","
|
|
||||||
+ String.format("#%06X", getColor()) + ";";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,95 +0,0 @@
|
|||||||
package net.sourceforge.guacamole.instruction.framebuffer;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.awt.image.BufferedImage;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import javax.imageio.IIOImage;
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.imageio.ImageWriter;
|
|
||||||
import javax.imageio.stream.ImageOutputStream;
|
|
||||||
import net.sourceforge.guacamole.GuacamoleException;
|
|
||||||
|
|
||||||
public class PNGImage {
|
|
||||||
|
|
||||||
private int width;
|
|
||||||
private int height;
|
|
||||||
private byte[] data;
|
|
||||||
|
|
||||||
public PNGImage(BufferedImage image) throws GuacamoleException {
|
|
||||||
|
|
||||||
width = image.getWidth();
|
|
||||||
height = image.getHeight();
|
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
try {
|
|
||||||
writeImage(image, bos);
|
|
||||||
bos.flush();
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new GuacamoleException("I/O Error while creating PNG.", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
data = bos.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getData() {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeight() {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWidth() {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void writeImage(BufferedImage image, OutputStream outputStream) throws GuacamoleException, IOException {
|
|
||||||
|
|
||||||
// Obtain list of image writers
|
|
||||||
// If no such writers exist, fail with error, exit.
|
|
||||||
Iterator<ImageWriter> writers = ImageIO.getImageWritersByMIMEType("image/png");
|
|
||||||
if (!writers.hasNext())
|
|
||||||
throw new GuacamoleException("No useful image writers found.");
|
|
||||||
|
|
||||||
// Obtain JPEG writer
|
|
||||||
ImageWriter imageWriter = writers.next();
|
|
||||||
|
|
||||||
// Setup image parameters (including compression quality)
|
|
||||||
/*ImageWriteParam imageParameters = new JPEGImageWriteParam(Locale.ENGLISH);
|
|
||||||
imageParameters.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
|
||||||
imageParameters.setCompressionQuality(0.6f); // 60% quality, currently...
|
|
||||||
imageParameters.setProgressiveMode(ImageWriteParam.MODE_DEFAULT);*/
|
|
||||||
|
|
||||||
ImageOutputStream out = ImageIO.createImageOutputStream(outputStream);
|
|
||||||
|
|
||||||
// Write image
|
|
||||||
imageWriter.setOutput(out);
|
|
||||||
imageWriter.write(null, new IIOImage(image, null, null), null/*imageParameters*/);
|
|
||||||
imageWriter.dispose();
|
|
||||||
|
|
||||||
out.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,65 +0,0 @@
|
|||||||
package net.sourceforge.guacamole.instruction.framebuffer;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.instruction.Instruction;
|
|
||||||
import net.sourceforge.guacamole.net.Base64;
|
|
||||||
|
|
||||||
public class PNGInstruction extends Instruction {
|
|
||||||
|
|
||||||
private int x;
|
|
||||||
private int y;
|
|
||||||
private PNGImage image;
|
|
||||||
|
|
||||||
public PNGInstruction(int x, int y, PNGImage image) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.image = image;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getX() {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getY() {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PNGImage getImage() {
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWidth() {
|
|
||||||
return getImage().getWidth();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeight() {
|
|
||||||
return getImage().getHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "png:"
|
|
||||||
+ getX() + ","
|
|
||||||
+ getY() + ","
|
|
||||||
+ Base64.toString(getImage().getData()) + ";";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@@ -27,7 +27,6 @@ import javax.servlet.http.HttpSessionBindingListener;
|
|||||||
import net.sourceforge.guacamole.Client;
|
import net.sourceforge.guacamole.Client;
|
||||||
import net.sourceforge.guacamole.GuacamoleClient;
|
import net.sourceforge.guacamole.GuacamoleClient;
|
||||||
import net.sourceforge.guacamole.GuacamoleException;
|
import net.sourceforge.guacamole.GuacamoleException;
|
||||||
import net.sourceforge.guacamole.instruction.Instruction;
|
|
||||||
import net.sourceforge.guacamole.event.KeyEvent;
|
import net.sourceforge.guacamole.event.KeyEvent;
|
||||||
import net.sourceforge.guacamole.event.PointerEvent;
|
import net.sourceforge.guacamole.event.PointerEvent;
|
||||||
|
|
||||||
@@ -59,26 +58,18 @@ public class GuacamoleSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void send(KeyEvent event) throws GuacamoleException {
|
public void write(char[] data, int off, int len) throws GuacamoleException {
|
||||||
client.send(event);
|
client.write(data, off, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void send(PointerEvent event) throws GuacamoleException {
|
public char[] read() throws GuacamoleException {
|
||||||
client.send(event);
|
return client.read();
|
||||||
}
|
|
||||||
|
|
||||||
public void setClipboard(String clipboard) throws GuacamoleException {
|
|
||||||
client.setClipboard(clipboard);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disconnect() throws GuacamoleException {
|
public void disconnect() throws GuacamoleException {
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Instruction nextInstruction(boolean blocking) throws GuacamoleException {
|
|
||||||
return client.nextInstruction(blocking);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GuacamoleSession(HttpSession session) throws GuacamoleException {
|
public GuacamoleSession(HttpSession session) throws GuacamoleException {
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
package net.sourceforge.guacamole.net.input;
|
package net.sourceforge.guacamole.net.input;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -23,46 +22,37 @@ import javax.servlet.ServletRequest;
|
|||||||
import net.sourceforge.guacamole.GuacamoleException;
|
import net.sourceforge.guacamole.GuacamoleException;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import net.sourceforge.guacamole.net.GuacamoleSession;
|
import net.sourceforge.guacamole.net.GuacamoleSession;
|
||||||
import net.sourceforge.guacamole.net.XMLGuacamoleServlet;
|
import net.sourceforge.guacamole.net.XMLGuacamoleServlet;
|
||||||
|
|
||||||
import java.io.IOException;
|
public class Inbound extends XMLGuacamoleServlet {
|
||||||
import java.io.Reader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Servlet which sets the clipboard data.
|
|
||||||
*
|
|
||||||
* This servlet takes one parameter:
|
|
||||||
* data: The data to set the clipboard to.
|
|
||||||
*
|
|
||||||
* @author Michael Jumper
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class Clipboard extends XMLGuacamoleServlet {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleRequest(GuacamoleSession session, ServletRequest request, Element root) throws GuacamoleException {
|
protected void handleRequest(GuacamoleSession session, ServletRequest request, Element root) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Send data
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Read data from request body
|
Reader input = request.getReader();
|
||||||
Reader reader = request.getReader();
|
char[] buffer = new char[8192];
|
||||||
StringBuilder data = new StringBuilder();
|
|
||||||
|
|
||||||
int codepoint;
|
int length;
|
||||||
while ((codepoint = reader.read()) != -1)
|
while ((length = input.read(buffer, 0, buffer.length)) != -1)
|
||||||
data.appendCodePoint(codepoint);
|
session.getClient().write(buffer, 0, length);
|
||||||
|
|
||||||
// Set clipboard
|
|
||||||
session.getClient().setClipboard(data.toString());
|
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
throw new GuacamoleException("I/O error sending clipboard to server: " + e.getMessage(), e);
|
throw new GuacamoleException("I/O Error sending data to server: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
catch (GuacamoleException e) {
|
catch (GuacamoleException e) {
|
||||||
throw new GuacamoleException("Error sending clipboard to server: " + e.getMessage(), e);
|
throw new GuacamoleException("Error sending data to server: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@@ -1,66 +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 net.sourceforge.guacamole.event.KeyEvent;
|
|
||||||
|
|
||||||
import net.sourceforge.guacamole.net.GuacamoleSession;
|
|
||||||
import net.sourceforge.guacamole.net.XMLGuacamoleServlet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Servlet which accepts keyboard input events, forwards these events to the
|
|
||||||
* client associated with the session, and returns the result (if any)
|
|
||||||
* to the HTTP client via XML.
|
|
||||||
*
|
|
||||||
* This servlet takes three parameters:
|
|
||||||
* index: The event index. As HTTP requests may arrive out of order,
|
|
||||||
* this index provides the event queue with a means of sorting
|
|
||||||
* events, and determining if events are missing. The first
|
|
||||||
* event has index 0.
|
|
||||||
* pressed: Whether the key was pressed (1) or released (0).
|
|
||||||
* keysym: The integer representing the corresponding X11 keysym.
|
|
||||||
*
|
|
||||||
* @author Michael Jumper
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class Key extends XMLGuacamoleServlet {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void handleRequest(GuacamoleSession session, ServletRequest request, Element root) throws GuacamoleException {
|
|
||||||
|
|
||||||
// Event parameters
|
|
||||||
int index = Integer.parseInt(request.getParameter("index"));
|
|
||||||
boolean pressed = request.getParameter("pressed").equals("1");
|
|
||||||
int keysym = Integer.parseInt(request.getParameter("keysym"));
|
|
||||||
|
|
||||||
// Send/queue event
|
|
||||||
try {
|
|
||||||
session.getClient().send(new KeyEvent(index, keysym, pressed));
|
|
||||||
}
|
|
||||||
catch (GuacamoleException e) {
|
|
||||||
throw new GuacamoleException("Error sending key event to server: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@@ -1,63 +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 net.sourceforge.guacamole.event.PointerEvent;
|
|
||||||
|
|
||||||
import net.sourceforge.guacamole.net.GuacamoleSession;
|
|
||||||
import net.sourceforge.guacamole.net.XMLGuacamoleServlet;
|
|
||||||
|
|
||||||
public class Pointer extends XMLGuacamoleServlet {
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void handleRequest(GuacamoleSession session, ServletRequest request, Element root) throws GuacamoleException {
|
|
||||||
// Event parameters
|
|
||||||
String[] events = request.getParameterValues("event");
|
|
||||||
|
|
||||||
for (String event : events) {
|
|
||||||
|
|
||||||
String[] parameters = event.split(",");
|
|
||||||
|
|
||||||
int index = Integer.parseInt(parameters[0]);
|
|
||||||
|
|
||||||
int x = Integer.parseInt(parameters[1]);
|
|
||||||
int y = Integer.parseInt(parameters[2]);
|
|
||||||
|
|
||||||
boolean left = parameters[3].equals("1");
|
|
||||||
boolean middle = parameters[4].equals("1");
|
|
||||||
boolean right = parameters[5].equals("1");
|
|
||||||
boolean up = parameters[6].equals("1");
|
|
||||||
boolean down = parameters[7].equals("1");
|
|
||||||
|
|
||||||
// Store event
|
|
||||||
try {
|
|
||||||
session.getClient().send(new PointerEvent(index, left, middle, right, up, down, x, y));
|
|
||||||
}
|
|
||||||
catch (GuacamoleException e) {
|
|
||||||
throw new GuacamoleException("Error sending pointer event to server: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@@ -18,12 +18,9 @@ package net.sourceforge.guacamole.net.output;
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.zip.DeflaterOutputStream;
|
|
||||||
import java.util.zip.GZIPOutputStream;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
@@ -31,8 +28,6 @@ import net.sourceforge.guacamole.Client;
|
|||||||
import net.sourceforge.guacamole.net.GuacamoleServlet;
|
import net.sourceforge.guacamole.net.GuacamoleServlet;
|
||||||
import net.sourceforge.guacamole.GuacamoleException;
|
import net.sourceforge.guacamole.GuacamoleException;
|
||||||
import net.sourceforge.guacamole.net.GuacamoleSession;
|
import net.sourceforge.guacamole.net.GuacamoleSession;
|
||||||
import net.sourceforge.guacamole.instruction.Instruction;
|
|
||||||
import net.sourceforge.guacamole.instruction.ErrorInstruction;
|
|
||||||
|
|
||||||
|
|
||||||
public class InstructionStream extends GuacamoleServlet {
|
public class InstructionStream extends GuacamoleServlet {
|
||||||
@@ -46,36 +41,7 @@ public class InstructionStream extends GuacamoleServlet {
|
|||||||
try {
|
try {
|
||||||
|
|
||||||
response.setContentType("text/plain");
|
response.setContentType("text/plain");
|
||||||
OutputStream out = response.getOutputStream();
|
Writer out = response.getWriter();
|
||||||
|
|
||||||
// Compress if enabled and supported by browser
|
|
||||||
if (session.getConfiguration().getCompressStream()) {
|
|
||||||
|
|
||||||
String encodingHeader = request.getHeader("Accept-Encoding");
|
|
||||||
if (encodingHeader != null) {
|
|
||||||
|
|
||||||
String[] encodings = encodingHeader.split(",");
|
|
||||||
for (String encoding : encodings) {
|
|
||||||
|
|
||||||
// Use gzip if supported
|
|
||||||
if (encoding.equals("gzip")) {
|
|
||||||
response.setHeader("Content-Encoding", "gzip");
|
|
||||||
out = new GZIPOutputStream(out);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use deflate if supported
|
|
||||||
if (encoding.equals("deflate")) {
|
|
||||||
response.setHeader("Content-Encoding", "deflate");
|
|
||||||
out = new DeflaterOutputStream(out);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
@@ -83,12 +49,11 @@ public class InstructionStream extends GuacamoleServlet {
|
|||||||
Client client = session.getClient();
|
Client client = session.getClient();
|
||||||
|
|
||||||
// For all messages, until another stream is ready (we send at least one message)
|
// For all messages, until another stream is ready (we send at least one message)
|
||||||
Instruction message = client.nextInstruction(true); // Block until first message is read
|
char[] message;
|
||||||
while (message != null) {
|
while ((message = client.read()) != null) {
|
||||||
|
|
||||||
// Get message output bytes
|
// Get message output bytes
|
||||||
byte[] outputBytes = message.toString().getBytes("UTF-8");
|
out.write(message, 0, message.length);
|
||||||
out.write(outputBytes);
|
|
||||||
out.flush();
|
out.flush();
|
||||||
response.flushBuffer();
|
response.flushBuffer();
|
||||||
|
|
||||||
@@ -96,14 +61,11 @@ public class InstructionStream extends GuacamoleServlet {
|
|||||||
if (instructionStreamLock.hasQueuedThreads())
|
if (instructionStreamLock.hasQueuedThreads())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
message = client.nextInstruction(false); // Read remaining messages, do not block.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (GuacamoleException e) {
|
catch (GuacamoleException e) {
|
||||||
Instruction message = new ErrorInstruction(e.getMessage());
|
out.write("error:" + e.getMessage() + ";");
|
||||||
byte[] outputBytes = message.toString().getBytes("UTF-8");
|
|
||||||
out.write(outputBytes);
|
|
||||||
out.flush();
|
out.flush();
|
||||||
response.flushBuffer();
|
response.flushBuffer();
|
||||||
}
|
}
|
||||||
|
@@ -53,31 +53,13 @@
|
|||||||
<url-pattern>/instructions</url-pattern>
|
<url-pattern>/instructions</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
<servlet>
|
<servlet>
|
||||||
<description>Clipboard input servlet.</description>
|
<description>Input servlet.</description>
|
||||||
<servlet-name>Clipboard</servlet-name>
|
<servlet-name>Inbound</servlet-name>
|
||||||
<servlet-class>net.sourceforge.guacamole.net.input.Clipboard</servlet-class>
|
<servlet-class>net.sourceforge.guacamole.net.input.Inbound</servlet-class>
|
||||||
</servlet>
|
</servlet>
|
||||||
<servlet-mapping>
|
<servlet-mapping>
|
||||||
<servlet-name>Clipboard</servlet-name>
|
<servlet-name>Inbound</servlet-name>
|
||||||
<url-pattern>/clipboard</url-pattern>
|
<url-pattern>/inbound</url-pattern>
|
||||||
</servlet-mapping>
|
|
||||||
<servlet>
|
|
||||||
<description>Key input servlet.</description>
|
|
||||||
<servlet-name>Key</servlet-name>
|
|
||||||
<servlet-class>net.sourceforge.guacamole.net.input.Key</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>Key</servlet-name>
|
|
||||||
<url-pattern>/key</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
<servlet>
|
|
||||||
<description>Pointer input servlet.</description>
|
|
||||||
<servlet-name>Pointer</servlet-name>
|
|
||||||
<servlet-class>net.sourceforge.guacamole.net.input.Pointer</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>Pointer</servlet-name>
|
|
||||||
<url-pattern>/pointer</url-pattern>
|
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
<security-constraint>
|
<security-constraint>
|
||||||
<display-name>Guacamole Access Restrictions</display-name>
|
<display-name>Guacamole Access Restrictions</display-name>
|
||||||
|
@@ -46,9 +46,6 @@ function VNCClient(display) {
|
|||||||
|| currentState == STATE_WAITING;
|
|| currentState == STATE_WAITING;
|
||||||
}
|
}
|
||||||
|
|
||||||
var keyIndex = 0;
|
|
||||||
var xmlIndex = 0;
|
|
||||||
|
|
||||||
// Layers
|
// Layers
|
||||||
var background = null;
|
var background = null;
|
||||||
var cursor = null;
|
var cursor = null;
|
||||||
@@ -118,17 +115,7 @@ function VNCClient(display) {
|
|||||||
this.enableKeyboard();
|
this.enableKeyboard();
|
||||||
|
|
||||||
function sendKeyEvent(pressed, keysym) {
|
function sendKeyEvent(pressed, keysym) {
|
||||||
|
sendMessage("key:" + keysym + "," + pressed + ";");
|
||||||
// Do not send requests if not connected
|
|
||||||
if (!isConnected())
|
|
||||||
return;
|
|
||||||
|
|
||||||
var key_xmlhttprequest = new XMLHttpRequest();
|
|
||||||
key_xmlhttprequest.open("GET",
|
|
||||||
"key?index=" + (keyIndex++)
|
|
||||||
+ "&pressed=" + pressed
|
|
||||||
+ "&keysym=" + keysym);
|
|
||||||
key_xmlhttprequest.send(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pressKey = function(keysym) {
|
this.pressKey = function(keysym) {
|
||||||
@@ -170,47 +157,63 @@ function VNCClient(display) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
var sendingMouseEvents = 0;
|
|
||||||
var mouseEventBuffer = "";
|
|
||||||
|
|
||||||
function sendMouseState(mouseState) {
|
function sendMouseState(mouseState) {
|
||||||
|
|
||||||
|
// Build mask
|
||||||
|
var buttonMask = 0;
|
||||||
|
if (mouseState.getLeft()) buttonMask |= 1;
|
||||||
|
if (mouseState.getMiddle()) buttonMask |= 2;
|
||||||
|
if (mouseState.getRight()) buttonMask |= 4;
|
||||||
|
if (mouseState.getUp()) buttonMask |= 8;
|
||||||
|
if (mouseState.getDown()) buttonMask |= 16;
|
||||||
|
|
||||||
|
// Send message
|
||||||
|
sendMessage("mouse:" + mouseState.getX() + "," + mouseState.getY() + "," + buttonMask + ";");
|
||||||
|
}
|
||||||
|
|
||||||
|
var sendingMessages = 0;
|
||||||
|
var outputMessageBuffer = "";
|
||||||
|
|
||||||
|
function sendMessage(message) {
|
||||||
|
|
||||||
// Do not send requests if not connected
|
// Do not send requests if not connected
|
||||||
if (!isConnected())
|
if (!isConnected())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Add event to queue, restart send loop if finished.
|
// Add event to queue, restart send loop if finished.
|
||||||
if (mouseEventBuffer.length > 0) mouseEventBuffer += "&";
|
outputMessageBuffer += message;
|
||||||
mouseEventBuffer += "event=" + mouseState.toString();
|
if (sendingMessages == 0)
|
||||||
if (sendingMouseEvents == 0)
|
sendPendingMessages();
|
||||||
sendPendingMouseEvents();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendPendingMouseEvents() {
|
function sendPendingMessages() {
|
||||||
|
|
||||||
// Do not send requests if not connected
|
// Do not send requests if not connected
|
||||||
if (!isConnected())
|
if (!isConnected())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mouseEventBuffer.length > 0) {
|
if (outputMessageBuffer.length > 0) {
|
||||||
|
|
||||||
sendingMouseEvents = 1;
|
sendingMessages = 1;
|
||||||
|
|
||||||
var mouse_xmlhttprequest = new XMLHttpRequest();
|
var message_xmlhttprequest = new XMLHttpRequest();
|
||||||
mouse_xmlhttprequest.open("GET", "pointer?" + mouseEventBuffer);
|
message_xmlhttprequest.open("POST", "inbound");
|
||||||
mouseEventBuffer = ""; // Clear buffer
|
message_xmlhttprequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||||
|
message_xmlhttprequest.setRequestHeader("Content-length", outputMessageBuffer.length);
|
||||||
|
|
||||||
// Once response received, send next queued event.
|
// Once response received, send next queued event.
|
||||||
mouse_xmlhttprequest.onreadystatechange = function() {
|
message_xmlhttprequest.onreadystatechange = function() {
|
||||||
if (mouse_xmlhttprequest.readyState == 4)
|
if (message_xmlhttprequest.readyState == 4)
|
||||||
sendPendingMouseEvents();
|
sendPendingMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
mouse_xmlhttprequest.send(null);
|
message_xmlhttprequest.send(outputMessageBuffer);
|
||||||
|
outputMessageBuffer = ""; // Clear buffer
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sendingMouseEvents = 0;
|
sendingMessages = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,10 +228,7 @@ function VNCClient(display) {
|
|||||||
if (!isConnected())
|
if (!isConnected())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var clipboard_xmlhttprequest = new XMLHttpRequest();
|
sendMessage("clipboard:" + escapeGuacamoleString(data) + ";");
|
||||||
clipboard_xmlhttprequest.open("POST", "clipboard");
|
|
||||||
clipboard_xmlhttprequest.send(data);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -387,6 +387,28 @@ function VNCClient(display) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function escapeGuacamoleString(str) {
|
||||||
|
|
||||||
|
var escapedString = "";
|
||||||
|
|
||||||
|
for (var i=0; i<str.length; i++) {
|
||||||
|
|
||||||
|
var c = str.charAt(i);
|
||||||
|
if (c == ",")
|
||||||
|
escapedString += "\\c";
|
||||||
|
else if (c == ";")
|
||||||
|
escapedString += "\\s";
|
||||||
|
else if (c == "\\")
|
||||||
|
escapedString += "\\\\";
|
||||||
|
else
|
||||||
|
escapedString += c;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return escapedString;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function unescapeGuacamoleString(str) {
|
function unescapeGuacamoleString(str) {
|
||||||
|
|
||||||
var unescapedString = "";
|
var unescapedString = "";
|
||||||
|
Reference in New Issue
Block a user