X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fibex%2Fnet%2FHTTP.java;fp=src%2Forg%2Fibex%2Fnet%2FHTTP.java;h=30de701db0840f229dcce8f4012272206f84709e;hb=3b6ea42a7cb180d9b16fdaf19c2068aaf88e0585;hp=18c40690412dd75580556aa5371a56cfe546934d;hpb=5977aec2588590b18be3f9f906a7598dbfddd988;p=org.ibex.net.git diff --git a/src/org/ibex/net/HTTP.java b/src/org/ibex/net/HTTP.java index 18c4069..30de701 100644 --- a/src/org/ibex/net/HTTP.java +++ b/src/org/ibex/net/HTTP.java @@ -16,16 +16,97 @@ public class HTTP { public static InetAddress originAddr = null; public static String originHost = null; + + // Cookies ////////////////////////////////////////////////////////////////////////////// + + public static class Cookie { + public final String name; + public final String value; + public final String domain; + public final String path; + public final Date expires; + public final boolean secure; + public Cookie(String name, String value, String domain, String path, Date expires, boolean secure) { + this.name = name; + this.value = value; + this.domain = domain; + this.path = path; + this.expires = expires; + this.secure = secure; + } + + // FIXME: this could be much more efficient + // FIXME currently only implements http://wp.netscape.com/newsref/std/cookie_spec.html + public static class Jar { + private Hash h = new Hash(); + public String getCookieHeader(String domain, String path, boolean secure) { + StringBuffer ret = new StringBuffer("Cookie: "); + Enumeration e = h.keys(); + while (e.hasMoreElements()) { + Vec v = (Vec)h.get(e.nextElement()); + Cookie cookie = null; + for(int i=0; i cookie.domain.length())) + cookie = c; + } + if (cookie != null) { + ret.append(cookie.name); + ret.append("="); + ret.append(cookie.value); + ret.append("; "); + } + } + //ret.setLength(ret.length() - 2); + return ret.toString(); + } + public void setCookie(String header, String defaultDomain) { + String name = null; + String value = null; + String domain = defaultDomain; + String path = "/"; + Date expires = null; + boolean secure = false; + StringTokenizer st = new StringTokenizer(header, ";"); + while(st.hasMoreTokens()) { + String s = st.nextToken(); + if (s.indexOf('=') == -1) { + if (s.equals("secure")) secure = true; + continue; + } + String start = s.substring(0, s.indexOf('=')); + String end = s.substring(s.indexOf('=')+1); + if (name == null) { + name = start; + value = end; + continue; + } + //#switch(start.toLowerCase()) + case "domain": domain = end; + case "path": path = end; + case "expires": expires = new Date(end); + //#end + } + if (h.get(name) == null) h.put(name, new Vec()); + ((Vec)h.get(name)).addElement(new Cookie(name, value, domain, path, expires, secure)); + } + } + } + // Public Methods //////////////////////////////////////////////////////////////////////////////////////// public HTTP(String url) { this(url, false); } public HTTP(String url, boolean skipResolveCheck) { originalUrl = url; this.skipResolveCheck = skipResolveCheck; } /** Performs an HTTP GET request */ - public InputStream GET() throws IOException { return makeRequest(null, null); } - + public InputStream GET(String referer, Cookie.Jar cookies) throws IOException { + return makeRequest(null, null, referer, cookies); } + /** Performs an HTTP POST request; content is additional headers, blank line, and body */ - public InputStream POST(String contentType, String content) throws IOException { return makeRequest(contentType, content); } + public InputStream POST(String contentType, String content, String referer, Cookie.Jar cookies) throws IOException { + return makeRequest(contentType, content, referer, cookies); } public static class HTTPException extends IOException { public HTTPException(String s) { super(s); } } @@ -63,7 +144,7 @@ public class HTTP { * This method isn't synchronized; however, only one thread can be in the inner synchronized block at a time, and the rest of * the method is protected by in-order one-at-a-time semaphore lock-steps */ - private InputStream makeRequest(String contentType, String content) throws IOException { + private InputStream makeRequest(String contentType, String content, String referer, Cookie.Jar cookies) throws IOException { // Step 1: send the request and establish a semaphore to stop any requests that pipeline after us Semaphore blockOn = null; @@ -71,7 +152,7 @@ public class HTTP { synchronized(this) { try { connect(); - sendRequest(contentType, content); + sendRequest(contentType, content, referer, cookies); } catch (IOException e) { reset(); throw e; @@ -91,13 +172,13 @@ public class HTTP { if (in == null) throw new HTTPException("a previous pipelined call messed up the socket"); - Hashtable h = in == null ? null : parseHeaders(in); + Hashtable h = in == null ? null : parseHeaders(in, cookies); if (h == null) { if (firstRequest) throw new HTTPException("server closed the socket with no response"); // sometimes the server chooses to close the stream between requests reset(); releaseMe.release(); - return makeRequest(contentType, content); + return makeRequest(contentType, content, referer, cookies); } String reply = h.get("STATUSLINE").toString(); @@ -115,7 +196,7 @@ public class HTTP { new HTTPInputStream(in, cl, releaseMe).close(); } releaseMe.release(); - return makeRequest(contentType, content); + return makeRequest(contentType, content, referer, cookies); } else if (reply.startsWith("2")) { if (h.get("HTTP").equals("1.0") && h.get("content-length") == null) @@ -361,7 +442,7 @@ public class HTTP { if (in == null) in = new BufferedInputStream(sock.getInputStream()); } - private void sendRequest(String contentType, String content) throws IOException { + private void sendRequest(String contentType, String content, String referer, Cookie.Jar cookies) throws IOException { PrintWriter pw = new PrintWriter(new OutputStreamWriter(originalUrl.equals("stdio:") ? System.out : sock.getOutputStream())); if (content != null) { @@ -576,7 +657,7 @@ public class HTTP { // Misc Helpers /////////////////////////////////////////////////////////////////////////////////// /** reads a set of HTTP headers off of the input stream, returning null if the stream is already at its end */ - private Hashtable parseHeaders(InputStream in) throws IOException { + private Hashtable parseHeaders(InputStream in, Cookie.Jar cookies) throws IOException { Hashtable ret = new Hashtable(); // we can't use a BufferedReader directly on the input stream, since it will buffer past the end of the headers @@ -610,6 +691,7 @@ public class HTTP { String back = s.substring(s.indexOf(':') + 1).trim(); // ugly hack: we never replace a Digest-auth with a Basic-auth (proxy + www) if (front.endsWith("-authenticate") && ret.get(front) != null && !back.equals("Digest")) continue; + if (front.equals("set-cookie")) cookies.setCookie(back, host); ret.put(front, back); } return ret;