Saif Ali
Saif Ali

Reputation: 49

PHP Random Number Generator Not Working When Compared to $_POST[]

This just gets the random numbers. Then converts the int to a string. The string is used in the HTML.

$num1 = mt_rand(1, 9);
$num2 = mt_rand(1, 9);
$sum = $num1 + $num2;
$str1 = (string) $num1;
$str2 = (string) $num2;

This section just gets all the POST information and variable declarations.

if (isset($_POST["submit"])) {
    $name = $_POST['name'];
    $email = $_POST['email'];

These are just declrations for variables.

    $message = $_POST['message'];
    $human = intval($_POST['human']);
    $from = 'STEM and Buds Contact Form';
    $to = '[email protected]';
    $subject = $_POST['subject'];
    $reason = $_POST['reason'];

This is where the code breaks. It always outputs Your anti-spam is incorrect when it is correct. This is where the error occurs. The $num1 and $num2 variables are the two random values that I declared earlier and when those are summed and the user input is correct it should (theoretically) work.

<div class="form-group">
    <label for="human" class="col-sm-2 control-label"><?php echo $str1 . " + " . $str2 . " = ?"; ?></label>
    <div class="col-sm-10">
        <input type="text" class="form-control" id="human" name="human" placeholder="Your Answer">
        <?php echo "<p class='text-danger'>$errHuman</p>"; ?>
    </div>
</div>

if ($human !== $num1 + $num2) {
    $errHuman = 'Your anti-spam is incorrect';
}

Upvotes: 4

Views: 91

Answers (2)

Professor Abronsius
Professor Abronsius

Reputation: 33813

To accomplish the math based captcha you need to use a session variable to store the answer and compare submitted answer against that session variable.

The following ought to help solve your issue - it is based around your original code snippets but does not have the full form with all the elements or variables but should give a clear idea how to proceed.

<?php
    session_start();

    $errHuman=false;

    $num1 = mt_rand(1,9);
    $num2 = mt_rand(1,9);
    $sum = $num1 + $num2;




    if( $_SERVER['REQUEST_METHOD']=='POST' && !empty( $_POST['human'] ) && !empty( $_SESSION['math-captcha'] ) ){

        $answer=filter_input( INPUT_POST, 'human', FILTER_SANITIZE_NUMBER_INT );
        $errHuman = ( intval( $answer )==$_SESSION['math-captcha']->sum ) ? 'Congratulations' : 'Sorry - that is incorrect';

    }

    $_SESSION['math-captcha']=(object)array(
        'num1'  =>  $num1,
        'num2'  =>  $num2,
        'sum'   =>  (int)$sum
    );      

?>
<!DOCTYPE html>
<html>
    <head>
        <title>Math based captcha</title>
    </head>
    <body>
        <form method='post'>
            <!-- other form elements-->
            <div class="form-group">
                <label for="human" class="col-sm-2 control-label"><?php printf( '%d + %d=?', $num1, $num2 );?></label>
                <div class="col-sm-10">
                    <input type="text" class="form-control" name="human" placeholder="Your Answer">
                    <?php

                        if( $errHuman ){
                            printf('<p class="text-danger">%s</p>', $errHuman );
                        }

                    ?>
                </div>
            </div>

            <input type='submit' />
        </form>
    </body>
</html>

Upvotes: 0

Nik
Nik

Reputation: 3215

Every time a user sends the form with the correct human value, the server receives the POST request and generates new values for $num1 and $num2. This is why your condition does not work.

You need to remember the operands and compare them against the values you showed to the user.

Simplest example (not safe against attack):

So, and this to your php file:

// init new random numbers
$num1New = mt_rand(1, 9);
$num2New = mt_rand(1, 9);

Add hidden values to your html form:

<input type="hidden" name="num1" value="<?php echo $num1New ?>">
<input type="hidden" name="num2" value="<?php echo $num2New ?>">

Extend receiving the variables:

$human = intval($_POST['human']);
$num1 = intval($_POST['num1']);
$num2 = intval($_POST['num2']);

In this case, you will compare the values which you displayed to the user.

Another solution would be to store the pair of the values in a database or user session or other storages.

Upvotes: 2

Related Questions