[go: nahoru, domu]

blob: 53078176524cc4105dc77dc89abc9d741118ab6f [file] [log] [blame]
Avi Drissman3e1a26c2022-09-15 20:26:031// Copyright 2013 The Chromium Authors
tfarina@chromium.org51bcc5d2013-04-24 01:41:372// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
brettw@chromium.orge7bba5f2013-04-10 20:10:524
avi51ba3e692015-12-26 17:30:505#include <limits.h>
6
Arthur Sonzogni75165b82023-11-07 18:25:477#include <optional>
Hans Wennborg0e223682020-04-27 21:51:298#include "base/check.h"
Vaclav Brozek295d736c2020-12-15 10:09:569#include "base/check_op.h"
tfarina@chromium.org318076b2013-04-18 21:19:4510#include "url/url_canon.h"
11#include "url/url_canon_internal.h"
Hayato Ito21947c42023-09-04 02:05:1512#include "url/url_features.h"
tfarina@chromium.org318076b2013-04-18 21:19:4513#include "url/url_parse_internal.h"
brettw@chromium.orge7bba5f2013-04-10 20:10:5214
vitalybuka@chromium.org0318f922014-04-22 00:09:2315namespace url {
brettw@chromium.orge7bba5f2013-04-10 20:10:5216
17namespace {
18
19enum CharacterFlags {
Hayato Ito737ccaa2023-10-24 02:57:5320 // Pass through unchanged, whether escaped or not. This doesn't
brettw@chromium.orge7bba5f2013-04-10 20:10:5221 // actually set anything so you can't OR it to check, it's just to make the
Hayato Ito737ccaa2023-10-24 02:57:5322 // table below more clear when any other flag is not set.
brettw@chromium.orge7bba5f2013-04-10 20:10:5223 PASS = 0,
24
Ben Kellyd18c0e82021-03-05 22:42:1725 // This character requires special handling in DoPartialPathInternal. Doing
26 // this test
brettw@chromium.orge7bba5f2013-04-10 20:10:5227 // first allows us to filter out the common cases of regular characters that
28 // can be directly copied.
29 SPECIAL = 1,
30
31 // This character must be escaped in the canonical output. Note that all
32 // escaped chars also have the "special" bit set so that the code that looks
33 // for this is triggered. Not valid with PASS or ESCAPE
34 ESCAPE_BIT = 2,
35 ESCAPE = ESCAPE_BIT | SPECIAL,
brettw@chromium.orge7bba5f2013-04-10 20:10:5236};
37
38// This table contains one of the above flag values. Note some flags are more
39// than one bits because they also turn on the "special" flag. Special is the
40// only flag that may be combined with others.
41//
Hayato Ito8caa9bb32023-07-25 00:34:4042// This table was used to be designed to match exactly what IE did with the
Hayato Ito56f19592023-12-07 08:23:4843// characters, however, which doesn't comply with the URL Standard as of Dec
44// 2023. See https://crbug.com/1509295.
brettw@chromium.orge7bba5f2013-04-10 20:10:5245//
46// Dot is even more special, and the escaped version is handled specially by
Hayato Ito737ccaa2023-10-24 02:57:5347// IsDot. Therefore, we don't need the "escape" flag. We just need the "special"
48// bit.
49//
Hayato Ito8caa9bb32023-07-25 00:34:4050// clang-format off
brettw@chromium.orge7bba5f2013-04-10 20:10:5251const unsigned char kPathCharLookup[0x100] = {
52// NULL control chars...
Hayato Ito8caa9bb32023-07-25 00:34:4053 ESCAPE , ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE,
brettw@chromium.orge7bba5f2013-04-10 20:10:5254// control chars...
55 ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE,
56// ' ' ! " # $ % & ' ( ) * + , - . /
Hayato Ito737ccaa2023-10-24 02:57:5357 ESCAPE, PASS, ESCAPE, ESCAPE, PASS, ESCAPE, PASS, PASS, PASS, PASS, PASS, PASS, PASS, PASS ,SPECIAL, PASS,
brettw@chromium.orge7bba5f2013-04-10 20:10:5258// 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
Hayato Ito737ccaa2023-10-24 02:57:5359 PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS, PASS, ESCAPE, PASS, ESCAPE, ESCAPE,
brettw@chromium.orge7bba5f2013-04-10 20:10:5260// @ A B C D E F G H I J K L M N O
Hayato Ito737ccaa2023-10-24 02:57:5361 PASS, PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,
brettw@chromium.orge7bba5f2013-04-10 20:10:5262// P Q R S T U V W X Y Z [ \ ] ^ _
Hayato Ito737ccaa2023-10-24 02:57:5363 PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS, ESCAPE, PASS, ESCAPE, PASS ,
brettw@chromium.orge7bba5f2013-04-10 20:10:5264// ` a b c d e f g h i j k l m n o
Hayato Ito737ccaa2023-10-24 02:57:5365 ESCAPE, PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,
brettw@chromium.orge7bba5f2013-04-10 20:10:5266// p q r s t u v w x y z { | } ~ <NBSP>
Hayato Ito737ccaa2023-10-24 02:57:5367 PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,PASS ,ESCAPE, ESCAPE, ESCAPE, PASS ,ESCAPE,
brettw@chromium.orge7bba5f2013-04-10 20:10:5268// ...all the high-bit characters are escaped
69 ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE,
70 ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE,
71 ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE,
72 ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE,
73 ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE,
74 ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE,
75 ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE,
76 ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE};
Hayato Ito8caa9bb32023-07-25 00:34:4077// clang-format on
brettw@chromium.orge7bba5f2013-04-10 20:10:5278
79enum DotDisposition {
80 // The given dot is just part of a filename and is not special.
81 NOT_A_DIRECTORY,
82
83 // The given dot is the current directory.
84 DIRECTORY_CUR,
85
86 // The given dot is the first of a double dot that should take us up one.
87 DIRECTORY_UP
88};
89
90// When the path resolver finds a dot, this function is called with the
91// character following that dot to see what it is. The return value
92// indicates what type this dot is (see above). This code handles the case
93// where the dot is at the end of the input.
94//
95// |*consumed_len| will contain the number of characters in the input that
96// express what we found.
97//
98// If the input is "../foo", |after_dot| = 1, |end| = 6, and
99// at the end, |*consumed_len| = 2 for the "./" this function consumed. The
100// original dot length should be handled by the caller.
Peter Kasting8bb45c22022-06-16 19:39:27101template <typename CHAR>
102DotDisposition ClassifyAfterDot(const CHAR* spec,
103 size_t after_dot,
104 size_t end,
105 size_t* consumed_len) {
brettw@chromium.orge7bba5f2013-04-10 20:10:52106 if (after_dot == end) {
107 // Single dot at the end.
108 *consumed_len = 0;
109 return DIRECTORY_CUR;
110 }
Hayato Ito2579d832023-11-29 07:57:40111 if (IsSlashOrBackslash(spec[after_dot])) {
brettw@chromium.orge7bba5f2013-04-10 20:10:52112 // Single dot followed by a slash.
113 *consumed_len = 1; // Consume the slash
114 return DIRECTORY_CUR;
115 }
116
Peter Kasting8bb45c22022-06-16 19:39:27117 size_t second_dot_len = IsDot(spec, after_dot, end);
brettw@chromium.orge7bba5f2013-04-10 20:10:52118 if (second_dot_len) {
Peter Kasting8bb45c22022-06-16 19:39:27119 size_t after_second_dot = after_dot + second_dot_len;
brettw@chromium.orge7bba5f2013-04-10 20:10:52120 if (after_second_dot == end) {
121 // Double dot at the end.
122 *consumed_len = second_dot_len;
123 return DIRECTORY_UP;
124 }
Hayato Ito2579d832023-11-29 07:57:40125 if (IsSlashOrBackslash(spec[after_second_dot])) {
brettw@chromium.orge7bba5f2013-04-10 20:10:52126 // Double dot followed by a slash.
127 *consumed_len = second_dot_len + 1;
128 return DIRECTORY_UP;
129 }
130 }
131
132 // The dots are followed by something else, not a directory.
133 *consumed_len = 0;
134 return NOT_A_DIRECTORY;
135}
136
137// Rewinds the output to the previous slash. It is assumed that the output
138// ends with a slash and this doesn't count (we call this when we are
139// appending directory paths, so the previous path component has and ending
140// slash).
141//
142// This will stop at the first slash (assumed to be at position
143// |path_begin_in_output| and not go any higher than that. Some web pages
144// do ".." too many times, so we need to handle that brokenness.
145//
146// It searches for a literal slash rather than including a backslash as well
147// because it is run only on the canonical output.
148//
149// The output is guaranteed to end in a slash when this function completes.
Peter Kastingcfdf32c2022-08-17 20:21:02150void BackUpToPreviousSlash(size_t path_begin_in_output, CanonOutput* output) {
151 CHECK(output->length() > 0);
152 CHECK(path_begin_in_output < output->length());
brettw@chromium.orge7bba5f2013-04-10 20:10:52153
Peter Kastingcfdf32c2022-08-17 20:21:02154 size_t i = output->length() - 1;
brettw@chromium.orge7bba5f2013-04-10 20:10:52155 DCHECK(output->at(i) == '/');
156 if (i == path_begin_in_output)
157 return; // We're at the first slash, nothing to do.
158
159 // Now back up (skipping the trailing slash) until we find another slash.
Peter Kastingcfdf32c2022-08-17 20:21:02160 do {
161 --i;
162 } while (output->at(i) != '/' && i > path_begin_in_output);
brettw@chromium.orge7bba5f2013-04-10 20:10:52163
164 // Now shrink the output to just include that last slash we found.
165 output->set_length(i + 1);
166}
167
Ben Kellyd18c0e82021-03-05 22:42:17168// Canonicalizes and appends the given path to the output. It assumes that if
169// the input path starts with a slash, it should be copied to the output.
brettw@chromium.orge7bba5f2013-04-10 20:10:52170//
171// If there are already path components (this mode is used when appending
172// relative paths for resolving), it assumes that the output already has
173// a trailing slash and that if the input begins with a slash, it should be
174// copied to the output.
175//
176// We do not collapse multiple slashes in a row to a single slash. It seems
qyearsley2bc727d2015-08-14 20:17:15177// no web browsers do this, and we don't want incompatibilities, even though
brettw@chromium.orge7bba5f2013-04-10 20:10:52178// it would be correct for most systems.
Ben Kellyd18c0e82021-03-05 22:42:17179template <typename CHAR, typename UCHAR>
180bool DoPartialPathInternal(const CHAR* spec,
181 const Component& path,
Peter Kastingcfdf32c2022-08-17 20:21:02182 size_t path_begin_in_output,
Hayato Ito727115f2023-12-11 06:41:58183 CanonMode canon_mode,
Ben Kellyd18c0e82021-03-05 22:42:17184 CanonOutput* output) {
Tom Sepez40fbf43e2022-11-15 00:11:03185 if (path.is_empty())
Peter Kasting8bb45c22022-06-16 19:39:27186 return true;
187
188 size_t end = static_cast<size_t>(path.end());
brettw@chromium.orge7bba5f2013-04-10 20:10:52189
190 bool success = true;
Peter Kasting8bb45c22022-06-16 19:39:27191 for (size_t i = static_cast<size_t>(path.begin); i < end; i++) {
brettw@chromium.orge7bba5f2013-04-10 20:10:52192 UCHAR uch = static_cast<UCHAR>(spec[i]);
pkasting69820362015-09-22 01:54:05193 if (sizeof(CHAR) > 1 && uch >= 0x80) {
brettw@chromium.orge7bba5f2013-04-10 20:10:52194 // We only need to test wide input for having non-ASCII characters. For
195 // narrow input, we'll always just use the lookup table. We don't try to
196 // do anything tricky with decoding/validating UTF-8. This function will
197 // read one or two UTF-16 characters and append the output as UTF-8. This
198 // call will be removed in 8-bit mode.
199 success &= AppendUTF8EscapedChar(spec, &i, end, output);
200 } else {
201 // Normal ASCII character or 8-bit input, use the lookup table.
202 unsigned char out_ch = static_cast<unsigned char>(uch);
203 unsigned char flags = kPathCharLookup[out_ch];
204 if (flags & SPECIAL) {
205 // Needs special handling of some sort.
Peter Kasting8bb45c22022-06-16 19:39:27206 size_t dotlen;
brettw@chromium.orge7bba5f2013-04-10 20:10:52207 if ((dotlen = IsDot(spec, i, end)) > 0) {
Ben Kellyd18c0e82021-03-05 22:42:17208 // See if this dot was preceded by a slash in the output.
brettw@chromium.orge7bba5f2013-04-10 20:10:52209 //
210 // Note that we check this in the case of dots so we don't have to
211 // special case slashes. Since slashes are much more common than
212 // dots, this actually increases performance measurably (though
213 // slightly).
brettw@chromium.orge7bba5f2013-04-10 20:10:52214 if (output->length() > path_begin_in_output &&
215 output->at(output->length() - 1) == '/') {
216 // Slash followed by a dot, check to see if this is means relative
Peter Kasting8bb45c22022-06-16 19:39:27217 size_t consumed_len;
brettw@chromium.orge7bba5f2013-04-10 20:10:52218 switch (ClassifyAfterDot<CHAR>(spec, i + dotlen, end,
219 &consumed_len)) {
220 case NOT_A_DIRECTORY:
221 // Copy the dot to the output, it means nothing special.
222 output->push_back('.');
223 i += dotlen - 1;
224 break;
225 case DIRECTORY_CUR: // Current directory, just skip the input.
226 i += dotlen + consumed_len - 1;
227 break;
228 case DIRECTORY_UP:
229 BackUpToPreviousSlash(path_begin_in_output, output);
230 i += dotlen + consumed_len - 1;
231 break;
232 }
233 } else {
qyearsley2bc727d2015-08-14 20:17:15234 // This dot is not preceded by a slash, it is just part of some
brettw@chromium.orge7bba5f2013-04-10 20:10:52235 // file name.
236 output->push_back('.');
237 i += dotlen - 1;
238 }
239
240 } else if (out_ch == '\\') {
Hayato Ito727115f2023-12-11 06:41:58241 if (canon_mode == CanonMode::kSpecialURL) {
242 // Backslashes are path separators in special URLs.
243 //
244 // URL Standard: https://url.spec.whatwg.org/#path-state
245 // > 1. url is special and c is U+005C (\)
246 //
247 // Convert backslashes to forward slashes.
248 output->push_back('/');
249 } else {
250 output->push_back(out_ch);
251 }
brettw@chromium.orge7bba5f2013-04-10 20:10:52252 } else if (out_ch == '%') {
253 // Handle escape sequences.
Hayato Ito737ccaa2023-10-24 02:57:53254 unsigned char unused_unescaped_value;
255 if (DecodeEscaped(spec, &i, end, &unused_unescaped_value)) {
256 // Valid escape sequence. We should just copy it exactly.
257 output->push_back('%');
258 output->push_back(static_cast<char>(spec[i - 1]));
259 output->push_back(static_cast<char>(spec[i]));
brettw@chromium.orge7bba5f2013-04-10 20:10:52260 } else {
pkasting69820362015-09-22 01:54:05261 // Invalid escape sequence. IE7+ rejects any URLs with such
262 // sequences, while other browsers pass them through unchanged. We
263 // use the permissive behavior.
264 // TODO(brettw): Consider testing IE's strict behavior, which would
265 // allow removing the code to handle nested escapes above.
brettw@chromium.orge7bba5f2013-04-10 20:10:52266 output->push_back('%');
267 }
brettw@chromium.orge7bba5f2013-04-10 20:10:52268 } else if (flags & ESCAPE_BIT) {
269 // This character should be escaped.
270 AppendEscapedChar(out_ch, output);
271 }
272 } else {
273 // Nothing special about this character, just append it.
274 output->push_back(out_ch);
275 }
276 }
277 }
278 return success;
279}
280
Ben Kellyd18c0e82021-03-05 22:42:17281// Perform the same logic as in DoPartialPathInternal(), but updates the
282// publicly exposed CanonOutput structure similar to DoPath(). Returns
283// true if successful.
284template <typename CHAR, typename UCHAR>
285bool DoPartialPath(const CHAR* spec,
286 const Component& path,
287 CanonOutput* output,
288 Component* out_path) {
289 out_path->begin = output->length();
Hayato Ito727115f2023-12-11 06:41:58290 bool success = DoPartialPathInternal<CHAR, UCHAR>(
291 spec, path, out_path->begin,
292 // TODO(crbug.com/1416006): Support Non-special URLs.
293 CanonMode::kSpecialURL, output);
Ben Kellyd18c0e82021-03-05 22:42:17294 out_path->len = output->length() - out_path->begin;
295 return success;
296}
297
Hayato Ito727115f2023-12-11 06:41:58298template <typename CHAR, typename UCHAR>
brettw@chromium.orge7bba5f2013-04-10 20:10:52299bool DoPath(const CHAR* spec,
vitalybuka@chromium.org0318f922014-04-22 00:09:23300 const Component& path,
Hayato Ito727115f2023-12-11 06:41:58301 CanonMode canon_mode,
brettw@chromium.orge7bba5f2013-04-10 20:10:52302 CanonOutput* output,
vitalybuka@chromium.org0318f922014-04-22 00:09:23303 Component* out_path) {
Hayato Ito727115f2023-12-11 06:41:58304 // URL Standard:
305 // - https://url.spec.whatwg.org/#path-start-state
306 // - https://url.spec.whatwg.org/#path-state
307
brettw@chromium.orge7bba5f2013-04-10 20:10:52308 bool success = true;
309 out_path->begin = output->length();
Tom Sepez2a0390182022-11-15 02:25:38310 if (path.is_nonempty()) {
brettw@chromium.orge7bba5f2013-04-10 20:10:52311 // Write out an initial slash if the input has none. If we just parse a URL
312 // and then canonicalize it, it will of course have a slash already. This
313 // check is for the replacement and relative URL resolving cases of file
314 // URLs.
Hayato Ito2579d832023-11-29 07:57:40315 if (!IsSlashOrBackslash(spec[path.begin])) {
brettw@chromium.orge7bba5f2013-04-10 20:10:52316 output->push_back('/');
Hayato Ito2579d832023-11-29 07:57:40317 }
brettw@chromium.orge7bba5f2013-04-10 20:10:52318
Hayato Ito727115f2023-12-11 06:41:58319 success = DoPartialPathInternal<CHAR, UCHAR>(spec, path, out_path->begin,
320 canon_mode, output);
321 } else if (canon_mode == CanonMode::kSpecialURL) {
322 // No input, canonical path is a slash for special URLs, but it is empty for
323 // non-special URLs.
324 //
325 // Implementation note:
326 //
327 // According to the URL Standard, for non-special URLs whose parsed path is
328 // empty, such as "git://host", the state-machine finishes in the
329 // `path-start-state` without entering the `path-state`. As a result, the
330 // url's path remains an empty array. Therefore, no slash should be
331 // appended.
brettw@chromium.orge7bba5f2013-04-10 20:10:52332 output->push_back('/');
333 }
334 out_path->len = output->length() - out_path->begin;
335 return success;
336}
337
338} // namespace
339
340bool CanonicalizePath(const char* spec,
vitalybuka@chromium.org0318f922014-04-22 00:09:23341 const Component& path,
Hayato Ito727115f2023-12-11 06:41:58342 CanonMode canon_mode,
brettw@chromium.orge7bba5f2013-04-10 20:10:52343 CanonOutput* output,
vitalybuka@chromium.org0318f922014-04-22 00:09:23344 Component* out_path) {
Hayato Ito727115f2023-12-11 06:41:58345 return DoPath<char, unsigned char>(spec, path, canon_mode, output, out_path);
346}
347
348bool CanonicalizePath(const char16_t* spec,
349 const Component& path,
350 CanonMode canon_mode,
351 CanonOutput* output,
352 Component* out_path) {
353 return DoPath<char16_t, char16_t>(spec, path, canon_mode, output, out_path);
354}
355
356bool CanonicalizePath(const char* spec,
357 const Component& path,
358 CanonOutput* output,
359 Component* out_path) {
360 return DoPath<char, unsigned char>(spec, path, CanonMode::kSpecialURL, output,
361 out_path);
brettw@chromium.orge7bba5f2013-04-10 20:10:52362}
363
Jan Wilken Dörrie5aad5c22021-03-08 21:44:12364bool CanonicalizePath(const char16_t* spec,
vitalybuka@chromium.org0318f922014-04-22 00:09:23365 const Component& path,
brettw@chromium.orge7bba5f2013-04-10 20:10:52366 CanonOutput* output,
vitalybuka@chromium.org0318f922014-04-22 00:09:23367 Component* out_path) {
Hayato Ito727115f2023-12-11 06:41:58368 return DoPath<char16_t, char16_t>(spec, path, CanonMode::kSpecialURL, output,
369 out_path);
brettw@chromium.orge7bba5f2013-04-10 20:10:52370}
371
372bool CanonicalizePartialPath(const char* spec,
vitalybuka@chromium.org0318f922014-04-22 00:09:23373 const Component& path,
Ben Kellyd18c0e82021-03-05 22:42:17374 CanonOutput* output,
375 Component* out_path) {
376 return DoPartialPath<char, unsigned char>(spec, path, output, out_path);
brettw@chromium.orge7bba5f2013-04-10 20:10:52377}
378
Jan Wilken Dörrie5aad5c22021-03-08 21:44:12379bool CanonicalizePartialPath(const char16_t* spec,
vitalybuka@chromium.org0318f922014-04-22 00:09:23380 const Component& path,
Ben Kellyd18c0e82021-03-05 22:42:17381 CanonOutput* output,
382 Component* out_path) {
Jan Wilken Dörrie5aad5c22021-03-08 21:44:12383 return DoPartialPath<char16_t, char16_t>(spec, path, output, out_path);
Ben Kellyd18c0e82021-03-05 22:42:17384}
385
386bool CanonicalizePartialPathInternal(const char* spec,
387 const Component& path,
Peter Kastingcfdf32c2022-08-17 20:21:02388 size_t path_begin_in_output,
Hayato Ito727115f2023-12-11 06:41:58389 CanonMode canon_mode,
Ben Kellyd18c0e82021-03-05 22:42:17390 CanonOutput* output) {
391 return DoPartialPathInternal<char, unsigned char>(
Hayato Ito727115f2023-12-11 06:41:58392 spec, path, path_begin_in_output, canon_mode, output);
Ben Kellyd18c0e82021-03-05 22:42:17393}
394
Jan Wilken Dörrie5aad5c22021-03-08 21:44:12395bool CanonicalizePartialPathInternal(const char16_t* spec,
Ben Kellyd18c0e82021-03-05 22:42:17396 const Component& path,
Peter Kastingcfdf32c2022-08-17 20:21:02397 size_t path_begin_in_output,
Hayato Ito727115f2023-12-11 06:41:58398 CanonMode canon_mode,
Ben Kellyd18c0e82021-03-05 22:42:17399 CanonOutput* output) {
Jan Wilken Dörrie5aad5c22021-03-08 21:44:12400 return DoPartialPathInternal<char16_t, char16_t>(
Hayato Ito727115f2023-12-11 06:41:58401 spec, path, path_begin_in_output, canon_mode, output);
brettw@chromium.orge7bba5f2013-04-10 20:10:52402}
403
vitalybuka@chromium.org0318f922014-04-22 00:09:23404} // namespace url