简体   繁体   中英

How to deal with unencoded URL redirects to my website correctly?

We are using CleverReach to redirect people to our website after they have double opt-in their mail account. We redirect the email as a query parameter to our website, like: example.com/thanks?email=foo@bar.com (by setting up a redirect in the CleverReach backend like example.com/thanks?email={EMAIL} ). Apparently, the email parameter doesnt get urlencoded by cleverreach.

Now, in Drupal, if the URL is like so: example.com/thanks?email=hello+world@bar.com and using this code:

$request = \Drupal::request();
$email = $request->query->get('email');

$email is hello world@bar.com . Now, I dont know what the correct processing is here. Obviously, I cant tell CleverReach to urlencode their redirects beforehand. I dont even know if that would be best practice or if I need to imlement something...

The only thing I found out is that $_SERVER['QUERY_STRING'] contains the "real" string, which I can urlencode and then redirect, and then, by reading the query params, urldecode them. But I feel like I am missing some crucial inbuilt functionality.

TL;DR

If a website redirects to my website using not urlencoded query params, how do I read them?

My current approach:

<?php
public function redirectIfIllegalUri() {
  $request = \Drupal::request();
  $email = $request->query->get('email', '');

  $needsRedirect = (false !== strpos($email, ' ') || false !== strpos($email, '@'));

  if ($needsRedirect && isset($_SERVER['QUERY_STRING']) && false !== strpos($_SERVER['QUERY_STRING'], 'email=')) {

    $sqs = $_SERVER['QUERY_STRING'];
    $sqs = htmlspecialchars($sqs);
    $sqs = filter_var($sqs, FILTER_SANITIZE_STRING);
    $sqs = filter_var($sqs, FILTER_SANITIZE_ENCODED);
    $sqs = urldecode($sqs);
    $sqs = explode('&', $sqs);

    foreach ($sqs as $queryParam) {
      if (false === strpos($queryParam, 'email=')) continue;
      $values = explode('=', $queryParam);
      $email = $values[1];
    }

    $emailEncoded = urlencode($email);
    $query = $request->query->all();
    $query['email'] = $emailEncoded;

    $refreshUrl = Url::fromRoute('<current>');
    $refreshUrl->setOptions([
      'query' => $query,
    ]);

    $response = new RedirectResponse($refreshUrl->toString(), 301);
    $response->send();
    return;
  }
}

$request = \Drupal::request();
$email = urldecode($request->query->get('email', false));

drupal request() docs

The problem you are facing is that the + will be treated as a space when you get the value from $_GET global variable.

Currently in PHP doesn't exist a method that returns these values without urldecoding and you need to build a custom function to achieve what you are asking:

A simple function will return not encoded input is by using this function:

function get_params() {
    $getData = $_SERVER['QUERY_STRING'];
    $getParams = explode('&', $getData);

    $getParameters = [];
    foreach ($getParams as $getParam) {
        $parsed = explode('=', $getParam);
        $getParameters[$parsed[0]] = $parsed[1];
    }

    return $getParameters;
}

This solution can be used if you do not have any other option. By using this function you will always get the data encoded.

If you can encode the value from cleverreach then the best approach is to encode it there.

Encoding the value in cleverreach for email hello+world@bar.com will give you this url example.com/thanks?email=hello%2Bworld%40bar.com and in $_GET you will have the email containing the + sign.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM