View Full Version : Resolved using a function to create math check - issue with checking if correct
?foru
05-10-2009, 04:39 AM
Rather than implementing an anti-spam captcha system with multiple files that has to be adapted to your script I'm writing a simple math check but am having trouble checking that the input value is correct.
<?php
function add_nums(){
global $num1, $num2, $sum;
$num1 = rand(0, 10);
$num2 = rand(0, 10);
$sum = $num1 + $num2;
}
add_nums();
echo "$num1 + $num2 =";
?><input name="answer" type="text" id="answer" size="4">
which outputs something like 3 + 4= (text field named "answer")
Trying to check $answer against $sum and if it isn't correct show error or execute code if ok
This check is located towards the top of the page with all other checks which is above the function
if ( $answer != $sum ) {
$e[] = 'Please enter the correct response to the question.(you can refresh to get another one)<br>';
}
I've looked at operators and I constantly get the error message. I also tried not identical to !== but that didn't work either.
Anyone have a suggestion? Thank you
Snookerman
05-10-2009, 05:54 AM
I don't know much PHP so I might be wrong, but are you sending along the sum with a session key or something? If you aren't then I think it will check against the new sum, which might be different.
forum_amnesiac
05-10-2009, 04:45 PM
Are you trying to do one of these ;-
A - set the test code, $sum, on one page and then check against it on all other pages
B- are you trying to set it and test against it on the same page.
If it is A then your problem is that it is not working as a session variable but as a page variable, you will need to find a way to retain it, possibly by using cookies, for the session.
If it is B then you will probably need to submit the form to SELF, or another PHP, and then test the value entered.
Just a suggestion, instead of using $sum = $num1 + $num2; why not use $sum = $num1.$num2;, the first code can give a value for $sum of 0 - 20, the second can give a value of 0 to 1010.
?foru
05-11-2009, 02:01 AM
Thank you both for your replies.
Snookerman
What you mentioned makes since because most of the image CAPTCHA scripts that I looked at use some form of SESSION...so I started to look into things a little further since this seemed like it might be a little more in depth than I originally thought.
forum_amnesiac
Everything is contained in the same form and currently uses <?php echo $_SERVER['PHP_SELF']; ?> as the action. When I first started testing rand() was (0, 100). Interesting point about $sum = $num1.$num2; giving a larger value range.
I did some further research and found a script called Math Guard which uses a class file to create the question and check the answer. (once resolved I will post it all in the hopes that it will help someone else just wanting to add a simple check to their form.)
This seemed pretty easy to implement into my existing script, and it does the job to check for the correct answer (had to modify it to run in the same page as it was originally setup by the creator to post to another page). One issue with the math check condition though...
I added quite a few comments to explain what is going on
<?php
// start form processing which is located at the top of the page
if (isset($_POST['submit'])) {
$e = array(); // An empty array to hold possible error messages
// Everytime an error occurs, add an error message to the errors array.
if (!ereg("^[a-zA-Z]+$", $name) ) {
$e[] = 'Please enter name of person you\'re sending the message to<br>';
}
if ( $email=='' ) {
$e[] = 'Please enter the email address of the person you\'re sending the message to<br>';
}
if ( $mathguard_answer=='' ) {
$e[] = 'Please enter the answer to the math question<br>';
}
/* require the MathGuard class */
require ("ClassMathGuard.php");
if (MathGuard :: checkResult($_REQUEST['mathguard_answer'], $_REQUEST['mathguard_code'])) {
echo ("Correct answer!"); //insert your code that will be executed when user enters the correct answer
}
else {
$e[] = 'Bad answer, please try again!<br>';
}
if ( empty($e) ) { // If the errors array is empty, there were no errors and we can execute the rest of the script
//...all the code to mail the user or any other form processing needed
} // end empty($e) if
if ($e == NULL) {
$success = true; // proceed because everything is ok
}
}
?>
<html>
<head>
<title></title>
</head>
<body>
<?php
if ( isset($success) ) { // Form processing above has completed now the success result is being displayed to the user.
echo '<p>Thank you. Your message has been sent.</p>';
} else { // Form either hasn't been submitted or wasn't successful
if ( !empty($e) ) { // If errors array is not empty echo them
foreach ( $e as $msg ) {
echo $msg;
}
}
?>
<!--- HTML FORM HERE --->
<?php
} //close the final if statement
?>
The issue is with this portion from above...
if (MathGuard :: checkResult($_REQUEST['mathguard_answer'], $_REQUEST['mathguard_code'])) {
echo ("Correct answer!");
}
else {
$e[] = 'Bad answer, please try again!<br>';
}
I believe I need to change the if (MathGuard :: statement so it eliminates the correct answer message and only shows the error since all the other field checks are done like that, but I'm not sure how I can do this.
Right now when the math answer is correct it echos "Correct answer!" and the form is submitted without jumping down to if ( isset($success) ) {... like before implementing the Math Guard code.
This is the important part of the class file that checks the answer if it helps to change the MathGuard :: conditional statement (I'm not sure what the :: is doing above)
function checkResult($mathguard_answer, $mathguard_code, $prime = 37) {
$result_encoded = MathGuard::encode($mathguard_answer, $prime);
if ($result_encoded == $mathguard_code)
return true;
else
return false;
}
Again, I appreciate the help so far.
?foru
05-12-2009, 03:36 AM
The Math Guard check is now structured like the other checks so it should jump down and show the thank you message and not show the form again.
<?php
// start form processing which is located at the top of the page
if (isset($_POST['submit'])) {
$e = array(); // An empty array to hold possible error messages
// Everytime an error occurs, add an error message to the errors array.
if (!ereg("^[a-zA-Z]+$", $name) ) {
$e[] = 'Please enter name of person you\'re sending the message to<br>';
}
if ( $email=='' ) {
$e[] = 'Please enter the email address of the person you\'re sending the message to<br>';
}
if ( $mathguard_answer=='' ) {
$e[] = 'Please enter the answer to the math question<br>';
}
/* require the MathGuard class */
require ("ClassMathGuard.php");
if ( ! ( MathGuard :: checkResult($_REQUEST['mathguard_answer'], $_REQUEST['mathguard_code']))) {
$e[] = 'Incorrect answer, please try again!<br>';
}
if ( empty($e) ) {
//If the errors array is empty, there were no errors and we can execute the rest of the script
//...all the code to mail the user or any other form processing needed
} // end empty($e) if
if ($e == NULL) {
$success = true; // everything was correct so jump down to the Thank you message and don't show the form anymore
}
}
?>
<html>
<head>
<title></title>
</head>
<body>
<?php
if ( isset($success) ) { // Form processing above has completed now the success result is being displayed to the user.
echo '<p>Thank you. Your message has been sent.</p>';
} else { // Form either hasn't been submitted or wasn't successful
if ( !empty($e) ) { // If errors array is not empty echo them
foreach ( $e as $msg ) {
echo $msg;
}
}
?>
<!--- HTML FORM HERE --->
<?php
} //close the final if statement
?>
The form is processing but since adding the Math check the thank you message no longer shows and form still shows after submitting.
Can anyone spot anything that is incorrect? Thank you
forum_amnesiac
05-12-2009, 08:41 AM
I created a small input document that used mathguard and used your script here to test the processing and testing. The only change to your script I made was to add a couple of HTML messages.
I found it worked ok for me if my input was validated correctly, I got the success HTML and also the Thank You message.
The only problem was when it failed the validation, I got the success HTML, the error message and the failure HTML.
Here are the 2 scripts I used
Input:
<form action='formhandler.php' method='post'>
<b>Name:</b><br/>
<input type='text' name='name' size='30'/><br/><br/>
<b>Email:</b><br/>
<input type='text' name='email' size='30'/><br/><br/>
<? require("ClassMathGuard.php"); MathGuard::insertQuestion(); ?>
<br/><br/>
<input type="submit" name="submit" value="Next">
</form>
Processing:
<?
if (isset($_POST["submit"])) {
$e = array(); // An empty array to hold possible error messages
// Everytime an error occurs, add an error message to the errors array.
if (!ereg("^[a-zA-Z]+$", $name) ) {
$e[] = 'Please enter name of person you\'re sending the message to<br>';
}
if ( $email=='' ) {
$e[] = 'Please enter the email address of the person you\'re sending the message to<br>';
}
if ( $mathguard_answer=='' ) {
$e[] = 'Please enter the answer to the math question<br>';
}
/* require the MathGuard class */
require ("ClassMathGuard.php");
if ( ! ( MathGuard :: checkResult($_REQUEST['mathguard_answer'], $_REQUEST['mathguard_code']))) {
$e[] = 'Incorrect answer, please try again!<br>';
}
if ( empty($e) ) {
//If the errors array is empty, there were no errors and we can execute the rest of the script
//...all the code to mail the user or any other form processing needed
} // end empty($e) if
if ($e == NULL) {
$success = true; // everything was correct so jump down to the Thank you message and don't show the form anymore
}
}
?>
<html>
<head>
<title></title>
</head>
<body>
SUCCESS! My testing worked
</body>
</html>
<?php
if ( isset($success) ) { // Form processing above has completed now the success result is being displayed to the user.
echo '<p>Thank you. Your message has been sent.</p>';
} else { // Form either hasn't been submitted or wasn't successful
if ( !empty($e) ) { // If errors array is not empty echo them
foreach ( $e as $msg ) {
echo $msg;
}
}
?>
<!--- HTML FORM HERE --->
<html>
<head>
<title></title>
</head>
<body>
FAILED! Shouldn't get here if successful
</body>
</html>
<?php
} //close the final if statement
?>
Based on my testing of the code you've submitted I can't recreate your problem
?foru
05-15-2009, 04:22 AM
I really appreciate you taking another look at the code forum_amnesiac.
I did further testing and didn't have any luck, but I did however get this working. I had additional validation in another form structure that I have been using so I tested to see if it would work in that form and I didn't run into any issues.
Here is the MathGuard class as promised if anyone is interested.
Where you want to display the question in your form add:
<? require("ClassMathGuard.php"); MathGuard::insertQuestion(); ?>
ClassMathGuard.php
<?
class MathGuard {
/** A main hashing function: concat of user's answer, hour and the additional prime number (default 37) */
function encode($input, $prime) {
return md5($input.date("H").$prime);
}
/** This function generates the hash code from the two numbers
* @param $a first number
* @param $b second sumber
* @param $prime additional number to encode with
* */
function generateCode($a, $b, $prime) {
$code = MathGuard::encode($a + $b, $prime);
return $code;
}
/** This function checks whether the answer and generated security code match
* @param $mathguard_answer answer the user has entered
* @param $mathguard_code hashcode the mathguard has generated
*/
function checkResult($mathguard_answer, $mathguard_code, $prime = 37) {
// echo("prime; $prime, $mathguard_answer");
$result_encoded = MathGuard::encode($mathguard_answer, $prime);
if ($result_encoded == $mathguard_code)
return true;
else
return false;
}
/** this function inserts the two math term into your form, the parameter is optional */
function insertQuestion($prime = 37) { //default prime is 37, you can change it when specifying the different parameter
$a = rand() % 10; // generates the random number
$b = rand() % 10; // generates the random number
$code = MathGuard :: generateCode($a, $b, $prime);
echo ("Security question: $a + $b =
<input type='input' name='mathguard_answer' size='2'/><input type='hidden' name='mathguard_code' value='$code' />");
}
/** this function returns math expression into your form, the parameter is optional
* quite simmilar to insertQuestion, but returns the output as a text instead of echoing
*/
function returnQuestion($prime = 37) { //default prime is 37, you can change it when specifying the different parameter
$a = rand() % 10; // generates the random number
$b = rand() % 10; // generates the random number
$code = MathGuard :: generateCode($a, $b, $prime);
return ("Security question: $a + $b =
<input type='input' name='mathguard_answer' size='2'/><input type='hidden' name='mathguard_code' value='$code' />");
}
}
?>
In your validation you can add something like this to check the value submitted (change $error_msg to whatever you need to fit the rest of your validation)
elseif (!( MathGuard :: checkResult($_REQUEST['mathguard_answer'], $_REQUEST['mathguard_code']))) {
$error_msg .= "Incorrect security question answer, please try again!";
}
Powered by vBulletin® Version 4.2.2 Copyright © 2021 vBulletin Solutions, Inc. All rights reserved.