1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.mimo.netty.handler.codec.icap;
15
16 import java.util.ArrayList;
17 import java.util.List;
18
19 import org.jboss.netty.buffer.ChannelBuffer;
20 import org.jboss.netty.handler.codec.frame.TooLongFrameException;
21
22
23
24
25
26
27
28 public final class IcapDecoderUtil {
29
30 private IcapDecoderUtil() {
31 }
32
33
34
35
36
37
38 public static void skipControlCharacters(ChannelBuffer buffer) {
39 for (;;) {
40 char c = (char) buffer.readUnsignedByte();
41 if (!Character.isISOControl(c) &&
42 !Character.isWhitespace(c)) {
43 buffer.readerIndex(buffer.readerIndex() - 1);
44 break;
45 }
46 }
47 }
48
49
50
51
52
53
54
55
56 public static String readLine(ChannelBuffer buffer, int maxLineLength) throws DecodingException {
57 StringBuilder sb = new StringBuilder(64);
58 int lineLength = 0;
59 while (true) {
60 byte nextByte = buffer.readByte();
61 if (nextByte == IcapCodecUtil.CR) {
62 nextByte = buffer.readByte();
63 if (nextByte == IcapCodecUtil.LF) {
64 return sb.toString();
65 }
66 } else if (nextByte == IcapCodecUtil.LF) {
67 return sb.toString();
68 } else {
69 if (lineLength >= maxLineLength) {
70 throw new DecodingException(new TooLongFrameException(
71 "An HTTP line is larger than " + maxLineLength +
72 " bytes."));
73 }
74 lineLength ++;
75 sb.append((char) nextByte);
76 }
77 }
78 }
79
80
81
82
83
84
85
86
87
88 public static String previewLine(ChannelBuffer buffer, int maxLineLength) throws DecodingException {
89 StringBuilder sb = new StringBuilder(64);
90 int lineLength = 0;
91 for(int i = buffer.readerIndex() ; i < buffer.readableBytes() ; i++) {
92 byte nextByte = buffer.getByte(i);
93 if (nextByte == IcapCodecUtil.CR) {
94 nextByte = buffer.getByte(++i);
95 if (nextByte == IcapCodecUtil.LF) {
96 break;
97 }
98 } else if (nextByte == IcapCodecUtil.LF) {
99 break;
100 } else {
101 if (lineLength >= maxLineLength) {
102 throw new DecodingException(new TooLongFrameException(
103 "An HTTP line is larger than " + maxLineLength +
104 " bytes."));
105 }
106 lineLength ++;
107 sb.append((char) nextByte);
108 }
109 }
110 return sb.toString();
111 }
112
113
114
115
116
117
118 public static String[] splitInitialLine(String sb) {
119 int aStart;
120 int aEnd;
121 int bStart;
122 int bEnd;
123 int cStart;
124 int cEnd;
125
126 aStart = findNonWhitespace(sb, 0);
127 aEnd = findWhitespace(sb, aStart);
128
129 bStart = findNonWhitespace(sb, aEnd);
130 bEnd = findWhitespace(sb, bStart);
131
132 cStart = findNonWhitespace(sb, bEnd);
133 cEnd = findEndOfString(sb);
134
135 return new String[] { sb.substring(aStart, aEnd),
136 sb.substring(bStart, bEnd),
137 cStart < cEnd ? sb.substring(cStart, cEnd) : "" };
138 }
139
140
141
142
143
144
145
146 public static int findNonWhitespace(String sb, int offset) {
147 int result;
148 for (result = offset; result < sb.length(); result++) {
149 if (!Character.isWhitespace(sb.charAt(result))) {
150 break;
151 }
152 }
153 return result;
154 }
155
156
157
158
159
160
161
162 public static int findWhitespace(String sb, int offset) {
163 int result;
164 for (result = offset; result < sb.length(); result++) {
165 if (Character.isWhitespace(sb.charAt(result))) {
166 break;
167 }
168 }
169 return result;
170 }
171
172
173
174
175
176
177 public static int findEndOfString(String sb) {
178 int result;
179 for (result = sb.length(); result > 0; result--) {
180 if (!Character.isWhitespace(sb.charAt(result - 1))) {
181 break;
182 }
183 }
184 return result;
185 }
186
187
188
189
190
191
192
193 public static int getChunkSize(String line) throws DecodingException {
194 String hex = line.trim();
195 if(hex.equals(IcapCodecUtil.IEOF_SEQUENCE_STRING)) {
196 return -1;
197 }
198 for (int i = 0; i < hex.length(); i ++) {
199 char c = hex.charAt(i);
200 if (c == ';' || Character.isWhitespace(c) || Character.isISOControl(c)) {
201 hex = hex.substring(0, i);
202 break;
203 }
204 }
205 try {
206 return Integer.parseInt(hex, 16);
207 } catch(NumberFormatException nfe) {
208 throw new DecodingException(nfe);
209 }
210 }
211
212
213
214
215
216
217
218
219 public static List<String[]> readHeaders(ChannelBuffer buffer, int maxSize) throws DecodingException {
220 List<String[]> headerList = new ArrayList<String[]>();
221 SizeDelimiter sizeDelimiter = new SizeDelimiter(maxSize);
222 String line = IcapDecoderUtil.readSingleHeaderLine(buffer,sizeDelimiter);
223 String name = null;
224 String value = null;
225 if(line.length() != 0) {
226 while(line.length() != 0) {
227 if(name != null && IcapDecoderUtil.isHeaderLineSimpleValue(line)) {
228 value = value + ' ' + line.trim();
229 } else {
230 if(name != null) {
231 headerList.add(new String[]{name,value});
232 }
233 String[] header = IcapDecoderUtil.splitHeader(line);
234 name = header[0];
235 value = header[1];
236 }
237 line = IcapDecoderUtil.readSingleHeaderLine(buffer,sizeDelimiter);
238 }
239 if (name != null) {
240 headerList.add(new String[]{name,value});
241 }
242 }
243 return headerList;
244 }
245
246 public static boolean isHeaderLineSimpleValue(String header) {
247 char firstChar = header.charAt(0);
248 return firstChar == ' ' || firstChar == '\t';
249 }
250
251
252
253
254
255
256
257
258 public static String readSingleHeaderLine(ChannelBuffer buffer, SizeDelimiter sizeDelimiter) throws DecodingException {
259 StringBuilder sb = new StringBuilder(64);
260 loop: for (;;) {
261 char nextByte = (char) buffer.readByte();
262 sizeDelimiter.increment();
263
264 if(nextByte == IcapCodecUtil.CR) {
265 nextByte = (char) buffer.readByte();
266 sizeDelimiter.increment();
267 if (nextByte == IcapCodecUtil.LF) {
268 break loop;
269 }
270 } else if(nextByte == IcapCodecUtil.LF) {
271 break loop;
272 }
273 sb.append(nextByte);
274 }
275 return sb.toString();
276 }
277
278
279
280
281
282
283 public static String[] splitHeader(String sb) {
284 final int length = sb.length();
285 int nameStart;
286 int nameEnd;
287 int colonEnd;
288 int valueStart;
289 int valueEnd;
290
291 nameStart = findNonWhitespace(sb, 0);
292 for (nameEnd = nameStart; nameEnd < length; nameEnd ++) {
293 char ch = sb.charAt(nameEnd);
294 if (ch == ':' || Character.isWhitespace(ch)) {
295 break;
296 }
297 }
298
299 for (colonEnd = nameEnd; colonEnd < length; colonEnd ++) {
300 if (sb.charAt(colonEnd) == ':') {
301 colonEnd ++;
302 break;
303 }
304 }
305
306 valueStart = findNonWhitespace(sb, colonEnd);
307 if (valueStart == length) {
308 return new String[] {
309 sb.substring(nameStart, nameEnd),
310 ""
311 };
312 }
313
314 valueEnd = findEndOfString(sb);
315 return new String[] {
316 sb.substring(nameStart, nameEnd),
317 sb.substring(valueStart, valueEnd)
318 };
319 }
320 }