Problem/Motivation

Redirects with periods in the query string (.) have those converted to underscores (_). This is actually due to core's Url::fromUri() method's use of parse_str:

    if (!empty($uri_parts['query'])) {
      $uri_query = [];
      parse_str($uri_parts['query'], $uri_query);
      $uri_options['query'] = isset($uri_options['query']) ? $uri_options['query'] + $uri_query : $uri_query;
      unset($uri_parts['query']);
    }

Proposed resolution

Either provide a workaround in the Redirect module, or fix upstream. If this issue happens with manually created menu links in core, then I'd recommend fixing there, but otherwise this seems like something that only Redirect might encounter.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Comments

jhedstrom created an issue. See original summary.

jhedstrom’s picture

Status: Active » Needs review
StatusFileSize
new1.11 KB

Test-only patch to demonstrate the issue.

Status: Needs review » Needs work

The last submitted patch, 2: 3153360-02-TEST-ONLY.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

malte.koelle’s picture

StatusFileSize
new25.83 KB
new88.33 KB

The problem is that parse_str converts the query string to an array like this:

[
  special.chars='foo.bar'
  foo.bar='baz'
]

But PHP variables cannot contain dots, so it just converts it to underscores.

But this issue also appears with manually created links outside the redirect module.

Steps to reproduce:
- Create a content type with a Link Field.
- Create a node of the content type and add an internal link with query parameters. (example: /node/1?special.chars=foo.bar) 'LinksWhileEditing.png'
- After saving the node, the Link will be displayed with underscores instead of dots. (/node/1?special_chars=foo.bar) 'LinksAfterSaving.png'

Therefore I guess it would make sense to open a core issue.

jhedstrom’s picture

@malte.koelle thanks for that research! It does indeed seem like a core issue should be open since this impacts link fields (which by-design should allow any external link with query parameters to be used.)

aaronpinero’s picture

I think the problem is in Drupal/Core/Url.php, specifically line 307:

parse_str($uri_parts['query'], $uri_query);

The PHP manual states "Because variables in PHP can't have dots and spaces in their names, those are converted to underscores. Same applies to naming of respective key names in case of using this function with result parameter."

I'm surprised that this is a bug because it's come up before (in Drupal 7) and supposedly patched. See https://www.drupal.org/project/link/issues/1616752

aaronpinero’s picture

There are a few other places where this might also need to be corrected because of use of parse_str on query strings:

core/modules/views/src/Plugin/views/field/FieldPluginBase.php around line 1548

core/lib/Drupal/Component/Utility/UrlHelper.php around line 163

On my own site, I replaced the parse_str instruction in each place with some version of:

$query_pairs = explode("&", {{query_string}});
foreach ($query_pairs as $pair) {
$pair_array = explode("=", $pair);
if (count($pair_array) < 2) {
array_push($pair_array,'');
}
list($k, $v) = array_map("urldecode", $pair_array);
{{output_array}}[$k] = $v;
}

This code is a minor modification of the solution from the Drupal 7 Link module patch in the issue I referenced previously. Not sure if this is the most effective solution, but it did have the desired result on my own site.

In a search of core, there seem to be several other places where parse_str is being used on query strings, so there may be other places where the problem exists but doesn't affect my particular use case.

aaronpinero’s picture

I found this core issue which has patches for Drupal 8.9 and 9.1:
https://www.drupal.org/project/drupal/issues/2984272

aaronpinero’s picture