Ampersands are being encoded as HTML instead of being URL friendly

Created on 5 September 2023, over 1 year ago

Problem/Motivation

When using a URI token that contains a query string as a linked field the ampersands (&) in the query string are being encoded as "&" which is not something a URL can handle. It breaks the query string.

Steps to reproduce

- Use a URLs URI token as a linked field value.
- Ensure the URL has a query string containing an &.
- View the rendered linked field.
- See that & are encoded as &.

Proposed resolution

When constructing the destination URL use htmlspecialchars_decode.
This should be pretty harmless since we are assuming it is just the URL,

🐛 Bug report
Status

Needs review

Version

1.0

Component

Code

Created by

🇨🇦Canada sstapleton

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @sstapleton
  • Status changed to Active over 1 year ago
  • @sstapleton opened merge request.
  • Status changed to Needs review over 1 year ago
  • 🇨🇦Canada sstapleton

    Merge request ready for review.

  • 🇩🇪Germany marcusx

    The problem comes from the token replacement with a plaintext string. Token does then escape the URL in the token value.

    see: Token.php

        // Each token value is markup if it implements MarkupInterface otherwise it
        // is plain text. Convert them, but only if needed. It can cause corruption
        // to render a string that's already plain text or to escape a string
        // that's already markup.
        foreach ($replacements as $token => $value) {
          if ($markup) {
            // Escape plain text tokens.
            $replacements[$token] = $value instanceof MarkupInterface ? $value : new HtmlEscapedText($value);
          }
          else {
            // Render markup tokens to plain text.
            $replacements[$token] = $value instanceof MarkupInterface ? PlainTextOutput::renderFromHtml($value) : $value;
          }
        }
    

    The correct fix is to mark the token as already sanitized markup.

    like:

    /**
     * Implements hook_tokens().
     */
    function my_module_tokens($type, $tokens, array $data = [], array $options = []) {
      $replacements = [];
    
      if ($type === 'my_module_type') {
        foreach ($tokens as $name => $original) {
          switch ($name) {
            case 'basepath':
              $replacements[$original] = Markup::create('https://something.dynamics.com/main.aspx');
              break;
    
            case 'config':
              $replacements[$original] = Markup::create('appid=1234&forceUCI=1&pagetype=entityrecord&etn=orb_object');
              break;
          }
        }
      }
    
      return $replacements;
    }
    
  • 🇩🇪Germany marcusx

    Setting this to → works as designed, as the issue is not in the linked_field module

Production build 0.71.5 2024