1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package org.apache.commons.httpclient;
33
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.ByteArrayOutputStream;
37 import java.util.ArrayList;
38
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41
42 /***
43 * A utility class for parsing http header values.
44 *
45 * @author Michael Becke
46 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
47 *
48 * @since 2.0beta1
49 */
50 public class HttpParser {
51
52 /*** Log object for this class. */
53 private static final Log LOG = LogFactory.getLog(HttpParser.class);
54
55 /***
56 * Constructor for HttpParser.
57 */
58 private HttpParser() { }
59
60 /***
61 * Return byte array from an (unchunked) input stream.
62 * Stop reading when <tt>"\n"</tt> terminator encountered
63 * If the stream ends before the line terminator is found,
64 * the last part of the string will still be returned.
65 * If no input data available, <code>null</code> is returned
66 *
67 * @param inputStream the stream to read from
68 *
69 * @throws IOException if an I/O problem occurs
70 * @return a byte array from the stream
71 */
72 public static byte[] readRawLine(InputStream inputStream) throws IOException {
73 LOG.trace("enter HttpParser.readRawLine()");
74
75 ByteArrayOutputStream buf = new ByteArrayOutputStream();
76 int ch;
77 while ((ch = inputStream.read()) >= 0) {
78 buf.write(ch);
79 if (ch == '\n') {
80 break;
81 }
82 }
83 if (buf.size() == 0) {
84 return null;
85 }
86 return buf.toByteArray();
87 }
88
89 /***
90 * Read up to <tt>"\n"</tt> from an (unchunked) input stream.
91 * If the stream ends before the line terminator is found,
92 * the last part of the string will still be returned.
93 * If no input data available, <code>null</code> is returned
94 *
95 * @param inputStream the stream to read from
96 *
97 * @throws IOException if an I/O problem occurs
98 * @return a line from the stream
99 */
100
101 public static String readLine(InputStream inputStream) throws IOException {
102 LOG.trace("enter HttpParser.readLine()");
103 byte[] rawdata = readRawLine(inputStream);
104 if (rawdata == null) {
105 return null;
106 }
107 int len = rawdata.length;
108 int offset = 0;
109 if (len > 0) {
110 if (rawdata[len - 1] == '\n') {
111 offset++;
112 if (len > 1) {
113 if (rawdata[len - 2] == '\r') {
114 offset++;
115 }
116 }
117 }
118 }
119 return HttpConstants.getString(rawdata, 0, len - offset);
120 }
121
122 /***
123 * Parses headers from the given stream. Headers with the same name are not
124 * combined.
125 *
126 * @param is the stream to read headers from
127 *
128 * @return an array of headers in the order in which they were parsed
129 *
130 * @throws IOException if an IO error occurs while reading from the stream
131 * @throws HttpException if there is an error parsing a header value
132 */
133 public static Header[] parseHeaders(InputStream is) throws IOException, HttpException {
134 LOG.trace("enter HeaderParser.parseHeaders(HttpConnection, HeaderGroup)");
135
136 ArrayList headers = new ArrayList();
137 String name = null;
138 StringBuffer value = null;
139 for (; ;) {
140 String line = HttpParser.readLine(is);
141 if ((line == null) || (line.length() < 1)) {
142 break;
143 }
144
145
146
147
148
149 if ((line.charAt(0) == ' ') || (line.charAt(0) == '\t')) {
150
151
152 if (value != null) {
153 value.append(' ');
154 value.append(line.trim());
155 }
156 } else {
157
158 if (name != null) {
159 headers.add(new Header(name, value.toString()));
160 }
161
162
163
164 int colon = line.indexOf(":");
165 if (colon < 0) {
166 throw new HttpException("Unable to parse header: " + line);
167 }
168 name = line.substring(0, colon).trim();
169 value = new StringBuffer(line.substring(colon + 1).trim());
170 }
171
172 }
173
174
175 if (name != null) {
176 headers.add(new Header(name, value.toString()));
177 }
178
179 return (Header[]) headers.toArray(new Header[headers.size()]);
180 }
181
182 }