I'm trying to redirect user to "userinfo.php" after successful registration, but the browser terminates the redirection because it goes into endless loops.

Moreover, I need your insight on if the script is secure or not.

I need your help, please. Thanks.

The following is the "register.php" script:

<?php

    // include configuration file
    require ("includes/config.php");

    //Class import for image uploading
    //classes is the map where the class file is stored (one above the root)
    include ("classes/upload/upload_class.php");

       // define variables and set to empty values
       $firstnameErr = $lastnameErr = $usernameErr = $genderErr = $passwordErr = $confirmationErr = $emailErr = $birthdayErr = $phoneErr = "";
      $firstname = $lastname = $username = $gender = $password = $confirmation = $email = $birthday = $phone = "";

    // if form was submitted
    if ($_SERVER["REQUEST_METHOD"] == "POST")
    {       
        $firstname = student_input($_POST["firstname"]);
        $lastname = student_input($_POST["lastname"]);
        $username = student_input($_POST["username"]);
        $gender = student_input($_POST["gender"]);
        $password = student_input($_POST["password"]);
        $confirmation = student_input($_POST["confirmation"]);
        $email = student_input($_POST["email"]);
        $birthday = student_input($_POST["birthday"]);
        $phone = student_input($_POST["phone"]);

            //This is the directory where images will be saved 
            $max_size = 160*170; // the max. size for uploading

            $my_upload = new file_upload;

            $my_upload->upload_dir = "images/user/"; // "files" is the folder for the uploaded files (you have to create this folder)
            $my_upload->extensions = array(".png", ".gif", ".jpeg", ".jpg"); // specify the allowed extensions here
            // $my_upload->extensions = "de"; // use this to switch the messages into an other language (translate first!!!)
            $my_upload->max_length_filename = 50; // change this value to fit your field length in your database (standard 100)
            $my_upload->rename_file = false;

            $my_upload->the_temp_file = $_FILES['userimage']['tmp_name'];
            $my_upload->the_file = $_FILES['userimage']['name'];
            $my_upload->http_error = $_FILES['userimage']['error'];
            $my_upload->replace = "y";
            $my_upload->do_filename_check = "n"; // use this boolean to check for a valid filename
            if ($my_upload->upload()) // new name is an additional filename information, use this to rename the uploaded file
            {
               $full_path = $my_upload->upload_dir.$my_upload->file_copy;
               $imagename = $my_upload->file_copy;
            }
            else
            {
              $imagename = "";
            }

        // validate submission
        if (empty($_POST["firstname"]))
        {
            $firstnameErr = "First name is required.";
        }
        if(empty($_POST["lastname"]))
        {
            $lastnameErr = "Last name is required.";
        }
        if(empty($_POST["username"]))
        {
            $usernameErr = "Username is required.";
        }
        if(!empty($_POST["username"]))
        { 
            // validate username
            if (!preg_match("/^[a-zA-Z0-9]*$/", $username))
            {
                $usernameErr = "Username must contain only letters and numbers.";
            }
            if (strlen($username) < 4 || strlen($username) > 15)
            {
                $usernameErr = "Username must be from 4 to 15 characters.";
            }
        }
        if(empty($_POST["gender"]))
        {
            $genderErr = "Gender is required.";
        }
        if(empty($_POST["password"]))
        {
            $passwordErr = "Enter a password.";
        }
        if(!empty($_POST["password"]))
        {           
            // validate password
            if (!preg_match("/^[a-zA-Z0-9]*$/", $password))
            {
                $passwordErr = "Password must contain letters, numbers and special characters.";
            }
            if (strlen($password) < 8 || strlen($password) > 20)
            {
                $passwordErr = "Password must be from 8 to 20 characters.";
            }
        }
        if (empty($_POST["confirmation"]))
        {
            $confirmationErr = "Confirm your password.";
        }
        if ($_POST["password"] != $_POST["confirmation"])
        {
            $confirmationErr = "Password and confirmation don't match.";
        }
        if(empty($_POST["email"]))
        {
            $emailErr = "Your email address is required.";
        }
        if(!filter_var($email, FILTER_VALIDATE_EMAIL))
        {
            $emailErr = "Invalid email format";
        }
        if(empty($_POST["birthday"]))
        {
            $birthdayErr = "Birthday is required.";
        }
        if(!empty($_POST["birthday"]))
        {
               $today = date("d-m-Y");
               $diff = date_diff(date_create($birthday), date_create($today));

               if($diff->format('%y%') < 6)
               {
                   $birthdayErr = "You must be at least 6 years old to register.";
               }
        }
        if(empty($_POST["phone"]))
        {
            $phoneErr = "Phone number is required.";
        }
        if(!empty($_POST["phone"]))
        {           
            // Don't allow country codes to be included (assumes a leading "+") 
            if (preg_match('/^(\+)[\s]*(.*)$/',$phone))
            {
                $phoneErr = "You should not include the country code.";
            }
            // Remove hyphens - they are not part of a telephone number
            $phone = str_replace ('-', '', $phone);

            // Now check that all the characters are digits
            if (!preg_match('/^[0-9]{10,11}$/',$phone))
            {
                $phoneErr = "Phone number should be either 10 or 11 digits";
            } 

            // Now check that the first digit is 0
            if (!preg_match('/^0[0-9]{9,10}$/',$phone))
            {
                $phoneErr = "The telephone number should start with a 0";
            }
        }
            try
            {   
            $stmt = $pdo->prepare("SELECT username, email, phone FROM users WHERE username = ? OR email = ? OR phone = ?");
            $stmt->execute([$username, $email, $phone]);
            $user = $stmt->fetch(); # get users data

            if($user["username"]==$username)
            {
                 $usernameErr="Sorry username already exists"; //check condition username already exists
            }
            else if($user["email"]==$email)
            {
                $emailErr="Sorry email already exists"; //check condition email already exists 
            }
            else if($user["phone"]==$phone)
            {
                 $phoneErr="Sorry, the phone number already exists"; //check condition email already exists 
            }
            else //check no "$error" shows, then continue
            {
                $new_password = password_hash($password, PASSWORD_DEFAULT); //encrypt password using password_hash()

               // insert form input into database           
               $result = "INSERT INTO users (firstname, lastname, username, gender, password, email, birthday, phone, regdate, userimage) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW(), ?)";
              $stmt= $pdo->prepare($result);
              $stmt->execute([$firstname, $lastname, $username, $gender, $new_password, $email, $birthday, $phone, $imagename]);

               // find out user's ID
           $stmt = $pdo->prepare("SELECT LAST_INSERT_ID() AS user_id");
               $stmt->execute();
               $user_id = $pdo->lastInsertId();

               // redirect to list users page
               header("Location: userinfo.php?id=".$user_id);
            }
         }
                catch(PDOException $e)
            {
                echo $e->getMessage();
            }       

}
        // render the header template
        include("templates/header.php");

        // render add user template
        include("templates/register-form.php");

       // render the footer template
       include("templates/footer.php");
