Source code: org/apache/http/util/HeaderUtils.java
1 /*
2 * $HeadURL: https://svn.apache.org/repos/asf/jakarta/httpcomponents/httpcore/tags/4.0-alpha2/src/java/org/apache/http/util/HeaderUtils.java $
3 * $Revision: 411100 $
4 * $Date: 2006-06-02 11:12:04 +0200 (Fri, 02 Jun 2006) $
5 *
6 * ====================================================================
7 *
8 * Copyright 1999-2006 The Apache Software Foundation
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 * ====================================================================
22 *
23 * This software consists of voluntary contributions made by many
24 * individuals on behalf of the Apache Software Foundation. For more
25 * information on the Apache Software Foundation, please see
26 * <http://www.apache.org/>.
27 *
28 */
29
30 package org.apache.http.util;
31
32 import java.io.IOException;
33 import java.util.ArrayList;
34
35 import org.apache.http.Header;
36 import org.apache.http.HeaderElement;
37 import org.apache.http.HttpException;
38 import org.apache.http.ProtocolException;
39 import org.apache.http.io.CharArrayBuffer;
40 import org.apache.http.io.HttpDataReceiver;
41
42 /**
43 * A utility class for processing HTTP headers.
44 *
45 * @author Michael Becke
46 * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
47 */
48 public class HeaderUtils {
49
50 private HeaderUtils() {
51 }
52
53 /**
54 * This class represents a raw HTTP header whose content is parsed
55 * 'on demand' only when the header value needs to be consumed
56 */
57 static class BufferedHeader extends Header {
58
59 private final CharArrayBuffer buffer;
60 private final int posValue;
61
62 public BufferedHeader(final String name, final CharArrayBuffer buffer, int posValue) {
63 super(name, null);
64 this.buffer = buffer;
65 this.posValue = posValue;
66 }
67
68 public String getValue() {
69 return this.buffer.substringTrimmed(this.posValue, this.buffer.length());
70 }
71
72 public HeaderElement[] getElements() {
73 return HeaderElement.parseAll(this.buffer, this.posValue, this.buffer.length());
74 }
75
76 public String toString() {
77 return this.buffer.toString();
78 }
79
80 }
81
82 /**
83 * Parses HTTP headers from the data receiver stream according to the generic
84 * format as given in Section 3.1 of RFC 822, RFC-2616 Section 4 and 19.3.
85 *
86 * @param datareceiver HTTP data receiver
87 * @param maxCount maximum number of headers allowed. If the number of headers
88 * received from the data stream exceeds maxCount value, an IOException
89 * will be thrown. Setting this parameter to a negative value or zero
90 * will disable the check.
91 * @return array of HTTP headers
92 *
93 * @throws HttpException
94 * @throws IOException
95 */
96 public static Header[] parseHeaders(final HttpDataReceiver datareceiver, int maxCount)
97 throws HttpException, IOException {
98 if (datareceiver == null) {
99 throw new IllegalArgumentException("HTTP data receiver may not be null");
100 }
101 ArrayList headerLines = new ArrayList();
102
103 CharArrayBuffer current = null;
104 CharArrayBuffer previous = null;
105 for (;;) {
106 if (current == null) {
107 current = new CharArrayBuffer(64);
108 } else {
109 current.clear();
110 }
111 int l = datareceiver.readLine(current);
112 if (l == -1 || current.length() < 1) {
113 break;
114 }
115 // Parse the header name and value
116 // Check for folded headers first
117 // Detect LWS-char see HTTP/1.0 or HTTP/1.1 Section 2.2
118 // discussion on folded headers
119 if ((current.charAt(0) == ' ' || current.charAt(0) == '\t') && previous != null) {
120 // we have continuation folded header
121 // so append value
122 int i = 0;
123 while (i < current.length()) {
124 char ch = current.charAt(i);
125 if (ch != ' ' && ch != '\t') {
126 break;
127 }
128 i++;
129 }
130 previous.append(' ');
131 previous.append(current, i, current.length() - i);
132 } else {
133 headerLines.add(current);
134 previous = current;
135 current = null;
136 }
137 if (maxCount > 0 && headerLines.size() >= maxCount) {
138 throw new IOException("Maximum header count exceeded");
139 }
140 }
141 Header[] headers = new Header[headerLines.size()];
142 for (int i = 0; i < headerLines.size(); i++) {
143 CharArrayBuffer buffer = (CharArrayBuffer) headerLines.get(i);
144 int colon = buffer.indexOf(':');
145 if (colon == -1) {
146 throw new ProtocolException("Invalid header: " + buffer.toString());
147 }
148 String s = buffer.substringTrimmed(0, colon);
149 if (s.equals("")) {
150 throw new ProtocolException("Invalid header: " + buffer.toString());
151 }
152 headers[i] = new BufferedHeader(s, buffer, colon + 1);
153 }
154 return headers;
155 }
156
157 public static Header[] parseHeaders(final HttpDataReceiver datareceiver)
158 throws HttpException, IOException {
159 return parseHeaders(datareceiver, -1);
160 }
161
162 }