From a5e7cecc27e491da4a7f8daf0b1ae1cc787dfe26 Mon Sep 17 00:00:00 2001 From: James Muehlner Date: Mon, 14 Dec 2015 22:09:05 -0800 Subject: [PATCH] GUAC-1427: Copy parameter values from request to new object since we can't keep the original request around. --- .../net/basic/HTTPTunnelRequest.java | 50 ++++++++++++++----- .../BasicGuacamoleWebSocketTunnelServlet.java | 7 ++- .../GuacamoleWebSocketTunnelServlet.java | 12 +++-- .../BasicGuacamoleWebSocketTunnelServlet.java | 7 ++- .../GuacamoleWebSocketTunnelServlet.java | 30 +++++++---- 5 files changed, 70 insertions(+), 36 deletions(-) diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/HTTPTunnelRequest.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/HTTPTunnelRequest.java index 3aab28006..aaf025f92 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/HTTPTunnelRequest.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/HTTPTunnelRequest.java @@ -22,8 +22,11 @@ package org.glyptodon.guacamole.net.basic; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import javax.servlet.http.HttpServletRequest; /** @@ -34,33 +37,54 @@ import javax.servlet.http.HttpServletRequest; public class HTTPTunnelRequest extends TunnelRequest { /** - * The wrapped HttpServletRequest. + * A copy of the parameters obtained from the HttpServletRequest used to + * construct the HttpTunnelRequest. */ - private final HttpServletRequest request; + private final Map> parameterMap = + new HashMap>(); /** - * Creates a TunnelRequest implementation which delegates parameter and - * session retrieval to the given HttpServletRequest. + * Creates a HTTPTunnelRequest which copies and exposes the parameters + * from the given HttpServletRequest. * - * @param request The HttpServletRequest to wrap. + * @param request + * The HttpServletRequest to copy parameter values from. */ + @SuppressWarnings("unchecked") // getParameterMap() is defined as returning Map public HTTPTunnelRequest(HttpServletRequest request) { - this.request = request; + + // For each parameter + for (Map.Entry mapEntry : ((Map) + request.getParameterMap()).entrySet()) { + + // Get parameter name and corresponding values + String parameterName = mapEntry.getKey(); + List parameterValues = Arrays.asList(mapEntry.getValue()); + + // Store copy of all values in our own map + parameterMap.put( + parameterName, + new ArrayList(parameterValues) + ); + + } + } @Override public String getParameter(String name) { - return request.getParameter(name); + List values = getParameterValues(name); + + // Return the first value from the list if available + if (values != null && !values.isEmpty()) + return values.get(0); + + return null; } @Override public List getParameterValues(String name) { - - String[] values = request.getParameterValues(name); - if (values == null) - return null; - - return Arrays.asList(values); + return parameterMap.get(name); } } diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty8/BasicGuacamoleWebSocketTunnelServlet.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty8/BasicGuacamoleWebSocketTunnelServlet.java index 035e8d3c1..418e16714 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty8/BasicGuacamoleWebSocketTunnelServlet.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty8/BasicGuacamoleWebSocketTunnelServlet.java @@ -24,11 +24,10 @@ package org.glyptodon.guacamole.net.basic.websocket.jetty8; import com.google.inject.Inject; import com.google.inject.Singleton; -import javax.servlet.http.HttpServletRequest; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.GuacamoleTunnel; import org.glyptodon.guacamole.net.basic.TunnelRequestService; -import org.glyptodon.guacamole.net.basic.HTTPTunnelRequest; +import org.glyptodon.guacamole.net.basic.TunnelRequest; /** * Tunnel servlet implementation which uses WebSocket as a tunnel backend, @@ -45,9 +44,9 @@ public class BasicGuacamoleWebSocketTunnelServlet extends GuacamoleWebSocketTunn private TunnelRequestService tunnelRequestService; @Override - protected GuacamoleTunnel doConnect(HttpServletRequest request) + protected GuacamoleTunnel doConnect(TunnelRequest request) throws GuacamoleException { - return tunnelRequestService.createTunnel(new HTTPTunnelRequest(request)); + return tunnelRequestService.createTunnel(request); } } diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty8/GuacamoleWebSocketTunnelServlet.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty8/GuacamoleWebSocketTunnelServlet.java index df5806822..75a978738 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty8/GuacamoleWebSocketTunnelServlet.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty8/GuacamoleWebSocketTunnelServlet.java @@ -33,6 +33,8 @@ import org.eclipse.jetty.websocket.WebSocket.Connection; import org.eclipse.jetty.websocket.WebSocketServlet; import org.glyptodon.guacamole.GuacamoleClientException; import org.glyptodon.guacamole.GuacamoleConnectionClosedException; +import org.glyptodon.guacamole.net.basic.HTTPTunnelRequest; +import org.glyptodon.guacamole.net.basic.TunnelRequest; import org.glyptodon.guacamole.protocol.GuacamoleStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -70,7 +72,9 @@ public abstract class GuacamoleWebSocketTunnelServlet extends WebSocketServlet { } @Override - public WebSocket doWebSocketConnect(final HttpServletRequest request, String protocol) { + public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) { + + final TunnelRequest tunnelRequest = new HTTPTunnelRequest(request); // Return new WebSocket which communicates through tunnel return new WebSocket.OnTextMessage() { @@ -109,7 +113,7 @@ public abstract class GuacamoleWebSocketTunnelServlet extends WebSocketServlet { public void onOpen(final Connection connection) { try { - tunnel = doConnect(request); + tunnel = doConnect(tunnelRequest); } catch (GuacamoleException e) { logger.error("Creation of WebSocket tunnel to guacd failed: {}", e.getMessage()); @@ -209,7 +213,7 @@ public abstract class GuacamoleWebSocketTunnelServlet extends WebSocketServlet { * result of this connection request (whether some sort of credentials must * be specified, for example). * - * @param request The HttpServletRequest associated with the connection + * @param request The TunnelRequest associated with the connection * request received. Any parameters specified along with * the connection request can be read from this object. * @return A newly constructed GuacamoleTunnel if successful, @@ -218,7 +222,7 @@ public abstract class GuacamoleWebSocketTunnelServlet extends WebSocketServlet { * GuacamoleTunnel, or if the conditions * required for connection are not met. */ - protected abstract GuacamoleTunnel doConnect(HttpServletRequest request) + protected abstract GuacamoleTunnel doConnect(TunnelRequest request) throws GuacamoleException; } diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/BasicGuacamoleWebSocketTunnelServlet.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/BasicGuacamoleWebSocketTunnelServlet.java index d0de4cbf3..a891575a8 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/BasicGuacamoleWebSocketTunnelServlet.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/BasicGuacamoleWebSocketTunnelServlet.java @@ -24,11 +24,10 @@ package org.glyptodon.guacamole.net.basic.websocket.tomcat; import com.google.inject.Inject; import com.google.inject.Singleton; -import javax.servlet.http.HttpServletRequest; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.GuacamoleTunnel; import org.glyptodon.guacamole.net.basic.TunnelRequestService; -import org.glyptodon.guacamole.net.basic.HTTPTunnelRequest; +import org.glyptodon.guacamole.net.basic.TunnelRequest; /** * Tunnel servlet implementation which uses WebSocket as a tunnel backend, @@ -45,9 +44,9 @@ public class BasicGuacamoleWebSocketTunnelServlet extends GuacamoleWebSocketTunn private TunnelRequestService tunnelRequestService; @Override - protected GuacamoleTunnel doConnect(HttpServletRequest request) + protected GuacamoleTunnel doConnect(TunnelRequest request) throws GuacamoleException { - return tunnelRequestService.createTunnel(new HTTPTunnelRequest(request)); + return tunnelRequestService.createTunnel(request); }; } diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/GuacamoleWebSocketTunnelServlet.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/GuacamoleWebSocketTunnelServlet.java index ed37a9e76..fb94371dc 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/GuacamoleWebSocketTunnelServlet.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/GuacamoleWebSocketTunnelServlet.java @@ -38,6 +38,8 @@ import org.apache.catalina.websocket.WebSocketServlet; import org.apache.catalina.websocket.WsOutbound; import org.glyptodon.guacamole.GuacamoleClientException; import org.glyptodon.guacamole.GuacamoleConnectionClosedException; +import org.glyptodon.guacamole.net.basic.HTTPTunnelRequest; +import org.glyptodon.guacamole.net.basic.TunnelRequest; import org.glyptodon.guacamole.protocol.GuacamoleStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -93,7 +95,9 @@ public abstract class GuacamoleWebSocketTunnelServlet extends WebSocketServlet { @Override public StreamInbound createWebSocketInbound(String protocol, - final HttpServletRequest request) { + HttpServletRequest request) { + + final TunnelRequest tunnelRequest = new HTTPTunnelRequest(request); // Return new WebSocket which communicates through tunnel return new StreamInbound() { @@ -137,7 +141,7 @@ public abstract class GuacamoleWebSocketTunnelServlet extends WebSocketServlet { public void onOpen(final WsOutbound outbound) { try { - tunnel = doConnect(request); + tunnel = doConnect(tunnelRequest); } catch (GuacamoleException e) { logger.error("Creation of WebSocket tunnel to guacd failed: {}", e.getMessage()); @@ -242,16 +246,20 @@ public abstract class GuacamoleWebSocketTunnelServlet extends WebSocketServlet { * result of this connection request (whether some sort of credentials must * be specified, for example). * - * @param request The HttpServletRequest associated with the connection - * request received. Any parameters specified along with - * the connection request can be read from this object. - * @return A newly constructed GuacamoleTunnel if successful, - * null otherwise. - * @throws GuacamoleException If an error occurs while constructing the - * GuacamoleTunnel, or if the conditions - * required for connection are not met. + * @param request + * The TunnelRequest associated with the connection request received. + * Any parameters specified along with the connection request can be + * read from this object. + * + * @return + * A newly constructed GuacamoleTunnel if successful, null otherwise. + * + * @throws GuacamoleException + * If an error occurs while constructing the GuacamoleTunnel, or if the + * conditions required for connection are not met. */ - protected abstract GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException; + protected abstract GuacamoleTunnel doConnect(TunnelRequest request) + throws GuacamoleException; }