strpos () not behaving as it should

0
strpos () is not behaving as it should, it always returns FALSE even with the two strings containing the value of the $ Czech variable.

<?php
$checa = "https://www.site.com.br/";

$url_ref = $_GET['url_ref']; // Recebe: https://www.site.com.br/login/usuarios/

if( strpos( $url_ref, $checa ) !== false ) {
    echo "Confere" . "<br>\n";
} else {
    echo "Não confere" . "<br>\n";
}
?>

It is always returning FALSE.

If I change the variable, it also gives FALSE

<?php
$checa = "Qualquer coisa";

$url_ref = $_GET['url_ref']; // Recebe: https://www.site.com.br/login/usuarios/

if( strpos( $url_ref, $checa ) !== false ) {
    echo "Confere" . "<br>\n";
} else {
    echo "Não confere" . "<br>\n";
}
?>
    
asked by anonymous 06.09.2018 / 21:56

1 answer

6

First that validate URLs so the chance to fail is extremely high, following problem points:

  • strpos only case-sensitive Czech
  • strpos "can" (depends on how you use) crash depending on case
  • strpos will not differentiate https from http
  • strpos will not ignore spaces at beginning and end

Other issues:

  • Missing isset or empty
  • strpos( $url_ref, $checa ) !== false only checks whether or not, the "correct" (theoretically) would be to use with "ZERO" strpos( $url_ref, $checa ) === 0) { echo 'confere'

A suggestion, whether to validate URL by domain, then use parse_url (and trim ) to remove spaces, a revised code:

<?php
$checa = "www.site.com.br"; //Sem http, sem https

if (empty($_GET['url_ref'])) {
    echo "Vazio ou não definido<br>\n"; //Customize a mensagem de erro
} else {
    $url = trim($_GET['url_ref']);

    if ($url == '') {
         echo "Vazio<br>\n"; //Customize a mensagem de erro
    } else {
         $scheme = parse_url($url, PHP_URL_SCHEME);

         if (!in_array($scheme, array('http', 'https'))) {
              echo "Não é HTTP(S)<br>\n"; //Customize a mensagem de erro
         } else {
              $host = parse_url($url, PHP_URL_HOST);

              if ($host === $checa) {
                  echo "Confere<br>\n";
              } else {
                  echo "Não confere<br>\n";
              }
         }
    }
}

With regex (preg_match)

Of course I could use regex too, which would even reduce the code a little, like this:

<?php
//NÃO passe o http, sem https
//preg_quote escapa caracteres que podem after a regex, no exemplo converte pontos em '\.'
$checa = preg_quote("www.site.com.br");

if (empty($_GET['url_ref'])) {
    echo "Vazio ou não definido<br>\n"; //Customize a mensagem de erro
} elseif (preg_match("#^https?://{$checa}(/|$)#", trim($_GET['url_ref']))) {
    echo "Confere<br>\n";
} else {
    echo "Não confere<br>\n";
}

Explaining the regex:

^https?://www\.site\.com\.br(/|$)
 ^         ^                 ^
 |         |                 |
 |         |                 |
 |         |                 +--- Checa se tem barra '/', se não tiver deve ser o final das string, caso contrário é uma dominio invalido
 |         |
 |         +--- Url passada na variavel, ela esta com \. no lugar de pontos, porque '.' é um caractere usado para expressões regulares, então o preg_quote o escapou
 |
 +--- Verifica se começa com HTTP ou HTTPS, o '?' após o 's' faz ele ser "opcional"
    
06.09.2018 / 22:17