A_Jelly_Doughnut wrote:
If you can find evidence, I'm listening. This style captcha was designed in part by the guy who broke phpBB's and vBulletin's, so it should last at least as long at phpBB's did (2 years?).
Naw, I can't, that's why the
I think, new captchas die every day, but I think "my idea" will last quite some time

(the idea about splitting the image)
anyways, I include my function if ever it is needed
Code: Select all
// makes text on the image somewhat arced
function arctext( $x, $y, $size, $font, &$img, $str, $col, $w, $ang )
{
// a few basic things that we'll need
$msize = ceil( $size/2 );
$delta = ceil( $msize/strlen( $str ) );
$xx = $x;
$yy = $y;
$sz = $size;
// now print the text
for ( $i = 0; $i < strlen( $str ); $i++ )
{
$s = imagettftext( $img, $sz, $ang, $xx, $yy, $col, $font, $str{$i} );
$xx = $s[ 2 ];
$ang = ( $w == 'd' ) ? $ang - 5 : $ang + 5;
$sz -= $delta;
}
}
// this creates the captcha for registration
function captcha()
{
global $cache, $security, $encryption, $Cl_root_path, $userdata, $Cl_root_path4template;
// first delete the images
$this->cleancaptcha();
// create an empty image
$maxx = 400;
$maxy = 300;
$img = imagecreatetruecolor( $maxx, $maxy );
// now put in a background
$b = rand( 0, 2 );
$bck = imagecreatefromjpeg( $Cl_root_path . 'includes/captcha/back' . $b . '.jpg' );
$size = getimagesize( $Cl_root_path . 'includes/captcha/back' . $b . '.jpg' );
imagecopy( $img, $bck, 0, 0, rand( 0, $size[ 0 ]-$maxx ), rand( 0, $size[ 1 ]-$maxy ), $maxx, $maxy );
imagedestroy( $bck );
// array of available fonts
$fonts = array( 'times', 'tahoma', 'lsans' );
// the font we'll be using
$col = imagecolorallocatealpha( $img, 0, 0, 0, 50 ); // and the colour
// make the array of strings
include( $Cl_root_path . 'includes/captcha/wordlist' . phpEx ); // get the word list
$words = array();
for ( $i = 0; $i < 10; $i++ )
{
$words[] = strtoupper( $list[ rand( 0, count( $list ) ) ] );
}
$x = 40;
$y = 50;
$size = 22;
$wordlist = array(); // this will later be used to determine the shortest and longest word
// print text to image
for ( $i = 0; $i < 4; $i++ )
{
// choose font for each line
$font1 = $Cl_root_path . 'includes/captcha/' . $fonts[ rand( 0, count( $fonts )-1 ) ] . '.ttf';
$font2 = $Cl_root_path . 'includes/captcha/' . $fonts[ rand( 0, count( $fonts )-1 ) ] . '.ttf';
// choose word for each line
$w1 = $words[ rand( 0, 9 ) ];
$w2 = $words[ rand( 0, 9 ) ];
// add words to list
$wordlist[] = $w1;
$wordlist[] = $w2;
// write text to image
$this->arctext( $x + 10, $y + 10, $size, $font1, $img, $w1, $col, 'd', 10 );
$this->arctext( $x, $y, $size, $font2, $img, $w2, $col, 'd', 10 );
// change position for next word
$dx = ( strlen( $w1 ) < strlen( $w2 ) ) ? strlen( $w1 ) * $size : strlen( $w2 ) * $size;
$x += $dx - 50;
$y += $size + 40;
}
// now we chop up the image into smaller entities
// first calculate the parts
$nrows = rand( 2, 10 );
$ncols = rand( 2, 10 );
$rows = array( 0 );
$cols = array( 0 );
// y borders
for ( $i = 1; $i < $nrows; $i++ )
{
$rows[ $i ] = rand( $rows[ $i - 1 ], $maxy );
if ( $rows[ $i ] == $maxy )
{ // break because we found the end
$nrows = $i;
break;
}
}
// x borders
for ( $i = 1; $i < $ncols; $i++ )
{
$cols[ $i ] = rand( $cols[ $i - 1 ], $maxx );
if ( $cols[ $i ] == $maxx )
{ // break because we found the end
$ncols = $i;
break;
}
}
if ( $rows[ $i ] != $maxy )
{ // we didn't have border yet
$rows[] = $maxy;
}
if ( $cols[ $i ] != $maxx )
{ // we didn't have border yet
$cols[] = $maxx;
}
$tosave = $Cl_root_path . 'cache/captcha_' . $userdata[ 'sid' ] . '_' . time();
$filelist = array(); // this will be the array of files that will later need deletion
// now do chopping and create the table as we go
$out = '<table cellspacing="0" cellpadding="0" border="0">';
for ( $i = 1; $i <= $nrows; $i++ )
{ // the rows
$y1 = $rows[ $i -1 ];
$y2 = $rows[ $i ];
if ( $y1 == $y2 )
{ // if the row is 0px big it can be skipped
continue;
}
$out .= '<tr>';
for ( $ii = 1; $ii <= $ncols; $ii++ )
{ // the cols
$x1 = $cols[ $ii - 1 ];
$x2 = $cols[ $ii ];
if ( $x1 == $x2 )
{ // if the col is 0px big it can be skipped
continue;
}
// make empty image
$im = imagecreatetruecolor( $x2-$x1, $y2-$y1 );
// paste part of the captcha onto it
imagecopy( $im, $img, 0, 0, $x1, $y1, $x2, $y2 );
// save it to cache
imagejpeg( $im, $tosave . "_$i:$ii.jpg" );
// don't need it anymore
imagedestroy( $im );
// add to table
$out .= "<td><img src=\"$Cl_root_path4template$tosave" . "_$i:$ii.jpg\"/></td>";
// add to filelist
$filelist[] = $tosave . "_$i:$ii.jpg";
}
$out .= '</tr>';
}
$out .= '</table>';
imagedestroy( $img );
// now store the filelist to cache
$cache->push( $userdata[ 'sid' ] . 'captchalist', $filelist, TRUE, ESSENTIAL );
// find the shortest and longest used word
$sh = array( 200, 0 );
$lng = array( 0, 0 );
for ( $i = 0; $i < count( $wordlist ); $i++ )
{
$l = strlen( $wordlist[ $i ] );
if ( $l < $sh[ 0 ] )
{ // shorter than the "shortest"
$sh[ 0 ] = $l;
$sh[ 1 ] = $i;
}
if ( $l > $lng[ 0 ] )
{ // longer than the "longest"
$lng[ 0 ] = $l;
$lng[ 1 ] = $i;
}
}
// save this too, but encrypted so it cannot be abused
$w1 = $encryption->encrypt( $security->make_key( 'short' ), $wordlist[ $sh[ 1 ] ], 15 );
$w2 = $encryption->encrypt( $security->make_key( 'long' ), $wordlist[ $lng[ 1 ] ], 15 );
$cache->push( $userdata[ 'sid' ] . 'captchawords', array( $w1, $w2 ), TRUE, ESSENTIAL );
return $out;
}
// this cleans the captcha images from cache
function cleancaptcha()
{
global $cache, $userdata;
// get filelist
$list = $cache->pull( $userdata[ 'sid' ] . 'captchalist', ESSENTIAL );
if ( empty( $list ) )
{ // nothing to do
return;
}
foreach( $list as $file )
{ // delete each one
@unlink( $file );
}
}
It's been coded for chlorine boards so yeah, changes will be needed for it to work.
A live example can be found
here
The only problem this actually has atm is that sometimes it is hard to tell which word exactly to input, and that sometimes trash is left behind in the cache, everything else is mmkay I think.
If anyone can break it, please please pleas tell me
