Improvements To Member Registration Site Reg.php

@uniqueideaman no offense, i saw you flooding this forum with random questions and comments, but i never see any code you type, even a some basic script.

I see you asked a questions, and i commented code and most of it is self explain code, just need learn to read and think a bit :smiley:

This way you can’t teach anything.

First make something, test, ask question.

1 Like

Hello Mates,

I am getting these irrelevant errors. Do you mind checking if you get the same on your Xampp ?

Member Reg & Login script

config.php


<?php

/*
*	ERROR HANDLING
*	ini_set('display_errors', 1);
*   ini_set('display_startup_errors', 1);

*	For All Error, Warning and Notice
*   error_reporting(E_ALL); OR error_reporting(-1);
*	For All Errors
*   error_reporting(E_ERROR);
*	For All Warnings
*   error_reporting(E_WARNING);
*	For All Notice
*   error_reporting(E_NOTICE);
*/
error_reporting(E_ALL);

// session start
session_start();

// include files
include 'conn.php';
include 'site_details.php';

// include functions
include 'functions.php';

?>

functions.php


<?php
// functions file

/*
* check if user is logged by checking if session named "user" isset
* return true if session "user" exists or false if not exists
*/
function is_logged() {
	if (isset($_SESSION["user"]) && !empty($_SESSION["user"])) {
		return true;
	} else {
		return false;
	}
}
?>

site_details.php


<?php

$site_name = "Programmer's Haven";
$site_domain = "domain.com";
$site_admin_email = "programmers_haven_admin@domain.com";

?>

reg.php


<?php

// config.php contains reference to site_details.php (which contains details such as site name, site domain, webmaster email) and conn.php (which contains db connection details).
include 'config.php';

// Check if user is already logged in or not.
if (is_logged() === true) {
	die("You are logged in, can't register.");
}

