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, such as a URL. | 8 * A parsed URI, such as a URL. |
9 * | 9 * |
10 * **See also:** | 10 * **See also:** |
(...skipping 1225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 bool isFile = (scheme == "file"); | 1236 bool isFile = (scheme == "file"); |
1237 bool ensureLeadingSlash = isFile || hasAuthority; | 1237 bool ensureLeadingSlash = isFile || hasAuthority; |
1238 if (path == null && pathSegments == null) return isFile ? "/" : ""; | 1238 if (path == null && pathSegments == null) return isFile ? "/" : ""; |
1239 if (path != null && pathSegments != null) { | 1239 if (path != null && pathSegments != null) { |
1240 throw new ArgumentError('Both path and pathSegments specified'); | 1240 throw new ArgumentError('Both path and pathSegments specified'); |
1241 } | 1241 } |
1242 var result; | 1242 var result; |
1243 if (path != null) { | 1243 if (path != null) { |
1244 result = _normalize(path, start, end, _pathCharOrSlashTable); | 1244 result = _normalize(path, start, end, _pathCharOrSlashTable); |
1245 } else { | 1245 } else { |
1246 result = pathSegments.map((s) => _uriEncode(_pathCharTable, s)).join("/"); | 1246 result = pathSegments.map((s) => |
| 1247 _uriEncode(_pathCharTable, s, UTF8, false)).join("/"); |
1247 } | 1248 } |
1248 if (result.isEmpty) { | 1249 if (result.isEmpty) { |
1249 if (isFile) return "/"; | 1250 if (isFile) return "/"; |
1250 } else if (ensureLeadingSlash && !result.startsWith('/')) { | 1251 } else if (ensureLeadingSlash && !result.startsWith('/')) { |
1251 result = "/" + result; | 1252 result = "/" + result; |
1252 } | 1253 } |
1253 result = _normalizePath(result, scheme, hasAuthority); | 1254 result = _normalizePath(result, scheme, hasAuthority); |
1254 return result; | 1255 return result; |
1255 } | 1256 } |
1256 | 1257 |
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1946 * string. | 1947 * string. |
1947 * | 1948 * |
1948 * For encoding the query part consider using | 1949 * For encoding the query part consider using |
1949 * [encodeQueryComponent]. | 1950 * [encodeQueryComponent]. |
1950 * | 1951 * |
1951 * To avoid the need for explicitly encoding use the [pathSegments] | 1952 * To avoid the need for explicitly encoding use the [pathSegments] |
1952 * and [queryParameters] optional named arguments when constructing | 1953 * and [queryParameters] optional named arguments when constructing |
1953 * a [Uri]. | 1954 * a [Uri]. |
1954 */ | 1955 */ |
1955 static String encodeComponent(String component) { | 1956 static String encodeComponent(String component) { |
1956 return _uriEncode(_unreserved2396Table, component); | 1957 return _uriEncode(_unreserved2396Table, component, UTF8, false); |
1957 } | 1958 } |
1958 | 1959 |
1959 /** | 1960 /** |
1960 * Encode the string [component] according to the HTML 4.01 rules | 1961 * Encode the string [component] according to the HTML 4.01 rules |
1961 * for encoding the posting of a HTML form as a query string | 1962 * for encoding the posting of a HTML form as a query string |
1962 * component. | 1963 * component. |
1963 * | 1964 * |
1964 * Encode the string [component] according to the HTML 4.01 rules | 1965 * Encode the string [component] according to the HTML 4.01 rules |
1965 * for encoding the posting of a HTML form as a query string | 1966 * for encoding the posting of a HTML form as a query string |
1966 * component. | 1967 * component. |
(...skipping 17 matching lines...) Expand all Loading... |
1984 * | 1985 * |
1985 * To avoid the need for explicitly encoding the query use the | 1986 * To avoid the need for explicitly encoding the query use the |
1986 * [queryParameters] optional named arguments when constructing a | 1987 * [queryParameters] optional named arguments when constructing a |
1987 * [Uri]. | 1988 * [Uri]. |
1988 * | 1989 * |
1989 * See http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 for more | 1990 * See http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 for more |
1990 * details. | 1991 * details. |
1991 */ | 1992 */ |
1992 static String encodeQueryComponent(String component, | 1993 static String encodeQueryComponent(String component, |
1993 {Encoding encoding: UTF8}) { | 1994 {Encoding encoding: UTF8}) { |
1994 return _uriEncode( | 1995 return _uriEncode(_unreservedTable, component, encoding, true); |
1995 _unreservedTable, component, encoding: encoding, spaceToPlus: true); | |
1996 } | 1996 } |
1997 | 1997 |
1998 /** | 1998 /** |
1999 * Decodes the percent-encoding in [encodedComponent]. | 1999 * Decodes the percent-encoding in [encodedComponent]. |
2000 * | 2000 * |
2001 * Note that decoding a URI component might change its meaning as | 2001 * Note that decoding a URI component might change its meaning as |
2002 * some of the decoded characters could be characters with are | 2002 * some of the decoded characters could be characters with are |
2003 * delimiters for a given URI componene type. Always split a URI | 2003 * delimiters for a given URI componene type. Always split a URI |
2004 * component using the delimiters for the component before decoding | 2004 * component using the delimiters for the component before decoding |
2005 * the individual parts. | 2005 * the individual parts. |
(...skipping 23 matching lines...) Expand all Loading... |
2029 /** | 2029 /** |
2030 * Encode the string [uri] using percent-encoding to make it | 2030 * Encode the string [uri] using percent-encoding to make it |
2031 * safe for literal use as a full URI. | 2031 * safe for literal use as a full URI. |
2032 * | 2032 * |
2033 * All characters except uppercase and lowercase letters, digits and | 2033 * All characters except uppercase and lowercase letters, digits and |
2034 * the characters `!#$&'()*+,-./:;=?@_~` are percent-encoded. This | 2034 * the characters `!#$&'()*+,-./:;=?@_~` are percent-encoded. This |
2035 * is the set of characters specified in in ECMA-262 version 5.1 for | 2035 * is the set of characters specified in in ECMA-262 version 5.1 for |
2036 * the encodeURI function . | 2036 * the encodeURI function . |
2037 */ | 2037 */ |
2038 static String encodeFull(String uri) { | 2038 static String encodeFull(String uri) { |
2039 return _uriEncode(_encodeFullTable, uri); | 2039 return _uriEncode(_encodeFullTable, uri, UTF8, false); |
2040 } | 2040 } |
2041 | 2041 |
2042 /** | 2042 /** |
2043 * Decodes the percent-encoding in [uri]. | 2043 * Decodes the percent-encoding in [uri]. |
2044 * | 2044 * |
2045 * Note that decoding a full URI might change its meaning as some of | 2045 * Note that decoding a full URI might change its meaning as some of |
2046 * the decoded characters could be reserved characters. In most | 2046 * the decoded characters could be reserved characters. In most |
2047 * cases an encoded URI should be parsed into components using | 2047 * cases an encoded URI should be parsed into components using |
2048 * [Uri.parse] before decoding the separate components. | 2048 * [Uri.parse] before decoding the separate components. |
2049 */ | 2049 */ |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2245 static const int _UPPER_CASE_F = 0x46; | 2245 static const int _UPPER_CASE_F = 0x46; |
2246 static const int _UPPER_CASE_Z = 0x5A; | 2246 static const int _UPPER_CASE_Z = 0x5A; |
2247 static const int _LEFT_BRACKET = 0x5B; | 2247 static const int _LEFT_BRACKET = 0x5B; |
2248 static const int _BACKSLASH = 0x5C; | 2248 static const int _BACKSLASH = 0x5C; |
2249 static const int _RIGHT_BRACKET = 0x5D; | 2249 static const int _RIGHT_BRACKET = 0x5D; |
2250 static const int _LOWER_CASE_A = 0x61; | 2250 static const int _LOWER_CASE_A = 0x61; |
2251 static const int _LOWER_CASE_F = 0x66; | 2251 static const int _LOWER_CASE_F = 0x66; |
2252 static const int _LOWER_CASE_Z = 0x7A; | 2252 static const int _LOWER_CASE_Z = 0x7A; |
2253 static const int _BAR = 0x7C; | 2253 static const int _BAR = 0x7C; |
2254 | 2254 |
2255 // Matches a String that _uriEncodes to itself regardless of the kind of | 2255 external static String _uriEncode(List<int> canonicalTable, |
2256 // component. This corresponds to [_unreservedTable], i.e. characters that | 2256 String text, |
2257 // are not encoded by any encoding table. | 2257 Encoding encoding, |
2258 static final RegExp _needsNoEncoding = new RegExp(r'^[\-\.0-9A-Z_a-z~]*$'); | 2258 bool spaceToPlus); |
2259 | |
2260 /** | |
2261 * This is the internal implementation of JavaScript's encodeURI function. | |
2262 * It encodes all characters in the string [text] except for those | |
2263 * that appear in [canonicalTable], and returns the escaped string. | |
2264 */ | |
2265 static String _uriEncode(List<int> canonicalTable, | |
2266 String text, | |
2267 {Encoding encoding: UTF8, | |
2268 bool spaceToPlus: false}) { | |
2269 if (_needsNoEncoding.hasMatch(text)) return text; | |
2270 | |
2271 byteToHex(byte, buffer) { | |
2272 const String hex = '0123456789ABCDEF'; | |
2273 buffer.writeCharCode(hex.codeUnitAt(byte >> 4)); | |
2274 buffer.writeCharCode(hex.codeUnitAt(byte & 0x0f)); | |
2275 } | |
2276 | |
2277 // Encode the string into bytes then generate an ASCII only string | |
2278 // by percent encoding selected bytes. | |
2279 StringBuffer result = new StringBuffer(); | |
2280 var bytes = encoding.encode(text); | |
2281 for (int i = 0; i < bytes.length; i++) { | |
2282 int byte = bytes[i]; | |
2283 if (byte < 128 && | |
2284 ((canonicalTable[byte >> 4] & (1 << (byte & 0x0f))) != 0)) { | |
2285 result.writeCharCode(byte); | |
2286 } else if (spaceToPlus && byte == _SPACE) { | |
2287 result.writeCharCode(_PLUS); | |
2288 } else { | |
2289 result.writeCharCode(_PERCENT); | |
2290 byteToHex(byte, result); | |
2291 } | |
2292 } | |
2293 return result.toString(); | |
2294 } | |
2295 | 2259 |
2296 /** | 2260 /** |
2297 * Convert a byte (2 character hex sequence) in string [s] starting | 2261 * Convert a byte (2 character hex sequence) in string [s] starting |
2298 * at position [pos] to its ordinal value | 2262 * at position [pos] to its ordinal value |
2299 */ | 2263 */ |
2300 static int _hexCharPairToByte(String s, int pos) { | 2264 static int _hexCharPairToByte(String s, int pos) { |
2301 int byte = 0; | 2265 int byte = 0; |
2302 for (int i = 0; i < 2; i++) { | 2266 for (int i = 0; i < 2; i++) { |
2303 var charCode = s.codeUnitAt(pos + i); | 2267 var charCode = s.codeUnitAt(pos + i); |
2304 if (0x30 <= charCode && charCode <= 0x39) { | 2268 if (0x30 <= charCode && charCode <= 0x39) { |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2612 0xafff, // 0x30 - 0x3f 1111111111110101 | 2576 0xafff, // 0x30 - 0x3f 1111111111110101 |
2613 // @ABCDEFGHIJKLMNO | 2577 // @ABCDEFGHIJKLMNO |
2614 0xffff, // 0x40 - 0x4f 1111111111111111 | 2578 0xffff, // 0x40 - 0x4f 1111111111111111 |
2615 // PQRSTUVWXYZ _ | 2579 // PQRSTUVWXYZ _ |
2616 0x87ff, // 0x50 - 0x5f 1111111111100001 | 2580 0x87ff, // 0x50 - 0x5f 1111111111100001 |
2617 // abcdefghijklmno | 2581 // abcdefghijklmno |
2618 0xfffe, // 0x60 - 0x6f 0111111111111111 | 2582 0xfffe, // 0x60 - 0x6f 0111111111111111 |
2619 // pqrstuvwxyz ~ | 2583 // pqrstuvwxyz ~ |
2620 0x47ff]; // 0x70 - 0x7f 1111111111100010 | 2584 0x47ff]; // 0x70 - 0x7f 1111111111100010 |
2621 } | 2585 } |
OLD | NEW |