package de.digitalstep.ntlmproxy; import java.io.IOException; import java.io.InputStream; import java.text.NumberFormat; import java.text.ParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HttpParser extends InputStream { private static final Logger log = LoggerFactory.getLogger(HttpParser.class); private int bodyIndex; private byte[] buffer = new byte[4096]; private long contentLength; private String contentType; private Header[] headers; private int index; private final InputStream delegate; private String method, uri, protocol; public HttpParser(InputStream is) { this.delegate = is; } public void close() throws IOException { delegate.close(); } public long getContentLength() { return contentLength; } public String getContentType() { return contentType; } public Header[] getHeaders() { return headers; } public String getMethod() { return method; } public String getUri() { return uri; } public boolean parse() throws IOException { index += delegate.read(buffer, index, buffer.length - index); String line = new String(buffer); log.debug(line); int splitAt = line.indexOf("\r\n\r\n"); if (splitAt == -1) { return false; } bodyIndex = splitAt + 4; line = line.substring(0, splitAt); String[] headerLines = line.split("\r\n"); try { String[] httpStuff = headerLines[0].split(" "); method = httpStuff[0]; uri = httpStuff[1]; protocol = httpStuff[2]; log.debug(method + " " + uri + " " + protocol); } catch (ArrayIndexOutOfBoundsException ex) { throw new IOException("Bad HTTP header", ex); } this.headers = new Header[headerLines.length - 1]; for (int i = 1; i < headerLines.length; i++) { String[] h = headerLines[i].split(": ", 2); if (h.length != 2) { throw new IOException("Bad Header:" + headerLines[i]); } final String name = h[0]; final String value = h[1]; if (name.equals("Content-Type")) { this.contentType = value; } else if (name.equals("Content-Length")) { try { this.contentLength = NumberFormat.getIntegerInstance().parse(value).longValue(); } catch (ParseException e) { throw new IOException("Cannot parse Content-Length", e); } } this.headers[i - 1] = new Header(name, value); } return true; } public int read() throws IOException { if (bodyIndex < index) { return buffer[bodyIndex++]; } else { return delegate.read(); } } public int read(byte[] b, int off, int len) throws IOException { if (bodyIndex < index) { int toCopy = Math.min(len, index - bodyIndex); System.arraycopy(buffer, bodyIndex, b, off, toCopy); bodyIndex += toCopy; return toCopy; } return delegate.read(b, off, len); } public void setBodyIndex(int i) { this.bodyIndex = i; } }