if ($_SERVER['REQUEST_METHOD'] == "POST")
{
	if (isset($_POST["username"]) && 
	   isset($_POST["password"]) &&
	   isset($_POST["password_confirmation"]) && 
	   isset($_POST["email"]) && 
	   isset($_POST["email_confirmation"]) && 
	   isset($_POST["forename"]) && 
	   isset($_POST["gender"]) &&
	   isset($_POST["surname"])) {

		// Create random hash for email confirmation.
	   	$member_registration_random_numbers = sha1(mt_rand(5, 30));

	   	// Account activation link that will verify email.
		$account_activation_link = "http://www.'".$site_domain."'.com/$site-name/activate_account.php?email='".$_POST['email']."'&hash='".$member_registration_random_numbers."'";

   		// Remove space in start of string.
   		/*
		*	Passwords and email are leaved unescaped here because
		*	if you put them into mysqli_real_escape_string they are not empty.
   		*/
        $username 	= trim(mysqli_real_escape_string($conn, $_POST["username"]));
		$password 	= $_POST["password"];
		$password2 	= $_POST["password_confirmation"];
        $forename 	= trim(mysqli_real_escape_string($conn, $_POST["forename"]));
        $surname 	= trim(mysqli_real_escape_string($conn, $_POST["surname"]));
		$gender 	= trim(mysqli_real_escape_string($conn, $_POST["gender"]));
        $email 		= $_POST["email"];
        $email_confirmation = $_POST["email_confirmation"];
        $email2 	= trim(mysqli_real_escape_string($conn, $email)); // Escaped email for inserting into database
        $activation = 0; // 1 = active | 0 = not active

        // Hashed password.
        $hashed_pass = password_hash($password, PASSWORD_DEFAULT); 
	
        // Select username and email to check if they exist or not.
		$stmt = mysqli_prepare($conn, "SELECT usernames, emails FROM users WHERE usernames = ? OR emails = ?");
		mysqli_stmt_bind_param($stmt, 'ss', $username, $email);
		mysqli_stmt_execute($stmt);
		$result = mysqli_stmt_get_result($stmt);

        $row = mysqli_fetch_array($result, MYSQLI_ASSOC);

		// check if username is registered
		if ($row['Usernames'] == $username) {
			$_SESSION['error'] = "That username is already registered.";
		// check if username is between 6 and 30 characters long
		} elseif (strlen($username) < 6 || strlen($username) > 30) {
			$_SESSION['error'] = "Username must be between 6 and 30 characters long.";
		// check if email is registered
		} elseif ($row['Emails'] == $email) {
			$_SESSION['error'] = "That email is already registered.";
		// check if emails match
		} elseif ($email != $email_confirmation) {
			$_SESSION['error'] = "Emails don't match.";
		// check if email is actual email
		} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
			$_SESSION['error'] = "Invalid email format.";
		// check if passwords match
		} elseif ($password != $password2) {
			$_SESSION['error'] = "Passwords don't match.";
		// check if password lenght is between 6 and 30 charaters long
		} elseif (strlen($password) < 6 || strlen($password) > 30) {
			$_SESSION['error'] = "Password must be between 6 and 30 characters long.";
		} else {

			// insert query with mysqli prepared statement
			$stmt = mysqli_prepare($conn, "INSERT INTO users(usernames, passwords, emails, forenames, surnames, genders, account_activation_codes, account_activations) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
			mysqli_stmt_bind_param($stmt, 'sssssssi', $username, $hashed_pass, $email2, $forename, $surname, $gender, $member_registration_random_numbers, $activation);
			mysqli_stmt_execute($stmt);

			// check if query is inserted
			if (mysqli_stmt_insert_id($stmt)) {
				echo "<h3 style='text-align:center'>Thank you for your registration.<br /> Redirecting to login page ...</h3>";

				// Redirect to login page after 5 seconds
				header("refresh:5;url=login.php");

				// Empty $_SESSION['error'] variable so no more in use, its empty now.
				unset($_SESSION['error']);
				unset($_POST);
				exit(); 

				// Email sent to new user with account activation link.
				$to = $email;
			    $subject = "Your '".$site_name."' Account Activation!";
			    $body = $forename.' '.$surname."\n\n You need to click the following link to confirm your email address and activate your account.\n\n\
			    $account_activation_link";
				$from = $site_admin_email;
			    $headers = "from: " . $from;
			
			    if (mail($to,$subject,$body,$headers)) {
			    	$_SESSION['error'] = "Registration sucessfuly. Check your email for further instructions!";
			    } else {
			    	$_SESSION['error'] = "Email not sent, please contact website administrator.";
			    }
			    */
			} else {
				$_SESSION['error'] = "There was a problem with registering, please try again.";
			}

	    }
	}
}


?>
<!DOCTYPE html>
<html>
	<head>
		<title><?php $site_name ?> Signup Page</title>
	</head>
<body>
<div class ="container">

<?php

// error messages
if (isset($_SESSION['error']) && !empty($_SESSION['error'])) {
	echo '<p style="color:red;">'.$_SESSION['error'].'</p>';
}

?>

