OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of mime; | 5 part of mime; |
6 | 6 |
7 | 7 |
8 /** | 8 /** |
9 * A Mime Multipart class representing each part parsed by | 9 * A Mime Multipart class representing each part parsed by |
10 * [MimeMultipartTransformer]. The data is streamed in as it become available. | 10 * [MimeMultipartTransformer]. The data is streamed in as it become available. |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
79 | 79 |
80 List<int> _boundary; | 80 List<int> _boundary; |
81 int _state = _START; | 81 int _state = _START; |
82 int _boundaryIndex = 2; | 82 int _boundaryIndex = 2; |
83 | 83 |
84 // Current index in the data buffer. If index is negative then it | 84 // Current index in the data buffer. If index is negative then it |
85 // is the index into the artificial prefix of the boundary string. | 85 // is the index into the artificial prefix of the boundary string. |
86 int _index; | 86 int _index; |
87 List<int> _buffer; | 87 List<int> _buffer; |
88 | 88 |
89 StringBuffer _headerField = new StringBuffer(); | 89 List<int> _headerField = []; |
90 StringBuffer _headerValue = new StringBuffer(); | 90 List<int> _headerValue = []; |
91 | 91 |
92 /** | 92 /** |
93 * Construct a new MIME multipart parser with the boundary | 93 * Construct a new MIME multipart parser with the boundary |
94 * [boundary]. The boundary should be as specified in the content | 94 * [boundary]. The boundary should be as specified in the content |
95 * type parameter, that is without the -- prefix. | 95 * type parameter, that is without the -- prefix. |
96 */ | 96 */ |
97 MimeMultipartTransformer(String boundary) { | 97 MimeMultipartTransformer(String boundary) { |
98 List<int> charCodes = boundary.codeUnits; | 98 List<int> charCodes = boundary.codeUnits; |
99 _boundary = new Uint8List(4 + charCodes.length); | 99 _boundary = new Uint8List(4 + charCodes.length); |
100 // Set-up the matching boundary preceding it with CRLF and two | 100 // Set-up the matching boundary preceding it with CRLF and two |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
239 _multipartController = null; | 239 _multipartController = null; |
240 _state = _HEADER_START; | 240 _state = _HEADER_START; |
241 break; | 241 break; |
242 | 242 |
243 case _HEADER_START: | 243 case _HEADER_START: |
244 _headers = new Map<String, String>(); | 244 _headers = new Map<String, String>(); |
245 if (byte == _CharCode.CR) { | 245 if (byte == _CharCode.CR) { |
246 _state = _HEADER_ENDING; | 246 _state = _HEADER_ENDING; |
247 } else { | 247 } else { |
248 // Start of new header field. | 248 // Start of new header field. |
249 _headerField.writeCharCode(_toLowerCase(byte)); | 249 _headerField.add(_toLowerCase(byte)); |
250 _state = _HEADER_FIELD; | 250 _state = _HEADER_FIELD; |
251 } | 251 } |
252 break; | 252 break; |
253 | 253 |
254 case _HEADER_FIELD: | 254 case _HEADER_FIELD: |
255 if (byte == _CharCode.COLON) { | 255 if (byte == _CharCode.COLON) { |
256 _state = _HEADER_VALUE_START; | 256 _state = _HEADER_VALUE_START; |
257 } else { | 257 } else { |
258 if (!_isTokenChar(byte)) { | 258 if (!_isTokenChar(byte)) { |
259 throw new MimeMultipartException("Invalid header field name"); | 259 throw new MimeMultipartException("Invalid header field name"); |
260 } | 260 } |
261 _headerField.writeCharCode(_toLowerCase(byte)); | 261 _headerField.add(_toLowerCase(byte)); |
262 } | 262 } |
263 break; | 263 break; |
264 | 264 |
265 case _HEADER_VALUE_START: | 265 case _HEADER_VALUE_START: |
266 if (byte == _CharCode.CR) { | 266 if (byte == _CharCode.CR) { |
267 _state = _HEADER_VALUE_FOLDING_OR_ENDING; | 267 _state = _HEADER_VALUE_FOLDING_OR_ENDING; |
268 } else if (byte != _CharCode.SP && byte != _CharCode.HT) { | 268 } else if (byte != _CharCode.SP && byte != _CharCode.HT) { |
269 // Start of new header value. | 269 // Start of new header value. |
270 _headerValue.writeCharCode(byte); | 270 _headerValue.add(byte); |
271 _state = _HEADER_VALUE; | 271 _state = _HEADER_VALUE; |
272 } | 272 } |
273 break; | 273 break; |
274 | 274 |
275 case _HEADER_VALUE: | 275 case _HEADER_VALUE: |
276 if (byte == _CharCode.CR) { | 276 if (byte == _CharCode.CR) { |
277 _state = _HEADER_VALUE_FOLDING_OR_ENDING; | 277 _state = _HEADER_VALUE_FOLDING_OR_ENDING; |
278 } else { | 278 } else { |
279 _headerValue.writeCharCode(byte); | 279 _headerValue.add(byte); |
280 } | 280 } |
281 break; | 281 break; |
282 | 282 |
283 case _HEADER_VALUE_FOLDING_OR_ENDING: | 283 case _HEADER_VALUE_FOLDING_OR_ENDING: |
284 _expect(byte, _CharCode.LF); | 284 _expect(byte, _CharCode.LF); |
285 _state = _HEADER_VALUE_FOLD_OR_END; | 285 _state = _HEADER_VALUE_FOLD_OR_END; |
286 break; | 286 break; |
287 | 287 |
288 case _HEADER_VALUE_FOLD_OR_END: | 288 case _HEADER_VALUE_FOLD_OR_END: |
289 if (byte == _CharCode.SP || byte == _CharCode.HT) { | 289 if (byte == _CharCode.SP || byte == _CharCode.HT) { |
290 _state = _HEADER_VALUE_START; | 290 _state = _HEADER_VALUE_START; |
291 } else { | 291 } else { |
292 String headerField = _headerField.toString(); | 292 String headerField = UTF8.decode(_headerField); |
Søren Gjesse
2013/10/30 10:08:09
Should there be a way of configuring this?
Anders Johnsen
2013/10/30 10:34:04
I don't think so. The only behavior I've seen has
| |
293 String headerValue =_headerValue.toString(); | 293 String headerValue = UTF8.decode(_headerValue); |
294 _headers[headerField.toLowerCase()] = headerValue; | 294 _headers[headerField.toLowerCase()] = headerValue; |
295 _headerField = new StringBuffer(); | 295 _headerField = []; |
296 _headerValue = new StringBuffer(); | 296 _headerValue = []; |
297 if (byte == _CharCode.CR) { | 297 if (byte == _CharCode.CR) { |
298 _state = _HEADER_ENDING; | 298 _state = _HEADER_ENDING; |
299 } else { | 299 } else { |
300 // Start of new header field. | 300 // Start of new header field. |
301 _headerField.writeCharCode(_toLowerCase(byte)); | 301 _headerField.add(_toLowerCase(byte)); |
302 _state = _HEADER_FIELD; | 302 _state = _HEADER_FIELD; |
303 } | 303 } |
304 } | 304 } |
305 break; | 305 break; |
306 | 306 |
307 case _HEADER_ENDING: | 307 case _HEADER_ENDING: |
308 _expect(byte, _CharCode.LF); | 308 _expect(byte, _CharCode.LF); |
309 _multipartController = new StreamController( | 309 _multipartController = new StreamController( |
310 sync: true, | 310 sync: true, |
311 onPause: () { | 311 onPause: () { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
409 } | 409 } |
410 } | 410 } |
411 } | 411 } |
412 | 412 |
413 | 413 |
414 class MimeMultipartException implements Exception { | 414 class MimeMultipartException implements Exception { |
415 const MimeMultipartException([String this.message = ""]); | 415 const MimeMultipartException([String this.message = ""]); |
416 String toString() => "MimeMultipartException: $message"; | 416 String toString() => "MimeMultipartException: $message"; |
417 final String message; | 417 final String message; |
418 } | 418 } |
OLD | NEW |