| Index: sdk/lib/core/uri.dart
|
| diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
|
| index ba65fa691d6ebf4123991a0f0aa59d3f123d0b37..bdaf08639b200222f667b76c3a888f3678393f99 100644
|
| --- a/sdk/lib/core/uri.dart
|
| +++ b/sdk/lib/core/uri.dart
|
| @@ -172,14 +172,17 @@ class Uri {
|
| // query = *( pchar / "/" / "?" )
|
| //
|
| // fragment = *( pchar / "/" / "?" )
|
| + bool isRegName(int ch) {
|
| + return ch < 128 && ((_regNameTable[ch >> 4] & (1 << (ch & 0x0f))) != 0);
|
| + }
|
|
|
| int ipV6Address(int index) {
|
| // IPv6. Skip to ']'.
|
| - int endIndex = uri.indexOf(']', index);
|
| - if (endIndex < 0) {
|
| - _fail(uri, index - 1, "Unmatched [ in host name");
|
| + index = uri.indexOf(']', index);
|
| + if (index == -1) {
|
| + throw new FormatException("Bad end of IPv6 host");
|
| }
|
| - return endIndex + 1;
|
| + return index + 1;
|
| }
|
|
|
| int length = uri.length;
|
| @@ -190,22 +193,18 @@ class Uri {
|
| if (length == 0) {
|
| return new Uri();
|
| }
|
| - // Whether to allow a colon in the first path segment.
|
| - bool allowColon = false;
|
|
|
| - if (_isAlphabeticCharacter(uri.codeUnitAt(0))) {
|
| + if (uri.codeUnitAt(0) != _SLASH) {
|
| // Can be scheme.
|
| while (index < length) {
|
| - // Look for ':' to end the scheme.
|
| - // If found continue from after ':'.
|
| - // If not (end reached or invalid scheme char found) back up one char,
|
| - // and continue as a path.
|
| + // Look for ':'. If found, continue from the post of ':'. If not (end
|
| + // reached or invalid scheme char found) back up one char, and continue
|
| + // to path.
|
| // Note that scheme-chars is contained in path-chars.
|
| int codeUnit = uri.codeUnitAt(index++);
|
| if (!_isSchemeCharacter(codeUnit)) {
|
| if (codeUnit == _COLON) {
|
| schemeEndIndex = index;
|
| - allowColon = true; // Scheme detected, allow colon in path.
|
| } else {
|
| // Back up one char, since we met an invalid scheme char.
|
| index--;
|
| @@ -224,12 +223,11 @@ class Uri {
|
| uri.codeUnitAt(authorityEndIndex) == _SLASH &&
|
| uri.codeUnitAt(authorityEndIndex + 1) == _SLASH) {
|
| // Skip '//'.
|
| - allowColon = true; // First slash seen, allow colon in path.
|
| authorityEndIndex += 2;
|
| // It can both be host and userInfo.
|
| while (authorityEndIndex < length) {
|
| int codeUnit = uri.codeUnitAt(authorityEndIndex++);
|
| - if (!_isRegNameChar(codeUnit)) {
|
| + if (!isRegName(codeUnit)) {
|
| if (codeUnit == _LEFT_BRACKET) {
|
| authorityEndIndex = ipV6Address(authorityEndIndex);
|
| } else if (portIndex == -1 && codeUnit == _COLON) {
|
| @@ -237,21 +235,18 @@ class Uri {
|
| portIndex = authorityEndIndex;
|
| } else if (codeUnit == _AT_SIGN || codeUnit == _COLON) {
|
| // Second time ':' or first '@'. Must be userInfo.
|
| - if (codeUnit == _AT_SIGN) {
|
| - userInfoEndIndex = authorityEndIndex - 1;
|
| - } else {
|
| - userInfoEndIndex = uri.indexOf('@', authorityEndIndex);
|
| - // @ Not found after something that can only be userinfo.
|
| - if (userInfoEndIndex < 0) {
|
| - _fail(uri, uri.length, "No '@' after userinfo");
|
| - }
|
| + userInfoEndIndex = uri.indexOf('@', authorityEndIndex - 1);
|
| + // Not found. Must be path then.
|
| + if (userInfoEndIndex == -1) {
|
| + authorityEndIndex = index;
|
| + break;
|
| }
|
| portIndex = -1;
|
| authorityEndIndex = userInfoEndIndex + 1;
|
| // Now it can only be host:port.
|
| while (authorityEndIndex < length) {
|
| int codeUnit = uri.codeUnitAt(authorityEndIndex++);
|
| - if (!_isRegNameChar(codeUnit)) {
|
| + if (!isRegName(codeUnit)) {
|
| if (codeUnit == _LEFT_BRACKET) {
|
| authorityEndIndex = ipV6Address(authorityEndIndex);
|
| } else if (codeUnit == _COLON) {
|
| @@ -272,35 +267,12 @@ class Uri {
|
| }
|
| }
|
| }
|
| - if (authorityEndIndex < length) {
|
| - // path-abempty - either absolute or empty, so we need a slash if
|
| - // there is a path.
|
| - int codeUnit = uri.codeUnitAt(authorityEndIndex);
|
| - if (codeUnit != _SLASH &&
|
| - codeUnit != _QUESTION &&
|
| - codeUnit != _NUMBER_SIGN) {
|
| - _fail(uri, authorityEndIndex, "Invalid character in authority");
|
| - }
|
| - }
|
| } else {
|
| authorityEndIndex = schemeEndIndex;
|
| }
|
|
|
| // At path now.
|
| int pathEndIndex = authorityEndIndex;
|
| - if (!allowColon) {
|
| - while (pathEndIndex < length) {
|
| - int codeUnit = uri.codeUnitAt(pathEndIndex++);
|
| - if (codeUnit == _QUESTION || codeUnit == _NUMBER_SIGN) {
|
| - pathEndIndex--;
|
| - break;
|
| - }
|
| - if (codeUnit == _SLASH) break;
|
| - if (codeUnit == _COLON) {
|
| - _fail(uri, pathEndIndex - 1, "Colon in initial path segment");
|
| - }
|
| - }
|
| - }
|
| while (pathEndIndex < length) {
|
| int codeUnit = uri.codeUnitAt(pathEndIndex++);
|
| if (codeUnit == _QUESTION || codeUnit == _NUMBER_SIGN) {
|
| @@ -368,38 +340,6 @@ class Uri {
|
| fragment: fragment);
|
| }
|
|
|
| - // Report a parse failure.
|
| - static void _fail(String uri, int index, String message) {
|
| - // TODO(lrn): Consider adding this to FormatException.
|
| - if (index == uri.length) {
|
| - message += " at end of input.";
|
| - } else {
|
| - message += " at position $index.\n";
|
| - // Pick a slice of uri containing index and, if
|
| - // necessary, truncate the ends to ensure the entire
|
| - // slice fits on one line.
|
| - int min = 0;
|
| - int max = uri.length;
|
| - String pre = "";
|
| - String post = "";
|
| - if (uri.length > 78) {
|
| - min = index - 10;
|
| - if (min < 0) min = 0;
|
| - int max = min + 72;
|
| - if (max > uri.length) {
|
| - max = uri.length;
|
| - min = max - 72;
|
| - }
|
| - if (min != 0) pre = "...";
|
| - if (max != uri.length) post = "...";
|
| - }
|
| - // Combine message, slice and a caret pointing to the error index.
|
| - message = "$message$pre${uri.substring(min, max)}$post\n"
|
| - "${' ' * (pre.length + index - min)}^";
|
| - }
|
| - throw new FormatException(message);
|
| - }
|
| -
|
| /**
|
| * Creates a new URI from its components.
|
| *
|
| @@ -447,7 +387,7 @@ class Uri {
|
| * The fragment component is set through [fragment].
|
| */
|
| Uri({String scheme,
|
| - String userInfo: "",
|
| + this.userInfo: "",
|
| String host: "",
|
| port: 0,
|
| String path,
|
| @@ -456,7 +396,6 @@ class Uri {
|
| Map<String, String> queryParameters,
|
| fragment: ""}) :
|
| scheme = _makeScheme(scheme),
|
| - userInfo = _makeUserInfo(userInfo),
|
| _host = _makeHost(host),
|
| query = _makeQuery(query, queryParameters),
|
| fragment = _makeFragment(fragment) {
|
| @@ -828,7 +767,6 @@ class Uri {
|
|
|
| static String _makeHost(String host) {
|
| if (host == null || host.isEmpty) return host;
|
| - // Host is an IPv6 address if it starts with '[' or contains a colon.
|
| if (host.codeUnitAt(0) == _LEFT_BRACKET) {
|
| if (host.codeUnitAt(host.length - 1) != _RIGHT_BRACKET) {
|
| throw new FormatException('Missing end `]` to match `[` in host');
|
| @@ -836,108 +774,40 @@ class Uri {
|
| parseIPv6Address(host.substring(1, host.length - 1));
|
| return host;
|
| }
|
| - // TODO(lrn): skip if too short to be a valid IPv6 address.
|
| for (int i = 0; i < host.length; i++) {
|
| if (host.codeUnitAt(i) == _COLON) {
|
| parseIPv6Address(host);
|
| return '[$host]';
|
| }
|
| }
|
| - return _normalizeRegName(host);
|
| + return host;
|
| }
|
|
|
| - static bool _isRegNameChar(int char) {
|
| - return char < 127 && (_regNameTable[char >> 4] & (1 << (char & 0xf))) != 0;
|
| - }
|
| -
|
| - /**
|
| - * Validates and does case- and percent-encoding normalization.
|
| - *
|
| - * The [host] must be an RFC3986 "reg-name". It is converted
|
| - * to lower case, and percent escapes are converted to either
|
| - * lower case unreserved characters or upper case escapes.
|
| - */
|
| - static String _normalizeRegName(String host) {
|
| - StringBuffer buffer;
|
| - int sectionStart = 0;
|
| - int index = 0;
|
| - // Whether all characters between sectionStart and index are normalized,
|
| - bool isNormalized = true;
|
| -
|
| - while (index < host.length) {
|
| - int char = host.codeUnitAt(index);
|
| - if (char == _PERCENT) {
|
| - // The _regNameTable contains "%", so we check that first.
|
| - String replacement = _normalizeEscape(host, index, true);
|
| - if (replacement == null && isNormalized) {
|
| - index += 3;
|
| - continue;
|
| - }
|
| - if (buffer == null) buffer = new StringBuffer();
|
| - String slice = host.substring(sectionStart, index);
|
| - if (!isNormalized) slice = slice.toLowerCase();
|
| - buffer.write(slice);
|
| - if (replacement == null) replacement = host.substring(index, index + 3);
|
| - buffer.write(replacement);
|
| - index += 3;
|
| - sectionStart = index;
|
| - isNormalized = true;
|
| - } else if (_isRegNameChar(char)) {
|
| - if (isNormalized && _UPPER_CASE_A <= char && _UPPER_CASE_Z >= char) {
|
| - // Put initial slice in buffer and continue in non-normalized mode
|
| - if (buffer == null) buffer = new StringBuffer();
|
| - if (sectionStart < index) {
|
| - buffer.write(host.substring(sectionStart, index));
|
| - sectionStart = index;
|
| - }
|
| - isNormalized = false;
|
| - }
|
| - index++;
|
| - } else {
|
| - _fail(host, index, "Invalid character");
|
| - }
|
| - }
|
| - if (buffer == null) return host;
|
| - if (sectionStart < host.length) {
|
| - String slice = host.substring(sectionStart);
|
| - if (!isNormalized) slice = slice.toLowerCase();
|
| - buffer.write(slice);
|
| - }
|
| - return buffer.toString();
|
| - }
|
| -
|
| - /**
|
| - * Validates scheme characters and does case-normalization.
|
| - *
|
| - * Schemes are converted to lower case. They cannot contain escapes.
|
| - */
|
| static String _makeScheme(String scheme) {
|
| - if (scheme == null || scheme.isEmpty) return "";
|
| - int char = scheme.codeUnitAt(0);
|
| - if (!_isAlphabeticCharacter(char)) {
|
| - _fail(scheme, 0, "Non-alphabetic character starting scheme");
|
| + bool isSchemeLowerCharacter(int ch) {
|
| + return ch < 128 &&
|
| + ((_schemeLowerTable[ch >> 4] & (1 << (ch & 0x0f))) != 0);
|
| }
|
| - bool allLowercase = char > _LOWER_CASE_A;
|
| - for (int i = 0; i < scheme.length; i++) {
|
| +
|
| + if (scheme == null) return "";
|
| + bool allLowercase = true;
|
| + int length = scheme.length;
|
| + for (int i = 0; i < length; i++) {
|
| int codeUnit = scheme.codeUnitAt(i);
|
| - if (!_isSchemeCharacter(codeUnit)) {
|
| - _fail(scheme, i, "Illegal scheme character");
|
| + if (i == 0 && !_isAlphabeticCharacter(codeUnit)) {
|
| + // First code unit must be an alphabetic character.
|
| + throw new ArgumentError('Illegal scheme: $scheme');
|
| }
|
| - if (_LOWER_CASE_A <= codeUnit && _LOWER_CASE_Z >= codeUnit) {
|
| - allLowercase = false;
|
| + if (!isSchemeLowerCharacter(codeUnit)) {
|
| + if (_isSchemeCharacter(codeUnit)) {
|
| + allLowercase = false;
|
| + } else {
|
| + throw new ArgumentError('Illegal scheme: $scheme');
|
| + }
|
| }
|
| }
|
| - return allLowercase ? scheme : scheme.toLowerCase();
|
| - }
|
| -
|
| - static String _makeUserInfo(String userInfo) {
|
| - if (userInfo == null) return "null";
|
| - return _normalize(userInfo, _userinfoTable);
|
| - }
|
|
|
| - static bool _isPathCharacter(int ch) {
|
| - return ch < 128 && ((_pathCharTable[ch >> 4] & (1 << (ch & 0x0f))) != 0) ||
|
| - ch == _SLASH;
|
| + return allLowercase ? scheme : scheme.toLowerCase();
|
| }
|
|
|
| String _makePath(String path, Iterable<String> pathSegments) {
|
| @@ -945,10 +815,9 @@ class Uri {
|
| if (path != null && pathSegments != null) {
|
| throw new ArgumentError('Both path and pathSegments specified');
|
| }
|
| - // TODO(lrn): Do path normalization to remove /./ and /../ segments.
|
| var result;
|
| if (path != null) {
|
| - result = _normalize(path, _pathCharOrSlashTable);
|
| + result = _normalize(path);
|
| } else {
|
| result = pathSegments.map((s) => _uriEncode(_pathCharTable, s)).join("/");
|
| }
|
| @@ -964,7 +833,7 @@ class Uri {
|
| if (query != null && queryParameters != null) {
|
| throw new ArgumentError('Both query and queryParameters specified');
|
| }
|
| - if (query != null) return _normalize(query, _queryCharTable);
|
| + if (query != null) return _normalize(query);
|
|
|
| var result = new StringBuffer();
|
| var first = true;
|
| @@ -984,112 +853,122 @@ class Uri {
|
|
|
| static String _makeFragment(String fragment) {
|
| if (fragment == null) return "";
|
| - return _normalize(fragment, _queryCharTable);
|
| + return _normalize(fragment);
|
| }
|
|
|
| - static bool _isLowerCaseHexDigit(int digit) {
|
| - return _LOWER_CASE_A <= digit && digit <= _LOWER_CASE_F;
|
| - }
|
| + static String _normalize(String component) {
|
| + int index = component.indexOf('%');
|
| + if (index < 0) return component;
|
|
|
| - /** Returns whether char is a hex digit. */
|
| - static bool _isHexDigit(int char) {
|
| - if (_NINE >= char) return _ZERO <= char;
|
| - char |= 0x20;
|
| - return _LOWER_CASE_A <= char && _LOWER_CASE_F >= char;
|
| - }
|
| + bool isNormalizedHexDigit(int digit) {
|
| + return (_ZERO <= digit && digit <= _NINE) ||
|
| + (_UPPER_CASE_A <= digit && digit <= _UPPER_CASE_F);
|
| + }
|
|
|
| - /** Returns value of char as hex digit. */
|
| - static int _hexValue(int digit) {
|
| - assert(_isHexDigit(digit));
|
| - if (_NINE >= digit) return digit - _ZERO;
|
| - return (digit | 0x20) - (_LOWER_CASE_A - 10);
|
| - }
|
| + bool isLowerCaseHexDigit(int digit) {
|
| + return _LOWER_CASE_A <= digit && digit <= _LOWER_CASE_F;
|
| + }
|
|
|
| - /**
|
| - * Performs RFC 3986 Percent-Encoding Normalization.
|
| - *
|
| - * Returns a replacement string that should be replace the original escape.
|
| - * Returns null if no replacement is necessary because the escape is
|
| - * not for an unreserved character and is already non-lower-case.
|
| - *
|
| - * If [lowerCase] is true, a single character returned is always lower case,
|
| - */
|
| - static String _normalizeEscape(String source, int index, bool lowerCase) {
|
| - assert(source.codeUnitAt(index) == _PERCENT);
|
| - if (index + 2 >= source.length) {
|
| - _fail(source, index, "Unterminated percent escape");
|
| - }
|
| - int firstDigit = source.codeUnitAt(index + 1);
|
| - int secondDigit = source.codeUnitAt(index + 2);
|
| - if (!_isHexDigit(firstDigit) || !_isHexDigit(secondDigit)) {
|
| - _fail(source, index, "Invalid escape");
|
| - }
|
| - int value = _hexValue(firstDigit) * 16 + _hexValue(secondDigit);
|
| - if (_isUnreservedChar(value)) {
|
| - if (lowerCase && _UPPER_CASE_A <= value && _UPPER_CASE_Z >= value) {
|
| - value |= 0x20;
|
| + bool isUnreserved(int ch) {
|
| + return ch < 128 &&
|
| + ((_unreservedTable[ch >> 4] & (1 << (ch & 0x0f))) != 0);
|
| + }
|
| +
|
| + int normalizeHexDigit(int index) {
|
| + var codeUnit = component.codeUnitAt(index);
|
| + if (isLowerCaseHexDigit(codeUnit)) {
|
| + return codeUnit - 0x20;
|
| + } else if (!isNormalizedHexDigit(codeUnit)) {
|
| + throw new ArgumentError("Invalid URI component: $component");
|
| + } else {
|
| + return codeUnit;
|
| }
|
| - return new String.fromCharCode(value);
|
| }
|
| - if (firstDigit >= _LOWER_CASE_A || secondDigit >= _LOWER_CASE_A) {
|
| - // Either digit is lower case.
|
| - return source.substring(index, index + 3).toUpperCase();
|
| +
|
| + int decodeHexDigitPair(int index) {
|
| + int byte = 0;
|
| + for (int i = 0; i < 2; i++) {
|
| + var codeUnit = component.codeUnitAt(index + i);
|
| + if (_ZERO <= codeUnit && codeUnit <= _NINE) {
|
| + byte = byte * 16 + codeUnit - _ZERO;
|
| + } else {
|
| + // Check ranges A-F (0x41-0x46) and a-f (0x61-0x66).
|
| + codeUnit |= 0x20;
|
| + if (_LOWER_CASE_A <= codeUnit &&
|
| + codeUnit <= _LOWER_CASE_F) {
|
| + byte = byte * 16 + codeUnit - _LOWER_CASE_A + 10;
|
| + } else {
|
| + throw new ArgumentError(
|
| + "Invalid percent-encoding in URI component: $component");
|
| + }
|
| + }
|
| + }
|
| + return byte;
|
| }
|
| - return null;
|
| - }
|
|
|
| - static bool _isUnreservedChar(int ch) {
|
| - return ch < 127 &&
|
| - ((_unreservedTable[ch >> 4] & (1 << (ch & 0x0f))) != 0);
|
| - }
|
| + // Start building the normalized component string.
|
| + StringBuffer result;
|
| + int length = component.length;
|
| + int prevIndex = 0;
|
|
|
| + // Copy a part of the component string to the result.
|
| + void fillResult() {
|
| + if (result == null) {
|
| + assert(prevIndex == 0);
|
| + result = new StringBuffer(component.substring(prevIndex, index));
|
| + } else {
|
| + result.write(component.substring(prevIndex, index));
|
| + }
|
| + }
|
|
|
| - /**
|
| - * Runs through component checking that each character is valid and
|
| - * normalize percent escapes.
|
| - *
|
| - * Uses [charTable] to check if a non-`%` character is allowed.
|
| - * Each `%` character must be followed by two hex digits.
|
| - * If the hex-digits are lower case letters, they are converted to
|
| - * upper case.
|
| - */
|
| - static String _normalize(String component, List<int> charTable) {
|
| - StringBuffer buffer;
|
| - int sectionStart = 0;
|
| - int index = 0;
|
| - // Loop while characters are valid and escapes correct and upper-case.
|
| - while (index < component.length) {
|
| - int char = component.codeUnitAt(index);
|
| - if (char < 127 && (charTable[char >> 4] & (1 << (char & 0x0f))) != 0) {
|
| - index++;
|
| - } else if (char == _PERCENT) {
|
| - String replacement = _normalizeEscape(component, index, false);
|
| - if (replacement == null) {
|
| - // _normalizeEscape returns null if no replacement necessary.
|
| - index += 3;
|
| - continue;
|
| + while (index < length) {
|
| + // Normalize percent-encoding to uppercase and don't encode
|
| + // unreserved characters.
|
| + assert(component.codeUnitAt(index) == _PERCENT);
|
| + if (length < index + 2) {
|
| + throw new ArgumentError(
|
| + "Invalid percent-encoding in URI component: $component");
|
| + }
|
| +
|
| + var codeUnit1 = component.codeUnitAt(index + 1);
|
| + var codeUnit2 = component.codeUnitAt(index + 2);
|
| + var decodedCodeUnit = decodeHexDigitPair(index + 1);
|
| + if (isNormalizedHexDigit(codeUnit1) &&
|
| + isNormalizedHexDigit(codeUnit2) &&
|
| + !isUnreserved(decodedCodeUnit)) {
|
| + index += 3;
|
| + } else {
|
| + fillResult();
|
| + if (isUnreserved(decodedCodeUnit)) {
|
| + result.writeCharCode(decodedCodeUnit);
|
| } else {
|
| - if (buffer == null) buffer = new StringBuffer();
|
| - buffer.write(component.substring(sectionStart, index));
|
| - buffer.write(replacement);
|
| - index += 3;
|
| - sectionStart = index;
|
| + result.write("%");
|
| + result.writeCharCode(normalizeHexDigit(index + 1));
|
| + result.writeCharCode(normalizeHexDigit(index + 2));
|
| }
|
| + index += 3;
|
| + prevIndex = index;
|
| + }
|
| + int next = component.indexOf('%', index);
|
| + if (next >= index) {
|
| + index = next;
|
| } else {
|
| - _fail(component, index, "Invalid character");
|
| + index = length;
|
| }
|
| }
|
| - if (buffer == null) return component;
|
| - if (sectionStart < component.length) {
|
| - buffer.write(component.substring(sectionStart));
|
| - }
|
| - return buffer.toString();
|
| + if (result == null) return component;
|
| +
|
| + if (result != null && prevIndex != index) fillResult();
|
| + assert(index == length);
|
| +
|
| + return result.toString();
|
| }
|
|
|
| static bool _isSchemeCharacter(int ch) {
|
| return ch < 128 && ((_schemeTable[ch >> 4] & (1 << (ch & 0x0f))) != 0);
|
| }
|
|
|
| +
|
| /**
|
| * Returns whether the URI is absolute.
|
| */
|
| @@ -1716,7 +1595,7 @@ class Uri {
|
| String text,
|
| {Encoding encoding: UTF8,
|
| bool spaceToPlus: false}) {
|
| - void byteToHex(byte, buffer) {
|
| + byteToHex(byte, buffer) {
|
| const String hex = '0123456789ABCDEF';
|
| buffer.writeCharCode(hex.codeUnitAt(byte >> 4));
|
| buffer.writeCharCode(hex.codeUnitAt(byte & 0x0f));
|
| @@ -1728,18 +1607,15 @@ class Uri {
|
| var bytes = encoding.encode(text);
|
| for (int i = 0; i < bytes.length; i++) {
|
| int byte = bytes[i];
|
| - if (byte < 128) {
|
| - if ((canonicalTable[byte >> 4] & (1 << (byte & 0x0f))) != 0) {
|
| - result.writeCharCode(byte);
|
| - continue;
|
| - }
|
| - if (spaceToPlus && byte == _SPACE) {
|
| - result.writeCharCode(_PLUS);
|
| - continue;
|
| - }
|
| + if (byte < 128 &&
|
| + ((canonicalTable[byte >> 4] & (1 << (byte & 0x0f))) != 0)) {
|
| + result.writeCharCode(byte);
|
| + } else if (spaceToPlus && byte == _SPACE) {
|
| + result.writeCharCode(_PLUS);
|
| + } else {
|
| + result.writeCharCode(_PERCENT);
|
| + byteToHex(byte, result);
|
| }
|
| - result.writeCharCode(_PERCENT);
|
| - byteToHex(byte, result);
|
| }
|
| return result.toString();
|
| }
|
| @@ -1965,27 +1841,6 @@ class Uri {
|
| // pqrstuvwxyz ~
|
| 0x47ff]; // 0x70 - 0x7f 1111111111100010
|
|
|
| - // Characters allowed in the userinfo as of RFC 3986.
|
| - // RFC 3986 Apendix A
|
| - // userinfo = *( unreserved / pct-encoded / sub-delims / ':')
|
| - static const _userinfoTable = const [
|
| - // LSB MSB
|
| - // | |
|
| - 0x0000, // 0x00 - 0x0f 0000000000000000
|
| - 0x0000, // 0x10 - 0x1f 0000000000000000
|
| - // ! $ &'()*+,-.
|
| - 0x7fd2, // 0x20 - 0x2f 0100101111111110
|
| - // 0123456789:; =
|
| - 0x2fff, // 0x30 - 0x3f 1111111111110100
|
| - // ABCDEFGHIJKLMNO
|
| - 0xfffe, // 0x40 - 0x4f 0111111111111111
|
| - // PQRSTUVWXYZ _
|
| - 0x87ff, // 0x50 - 0x5f 1111111111100001
|
| - // abcdefghijklmno
|
| - 0xfffe, // 0x60 - 0x6f 0111111111111111
|
| - // pqrstuvwxyz ~
|
| - 0x47ff]; // 0x70 - 0x7f 1111111111100010
|
| -
|
| // Characters allowed in the path as of RFC 3986.
|
| // RFC 3986 section 3.3.
|
| // pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
| @@ -2007,26 +1862,6 @@ class Uri {
|
| // pqrstuvwxyz ~
|
| 0x47ff]; // 0x70 - 0x7f 1111111111100010
|
|
|
| - // Characters allowed in the path as of RFC 3986.
|
| - // RFC 3986 section 3.3 *and* slash.
|
| - static const _pathCharOrSlashTable = const [
|
| - // LSB MSB
|
| - // | |
|
| - 0x0000, // 0x00 - 0x0f 0000000000000000
|
| - 0x0000, // 0x10 - 0x1f 0000000000000000
|
| - // ! $ &'()*+,-./
|
| - 0xffd2, // 0x20 - 0x2f 0100101111111111
|
| - // 0123456789:; =
|
| - 0x2fff, // 0x30 - 0x3f 1111111111110100
|
| - // @ABCDEFGHIJKLMNO
|
| - 0xffff, // 0x40 - 0x4f 1111111111111111
|
| - // PQRSTUVWXYZ _
|
| - 0x87ff, // 0x50 - 0x5f 1111111111100001
|
| - // abcdefghijklmno
|
| - 0xfffe, // 0x60 - 0x6f 0111111111111111
|
| - // pqrstuvwxyz ~
|
| - 0x47ff]; // 0x70 - 0x7f 1111111111100010
|
| -
|
| // Characters allowed in the query as of RFC 3986.
|
| // RFC 3986 section 3.4.
|
| // query = *( pchar / "/" / "?" )
|
|
|