3

i am facing a problem with server side validation with php. The problem is that it always shows the validation error message even with valid values. For example on the username field if i enter something that contains no special symbols it still enters the if statement and shows the error message: "User name must not contains Special characters". The regex seems to be working fine so i think it is a logic fault. Here is my php code:

<?php

/**
 * Include our MySQL connection.
 */
require 'connect.php';

$error = '';
try {
//If the POST var "register" exists (our submit button), then we can
//assume that the user has submitted the registration form.
    if (isset($_POST['register'])) {

        $form = $_POST;
        $username = $form['username'];
        $password = $form['password'];
        $firstName = $form['firstName'];
        $lastName = $form['lastName'];
        $address = $form['address'];
        $email = $form['email'];
        $age = $form['age'];
        $phone = $form['phone'];
//Retrieve the field values from our registration form.
        $username = !empty($_POST['username']) ? trim($_POST['username']) : null;
        $password = !empty($_POST['password']) ? trim($_POST['password']) : null;

//TO ADD: Error checking (username characters, password length, etc).
//Basically, you will need to add your own error checking BEFORE
//the prepared statement is built and executed.
        //Validations username
        if (strlen($username) < 4 || strlen($username) > 8 || empty($username)) {
            throw new Exception("User name must be between 4 an 8 symbols.");
        }

        $patern = '[A-Za-z0-9]+';
        if (!preg_match($patern, $form['username'])) {
            throw new Exception("User name must not contains Special characters.");
        }
        $patern = '^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$';
        //Validation email
        if (!preg_match($patern, $email)) {
            throw new Exception("Please fill valid email.");
        }
        //Validation password
        if (strlen($password < 8 || strlen($password > 15) || empty($password))) {
            throw new Exception("Password must be between 8 an 15 symbols.");
        }
        $patern = '(?=(.*\d){2,})(?=.*[A-Z]{1,})(?=.*[a-zA-Z]{2,})(?=.*[!@~#$%^&?]{1,})[0-9a-zA-Z!@~#?$^%&`]{8,15}';
        if (!preg_match($patern, $password)) {
            throw new Exception("Password must contains at least 1 special symbol at least 1 uppercase letter at least 2 numbers at least 3 letters.");
        }
        if (strlen($password < 8 || strlen($password > 15) || empty($password))) {
            throw new Exception("Password must contains at least 1 special symbol at least 1 uppercase letter at least 2 numbers at least 3 letters.");
        }
        if (strlen($phone) != 10) {
            throw new Exception("Phone must be 10 numbers.");
        }
//Now, we need to check if the supplied username already exists.

//Construct the SQL statement and prepare it.
        $sql = "SELECT COUNT(username) AS num FROM users WHERE username = :username";
        $stmt = $pdo->prepare($sql);

//Bind the provided username to our prepared statement.
        $stmt->bindValue(':username', $username);

//Execute.
        $stmt->execute();

//Fetch the row.
        $row = $stmt->fetch(PDO::FETCH_ASSOC);

//If the provided username already exists - display error.
//TO ADD - Your own method of handling this error. For example purposes,
//I'm just going to kill the script completely, as error handling is outside
//the scope of this tutorial.
        if ($row['num'] > 0) {
            throw new Exception('That username already exists!');
        }
        $sql = "SELECT COUNT(email) AS test FROM users WHERE email = :email";
        $stmt = $pdo->prepare($sql);

//Bind the provided username to our prepared statement.
        $stmt->bindValue(':email', $email);

//Execute.
        $stmt->execute();

//Fetch the row.
        $result = $stmt->fetch(PDO::FETCH_ASSOC);

//If the provided username already exists - display error.
//TO ADD - Your own method of handling this error. For example purposes,
//I'm just going to kill the script completely, as error handling is outside
//the scope of this tutorial.
        if ($result['test'] > 0) {
            throw new Exception('That email already exists!');
        }
//Hash the password as we do NOT want to store our passwords in plain text.
        $passwordHash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 12));

//Prepare our INSERT statement.
//Remember: We are inserting a new row into our users table.
        $sql = "INSERT INTO users (username, password, email, phone, address, first_name, last_name, age) 
VALUES (:username, :password,:email, :phone, :address, :first_name, :last_name, :age)";
        $stmt = $pdo->prepare($sql);

//Bind our variables.
        $stmt->bindValue(':username', $username);
        $stmt->bindValue(':password', $passwordHash);
        $stmt->bindValue(':email', $email);
        $stmt->bindValue(':phone', $phone);
        $stmt->bindValue(':address', $address);
        $stmt->bindValue(':first_name', $firstName);
        $stmt->bindValue(':last_name', $lastName);
        $stmt->bindValue(':age', $age);

