--- /dev/null
+/* Written and copyright 2001-2003 Benjamin Kohl.\r
+ * Distributed under the GNU General Public License; see the README file.\r
+ * This code comes with NO WARRANTY.\r
+ */\r
+\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.BufferedInputStream;\r
+import java.net.InetAddress;\r
+import java.net.UnknownHostException;\r
+\r
+\r
+/**\r
+ File: Jhttpp2BufferedFilterStream.java\r
+ @author Benjamin Kohl\r
+*/\r
+public class Jhttpp2ClientInputStream {\r
+ private boolean filter;\r
+ /**\r
+ * This is set to true with requests with bodies, like "POST"\r
+ */\r
+ \r
+ public boolean ssl;\r
+ flag foo;\r
+ \r
+ private void init() {\r
+ ssl = false;\r
+ }\r
+\r
+ public Jhttpp2ClientInputStream() {\r
+ init();\r
+ }\r
+\r
+\r
+ public Request read(String str, Jhttpp2HTTPSession connection, tag ct, tag tc) {\r
+ //can check for ssl first\r
+ String s=readstr(str, connection);\r
+ if (s!=null) {\r
+ return new Request(s){}{ct, tc};\r
+ } else\r
+ return null;\r
+ }\r
+\r
+ public Request readfirst(String str, Jhttpp2HTTPSession connection, tag ct, tag tc) {\r
+ String s=readstr(str, connection);\r
+ if (s!=null) {\r
+ return new Request(s){first}{ct, tc};\r
+ } else\r
+ return null;\r
+ }\r
+ \r
+ public String readstr(String str, Jhttpp2HTTPSession connection) {\r
+ String rq="";\r
+ int content_len=0;\r
+ boolean tempssl=false;\r
+\r
+ if (ssl) \r
+ return str;\r
+\r
+ String buf = getLine(str); // reads the first line\r
+ str = updateBuffer(str, buf);\r
+ if (buf==null)\r
+ return null;\r
+ rq += buf;\r
+ if (buf.startsWith("CONNECT"))\r
+ tempssl=true;\r
+ boolean cnt=true;\r
+ while(cnt) {\r
+ buf = getLine(str); // reads the first line\r
+ str = updateBuffer(str, buf);\r
+ if (buf==null)\r
+ return null;\r
+ rq += buf;\r
+ \r
+ if (buf.length()<=2) {\r
+ cnt=false;\r
+ } else {\r
+ if (buf.toUpperCase().startsWith("CONTENT-LENGTH")) {\r
+ String clen=buf.substring(16);\r
+ if (clen.indexOf("\r")!=-1) \r
+ clen=clen.substring(0,clen.indexOf("\r"));\r
+ else \r
+ if(clen.indexOf("\n")!=-1) clen=clen.substring(0,clen.indexOf("\n"));\r
+ content_len=Integer.parseInt(clen);\r
+ }\r
+ }\r
+ }\r
+ if (!tempssl) {\r
+ buf=getAdditional(str, content_len);\r
+ str = updateBuffer(str, buf);\r
+ if (buf==null)\r
+ return null;\r
+ rq+=buf;\r
+ }\r
+ ssl=tempssl;\r
+ return rq;\r
+ }\r
+\r
+\r
+ /**\r
+ * reads a line\r
+ * @exception IOException\r
+ */\r
+ public static String getLine(String str) {\r
+ int l=str.indexOf('\n');\r
+ if (l!=-1)\r
+ return str.substring(0, l+1);\r
+ else\r
+ return null;\r
+ }\r
+ \r
+ public static String getAdditional(String str, int content_len) {\r
+ if (content_len>str.length())\r
+ return null;\r
+ else\r
+ return str.substring(0, content_len);\r
+\r
+ }\r
+\r
+ public static String updateBuffer(String buf, String str) {\r
+ if (str!=null) {\r
+ return buf.substring(str.length(), buf.length());\r
+ } else\r
+ return buf;\r
+ }\r
+\r
+ /**\r
+ * @return boolean whether the actual connection was established with the CONNECT method.\r
+ * @since 0.2.21\r
+ */\r
+ public boolean isTunnel() {\r
+ return ssl;\r
+ }\r
+}\r
--- /dev/null
+/* Written and copyright 2001-2003 Benjamin Kohl.
+ * Distributed under the GNU General Public License; see the README file.
+ * This code comes with NO WARRANTY.
+ */
+
+import java.net.Socket;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.File;
+import java.io.FileInputStream;
+
+
+/**
+ One HTTP connection
+ @file Jhttpp2HTTPSession.java
+ @author Benjamin Kohl
+*/
+public class Jhttpp2HTTPSession {
+ String request;
+ flag more;
+ flag first;
+
+ public Jhttpp2HTTPSession() {
+ }
+}
+
--- /dev/null
+/* Written and copyright 2001-2003 Benjamin Kohl.\r
+ * Distributed under the GNU General Public License; see the README file.\r
+ * This code comes with NO WARRANTY.\r
+ * More Information and documentation: HTTP://jhttp2.sourceforge.net/\r
+ */\r
+\r
+import java.net.ServerSocket;\r
+import java.net.Socket;\r
+import java.net.UnknownHostException;\r
+import java.net.InetAddress;\r
+import java.net.BindException;\r
+\r
+import java.io.*;\r
+\r
+import java.util.Vector;\r
+import java.util.Date;\r
+\r
+public class Jhttpp2Server\r
+{\r
+ private static final String CRLF;\r
+ private final String VERSION;\r
+ private final String V_SPECIAL;\r
+ private final String HTTP_VERSION;\r
+ private final String MAIN_LOGFILE;\r
+\r
+ private final String DATA_FILE;\r
+ private final String SERVER_PROPERTIES_FILE;\r
+\r
+ private String http_useragent;\r
+ private ServerSocket listen;\r
+ private BufferedWriter logfile;\r
+ private BufferedWriter access_logfile;\r
+ private long bytesread;\r
+ private long byteswritten;\r
+ private int numconnections;\r
+\r
+ private boolean enable_cookies_by_default;\r
+ private WildcardDictionary dic;\r
+ private Vector urlactions;\r
+\r
+ public final int DEFAULT_SERVER_PORT;\r
+ public final String WEB_CONFIG_FILE;\r
+\r
+ public int port;\r
+ public InetAddress proxy;\r
+ public int proxy_port;\r
+\r
+ public long config_auth;\r
+ public long config_session_id;\r
+ public String config_user;\r
+ public String config_password;\r
+\r
+ public static boolean error;\r
+ public static String error_msg;\r
+\r
+ public boolean use_proxy;\r
+ public boolean block_urls;\r
+ public boolean filter_http;\r
+ public boolean debug;\r
+ public boolean log_access;\r
+ public String log_access_filename;\r
+ public boolean webconfig;\r
+ public boolean www_server;\r
+ \r
+\r
+ public initvars() {\r
+ CRLF="\r\n";\r
+ VERSION = "0.4.62";\r
+ V_SPECIAL = " 2003-05-20";\r
+ HTTP_VERSION = "HTTP/1.1";\r
+ MAIN_LOGFILE = "server.log";\r
+ DATA_FILE = "server.data";\r
+ SERVER_PROPERTIES_FILE = "server.properties";\r
+ http_useragent = "Mozilla/4.0 (compatible; MSIE 4.0; WindowsNT 5.0)";\r
+ enable_cookies_by_default=true;\r
+ dic = new WildcardDictionary();\r
+ urlactions = new Vector();\r
+ DEFAULT_SERVER_PORT = 8088;\r
+ WEB_CONFIG_FILE = "admin/jp2-config";\r
+ port = DEFAULT_SERVER_PORT;\r
+ proxy_port = 0;\r
+ config_auth = 0;\r
+ config_session_id = 0;\r
+ config_user = "root";\r
+ config_password = "geheim";\r
+ use_proxy=false;\r
+ block_urls=false;\r
+ filter_http=false;\r
+ debug=false;\r
+ log_access = true;\r
+ log_access_filename="paccess.log";\r
+ webconfig = true;\r
+ www_server = true;\r
+}\r
+\r
+ void init()\r
+ {\r
+ if(log_access) {\r
+ access_logfile=new BufferedWriter(new FileWriter(log_access_filename,true)); \r
+ }\r
+\r
+ logfile=new BufferedWriter(new FileWriter(MAIN_LOGFILE,true));\r
+ writeLog("server startup...");\r
+\r
+ listen = new ServerSocket(port);\r
+ \r
+ if (error) {\r
+ writeLog(error_msg);\r
+ return;\r
+ }\r
+ }\r
+ public Jhttpp2Server() {\r
+ initvars();\r
+ init();\r
+ }\r
+ public Jhttpp2Server(boolean b)\r
+ {\r
+ initvars();\r
+ System.printString("jHTTPp2 HTTP Proxy Server Release " + getServerVersion() + "\r\n"\r
+ +"Copyright (c) 2001-2003 Benjamin Kohl <bkohl@users.sourceforge.net>\r\n"\r
+ +"This software comes with ABSOLUTELY NO WARRANTY OF ANY KIND.\r\n"\r
+ +"http://jhttp2.sourceforge.net/\n");\r
+ init();\r
+ }\r
+ /** calls init(), sets up the serverport and starts for each connection\r
+ * new Jhttpp2Connection\r
+ */\r
+ public void setErrorMsg(String a)\r
+ {\r
+ error=true;\r
+ error_msg=a;\r
+ }\r
+ /**\r
+ * Tests what method is used with the reqest\r
+ * @return -1 if the server doesn't support the method\r
+ */\r
+ public static int getHttpMethod(String d)\r
+ {\r
+ if (startsWith(d,"GET") || startsWith(d,"HEAD")) return 0;\r
+ if (startsWith(d,"POST") || startsWith(d,"PUT")) return 1;\r
+ if (startsWith(d,"CONNECT")) return 2;\r
+ if (startsWith(d,"OPTIONS")) return 3;\r
+\r
+ return -1;/* No match...\r
+\r
+ Following methods are not implemented:\r
+ || startsWith(d,"TRACE") */\r
+ }\r
+ public static boolean startsWith(String a,String what)\r
+ {\r
+ int l=what.length();\r
+ int l2=a.length();\r
+ if (l2>l)\r
+ return a.substring(0,l).equals(what);\r
+ else\r
+ return false;\r
+ }\r
+ /**\r
+ *@return the Server response-header field\r
+ */\r
+ public String getServerIdentification()\r
+ {\r
+ return "jHTTPp2/" + getServerVersion();\r
+ }\r
+ public String getServerVersion()\r
+ {\r
+ return VERSION + V_SPECIAL;\r
+ }\r
+ /**\r
+ * saves all settings with a ObjectOutputStream into a file\r
+ * @since 0.2.10\r
+ */\r
+ /** restores all Jhttpp2 options from "settings.dat"\r
+ * @since 0.2.10\r
+ */\r
+ /**\r
+ * @return the HTTP version used by jHTTPp2\r
+ */\r
+ public String getHttpVersion()\r
+ {\r
+ return HTTP_VERSION;\r
+ }\r
+ /** the User-Agent header field\r
+ * @since 0.2.17\r
+ * @return User-Agent String\r
+ */\r
+ public String getUserAgent()\r
+ {\r
+ return http_useragent;\r
+ }\r
+ public void setUserAgent(String ua)\r
+ {\r
+ http_useragent=ua;\r
+ }\r
+ /**\r
+ * writes into the server log file and adds a new line\r
+ * @since 0.2.21\r
+ */\r
+ public void writeLog(String s)\r
+ {\r
+ writeLog(s,true);\r
+ }\r
+ /** writes to the server log file\r
+ * @since 0.2.21\r
+ */\r
+ public void writeLog(String s,boolean b)\r
+ {\r
+ s=new Date().toString() + " " + s;\r
+ logfile.write(s,0,s.length());\r
+ if (b) logfile.newLine();\r
+ logfile.flush();\r
+ if (debug)System.printString(s);\r
+ }\r
+\r
+ public void closeLog()\r
+ {\r
+ writeLog("Server shutdown.");\r
+ logfile.flush();\r
+ logfile.close();\r
+ access_logfile.close();\r
+ }\r
+\r
+ public void addBytesRead(long read)\r
+ {\r
+ bytesread+=read;\r
+ }\r
+ /**\r
+ * Functions for the jHTTPp2 statistics:\r
+ * How many connections\r
+ * Bytes read/written\r
+ * @since 0.3.0\r
+ */\r
+ public void addBytesWritten(int written)\r
+ {\r
+ byteswritten+=written;\r
+ }\r
+ public int getServerConnections()\r
+ {\r
+ return numconnections;\r
+ }\r
+ public long getBytesRead()\r
+ {\r
+ return bytesread;\r
+ }\r
+ public long getBytesWritten()\r
+ {\r
+ return byteswritten;\r
+ }\r
+ public void increaseNumConnections()\r
+ {\r
+ numconnections++;\r
+ }\r
+ public void decreaseNumConnections()\r
+ {\r
+ numconnections--;\r
+ }\r
+ public void AuthenticateUser(String u,String p) {\r
+ if (config_user.equals(u) && config_password.equals(p)) {\r
+ config_auth = 1;\r
+ } else config_auth = 0;\r
+ }\r
+ public String getGMTString()\r
+ {\r
+ return new Date().toString();\r
+ }\r
+ public Jhttpp2URLMatch findMatch(String url)\r
+ {\r
+ return (Jhttpp2URLMatch)dic.get(url);\r
+ }\r
+ public WildcardDictionary getWildcardDictionary()\r
+ {\r
+ return dic;\r
+ }\r
+ public Vector getURLActions()\r
+ {\r
+ return urlactions;\r
+ }\r
+ public boolean enableCookiesByDefault()\r
+ {\r
+ return this.enable_cookies_by_default;\r
+ }\r
+ public void enableCookiesByDefault(boolean a)\r
+ {\r
+ enable_cookies_by_default=a;\r
+ }\r
+ public void resetStat()\r
+ {\r
+ bytesread=0;\r
+ byteswritten=0;\r
+ }\r
+ /**\r
+ * @since 0.4.10a\r
+ */\r
+ /**\r
+ * @since 0.4.10a\r
+ */\r
+ /**\r
+ * @since 0.4.10a\r
+ */\r
+ public void logAccess(String s)\r
+ {\r
+ access_logfile.write("[" + new Date().toString() + "] " + s + "\r\n");\r
+ access_logfile.flush();\r
+ }\r
+ public void shutdownServer() {\r
+ closeLog();\r
+ System.exit(0);\r
+ }\r
+\r
+}\r
--- /dev/null
+task start(StartupObject s{initialstate}) {
+ Jhttpp2Server js=new Jhttpp2Server(true);
+ taskexit(s{!initialstate});
+}
+
+task acceptconnection(ServerSocket ss{SocketPending}) {
+ tag t=new tag(connection);
+ Socket s=ss.accept(t);
+ Jhttpp2HTTPSession js=new Jhttpp2HTTPSession() {first}{t};
+ Jhttpp2ClientInputStream jcis=new Jhttpp2ClientInputStream() {}{t};
+}
+
+task requestfirst(Jhttpp2HTTPSession session {first}{connection tc}, Jhttpp2ClientInputStream jcis {}{connection tc}, Socket socket {IOPending}{connection tc}) {
+ byte[] buf=new byte[10000];
+ int length=socket.read(buf);
+ String str=new String(buf, 0, length);
+ System.printString("["+str+"]\n");
+ if (session.request!=null) {
+ str=session.request.concat(str);
+ }
+ tag ct=new tag(chained);
+ Request r=jcis.readfirst(str, session, ct, tc);
+ if (r==null) {
+ session.request=str;
+ taskexit;
+ } else {
+ session.request=str.substring(r.length(), str.length());
+ if (session.request.length()>0)
+ taskexit(session{more, !first});
+ else
+ taskexit(session{!first});
+ }
+}
+
+task request(Jhttpp2HTTPSession session {}{connection tc}, Jhttpp2ClientInputStream jcis {}{connection tc}, Socket socket {IOPending}{connection tc}, optional Request rold{!chained}{connection tc}) {
+ byte[] buf=new byte[10000];
+ int length=socket.read(buf);
+ System.printString("length="+length+"\n");
+ if (session.request!=null)
+ System.printString(session.request+"\n");
+ if (length==0) {
+ taskexit;
+ } else if (length < 0 ) {
+ System.printString("ERROR\n");
+ taskexit;
+ }
+ String str=new String(buf, 0, length);
+ System.printString("["+str+"]\n");
+
+ if (session.request!=null) {
+ str=session.request.concat(str);
+ }
+ //pull off the next request
+ tag ct=new tag(chained);
+ Request r=jcis.read(str, session, ct, tc);
+ if (r==null) {
+ session.request=str;
+ taskexit;
+ } else {
+ System.printString("new Request\n");
+ session.request=str.substring(r.length(), str.length());
+ if (session.request.length()>0)
+ taskexit(session{more}, rold{chained}{ct});
+ else
+ taskexit(rold{chained}{ct});
+ }
+}
+
+task requestmore(Jhttpp2HTTPSession session {more}{connection tc}, Jhttpp2ClientInputStream jcis {}{connection tc}, optional Request rold{!chained}{connection tc}) {
+ String str=session.request;
+ //pull off the next request
+ tag ct=new tag(chained);
+ Request r=jcis.read(str, session, ct, tc);
+ if (r==null) {
+ session.request=str;
+ taskexit;
+ } else {
+ session.request=str.substring(r.length(), str.length());
+ if (session.request.length()>0)
+ taskexit(rold{chained}{ct});
+ else
+ taskexit(session{!more}, rold{chained}{ct});
+ }
+}
+
+task sendfirst(Request r{first&&!processed}{connection tc}) {
+ r.parseRequest();
+ r.connect();
+ r.sendRequest();
+ taskexit(r{processed});
+}
+
+task sendnext(optional Request rprev{received&&!done}{chained ct}, Request r{!processed}{chained ct}) {
+ r.parseRequest();
+ r.connect();
+ r.sendRequest();
+ taskexit(r{processed}, rprev{done});
+}
+
+task recvreq(Request r{processed&&!received&&IOPending}) {
+ byte[] buf=new byte[10000];
+ int length=r.read(buf);
+ if (length==0) {
+ //Done
+ taskexit(r{received});
+ }
+ String str=new String(buf, 0, length);
+ if (r.response!=null) {
+ str=r.response.concat(str);
+ }
+ boolean cnt=true;
+ int lastindex=0;
+ int bytes=0;
+ while(cnt) {
+ int nextindex=str.indexOf('\n',lastindex)+1;
+ if (nextindex==-1) {
+ r.response=str;
+ taskexit;
+ }
+ if (nextindex-lastindex<=2) {
+ cnt=false;
+ } else if (str.substring(lastindex, nextindex+1).toUpperCase().startsWith("CONTENT-LENGTH")) {
+ String clen=str.substring(lastindex+16, nextindex+1);
+ if (clen.indexOf("\r")!=-1)
+ clen=clen.substring(0,clen.indexOf("\r"));
+ else
+ if(clen.indexOf("\n")!=-1)
+ clen=clen.substring(0,clen.indexOf("\n"));
+ bytes=Integer.parseInt(clen);
+ }
+ lastindex=nextindex;
+ }
+ if (bytes>0) {
+ if ((lastindex+bytes)<str.length()) {
+ r.response=str;
+ taskexit(r{received});
+ } else {
+ r.response=str;
+ taskexit;
+ }
+ } else {
+ //read until 0
+ r.response=str;
+ taskexit;
+ }
+}
+
+task sendfirstresp(optional Request r{first && !sent && received}{connection tc}, Socket sock{}{connection tc}) {
+ if (isavailable(r)) {
+ System.printString(r.response);
+ sock.write(r.response.getBytes());
+ taskexit(r{sent});
+ } else {
+ String msg="<HTML><HEAD><TITLE> 503 Service Unavailable </TITLE></HEAD>\r<BODY>Request Failed</BODY></HTML>\r\n";
+ String resp="HTTP/1.1 503 Service Unavailable\r\n"+
+ "Cache-Control: nocache, must-revalidate\r\n"+
+ "Connection: close\r\n"+
+ "Content-Length: "+msg.length()+"\r\n"+
+ "Content-Type: text/html; charset=iso-8859-1\r\n\r\n"+msg;
+ sock.write(resp.getBytes());
+ taskexit(r{sent});
+ }
+}
+
+task sendresp(optional Request rprev {sent}{chained ct}, optional Request r{!sent && received}{chained ct, connection tc}, Socket sock{}{connection tc}) {
+ if (isavailable(r)) {
+ System.printString(r.response);
+ sock.write(r.response.getBytes());
+ taskexit(r{sent});
+ } else {
+ String msg="<HTML><HEAD><TITLE> 503 Service Unavailable </TITLE></HEAD>\r<BODY>Request Failed</BODY></HTML>\r\n";
+ String resp="HTTP/1.1 503 Service Unavailable\r\n"+
+ "Cache-Control: nocache, must-revalidate\r\n"+
+ "Connection: close\r\n"+
+ "Content-Length: "+msg.length()+"\r\n"+
+ "Content-Type: text/html; charset=iso-8859-1\r\n\r\n"+msg;
+ sock.write(resp.getBytes());
+ taskexit(r{sent});
+ }
+}
--- /dev/null
+/**
+ * Title: jHTTPp2: Java HTTP Filter Proxy
+ * Copyright: Copyright (c) 2001-2003 Benjamin Kohl
+ * @author Benjamin Kohl
+ * @version 0.2.8
+ */
+
+public class Jhttpp2URLMatch {
+ String match;
+ String desc;
+ boolean cookies_enabled;
+ int actionindex;
+
+ public Jhttpp2URLMatch(String match,boolean cookies_enabled,int actionindex,String description)
+ {
+ this.match=match;
+ this.cookies_enabled=cookies_enabled;
+ this.actionindex=actionindex;
+ this.desc=description;
+ }
+ public String getMatch()
+ {
+ return match;
+ }
+ public boolean getCookiesEnabled()
+ {
+ return cookies_enabled;
+ }
+ public int getActionIndex()
+ {
+ return actionindex;
+ }
+ public String getDescription()
+ {
+ return desc;
+ }
+ public String toString()
+ {
+ return "\"" + match + "\" " + desc;
+ }
+}
--- /dev/null
+/* Written and copyright 2001 Benjamin Kohl.
+ * Distributed under the GNU General Public License; see the README file.
+ * This code comes with NO WARRANTY.
+ *
+ * Title: jHTTPp2: Java HTTP Filter Proxy
+ * Description: An OpenSource HTTP Proxy
+ * Copyright: Copyright (c) 2001 Benjamin Kohl
+ * @author Benjamin Kohl
+ */
+
+public class OnURLAction {
+
+ private String customerrortext, desc, httppath, newlocation;
+ private boolean log,block,customtext,http_rq,anotherlocation;
+ public OnURLAction(String desc)
+ {
+ this.desc=desc;
+ }
+ public void denyAccess(String customerrortext)
+ {
+ this.block=true;
+ this.customtext=true;
+ this.customerrortext=customerrortext;
+ }
+ public void denyAccess()
+ {
+ block=true;
+ }
+ public void logAccess()
+ {
+ log=true;
+ }
+ public void anotherLocation(String newlocation)
+ {
+ this.anotherlocation=true;
+ this.newlocation=newlocation;
+ }
+
+ public boolean onAccesssDeny()
+ {
+ return block;
+ }
+ public boolean onAccessLog()
+ {
+ return log;
+ }
+ public boolean onAccessDenyWithCustomText()
+ {
+ return customtext;
+ }
+ public boolean onAccessSendHTTPRequest()
+ {
+ return http_rq;
+ }
+ public boolean onAccessRedirect()
+ {
+ return this.anotherlocation;
+ }
+ public String newLocation()
+ {
+ return this.newlocation;
+ }
+ public void setHTTPAction(boolean http_rq, String httppath)
+ {
+ this.http_rq=http_rq;
+ this.httppath=httppath;
+ }
+ public String getCustomErrorText()
+ {
+ return customerrortext;
+ }
+ public String getDescription()
+ {
+ return desc;
+ }
+ public String toString()
+ {
+ return desc;
+ }
+
+}
--- /dev/null
+public class Request extends Socket {
+ flag first;
+ flag chained;
+ flag done;
+ flag sent;
+ flag received;
+ flag processed;
+
+ String response;
+ String request;
+ int port;
+ String remote_host_name;
+ InetAddress address;
+ int statuscode;
+ String url;
+ String method;
+ boolean ssl;
+ String errordescription;
+
+ public final int SC_OK;
+ public final int SC_CONNECTING_TO_HOST;
+ public final int SC_HOST_NOT_FOUND;
+ public final int SC_URL_BLOCKED;
+ public final int SC_CLIENT_ERROR;
+ public final int SC_INTERNAL_SERVER_ERROR;
+ public final int SC_NOT_SUPPORTED;
+ public final int SC_REMOTE_DEBUG_MODE;
+ public final int SC_CONNECTION_CLOSED;
+ public final int SC_HTTP_OPTIONS_THIS;
+ public final int SC_FILE_REQUEST;
+ public final int SC_MOVED_PERMANENTLY;
+ public final int SC_CONFIG_RQ;
+
+ public int length() {
+ return request.length();
+ }
+
+ void init() {
+ SC_OK=0;
+ SC_CONNECTING_TO_HOST=1;
+ SC_HOST_NOT_FOUND=2;
+ SC_URL_BLOCKED=3;
+ SC_CLIENT_ERROR=4;
+ SC_INTERNAL_SERVER_ERROR=5;
+ SC_NOT_SUPPORTED=6;
+ SC_REMOTE_DEBUG_MODE=7;
+ SC_CONNECTION_CLOSED=8;
+ SC_HTTP_OPTIONS_THIS=9;
+ SC_FILE_REQUEST=10;
+ SC_MOVED_PERMANENTLY=11;
+ SC_CONFIG_RQ = 12;
+ }
+
+ public Request(String request) {
+ init();
+ this.request=request;
+ }
+
+ /**
+ * Parser for the first (!) line from the HTTP request<BR>
+ * Sets up the URL, method and remote hostname.
+ * @return an InetAddress for the hostname, null on errors with a statuscode!=SC_OK
+ */
+ public void parseRequest() {
+ String a=request.substring(0,request.indexOf('\n'));
+ String f;
+ int pos;
+ int method_index=Jhttpp2Server.getHttpMethod(a);
+
+ if (ssl) {
+ url="";
+ f = a.substring(8);
+ } else {
+ method = a.substring(0,a.indexOf(" ")); //first word in the line
+ pos = a.indexOf(":"); // locate first :
+ if (pos == -1) { // occours with "GET / HTTP/1.1"
+ url = a.substring(a.indexOf(" ")+1,a.lastIndexOf(" "));
+ if (method_index == 0) { // method_index==0 --> GET
+ statuscode = SC_FILE_REQUEST;
+ } else {
+ statuscode = SC_INTERNAL_SERVER_ERROR;
+ errordescription="This WWW proxy supports only the \"GET\" method while acting as webserver.";
+ }
+ return;
+ }
+ f = a.substring(pos+3); //removes "http://"
+ }
+ pos=f.indexOf(" "); // locate space, should be the space before "HTTP/1.1"
+ if (pos==-1) { // buggy request
+ statuscode = SC_CLIENT_ERROR;
+ errordescription="Your browser sent an invalid request: \""+ a + "\"";
+ return;
+ }
+ f = f.substring(0,pos); //removes all after space
+ // if the url contains a space... it's not our mistake...(url's must never contain a space character)
+ pos=f.indexOf("/"); // locate the first slash
+ if (pos!=-1) {
+ url=f.substring(pos); // saves path without hostname
+ f=f.substring(0,pos); // reduce string to the hostname
+ }
+ else url="/"; // occurs with this request: "GET http://localhost HTTP/1.1"
+ pos = f.indexOf(":"); // check for the portnumber
+ if (pos!=-1) {
+ String l_port =f.substring(pos+1);
+ if (l_port.indexOf(" ")!=-1)
+ l_port=l_port.substring(0,l_port.indexOf(" "));
+ int i_port=80;
+ i_port = Integer.parseInt(l_port);
+ f = f.substring(0,pos);
+ port=i_port;
+ } else
+ port=80;
+ remote_host_name = f;
+ address = InetAddress.getByName(f);
+ }
+
+ public void connect() {
+ connect(address, port);
+ }
+
+ public String getRequest() {
+ return method + " "+url+" "+"HTTP/1.1"+"\r\n";
+ }
+
+ public void sendRequest() {
+ write(getRequest().getBytes());
+ write(request.substring(request.indexOf('\n')+1,request.length()).getBytes());
+ }
+}
--- /dev/null
+// WildcardDictionary - a dictionary with wildcard lookups
+//
+// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// Visit the ACME Labs Java page for up-to-date versions of this and other
+// fine Java utilities: http://www.acme.com/java/
+
+// package Acme;
+
+import java.util.*;
+
+/// A dictionary with wildcard lookups.
+// <P>
+// The keys in this dictionary are wildcard patterns. When you do a get(),
+// the string you pass in is matched against all the patterns, and the
+// first match is returned.
+// <P>
+// The wildcard matcher is fairly simple, it implements * meaning any
+// string, ? meaning any single character, and | separating multiple
+// patterns. All other characters must match literally.
+// <P>
+// <A HREF="/resources/classes/Acme/WildcardDictionary.java">Fetch the software.</A><BR>
+// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
+// <P>
+// @see Acme.Utils#match
+
+public class WildcardDictionary extends Dictionary {
+
+ private Vector keys;
+ private Vector elements;
+
+ /// Constructor.
+ public WildcardDictionary() {
+ keys = new Vector();
+ elements = new Vector();
+ }
+
+ /// Returns the number of elements contained within the dictionary.
+ public int size() {
+ return elements.size();
+ }
+
+ /// Returns true if the dictionary contains no elements.
+ public boolean isEmpty() {
+ return size() == 0;
+ }
+
+ /// Returns an enumeration of the dictionary's keys.
+ public Enumeration keys() {
+ return keys.elements();
+ }
+
+ /// Returns an enumeration of the elements. Use the Enumeration methods
+ // on the returned object to fetch the elements sequentially.
+ public Enumeration elements() {
+ return elements.elements();
+ }
+
+ /// Gets the object associated with the specified key in the dictionary.
+ // The key is assumed to be a String, which is matched against
+ // the wildcard-pattern keys in the dictionary.
+ // @param key the string to match
+ // @returns the element for the key, or null if there's no match
+ // @see Acme.Utils#match
+ public synchronized Object get( Object key )
+ {
+ String sKey = (String) key;
+ for ( int i = 0; i < keys.size(); ++i )
+ {
+ String thisKey = (String) keys.elementAt( i );
+ if ( match( thisKey, sKey ) )
+ return elements.elementAt( i );
+ }
+ return null;
+ }
+
+ /// Puts the specified element into the Dictionary, using the specified
+ // key. The element may be retrieved by doing a get() with the same
+ // key. The key and the element cannot be null.
+ // @param key the specified wildcard-pattern key
+ // @param value the specified element
+ // @return the old value of the key, or null if it did not have one.
+ // @exception NullPointerException If the value of the specified
+ // element is null.
+ public synchronized Object put( Object key, Object element )
+ {
+ int i = keys.indexOf( key );
+ if ( i != -1 )
+ {
+ Object oldElement = elements.elementAt( i );
+ elements.setElementAt( element, i );
+ return oldElement;
+ }
+ else
+ {
+ keys.addElement( key );
+ elements.addElement( element );
+ return null;
+ }
+ }
+
+ /// Removes the element corresponding to the key. Does nothing if the
+ // key is not present.
+ // @param key the key that needs to be removed
+ // @return the value of key, or null if the key was not found.
+ public synchronized Object remove( Object key )
+ {
+ int i = keys.indexOf( key );
+ if ( i != -1 )
+ {
+ Object oldElement = elements.elementAt( i );
+ keys.removeElementAt( i );
+ elements.removeElementAt( i );
+ return oldElement;
+ }
+ else
+ return null;
+ }
+
+ /** Checks whether a string matches a given wildcard pattern.
+ * Only does ? and *, and multiple patterns separated by |.
+ */
+ public static boolean match( String pattern, String string ) {
+ for ( int p = 0; true; ++p ) {
+ boolean cnt=true;
+ for ( int s = 0; cnt; ++p, ++s ) {
+ boolean sEnd = ( s >= string.length() );
+ boolean pEnd = ( p >= pattern.length() ||
+ pattern.charAt( p ) == '|' );
+ if ( sEnd && pEnd )
+ return true;
+ if ( sEnd || pEnd )
+ cnt=false;
+ else if ( pattern.charAt( p ) != '?' ) {
+ if ( pattern.charAt( p ) == '*' ) {
+ int i;
+ ++p;
+ for ( i = string.length(); i >= s; --i )
+ if ( match(
+ pattern.substring( p ),
+ string.substring( i ) ) ) /* not quite right */
+ return true;
+ cnt=false;
+ }
+ if ( pattern.charAt( p ) != string.charAt( s ) )
+ cnt=false;
+ }
+ }
+ p = pattern.indexOf( '|', p );
+ if ( p == -1 )
+ return false;
+ }
+ }
+ /**
+ * Deletes all elements and keys.
+ */
+ public void removeAllElements() {
+ elements.clear();
+ keys.clear();
+ }
+}