0

I am trying to generate a password reset token but getting the error:

Fatal error: Can't use function return value in write context in /path/to//test2.php on line 9

I have a form on page test.php that asks users to enter their email address, then I am trying to check if that email address already exists in my database in the user table, and if so, generate a random token and store in the users table to use in a password reset URL AND set a date column in the DB to today to use for token expiration.

Here is my test.php file:

<?php

// Include config file
require_once '../../db_connect.php';

// Define variables and initialize with empty values
$user_email = "";
$user_email_err = "";

// Processing form data when form is submitted
if(isset($_POST["user_email"])) {

$user_email = trim($_POST["user_email"]);

include 'test2.php';    

//End if statement checking to see if form has been submitted   
}

?>
<html>
<head></head>
<body>
<!-- html form -->
<form  action="<?php echo htmlspecialchars(basename($_SERVER['REQUEST_URI'])); ?>" method="post" name="resetform">

    <!-- the user name input field uses a HTML5 pattern check -->

    <!-- the email input field uses a HTML5 email type check -->
    <div class="form-group <?php echo (!empty($user_email_err)) ? 'has-error' : ''; ?>">
    <label for="login_input_email">User email </label>

    <input id="login_input_email" class="login_input" type="email" name="user_email" required />

     <span class="help-block"><?php echo $user_email_err;?></span>
     </div>
    <input type="submit"  name="reset_submit" value="Reset password" />

</form>
</body>
</html>

Here is what is in test2.php

<?php    

//Select posts 
$sqlcheck = "SELECT * FROM users WHERE user_email = '$user_email'";


        if($stmt = mysqli_prepare($conn, $sqlcheck)){
            // Bind variables to the prepared statement as parameters
            mysqli_stmt_bind_param($stmt, "s", $param_user_email);

            // Set parameters
            $param_user_email = $user_email;

            // Attempt to execute the prepared statement
            if(mysqli_stmt_execute($stmt)){
                   // Records selected - now query the DB
                   if($result2 = mysqli_query($conn, $sqlcheck)) { 

                        if(mysqli_num_rows($result2) == 0) {
                            //email address is not found
                            $user_email_err = "User email not found.";
                        } elseif (mysqli_num_rows($result2) == 1){
                    //email address is in the database - request password reset
                        $token = bin2hex(openssl_random_pseudo_bytes(150));
                        $sqlsetrequest = "UPDATE users SET reset_code = '$token', reset_date = NOW() WHERE user_email = '$user_email'";

                                if ($conn->query($sqlsetrequest) === TRUE) {
                                echo "Password reset request submitted successfully"."<br>";
                                    //email link to user email
                                    //redirect to generic success page???

                                } else {
                                    echo "Error updating record: " . $conn->error;
                                }

                        } else {
                        //This scenario should not happen -- looks like the email address has been found more than once
                        echo "Oooops,some crazy error just happened.";
                        }
                    }

            }

        // Close statement
        mysqli_stmt_close($stmt);

        }
?>

Any help would be hugely appreciated.

  • 1
    `mysqli_num_rows($result2) = 0` is an assignment (you can't assign things to a function call), not a comparison (i.e. == or ===). – Jonnix Feb 08 '18 at 00:06
  • **WARNING**: When using `mysqli` you should be using [parameterized queries](http://php.net/manual/en/mysqli.quickstart.prepared-statements.php) and [`bind_param`](http://php.net/manual/en/mysqli-stmt.bind-param.php) to add user data to your query. **DO NOT** use string interpolation or concatenation to accomplish this because you have created a severe [SQL injection bug](http://bobby-tables.com/). **NEVER** put `$_POST`, `$_GET` or **any** user data directly into a query, it can be very harmful if someone seeks to exploit your mistake. – tadman Feb 08 '18 at 00:56
  • Note: The object-oriented interface to `mysqli` is significantly less verbose, making code easier to read and audit, and is not easily confused with the obsolete `mysql_query` interface. Before you get too invested in the procedural style it’s worth switching over. Example: `$db = new mysqli(…)` and `$db->prepare("…")` The procedural interface is an artifact from the PHP 4 era when `mysqli` API was introduced and should not be used in new code. – tadman Feb 08 '18 at 00:56
  • @JonStirling thank you very much, that worked. However now I need to use prepared statements per tadman to avoid sql injection – ramsjared16 Feb 09 '18 at 21:18
  • @tadman Thank you so much for the tip. I assumed - incorrectly I guess - that since I wasn't inserting the user data into the DB, that I would be ok. I updated the test2.php file above with prepared statements. However, now I am getting the error: **Parse error: syntax error, unexpected end of file in... on line 50**... Do you know what I am doing wrong? I am very new at this and obviously don't know what I am doing. – ramsjared16 Feb 09 '18 at 21:35
  • One thing to consider is being extremely vigilant about proper indentation and consistent formatting. Your indentation in this example is all over the place and a single missing `}` is what causes errors like that, so having it all aligned helps make syntax errors more visibly obvious. Check that each opening brace has a matching close. – tadman Feb 12 '18 at 15:48
  • @tadman Thank you so much for your patience! I fixed my bracket alignment issues in test2.php and that error is gone. However, now I am getting the error: **Warning: mysqli_stmt_bind_param(): Number of variables doesn't match number of parameters in prepared statement in .../test2.php on line 9** Line 9 is: `mysqli_stmt_bind_param($stmt, "s", $param_user_email);` The variable $param_user_email is the only one I need to check the DB for, so I don't understand which other(s) I would need to add. Do you have any suggestions? Thanks again! – ramsjared16 Feb 12 '18 at 21:44
  • A) Use the object-oriented interface, it's much shorter. B) Check that `$stmt` is defined as it looks like your `prepare` call failed. `mysqli` can raise exceptions if you configure it to which helps avoid hidden errors. – tadman Feb 12 '18 at 22:59

0 Answers0