//Execute the statement and insert the new account.
        $result = $stmt->execute();

//If the signup process is successful.
        if ($result) {
            $_SESSION['username'] = $firstName;

            header('Location: login.php');

        }

    }
} catch (Exception $exception) {
    $error = $exception->getMessage();
}
?>

And the html form:

<form name="registration" action="#" method="post">
            <fieldset>
                <legend class="extraPlace">Register</legend>
                <?php if ($error) : ?>
                    <h2 style="color:red">   <?= $error ?></h2>
                <?php endif; ?>
                <?php $error = ''; ?>
                <div class="input-group margin col-lg-6">
                    <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
                    <input class="form-control" id="username" name="username" type="text" placeholder="Username *"
                           minlength="4" maxlength="8" min="4" required>

                </div>

                <div class="input-group margin">
                    <span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
                    <input class="form-control" id="password" name="password" type="password" placeholder="Password *"
                           maxlength="15" minlength="8" required>

                    <span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
                    <input class="form-control" id="confirm_password" name="confirmPass" type="password"
                           placeholder="Confirm Password *" required>

                </div>

                <div class="input-group margin">
                    <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
                    <input class="form-control" id="firstName" name="firstName" type="text" placeholder="First Name *"
                           required>

                    <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
                    <input class="form-control" id="lastName" name="lastName" type="text" placeholder="Last Name *"
                           required>
                </div>

                <div class="input-group margin col-lg-6">
                    <span class="input-group-addon"><i class="glyphicon glyphicon-envelope"></i></span>
                    <input class="form-control" id="email" name="email" type="email" placeholder="Email *" required>
                </div>

                <div class="input-group margin col-lg-6">
                    <span class="input-group-addon"><i class="glyphicon glyphicon-phone-alt"></i></span>
                    <input class="form-control" id="phone" name="phone" type="number" maxlength="10"
                           placeholder="Phone Number *" required>
                </div>

                <div class="input-group margin col-lg-6">
                    <span class="input-group-addon"><i class="glyphicon glyphicon-home"></i></span>
                    <input class="form-control" id="address" name="address" type="text" placeholder="Address *"
                           required>
                </div>

                <div class="input-group margin col-lg-6">
                    <span class="input-group-addon"><i class="glyphicon glyphicon-time"></i></span>
                    <input class="form-control" id="age" name="age" type="number" placeholder="Age *" min="18" required>
                </div>

                <div class="checkbox alignLeftContent">
                    <label>
                        <input type="checkbox" name="agreement" value="1" required> I have read and agree to the <a
                                href="https://www.un.org/Depts/ptd/terms-and-conditions-agreement">Terms and Conditions
                            *</a>
                    </label><br>
                    <label>
                        <input type="checkbox" name="gdpr" value="1" required> GDPR Agreement *
                    </label>
                    <div class="margin"><span>* &nbsp;&nbsp; Mandatory fields</span></div>
                </div>

                <button class="btn btn-success " type="submit" name="register">Register</button>
            </fieldset>
        </form>
6
  • to - $patern = '/[A-Za-z0-9]+/'; Commented Mar 22, 2018 at 11:13
  • Changed it, but still does the same. Commented Mar 22, 2018 at 11:16
  • 1
    to - $patern = '/[A-Za-z0-9]+/'; Commented Mar 22, 2018 at 11:17
  • How do you call you server side script? You use GET or POST method? Commented Mar 22, 2018 at 11:22
  • Oh sorry, I just discovered it is POST. The problem is somewhere else then... :) Commented Mar 22, 2018 at 11:23

2 Answers 2

5

The problem is with your regex:

$patern = '[A-Za-z0-9]';

You are missing the delimiters and you should fix the pattern to the start and the end as now it will only fail if the string contains only invalid characters:

$patern = '#^[A-Za-z0-9]+$#';
                          ^ delimiter
                         ^ end of string
                        ^ 1 or more characters
            ^ beginning of string
           ^ delimiter

Alternatively you could search for invalid characters instead by inverting the character group:

$patern = '#[^A-Za-z0-9]#';
//           ^ negate the character class
// or case insensitive
$patern = '#[^a-z0-9]#i';

// Change the condition
if (preg_match($patern, $form['username'])) {
    // At least 1 invalid character found
Sign up to request clarification or add additional context in comments.

2 Comments

That fixed it, but why put the delimeter '#' at start and end?
@TwinAxe96 That is required in preg_*, see php.net/manual/en/regexp.reference.delimiters.php
0
$patern = '#[^a-z0-9]#i';

        if (preg_match($patern, $form['username'])) {
            throw new Exception("User name must not contains Special characters.");
        }

just replace this block

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.