Edit: Fixed a few bugs. The code below is now corrected.
Garciat wrote:You could make it more random by adding other colors (only 2 will be used on a single image), randomizing the color needed for the input (it's always red), adding some letters, and maybe using a longer string.
Garciat - Die hard
My Extensions and Me
Your wish is my command.
image.php has been changed to:
<?php
/**
* Generates a CAPTCHA picture
*
* @copyright Copyright (C) 2008 PunBB, partially based on code by Jamie Furness
* @license http://www.gnu.org/licenses/gpl.html GPL version 2 or higher
* @package pun_antispam
* modified by James Anderson :)
*/
// Generate a random string
function pun_antispam_rand_str()
{
return strtr(substr(strtolower(md5(uniqid(rand(), 1))), 2, 6), 'abcdef', '165380');
}
//decide what color to use
function pun_antispam_random_color() {
$random_color = rand(0, 2);
switch($random_color) {
case "0";
$use = "red";
break;
case "1";
$use = "blue";
break;
case "2";
$use = "green";
break;
}
return $use;
}
// Output CAPTCHA string into an image
function pun_antispam_image($string, $usecolor)
{
$im = imagecreatetruecolor(100, 18);
// Make the background white
imagefilledrectangle($im, 0, 0, 99, 17, 0xFFFFFF);
//other colors
$red = imagecolorallocate($im, 255, 0, 0);
$blue = imagecolorallocate($im, 0, 0, 255);
$green = imagecolorallocate($im, 0, 168, 20);
$noise = imagecolorallocate($im, 255, 0, 0);
$x = 0;
while($x <= 5) {
$color = rand(0,2); //is this character red or blue? make it up
$pallet = $pallet.$color; //This attaches a number, 0 or 1, to each character, determining whether it is red or blue
//pallet is an all numerical string. there are no letters in pallet
$x++;
}
//if the first is red, the last has to be blue, and vice versa
//this is to ensure that there will always be at least one red and at least one blue
//also if the first one is blue, then the second one is green, and if the last one is blue, then the next to last one is green
$pallet{0} = rand(0,1);
if($pallet{0} == 1) { //the first one is blue
$pallet{5} = 0; //the last one is red
$pallet{1} = 2; //the second one is green
}
elseif($pallet{0} == 0) { //the first one is red
$pallet{5} = 1; //the last one is blue
$pallet{4} = 2; //the second to last one is green
}
$px = rand(1,10); //moves it around a bit, x
//draw each character
//reads pallet to see whether the letter is red or blue
$j = 0;
while($j <= 5) {
$color = rand(0, 2);
if($pallet{$j} == 0) {
$y = rand(2,4);
imagestring($im, 5, $px, $y, $string{$j}, $red);
if($usecolor == "red")
$list .= $string{$j}; //make the list of red chars
}
elseif($pallet{$j} == 1) {
$y = rand(2,4);
imagestring($im, 5, $px, $y, $string{$j}, $blue);
if($usecolor == "blue")
$list .= $string{$j}; //make the list of blue chars
}
elseif($pallet{$j} == 2) {
$y = rand(2,4);
imagestring($im, 5, $px, $y, $string{$j}, $green);
if($usecolor == "green")
$list .= $string{$j}; //make the list of green chars
}
else { die("Something went wrong in pallet. It didn't make any colors."); }
$j++;
$px = $px + 15; //move for the next char
}
//make some noise
while($k<(100*18)/1000) { //where it says 1000, raise/lower the value to increase or decrease the noise leve. Higher numbers = LESS noise
imageline($im, mt_rand(0,100), mt_rand(0,18), mt_rand(0,100), mt_rand(0,18), $noise);
$k++;
}
sleep(1);
header('Content-type:image/gif');
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Pragma: no-cache');
imagegif($im, null, 30);
imagedestroy($im);
return $list; //the list of red chars
}
session_start();
$pun_antispam_string = pun_antispam_rand_str();
$_SESSION['use_color'] = pun_antispam_random_color();
$_SESSION['pun_antispam_text'] = pun_antispam_image($pun_antispam_string, $_SESSION['use_color']);
?>
and please also modify pun_antispam.php to this:
<?php
<?php
if(!@defined($_SESSION)) {
session_start();
}
// Language definitions used in pun_antispam
$lang_pun_antispam = array(
'Captcha' => 'Captcha',
'Captcha Info' => 'Please enter <i>only</i> the <b><font color="'.$_SESSION['use_color'].'">'.$_SESSION['use_color'].'</font></b> character(s) in the image.',
'Invalid Text' => 'The captcha text you entered appears to be wrong. <b>Please <i>only</i> enter the <font color="'.$_SESSION['use_color'].'">'.$_SESSION['use_color'].'</font> character(s).</b>',
'Captcha admin head' => 'Setup which actions are protected by a captcha',
'Captcha admin info' => 'You may enable captcha in certain areas of your forum if you are experiencing problems with spam.',
'Captcha admin legend' => 'Enable Captcha',
'Captcha registrations info' => 'Require a captcha before users may register. This can be helpful to stop spam.',
'Captcha login info' => 'Require a captcha when logging in. This can be helpful to stop brute-force attacks.',
'Captcha reset info' => 'Require a captcha to be entered when a user tries to reset their password.',
'Captcha guestpost info' => 'Require a captcha for guest posting (if enabled one).'
);
?>
Also modify post.php in your installation's root directory. Find
($hook = get_hook('po_end_validation')) ? eval($hook) : null;
and change that to
($hook = get_hook('po_end_validation')) ? @eval($hook) : null;
Edit:
And find in login.php in your installation's root directory
($hook = get_hook('li_login_form_submitted')) ? eval($hook) : null;
and change that to
($hook = get_hook('li_login_form_submitted')) ? @eval($hook) : null;
Find in login.php in your installation's root directory
<?php ($hook = get_hook('li_login_pre_remember_me_checkbox')) ? eval($hook) : null; ?>
and change that to
<?php ($hook = get_hook('li_login_pre_remember_me_checkbox')) ? @eval($hook) : null; ?>
I decided to leave the numbers as they were because I suppose the PunBB developers had a reason for it. I also removed one of the pesky lines of code that was actually generating a random string from the already generated random string. That wasn't good... ;p
The reason for the @'s is to suppress the errors that would be generated by conflicting sessions. In the end, there is only one session created. The errors are not visible because of the @'s and won't interfere with anything. I didn't want to have to modify the hook for the extension which is the reason why I just added the @ in post.php instead of just removing the session_start in the hook.
Anyway, please keep up the feedback, I'd like to improve it even more.