| 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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 return _host.substring(1, _host.length - 1); | 56 return _host.substring(1, _host.length - 1); |
| 57 } | 57 } |
| 58 return _host; | 58 return _host; |
| 59 } | 59 } |
| 60 | 60 |
| 61 /** | 61 /** |
| 62 * Returns the port part of the authority component. | 62 * Returns the port part of the authority component. |
| 63 * | 63 * |
| 64 * Returns 0 if there is no port in the authority component. | 64 * Returns 0 if there is no port in the authority component. |
| 65 */ | 65 */ |
| 66 int get port => _port; | 66 int get port { |
| 67 if (_port == 0) { |
| 68 if (scheme == "http") return 80; |
| 69 if (scheme == "https") return 443; |
| 70 } |
| 71 return _port; |
| 72 } |
| 67 | 73 |
| 68 /** | 74 /** |
| 69 * Returns the path component. | 75 * Returns the path component. |
| 70 * | 76 * |
| 71 * The returned path is encoded. To get direct access to the decoded | 77 * The returned path is encoded. To get direct access to the decoded |
| 72 * path use [pathSegments]. | 78 * path use [pathSegments]. |
| 73 * | 79 * |
| 74 * Returns the empty string if there is no path component. | 80 * Returns the empty string if there is no path component. |
| 75 */ | 81 */ |
| 76 String get path => _path; | 82 String get path => _path; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 100 * Cache the computed return value of [queryParameters]. | 106 * Cache the computed return value of [queryParameters]. |
| 101 */ | 107 */ |
| 102 Map<String, String> _queryParameters; | 108 Map<String, String> _queryParameters; |
| 103 | 109 |
| 104 /** | 110 /** |
| 105 * Creates a new URI object by parsing a URI string. | 111 * Creates a new URI object by parsing a URI string. |
| 106 */ | 112 */ |
| 107 static Uri parse(String uri) => new Uri._fromMatch(_splitRe.firstMatch(uri)); | 113 static Uri parse(String uri) => new Uri._fromMatch(_splitRe.firstMatch(uri)); |
| 108 | 114 |
| 109 Uri._fromMatch(Match m) : | 115 Uri._fromMatch(Match m) : |
| 110 this(scheme: _emptyIfNull(m[_COMPONENT_SCHEME]), | 116 this(scheme: _makeScheme(_emptyIfNull(m[_COMPONENT_SCHEME])), |
| 111 userInfo: _emptyIfNull(m[_COMPONENT_USER_INFO]), | 117 userInfo: _emptyIfNull(m[_COMPONENT_USER_INFO]), |
| 112 host: _eitherOf( | 118 host: _eitherOf( |
| 113 m[_COMPONENT_HOST], m[_COMPONENT_HOST_IPV6]), | 119 m[_COMPONENT_HOST], m[_COMPONENT_HOST_IPV6]), |
| 114 port: _parseIntOrZero(m[_COMPONENT_PORT]), | 120 port: _parseIntOrZero(m[_COMPONENT_PORT]), |
| 115 path: _emptyIfNull(m[_COMPONENT_PATH]), | 121 path: _emptyIfNull(m[_COMPONENT_PATH]), |
| 116 query: _emptyIfNull(m[_COMPONENT_QUERY_DATA]), | 122 query: _emptyIfNull(m[_COMPONENT_QUERY_DATA]), |
| 117 fragment: _emptyIfNull(m[_COMPONENT_FRAGMENT])); | 123 fragment: _emptyIfNull(m[_COMPONENT_FRAGMENT])); |
| 118 | 124 |
| 119 /** | 125 /** |
| 120 * Creates a new URI from its components. | 126 * Creates a new URI from its components. |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 | 528 |
| 523 bool isSchemeCharacter(int ch) { | 529 bool isSchemeCharacter(int ch) { |
| 524 return ch < 128 && ((_schemeTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); | 530 return ch < 128 && ((_schemeTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); |
| 525 } | 531 } |
| 526 | 532 |
| 527 if (scheme == null) return ""; | 533 if (scheme == null) return ""; |
| 528 bool allLowercase = true; | 534 bool allLowercase = true; |
| 529 int length = scheme.length; | 535 int length = scheme.length; |
| 530 for (int i = 0; i < length; i++) { | 536 for (int i = 0; i < length; i++) { |
| 531 int codeUnit = scheme.codeUnitAt(i); | 537 int codeUnit = scheme.codeUnitAt(i); |
| 538 if (i == 0 && !_isAlphabeticCharacter(codeUnit)) { |
| 539 // First code unit must be an alphabetic character. |
| 540 throw new ArgumentError('Illegal scheme: $scheme'); |
| 541 } |
| 532 if (!isSchemeLowerCharacter(codeUnit)) { | 542 if (!isSchemeLowerCharacter(codeUnit)) { |
| 533 if (isSchemeCharacter(codeUnit)) { | 543 if (isSchemeCharacter(codeUnit)) { |
| 534 allLowercase = false; | 544 allLowercase = false; |
| 535 } else { | 545 } else { |
| 536 throw new ArgumentError('Illegal scheme: $scheme'); | 546 throw new ArgumentError('Illegal scheme: $scheme'); |
| 537 } | 547 } |
| 538 } | 548 } |
| 539 } | 549 } |
| 540 | 550 |
| 541 return allLowercase ? scheme : scheme.toLowerCase(); | 551 return allLowercase ? scheme : scheme.toLowerCase(); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 703 static String _eitherOf(String val1, String val2) { | 713 static String _eitherOf(String val1, String val2) { |
| 704 if (val1 != null) return val1; | 714 if (val1 != null) return val1; |
| 705 if (val2 != null) return val2; | 715 if (val2 != null) return val2; |
| 706 return ''; | 716 return ''; |
| 707 } | 717 } |
| 708 | 718 |
| 709 // NOTE: This code was ported from: closure-library/closure/goog/uri/utils.js | 719 // NOTE: This code was ported from: closure-library/closure/goog/uri/utils.js |
| 710 static final RegExp _splitRe = new RegExp( | 720 static final RegExp _splitRe = new RegExp( |
| 711 '^' | 721 '^' |
| 712 '(?:' | 722 '(?:' |
| 713 '([^:/?#.]+)' // scheme - ignore special characters | 723 '([^:/?#]+)' // scheme - ignore special characters |
| 714 // used by other URL parts such as :, | 724 // used by other URL parts such as :, |
| 715 // ?, /, #, and . | 725 // ?, /, #, and . |
| 716 ':)?' | 726 ':)?' |
| 717 '(?://' | 727 '(?://' |
| 718 '(?:([^/?#]*)@)?' // userInfo | 728 '(?:([^/?#]*)@)?' // userInfo |
| 719 '(?:' | 729 '(?:' |
| 720 r'([\w\d\-\u0100-\uffff.%]*)' | 730 r'([\w\d\-\u0100-\uffff.%]*)' |
| 721 // host - restrict to letters, | 731 // host - restrict to letters, |
| 722 // digits, dashes, dots, percent | 732 // digits, dashes, dots, percent |
| 723 // escapes, and unicode characters. | 733 // escapes, and unicode characters. |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 868 * See: http://www.w3.org/TR/2011/WD-html5-20110405/origin-0.html#origin | 878 * See: http://www.w3.org/TR/2011/WD-html5-20110405/origin-0.html#origin |
| 869 */ | 879 */ |
| 870 String get origin { | 880 String get origin { |
| 871 if (scheme == "" || _host == null || _host == "") { | 881 if (scheme == "" || _host == null || _host == "") { |
| 872 throw new StateError("Cannot use origin without a scheme: $this"); | 882 throw new StateError("Cannot use origin without a scheme: $this"); |
| 873 } | 883 } |
| 874 if (scheme != "http" && scheme != "https") { | 884 if (scheme != "http" && scheme != "https") { |
| 875 throw new StateError( | 885 throw new StateError( |
| 876 "Origin is only applicable schemes http and https: $this"); | 886 "Origin is only applicable schemes http and https: $this"); |
| 877 } | 887 } |
| 878 if (port == 0) return "$scheme://$_host"; | 888 if (_port == 0) return "$scheme://$_host"; |
| 879 return "$scheme://$_host:$port"; | 889 return "$scheme://$_host:$_port"; |
| 880 } | 890 } |
| 881 | 891 |
| 882 /** | 892 /** |
| 883 * Returns the file path from a file URI. | 893 * Returns the file path from a file URI. |
| 884 * | 894 * |
| 885 * The returned path has either Windows or non-Windows | 895 * The returned path has either Windows or non-Windows |
| 886 * semantics. | 896 * semantics. |
| 887 * | 897 * |
| 888 * For non-Windows semantics the slash ("/") is used to separate | 898 * For non-Windows semantics the slash ("/") is used to separate |
| 889 * path segments. | 899 * path segments. |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1001 } | 1011 } |
| 1002 | 1012 |
| 1003 bool get _isPathAbsolute { | 1013 bool get _isPathAbsolute { |
| 1004 if (path == null || path.isEmpty) return false; | 1014 if (path == null || path.isEmpty) return false; |
| 1005 return path.startsWith('/'); | 1015 return path.startsWith('/'); |
| 1006 } | 1016 } |
| 1007 | 1017 |
| 1008 void _writeAuthority(StringSink ss) { | 1018 void _writeAuthority(StringSink ss) { |
| 1009 _addIfNonEmpty(ss, userInfo, userInfo, "@"); | 1019 _addIfNonEmpty(ss, userInfo, userInfo, "@"); |
| 1010 ss.write(_host == null ? "null" : _host); | 1020 ss.write(_host == null ? "null" : _host); |
| 1011 if (port != 0) { | 1021 if (_port != 0) { |
| 1012 ss.write(":"); | 1022 ss.write(":"); |
| 1013 ss.write(port.toString()); | 1023 ss.write(_port.toString()); |
| 1014 } | 1024 } |
| 1015 } | 1025 } |
| 1016 | 1026 |
| 1017 String toString() { | 1027 String toString() { |
| 1018 StringBuffer sb = new StringBuffer(); | 1028 StringBuffer sb = new StringBuffer(); |
| 1019 _addIfNonEmpty(sb, scheme, scheme, ':'); | 1029 _addIfNonEmpty(sb, scheme, scheme, ':'); |
| 1020 if (hasAuthority || (scheme == "file")) { | 1030 if (hasAuthority || (scheme == "file")) { |
| 1021 sb.write("//"); | 1031 sb.write("//"); |
| 1022 _writeAuthority(sb); | 1032 _writeAuthority(sb); |
| 1023 } | 1033 } |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1447 i += 2; | 1457 i += 2; |
| 1448 if (i == text.length) break; | 1458 if (i == text.length) break; |
| 1449 ch = text.codeUnitAt(i); | 1459 ch = text.codeUnitAt(i); |
| 1450 } | 1460 } |
| 1451 result.write(encoding.decode(codepoints)); | 1461 result.write(encoding.decode(codepoints)); |
| 1452 } | 1462 } |
| 1453 } | 1463 } |
| 1454 return result.toString(); | 1464 return result.toString(); |
| 1455 } | 1465 } |
| 1456 | 1466 |
| 1467 static bool _isAlphabeticCharacter(int codeUnit) |
| 1468 => (codeUnit >= _LOWER_CASE_A && codeUnit <= _LOWER_CASE_Z) || |
| 1469 (codeUnit >= _UPPER_CASE_A && codeUnit <= _UPPER_CASE_Z); |
| 1470 |
| 1457 // Tables of char-codes organized as a bit vector of 128 bits where | 1471 // Tables of char-codes organized as a bit vector of 128 bits where |
| 1458 // each bit indicate whether a character code on the 0-127 needs to | 1472 // each bit indicate whether a character code on the 0-127 needs to |
| 1459 // be escaped or not. | 1473 // be escaped or not. |
| 1460 | 1474 |
| 1461 // The unreserved characters of RFC 3986. | 1475 // The unreserved characters of RFC 3986. |
| 1462 static const _unreservedTable = const [ | 1476 static const _unreservedTable = const [ |
| 1463 // LSB MSB | 1477 // LSB MSB |
| 1464 // | | | 1478 // | | |
| 1465 0x0000, // 0x00 - 0x0f 0000000000000000 | 1479 0x0000, // 0x00 - 0x0f 0000000000000000 |
| 1466 0x0000, // 0x10 - 0x1f 0000000000000000 | 1480 0x0000, // 0x10 - 0x1f 0000000000000000 |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1641 void clear() { | 1655 void clear() { |
| 1642 throw new UnsupportedError("Cannot modify an unmodifiable map"); | 1656 throw new UnsupportedError("Cannot modify an unmodifiable map"); |
| 1643 } | 1657 } |
| 1644 void forEach(void f(K key, V value)) => _map.forEach(f); | 1658 void forEach(void f(K key, V value)) => _map.forEach(f); |
| 1645 Iterable<K> get keys => _map.keys; | 1659 Iterable<K> get keys => _map.keys; |
| 1646 Iterable<V> get values => _map.values; | 1660 Iterable<V> get values => _map.values; |
| 1647 int get length => _map.length; | 1661 int get length => _map.length; |
| 1648 bool get isEmpty => _map.isEmpty; | 1662 bool get isEmpty => _map.isEmpty; |
| 1649 bool get isNotEmpty => _map.isNotEmpty; | 1663 bool get isNotEmpty => _map.isNotEmpty; |
| 1650 } | 1664 } |
| OLD | NEW |