I have extensively looked for a solution for this issue but none of the ones I have found seems to match my needs, so I kindly ask for help or ideas.
Short story: I am creating a reset password procedure for my website. This code should check if the email entered by the user in the page that is posting to this one is actually present in the db (table: users) and, if it is, it should create a token, add it to the table password_reset and send it to the user's email to complete the password reset procedure.
Error: The error that I get on the second query is "command out of sync", and I understands that it means that I cannot execute the query before I free up the result of the previous one. However, I need to use the result of the first query in the second, and for this reason I cannot free it up. What is the best solution to achieve my goal?
<?php
use PHPMailer\PHPMailer\PHPMailer;
require '../vendor/phpmailer/phpmailer/src/PHPMailer.php';
require '../vendor/phpmailer/phpmailer/src/SMTP.php';
require_once('./include/dbconnect.php');
$sendmail = 0; //initialize
$addtoken = 0; //initialize
date_default_timezone_set('UTC');
// Was the form submitted?
if (isset($_POST["ForgotPassword"])) {
// Harvest submitted e-mail address
if (filter_var($_POST["email"], FILTER_VALIDATE_EMAIL)) {
$email = $_POST["email"];
} else {
echo "Please, enter a valid email address";
exit;
}
// Check to see if a user exists with this e-mail exists
if ($query = mysqli_prepare($db, "SELECT email, username FROM users WHERE email = ?")) {
mysqli_stmt_bind_param($query, 's', $email);
mysqli_stmt_execute($query);
mysqli_stmt_bind_result($query, $selected_email, $selected_user);
$userExists=mysqli_stmt_fetch($query);
if ($userExists) {
// Create a unique salt.
$salt = "<salt code>";
// Create the unique user password reset token
$token = hash('sha512', $salt.$selected_email);
// calculate the current timestamp
date_default_timezone_set('UTC');
$timestamp = mktime(date("H"), date("i"), date("s"), date("m"), date("d"), date("Y"));
$curDate = date("Y-m-d H:i:s", $timestamp);
$exp_timestamp = mktime(date("H"), date("i"), date("s"), date("m"), date("d")+1, date("Y"));
$exp = date("Y-m-d H:i:s", $exp_timestamp);
//If the email is already present in the reset database
if ($query1 = mysqli_prepare($db, "SELECT expdate FROM password_reset WHERE email=?")) {
mysqli_stmt_bind_param($query1, 's', $selected_email);
mysqli_stmt_execute($query1);
mysqli_stmt_bind_result($query1, $expdate);
$entryExists = mysqli_stmt_fetch($query1);
} else {
die(mysqli_error($db));
}
if ($entryExists) { //if there is a result, meaning the pwd reset for this email has already been requested
echo "Password reset already contains this email";
//if the token is still valid - do nothing
if ($expdate >= $curDate) {
echo "A password reset email has already been sent to this address. Please double check.";
} else {
//if the token is expired - replace it with the new one
if ($query2 = mysqli_prepare($db, "UPDATE password_reset SET token = ?, expdate = ? WHERE email=?")){
mysqli_stmt_bind_param($query2, 'sss', $token, $exp, $selected_email);
mysqli_stmt_execute($query2);
$sendmail = 1;
}
}
} else { //it means that a pwd reset hasn't been requested yet
$addtoken = 1;
$sendmail = 1;
}
} else { //there is no such user in the DB, so we do nothing
$addtoken = 0;
$sendmail = 0;
}
if ($addtoken==1){
$insert = mysqli_prepare($db, "INSERT INTO password_reset (email, token, expdate) VALUES(?, ?, ?)");
mysqli_stmt_bind_param($insert, 'sss', $selected_email, $token, $exp);
mysqli_stmt_execute($insert);
}
if ($sendmail==1){...INSTRUCTIONS TO SEND EMAIL...}
}
}
?>