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 dart.core; | 5 part of dart.core; |
6 | 6 |
7 /** | 7 /** |
8 * A parsed URI, as specified by RFC-3986, http://tools.ietf.org/html/rfc3986. | 8 * A parsed URI, as specified by RFC-3986, http://tools.ietf.org/html/rfc3986. |
9 */ | 9 */ |
10 class Uri { | 10 class Uri { |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
146 * [queryParameters]. When [query] is used the provided string is | 146 * [queryParameters]. When [query] is used the provided string is |
147 * expected to be fully percent-encoded and is used in its literal | 147 * expected to be fully percent-encoded and is used in its literal |
148 * form. When [queryParameters] is used the query is built from the | 148 * form. When [queryParameters] is used the query is built from the |
149 * provided map. Each key and value in the map is percent-encoded | 149 * provided map. Each key and value in the map is percent-encoded |
150 * and joined using equal and ampersand characters. The | 150 * and joined using equal and ampersand characters. The |
151 * percent-encoding of the keys and values encodes all characters | 151 * percent-encoding of the keys and values encodes all characters |
152 * except for the unreserved characters. | 152 * except for the unreserved characters. |
153 * | 153 * |
154 * The fragment component is set through [fragment]. | 154 * The fragment component is set through [fragment]. |
155 */ | 155 */ |
156 Uri({scheme, | 156 Uri({String scheme, |
157 this.userInfo: "", | 157 this.userInfo: "", |
158 this.host: "", | 158 String host: "", |
159 port: 0, | 159 port: 0, |
160 String path, | 160 String path, |
161 Iterable<String> pathSegments, | 161 Iterable<String> pathSegments, |
162 String query, | 162 String query, |
163 Map<String, String> queryParameters, | 163 Map<String, String> queryParameters, |
164 fragment: ""}) : | 164 fragment: ""}) : |
165 scheme = _makeScheme(scheme), | 165 scheme = _makeScheme(scheme), |
166 host = _makeHost(host), | |
166 query = _makeQuery(query, queryParameters), | 167 query = _makeQuery(query, queryParameters), |
167 fragment = _makeFragment(fragment) { | 168 fragment = _makeFragment(fragment) { |
168 // Perform scheme specific normalization. | 169 // Perform scheme specific normalization. |
169 if (scheme == "http" && port == 80) { | 170 if (scheme == "http" && port == 80) { |
170 _port = 0; | 171 _port = 0; |
171 } else if (scheme == "https" && port == 443) { | 172 } else if (scheme == "https" && port == 443) { |
172 _port = 0; | 173 _port = 0; |
173 } else { | 174 } else { |
174 _port = port; | 175 _port = port; |
175 } | 176 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
230 // Split off the user info. | 231 // Split off the user info. |
231 bool hasUserInfo = false; | 232 bool hasUserInfo = false; |
232 for (int i = 0; i < authority.length; i++) { | 233 for (int i = 0; i < authority.length; i++) { |
233 if (authority.codeUnitAt(i) == _AT_SIGN) { | 234 if (authority.codeUnitAt(i) == _AT_SIGN) { |
234 hasUserInfo = true; | 235 hasUserInfo = true; |
235 userInfo = authority.substring(0, i); | 236 userInfo = authority.substring(0, i); |
236 hostStart = i + 1; | 237 hostStart = i + 1; |
237 break; | 238 break; |
238 } | 239 } |
239 } | 240 } |
241 var hostEnd = null; | |
floitsch
2013/09/09 13:32:21
That's how I would write it.
var hostEnd = hostSt
Anders Johnsen
2013/09/10 11:13:23
Done.
| |
242 var portStart = hostStart; | |
243 if (authority.codeUnitAt(hostStart) == _LEFT_BRACKET) { | |
244 // IPv6 host. | |
245 for (int i = hostStart; i < authority.length; i++) { | |
246 if (authority.codeUnitAt(i) == _RIGHT_BRACKET) { | |
247 hostEnd = i; | |
248 break; | |
249 } | |
250 } | |
251 if (hostEnd == null) { | |
252 throw new FormatException("Invalid IPv6 host entry."); | |
253 } | |
254 hostEnd++; | |
255 portStart = hostEnd; | |
256 } | |
240 // Split host and port. | 257 // Split host and port. |
241 bool hasPort = false; | 258 bool hasPort = false; |
242 for (int i = hostStart; i < authority.length; i++) { | 259 for (int i = portStart; i < authority.length; i++) { |
243 if (authority.codeUnitAt(i) == _COLON) { | 260 if (authority.codeUnitAt(i) == _COLON) { |
244 hasPort = true; | 261 hasPort = true; |
floitsch
2013/09/09 13:32:21
you set hasPort to true, but if the host is empty
Anders Johnsen
2013/09/10 11:13:23
Done.
| |
245 host = authority.substring(hostStart, i); | 262 if (hostEnd == null) hostEnd = i; |
263 host = authority.substring(hostStart, hostEnd); | |
246 if (!host.isEmpty) { | 264 if (!host.isEmpty) { |
floitsch
2013/09/09 13:32:21
if you just check hostStart != hostEnd you don't n
Anders Johnsen
2013/09/10 11:13:23
Done.
| |
247 var portString = authority.substring(i + 1); | 265 var portString = authority.substring(i + 1); |
248 if (portString.isNotEmpty) port = int.parse(portString); | 266 if (portString.isNotEmpty) port = int.parse(portString); |
floitsch
2013/09/09 13:32:21
is this intended behavior? (an authority with ":"
Anders Johnsen
2013/09/10 11:13:23
Done.
| |
249 } | 267 } |
250 break; | 268 break; |
251 } | 269 } |
252 } | 270 } |
253 if (!hasPort) { | 271 if (!hasPort) { |
254 host = hasUserInfo ? authority.substring(hostStart) : authority; | 272 host = authority.substring(hostStart, hostEnd); |
255 } | 273 } |
256 | 274 |
257 return new Uri(scheme: scheme, | 275 return new Uri(scheme: scheme, |
258 userInfo: userInfo, | 276 userInfo: userInfo, |
259 host: host, | 277 host: host, |
260 port: port, | 278 port: port, |
261 pathSegments: unencodedPath.split("/"), | 279 pathSegments: unencodedPath.split("/"), |
262 queryParameters: queryParameters); | 280 queryParameters: queryParameters); |
263 } | 281 } |
264 | 282 |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
467 * The returned map is unmodifiable and will throw [UnsupportedError] on any | 485 * The returned map is unmodifiable and will throw [UnsupportedError] on any |
468 * calls that would mutate it. | 486 * calls that would mutate it. |
469 */ | 487 */ |
470 Map<String, String> get queryParameters { | 488 Map<String, String> get queryParameters { |
471 if (_queryParameters == null) { | 489 if (_queryParameters == null) { |
472 _queryParameters = new _UnmodifiableMap(splitQueryString(query)); | 490 _queryParameters = new _UnmodifiableMap(splitQueryString(query)); |
473 } | 491 } |
474 return _queryParameters; | 492 return _queryParameters; |
475 } | 493 } |
476 | 494 |
495 static String _makeHost(String host) { | |
496 if (host.isEmpty) return host; | |
497 if (host.codeUnitAt(0) == _LEFT_BRACKET) return host; | |
floitsch
2013/09/09 13:32:21
I would prefer a more sophisticated host-parser:
d
Anders Johnsen
2013/09/10 11:13:23
Done.
| |
498 for (int i = 0; i < host.length; i++) { | |
499 if (host.codeUnitAt(i) == _COLON) { | |
500 var buffer = new StringBuffer(); | |
501 buffer.writeCharCode(_LEFT_BRACKET); | |
502 buffer.write(host); | |
503 if (host.codeUnitAt(host.length - 1) != _RIGHT_BRACKET) { | |
504 buffer.writeCharCode(_RIGHT_BRACKET); | |
505 } | |
506 return buffer.toString(); | |
507 } | |
508 } | |
509 return host; | |
510 } | |
511 | |
477 static String _makeScheme(String scheme) { | 512 static String _makeScheme(String scheme) { |
478 bool isSchemeLowerCharacter(int ch) { | 513 bool isSchemeLowerCharacter(int ch) { |
479 return ch < 128 && | 514 return ch < 128 && |
480 ((_schemeLowerTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); | 515 ((_schemeLowerTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); |
481 } | 516 } |
482 | 517 |
483 bool isSchemeCharacter(int ch) { | 518 bool isSchemeCharacter(int ch) { |
484 return ch < 128 && ((_schemeTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); | 519 return ch < 128 && ((_schemeTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); |
485 } | 520 } |
486 | 521 |
(...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1157 static const int _ZERO = 0x30; | 1192 static const int _ZERO = 0x30; |
1158 static const int _NINE = 0x39; | 1193 static const int _NINE = 0x39; |
1159 static const int _COLON = 0x3A; | 1194 static const int _COLON = 0x3A; |
1160 static const int _LESS = 0x3C; | 1195 static const int _LESS = 0x3C; |
1161 static const int _GREATER = 0x3E; | 1196 static const int _GREATER = 0x3E; |
1162 static const int _QUESTION = 0x3F; | 1197 static const int _QUESTION = 0x3F; |
1163 static const int _AT_SIGN = 0x40; | 1198 static const int _AT_SIGN = 0x40; |
1164 static const int _UPPER_CASE_A = 0x41; | 1199 static const int _UPPER_CASE_A = 0x41; |
1165 static const int _UPPER_CASE_F = 0x46; | 1200 static const int _UPPER_CASE_F = 0x46; |
1166 static const int _UPPER_CASE_Z = 0x5A; | 1201 static const int _UPPER_CASE_Z = 0x5A; |
1202 static const int _LEFT_BRACKET = 0x5B; | |
1167 static const int _BACKSLASH = 0x5C; | 1203 static const int _BACKSLASH = 0x5C; |
1204 static const int _RIGHT_BRACKET = 0x5D; | |
1168 static const int _LOWER_CASE_A = 0x61; | 1205 static const int _LOWER_CASE_A = 0x61; |
1169 static const int _LOWER_CASE_F = 0x66; | 1206 static const int _LOWER_CASE_F = 0x66; |
1170 static const int _LOWER_CASE_Z = 0x7A; | 1207 static const int _LOWER_CASE_Z = 0x7A; |
1171 static const int _BAR = 0x7C; | 1208 static const int _BAR = 0x7C; |
1172 | 1209 |
1173 /** | 1210 /** |
1174 * This is the internal implementation of JavaScript's encodeURI function. | 1211 * This is the internal implementation of JavaScript's encodeURI function. |
1175 * It encodes all characters in the string [text] except for those | 1212 * It encodes all characters in the string [text] except for those |
1176 * that appear in [canonicalTable], and returns the escaped string. | 1213 * that appear in [canonicalTable], and returns the escaped string. |
1177 */ | 1214 */ |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1465 void clear() { | 1502 void clear() { |
1466 throw new UnsupportedError("Cannot modify an unmodifiable map"); | 1503 throw new UnsupportedError("Cannot modify an unmodifiable map"); |
1467 } | 1504 } |
1468 void forEach(void f(K key, V value)) => _map.forEach(f); | 1505 void forEach(void f(K key, V value)) => _map.forEach(f); |
1469 Iterable<K> get keys => _map.keys; | 1506 Iterable<K> get keys => _map.keys; |
1470 Iterable<V> get values => _map.values; | 1507 Iterable<V> get values => _map.values; |
1471 int get length => _map.length; | 1508 int get length => _map.length; |
1472 bool get isEmpty => _map.isEmpty; | 1509 bool get isEmpty => _map.isEmpty; |
1473 bool get isNotEmpty => _map.isNotEmpty; | 1510 bool get isNotEmpty => _map.isNotEmpty; |
1474 } | 1511 } |
OLD | NEW |