[php] Problem with verifying secruity code

Joined
Apr 29, 2005
Messages
6,400
Reaction score
130
I'm totally lost on this one. As you can see here: cuteness.pie-designs.net/test2.php
The security image displays without any problem. However if you enter the right code, it still echoes "Oops the security code does not match the code shown in the image."

The scripts I'm using:
captcha.php:(The image)
PHP:
<?php
$width = 160;
$height = 40;
$characters = 5;
$font_size = 12;

$im = imagecreate($width, $height);
$bg = imagecolorallocate($im, 0, 0, 0);

$character_array = array("A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9");
$i = 0;
while ($i<5)
{
    imageline($im, rand(0, 8), rand(0, $height), ($width-rand(0, 8)), rand(0, $height), imagecolorallocate($im, rand(95, 159), rand(95, 159), rand(95, 159)));
    $i++;
}

$total_string = "";
$i=0;
while ($i<$characters)
{    
    $string = $character_array[rand(0, (count($character_array)-1))];
    $total_string .= $string;
    $textcolor = imagecolorallocate($im, rand(127, 255), rand(127, 255), rand(127, 255));
    imagestring($im, 5, rand((((($width)/$characters)*$i)+3), ((($width/$characters)*($i+1))-16)), rand(0, ($height-20)), $string, $textcolor);
    $i++;
}
mysql_connect('localhost', '***', '***');
mysql_select_db('***');

$insert = mysql_query("INSERT INTO verification VALUES ('', '".md5($total_string)."', '".$_SERVER['REMOTE_ADDR']."', '".time()."')") or exit('Error!');

header("Content-type: image/png");
imagepng($im);
imagedestroy($im);
?>

test2.php:
PHP:
					$connection = mysql_connect($host, $user, $pass) or die ("unable to connect");
					
					  mysql_select_db($db) or die ("Unable to select database!"); 

                $_POST['code'] = strtoupper($_POST['code']);        
        if (empty($_POST['code']))
        {
            $error[] = 'You must fill in the <b>security code</b>.';
        }
        elseif (!ereg("^[A-Z]{5}$", $_POST['code']))
        {
            $error[] = 'the <b>security code</b> does not match the code shown in the image.';
        }
        else
        {
		$select = mysql_query("SELECT code FROM verification WHERE code = '".md5($_POST['code'])."'' LIMIT 1");

                        mysql_query("DELETE FROM verification WHERE ip_address = '".$_SERVER['REMOTE_ADDR']."' OR time <= '".(time()-(60*60))."'");
                          
            if (!mysql_num_rows($select))
            {
                $error[] = 'the <b>security code</b> does not match the code shown in the image.';
            }
            else { $code = true; }
        }

if ($code == true)
{
    echo 'code was allright';
}
else
{
    echo 'Oops ';
    foreach($error as $single_error)
    {
        echo $single_error.'<br>';
		echo $_POST['code'];
    }
} 
}
?>

I've already checked if the code gets inserted properly in the db.

Any suggestions?
 
Can you show us the code for the form?

PS: $select = mysql_query("SELECT code FROM verification WHERE code = '".md5($_POST['code'])."'' LIMIT 1"); has double single-quotes, should be:

$select = mysql_query("SELECT code FROM verification WHERE code = '".md5($_POST['code'])."' LIMIT 1");
 
Code:
<form action ="<?php echo $_SERVER['PHP_SELF']; ?>" method ="post">
Enter the security code: <br/><input type="text" name="code" size="20" align="left"><br />Security code:<br /> <img src="captcha.php" />
<input type="submit" name="submit" value="submit" />
</form>

That's the code for the form.
 
I would recommend you to assign your $_POST['code'] with a variable,
example
PHP:
$code = $_POST['code'];
then you do all the stuffs like strtoupper, md5 ects..

In your query it would be better to just use the variable, rather than md5 at the same time. What I mean was,
PHP:
$code = strtoupper($_POST['code']);
$encrypt = md5($code);
$select = mysql_query("SELECT code from verification WHERE code='$encrypt' LIMIT 1");

Your delete query seems weird to me, you're trying to delete the row(s) by IP/time? It suppose to be the code right?

I think that's all.
 
It was my code. It first selects the row with the appropriate code, than deletes all rows of your IP address (because every code generated for your pc has become useless when you pressed submit) OR rows that are older than a day...this keeps the table clean.

As for variable assigning, your method takes more memory, but it really doesn't care if you do it inline or not.
 
I see, but for captcha it would be better to use session and cookie. You know that IP can easily be changed, and by just using $_SERVER['REMOTE_ADDR'] it can't check for the real IP address if the person running behind a proxy server.
Just my 2 cents comment(:
 
Hmm yes, perhaps using sessions is better yes...wrote this long time ago ^^,
 
I went on the test page (cuteness.pie-designs.net/test2.php) and entered the right code and it said that "code was allright".
 
Well, I tried it the second time. Now it didn't work. But it did work the first time.

Edit:
You could just use sessions. I have already got a script for that.

Just save the below code as random.php
Code:
<?php
session_start();

// make a string with all the characters that we 
// want to use as the verification code
$alphanum  = "abcdefghijklmnopqrstuvwxyz0123456789";

// generate the verication code 
$rand = substr(str_shuffle($alphanum), 0, 5);

// create the hash for the verification code
// and put it in the session
$_SESSION['image_random_value'] = md5($rand);

// create the image
$image = imagecreate(100, 30);

// use white as the background image
$bgColor = imagecolorallocate ($image, 255, 255, 255); 

// the text color is black
$textColor = imagecolorallocate ($image, 0, 0, 0); 

// write the random number
imagestring ($image, 5, 25, 8,  $rand, $textColor); 
	
// send several headers to make sure the image is not cached	
// taken directly from the PHP Manual
	
// Date in the past 
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); 

// always modified 
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); 

// HTTP/1.1 
header("Cache-Control: no-store, no-cache, must-revalidate"); 
header("Cache-Control: post-check=0, pre-check=0", false); 

// HTTP/1.0 
header("Pragma: no-cache"); 	


// send the content type header so the image is displayed properly
header('Content-type: image/jpeg');

// send the image to the browser
imagejpeg($image);

// destroy the image to free up the memory
imagedestroy($image);
?>

Then, make the script of the form.
Code:
<?
session_start();
$number = $_POST['code'];

if(!isset($_POST['submit'])) {
?>
<div>
<form action ="<?php echo $_SERVER['PHP_SELF']; ?>" method ="post">
Name: 
<br/><input name="name" size="20" type="text" align="left" maxlength="20">
<br/>
Enter the security code: 
<br/><input name ="code" size="20" type="text" align="left"><img src="random.php">
<br/>
Message:
<br/>
<textarea name="message" rows="5" cols="50"> Adding comments hasn't been enabled yet.</textarea>
<input type="submit" name="submit" value="Go">
</form>
</div>
<?php
} else {
if (md5($number) == $_SESSION['image_random_value']) {
//IF CODE IS RIGHT
} else {
echo "Wrong security code.";
}
?>
 
Ok,I fixed it I just rewrote the entire code, and left all unnecessary stuff out.
PHP:
$host = "localhost";
$user = "***";
$pass = "***";
$db = "***"; 
$code = md5($_POST['code']);
$connection = mysql_connect($host, $user, $pass);
	
	mysql_select_db($db);
	
	$query1 = "SELECT code FROM verification WHERE code = '$code'";
	
	$result = mysql_query($query1);
	
	if(mysql_num_rows($result) < 1) {
		echo "Wrong security code";
		} else { //rest of script }
 
Back