<form method="post" action="">
	<center><h2>Signup Form</h2></center>
	<div class="form-group">
		<center><label>Username:</label>
		<input type="text" placeholder="Enter a unique Username" name="username" required [A-Za-z0-9] value="<?php if(isset($_POST['username'])) { echo htmlentities($_POST['username']); }?>"></center>
	</div>
	<div class="form-group">
		<center><label>Password:</label>
		<input type="password" placeholder="Enter a new Password" name="password" required [A-Za-z0-9]></center>
	</div>
	<div class="form-group">
		<center><label>Repeat Password:</label>
		<input type="password" placeholder="Repeat a new Password" name="password_confirmation" required [A-Za-z0-9]></center>
	</div>
	<div class="form-group">
		<center><label>First Name:</label>
		<input type="text" placeholder="Enter your First Name" name="forename" required [A-Za-z] value="<?php if(isset($_POST['forename'])) { echo htmlentities($_POST['forename']); }?>"></center>
	</div>
	<div class="form-group">
		<center><label>Surname:</label>
		<input type="text" placeholder="Enter your Surname" name="surname" required [A-Za-z] value="<?php if(isset($_POST['surname'])) { echo htmlentities($_POST['surname']); }?>"></center>
	</div>
	<div class="form-group">
		<center><label>Gender:</label>
		<input type="radio" name="gender" value="male" <?php if(isset($_POST['gender'])) { echo 'checked'; }?> required>Male<input type="radio" name="gender" value="female" <?php if(isset($_POST['gender'])) { echo 'checked'; }?> required>Female</center>
	</div>
	<div class="form-group">
		<center><label>Email:</label>
		<input type="email" placeholder="Enter your Email" name="email" required [A-Za-z0-9] value="<?php if(isset($_POST['email'])) { echo htmlentities($_POST['email']); }?>"></center>
	</div>
	<div class="form-group">
		<center><label>Repeat Email:</label>
		<input type="email" placeholder="Repeat your Email" name="email_confirmation" required [A-Za-z0-9] value="<?php if(isset($_POST['email_confirmation'])) { echo htmlentities($_POST['email_confirmation']); }?>"></center>
	</div>
	<center><button type="submit" class="btn btn-default" name="submit">Register!</button></center>
	<center><font color="red" size="3"><b>Already have an account ?</b><br><a href="login.php">Login here!</a></font></center>

</form>

</div>
</body>
</html>

login.php


<?php
include 'config.php';

// check if user is already logged in
if (is_logged() === true) {
	die("You are already logged in.");
}

if ($_SERVER['REQUEST_METHOD'] == "POST")
{
	if (isset($_POST["username_or_email"]) && isset($_POST["password"])) {

		$username = $_POST["username_or_email"];
		$email = $_POST["username_or_email"];
		$password = $_POST["password"];

		$stmt = mysqli_prepare($conn, "SELECT Usernames, Passwords, Emails, Account_Activation_Codes, Account_Activations FROM users WHERE Usernames = ? OR Emails = ?");
		mysqli_stmt_bind_param($stmt, 'ss', $username, $email);
		mysqli_stmt_execute($stmt);
		$result = mysqli_stmt_get_result($stmt);

        $row = mysqli_fetch_array($result, MYSQLI_ASSOC);
		
		// check for username and password matching
        if ($username == $row['Usernames']  || $email == $row['Emails'] && password_verify($password, $row['Passwords'])) {

        	/* 
        	* Check if user has activation link in database, if it has then he has not activated his account
        	* or
			* check if user Activation_Accounts is set to 1 its active and 0 is not active.
			*/
        	if ($row['Account_Activation_Codes'] != '' || $row['Account_Activations'] == '0') {
        		$error = "You didn't activate your account. Please check your email.";
        	} else {		

	        	// if remember me check box is checked set cookie
	        	if (isset($_POST['remember']) && $_POST['remember'] == "on") {
	        		/*
					* if you want to set cookie, set only hash and store it into database
					* when you come on login page you need to check  if that hash from cookie exists in database
					* if it exist just start session
					* NEVER STORE USERNAMES, EMAILS, PASSWORDS AND OTHER USER INFORMATION IN COOKIE
					*/

	        		//setcookie("username_or_email", $username_or_email, time()+ (10 * 365 * 24 * 60 * 60));
					//setcookie("password", $password, time()+ (10 * 365 * 24 * 60 * 60));
	        	} else {
	        		// start session
	        		$_SESSION["user"] = $username;
	        		$_SESSION["user"] = $email;

	        		// redirect to member page
	        		header("Location: home.php");
	        		exit();
	        	}

	        }
					
	    } else {
            $error = "Invalid username or password.";
        }		
	}
}	

?>
<!DOCTYPE html>
<html>
	<head>
		<title><?php $site_name?> Member Login Page</title>
	</head>
