@@ -223,8 +223,12 @@ inline int hex_digit_to_int(char c) {
223223// If the next three characters are an escaped character then this function will
224224// also return what character is escaped.
225225bool 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 );
228232 if (i + 2 < src.size () && src[i] == ' %' ) {
229233 if (ascii_isxdigit (src[i + 1 ]) && ascii_isxdigit (src[i + 2 ])) {
230234 char c =
@@ -246,15 +250,13 @@ bool GetEscapedChar(const std::string& src, size_t i,
246250// (as specified in RFC 6570) are not escaped if unescape_reserved_chars is
247251// false.
248252std::string UrlUnescapeString (const std::string& part,
249- bool unescape_reserved_chars,
250- bool unescape_slash_char) {
253+ UrlUnescapeSpec unescape_spec) {
251254 std::string unescaped;
252255 // Check whether we need to escape at all.
253256 bool needs_unescaping = false ;
254257 char ch = ' \0 ' ;
255258 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)) {
258260 needs_unescaping = true ;
259261 break ;
260262 }
@@ -270,8 +272,7 @@ std::string UrlUnescapeString(const std::string& part,
270272 char * p = begin;
271273
272274 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)) {
275276 *p++ = ch;
276277 i += 3 ;
277278 } else {
@@ -288,8 +289,7 @@ template <class VariableBinding>
288289void ExtractBindingsFromPath (const std::vector<HttpTemplate::Variable>& vars,
289290 const std::vector<std::string>& parts,
290291 std::vector<VariableBinding>* bindings,
291- bool fully_decode_reserved_expansion,
292- bool decode_slash_character) {
292+ UrlUnescapeSpec unescape_spec) {
293293 for (const auto & var : vars) {
294294 // Determine the subpath bound to the variable based on the
295295 // [start_segment, end_segment) segment range of the variable.
@@ -307,12 +307,13 @@ void ExtractBindingsFromPath(const std::vector<HttpTemplate::Variable>& vars,
307307 // multi-part match by checking if it->second.end_segment is negative.
308308 bool is_multipart =
309309 (end_segment - var.start_segment ) > 1 || var.end_segment < 0 ;
310+ const UrlUnescapeSpec var_unescape_spec =
311+ is_multipart ? unescape_spec : UrlUnescapeSpec::kAllCharacters ;
312+
310313 // Joins parts with "/" to form a path string.
311314 for (size_t i = var.start_segment ; i < end_segment; ++i) {
312315 // 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);
316317 if (i < end_segment - 1 ) {
317318 binding.value += " /" ;
318319 }
@@ -345,7 +346,8 @@ void ExtractBindingsFromQueryParameters(
345346 // in the request, e.g. `book.author.name`.
346347 VariableBinding binding;
347348 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 );
349351 bindings->emplace_back (std::move (binding));
350352 }
351353 }
@@ -456,11 +458,8 @@ Method PathMatcher<Method>::Lookup(
456458 MethodData* method_data = reinterpret_cast <MethodData*>(lookup_result.data );
457459 if (variable_bindings != nullptr ) {
458460 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_);
464463 ExtractBindingsFromQueryParameters (
465464 query_params, method_data->system_query_parameter_names ,
466465 variable_bindings);
0 commit comments