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 751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
762 * the individual parts. | 762 * the individual parts. |
763 * | 763 * |
764 * For handling the [path] and [query] components consider using | 764 * For handling the [path] and [query] components consider using |
765 * [pathSegments] and [queryParameters] to get the separated and | 765 * [pathSegments] and [queryParameters] to get the separated and |
766 * decoded component. | 766 * decoded component. |
767 */ | 767 */ |
768 static String decodeComponent(String encodedComponent) { | 768 static String decodeComponent(String encodedComponent) { |
769 return _uriDecode(encodedComponent); | 769 return _uriDecode(encodedComponent); |
770 } | 770 } |
771 | 771 |
772 static String decodeQueryComponent(String encodedComponent) { | 772 /** |
773 return _uriDecode(encodedComponent, plusToSpace: true); | 773 * Decodes the percent-encoding in [encodedComponent], converting |
| 774 * pluses to spaces. |
| 775 * |
| 776 * It will create a byte-list of the decoded characters, and then use |
| 777 * [decode] to decode the byte-list to a String. Default is a UTF_8 decoder. |
| 778 */ |
| 779 static String decodeQueryComponent( |
| 780 String encodedComponent, |
| 781 {String decode(List<int> bytes): decodeUtf8}) { |
| 782 return _uriDecode(encodedComponent, plusToSpace: true, decode: decode); |
774 } | 783 } |
775 | 784 |
776 /** | 785 /** |
777 * Encode the string [uri] using percent-encoding to make it | 786 * Encode the string [uri] using percent-encoding to make it |
778 * safe for literal use as a full URI. | 787 * safe for literal use as a full URI. |
779 * | 788 * |
780 * All characters except uppercase and lowercase letters, digits and | 789 * All characters except uppercase and lowercase letters, digits and |
781 * the characters `!#$&'()*+,-./:;=?@_~` are percent-encoded. This | 790 * the characters `!#$&'()*+,-./:;=?@_~` are percent-encoded. This |
782 * is the set of characters specified in in ECMA-262 version 5.1 for | 791 * is the set of characters specified in in ECMA-262 version 5.1 for |
783 * the encodeURI function . | 792 * the encodeURI function . |
(...skipping 18 matching lines...) Expand all Loading... |
802 * Returns the [query] split into a map according to the rules | 811 * Returns the [query] split into a map according to the rules |
803 * specified for FORM post in the | 812 * specified for FORM post in the |
804 * [HTML 4.01 specification section 17.13.4] | 813 * [HTML 4.01 specification section 17.13.4] |
805 * (http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4 | 814 * (http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4 |
806 * "HTML 4.01 section 17.13.4"). Each key and value in the returned | 815 * "HTML 4.01 section 17.13.4"). Each key and value in the returned |
807 * map has been decoded. If the [query] | 816 * map has been decoded. If the [query] |
808 * is the empty string an empty map is returned. | 817 * is the empty string an empty map is returned. |
809 * | 818 * |
810 * Keys in the query string that have no value are mapped to the | 819 * Keys in the query string that have no value are mapped to the |
811 * empty string. | 820 * empty string. |
| 821 * |
| 822 * Each query component will be decoded using [decode]. Default is a UTF_8 |
| 823 * decoder. |
812 */ | 824 */ |
813 static Map<String, String> splitQueryString(String query) { | 825 static Map<String, String> splitQueryString( |
| 826 String query, |
| 827 {String decode(List<int> bytes): decodeUtf8}) { |
814 return query.split("&").fold({}, (map, element) { | 828 return query.split("&").fold({}, (map, element) { |
815 int index = element.indexOf("="); | 829 int index = element.indexOf("="); |
816 if (index == -1) { | 830 if (index == -1) { |
817 if (element != "") map[decodeQueryComponent(element)] = ""; | 831 if (element != "") map[decodeQueryComponent(element)] = ""; |
818 } else if (index != 0) { | 832 } else if (index != 0) { |
819 var key = element.substring(0, index); | 833 var key = element.substring(0, index); |
820 var value = element.substring(index + 1); | 834 var value = element.substring(index + 1); |
821 map[Uri.decodeQueryComponent(key)] = decodeQueryComponent(value); | 835 map[Uri.decodeQueryComponent(key, decode: decode)] = |
| 836 decodeQueryComponent(value, decode: decode); |
822 } | 837 } |
823 return map; | 838 return map; |
824 }); | 839 }); |
825 } | 840 } |
826 | 841 |
827 // Frequently used character codes. | 842 // Frequently used character codes. |
828 static const int _PERCENT = 0x25; | 843 static const int _PERCENT = 0x25; |
829 static const int _PLUS = 0x2B; | 844 static const int _PLUS = 0x2B; |
830 static const int _SLASH = 0x2F; | 845 static const int _SLASH = 0x2F; |
831 static const int _ZERO = 0x30; | 846 static const int _ZERO = 0x30; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 byte = byte * 16 + charCode - 0x57; | 909 byte = byte * 16 + charCode - 0x57; |
895 } else { | 910 } else { |
896 throw new ArgumentError("Invalid URL encoding"); | 911 throw new ArgumentError("Invalid URL encoding"); |
897 } | 912 } |
898 } | 913 } |
899 } | 914 } |
900 return byte; | 915 return byte; |
901 } | 916 } |
902 | 917 |
903 /** | 918 /** |
904 * A JavaScript-like decodeURI function. It unescapes the string [text] and | 919 * Uri-decode a percent-encoded string. |
905 * returns the unescaped string. | 920 * |
| 921 * It unescapes the string [text] and returns the unescaped string. |
| 922 * |
| 923 * This function is similar to the JavaScript-function `decodeURI`. |
| 924 * |
| 925 * If [plusToSpace] is `true`, plus characters will be converted to spaces. |
| 926 * |
| 927 * The decoder will create a byte-list of the percent-encoded parts, and then |
| 928 * decode the byte-list using [decode]. Default is a UTF_8 decoder. |
906 */ | 929 */ |
907 static String _uriDecode(String text, {bool plusToSpace: false}) { | 930 static String _uriDecode(String text, |
| 931 {bool plusToSpace: false, |
| 932 String decode(List<int> bytes): decodeUtf8}) { |
908 StringBuffer result = new StringBuffer(); | 933 StringBuffer result = new StringBuffer(); |
909 List<int> codepoints = new List<int>(); | 934 List<int> codepoints = new List<int>(); |
910 for (int i = 0; i < text.length;) { | 935 for (int i = 0; i < text.length;) { |
911 int ch = text.codeUnitAt(i); | 936 int ch = text.codeUnitAt(i); |
912 if (ch != _PERCENT) { | 937 if (ch != _PERCENT) { |
913 if (plusToSpace && ch == _PLUS) { | 938 if (plusToSpace && ch == _PLUS) { |
914 result.write(" "); | 939 result.write(" "); |
915 } else { | 940 } else { |
916 result.writeCharCode(ch); | 941 result.writeCharCode(ch); |
917 } | 942 } |
918 i++; | 943 i++; |
919 } else { | 944 } else { |
920 codepoints.clear(); | 945 codepoints.clear(); |
921 while (ch == _PERCENT) { | 946 while (ch == _PERCENT) { |
922 if (++i > text.length - 2) { | 947 if (++i > text.length - 2) { |
923 throw new ArgumentError('Truncated URI'); | 948 throw new ArgumentError('Truncated URI'); |
924 } | 949 } |
925 codepoints.add(_hexCharPairToByte(text, i)); | 950 codepoints.add(_hexCharPairToByte(text, i)); |
926 i += 2; | 951 i += 2; |
927 if (i == text.length) break; | 952 if (i == text.length) break; |
928 ch = text.codeUnitAt(i); | 953 ch = text.codeUnitAt(i); |
929 } | 954 } |
930 result.write(decodeUtf8(codepoints)); | 955 result.write(decode(codepoints)); |
931 } | 956 } |
932 } | 957 } |
933 return result.toString(); | 958 return result.toString(); |
934 } | 959 } |
935 | 960 |
936 // Tables of char-codes organized as a bit vector of 128 bits where | 961 // Tables of char-codes organized as a bit vector of 128 bits where |
937 // each bit indicate whether a character code on the 0-127 needs to | 962 // each bit indicate whether a character code on the 0-127 needs to |
938 // be escaped or not. | 963 // be escaped or not. |
939 | 964 |
940 // The unreserved characters of RFC 3986. | 965 // The unreserved characters of RFC 3986. |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1120 void clear() { | 1145 void clear() { |
1121 throw new UnsupportedError("Cannot modify an unmodifiable map"); | 1146 throw new UnsupportedError("Cannot modify an unmodifiable map"); |
1122 } | 1147 } |
1123 void forEach(void f(K key, V value)) => _map.forEach(f); | 1148 void forEach(void f(K key, V value)) => _map.forEach(f); |
1124 Iterable<K> get keys => _map.keys; | 1149 Iterable<K> get keys => _map.keys; |
1125 Iterable<V> get values => _map.values; | 1150 Iterable<V> get values => _map.values; |
1126 int get length => _map.length; | 1151 int get length => _map.length; |
1127 bool get isEmpty => _map.isEmpty; | 1152 bool get isEmpty => _map.isEmpty; |
1128 bool get isNotEmpty => _map.isNotEmpty; | 1153 bool get isNotEmpty => _map.isNotEmpty; |
1129 } | 1154 } |
OLD | NEW |