diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/CaptureClipboard.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/CaptureClipboard.java
new file mode 100644
index 000000000..0aaec2f8b
--- /dev/null
+++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/CaptureClipboard.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2013 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.glyptodon.guacamole.net.basic;
+
+import java.io.IOException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.glyptodon.guacamole.GuacamoleException;
+import org.glyptodon.guacamole.GuacamoleServerException;
+import org.glyptodon.guacamole.net.auth.UserContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Servlet which dumps the current contents of the clipboard.
+ *
+ * @author Michael Jumper
+ */
+public class CaptureClipboard extends AuthenticatingHttpServlet {
+
+ /**
+ * Logger for this class.
+ */
+ private Logger logger = LoggerFactory.getLogger(CaptureClipboard.class);
+
+ /**
+ * The amount of time to wait for clipboard changes, in milliseconds.
+ */
+ private static final int CLIPBOARD_TIMEOUT = 250;
+
+ @Override
+ protected void authenticatedService(
+ UserContext context,
+ HttpServletRequest request, HttpServletResponse response)
+ throws GuacamoleException {
+
+ // Get clipboard
+ final HttpSession session = request.getSession(true);
+ final ClipboardState clipboard = getClipboardState(session);
+
+ // FIXME: Don't do this
+ try {
+ Thread.sleep(CLIPBOARD_TIMEOUT);
+ }
+ catch (InterruptedException e) { /* ignore */ }
+
+ // Send clipboard contents
+ try {
+ response.setContentType("text/plain");
+ response.getWriter().print(clipboard.getContents());
+ }
+ catch (IOException e) {
+ throw new GuacamoleServerException("Unable to send clipboard contents", e);
+ }
+
+ }
+
+}
diff --git a/guacamole/src/main/webapp/WEB-INF/web.xml b/guacamole/src/main/webapp/WEB-INF/web.xml
index 3f6fb6ec6..12d25d1ca 100644
--- a/guacamole/src/main/webapp/WEB-INF/web.xml
+++ b/guacamole/src/main/webapp/WEB-INF/web.xml
@@ -59,6 +59,17 @@
/logout
+
+
+ Clipboard state servlet.
+ Clipboard
+ org.glyptodon.guacamole.net.basic.CaptureClipboard
+
+
+ Clipboard
+ /clipboard
+
+
Connection creation servlet.
diff --git a/guacamole/src/main/webapp/client.xhtml b/guacamole/src/main/webapp/client.xhtml
index 16bf7ba2a..1ed96f7cd 100644
--- a/guacamole/src/main/webapp/client.xhtml
+++ b/guacamole/src/main/webapp/client.xhtml
@@ -66,6 +66,7 @@
+
diff --git a/guacamole/src/main/webapp/scripts/client-ui.js b/guacamole/src/main/webapp/scripts/client-ui.js
index 52beedb80..f3cff081d 100644
--- a/guacamole/src/main/webapp/scripts/client-ui.js
+++ b/guacamole/src/main/webapp/scripts/client-ui.js
@@ -985,16 +985,16 @@ GuacUI.Client.attach = function(guac) {
// Set local clipboard contents on cut
document.body.addEventListener("cut", function handle_cut(e) {
- /* STUB */
e.preventDefault();
- e.clipboardData.setData("text/plain", "STUB: CUT");
+ var data = GuacamoleService.Clipboard.get();
+ e.clipboardData.setData("text/plain", data);
}, false);
// Set local clipboard contents on copy
document.body.addEventListener("copy", function handle_copy(e) {
- /* STUB */
e.preventDefault();
- e.clipboardData.setData("text/plain", "STUB: COPY");
+ var data = GuacamoleService.Clipboard.get();
+ e.clipboardData.setData("text/plain", data);
}, false);
// Set remote clipboard contents on paste
diff --git a/guacamole/src/main/webapp/scripts/service.js b/guacamole/src/main/webapp/scripts/service.js
index 0e0e46973..9a2efc833 100644
--- a/guacamole/src/main/webapp/scripts/service.js
+++ b/guacamole/src/main/webapp/scripts/service.js
@@ -1410,3 +1410,28 @@ GuacamoleService.Protocols = {
}
};
+
+/**
+ * Collection of service functions which deal with the clipboard state. Each
+ * function makes an explicit HTTP query to the server, and parses the response.
+ */
+GuacamoleService.Clipboard = {
+
+ "get" : function(parameters) {
+
+ // Construct request URL
+ var list_url = "clipboard";
+ if (parameters) list_url += "?" + parameters;
+
+ // Get permission list
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", list_url, false);
+ xhr.send(null);
+
+ // Handle response
+ GuacamoleService.handleResponse(xhr);
+ return xhr.responseText;
+
+ }
+
+};