<body>
<div class="container">
	<form method="post" action="">
	<h3 style="text-align:center;"><?php $site_name ?> Member Login Form</h3>

	<?php if(!empty($error)) { echo '<p style="color:red; text-align:center;">'.$error.'</p>'; } ?>

		<div class="form-group">
			<center><label>Username/Email:</label>
			<input type="text" placeholder="Enter Username or Email" name="username_or_email" required></center>
		</div>
		<div class="form-group">
			<center><label>Password:</label>
			<input type="password" placeholder="Enter password" name="password" required></center>
		</div>
		<div class="form-group">
			<center><label>Remember Login Details:</label>
			<input type="checkbox" name="remember"></center>
		</div>
		<div class="form-group">
			<center><input type="submit" name="submit" value="Login" class="button button-success"></center>
		</div>

		<div class="form-group">
			<center><font color="red" size="3"><b>Forgot your password ?</b><br><a href="member_login_password_reset.php">Reset it here!</a></font></center>
			<center><font color="red" size="3"><b>Not registered ?</b><br><a href="register.php">Register here!</a></font></center>
		</div>
	</form>
</div>
</body>
</html>

I am getting these absurd errors on reg.php:

Notice: Undefined variable: site in C:\xampp\htdocs.….…\register.php on line 24
Warning: mysqli_stmt_bind_param() expects parameter 1 to be mysqli_stmt, boolean given in C:\xampp\htdocs.….…\register.php on line 78
Warning: mysqli_stmt_execute() expects parameter 1 to be mysqli_stmt, boolean given in C:\xampp\htdocs.….…\register.php on line 79
Warning: mysqli_stmt_insert_id() expects parameter 1 to be mysqli_stmt, boolean given in C:\xampp\htdocs.….…\register.php on line 82

And these errors on the login.php:

Warning: mysqli_stmt_bind_param() expects parameter 1 to be mysqli_stmt, boolean given in C:\xampp\htdocs.….…\login.php on line 18
Warning: mysqli_stmt_execute() expects parameter 1 to be mysqli_stmt, boolean given in C:\xampp\htdocs.….…\login.php on line 19
Warning: mysqli_stmt_get_result() expects parameter 1 to be mysqli_stmt, boolean given in C:\xampp\htdocs.….…\login.php on line 20
Warning: mysqli_fetch_array() expects parameter 1 to be mysqli_result, null given in C:\xampp\htdocs.….…\login.php on line 22

Apart from the error codes. I believe the script is now sql injection free and the password hashing is sound. What is your opinion ?

What you changed into script, there was no any errors, i tested it few times ?

Spot the typo:

$account_activation_link = "http://www.'".$site_domain."'.com/$site-name/activate_account.php?email='".$_POST['email']."'&hash='".$member_registration_random_numbers."'";

(ETA: multiple typos there - there is a problem with your quotes in the line above, even when you’ve corrected the main one)

Usually, something like:

means that the previous sql statement has failed, and returned false instead of returning an object such a reference to a prepared statement, or a result set. I think the specific one above is immediately after a prepare(), though I might have lost count while trying to find line 78 and you didn’t highlight it. So, if that’s the correct line, look for syntax errors in the query - commas in the wrong place, incorrect column names, etc.

I’ve mentioned highlighting line numbers before when posting errors at specific lines, and it’s particularly important here when the code you post doesn’t seem to line up exactly with the error messages. The first error in line 18 in login.php isn’t line 18 in your code, so we have to guess that it’s actually line 15 and presume the difference is not material to the error.

1 Like

On line 40, your code was:

    $activation = 1; // 1 = active | 0 = not active

I changed it to:

    $activation = 0; // 1 = active | 0 = not active

Originally, that variable is supposed to be set to zero. Only when the user has clicked the account activation link and confirmed his email then it is supposed to switch to “1”. I assumed it was a typo on your part. Afterall, you were busy when you were dealing with this script.
Apart from that, I have not changed anything in the script you gave me.

Thanks. :slight_smile:

I’m having trouble finding the lines in the post box in this forum in order to highlight the lines. Therefore, I do not have any other options but to just list below the lines where the errors occur:

I am getting these absurd errors on reg.php:

