1 /* HTTPInputStream.java created 19th October 2008
2 * Copyright (c) 2007-2008 Mathew McBride / "BionicMessage.net"
3 * Permission is hereby granted, free of charge, to any person obtaining a
4 * copy of this software and associated documentation files (the "Software"),
5 * to deal in the Software without restriction, including without limitation
6 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 * and/or sell copies of the Software, and to permit persons to whom the
8 * Software is furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
15 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 package net
.bionicmessage
.groupdav
;
23 import java
.io
.BufferedInputStream
;
24 import java
.io
.IOException
;
25 import java
.net
.Socket
;
26 import java
.util
.ArrayList
;
27 import java
.util
.HashMap
;
28 import java
.util
.List
;
31 * A HTTP Input Stream that supports chunked-transfer-encoding
32 * and hides HTTP headers from the reader.
35 public class HTTPInputStream
extends BufferedInputStream
{
37 protected Socket sock
;
38 protected HashMap headers
;
39 protected List
<HTTPCookie
> setCookies
;
40 protected boolean chunked
= false;
41 protected boolean headersRead
= false;
42 protected int headerLinesRead
= 0;
43 protected int returnedStatus
= 0;
44 protected String returnedReason
= "";
45 protected boolean outOfChunks
= false;
47 public HTTPInputStream(Socket parent
) throws IOException
{
48 super(parent
.getInputStream());
50 headers
= new HashMap(10);
51 setCookies
= new ArrayList
<HTTPCookie
>(10);
55 public synchronized int read() throws IOException
{
56 byte[] d
= new byte[1];
62 public int read(byte[] b
) throws IOException
{
63 return this.read(b
,0,b
.length
);
67 public synchronized int read(byte[] b
, int off
, int len
) throws IOException
{
70 // Intercept the read request if we don't have headers.
72 while ((str
= readLineASCII()) != null) {
73 if (headerLinesRead
== 0) {
74 returnedStatus
= Integer
.parseInt(str
.substring(10, 12));
75 returnedReason
= str
.substring(13);
77 bytesAck
= bytesAck
+ str
.length();
78 } else if (str
.contains(":")) {
79 String
[] kv
= str
.split(":");
80 String name
= kv
[0].toLowerCase().trim();
81 if (name
.contains("set-cookie")) {
82 HTTPCookie cookie
= new HTTPCookie(kv
[1].trim());
83 setCookies
.add(cookie
);
85 headers
.put(name
, kv
[1].trim());
88 bytesAck
= bytesAck
+ str
.length();
96 if ("chunked".equals(headers
.get("transfer-encoding"))) {
98 // read one line for size, then read n bytes
99 String chunkheader
= readLineASCII();
100 chunkheader
= chunkheader
.trim();
101 int size
= Integer
.parseInt(chunkheader
, 16)+2; // add two for CRLF
102 if (size
!= 0 && (size
-2) != 0) { // stupid hack to see if s-2, should be fixed
103 byte[] chunk
= new byte[size
];
106 } while (size
> super.available());
107 int read
= super.read(chunk
,off
,size
);
108 //if (size != read) {
109 // System.err.println("OOPS! Read "+read + " out of "+size);
111 System
.arraycopy(chunk
, 0, b
, off
, size
-2);
117 return super.read(b
, off
, len
);
120 protected String
readLineASCII() throws IOException
{
123 byte[] buf
= new byte[65535];
124 while ((b
= super.read()) != -1) {
126 buf
[read
] = (byte) b
;
136 } else if (b
== '\n') {
140 return new String(buf
, 0, read
);
143 public HashMap
getHeaders() {
146 public List
<HTTPCookie
> getCookies() {