?>

I do have the following redirect code in the "config.php":

    // require authentication for most pages
    if (!preg_match("{(admin/login|logout|register)\.php$}", $_SERVER["PHP_SELF"]))
    {
       if (empty($_SESSION["aid"]))
        {
           header("Location: login.php");
        }
    }
    if (!preg_match("{(?:index|login|logout|register|userinfo)\.php$}", $_SERVER["PHP_SELF"]))
    {
        if (empty($_SESSION["user_id"]))
        {
           header("Location: login.php");
        }
    }

@rproffitt,
I've modified line 177 you pointed out to the following:

// insert form input into database          
$stmt=$pdo->prepare("INSERT INTO users (firstname, lastname, username, gender, password, email, birthday, phone, regdate, userimage) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW(), ?)");
$stmt->execute([$firstname, $lastname, $username, $gender, $new_password, $email, $birthday, $phone, $imagename]);

While prepared statements are better, it still stores the unencrypted content (password and more) into the database. If this was my class, this area would be covered in depth then any code that did this would get a failing grade.

@rproffitt,
During my quick research, I saw a recommendation of PBKDF2 and HMAC-SHA-256, but no programmatic example I can easily understand. Please, do you have an example code for that?

Coming back to my original post regarding redirection, can you please, take a look at my "config.php" file and help me to understand why the redirection is going into endless loops, until terminated by browser:

    // require authentication for most pages
    if (!preg_match("{(admin/login|logout|register)\.php$}", $_SERVER["PHP_SELF"]))
    {
       if (empty($_SESSION["aid"]))
        {
           header("Location: login.php");
        }
    }
    elseif (!preg_match("{(?:index|login|logout|register)\.php$}", $_SERVER["PHP_SELF"]))
    {
        if (empty($_SESSION["user_id"]))
        {
           header("Location: login.php");
        }
    }
commented: There are numerous examples out there. Some what instant gratification, this takes more study. +15

My guess is there's something wrong with your regex. I'm not familiar enough with regex. What are the purposes of the {brackets} in the preg_match? For some reason preg_match() is being returned false even if the current script is login.php

@Dani, thanks for your time and input.

I can't seem to figure out what's causing the isssue. That's why I need help.

What made you think of using brackets in regex? Did you write the regex?

What if you try doing it a non-regex way?

if (
    stripos($_SERVER['PHP_SELF'], 'admin/login.php') === false &&
    stripos($_SERVER['PHP_SELF'], 'login.php') === false &&
    stripos($_SERVER['PHP_SELF'], 'logout.php') === false &&
    stripos($_SERVER['PHP_SELF'], 'register.php') === false
)

instead of

if (!preg_match("{(admin/login|logout|register)\.php$}", $_SERVER["PHP_SELF"]))

Get rid of the else if as well, and just check for both session variables not being present within the same if statement.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.