1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.codec.http;
17
18 import java.util.Iterator;
19 import java.util.List;
20
21 final class HttpCodecUtil {
22
23 static void validateHeaderName(String name) {
24 if (name == null) {
25 throw new NullPointerException("name");
26 }
27 for (int i = 0; i < name.length(); i ++) {
28 char c = name.charAt(i);
29 if (c > 127) {
30 throw new IllegalArgumentException(
31 "name contains non-ascii character: " + name);
32 }
33
34
35 switch (c) {
36 case '\t': case '\n': case 0x0b: case '\f': case '\r':
37 case ' ': case ',': case ':': case ';': case '=':
38 throw new IllegalArgumentException(
39 "name contains one of the following prohibited characters: " +
40 "=,;: \\t\\r\\n\\v\\f: " + name);
41 }
42 }
43 }
44
45 static void validateHeaderValue(String value) {
46 if (value == null) {
47 throw new NullPointerException("value");
48 }
49
50
51
52
53 int state = 0;
54
55 for (int i = 0; i < value.length(); i ++) {
56 char c = value.charAt(i);
57
58
59 switch (c) {
60 case 0x0b:
61 throw new IllegalArgumentException(
62 "value contains a prohibited character '\\v': " + value);
63 case '\f':
64 throw new IllegalArgumentException(
65 "value contains a prohibited character '\\f': " + value);
66 }
67
68
69 switch (state) {
70 case 0:
71 switch (c) {
72 case '\r':
73 state = 1;
74 break;
75 case '\n':
76 state = 2;
77 break;
78 }
79 break;
80 case 1:
81 switch (c) {
82 case '\n':
83 state = 2;
84 break;
85 default:
86 throw new IllegalArgumentException(
87 "Only '\\n' is allowed after '\\r': " + value);
88 }
89 break;
90 case 2:
91 switch (c) {
92 case '\t': case ' ':
93 state = 0;
94 break;
95 default:
96 throw new IllegalArgumentException(
97 "Only ' ' and '\\t' are allowed after '\\n': " + value);
98 }
99 }
100 }
101
102 if (state != 0) {
103 throw new IllegalArgumentException(
104 "value must not end with '\\r' or '\\n':" + value);
105 }
106 }
107
108 static boolean isTransferEncodingChunked(HttpMessage m) {
109 List<String> chunked = m.headers().getAll(HttpHeaders.Names.TRANSFER_ENCODING);
110 if (chunked.isEmpty()) {
111 return false;
112 }
113
114 for (String v: chunked) {
115 if (v.equalsIgnoreCase(HttpHeaders.Values.CHUNKED)) {
116 return true;
117 }
118 }
119 return false;
120 }
121
122 static void removeTransferEncodingChunked(HttpMessage m) {
123 List<String> values = m.headers().getAll(HttpHeaders.Names.TRANSFER_ENCODING);
124 if (values.isEmpty()) {
125 return;
126 }
127 Iterator<String> valuesIt = values.iterator();
128 while (valuesIt.hasNext()) {
129 String value = valuesIt.next();
130 if (value.equalsIgnoreCase(HttpHeaders.Values.CHUNKED)) {
131 valuesIt.remove();
132 }
133 }
134 if (values.isEmpty()) {
135 m.headers().remove(HttpHeaders.Names.TRANSFER_ENCODING);
136 } else {
137 m.headers().set(HttpHeaders.Names.TRANSFER_ENCODING, values);
138 }
139 }
140
141 static boolean isContentLengthSet(HttpMessage m) {
142 List<String> contentLength = m.headers().getAll(HttpHeaders.Names.CONTENT_LENGTH);
143 return !contentLength.isEmpty();
144 }
145
146 private HttpCodecUtil() {
147 }
148 }