| Index: sdk/lib/uri/uri.dart
|
| diff --git a/sdk/lib/uri/uri.dart b/sdk/lib/uri/uri.dart
|
| index 640ce3d0c7a32798ef2d019c322825be88896cdd..5cfa60ed0e3d3dd8caf93f97e0498f8763d18f40 100644
|
| --- a/sdk/lib/uri/uri.dart
|
| +++ b/sdk/lib/uri/uri.dart
|
| @@ -12,8 +12,13 @@ part 'helpers.dart';
|
|
|
| /**
|
| * A parsed URI, inspired by Closure's [URI][] class. Implements [RFC-3986][].
|
| - * [uri]: http://closure-library.googlecode.com/svn/docs/class_goog_Uri.html
|
| + * The domain component can either be a hostname, a IPv4 address or an IPv6
|
| + * address, contained in '[' and ']', following [RFC-2732][]. If the domain
|
| + * component contains a ':', the String returned from [toString] will have
|
| + * '[' and ']' around the domain part.
|
| + * [URI]: http://closure-library.googlecode.com/svn/docs/class_goog_Uri.html
|
| * [RFC-3986]: http://tools.ietf.org/html/rfc3986#section-4.3)
|
| + * [RFC-2732]: http://www.ietf.org/rfc/rfc2732.txt
|
| */
|
| class Uri {
|
| final String scheme;
|
| @@ -24,17 +29,13 @@ class Uri {
|
| final String query;
|
| final String fragment;
|
|
|
| - /**
|
| - * Deprecated. Please use [parse] instead.
|
| - */
|
| - Uri.fromString(String uri) : this._fromMatch(_splitRe.firstMatch(uri));
|
| -
|
| static Uri parse(String uri) => new Uri._fromMatch(_splitRe.firstMatch(uri));
|
|
|
| Uri._fromMatch(Match m) :
|
| this.fromComponents(scheme: _emptyIfNull(m[_COMPONENT_SCHEME]),
|
| userInfo: _emptyIfNull(m[_COMPONENT_USER_INFO]),
|
| - domain: _emptyIfNull(m[_COMPONENT_DOMAIN]),
|
| + domain: _eitherOf(
|
| + m[_COMPONENT_DOMAIN], m[_COMPONENT_DOMAIN_IPV6]),
|
| port: _parseIntOrZero(m[_COMPONENT_PORT]),
|
| path: _emptyIfNull(m[_COMPONENT_PATH]),
|
| query: _emptyIfNull(m[_COMPONENT_QUERY_DATA]),
|
| @@ -48,7 +49,7 @@ class Uri {
|
| this.query: "",
|
| this.fragment: ""});
|
|
|
| - Uri(String uri) : this.fromString(uri);
|
| + factory Uri(String uri) => parse(uri);
|
|
|
| static String _emptyIfNull(String val) => val != null ? val : '';
|
|
|
| @@ -60,6 +61,12 @@ class Uri {
|
| }
|
| }
|
|
|
| + static String _eitherOf(String val1, String val2) {
|
| + if (val1 != null) return val1;
|
| + if (val2 != null) return val2;
|
| + return '';
|
| + }
|
| +
|
| // NOTE: This code was ported from: closure-library/closure/goog/uri/utils.js
|
| static final RegExp _splitRe = new RegExp(
|
| '^'
|
| @@ -70,24 +77,31 @@ class Uri {
|
| ':)?'
|
| '(?://'
|
| '(?:([^/?#]*)@)?' // userInfo
|
| - '([\\w\\d\\-\\u0100-\\uffff.%]*)'
|
| + '(?:'
|
| + r'([\w\d\-\u0100-\uffff.%]*)'
|
| // domain - restrict to letters,
|
| // digits, dashes, dots, percent
|
| // escapes, and unicode characters.
|
| + '|'
|
| + // TODO(ajohnsen): Only allow a max number of parts?
|
| + r'\[([A-Fa-f0-9:.]*)\])'
|
| + // IPv6 domain - restrict to hex,
|
| + // dot and colon.
|
| '(?::([0-9]+))?' // port
|
| ')?'
|
| - '([^?#]+)?' // path
|
| - '(?:\\?([^#]*))?' // query
|
| + r'([^?#[]+)?' // path
|
| + r'(?:\?([^#]*))?' // query
|
| '(?:#(.*))?' // fragment
|
| - '\$');
|
| + r'$');
|
|
|
| static const _COMPONENT_SCHEME = 1;
|
| static const _COMPONENT_USER_INFO = 2;
|
| static const _COMPONENT_DOMAIN = 3;
|
| - static const _COMPONENT_PORT = 4;
|
| - static const _COMPONENT_PATH = 5;
|
| - static const _COMPONENT_QUERY_DATA = 6;
|
| - static const _COMPONENT_FRAGMENT = 7;
|
| + static const _COMPONENT_DOMAIN_IPV6 = 4;
|
| + static const _COMPONENT_PORT = 5;
|
| + static const _COMPONENT_PATH = 6;
|
| + static const _COMPONENT_QUERY_DATA = 7;
|
| + static const _COMPONENT_FRAGMENT = 8;
|
|
|
| /**
|
| * Returns `true` if the URI is absolute.
|
| @@ -222,7 +236,8 @@ class Uri {
|
| if (hasAuthority || (scheme == "file")) {
|
| sb.write("//");
|
| _addIfNonEmpty(sb, userInfo, userInfo, "@");
|
| - sb.write(domain == null ? "null" : domain);
|
| + sb.write(domain == null ? "null" :
|
| + domain.contains(':') ? '[$domain]' : domain);
|
| if (port != 0) {
|
| sb.write(":");
|
| sb.write(port.toString());
|
|
|