Notice: Undefined variable: site in C:\xampp\htdocs…\register.php on line 24
Warning: mysqli_stmt_bind_param() expects parameter 1 to be mysqli_stmt, boolean given in C:\xampp\htdocs…\register.php on line 78
Warning: mysqli_stmt_execute() expects parameter 1 to be mysqli_stmt, boolean given in C:\xampp\htdocs…\register.php on line 79
Warning: mysqli_stmt_insert_id() expects parameter 1 to be mysqli_stmt, boolean given in C:\xampp\htdocs…\register.php on line 82

And these errors on the login.php:

Warning: mysqli_stmt_bind_param() expects parameter 1 to be mysqli_stmt, boolean given in C:\xampp\htdocs…\login.php on line 18
Warning: mysqli_stmt_execute() expects parameter 1 to be mysqli_stmt, boolean given in C:\xampp\htdocs…\login.php on line 19
Warning: mysqli_stmt_get_result() expects parameter 1 to be mysqli_stmt, boolean given in C:\xampp\htdocs…\login.php on line 20
Warning: mysqli_fetch_array() expects parameter 1 to be mysqli_result, null given in C:\xampp\htdocs…\login.php on line 22

reg.php:

Line 78:

mysqli_stmt_bind_param($stmt, 'sssssssi', $username, $hashed_pass, $email2, $forename, $surname, $gender, $member_registration_random_numbers, $activation);

Line 79:

mysqli_stmt_execute($stmt);

Here’s the full context of line 78 & 79:

