Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(291)

Side by Side Diff: sdk/lib/core/uri.dart

Issue 94733003: Add encodimg argument to Uri.encodeQueryString (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review commetns Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sdk/lib/core/core.dart ('k') | tests/corelib/uri_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 663 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 if (result == null) { 674 if (result == null) {
675 assert(prevIndex == 0); 675 assert(prevIndex == 0);
676 result = new StringBuffer(component.substring(prevIndex, index)); 676 result = new StringBuffer(component.substring(prevIndex, index));
677 } else { 677 } else {
678 result.write(component.substring(prevIndex, index)); 678 result.write(component.substring(prevIndex, index));
679 } 679 }
680 } 680 }
681 681
682 while (index < length) { 682 while (index < length) {
683 683
684 // Normalize percent encoding to uppercase and don't encode 684 // Normalize percent-encoding to uppercase and don't encode
685 // unreserved characters. 685 // unreserved characters.
686 if (component.codeUnitAt(index) == _PERCENT) { 686 if (component.codeUnitAt(index) == _PERCENT) {
687 if (length < index + 2) { 687 if (length < index + 2) {
688 throw new ArgumentError( 688 throw new ArgumentError(
689 "Invalid percent-encoding in URI component: $component"); 689 "Invalid percent-encoding in URI component: $component");
690 } 690 }
691 691
692 var codeUnit1 = component.codeUnitAt(index + 1); 692 var codeUnit1 = component.codeUnitAt(index + 1);
693 var codeUnit2 = component.codeUnitAt(index + 2); 693 var codeUnit2 = component.codeUnitAt(index + 2);
694 var decodedCodeUnit = decodeHexDigitPair(index + 1); 694 var decodedCodeUnit = decodeHexDigitPair(index + 1);
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 */ 1107 */
1108 static String encodeComponent(String component) { 1108 static String encodeComponent(String component) {
1109 return _uriEncode(_unreserved2396Table, component); 1109 return _uriEncode(_unreserved2396Table, component);
1110 } 1110 }
1111 1111
1112 /** 1112 /**
1113 * Encode the string [component] according to the HTML 4.01 rules 1113 * Encode the string [component] according to the HTML 4.01 rules
1114 * for encoding the posting of a HTML form as a query string 1114 * for encoding the posting of a HTML form as a query string
1115 * component. 1115 * component.
1116 * 1116 *
1117 * Spaces will be replaced with plus and all characters except for 1117 * Encode the string [component] according to the HTML 4.01 rules
1118 * uppercase and lowercase letters, decimal digits and the 1118 * for encoding the posting of a HTML form as a query string
1119 * characters `-._~`. Note that the set of characters encoded is a 1119 * component.
1120 * superset of what HTML 4.01 says as it refers to RFC 1738 for 1120
1121 * reserved characters. 1121 * The component is first encoded to bytes using [encoding].
1122 * The default is to use [UTF8] encoding, which preserves all
1123 * the characters that don't need encoding.
1124
1125 * Then the resulting bytes are "percent-encoded". This transforms
1126 * spaces (U+0020) to a plus sign ('+') and all bytes that are not
1127 * the ASCII decimal digits, letters or one of '-._~' are written as
1128 * a percent sign '%' followed by the two-digit hexadecimal
1129 * representation of the byte.
1130
1131 * Note that the set of characters which are percent-encoded is a
1132 * superset of what HTML 4.01 requires, since it refers to RFC 1738
1133 * for reserved characters.
1122 * 1134 *
1123 * When manually encoding query components remember to encode each 1135 * When manually encoding query components remember to encode each
1124 * part separately before building the query string. 1136 * part separately before building the query string.
1125 * 1137 *
1126 * To avoid the need for explicitly encoding the query use the 1138 * To avoid the need for explicitly encoding the query use the
1127 * [queryParameters] optional named arguments when constructing a 1139 * [queryParameters] optional named arguments when constructing a
1128 * [Uri]. 1140 * [Uri].
1129 * 1141 *
1130 * See http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 for more 1142 * See http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 for more
1131 * details. 1143 * details.
1132 */ 1144 */
1133 static String encodeQueryComponent(String component) { 1145 static String encodeQueryComponent(String component,
1134 return _uriEncode(_unreservedTable, component, spaceToPlus: true); 1146 {Encoding encoding: UTF8}) {
1147 return _uriEncode(
1148 _unreservedTable, component, encoding: encoding, spaceToPlus: true);
1135 } 1149 }
1136 1150
1137 /** 1151 /**
1138 * Decodes the percent-encoding in [encodedComponent]. 1152 * Decodes the percent-encoding in [encodedComponent].
1139 * 1153 *
1140 * Note that decoding a URI component might change its meaning as 1154 * Note that decoding a URI component might change its meaning as
1141 * some of the decoded characters could be characters with are 1155 * some of the decoded characters could be characters with are
1142 * delimiters for a given URI componene type. Always split a URI 1156 * delimiters for a given URI componene type. Always split a URI
1143 * component using the delimiters for the component before decoding 1157 * component using the delimiters for the component before decoding
1144 * the individual parts. 1158 * the individual parts.
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1346 if (value == -1) { 1360 if (value == -1) {
1347 return new List.filled((9 - parts.length) * 2, 0); 1361 return new List.filled((9 - parts.length) * 2, 0);
1348 } else { 1362 } else {
1349 return [(value >> 8) & 0xFF, value & 0xFF]; 1363 return [(value >> 8) & 0xFF, value & 0xFF];
1350 } 1364 }
1351 }) 1365 })
1352 .toList(); 1366 .toList();
1353 } 1367 }
1354 1368
1355 // Frequently used character codes. 1369 // Frequently used character codes.
1370 static const int _SPACE = 0x20;
1356 static const int _DOUBLE_QUOTE = 0x22; 1371 static const int _DOUBLE_QUOTE = 0x22;
1357 static const int _PERCENT = 0x25; 1372 static const int _PERCENT = 0x25;
1358 static const int _ASTERISK = 0x2A; 1373 static const int _ASTERISK = 0x2A;
1359 static const int _PLUS = 0x2B; 1374 static const int _PLUS = 0x2B;
1360 static const int _SLASH = 0x2F; 1375 static const int _SLASH = 0x2F;
1361 static const int _ZERO = 0x30; 1376 static const int _ZERO = 0x30;
1362 static const int _NINE = 0x39; 1377 static const int _NINE = 0x39;
1363 static const int _COLON = 0x3A; 1378 static const int _COLON = 0x3A;
1364 static const int _LESS = 0x3C; 1379 static const int _LESS = 0x3C;
1365 static const int _GREATER = 0x3E; 1380 static const int _GREATER = 0x3E;
1366 static const int _QUESTION = 0x3F; 1381 static const int _QUESTION = 0x3F;
1367 static const int _AT_SIGN = 0x40; 1382 static const int _AT_SIGN = 0x40;
1368 static const int _UPPER_CASE_A = 0x41; 1383 static const int _UPPER_CASE_A = 0x41;
1369 static const int _UPPER_CASE_F = 0x46; 1384 static const int _UPPER_CASE_F = 0x46;
1370 static const int _UPPER_CASE_Z = 0x5A; 1385 static const int _UPPER_CASE_Z = 0x5A;
1371 static const int _LEFT_BRACKET = 0x5B; 1386 static const int _LEFT_BRACKET = 0x5B;
1372 static const int _BACKSLASH = 0x5C; 1387 static const int _BACKSLASH = 0x5C;
1373 static const int _RIGHT_BRACKET = 0x5D; 1388 static const int _RIGHT_BRACKET = 0x5D;
1374 static const int _LOWER_CASE_A = 0x61; 1389 static const int _LOWER_CASE_A = 0x61;
1375 static const int _LOWER_CASE_F = 0x66; 1390 static const int _LOWER_CASE_F = 0x66;
1376 static const int _LOWER_CASE_Z = 0x7A; 1391 static const int _LOWER_CASE_Z = 0x7A;
1377 static const int _BAR = 0x7C; 1392 static const int _BAR = 0x7C;
1378 1393
1379 /** 1394 /**
1380 * This is the internal implementation of JavaScript's encodeURI function. 1395 * This is the internal implementation of JavaScript's encodeURI function.
1381 * It encodes all characters in the string [text] except for those 1396 * It encodes all characters in the string [text] except for those
1382 * that appear in [canonicalTable], and returns the escaped string. 1397 * that appear in [canonicalTable], and returns the escaped string.
1383 */ 1398 */
1384 static String _uriEncode(List<int> canonicalTable, 1399 static String _uriEncode(List<int> canonicalTable,
1385 String text, 1400 String text,
1386 {bool spaceToPlus: false}) { 1401 {Encoding encoding: UTF8,
1387 byteToHex(int v) { 1402 bool spaceToPlus: false}) {
1388 final String hex = '0123456789ABCDEF'; 1403 byteToHex(byte, buffer) {
1389 return '%${hex[v >> 4]}${hex[v & 0x0f]}'; 1404 const String hex = '0123456789ABCDEF';
1405 buffer.writeCharCode(hex.codeUnitAt(byte >> 4));
1406 buffer.writeCharCode(hex.codeUnitAt(byte & 0x0f));
1390 } 1407 }
1391 1408
1409 // Encode the string into bytes then generate an ASCII only string
1410 // by percent encoding selected bytes.
1392 StringBuffer result = new StringBuffer(); 1411 StringBuffer result = new StringBuffer();
1393 for (int i = 0; i < text.length; i++) { 1412 var bytes = encoding.encode(text);
1394 int ch = text.codeUnitAt(i); 1413 for (int i = 0; i < bytes.length; i++) {
1395 if (ch < 128 && ((canonicalTable[ch >> 4] & (1 << (ch & 0x0f))) != 0)) { 1414 int byte = bytes[i];
1396 result.write(text[i]); 1415 if (byte < 128 &&
1397 } else if (spaceToPlus && text[i] == " ") { 1416 ((canonicalTable[byte >> 4] & (1 << (byte & 0x0f))) != 0)) {
1398 result.write("+"); 1417 result.writeCharCode(byte);
1418 } else if (spaceToPlus && byte == _SPACE) {
1419 result.writeCharCode(_PLUS);
1399 } else { 1420 } else {
1400 if (ch >= 0xD800 && ch < 0xDC00) { 1421 result.writeCharCode(_PERCENT);
1401 // Low surrogate. We expect a next char high surrogate. 1422 byteToHex(byte, result);
1402 ++i;
1403 int nextCh = text.length == i ? 0 : text.codeUnitAt(i);
1404 if (nextCh >= 0xDC00 && nextCh < 0xE000) {
1405 // convert the pair to a U+10000 codepoint
1406 ch = 0x10000 + ((ch - 0xD800) << 10) + (nextCh - 0xDC00);
1407 } else {
1408 throw new ArgumentError('Malformed URI');
1409 }
1410 }
1411 // TODO(floitsch): don't allocate a new string.
1412 for (int codepoint in UTF8.encode(new String.fromCharCode(ch))) {
1413 result.write(byteToHex(codepoint));
1414 }
1415 } 1423 }
1416 } 1424 }
1417 return result.toString(); 1425 return result.toString();
1418 } 1426 }
1419 1427
1420 /** 1428 /**
1421 * Convert a byte (2 character hex sequence) in string [s] starting 1429 * Convert a byte (2 character hex sequence) in string [s] starting
1422 * at position [pos] to its ordinal value 1430 * at position [pos] to its ordinal value
1423 */ 1431 */
1424 static int _hexCharPairToByte(String s, int pos) { 1432 static int _hexCharPairToByte(String s, int pos) {
(...skipping 23 matching lines...) Expand all
1448 * This function is similar to the JavaScript-function `decodeURI`. 1456 * This function is similar to the JavaScript-function `decodeURI`.
1449 * 1457 *
1450 * If [plusToSpace] is `true`, plus characters will be converted to spaces. 1458 * If [plusToSpace] is `true`, plus characters will be converted to spaces.
1451 * 1459 *
1452 * The decoder will create a byte-list of the percent-encoded parts, and then 1460 * The decoder will create a byte-list of the percent-encoded parts, and then
1453 * decode the byte-list using [encoding]. The default encodingis UTF-8. 1461 * decode the byte-list using [encoding]. The default encodingis UTF-8.
1454 */ 1462 */
1455 static String _uriDecode(String text, 1463 static String _uriDecode(String text,
1456 {bool plusToSpace: false, 1464 {bool plusToSpace: false,
1457 Encoding encoding: UTF8}) { 1465 Encoding encoding: UTF8}) {
1458 StringBuffer result = new StringBuffer(); 1466 // First check whether there is any characters which need special handling.
1459 List<int> codepoints = new List<int>(); 1467 bool simple = true;
1460 for (int i = 0; i < text.length;) { 1468 for (int i = 0; i < text.length && simple; i++) {
1461 int ch = text.codeUnitAt(i); 1469 var codeUnit = text.codeUnitAt(i);
1462 if (ch != _PERCENT) { 1470 simple = codeUnit != _PERCENT && codeUnit != _PLUS;
1463 if (plusToSpace && ch == _PLUS) { 1471 }
1464 result.write(" "); 1472 List<int> bytes;
1465 } else { 1473 if (simple) {
1466 result.writeCharCode(ch); 1474 if (encoding == UTF8 || encoding == LATIN1) {
1475 return text;
1476 } else {
1477 bytes = text.codeUnits;
1478 }
1479 } else {
1480 bytes = new List();
1481 for (int i = 0; i < text.length; i++) {
1482 var codeUnit = text.codeUnitAt(i);
1483 if (codeUnit > 127) {
1484 throw new ArgumentError("Illegal percent encoding in URI");
1467 } 1485 }
1468 i++; 1486 if (codeUnit == _PERCENT) {
1469 } else { 1487 if (i + 3 > text.length) {
1470 codepoints.clear();
1471 while (ch == _PERCENT) {
1472 if (++i > text.length - 2) {
1473 throw new ArgumentError('Truncated URI'); 1488 throw new ArgumentError('Truncated URI');
1474 } 1489 }
1475 codepoints.add(_hexCharPairToByte(text, i)); 1490 bytes.add(_hexCharPairToByte(text, i + 1));
1476 i += 2; 1491 i += 2;
1477 if (i == text.length) break; 1492 } else if (plusToSpace && codeUnit == _PLUS) {
1478 ch = text.codeUnitAt(i); 1493 bytes.add(_SPACE);
1494 } else {
1495 bytes.add(codeUnit);
1479 } 1496 }
1480 result.write(encoding.decode(codepoints));
1481 } 1497 }
1482 } 1498 }
1483 return result.toString(); 1499 return encoding.decode(bytes);
1484 } 1500 }
1485 1501
1486 static bool _isAlphabeticCharacter(int codeUnit) 1502 static bool _isAlphabeticCharacter(int codeUnit)
1487 => (codeUnit >= _LOWER_CASE_A && codeUnit <= _LOWER_CASE_Z) || 1503 => (codeUnit >= _LOWER_CASE_A && codeUnit <= _LOWER_CASE_Z) ||
1488 (codeUnit >= _UPPER_CASE_A && codeUnit <= _UPPER_CASE_Z); 1504 (codeUnit >= _UPPER_CASE_A && codeUnit <= _UPPER_CASE_Z);
1489 1505
1490 // Tables of char-codes organized as a bit vector of 128 bits where 1506 // Tables of char-codes organized as a bit vector of 128 bits where
1491 // each bit indicate whether a character code on the 0-127 needs to 1507 // each bit indicate whether a character code on the 0-127 needs to
1492 // be escaped or not. 1508 // be escaped or not.
1493 1509
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
1674 void clear() { 1690 void clear() {
1675 throw new UnsupportedError("Cannot modify an unmodifiable map"); 1691 throw new UnsupportedError("Cannot modify an unmodifiable map");
1676 } 1692 }
1677 void forEach(void f(K key, V value)) => _map.forEach(f); 1693 void forEach(void f(K key, V value)) => _map.forEach(f);
1678 Iterable<K> get keys => _map.keys; 1694 Iterable<K> get keys => _map.keys;
1679 Iterable<V> get values => _map.values; 1695 Iterable<V> get values => _map.values;
1680 int get length => _map.length; 1696 int get length => _map.length;
1681 bool get isEmpty => _map.isEmpty; 1697 bool get isEmpty => _map.isEmpty;
1682 bool get isNotEmpty => _map.isNotEmpty; 1698 bool get isNotEmpty => _map.isNotEmpty;
1683 } 1699 }
OLDNEW
« no previous file with comments | « sdk/lib/core/core.dart ('k') | tests/corelib/uri_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698