1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.http.multipart;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.handler.codec.http.HttpConstants;
20
21
22
23
24 final class HttpPostBodyUtil {
25
26 public static final int chunkSize = 8096;
27
28
29
30
31 public static final String DEFAULT_BINARY_CONTENT_TYPE = "application/octet-stream";
32
33
34
35
36 public static final String DEFAULT_TEXT_CONTENT_TYPE = "text/plain";
37
38
39
40
41
42
43
44
45
46 public enum TransferEncodingMechanism {
47
48
49
50 BIT7("7bit"),
51
52
53
54 BIT8("8bit"),
55
56
57
58 BINARY("binary");
59
60 private final String value;
61
62 TransferEncodingMechanism(String value) {
63 this.value = value;
64 }
65
66 public String value() {
67 return value;
68 }
69
70 @Override
71 public String toString() {
72 return value;
73 }
74 }
75
76 private HttpPostBodyUtil() {
77 }
78
79
80
81
82
83 static class SeekAheadOptimize {
84 byte[] bytes;
85 int readerIndex;
86 int pos;
87 int origPos;
88 int limit;
89 ByteBuf buffer;
90
91
92
93
94 SeekAheadOptimize(ByteBuf buffer) {
95 if (!buffer.hasArray()) {
96 throw new IllegalArgumentException("buffer hasn't backing byte array");
97 }
98 this.buffer = buffer;
99 bytes = buffer.array();
100 readerIndex = buffer.readerIndex();
101 origPos = pos = buffer.arrayOffset() + readerIndex;
102 limit = buffer.arrayOffset() + buffer.writerIndex();
103 }
104
105
106
107
108
109
110 void setReadPosition(int minus) {
111 pos -= minus;
112 readerIndex = getReadPosition(pos);
113 buffer.readerIndex(readerIndex);
114 }
115
116
117
118
119
120
121 int getReadPosition(int index) {
122 return index - origPos + readerIndex;
123 }
124 }
125
126
127
128
129
130 static int findNonWhitespace(String sb, int offset) {
131 int result;
132 for (result = offset; result < sb.length(); result ++) {
133 if (!Character.isWhitespace(sb.charAt(result))) {
134 break;
135 }
136 }
137 return result;
138 }
139
140
141
142
143
144 static int findEndOfString(String sb) {
145 int result;
146 for (result = sb.length(); result > 0; result --) {
147 if (!Character.isWhitespace(sb.charAt(result - 1))) {
148 break;
149 }
150 }
151 return result;
152 }
153
154
155
156
157
158
159
160
161
162 static int findLineBreak(ByteBuf buffer, int index) {
163 int toRead = buffer.readableBytes() - (index - buffer.readerIndex());
164 int posFirstChar = buffer.bytesBefore(index, toRead, HttpConstants.LF);
165 if (posFirstChar == -1) {
166
167 return -1;
168 }
169 if (posFirstChar > 0 && buffer.getByte(index + posFirstChar - 1) == HttpConstants.CR) {
170 posFirstChar--;
171 }
172 return posFirstChar;
173 }
174
175
176
177
178
179
180
181
182
183 static int findLastLineBreak(ByteBuf buffer, int index) {
184 int candidate = findLineBreak(buffer, index);
185 int findCRLF = 0;
186 if (candidate >= 0) {
187 if (buffer.getByte(index + candidate) == HttpConstants.CR) {
188 findCRLF = 2;
189 } else {
190 findCRLF = 1;
191 }
192 candidate += findCRLF;
193 }
194 int next;
195 while (candidate > 0 && (next = findLineBreak(buffer, index + candidate)) >= 0) {
196 candidate += next;
197 if (buffer.getByte(index + candidate) == HttpConstants.CR) {
198 findCRLF = 2;
199 } else {
200 findCRLF = 1;
201 }
202 candidate += findCRLF;
203 }
204 return candidate - findCRLF;
205 }
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220 static int findDelimiter(ByteBuf buffer, int index, byte[] delimiter, boolean precededByLineBreak) {
221 final int delimiterLength = delimiter.length;
222 final int readerIndex = buffer.readerIndex();
223 final int writerIndex = buffer.writerIndex();
224 int toRead = writerIndex - index;
225 int newOffset = index;
226 boolean delimiterNotFound = true;
227 while (delimiterNotFound && delimiterLength <= toRead) {
228
229 int posDelimiter = buffer.bytesBefore(newOffset, toRead, delimiter[0]);
230 if (posDelimiter < 0) {
231 return -1;
232 }
233 newOffset += posDelimiter;
234 toRead -= posDelimiter;
235
236 if (toRead >= delimiterLength) {
237 delimiterNotFound = false;
238 for (int i = 0; i < delimiterLength; i++) {
239 if (buffer.getByte(newOffset + i) != delimiter[i]) {
240 newOffset++;
241 toRead--;
242 delimiterNotFound = true;
243 break;
244 }
245 }
246 }
247 if (!delimiterNotFound) {
248
249 if (precededByLineBreak && newOffset > readerIndex) {
250 if (buffer.getByte(newOffset - 1) == HttpConstants.LF) {
251 newOffset--;
252
253 if (newOffset > readerIndex && buffer.getByte(newOffset - 1) == HttpConstants.CR) {
254 newOffset--;
255 }
256 } else {
257
258 newOffset++;
259 toRead--;
260 delimiterNotFound = true;
261 continue;
262 }
263 }
264 return newOffset - readerIndex;
265 }
266 }
267 return -1;
268 }
269 }