| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 /** |
| 6 * Javascript-like URI encode/decode functions. |
| 7 * The documentation here borrows heavily from the original Javascript |
| 8 * doumentation on MDN at: |
| 9 * https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects |
| 10 */ |
| 11 |
| 12 /** |
| 13 * A JavaScript-like URI encoder. Encodes Uniform Resource Identifier [uri] |
| 14 * by replacing each instance of certain characters by one, two, three, or four |
| 15 * escape sequences representing the UTF-8 encoding of the character (will |
| 16 * only be four escape sequences for characters composed of two "surrogate" |
| 17 * characters). This assumes that [uri] is a complete URI, so does not encode |
| 18 * reserved characters that have special meaning in the URI: [:#;,/?:@&=+\$:] |
| 19 * It returns the escaped URI. |
| 20 */ |
| 21 String encodeUri(String uri) { |
| 22 return _uriEncode( |
| 23 "-_.!~*'()#;,/?:@&=+\$0123456789" |
| 24 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", uri); |
| 25 } |
| 26 |
| 27 /** |
| 28 * An implementation of JavaScript's decodeURIComponent function. |
| 29 * Decodes a Uniform Resource Identifier [uri] previously created by |
| 30 * encodeURI or by a similar routine. It replaces each escape sequence |
| 31 * in [uri] with the character that it represents. It does not decode |
| 32 * escape sequences that could not have been introduced by encodeURI. |
| 33 * It returns the unescaped URI. |
| 34 */ |
| 35 String decodeUri(String uri) { |
| 36 return _uriDecode(uri); |
| 37 } |
| 38 |
| 39 /** |
| 40 * A javaScript-like URI component encoder, this encodes a URI |
| 41 * [component] by replacing each instance of certain characters by one, |
| 42 * two, three, or four escape sequences representing the UTF-8 encoding of |
| 43 * the character (will only be four escape sequences for characters composed |
| 44 * of two "surrogate" characters). |
| 45 * To avoid unexpected requests to the server, you should call |
| 46 * encodeURIComponent on any user-entered parameters that will be passed as |
| 47 * part of a URI. For example, a user could type "Thyme &time=again" for a |
| 48 * variable comment. Not using encodeURIComponent on this variable will give |
| 49 * comment=Thyme%20&time=again. Note that the ampersand and the equal sign |
| 50 * mark a new key and value pair. So instead of having a POST comment key |
| 51 * equal to "Thyme &time=again", you have two POST keys, one equal to "Thyme " |
| 52 * and another (time) equal to again. |
| 53 * It returns the escaped string. |
| 54 */ |
| 55 String encodeUriComponent(String component) { |
| 56 return _uriEncode( |
| 57 "-_.!~*'()0123456789" |
| 58 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", component); |
| 59 } |
| 60 |
| 61 /** |
| 62 * An implementation of JavaScript's decodeURIComponent function. |
| 63 * Decodes a Uniform Resource Identifier (URI) [component] previously |
| 64 * created by encodeURIComponent or by a similar routine. |
| 65 * It returns the unescaped string. |
| 66 */ |
| 67 String decodeUriComponent(String encodedComponent) { |
| 68 return _uriDecode(encodedComponent); |
| 69 } |
| 70 |
| 71 /** |
| 72 * This is the internal implementation of JavaScript's encodeURI function. |
| 73 * It encodes all characters in the string [text] except for those |
| 74 * that appear in [canonical], and returns the escaped string. |
| 75 */ |
| 76 String _uriEncode(String canonical, String text) { |
| 77 final String hex = '0123456789ABCDEF'; |
| 78 var byteToHex = (int v) => '%${hex[v >> 4]}${hex[v&0xf]}'; |
| 79 StringBuffer result = new StringBuffer(); |
| 80 for (int i = 0; i < text.length; i++) { |
| 81 if (canonical.indexOf(text[i]) >= 0) { |
| 82 result.add(text[i]); |
| 83 } else { |
| 84 int ch = text.charCodeAt(i); |
| 85 if (ch >= 0xD800 && ch < 0xDC00) { |
| 86 // Low surrogate. We expect a next char high surrogate. |
| 87 ++i; |
| 88 int nextCh = text.length == i ? 0 : text.charCodeAt(i); |
| 89 if (nextCh >= 0xDC00 && nextCh < 0xE000) { |
| 90 // convert the pair to a U+10000 codepoint |
| 91 ch = 0x10000 + ((ch-0xD800) << 10) + (nextCh - 0xDC00); |
| 92 } else { |
| 93 throw new IllegalArgumentException('Malformed URI'); |
| 94 } |
| 95 } |
| 96 for (int codepoint in codepointsToUtf8([ch])) { |
| 97 result.add(byteToHex(codepoint)); |
| 98 } |
| 99 } |
| 100 } |
| 101 return result.toString(); |
| 102 } |
| 103 |
| 104 /** |
| 105 * Convert a byte (2 character hex sequence) in string [s] starting |
| 106 * at position [pos] to its ordinal value |
| 107 */ |
| 108 |
| 109 int _hexCharPairToByte(String s, int pos) { |
| 110 // An alternative to calling parseInt twice would be to take a |
| 111 // two character substring and call it once, but that may be less |
| 112 // efficient. |
| 113 int d1 = Math.parseInt("0x${s[pos]}"); |
| 114 int d2 = Math.parseInt("0x${s[pos+1]}"); |
| 115 return d1 * 16 + d2; |
| 116 } |
| 117 |
| 118 /** |
| 119 * A JavaScript-like decodeURI function. It unescapes the string [text] and |
| 120 * returns the unescaped string. |
| 121 */ |
| 122 String _uriDecode(String text) { |
| 123 StringBuffer result = new StringBuffer(); |
| 124 List<int> codepoints = new List<int>(); |
| 125 for (int i = 0; i < text.length;) { |
| 126 String ch = text[i]; |
| 127 if (ch != '%') { |
| 128 result.add(ch); |
| 129 i++; |
| 130 } else { |
| 131 codepoints.clear(); |
| 132 while (ch == '%') { |
| 133 if (++i > text.length - 2) { |
| 134 throw new IllegalArgumentException('Truncated URI'); |
| 135 } |
| 136 codepoints.add(_hexCharPairToByte(text, i)); |
| 137 i += 2; |
| 138 if (i == text.length) |
| 139 break; |
| 140 ch = text[i]; |
| 141 } |
| 142 result.add(decodeUtf8(codepoints)); |
| 143 } |
| 144 } |
| 145 return result.toString(); |
| 146 } |
| 147 |
| OLD | NEW |