View Javadoc

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