Why my regex inside a function doesn't work in PHP?

94 Views Asked by At

I've to validate some data in my form, none of them works but i'd like some help for the username validation hoping that I can fix the other problems later.

So here is my form, nothing unusual :

<form action="inscription_traitement.php" method="post">
    <label>Nom d'utilisateur : </label><br/>
    <input type="text" name="username"/>
    <label>Adresse e-mail : </label><br/>
    <input type="text" name="mail"/>
    <label>Mot de passe : </label><br/>
    <input type="password" name="password"/>
    <label>Répétez votre mot de passe : </label><br/>
    <input type="password" name="password_r"/>
    <input type="submit" name="submit" value="S'inscrire"/><input type="reset" value="Annuler"/>
</form>

Then that redirect to my validation file (the problem is in invalidUsername()):

<?php
if (isset($_POST["submit"])){
    
    $username = $_POST["username"];
    $mail = $_POST["mail"];
    $password = $_POST["password"];
    $password_r = $_POST["password_r"];
    

    require_once "database_connection.php";
    require_once "functions.php";


    // Here is the problem
    if(invalidUsername($username) !== false){
        header("Location: inscription.php?error=invalid_username");
        exit();
    }
    if(usernameExists($db, $username) !== false){
        header("Location: inscription.php?error=username_exists");
        exit();
    }
    if(invalidMail($mail) !== false){
        header("Location: inscription.php?error=invalid_mail");
        exit();
    }
    if(mailExists($db, $mail) !== false){
        header("Location: inscription.php?error=mail_exists");
        exit();
    }
    if(invalidPassword($password) !== false){
        header("Location: inscription.php?error=invalid_password");
        exit();
    }
    if (passwordMatch($password, $password_r) !== false){
        header("Location: inscription.php?error=password_match");
        exit();
    }

    createUser($db, $username, $mail, $password);
}
else{
    header("location: inscription.php");
}?>

And finally i created a file that regroups all my functions, the one we are interested in is invalidUsername():

<?php

// here is the problem
function invalidUsername($username){
    $usernameRegex = "/[A-Za-z0-9-_]{5,15}/";
    if(!preg_match($usernameRegex, $username)){
        return true;
    }else{
        return false;
    }
}

function usernameExists($db, $username){
    $username = mysql_real_escape_string($username);
    $query = mysql_query("SELECT * FROM player WHERE p_username = ".$username.";");
    try{
        $stmt = $db->prepare($query);
        $stmt->execute();
    }catch(PDOException $e){
        header("Location: inscription.php?error=\".$e.\"");
        return true;
    }
    return false;
}

function invalidMail($mail){
    if(!filter_var($mail, FILTER_VALIDATE_EMAIL)){
        return true;
    }else{
        return false;
    }
}

function mailExists($db, $mail){
    $query = "SELECT * FROM player WHERE p_mail_adress = ?;";
    $stmt = $db->prepare($query);
    try{
        $stmt->execute(array($mail));
    }catch(Exception $e){
        header("Location: inscription.php?error=stmt_error");
        return true;
    }
    return false;
}

function invalidPassword($password){
    $passwordRegex = "/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,20}$/";
    if(!preg_match($passwordRegex, $password)){
        return true;
    }else{
        return false;
    }
}

function passwordMatch($password, $password_r){
    if($password != $password_r){
        return true;
    }else{
        return false;
    }
}

function createUser($db, $username, $mail, $password){
    $ip_adress = $_SERVER['REMOTE_ADDR'];
    $query = "INSERT INTO player(p_username, p_mail_adress, p_password, p_ip, p_score, p_is_online) VALUES(?, ?, ?, ?, ?, ?);";
    $stmt = $db->prepare($query);
    try{
        $stmt->execute(array($username, $mail, $password, $ip_adress, 0, 0));
    }catch(Exception $e){
        header("Location: inscription.php?error=$e");
    }
    header("Location: inscription.php?bienvenu");
}?>

The problem is the following : the invalidUsername() function return me true (meaning that the validation did not pass) all the time, even if i put correct data in my username field. I tried my regex online and it works. I can't understand where I messed up and the logic seems good to me.

I use Easyphp Devserver 17 if it can help you.

4

There are 4 best solutions below

0
Ali Duman On BEST ANSWER

I found the solution with your help. In my validation file I called "database_connection.php", the variable $username and $password was overwriting my variable in my validation file :

<?php
    $hostname  = "localhost";
    $database   = "db_name";
    $username  = "root";
    $password   = "";
    try
    {
        $db = new PDO('mysql:host='.$hostname.';dbname='.$database, $username, $password);    
    }
    catch(Exception $e)
    {
        die('Erreur : '.$e->getMessage());
    }
?>

There is one thing to do :
Changing the variable name in my "database_connection.php" :

$db_username  = "root";
$db_password   = "";

Or you can redefine your variable in your functions, which is not recommended :

<?php
     $username = $_POST["username"];
     function invalidUsername($username){
          $usernameRegex = "/^[\w-]{5,15}$/D";
          return (bool)preg_match($usernameRegex, $username);
     }
?>
1
Levi On

The dash character matches characters from X to Y:

a-z = match from "a" to "z"
0-9 = match from "0" to "9"

The last dash is interpreted the same way:

9-_ = match from "9" to "_"

This is obviously nonsense. You can fix this by placing the dash at the end.

/[A-Za-z0-9_-]{5,15}/
1
Damiano93 On

Regex:

[0-9]  # A single digit
[_]    # An underscore 
[0-9]  # A single digit

According to PHP manual:

preg_match() returns 1 if the pattern matches given subject, 0 if it does not, or false on failure.

I recommend online preg_match editor: https://www.phpliveregex.com/#tab-preg-match

This will solve your problems. I am not able to verify what string parameters you provide.

3
Wiktor Stribiżew On

There are two issues:

  • The hyphen placement inside a character class is strict in the latest PHP versions, it should be located either at the start of end of the pattern to avoid any issues
  • The pattern must be anchored, i.e. it must match the entire string, else, the {5,15} limiting quantifier makes little sense.

You need to use

function invalidUsername($username){
    $usernameRegex = "/^[\w-]{5,15}$/D";
    return (bool)preg_match($usernameRegex, $username));
}

Details:

  • ^ - start of string
  • [\w-]{5,15} - five to fifteen ASCII letters, digits, underscores or hyphens
  • $ - end of string
  • D - the flag means that the end of string $ anchor matches only at the end of string.