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 library mime.multipart_transformer; |
6 | 6 |
| 7 import 'dart:async'; |
| 8 import 'dart:convert'; |
| 9 import 'dart:typed_data'; |
7 | 10 |
8 /** | 11 /** |
9 * A Mime Multipart class representing each part parsed by | 12 * A Mime Multipart class representing each part parsed by |
10 * [MimeMultipartTransformer]. The data is streamed in as it become available. | 13 * [MimeMultipartTransformer]. The data is streamed in as it become available. |
11 */ | 14 */ |
12 abstract class MimeMultipart extends Stream<List<int>> { | 15 abstract class MimeMultipart extends Stream<List<int>> { |
13 Map<String, String> get headers; | 16 Map<String, String> get headers; |
14 } | 17 } |
15 | 18 |
16 class _MimeMultipart extends MimeMultipart { | 19 class _MimeMultipart extends MimeMultipart { |
17 final Map<String, String> headers; | 20 final Map<String, String> headers; |
18 final Stream<List<int>> _stream; | 21 final Stream<List<int>> _stream; |
19 | 22 |
20 _MimeMultipart(this.headers, this._stream); | 23 _MimeMultipart(this.headers, this._stream); |
21 | 24 |
22 StreamSubscription<List<int>> listen(void onData(List<int> data), | 25 StreamSubscription<List<int>> listen(void onData(List<int> data), |
23 {void onDone(), | 26 {void onDone(), |
24 Function onError, | 27 Function onError, |
25 bool cancelOnError}) { | 28 bool cancelOnError}) { |
26 return _stream.listen(onData, | 29 return _stream.listen(onData, |
27 onDone: onDone, | 30 onDone: onDone, |
28 onError: onError, | 31 onError: onError, |
29 cancelOnError: cancelOnError); | 32 cancelOnError: cancelOnError); |
30 } | 33 } |
31 } | 34 } |
32 | 35 |
33 class _Const { | |
34 // Bytes for '()<>@,;:\\"/[]?={} \t'. | |
35 static const SEPARATORS = const [40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47, | |
36 91, 93, 63, 61, 123, 125, 32, 9]; | |
37 } | |
38 | |
39 class _CharCode { | 36 class _CharCode { |
40 static const int HT = 9; | 37 static const int HT = 9; |
41 static const int LF = 10; | 38 static const int LF = 10; |
42 static const int CR = 13; | 39 static const int CR = 13; |
43 static const int SP = 32; | 40 static const int SP = 32; |
44 static const int DASH = 45; | 41 static const int DASH = 45; |
45 static const int COLON = 58; | 42 static const int COLON = 58; |
46 } | 43 } |
47 | 44 |
48 /** | 45 /** |
(...skipping 15 matching lines...) Expand all Loading... |
64 static const int _HEADER_VALUE_FOLDING_OR_ENDING = 7; | 61 static const int _HEADER_VALUE_FOLDING_OR_ENDING = 7; |
65 static const int _HEADER_VALUE_FOLD_OR_END = 8; | 62 static const int _HEADER_VALUE_FOLD_OR_END = 8; |
66 static const int _HEADER_ENDING = 9; | 63 static const int _HEADER_ENDING = 9; |
67 static const int _CONTENT = 10; | 64 static const int _CONTENT = 10; |
68 static const int _LAST_BOUNDARY_DASH2 = 11; | 65 static const int _LAST_BOUNDARY_DASH2 = 11; |
69 static const int _LAST_BOUNDARY_ENDING = 12; | 66 static const int _LAST_BOUNDARY_ENDING = 12; |
70 static const int _LAST_BOUNDARY_END = 13; | 67 static const int _LAST_BOUNDARY_END = 13; |
71 static const int _DONE = 14; | 68 static const int _DONE = 14; |
72 static const int _FAILURE = 15; | 69 static const int _FAILURE = 15; |
73 | 70 |
| 71 // Bytes for '()<>@,;:\\"/[]?={} \t'. |
| 72 static const _SEPARATORS = const [40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47, |
| 73 91, 93, 63, 61, 123, 125, 32, 9]; |
| 74 |
74 StreamController _controller; | 75 StreamController _controller; |
75 StreamSubscription _subscription; | 76 StreamSubscription _subscription; |
76 | 77 |
77 StreamController _multipartController; | 78 StreamController _multipartController; |
78 Map<String, String> _headers; | 79 Map<String, String> _headers; |
79 | 80 |
80 List<int> _boundary; | 81 List<int> _boundary; |
81 int _state = _START; | 82 int _state = _START; |
82 int _boundaryIndex = 2; | 83 int _boundaryIndex = 2; |
83 | 84 |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 | 381 |
381 // Resume if at end. | 382 // Resume if at end. |
382 if (_index == _buffer.length) { | 383 if (_index == _buffer.length) { |
383 _buffer = null; | 384 _buffer = null; |
384 _index = null; | 385 _index = null; |
385 _resumeStream(); | 386 _resumeStream(); |
386 } | 387 } |
387 } | 388 } |
388 | 389 |
389 bool _isTokenChar(int byte) { | 390 bool _isTokenChar(int byte) { |
390 return byte > 31 && byte < 128 && _Const.SEPARATORS.indexOf(byte) == -1; | 391 return byte > 31 && byte < 128 && _SEPARATORS.indexOf(byte) == -1; |
391 } | 392 } |
392 | 393 |
393 int _toLowerCase(int byte) { | 394 int _toLowerCase(int byte) { |
394 final int aCode = "A".codeUnitAt(0); | 395 final int aCode = "A".codeUnitAt(0); |
395 final int zCode = "Z".codeUnitAt(0); | 396 final int zCode = "Z".codeUnitAt(0); |
396 final int delta = "a".codeUnitAt(0) - aCode; | 397 final int delta = "a".codeUnitAt(0) - aCode; |
397 return (aCode <= byte && byte <= zCode) ? byte + delta : byte; | 398 return (aCode <= byte && byte <= zCode) ? byte + delta : byte; |
398 } | 399 } |
399 | 400 |
400 void _expect(int val1, int val2) { | 401 void _expect(int val1, int val2) { |
401 if (val1 != val2) { | 402 if (val1 != val2) { |
402 throw new MimeMultipartException("Failed to parse multipart mime 1"); | 403 throw new MimeMultipartException("Failed to parse multipart mime 1"); |
403 } | 404 } |
404 } | 405 } |
405 | 406 |
406 void _expectWS(int byte) { | 407 void _expectWS(int byte) { |
407 if (byte != _CharCode.SP && byte != _CharCode.HT) { | 408 if (byte != _CharCode.SP && byte != _CharCode.HT) { |
408 throw new MimeMultipartException("Failed to parse multipart mime 2"); | 409 throw new MimeMultipartException("Failed to parse multipart mime 2"); |
409 } | 410 } |
410 } | 411 } |
411 } | 412 } |
412 | 413 |
413 | 414 |
414 class MimeMultipartException implements Exception { | 415 class MimeMultipartException implements Exception { |
| 416 final String message; |
| 417 |
415 const MimeMultipartException([String this.message = ""]); | 418 const MimeMultipartException([String this.message = ""]); |
| 419 |
416 String toString() => "MimeMultipartException: $message"; | 420 String toString() => "MimeMultipartException: $message"; |
417 final String message; | |
418 } | 421 } |
OLD | NEW |