1 /*
2 * Copyright 2009 Red Hat, Inc.
3 *
4 * Red Hat licenses this file to you under the Apache License, version 2.0
5 * (the "License"); you may not use this file except in compliance with the
6 * License. You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 package org.jboss.netty.handler.codec.http2;
17
18 import java.nio.charset.Charset;
19
20 import org.jboss.netty.buffer.ChannelBuffer;
21 import org.jboss.netty.util.CharsetUtil;
22
23 /**
24 * Shared Static object between HttpMessageDecoder, HttpPostRequestDecoder and HttpPostRequestEncoder
25 *
26 * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
27 * @author Andy Taylor (andy.taylor@jboss.org)
28 * @author <a href="http://gleamynode.net/">Trustin Lee</a>
29 * @author <a href="http://openr66.free.fr/">Frederic Bregier</a>
30 *
31 */
32 public class HttpPostBodyUtil {
33 public static int chunkSize = 8096;
34
35 /**
36 * HTTP content disposition header name.
37 */
38 public static final String CONTENT_DISPOSITION = "Content-Disposition";
39
40 public static final String NAME = "name";
41
42 public static final String FILENAME = "filename";
43
44 /**
45 * Content-disposition value for form data.
46 */
47 public static final String FORM_DATA = "form-data";
48
49 /**
50 * Content-disposition value for file attachment.
51 */
52 public static final String ATTACHMENT = "attachment";
53
54 /**
55 * Content-disposition value for file attachment.
56 */
57 public static final String FILE = "file";
58
59 /**
60 * HTTP content type body attribute for multiple uploads.
61 */
62 public static final String MULTIPART_MIXED = "multipart/mixed";
63
64 /**
65 * Charset for 8BIT
66 */
67 public static final Charset ISO_8859_1 = CharsetUtil.ISO_8859_1;
68
69 /**
70 * Charset for 7BIT
71 */
72 public static final Charset US_ASCII = CharsetUtil.US_ASCII;
73
74 /**
75 * Default Content-Type in binary form
76 */
77 public static final String DEFAULT_BINARY_CONTENT_TYPE = "application/octet-stream";
78
79 /**
80 * Default Content-Type in Text form
81 */
82 public static final String DEFAULT_TEXT_CONTENT_TYPE = "text/plain";
83
84 /**
85 * Allowed mechanism for multipart
86 * mechanism := "7bit"
87 / "8bit"
88 / "binary"
89 Not allowed: "quoted-printable"
90 / "base64"
91 */
92 public static enum TransferEncodingMechanism {
93 /**
94 * Default encoding
95 */
96 BIT7("7bit"),
97 /**
98 * Short lines but not in ASCII - no encoding
99 */
100 BIT8("8bit"),
101 /**
102 * Could be long text not in ASCII - no encoding
103 */
104 BINARY("binary");
105
106 public String value;
107
108 private TransferEncodingMechanism(String value) {
109 this.value = value;
110 }
111
112 private TransferEncodingMechanism() {
113 value = name();
114 }
115
116 @Override
117 public String toString() {
118 return value;
119 }
120 }
121
122 private HttpPostBodyUtil() {
123 super();
124 }
125
126 /**
127 * Exception when NO Backend Array is found
128 */
129 static class SeekAheadNoBackArrayException extends Exception {
130 private static final long serialVersionUID = -630418804938699495L;
131 }
132
133 /**
134 * This class intends to decrease the CPU in seeking ahead some bytes in
135 * HttpPostRequestDecoder
136 */
137 static class SeekAheadOptimize {
138 byte[] bytes;
139
140 int readerIndex;
141
142 int pos;
143
144 int limit;
145
146 ChannelBuffer buffer;
147
148 /**
149 * @param buffer
150 */
151 SeekAheadOptimize(ChannelBuffer buffer) throws SeekAheadNoBackArrayException {
152 if (!buffer.hasArray()) {
153 throw new SeekAheadNoBackArrayException();
154 }
155 this.buffer = buffer;
156 this.bytes = buffer.array();
157 this.pos = this.readerIndex = buffer.readerIndex();
158 this.limit = buffer.writerIndex();
159 }
160
161 /**
162 *
163 * @param minus this value will be used as (currentPos - minus) to set
164 * the current readerIndex in the buffer.
165 */
166 void setReadPosition(int minus) {
167 pos -= minus;
168 readerIndex = pos;
169 buffer.readerIndex(readerIndex);
170 }
171
172 void clear() {
173 this.buffer = null;
174 this.bytes = null;
175 this.limit = 0;
176 this.pos = 0;
177 this.readerIndex = 0;
178 }
179 }
180
181 /**
182 * Find the first non whitespace
183 * @param sb
184 * @param offset
185 * @return the rank of the first non whitespace
186 */
187 static int findNonWhitespace(String sb, int offset) {
188 int result;
189 for (result = offset; result < sb.length(); result ++) {
190 if (!Character.isWhitespace(sb.charAt(result))) {
191 break;
192 }
193 }
194 return result;
195 }
196
197 /**
198 * Find the first whitespace
199 * @param sb
200 * @param offset
201 * @return the rank of the first whitespace
202 */
203 static int findWhitespace(String sb, int offset) {
204 int result;
205 for (result = offset; result < sb.length(); result ++) {
206 if (Character.isWhitespace(sb.charAt(result))) {
207 break;
208 }
209 }
210 return result;
211 }
212
213 /**
214 * Find the end of String
215 * @param sb
216 * @return the rank of the end of string
217 */
218 static int findEndOfString(String sb) {
219 int result;
220 for (result = sb.length(); result > 0; result --) {
221 if (!Character.isWhitespace(sb.charAt(result - 1))) {
222 break;
223 }
224 }
225 return result;
226 }
227 }