url_canon_pathurl.cc 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. // Functions for canonicalizing "path" URLs. Not to be confused with the path
  5. // of a URL, these are URLs that have no authority section, only a path. For
  6. // example, "javascript:" and "data:".
  7. #include "url/url_canon.h"
  8. #include "url/url_canon_internal.h"
  9. namespace url {
  10. namespace {
  11. // Canonicalize the given |component| from |source| into |output| and
  12. // |new_component|. If |separator| is non-zero, it is pre-pended to |output|
  13. // prior to the canonicalized component; i.e. for the '?' or '#' characters.
  14. template <typename CHAR, typename UCHAR>
  15. void DoCanonicalizePathComponent(const CHAR* source,
  16. const Component& component,
  17. char separator,
  18. CanonOutput* output,
  19. Component* new_component) {
  20. if (component.is_valid()) {
  21. if (separator)
  22. output->push_back(separator);
  23. // Copy the path using path URL's more lax escaping rules (think for
  24. // javascript:). We convert to UTF-8 and escape characters from the
  25. // C0 control percent-encode set, but leave all other characters alone.
  26. // This helps readability of JavaScript.
  27. // https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state
  28. // https://url.spec.whatwg.org/#c0-control-percent-encode-set
  29. new_component->begin = output->length();
  30. size_t end = static_cast<size_t>(component.end());
  31. for (size_t i = static_cast<size_t>(component.begin); i < end; i++) {
  32. UCHAR uch = static_cast<UCHAR>(source[i]);
  33. if (uch < 0x20 || uch > 0x7E)
  34. AppendUTF8EscapedChar(source, &i, end, output);
  35. else
  36. output->push_back(static_cast<char>(uch));
  37. }
  38. new_component->len = output->length() - new_component->begin;
  39. } else {
  40. // Empty part.
  41. new_component->reset();
  42. }
  43. }
  44. template <typename CHAR, typename UCHAR>
  45. bool DoCanonicalizePathURL(const URLComponentSource<CHAR>& source,
  46. const Parsed& parsed,
  47. CanonOutput* output,
  48. Parsed* new_parsed) {
  49. // Scheme: this will append the colon.
  50. bool success = CanonicalizeScheme(source.scheme, parsed.scheme,
  51. output, &new_parsed->scheme);
  52. // We assume there's no authority for path URLs. Note that hosts should never
  53. // have -1 length.
  54. new_parsed->username.reset();
  55. new_parsed->password.reset();
  56. new_parsed->host.reset();
  57. new_parsed->port.reset();
  58. // Canonicalize path via the weaker path URL rules.
  59. //
  60. // Note: parsing the path part should never cause a failure, see
  61. // https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state
  62. DoCanonicalizePathComponent<CHAR, UCHAR>(source.path, parsed.path, '\0',
  63. output, &new_parsed->path);
  64. // Similar to mailto:, always use the default UTF-8 charset converter for
  65. // query.
  66. CanonicalizeQuery(source.query, parsed.query, nullptr, output,
  67. &new_parsed->query);
  68. CanonicalizeRef(source.ref, parsed.ref, output, &new_parsed->ref);
  69. return success;
  70. }
  71. } // namespace
  72. bool CanonicalizePathURL(const char* spec,
  73. int spec_len,
  74. const Parsed& parsed,
  75. CanonOutput* output,
  76. Parsed* new_parsed) {
  77. return DoCanonicalizePathURL<char, unsigned char>(
  78. URLComponentSource<char>(spec), parsed, output, new_parsed);
  79. }
  80. bool CanonicalizePathURL(const char16_t* spec,
  81. int spec_len,
  82. const Parsed& parsed,
  83. CanonOutput* output,
  84. Parsed* new_parsed) {
  85. return DoCanonicalizePathURL<char16_t, char16_t>(
  86. URLComponentSource<char16_t>(spec), parsed, output, new_parsed);
  87. }
  88. void CanonicalizePathURLPath(const char* source,
  89. const Component& component,
  90. CanonOutput* output,
  91. Component* new_component) {
  92. DoCanonicalizePathComponent<char, unsigned char>(source, component, '\0',
  93. output, new_component);
  94. }
  95. void CanonicalizePathURLPath(const char16_t* source,
  96. const Component& component,
  97. CanonOutput* output,
  98. Component* new_component) {
  99. DoCanonicalizePathComponent<char16_t, char16_t>(source, component, '\0',
  100. output, new_component);
  101. }
  102. bool ReplacePathURL(const char* base,
  103. const Parsed& base_parsed,
  104. const Replacements<char>& replacements,
  105. CanonOutput* output,
  106. Parsed* new_parsed) {
  107. URLComponentSource<char> source(base);
  108. Parsed parsed(base_parsed);
  109. SetupOverrideComponents(base, replacements, &source, &parsed);
  110. return DoCanonicalizePathURL<char, unsigned char>(
  111. source, parsed, output, new_parsed);
  112. }
  113. bool ReplacePathURL(const char* base,
  114. const Parsed& base_parsed,
  115. const Replacements<char16_t>& replacements,
  116. CanonOutput* output,
  117. Parsed* new_parsed) {
  118. RawCanonOutput<1024> utf8;
  119. URLComponentSource<char> source(base);
  120. Parsed parsed(base_parsed);
  121. SetupUTF16OverrideComponents(base, replacements, &utf8, &source, &parsed);
  122. return DoCanonicalizePathURL<char, unsigned char>(
  123. source, parsed, output, new_parsed);
  124. }
  125. } // namespace url