From 06da6f517c45e1afc64d7eda5185599b82c0159d Mon Sep 17 00:00:00 2001 From: reger Date: Sun, 27 Oct 2013 05:04:24 +0100 Subject: [PATCH] add YaCyProxyServlet to handle /proxy.html?url=proxyurl - based on Jetty ProxyServlet - at this time use existing HTTPD ProxyHandler for url rewrite - add jetty-client jar (dependency in Jetty ProxyServlet) reuse ProxyHandler.convertHeaderFromJetty in YaCyDefaultServlet --- build.xml | 3 +- lib/jetty-client-8.1.13.v20130916.jar | Bin 0 -> 88251 bytes libt/ProxyServlet.java | 418 ++++++++++++++++++ .../net/yacy/http/Jetty8HttpServerImpl.java | 5 +- source/net/yacy/http/YaCyDefaultServlet.java | 14 +- source/net/yacy/http/YaCyProxyServlet.java | 377 ++++++++++++++++ 6 files changed, 802 insertions(+), 15 deletions(-) create mode 100644 lib/jetty-client-8.1.13.v20130916.jar create mode 100644 libt/ProxyServlet.java create mode 100644 source/net/yacy/http/YaCyProxyServlet.java diff --git a/build.xml b/build.xml index 78a41e8b5..4b1ea5036 100644 --- a/build.xml +++ b/build.xml @@ -161,6 +161,7 @@ + @@ -169,7 +170,7 @@ - + diff --git a/lib/jetty-client-8.1.13.v20130916.jar b/lib/jetty-client-8.1.13.v20130916.jar new file mode 100644 index 0000000000000000000000000000000000000000..ffb8cef919004e7cef87807007b12f9ef1809f6f GIT binary patch literal 88251 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>*U(LE!$#K3#uKD(L3K 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®&8n4H=SAT_w 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 BAjkj! literal 0 HcmV?d00001 diff --git a/libt/ProxyServlet.java b/libt/ProxyServlet.java new file mode 100644 index 000000000..19b156ac0 --- /dev/null +++ b/libt/ProxyServlet.java @@ -0,0 +1,418 @@ +// package de.spieleck.servlets; +// ProxyServlet - serving pages from foreign servers.... +// + +import java.io.*; +import java.net.*; +import java.lang.Integer; +import java.util.StringTokenizer; + +import javax.servlet.*; +import javax.servlet.http.*; + +/** + * Serves pages which are fetched from another HTTP-Server + * useful for going thru firewalls and other trickery... + *

+ * The communication is somewhat this way: + *

    + *
  • Client requests data from servlet + *
  • Servlet interprets path and requests data from remote server + *
  • Servlet obtains answer from remote server and forwards it to client + *
  • Client obtains answer + *
+ *

+ * XXX There is a problem with If-Modified and If-None-Match requests: + * the 304 Not Modified answer does not go thru the servelet in the + * backward direction. It could be that the HttpServletResponse does hava + * some sideeffects which are not helpfull in this special situation. + * This type of request is currently avoided by removing all "If-" requests. + *
+ * Note: This servlet is actually buggy. It is buggy since it does + * not solve all problems, it only solves the problems I needed to solve. + * Many thanks to Thorsten Gast the creator of dirjack + * for pointing at least some bugs. + * @author
Frank Nestel. + */ + +public class ProxyServlet extends HttpServlet +{ + /** + * "Official" HTTP line end + */ + public final static String CRLF = "\r\n"; + public final static String LF = "\n"; + + /** + * remote path + */ + protected String remotePath; + + /** + * remote server + */ + protected String remoteServer; + + /** + * Port at remote server + */ + protected int remotePort; + + /** + * Debug mode? + */ + protected boolean debugFlag; + + /** Init + */ + public void init(ServletConfig config) + throws ServletException + { + super.init(config); + remotePath = getInitParameter("remotePath"); + remoteServer = getInitParameter("remoteServer"); + String remotePortStr= getInitParameter("remotePort"); + if ( remotePath == null || remoteServer == null ) + throw new ServletException( + "Servlet needs remotePath & remoteServer."); + if ( remotePortStr != null ) + { + try + { + remotePort = Integer.parseInt(remotePortStr); + } + catch ( Exception e ) + { + throw new ServletException("Port must be a number!"); + } + } + else + remotePort = 80; + if ( "".equals(remotePath) ) + remotePath = ""; // XXX ??? "/" + else if ( remotePath.charAt(0) != '/' ) + remotePath = "/"+remotePath; + debugFlag = "true".equals(getInitParameter("debug")); + // + log("remote="+remoteServer+" "+remotePort+" "+remotePath); + } + + /// Returns a string containing information about the author, version, and + // copyright of the servlet. + public String getServletInfo() + { + return "Online redirecting content."; + } + + /// Services a single request from the client. + // @param req the servlet request + // @param req the servlet response + // @exception ServletException when an exception has occurred + public void service( HttpServletRequest req, HttpServletResponse res ) + throws ServletException, IOException + { + // + // Connect to "remote" server: + Socket sock; + OutputStream out; + InputStream in; + // + try + { + sock = new Socket(remoteServer, remotePort); // !!!!!!!! + out = new BufferedOutputStream(sock.getOutputStream()); + in = new BufferedInputStream(sock.getInputStream()); + } + catch (IOException e) + { + res.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + "Socket opening: "+remoteServer+" "+remotePort); + return; + } + try + { + // + // Build up a HTTP request from pure strings: + StringBuffer sb = new StringBuffer(200); + sb.append(req.getMethod()); + sb.append(' '); + String pi = req.getPathInfo(); + sb.append(remotePath); + if ( pi != null ) + { + appendCleaned(sb, pi); + } + else + sb.append("/"); + if ( req.getQueryString() != null ) + { + sb.append('?'); + appendCleaned(sb, req.getQueryString()); + } + sb.append(' '); + sb.append("HTTP/1.0"); + sb.append(CRLF); + log(sb.toString()); + out.write(sb.toString().getBytes()); + java.util.Enumeration en = req.getHeaderNames(); + while ( en.hasMoreElements() ) + { + String k = (String) en.nextElement(); + // Filter incoming headers: + if ( "Host".equalsIgnoreCase(k) ) + { + sb.setLength(0); + sb.append(k); + sb.append(": "); + sb.append(remoteServer); + sb.append(":"); + sb.append(remotePort); + sb.append(CRLF); + log("c["+k+"]: "+sb+" "+req.getHeader(k)); + out.write(sb.toString().getBytes()); + } + // + // Throw away persistant connections between servers + // Throw away request potentially causing a 304 response. + else if ( + ! "Connection".equalsIgnoreCase(k) + && ! "If-Modified-Since".equalsIgnoreCase(k) + && ! "If-None-Match".equalsIgnoreCase(k) + ) + { + sb.setLength(0); + sb.append(k); + sb.append(": "); + sb.append(req.getHeader(k)); + sb.append(CRLF); + log("=["+k+"]: "+req.getHeader(k)); + out.write(sb.toString().getBytes()); + } + else + { + log("*["+k+"]: "+req.getHeader(k)); + } + } + // Finish request header by an empty line + out.write(CRLF.getBytes()); + // Copy post data + InputStream inr = req.getInputStream(); + copyStream(inr, out); + out.flush(); + log("Remote request finished. Reading answer."); + + // Now we have finished the outgoing request. + // We'll now see, what is coming back from remote: + + // Get the answer, treat its header and copy the stream data: + if ( treatHeader(in, req, res) ) + { + log("+ copyStream"); + // if ( debugFlag ) res.setContentType("text/plain"); + out = res.getOutputStream(); + copyStream(in, out); + } + else + log("- copyStream"); + } + catch (IOException e) + { + log("out-in.open!"); + // res.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + // "out-in open!"); + return; + } + try + { + // out.close(); + in.close(); + sock.close(); + } + catch (IOException ignore) + { + log("Exception "+ignore); + } + } + + public static void appendCleaned(StringBuffer sb, String str) + { + for(int i = 0; i < str.length(); i++) + { + char ch = str.charAt(i); + if ( ch == ' ' ) + sb.append("%20"); + else + sb.append(ch); + } + } + + + /** + * Forward and filter header from backend Request. + */ + private boolean treatHeader(InputStream in, + HttpServletRequest req, + HttpServletResponse res) + throws ServletException + { + boolean retval = true; + byte[] lineBytes = new byte[4096]; + int len; + String line; + + try + { + // Read the first line of the request. + len = readLine(in, lineBytes ); + if ( len == -1 || len == 0 ) + throw new ServletException( "No Request found in Data." ); +{ + String line2 = new String( lineBytes, 0, len ); + log("head: "+line2+" "+len); +} + + // We mainly skip the header by the foreign server + // assuming, that we can handle protocoll mismatch or so! + res.setHeader("viaJTTP","JTTP"); + + // Some more headers require special care .... + boolean firstline = true; + // Shortcut evaluation skips the read on first time! + while ( firstline || ((len=readLine(in,lineBytes)) > 0) ) + { + line = new String( lineBytes, 0, len ); + int colonPos = line.indexOf( ":" ); + if ( firstline && colonPos == -1 ) + { + // Special first line considerations ... + String headl[] = wordStr(line); +log("head: "+line+" "+headl.length); + try + { + res.setStatus(Integer.parseInt(headl[1])); + } + catch ( NumberFormatException ignore ) + { + log("ID exception: "+headl); + } + catch ( Exception panik ) + { + log("First line invalid!"); + return true; + } + } + else if ( colonPos != -1 ) + { + String head = line.substring(0,colonPos); + // XXX Skip LWS (what is LWS) + int i = colonPos + 1; + while ( isLWS(line.charAt(i)) ) i++; + String value= line.substring(i); +log("<"+head+">=<"+ value+">"); + if ( head.equalsIgnoreCase("Location") ) + { + // res.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); + // res.setHeader(head, value ); + log("Location cutted: "+value); + } + else if ( head.equalsIgnoreCase( "Content-type" ) ) + res.setContentType( value ); + else if ( head.equalsIgnoreCase( "Content-length" ) ) + { + try + { + int cLen = Integer.parseInt( value ); + retval = ( cLen > 0 ); + res.setContentLength(cLen); + } + catch ( NumberFormatException ignore ) {} + } + // Generically treat unknown headers + else + { + log("^- generic."); + res.setHeader(head, value ); + } + } + // XXX We do not treat multiline continuation Headers here + // which have not occured anywhere yet. + firstline = false; + } + } + catch ( IOException e ) + { + log("Header skip problem:"); + throw new ServletException("Header skip problem: "+e.getMessage()); + } +log( "--------------" ); + return retval; + } + + /** + * Read a RFC2616 line from an InputStream: + */ + public int readLine(InputStream in, byte[] b ) + throws IOException + { + int off2 = 0; + while ( off2 < b.length ) + { + int r = in.read(); + if ( r == -1 ) + { + if (off2 == 0 ) + return -1; + break; + } + if ( r == 13 ) + continue; + if ( r == 10 ) + break; + b[off2] = (byte) r; + ++off2; + } + return off2; + } + + /** Copy a file from in to out. + * Sub-classes can override this in order to do filtering of some sort. + */ + public void copyStream( InputStream in, OutputStream out ) + throws IOException + { + BufferedInputStream bin = new BufferedInputStream(in); + int b; + while ( ( b = bin.read() ) != -1 ) + out.write(b); + } + + /** + * Split a blank separated string into + */ + public String[] wordStr( String inp ) + { + StringTokenizer tok = new StringTokenizer(inp, " "); + int i, n = tok.countTokens(); + String[] res = new String[n]; + for(i = 0; i < n; i++ ) + res[i] = tok.nextToken(); + return res; + } + + /** + * XXX Should identify RFC2616 LWS + */ + protected boolean isLWS(char c) + { + return c == ' '; + } + + /** + * Capture awaay the standard servlet log .. + */ + public void log(String msg) + { + if ( debugFlag ) + System.err.println("## "+msg); + } +} diff --git a/source/net/yacy/http/Jetty8HttpServerImpl.java b/source/net/yacy/http/Jetty8HttpServerImpl.java index 5bc25f87d..c75d28ed9 100644 --- a/source/net/yacy/http/Jetty8HttpServerImpl.java +++ b/source/net/yacy/http/Jetty8HttpServerImpl.java @@ -63,7 +63,7 @@ public class Jetty8HttpServerImpl implements YaCyHttpServer { connector.setName("httpd:"+Integer.toString(port)); //connector.setThreadPool(new QueuedThreadPool(20)); server.addConnector(connector); - + YacyDomainHandler domainHandler = new YacyDomainHandler(); domainHandler.setAlternativeResolver(sb.peers); @@ -91,6 +91,9 @@ public class Jetty8HttpServerImpl implements YaCyHttpServer { sholder.setInitParameter("gzip","false"); htrootContext.addServlet(sholder,"/*"); + ServletHolder proxyholder= new ServletHolder(YaCyProxyServlet.class); + htrootContext.addServlet(proxyholder,"/proxy.html"); + // assemble the servlet handlers ContextHandlerCollection servletContext = new ContextHandlerCollection(); servletContext.setHandlers(new Handler[] { solrContext, htrootContext }); diff --git a/source/net/yacy/http/YaCyDefaultServlet.java b/source/net/yacy/http/YaCyDefaultServlet.java index b5f26b0b1..8cf1e81f3 100644 --- a/source/net/yacy/http/YaCyDefaultServlet.java +++ b/source/net/yacy/http/YaCyDefaultServlet.java @@ -49,7 +49,6 @@ import net.yacy.cora.date.GenericFormatter; import net.yacy.cora.document.analysis.Classification; import net.yacy.cora.protocol.HeaderFramework; import net.yacy.cora.protocol.RequestHeader; -import net.yacy.cora.protocol.ResponseHeader; import net.yacy.cora.util.ConcurrentLog; import net.yacy.kelondro.util.FileUtils; import net.yacy.kelondro.util.MemoryControl; @@ -76,7 +75,6 @@ import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.resource.ResourceFactory; /** * YaCyDefaultServlet based on Jetty DefaultServlet.java @@ -480,17 +478,7 @@ public abstract class YaCyDefaultServlet extends HttpServlet { } protected RequestHeader generateLegacyRequestHeader(HttpServletRequest request, String target, String targetExt) { - RequestHeader legacyRequestHeader = new RequestHeader(); - @SuppressWarnings("unchecked") - Enumeration headers = request.getHeaderNames(); - while (headers.hasMoreElements()) { - String headerName = headers.nextElement(); - @SuppressWarnings("unchecked") - Enumeration header = request.getHeaders(headerName); - while (header.hasMoreElements()) { - legacyRequestHeader.add(headerName, header.nextElement()); - } - } + RequestHeader legacyRequestHeader = ProxyHandler.convertHeaderFromJetty(request); legacyRequestHeader.put(HeaderFramework.CONNECTION_PROP_CLIENTIP, request.getRemoteAddr()); legacyRequestHeader.put(HeaderFramework.CONNECTION_PROP_PATH, target); diff --git a/source/net/yacy/http/YaCyProxyServlet.java b/source/net/yacy/http/YaCyProxyServlet.java new file mode 100644 index 000000000..078dbdb7a --- /dev/null +++ b/source/net/yacy/http/YaCyProxyServlet.java @@ -0,0 +1,377 @@ +package net.yacy.http; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLDecoder; +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import net.yacy.cora.document.encoding.UTF8; +import net.yacy.cora.document.id.DigestURL; +import net.yacy.cora.document.id.MultiProtocolURL; +import net.yacy.cora.protocol.ClientIdentification; +import net.yacy.cora.protocol.HeaderFramework; +import net.yacy.cora.protocol.RequestHeader; +import net.yacy.cora.protocol.ResponseHeader; +import net.yacy.cora.util.ConcurrentLog; +import net.yacy.kelondro.util.FileUtils; +import net.yacy.search.Switchboard; +import net.yacy.server.http.ChunkedInputStream; +import net.yacy.server.http.HTTPDProxyHandler; +import org.eclipse.jetty.continuation.Continuation; +import org.eclipse.jetty.continuation.ContinuationSupport; +import org.eclipse.jetty.http.HttpURI; +import org.eclipse.jetty.servlets.ProxyServlet; + +/** + * Servlet to implement proxy via url parameter "/proxy.html?url=xyz_urltoproxy" + * this implementation uses the existing proxy functions from YaCy HTTPDProxyHandler + * + * InitParameters + * ProxyHost : hostname of proxy host, default is "localhost" + * ProxyPort : port of the proxy host, default 8090 + * + * functionality + * - get parameters + * - convert headers to YaCy style headers and parameters + * - call existing HTTPDProxy + * - revert response headers back from YaCy style to servlet specification + * - handle rewrite of link (to point to proxy) + * - send to client + * + * later improvemnts should/could use implementation to avoid back and forth converting + * between YaCy and Servlet header/parameter style and use proxy implementation within + * servlet specification or a existing reverse-proxy library. + * + */ +public class YaCyProxyServlet extends ProxyServlet implements Servlet { + + @Override + public void init(ServletConfig config) throws ServletException { + super.init(config); + + // must be lower case (header names are internally converted to lower) + _DontProxyHeaders.add("host"); // to prevent Host header setting from original servletrequest (which is localhost) + + } + /* ------------------------------------------------------------ */ + + @Override + public void service (ServletRequest req, ServletResponse res) throws ServletException, IOException { + + final HttpServletRequest request = (HttpServletRequest) req; + final HttpServletResponse response = (HttpServletResponse) res; + + if ("CONNECT".equalsIgnoreCase(request.getMethod())) { + handleConnect(request, response); + } else { + String action = null; + + final Continuation continuation = ContinuationSupport.getContinuation(request); + + if (!continuation.isInitial()) { + response.sendError(HttpServletResponse.SC_GATEWAY_TIMEOUT); // Need better test that isInitial + return; + } else { + URL proxyurl = null; + String strARGS = request.getQueryString(); + if (strARGS == null) { + response.sendError(HttpServletResponse.SC_NOT_FOUND,"url parameter missing"); + return; + } + + if (strARGS.startsWith("action=")) { + int detectnextargument = strARGS.indexOf("&"); + action = strARGS.substring(7, detectnextargument); + strARGS = strARGS.substring(detectnextargument + 1); + } + if (strARGS.startsWith("url=")) { + final String strUrl = strARGS.substring(4); // strip "url=" + + try { + proxyurl = new URL(strUrl); + } catch (final MalformedURLException e) { + proxyurl = new URL(URLDecoder.decode(strUrl, UTF8.charset.name())); + + } + } + if (proxyurl == null) { + response.sendError(HttpServletResponse.SC_NOT_FOUND,"url parameter missing"); + return; + } + int port = proxyurl.getPort(); + if (port < 1) { + port = 80; + } + + String host = proxyurl.getHost(); + if (proxyurl.getPort() != -1) { + host += ":" + proxyurl.getPort(); + } + RequestHeader yacyRequestHeader = ProxyHandler.convertHeaderFromJetty(request); + yacyRequestHeader.remove(RequestHeader.KEEP_ALIVE); + yacyRequestHeader.remove(RequestHeader.CONTENT_LENGTH); + + final HashMap prop = new HashMap(); + prop.put(HeaderFramework.CONNECTION_PROP_HTTP_VER, HeaderFramework.HTTP_VERSION_1_1); + prop.put(HeaderFramework.CONNECTION_PROP_HOST, proxyurl.getHost()); + prop.put(HeaderFramework.CONNECTION_PROP_PATH, proxyurl.getFile().replaceAll(" ", "%20")); + prop.put(HeaderFramework.CONNECTION_PROP_REQUESTLINE, "PROXY"); + prop.put("CLIENTIP", "0:0:0:0:0:0:0:1"); + + yacyRequestHeader.put(HeaderFramework.HOST, proxyurl.getHost()); + // temporarily add argument to header to pass it on to augmented browsing + if (action != null) yacyRequestHeader.put("YACYACTION", action); + + final ByteArrayOutputStream tmpproxyout = new ByteArrayOutputStream(); + HTTPDProxyHandler.doGet(prop, yacyRequestHeader, tmpproxyout, ClientIdentification.yacyProxyAgent); + + // reparse header to extract content-length and mimetype + final ResponseHeader outgoingHeader = new ResponseHeader(200); // + final InputStream proxyout = new ByteArrayInputStream(tmpproxyout.toByteArray()); + String line = readLine(proxyout); + while (line != null && !line.equals("")) { + int p; + if ((p = line.indexOf(':')) >= 0) { + // store a property + outgoingHeader.add(line.substring(0, p).trim(), line.substring(p + 1).trim()); + } + line = readLine(proxyout); + } + if (line == null) { + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,"Proxy Header missing"); + return; + } + + final int httpStatus = Integer.parseInt((String) prop.get(HeaderFramework.CONNECTION_PROP_PROXY_RESPOND_STATUS)); + + String directory = ""; + if (proxyurl.getPath().lastIndexOf('/') > 0) { + directory = proxyurl.getPath().substring(0, proxyurl.getPath().lastIndexOf('/')); + } + + if (response.getHeader(HeaderFramework.LOCATION) != null) { + // rewrite location header + String location = response.getHeader(HeaderFramework.LOCATION); + String actioncmdstr = (action != null) ? "action=" + action + "&" : ""; + if (location.startsWith("http")) { + location = "/proxy.html?" + actioncmdstr + "url=" + location; + } else { + location = "/proxy.html?" + actioncmdstr + "url=http://" + proxyurl.getHost() + "/" + location; + } + //outgoingHeader.put(HeaderFramework.LOCATION, location); + response.addHeader(HeaderFramework.LOCATION, location); + } + + //final String mimeType = outgoingHeader.getContentType(); + final String mimeType = outgoingHeader.getContentType(); + if ((mimeType != null) && (mimeType.startsWith("text/html") || mimeType.startsWith("text"))) { + final StringWriter buffer = new StringWriter(); + + if (outgoingHeader.containsKey(HeaderFramework.TRANSFER_ENCODING)) { + FileUtils.copy(new ChunkedInputStream(proxyout), buffer, UTF8.charset); + } else { + FileUtils.copy(proxyout, buffer, UTF8.charset); + } + final String sbuffer = buffer.toString(); + + final Pattern p = Pattern.compile("(href=\"|src=\")([^\"]+)|(href='|src=')([^']+)|(url\\(')([^']+)|(url\\(\")([^\"]+)|(url\\()([^\\)]+)"); + final Matcher m = p.matcher(sbuffer); + final StringBuffer result = new StringBuffer(80); + String init, url; + Switchboard sb = Switchboard.getSwitchboard(); + while (m.find()) { + init = null; + if (m.group(1) != null) { init = m.group(1); } + if (m.group(3) != null) { init = m.group(3); } + if (m.group(5) != null) { init = m.group(5); } + if (m.group(7) != null) { init = m.group(7); } + if (m.group(9) != null) { init = m.group(9); } + url = null; + if (m.group(2) != null) { url = m.group(2); } + if (m.group(4) != null) { url = m.group(4); } + if (m.group(6) != null) { url = m.group(6); } + if (m.group(8) != null) { url = m.group(8); } + if (m.group(10) != null) { url = m.group(10); } + if (url.startsWith("data:") || url.startsWith("#") || url.startsWith("mailto:") || url.startsWith("javascript:")) { + String newurl = init + url; + newurl = newurl.replaceAll("\\$", "\\\\\\$"); + m.appendReplacement(result, newurl); + + } else if (url.startsWith("http")) { + // absoulte url of form href="http://domain.com/path" + if (sb.getConfig("proxyURL.rewriteURLs", "all").equals("domainlist")) { + try { + if (sb.crawlStacker.urlInAcceptedDomain(new DigestURL(url)) != null) { + continue; + } + } catch (final MalformedURLException e) { + ConcurrentLog.fine("ProxyServlet", "malformed url for url-rewirte " + url); + continue; + } + } + + String newurl = init + "/proxy.html?url=" + url; + newurl = newurl.replaceAll("\\$", "\\\\\\$"); + m.appendReplacement(result, newurl); + + } else if (url.startsWith("//")) { + // absoulte url but same protocol of form href="//domain.com/path" + final String complete_url = proxyurl.getProtocol() + ":" + url; + if (sb.getConfig("proxyURL.rewriteURLs", "all").equals("domainlist")) { + try { + if (sb.crawlStacker.urlInAcceptedDomain(new DigestURL(complete_url)) != null) { + continue; + } + } catch (MalformedURLException ex) { + ConcurrentLog.fine("ProxyServlet", "malformed url for url-rewirte " + complete_url); + continue; + } + } + + String newurl = init + "/proxy.html?url=" + complete_url; + newurl = newurl.replaceAll("\\$", "\\\\\\$"); + m.appendReplacement(result, newurl); + + } else if (url.startsWith("/")) { + // absolute path of form href="/absolute/path/to/linked/page" + String newurl = init + "/proxy.html?url=http://" + host + url; + newurl = newurl.replaceAll("\\$", "\\\\\\$"); + m.appendReplacement(result, newurl); + + } else { + // relative path of form href="relative/path" + try { + MultiProtocolURL target = new MultiProtocolURL("http://" + host + directory + "/" + url); + String newurl = init + "/proxy.html?url=" + target.toString(); + newurl = newurl.replaceAll("\\$", "\\\\\\$"); + m.appendReplacement(result, newurl); + } catch (final MalformedURLException e) {} + } + } + m.appendTail(result); + + byte[] sbb = UTF8.getBytes(result.toString()); + + // add some proxy-headers to response header + response.setContentType(outgoingHeader.getContentType()); + if (outgoingHeader.containsKey(HeaderFramework.SERVER)) { + response.addHeader(HeaderFramework.SERVER, outgoingHeader.get(HeaderFramework.SERVER)); + } + if (outgoingHeader.containsKey(HeaderFramework.DATE)) { + response.addHeader(HeaderFramework.DATE, outgoingHeader.get(HeaderFramework.DATE)); + } + if (outgoingHeader.containsKey(HeaderFramework.LAST_MODIFIED)) { + response.addHeader(HeaderFramework.LAST_MODIFIED, outgoingHeader.get(HeaderFramework.LAST_MODIFIED)); + } + if (outgoingHeader.containsKey(HeaderFramework.EXPIRES)) { + response.addHeader(HeaderFramework.EXPIRES, outgoingHeader.get(HeaderFramework.EXPIRES)); + } + + response.setStatus(httpStatus); + response.addIntHeader(HeaderFramework.CONTENT_LENGTH, sbb.length); + response.getOutputStream().write(sbb); + + } else { + if ((response.getHeader(HeaderFramework.CONTENT_LENGTH) == null) && prop.containsKey(HeaderFramework.CONNECTION_PROP_PROXY_RESPOND_SIZE)) { + response.addHeader(HeaderFramework.CONTENT_LENGTH, (String) prop.get(HeaderFramework.CONNECTION_PROP_PROXY_RESPOND_SIZE)); + } + response.setStatus(httpStatus); + FileUtils.copy(proxyout, response.getOutputStream()); + } + } + } + } + + private String readLine(final InputStream in) throws IOException { + final ByteArrayOutputStream buf = new ByteArrayOutputStream(); + int b; + while ((b = in.read()) != '\r' && b != -1) { + buf.write(b); + } + if (b == -1) { + return null; + } + b = in.read(); // read \n + if (b == -1) { + return null; + } + return buf.toString("UTF-8"); + } + + + /** + * get a destination url from a querysting with parameter &url=_destinationurl_ + * + * @param querystring + * @return destinationURL + * @throws MalformedURLException + */ + protected HttpURI proxyHttpURIfromQueryString(String querystring) throws MalformedURLException { + URL newurl = null; + String strARGS = querystring; + String action; + if (strARGS.startsWith("action=")) { + int detectnextargument = strARGS.indexOf("&"); + action = strARGS.substring(7, detectnextargument); + strARGS = strARGS.substring(detectnextargument + 1); + } + if (strARGS.startsWith("url=")) { + final String strUrl = strARGS.substring(4); // strip url= + + try { + newurl = new URL(strUrl); + } catch (final MalformedURLException e) { + + } + } + int port = newurl.getPort(); + if (port < 1) { + port = newurl.getDefaultPort(); + } + return proxyHttpURI(newurl.getProtocol(), newurl.getHost(), port, newurl.getPath()); + } + + @Override + protected HttpURI proxyHttpURI(HttpServletRequest request, String uri) throws MalformedURLException { + URL newurl = null; + String strARGS = request.getQueryString(); + if (strARGS.startsWith("action=")) { + int detectnextargument = strARGS.indexOf("&"); + strARGS = strARGS.substring(detectnextargument + 1); + } + if (strARGS.startsWith("url=")) { + final String strUrl = strARGS.substring(4); // strip url= + + try { + newurl = new URL(strUrl); + } catch (final MalformedURLException e) { + + } + } + int port = newurl.getPort(); + if (port < 1) { + port = newurl.getDefaultPort(); + } + return proxyHttpURI(newurl.getProtocol(), newurl.getHost(), port, newurl.getPath()); + } + + @Override + public String getServletInfo() { + return "YaCy Proxy Servlet"; + } + +}