Home > Software engineering >  Why my regex inside a function doesn't work in PHP?
Why my regex inside a function doesn't work in PHP?

Time:05-22

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.

CodePudding user response:

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.

CodePudding user response:

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. To avoid this you must escape the dash character with \

Example:

/[A-Za-z0-9\-_]{5,15}/

CodePudding user response:

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.

  • Related