@@ -223,8 +223,12 @@ inline int hex_digit_to_int(char c) {
223
223
// If the next three characters are an escaped character then this function will
224
224
// also return what character is escaped.
225
225
bool GetEscapedChar (const std::string& src, size_t i,
226
- bool unescape_reserved_chars, bool unescape_slash_char,
227
- char * out) {
226
+ UrlUnescapeSpec unescape_spec, char * out) {
227
+ const bool unescape_slash_char =
228
+ unescape_spec == UrlUnescapeSpec::kAllCharacters ;
229
+ const bool unescape_reserved_chars =
230
+ (unescape_spec == UrlUnescapeSpec::kAllCharacters ) ||
231
+ (unescape_spec == UrlUnescapeSpec::kAllCharactersExceptSlash );
228
232
if (i + 2 < src.size () && src[i] == ' %' ) {
229
233
if (ascii_isxdigit (src[i + 1 ]) && ascii_isxdigit (src[i + 2 ])) {
230
234
char c =
@@ -246,15 +250,13 @@ bool GetEscapedChar(const std::string& src, size_t i,
246
250
// (as specified in RFC 6570) are not escaped if unescape_reserved_chars is
247
251
// false.
248
252
std::string UrlUnescapeString (const std::string& part,
249
- bool unescape_reserved_chars,
250
- bool unescape_slash_char) {
253
+ UrlUnescapeSpec unescape_spec) {
251
254
std::string unescaped;
252
255
// Check whether we need to escape at all.
253
256
bool needs_unescaping = false ;
254
257
char ch = ' \0 ' ;
255
258
for (size_t i = 0 ; i < part.size (); ++i) {
256
- if (GetEscapedChar (part, i, unescape_reserved_chars, unescape_slash_char,
257
- &ch)) {
259
+ if (GetEscapedChar (part, i, unescape_spec, &ch)) {
258
260
needs_unescaping = true ;
259
261
break ;
260
262
}
@@ -270,8 +272,7 @@ std::string UrlUnescapeString(const std::string& part,
270
272
char * p = begin;
271
273
272
274
for (size_t i = 0 ; i < part.size ();) {
273
- if (GetEscapedChar (part, i, unescape_reserved_chars, unescape_slash_char,
274
- &ch)) {
275
+ if (GetEscapedChar (part, i, unescape_spec, &ch)) {
275
276
*p++ = ch;
276
277
i += 3 ;
277
278
} else {
@@ -288,8 +289,7 @@ template <class VariableBinding>
288
289
void ExtractBindingsFromPath (const std::vector<HttpTemplate::Variable>& vars,
289
290
const std::vector<std::string>& parts,
290
291
std::vector<VariableBinding>* bindings,
291
- bool fully_decode_reserved_expansion,
292
- bool decode_slash_character) {
292
+ UrlUnescapeSpec unescape_spec) {
293
293
for (const auto & var : vars) {
294
294
// Determine the subpath bound to the variable based on the
295
295
// [start_segment, end_segment) segment range of the variable.
@@ -307,12 +307,13 @@ void ExtractBindingsFromPath(const std::vector<HttpTemplate::Variable>& vars,
307
307
// multi-part match by checking if it->second.end_segment is negative.
308
308
bool is_multipart =
309
309
(end_segment - var.start_segment ) > 1 || var.end_segment < 0 ;
310
+ const UrlUnescapeSpec var_unescape_spec =
311
+ is_multipart ? unescape_spec : UrlUnescapeSpec::kAllCharacters ;
312
+
310
313
// Joins parts with "/" to form a path string.
311
314
for (size_t i = var.start_segment ; i < end_segment; ++i) {
312
315
// For multipart matches only unescape non-reserved characters.
313
- binding.value += UrlUnescapeString (
314
- parts[i], fully_decode_reserved_expansion || !is_multipart,
315
- decode_slash_character || !is_multipart);
316
+ binding.value += UrlUnescapeString (parts[i], var_unescape_spec);
316
317
if (i < end_segment - 1 ) {
317
318
binding.value += " /" ;
318
319
}
@@ -345,7 +346,8 @@ void ExtractBindingsFromQueryParameters(
345
346
// in the request, e.g. `book.author.name`.
346
347
VariableBinding binding;
347
348
split (name, ' .' , binding.field_path );
348
- binding.value = UrlUnescapeString (param.substr (pos + 1 ), true , true );
349
+ binding.value = UrlUnescapeString (param.substr (pos + 1 ),
350
+ UrlUnescapeSpec::kAllCharacters );
349
351
bindings->emplace_back (std::move (binding));
350
352
}
351
353
}
@@ -456,11 +458,8 @@ Method PathMatcher<Method>::Lookup(
456
458
MethodData* method_data = reinterpret_cast <MethodData*>(lookup_result.data );
457
459
if (variable_bindings != nullptr ) {
458
460
variable_bindings->clear ();
459
- ExtractBindingsFromPath (
460
- method_data->variables , parts, variable_bindings,
461
- unescape_spec_ == UrlUnescapeSpec::kAllCharacters ||
462
- unescape_spec_ == UrlUnescapeSpec::kAllCharactersExceptSlash ,
463
- unescape_spec_ == UrlUnescapeSpec::kAllCharacters );
461
+ ExtractBindingsFromPath (method_data->variables , parts, variable_bindings,
462
+ unescape_spec_);
464
463
ExtractBindingsFromQueryParameters (
465
464
query_params, method_data->system_query_parameter_names ,
466
465
variable_bindings);
0 commit comments