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 final 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     * Exception when NO Backend Array is found
125     */
126     static class SeekAheadNoBackArrayException extends Exception {
127         private static final long serialVersionUID = -630418804938699495L;
128     }
129 
130     /**
131     * This class intends to decrease the CPU in seeking ahead some bytes in
132     * HttpPostRequestDecoder
133     */
134     static class SeekAheadOptimize {
135         byte[] bytes;
136         int readerIndex;
137         int pos;
138         int origPos;
139         int limit;
140         ChannelBuffer buffer;
141 
142         SeekAheadOptimize(ChannelBuffer buffer) throws SeekAheadNoBackArrayException {
143             if (!buffer.hasArray()) {
144                 throw new SeekAheadNoBackArrayException();
145             }
146             this.buffer = buffer;
147             bytes = buffer.array();
148             readerIndex = buffer.readerIndex();
149             origPos = pos = buffer.arrayOffset() + readerIndex;
150             limit = buffer.arrayOffset() + buffer.writerIndex();
151         }
152 
153         /**
154         * @param minus this value will be used as (currentPos - minus) to set
155         * the current readerIndex in the buffer.
156         */
157         void setReadPosition(int minus) {
158             pos -= minus;
159             readerIndex = getReadPosition(pos);
160             buffer.readerIndex(readerIndex);
161         }
162 
163         /**
164         *
165         * @param index raw index of the array (pos in general)
166         * @return the value equivalent of raw index to be used in readerIndex(value)
167         */
168         int getReadPosition(int index) {
169             return index - origPos + readerIndex;
170         }
171 
172         void clear() {
173             buffer = null;
174             bytes = null;
175             limit = 0;
176             pos = 0;
177             readerIndex = 0;
178         }
179     }
180 
181     /**
182      * Find the first non whitespace
183      * @return the rank of the first non whitespace
184      */
185     static int findNonWhitespace(String sb, int offset) {
186         int result;
187         for (result = offset; result < sb.length(); result ++) {
188             if (!Character.isWhitespace(sb.charAt(result))) {
189                 break;
190             }
191         }
192         return result;
193     }
194 
195     /**
196      * Find the first whitespace
197      * @return the rank of the first whitespace
198      */
199     static int findWhitespace(String sb, int offset) {
200         int result;
201         for (result = offset; result < sb.length(); result ++) {
202             if (Character.isWhitespace(sb.charAt(result))) {
203                 break;
204             }
205         }
206         return result;
207     }
208 
209     /**
210      * Find the end of String
211      * @return the rank of the end of string
212      */
213     static int findEndOfString(String sb) {
214         int result;
215         for (result = sb.length(); result > 0; result --) {
216             if (!Character.isWhitespace(sb.charAt(result - 1))) {
217                 break;
218             }
219         }
220         return result;
221     }
222 
223 }