1 19 20 package com.sslexplorer.replacementproxy; 21 22 import java.io.ByteArrayOutputStream ; 23 import java.io.IOException ; 24 import java.io.InputStream ; 25 import java.io.OutputStream ; 26 import java.lang.reflect.Constructor ; 27 import java.net.URL ; 28 import java.text.SimpleDateFormat ; 29 import java.util.Iterator ; 30 import java.util.List ; 31 32 import org.apache.commons.logging.Log; 33 import org.apache.commons.logging.LogFactory; 34 35 import com.sslexplorer.boot.ReplacementEngine; 36 import com.sslexplorer.boot.Replacer; 37 import com.sslexplorer.boot.RequestHandlerResponse; 38 import com.sslexplorer.boot.Util; 39 import com.sslexplorer.policyframework.LaunchSession; 40 import com.sslexplorer.security.User; 41 import com.sslexplorer.webforwards.WebForwardDatabaseFactory; 42 import com.sslexplorer.webforwards.WebForwardTypes; 43 44 47 public class ProxiedResponseDispatcher { 48 49 final static Log log = LogFactory.getLog(ProxiedResponseDispatcher.class); 50 51 private RequestProcessor requestProcessor; 52 private ProxiedResponseProcessor responseProcessor; 53 private RequestHandlerResponse response; 54 private LaunchSession launchSession; 55 private ContentCache cache; 56 private SimpleDateFormat sdf; 57 private ReplacementProxyMethodHandler proxyMethodHandler; 58 59 public ProxiedResponseDispatcher(ReplacementProxyMethodHandler proxyMethodHandler, RequestProcessor requestProcessor, ProxiedResponseProcessor responseProcessor, 60 RequestHandlerResponse response, LaunchSession launchSession, ContentCache cache) { 61 this.proxyMethodHandler = proxyMethodHandler; 62 this.responseProcessor = responseProcessor; 63 this.requestProcessor = requestProcessor; 64 this.response = response; 65 this.cache = cache; 66 this.launchSession = launchSession; 67 sdf = new SimpleDateFormat ("EEEE, dd-MMM-yy HH:mm:ss zzz"); 68 69 } 70 71 public void sendResponse() throws Exception { 72 String type = responseProcessor.getContentType(); 75 if (type == null) { 76 type = requestProcessor.getSession().getServletContext().getMimeType( 78 requestProcessor.getRequestParameters().getProxiedURL().getFile()); 79 if (log.isDebugEnabled()) 80 log.debug("Guessed response type " + type + " from URL"); 81 } 82 else { 83 if (log.isDebugEnabled()) 84 log.debug("Sending response of type " + type); 85 } 86 if (type != null) { 87 response.setField("Content-Type", type); 88 } 89 90 int code = responseProcessor.getRequestDispatcher().getResponseCode(); 91 if (log.isDebugEnabled()) 92 log.debug("Sending response code " + code); 93 response.setStatus(code); 94 95 if(requestProcessor.getWebForward().getEncoding()==null || requestProcessor.getWebForward().getEncoding().equals(WebForwardTypes.DEFAULT_ENCODING)) { 97 if(responseProcessor.getCharset() != null) { 98 response.setCharacterEncoding(responseProcessor.getCharset()); 99 } 100 } else 101 response.setCharacterEncoding(requestProcessor.getWebForward().getEncoding()); 102 103 copyHeaders(); 105 106 OutputStream responseOut = getOutputStream(type); 108 109 InputStream serverIn = responseProcessor.getProxiedInputStream(); 111 User user = launchSession.getSession().getUser(); 112 113 if (serverIn != null) { 114 115 117 String mimeType = type; 118 int idx = mimeType == null ? -1 : mimeType.indexOf(";"); 119 if (idx != -1) { 120 mimeType = mimeType.substring(0, idx); 121 } 122 123 List replacements = WebForwardDatabaseFactory.getInstance().getReplacementsForContent( 125 user.getPrincipalName(), Replacement.REPLACEMENT_TYPE_RECEIVED_CONTENT, mimeType, 126 requestProcessor.getRequestParameters().getProxiedURL().toExternalForm()); 127 if (replacements.size() > 0) { 128 if (log.isDebugEnabled()) 130 log.debug("Found " + replacements.size() + ", processing"); 131 ReplacementEngine replace = new ReplacementEngine(); 132 133 if(!requestProcessor.getWebForward().getEncoding().equals(WebForwardTypes.DEFAULT_ENCODING)) 134 replace.setEncoding(requestProcessor.getWebForward().getEncoding()); 135 else 136 replace.setEncoding(responseProcessor.getCharset()); 137 138 replace.setCaseSensitive(false); 139 replace.setDotAll(true); 140 final BaseSearch baseSearch = new BaseSearch(); 141 replace.addPattern("(<base*\\s+(?:href)\\=['\\\"]*)([^\\s'>\\\"]*)([^>]*)(>)", baseSearch, ""); 142 143 Replacer replacer = new ProxyReplacer(requestProcessor, baseSearch); 144 145 for (Iterator i = replacements.iterator(); i.hasNext();) { 146 Replacement r = (Replacement) i.next(); 147 if (log.isDebugEnabled()) 148 log.debug("Adding replacement pattern '" + r.getMatchPattern() + "' = '" + r.getReplacePattern() + "'"); 149 if (r.getReplacePattern().startsWith("#")) { 150 String cn = r.getReplacePattern().substring(1); 151 try { 152 Class clazz = Class.forName(cn); 153 Constructor c = clazz.getConstructor(new Class [] { URL .class, String .class }); 154 Replacer re = (Replacer) (c.newInstance(new Object [] { requestProcessor.getRequestParameters().getProxiedURLBase(), requestProcessor.getLaunchId() })); 155 if (log.isDebugEnabled()) 156 log.debug("Loaded custom replacer " + cn + "."); 157 replace.addPattern(r.getMatchPattern(), re, null); 158 } catch (Throwable t) { 159 log.error("Could not load custom replacer " + cn + ".", t); 160 } 161 } else { 162 replace.addPattern(r.getMatchPattern(), replacer, r.getReplacePattern()); 163 } 164 } 165 166 OutputStream monitorOut = responseOut; 167 int origLen = responseProcessor.getContentLength(); 168 int len = origLen == -1 ? 1024 : responseProcessor.getContentLength(); 169 if (log.isDebugEnabled()) 170 log.debug("Reading response from target and processing into memory (" + len + " bytes buffer)"); 171 monitorOut = new ByteArrayOutputStream (len); 172 long length = replace.replace(serverIn, monitorOut); 173 if (log.isDebugEnabled()) 174 log.debug("Replacement complete"); 175 176 177 180 if (mimeType.equals("text/html") && requestProcessor.getWebForward().getFormType().equals(WebForwardTypes.FORM_SUBMIT_JAVASCRIPT) 181 && !Boolean.TRUE.equals(launchSession.getAttribute(ProxiedRequestDispatcher.LAUNCH_ATTR_AUTH_POSTED))) { 182 length = proxyMethodHandler.addJavaScriptAuthenticationCode(launchSession, monitorOut, length); 183 } 184 185 if (origLen != -1) { 186 if (log.isDebugEnabled()) 187 log.debug("New output length is " + length); 188 response.setContentLength((int) length); 189 } 190 if (log.isDebugEnabled()) 191 log.debug("Writing respone back to client"); 192 responseOut.write(((ByteArrayOutputStream ) monitorOut).toByteArray()); 193 } else { 194 if (log.isDebugEnabled()) 195 log.debug("Just copying content type of " + type); 196 Util.copy(serverIn, responseOut); 197 } 198 199 if (log.isDebugEnabled()) { 200 if (responseProcessor.isCacheable()) { 202 log.debug("Caching page " 203 + requestProcessor.getRequestParameters().getProxiedURL() 204 + (responseProcessor.getCacheExpiryDate() == null ? " (never expires)" : (" (expires on " + sdf 205 .format(responseProcessor.getCacheExpiryDate()))) + ")"); 206 if (!cache.store(requestProcessor.getRequestParameters().getProxiedURL(), (CacheingOutputStream) responseOut, responseProcessor 207 .getCacheExpiryDate() == null ? null : new Long (responseProcessor.getCacheExpiryDate().getTime()), 208 null)) { 209 log.warn("Failed to cache page " + requestProcessor.getRequestParameters().getProxiedURL()); 210 } else { 211 log.debug("Cached page " + requestProcessor.getRequestParameters().getProxiedURL()); 212 } 213 } else { 214 log.debug("Removing " + requestProcessor.getRequestParameters().getProxiedURL() + " from cache"); 215 cache.clear(requestProcessor.getRequestParameters().getProxiedURL()); 216 } 217 } 218 } else { 219 throw new Exception ("No streams."); 220 } 221 } 222 223 void copyHeaders() { 224 225 for (Iterator i = responseProcessor.getHeaders().iterator(); i.hasNext();) { 226 Header hi = (Header) i.next(); 227 228 229 response.addField(hi.getName(), hi.getVal()); 230 } 231 } 232 233 OutputStream getOutputStream(String type) throws IOException { 234 if (responseProcessor.isCacheable()) { 235 if (log.isDebugEnabled()) 236 log.debug("Opening output stream via a cache"); 237 return new CacheingOutputStream(response.getOutputStream(), responseProcessor.getContentLength() == -1 ? 1024 238 : responseProcessor.getContentLength(), responseProcessor.getHeaders(), type); 239 } else { 240 if (log.isDebugEnabled()) 241 log.debug("Opening non-cached output stream"); 242 return response.getOutputStream(); 243 } 244 } 245 } 246 | Popular Tags |