OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/base/net_util.h" | 5 #include "net/base/net_util.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <map> | 8 #include <map> |
9 #include <unicode/ucnv.h> | 9 #include <unicode/ucnv.h> |
10 #include <unicode/uidna.h> | 10 #include <unicode/uidna.h> |
11 #include <unicode/ulocdata.h> | 11 #include <unicode/ulocdata.h> |
(...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 // Failed, revert back to original string. | 700 // Failed, revert back to original string. |
701 out->resize(original_length); | 701 out->resize(original_length); |
702 } | 702 } |
703 | 703 |
704 // We get here with no IDN or on error, in which case we just append the | 704 // We get here with no IDN or on error, in which case we just append the |
705 // literal input. | 705 // literal input. |
706 out->append(comp, comp_len); | 706 out->append(comp, comp_len); |
707 return false; | 707 return false; |
708 } | 708 } |
709 | 709 |
| 710 // If |component| is valid, its begin is incremented by |delta|. |
| 711 void AdjustComponent(int delta, url_parse::Component* component) { |
| 712 if (!component->is_valid()) |
| 713 return; |
| 714 |
| 715 DCHECK(delta >= 0 || component->begin >= -delta); |
| 716 component->begin += delta; |
| 717 } |
| 718 |
| 719 // Adjusts all the components of |parsed| by |delta|, except for the scheme. |
| 720 void AdjustComponents(int delta, url_parse::Parsed* parsed) { |
| 721 AdjustComponent(delta, &(parsed->username)); |
| 722 AdjustComponent(delta, &(parsed->password)); |
| 723 AdjustComponent(delta, &(parsed->host)); |
| 724 AdjustComponent(delta, &(parsed->port)); |
| 725 AdjustComponent(delta, &(parsed->path)); |
| 726 AdjustComponent(delta, &(parsed->query)); |
| 727 AdjustComponent(delta, &(parsed->ref)); |
| 728 } |
| 729 |
710 // Helper for FormatUrl(). | 730 // Helper for FormatUrl(). |
711 std::wstring FormatViewSourceUrl(const GURL& url, | 731 std::wstring FormatViewSourceUrl(const GURL& url, |
712 const std::wstring& languages, | 732 const std::wstring& languages, |
713 bool omit_username_password, | 733 net::FormatUrlTypes format_types, |
714 UnescapeRule::Type unescape_rules, | 734 UnescapeRule::Type unescape_rules, |
715 url_parse::Parsed* new_parsed, | 735 url_parse::Parsed* new_parsed, |
716 size_t* prefix_end, | 736 size_t* prefix_end, |
717 size_t* offset_for_adjustment) { | 737 size_t* offset_for_adjustment) { |
718 DCHECK(new_parsed); | 738 DCHECK(new_parsed); |
719 const wchar_t* const kWideViewSource = L"view-source:"; | 739 const wchar_t* const kWideViewSource = L"view-source:"; |
720 const size_t kViewSourceLengthPlus1 = 12; | 740 const size_t kViewSourceLengthPlus1 = 12; |
721 | 741 |
722 GURL real_url(url.possibly_invalid_spec().substr(kViewSourceLengthPlus1)); | 742 GURL real_url(url.possibly_invalid_spec().substr(kViewSourceLengthPlus1)); |
723 size_t temp_offset = (*offset_for_adjustment == std::wstring::npos) ? | 743 size_t temp_offset = (*offset_for_adjustment == std::wstring::npos) ? |
724 std::wstring::npos : (*offset_for_adjustment - kViewSourceLengthPlus1); | 744 std::wstring::npos : (*offset_for_adjustment - kViewSourceLengthPlus1); |
725 size_t* temp_offset_ptr = (*offset_for_adjustment < kViewSourceLengthPlus1) ? | 745 size_t* temp_offset_ptr = (*offset_for_adjustment < kViewSourceLengthPlus1) ? |
726 NULL : &temp_offset; | 746 NULL : &temp_offset; |
727 std::wstring result = net::FormatUrl(real_url, languages, | 747 std::wstring result = net::FormatUrl(real_url, languages, |
728 omit_username_password, unescape_rules, new_parsed, prefix_end, | 748 format_types, unescape_rules, new_parsed, prefix_end, temp_offset_ptr); |
729 temp_offset_ptr); | |
730 result.insert(0, kWideViewSource); | 749 result.insert(0, kWideViewSource); |
731 | 750 |
732 // Adjust position values. | 751 // Adjust position values. |
733 if (new_parsed->scheme.is_nonempty()) { | 752 if (new_parsed->scheme.is_nonempty()) { |
734 // Assume "view-source:real-scheme" as a scheme. | 753 // Assume "view-source:real-scheme" as a scheme. |
735 new_parsed->scheme.len += kViewSourceLengthPlus1; | 754 new_parsed->scheme.len += kViewSourceLengthPlus1; |
736 } else { | 755 } else { |
737 new_parsed->scheme.begin = 0; | 756 new_parsed->scheme.begin = 0; |
738 new_parsed->scheme.len = kViewSourceLengthPlus1 - 1; | 757 new_parsed->scheme.len = kViewSourceLengthPlus1 - 1; |
739 } | 758 } |
740 if (new_parsed->username.is_nonempty()) | 759 AdjustComponents(kViewSourceLengthPlus1, new_parsed); |
741 new_parsed->username.begin += kViewSourceLengthPlus1; | |
742 if (new_parsed->password.is_nonempty()) | |
743 new_parsed->password.begin += kViewSourceLengthPlus1; | |
744 if (new_parsed->host.is_nonempty()) | |
745 new_parsed->host.begin += kViewSourceLengthPlus1; | |
746 if (new_parsed->port.is_nonempty()) | |
747 new_parsed->port.begin += kViewSourceLengthPlus1; | |
748 if (new_parsed->path.is_nonempty()) | |
749 new_parsed->path.begin += kViewSourceLengthPlus1; | |
750 if (new_parsed->query.is_nonempty()) | |
751 new_parsed->query.begin += kViewSourceLengthPlus1; | |
752 if (new_parsed->ref.is_nonempty()) | |
753 new_parsed->ref.begin += kViewSourceLengthPlus1; | |
754 if (prefix_end) | 760 if (prefix_end) |
755 *prefix_end += kViewSourceLengthPlus1; | 761 *prefix_end += kViewSourceLengthPlus1; |
756 if (temp_offset_ptr) { | 762 if (temp_offset_ptr) { |
757 *offset_for_adjustment = (temp_offset == std::wstring::npos) ? | 763 *offset_for_adjustment = (temp_offset == std::wstring::npos) ? |
758 std::wstring::npos : (temp_offset + kViewSourceLengthPlus1); | 764 std::wstring::npos : (temp_offset + kViewSourceLengthPlus1); |
759 } | 765 } |
760 return result; | 766 return result; |
761 } | 767 } |
762 | 768 |
763 } // namespace | 769 } // namespace |
764 | 770 |
765 namespace net { | 771 namespace net { |
766 | 772 |
| 773 const FormatUrlType kFormatUrlOmitNothing = 0; |
| 774 const FormatUrlType kFormatUrlOmitUsernamePassword = 1 << 0; |
| 775 const FormatUrlType kFormatUrlOmitHTTP = 1 << 1; |
| 776 const FormatUrlType kFormatUrlOmitAll = kFormatUrlOmitUsernamePassword | |
| 777 kFormatUrlOmitHTTP; |
| 778 |
767 std::set<int> explicitly_allowed_ports; | 779 std::set<int> explicitly_allowed_ports; |
768 | 780 |
769 // Appends the substring |in_component| inside of the URL |spec| to |output|, | 781 // Appends the substring |in_component| inside of the URL |spec| to |output|, |
770 // and the resulting range will be filled into |out_component|. |unescape_rules| | 782 // and the resulting range will be filled into |out_component|. |unescape_rules| |
771 // defines how to clean the URL for human readability. |offset_for_adjustment| | 783 // defines how to clean the URL for human readability. |offset_for_adjustment| |
772 // is an offset into |output| which will be adjusted based on how it maps to the | 784 // is an offset into |output| which will be adjusted based on how it maps to the |
773 // component being converted; if it is less than output->length(), it will be | 785 // component being converted; if it is less than output->length(), it will be |
774 // untouched, and if it is greater than output->length() + in_component.len it | 786 // untouched, and if it is greater than output->length() + in_component.len it |
775 // will be shortened by the difference in lengths between the input and output | 787 // will be shortened by the difference in lengths between the input and output |
776 // components. Otherwise it points into the component being converted, and is | 788 // components. Otherwise it points into the component being converted, and is |
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1365 } else if (offset_past_current_output != std::wstring::npos) { | 1377 } else if (offset_past_current_output != std::wstring::npos) { |
1366 *offset_for_adjustment += out_component->len - in_component.len; | 1378 *offset_for_adjustment += out_component->len - in_component.len; |
1367 } | 1379 } |
1368 } else { | 1380 } else { |
1369 out_component->reset(); | 1381 out_component->reset(); |
1370 } | 1382 } |
1371 } | 1383 } |
1372 | 1384 |
1373 std::wstring FormatUrl(const GURL& url, | 1385 std::wstring FormatUrl(const GURL& url, |
1374 const std::wstring& languages, | 1386 const std::wstring& languages, |
1375 bool omit_username_password, | 1387 FormatUrlTypes format_types, |
1376 UnescapeRule::Type unescape_rules, | 1388 UnescapeRule::Type unescape_rules, |
1377 url_parse::Parsed* new_parsed, | 1389 url_parse::Parsed* new_parsed, |
1378 size_t* prefix_end, | 1390 size_t* prefix_end, |
1379 size_t* offset_for_adjustment) { | 1391 size_t* offset_for_adjustment) { |
1380 url_parse::Parsed parsed_temp; | 1392 url_parse::Parsed parsed_temp; |
1381 if (!new_parsed) | 1393 if (!new_parsed) |
1382 new_parsed = &parsed_temp; | 1394 new_parsed = &parsed_temp; |
1383 size_t offset_temp = std::wstring::npos; | 1395 size_t offset_temp = std::wstring::npos; |
1384 if (!offset_for_adjustment) | 1396 if (!offset_for_adjustment) |
1385 offset_for_adjustment = &offset_temp; | 1397 offset_for_adjustment = &offset_temp; |
1386 | 1398 |
1387 std::wstring url_string; | 1399 std::wstring url_string; |
1388 | 1400 |
1389 // Check for empty URLs or 0 available text width. | 1401 // Check for empty URLs or 0 available text width. |
1390 if (url.is_empty()) { | 1402 if (url.is_empty()) { |
1391 if (prefix_end) | 1403 if (prefix_end) |
1392 *prefix_end = 0; | 1404 *prefix_end = 0; |
1393 *offset_for_adjustment = std::wstring::npos; | 1405 *offset_for_adjustment = std::wstring::npos; |
1394 return url_string; | 1406 return url_string; |
1395 } | 1407 } |
1396 | 1408 |
1397 // Special handling for view-source:. Don't use chrome::kViewSourceScheme | 1409 // Special handling for view-source:. Don't use chrome::kViewSourceScheme |
1398 // because this library shouldn't depend on chrome. | 1410 // because this library shouldn't depend on chrome. |
1399 const char* const kViewSource = "view-source"; | 1411 const char* const kViewSource = "view-source"; |
1400 const char* const kViewSourceTwice = "view-source:view-source:"; | 1412 const char* const kViewSourceTwice = "view-source:view-source:"; |
1401 // Rejects view-source:view-source:... to avoid deep recursive call. | 1413 // Rejects view-source:view-source:... to avoid deep recursive call. |
1402 if (url.SchemeIs(kViewSource) && | 1414 if (url.SchemeIs(kViewSource) && |
1403 !StartsWithASCII(url.possibly_invalid_spec(), kViewSourceTwice, false)) { | 1415 !StartsWithASCII(url.possibly_invalid_spec(), kViewSourceTwice, false)) { |
1404 return FormatViewSourceUrl(url, languages, omit_username_password, | 1416 return FormatViewSourceUrl(url, languages, format_types, |
1405 unescape_rules, new_parsed, prefix_end, offset_for_adjustment); | 1417 unescape_rules, new_parsed, prefix_end, offset_for_adjustment); |
1406 } | 1418 } |
1407 | 1419 |
1408 // We handle both valid and invalid URLs (this will give us the spec | 1420 // We handle both valid and invalid URLs (this will give us the spec |
1409 // regardless of validity). | 1421 // regardless of validity). |
1410 const std::string& spec = url.possibly_invalid_spec(); | 1422 const std::string& spec = url.possibly_invalid_spec(); |
1411 const url_parse::Parsed& parsed = url.parsed_for_possibly_invalid_spec(); | 1423 const url_parse::Parsed& parsed = url.parsed_for_possibly_invalid_spec(); |
1412 if (*offset_for_adjustment >= spec.length()) | 1424 if (*offset_for_adjustment >= spec.length()) |
1413 *offset_for_adjustment = std::wstring::npos; | 1425 *offset_for_adjustment = std::wstring::npos; |
1414 | 1426 |
1415 // Copy everything before the username (the scheme and the separators.) | 1427 // Copy everything before the username (the scheme and the separators.) |
1416 // These are ASCII. | 1428 // These are ASCII. |
1417 std::copy(spec.begin(), | 1429 std::copy(spec.begin(), |
1418 spec.begin() + parsed.CountCharactersBefore(url_parse::Parsed::USERNAME, | 1430 spec.begin() + parsed.CountCharactersBefore(url_parse::Parsed::USERNAME, |
1419 true), | 1431 true), |
1420 std::back_inserter(url_string)); | 1432 std::back_inserter(url_string)); |
| 1433 |
| 1434 const wchar_t* const kHTTP = L"http://"; |
| 1435 const size_t kHTTPSize = std::wstring(kHTTP).size(); |
| 1436 bool omit_http = ((format_types & kFormatUrlOmitHTTP) != 0 && |
| 1437 url_string == kHTTP); |
| 1438 |
1421 new_parsed->scheme = parsed.scheme; | 1439 new_parsed->scheme = parsed.scheme; |
1422 | 1440 |
1423 if (omit_username_password) { | 1441 if ((format_types & kFormatUrlOmitUsernamePassword) != 0) { |
1424 // Remove the username and password fields. We don't want to display those | 1442 // Remove the username and password fields. We don't want to display those |
1425 // to the user since they can be used for attacks, | 1443 // to the user since they can be used for attacks, |
1426 // e.g. "http://google.com:search@evil.ru/" | 1444 // e.g. "http://google.com:search@evil.ru/" |
1427 new_parsed->username.reset(); | 1445 new_parsed->username.reset(); |
1428 new_parsed->password.reset(); | 1446 new_parsed->password.reset(); |
1429 if ((*offset_for_adjustment != std::wstring::npos) && | 1447 if ((*offset_for_adjustment != std::wstring::npos) && |
1430 (parsed.username.is_nonempty() || parsed.password.is_nonempty())) { | 1448 (parsed.username.is_nonempty() || parsed.password.is_nonempty())) { |
1431 if (parsed.username.is_nonempty() && parsed.password.is_nonempty()) { | 1449 if (parsed.username.is_nonempty() && parsed.password.is_nonempty()) { |
1432 // The seeming off-by-one and off-by-two in these first two lines are to | 1450 // The seeming off-by-one and off-by-two in these first two lines are to |
1433 // account for the ':' after the username and '@' after the password. | 1451 // account for the ':' after the username and '@' after the password. |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1513 } else if (offset_past_current_output != std::wstring::npos) { | 1531 } else if (offset_past_current_output != std::wstring::npos) { |
1514 // We clamped the offset near the beginning of this function to ensure it | 1532 // We clamped the offset near the beginning of this function to ensure it |
1515 // was within the input URL. If we reach here, the input was something | 1533 // was within the input URL. If we reach here, the input was something |
1516 // invalid and non-parseable such that the offset was past any component | 1534 // invalid and non-parseable such that the offset was past any component |
1517 // we could figure out. In this case it won't be represented in the | 1535 // we could figure out. In this case it won't be represented in the |
1518 // output string, so reset it. | 1536 // output string, so reset it. |
1519 *offset_for_adjustment = std::wstring::npos; | 1537 *offset_for_adjustment = std::wstring::npos; |
1520 } | 1538 } |
1521 } | 1539 } |
1522 | 1540 |
| 1541 // If we need to strip out http do it after the fact. This way we don't need |
| 1542 // to worry about how offset_for_adjustment is interpreted. |
| 1543 if (omit_http && !url_string.compare(0, kHTTPSize, kHTTP)) { |
| 1544 url_string = url_string.substr(kHTTPSize); |
| 1545 if (*offset_for_adjustment != std::wstring::npos) { |
| 1546 if (*offset_for_adjustment < kHTTPSize) |
| 1547 *offset_for_adjustment = std::wstring::npos; |
| 1548 else |
| 1549 *offset_for_adjustment -= kHTTPSize; |
| 1550 } |
| 1551 if (prefix_end) |
| 1552 *prefix_end -= kHTTPSize; |
| 1553 |
| 1554 // Adjust new_parsed. |
| 1555 DCHECK(new_parsed->scheme.is_valid()); |
| 1556 int delta = -(new_parsed->scheme.len + 3); // +3 for ://. |
| 1557 new_parsed->scheme.reset(); |
| 1558 AdjustComponents(delta, new_parsed); |
| 1559 } |
| 1560 |
1523 return url_string; | 1561 return url_string; |
1524 } | 1562 } |
1525 | 1563 |
1526 GURL SimplifyUrlForRequest(const GURL& url) { | 1564 GURL SimplifyUrlForRequest(const GURL& url) { |
1527 DCHECK(url.is_valid()); | 1565 DCHECK(url.is_valid()); |
1528 GURL::Replacements replacements; | 1566 GURL::Replacements replacements; |
1529 replacements.ClearUsername(); | 1567 replacements.ClearUsername(); |
1530 replacements.ClearPassword(); | 1568 replacements.ClearPassword(); |
1531 replacements.ClearRef(); | 1569 replacements.ClearRef(); |
1532 return url.ReplaceComponents(replacements); | 1570 return url.ReplaceComponents(replacements); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1677 | 1715 |
1678 IPv6SupportResults(IPV6_GLOBAL_ADDRESS_MISSING); | 1716 IPv6SupportResults(IPV6_GLOBAL_ADDRESS_MISSING); |
1679 return false; | 1717 return false; |
1680 #else | 1718 #else |
1681 NOTIMPLEMENTED(); | 1719 NOTIMPLEMENTED(); |
1682 return true; | 1720 return true; |
1683 #endif // defined(various platforms) | 1721 #endif // defined(various platforms) |
1684 } | 1722 } |
1685 | 1723 |
1686 } // namespace net | 1724 } // namespace net |
OLD | NEW |