// insert query
			$stmt = mysqli_prepare($conn, "INSERT INTO users(usernames, passwords, emails, forenames, surnames, genders, account_activation_codes, account_activations) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
			mysqli_stmt_bind_param($stmt, 'sssssssi', $username, $hashed_pass, $email2, $forename, $surname, $gender, $member_registration_random_numbers, $activation);
			mysqli_stmt_execute($stmt);

Line 82:

if (mysqli_stmt_insert_id($stmt)) {

Here’s the context of line 82:

// check if query is inserted
			if (mysqli_stmt_insert_id($stmt)) {
				echo "<h3 style='text-align:center'>Thank you for your registration.<br /> Redirecting to login page ...</h3>";

login.php

Line 18:

mysqli_stmt_bind_param($stmt, 'ss', $username, $email);

Line 19:

mysqli_stmt_execute($stmt);

Line 20:

$result = mysqli_stmt_get_result($stmt);

Line 22:

$row = mysqli_fetch_array($result, MYSQLI_ASSOC);

Here’s the context from Lines 18-22.

$stmt = mysqli_prepare($conn, "SELECT usernames, passwords, emails, account_activation_codes, account_activations FROM users WHERE usernames = ? OR emails = ?");
		mysqli_stmt_bind_param($stmt, 'ss', $username, $email);
		mysqli_stmt_execute($stmt);
		$result = mysqli_stmt_get_result($stmt);

        $row = mysqli_fetch_array($result, MYSQLI_ASSOC);

Here’s Lines 10-22:

if (isset($_POST["submit"]))
{
	if (isset($_POST["username_or_email"]) && isset($_POST["password"])) {

		$username = $_POST["username_or_email"];
		$email = $_POST["username_or_email"];
		$password = $_POST["password"];

		$stmt = mysqli_prepare($conn, "SELECT usernames, passwords, emails, account_activation_codes, account_activations FROM users WHERE usernames = ? OR emails = ?");
		mysqli_stmt_bind_param($stmt, 'ss', $username, $email);
		mysqli_stmt_execute($stmt);
		$result = mysqli_stmt_get_result($stmt);

        $row = mysqli_fetch_array($result, MYSQLI_ASSOC);

You know the silly errors keep complaining that parameter 1 should not be boolean but if you look carefully the parameter does not contain any boolean atall! Is this a bug in php 7 ?

Thanks for pointing out my typos on line 24. My typo-d line was:

$account_activation_link = "http://www.'".$site_domain."'.com/$site-name/activate_account.php?email='".$_POST['email']."'&hash='".$member_registration_random_numbers."'";

I have now fixed the typos to this:

$account_activation_link = "http://www.'".$site_domain."'.com/"'.$site_name.'"/activate_account.php?email='".$_POST['email']."'&hash='".$member_registration_random_numbers."'";

The typos were mine and not mlukac89’s, who edited my script. :banghead:

Add the following line in conn.php

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
1 Like

As I said earlier, in this case $stmt can contain a Boolean. If you look at the documentation for mysqli_prepare(), it says:

So, when you get a message that tells you you’re passing a Boolean in, that’s because the earlier statement that should have returned an object (in $stmt) has actually returned a false. This means that prepare() failed, so you need to look at why it failed. This is why you often see code like this:

if ($stmt = mysqli_prepare($conn, "SELECT usernames, passwords, emails, account_activation_codes, account_activations FROM users WHERE usernames = ? OR emails = ?")) { 
  // code for if the prepare worked
  }
else {
  // code for if it failed
  }

This means that if the prepare() function returns anything other than false, do the code in the if() clause, otherwise execute the stuff in the else() clause, handle the error somehow.

So in your case here, the first question is if you run the query from phpmyadmin, does it work? Obviously you have to drop the end bits, so just run

SELECT usernames, passwords, emails, account_activation_codes, account_activations FROM users

If that doesn’t work, then there’s your problem and you need to figure out why it’s not working. If it does work, add one of the clauses in, with a hard-coded selection similar to what you’d have typed in, and see if that makes any difference.

SELECT usernames, passwords, emails, account_activation_codes, account_activations FROM users WHERE usernames = 'bill'

If that doesn’t show the error, please post the table layout for the users table.


(By “highlight the line” I just meant stick some ** on the end, or a comment “this is line 78” or whatever. If you can’t find the lines in the post entry, what chance have we got? You can find them in your editor, though, and just add a comment).

He often sees it because PHP users en masse are cargo cult programmers, in 2017 using the same approach as in 1997.

Well, I wasn’t getting into whether it was a good idea or not as I don’t have the experience to say. My point was to try to get over why he’s getting a Boolean passed in when he thinks there is no Boolean. The revised bit I posted was just as it shows on php.net.

mlukac89, is the script still working on your end, fine without these errors I am facing ?

Thanks. Gonna seriously look into your correction. :winky:

Yes script is working fine.

If this code $activation = 1; // 1 = active | 0 = not active bothers you, you can always set that field into database to be default by 0 on insertion, so you don’t need to do it in code. If you make it like that change code to this

$stmt = mysqli_prepare($conn, "INSERT INTO users(Usernames, Passwords, Emails, Forenames, Surnames, Genders, Account_Activation_Codes) VALUES (?, ?, ?, ?, ?, ?, ?, )");
mysqli_stmt_bind_param($stmt, 'sssssssi', $username, $hashed_pass, $email2, $forename, $surname, $gender, $member_registration_random_numbers);

and in database http://prntscr.com/f1bkis

If it’s working then you’re must not have error logs turned on. Might suggest learning how to do that so you can see how many errors are in your codes. I took a look at it a week back and it came up with a few errors on my localhost since I always have error logs turned on in development.

2 Likes

Mine error report is always on, and i don’t have any errors running localhost php 7.1

2 Likes

Are you sure? Because I have error logs turned on in PHP 7.1.4 and I’m seeing undefined index errors left and right. Which means the variables are not created. So you might want to turn error logs on before actually saying “it is” turned on. If you don’t see these errors and more than 1 person sees it, then you’re not logging any errors in your development environment at all.

What are the names of a indexes ?

For example, the title asks for a $site variable, but one isn’t created. If you HAD error logs turned on, you would see this error.

That is probably in
register.php “$site_domain.”'.com/$site-name"
and in

site_details.php is declared only this
$site_name = ""; $site_domain = ""; $site = ""; $site_admin_email = "";

so its only a typo, if he is not so lazy and know anything he can spot a typo ??

And no offense but i don’t know why you posting in this topic anymore, as you can see that topic starter want’s a working code :smiley: