1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.codec.http2;
17
18 import java.nio.charset.Charset;
19 import java.util.List;
20
21 import org.jboss.netty.util.CharsetUtil;
22
23
24
25
26
27
28 class HttpCodecUtil {
29
30 static final byte SP = 32;
31
32
33 static final byte HT = 9;
34
35
36
37
38 static final byte CR = 13;
39
40
41
42
43 static final byte EQUALS = 61;
44
45
46
47
48 static final byte LF = 10;
49
50
51
52
53 static final byte[] CRLF = new byte[] { CR, LF };
54
55
56
57
58 static final byte COLON = 58;
59
60
61
62
63 static final byte SEMICOLON = 59;
64
65
66
67
68 static final byte COMMA = 44;
69
70 static final byte DOUBLE_QUOTE = '"';
71
72 static final Charset DEFAULT_CHARSET = CharsetUtil.UTF_8;
73
74 private HttpCodecUtil() {
75 super();
76 }
77
78 static void validateHeaderName(String name) {
79 if (name == null) {
80 throw new NullPointerException("name");
81 }
82 for (int i = 0; i < name.length(); i ++) {
83 char c = name.charAt(i);
84 if (c > 127) {
85 throw new IllegalArgumentException(
86 "name contains non-ascii character: " + name);
87 }
88
89
90 switch (c) {
91 case '\t': case '\n': case 0x0b: case '\f': case '\r':
92 case ' ': case ',': case ':': case ';': case '=':
93 throw new IllegalArgumentException(
94 "name contains one of the following prohibited characters: " +
95 "=,;: \\t\\r\\n\\v\\f: " + name);
96 }
97 }
98 }
99
100 static void validateHeaderValue(String value) {
101 if (value == null) {
102 throw new NullPointerException("value");
103 }
104
105
106
107
108 int state = 0;
109
110 for (int i = 0; i < value.length(); i ++) {
111 char c = value.charAt(i);
112
113
114 switch (c) {
115 case 0x0b:
116 throw new IllegalArgumentException(
117 "value contains a prohibited character '\\v': " + value);
118 case '\f':
119 throw new IllegalArgumentException(
120 "value contains a prohibited character '\\f': " + value);
121 }
122
123
124 switch (state) {
125 case 0:
126 switch (c) {
127 case '\r':
128 state = 1;
129 break;
130 case '\n':
131 state = 2;
132 break;
133 }
134 break;
135 case 1:
136 switch (c) {
137 case '\n':
138 state = 2;
139 break;
140 default:
141 throw new IllegalArgumentException(
142 "Only '\\n' is allowed after '\\r': " + value);
143 }
144 break;
145 case 2:
146 switch (c) {
147 case '\t': case ' ':
148 state = 0;
149 break;
150 default:
151 throw new IllegalArgumentException(
152 "Only ' ' and '\\t' are allowed after '\\n': " + value);
153 }
154 }
155 }
156
157 if (state != 0) {
158 throw new IllegalArgumentException(
159 "value must not end with '\\r' or '\\n':" + value);
160 }
161 }
162
163 static boolean isTransferEncodingChunked(HttpMessage m) {
164 List<String> chunked = m.getHeaders(HttpHeaders.Names.TRANSFER_ENCODING);
165 if (chunked.isEmpty()) {
166 return false;
167 }
168
169 for (String v: chunked) {
170 if (v.equalsIgnoreCase(HttpHeaders.Values.CHUNKED)) {
171 return true;
172 }
173 }
174 return false;
175 }
176 }