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 http_server; | 5 part of http_server; |
6 | 6 |
7 | 7 |
8 class _HttpMultipartFormData extends Stream implements HttpMultipartFormData { | 8 class _HttpMultipartFormData extends Stream implements HttpMultipartFormData { |
9 final ContentType contentType; | 9 final ContentType contentType; |
10 final HeaderValue contentDisposition; | 10 final HeaderValue contentDisposition; |
11 final HeaderValue contentTransferEncoding; | 11 final HeaderValue contentTransferEncoding; |
12 | 12 |
13 final MimeMultipart _mimeMultipart; | 13 final MimeMultipart _mimeMultipart; |
14 | 14 |
15 bool _isText = false; | 15 bool _isText = false; |
16 | 16 |
17 Stream _stream; | 17 Stream _stream; |
18 | 18 |
19 _HttpMultipartFormData(ContentType this.contentType, | 19 _HttpMultipartFormData(ContentType this.contentType, |
20 HeaderValue this.contentDisposition, | 20 HeaderValue this.contentDisposition, |
21 HeaderValue this.contentTransferEncoding, | 21 HeaderValue this.contentTransferEncoding, |
22 MimeMultipart this._mimeMultipart) { | 22 MimeMultipart this._mimeMultipart, |
| 23 Encoding defaultEncoding) { |
23 _stream = _mimeMultipart; | 24 _stream = _mimeMultipart; |
24 if (contentTransferEncoding != null) { | 25 if (contentTransferEncoding != null) { |
25 // TODO(ajohnsen): Support BASE64, etc. | 26 // TODO(ajohnsen): Support BASE64, etc. |
26 throw new HttpException("Unsupported contentTransferEncoding: " | 27 throw new HttpException("Unsupported contentTransferEncoding: " |
27 "${contentTransferEncoding.value}"); | 28 "${contentTransferEncoding.value}"); |
28 } | 29 } |
29 | 30 |
30 if (contentType == null || | 31 if (contentType == null || |
31 contentType.primaryType == 'text' || | 32 contentType.primaryType == 'text' || |
32 contentType.mimeType == 'application/json') { | 33 contentType.mimeType == 'application/json') { |
33 _isText = true; | 34 _isText = true; |
34 StringBuffer buffer = new StringBuffer(); | 35 StringBuffer buffer = new StringBuffer(); |
35 Encoding encoding; | 36 Encoding encoding; |
36 if (contentType != null) { | 37 if (contentType != null) { |
37 encoding = Encoding.getByName(contentType.charset); | 38 encoding = Encoding.getByName(contentType.charset); |
38 } | 39 } |
39 if (encoding == null) encoding = LATIN1; | 40 if (encoding == null) encoding = defaultEncoding; |
40 _stream = _stream | 41 _stream = _stream |
41 .transform(encoding.decoder) | 42 .transform(encoding.decoder) |
42 .expand((data) { | 43 .expand((data) { |
43 buffer.write(data); | 44 buffer.write(data); |
44 var out = _decodeHttpEntityString(buffer.toString()); | 45 var out = _decodeHttpEntityString(buffer.toString()); |
45 if (out != null) { | 46 if (out != null) { |
46 buffer.clear(); | 47 buffer.clear(); |
47 return [out]; | 48 return [out]; |
48 } | 49 } |
49 return const []; | 50 return const []; |
50 }); | 51 }); |
51 } | 52 } |
52 } | 53 } |
53 | 54 |
54 bool get isText => _isText; | 55 bool get isText => _isText; |
55 bool get isBinary => !_isText; | 56 bool get isBinary => !_isText; |
56 | 57 |
57 static HttpMultipartFormData parse(MimeMultipart multipart) { | 58 static HttpMultipartFormData parse(MimeMultipart multipart, |
| 59 Encoding defaultEncoding) { |
58 var type; | 60 var type; |
59 var encoding; | 61 var encoding; |
60 var disposition; | 62 var disposition; |
61 var remaining = new Map<String, String>(); | 63 var remaining = new Map<String, String>(); |
62 for (String key in multipart.headers.keys) { | 64 for (String key in multipart.headers.keys) { |
63 switch (key) { | 65 switch (key) { |
64 case 'content-type': | 66 case 'content-type': |
65 type = ContentType.parse(multipart.headers[key]); | 67 type = ContentType.parse(multipart.headers[key]); |
66 break; | 68 break; |
67 | 69 |
68 case 'content-transfer-encoding': | 70 case 'content-transfer-encoding': |
69 encoding = HeaderValue.parse(multipart.headers[key]); | 71 encoding = HeaderValue.parse(multipart.headers[key]); |
70 break; | 72 break; |
71 | 73 |
72 case 'content-disposition': | 74 case 'content-disposition': |
73 disposition = HeaderValue.parse(multipart.headers[key]); | 75 disposition = HeaderValue.parse(multipart.headers[key]); |
74 break; | 76 break; |
75 | 77 |
76 default: | 78 default: |
77 remaining[key] = multipart.headers[key]; | 79 remaining[key] = multipart.headers[key]; |
78 break; | 80 break; |
79 } | 81 } |
80 } | 82 } |
81 if (disposition == null) { | 83 if (disposition == null) { |
82 throw new HttpException( | 84 throw new HttpException( |
83 "Mime Multipart doesn't contain a Content-Disposition header value"); | 85 "Mime Multipart doesn't contain a Content-Disposition header value"); |
84 } | 86 } |
85 return new _HttpMultipartFormData(type, disposition, encoding, multipart); | 87 return new _HttpMultipartFormData( |
| 88 type, disposition, encoding, multipart, defaultEncoding); |
86 } | 89 } |
87 | 90 |
88 StreamSubscription listen(void onData(data), | 91 StreamSubscription listen(void onData(data), |
89 {void onDone(), | 92 {void onDone(), |
90 void onError(error), | 93 void onError(error), |
91 bool cancelOnError}) { | 94 bool cancelOnError}) { |
92 return _stream.listen(onData, | 95 return _stream.listen(onData, |
93 onDone: onDone, | 96 onDone: onDone, |
94 onError: onError, | 97 onError: onError, |
95 cancelOnError: cancelOnError); | 98 cancelOnError: cancelOnError); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 while ((amp = input.indexOf('&', offset)) >= 0) { | 132 while ((amp = input.indexOf('&', offset)) >= 0) { |
130 buffer.write(input.substring(offset, amp)); | 133 buffer.write(input.substring(offset, amp)); |
131 int end = input.indexOf(';', amp); | 134 int end = input.indexOf(';', amp); |
132 parse(amp, end); | 135 parse(amp, end); |
133 offset = end + 1; | 136 offset = end + 1; |
134 } | 137 } |
135 buffer.write(input.substring(offset)); | 138 buffer.write(input.substring(offset)); |
136 return buffer.toString(); | 139 return buffer.toString(); |
137 } | 140 } |
138 } | 141 } |
OLD | NEW |