<?php
/**
* CAPTCHA X
*
* This is simple class for CAPTCHA (Completely Automated Public Turing to tell
* Computers from Humans Apart)
*
* It's small, compact and scalable. Tuning of the parameters is done completely
* via the captcha_x.ini file, which contains also the deeper documentation on
* their meaning.
*
*
* INSTALLATION
*
* Place the files anywhere you wish, preferrably in separate folder in some
* directory from where you include scripts. ( This folder would be referred as
* $APP_ROOT.)
*
* Set up the fonts (captcha_x.ini). You can use system fonts ( default) or local
* fonts. If so, you should create the $APP_ROOT/fonts folder and place the fonts
* there. Edit the 'fonts' key accordingly and use only the names without the ttf
* extension. For more info discuss the PHP manual on imagettftext() function.
*
* If you use some kind of protection of the include folder ( eg. .htaccess), you
* should move the server.php somewhere from where you normally link your images
* and set up properly the inclusion of the captcha_x class.
*
* Tune the parameters of the CAPTCHA image according to your needs.
*
*
* IMPORTANT NOTE
*
* The image server MUST be in the same domain as the target of the web-form
* ( eg. the fully qualified domain names of their url MUST be identical).
* In other case the session based validation will fail.
*
*
* THIS SOFTWARE IS SPELLWARE
*
* Its author wrote it in the hope, that COMPUTERS OF THOSE FUCKING BASTARDS
* SPAMMING GROUPS WITH THEIR BULLSHIT WILL CRASH, BURN AND BLOW UP !!!
*
*
* @package CAPTCHA X
* @license GPL
*/
class captcha_x {
/**
* Parsed captcha_x.ini
*/
var $INI;
/**
* Resulting image
*/
var $image;
/**
* Array of letters
*/
var $letters;
/**
* @access public
* @return void
* @constructor
*/
function captcha_x () {
$this->INI = parse_ini_file ( dirname ( __FILE__) . '/captcha_x.ini', true);
}
/* ========== PUBLIC METHODS ========== */
/**
* Generates the image and puts md5 hash into the session
*
* @access public
* @return void
*/
function handle_request () {
extract ( $this->INI);
$this->letters = $this->_get_random_letters ();
$this->_put_md5_into_session ();
$this->image = $this->_create_img_base ();
$this->_add_dust_and_scratches ( $bg_color_2);
$this->_print_letters ();
$this->_add_dust_and_scratches ( $bg_color_1);
header("Content-type: image/jpeg");
imagejpeg ( $this->image);
imagedestroy ( $this->image);
}
/**
* Compares the user's input with the hash stored in the session
*
* @param string $user_string
* @access public
* @return boolean
*/
function validate ( $user_string) {
extract ( $this->INI);
session_start ();
if ( ! $case_sensitive) {
$user_string = strtolower ( $user_string);
}
$md5 = md5 ( $user_string);
if ( $md5 == $_SESSION['captcha']) {
return true;
}
}
/* ========== PRIVATE METHODS =========== */
/**
* Generate some noise
*
* @param string $color -- rgb color representation, see captcha_x.ini
* @access private
* @return void
*/
function _add_dust_and_scratches ( $color) {
extract ( $this->INI);
$max_x = $width - 1;
$max_y = $height - 1;
$color = $this->_split ( $color);
$color = imagecolorallocate ( $this->image, $color[0], $color[1], $color[2]);
for ( $i = 0; $i < $noise; ++$i) {
if ( rand ( 1, 100) > $dust_vs_scratches) {
imageline ( $this->image, rand ( 0, $max_x), rand ( 0, $max_y), rand ( 0, $max_x), rand ( 0, $max_y), $color);
} else {
imagesetpixel ( $this->image, rand ( 0, $max_x), rand ( 0, $max_y), $color);
}
}
}
/**
* Sets the new image and its background
*
* @access private
* $return resource
*/
function _create_img_base () {
extract ( $this->INI);
$bg_color = $this->_split ( $bg_color_1);
$img = imagecreate ( $width, $height);
imagecolorallocate ( $img, $bg_color[0], $bg_color[1], $bg_color[2]);
return $img;
}
/**
* Gets some letters from the set defined in captcha_x.ini
*
* @access private
* @return array
*/
function _get_random_letters () {
extract ( $this->INI);
$letters = $this->_split ( $letters);
$letters_max = (count ( $letters) - 1);
for ( $i = 0; $i < $letters_no; ++$i) {
$letter_index = rand ( 0, $letters_max);
$rtn_val[] = $letters[$letter_index];
}
return $rtn_val;
}
/**
* Generates the text in the image
*
* This function takes many parameters from the captcha_x.ini file, which
* define the fonts, their sizes, letter angle and letterr colors
*
* @access private
* @return void
*/
function _print_letters () {
extract ( $this->INI);
// whether use the local fonts or the system fonts
if ( $use_local_fonts) {
$font_path = realpath ( dirname ( __FILE__) . '/fonts');
if ( @putenv ( 'GDFONTPATH=' . $font_path) === false) {
$no_putenv = true;
}
}
list ( $padding_top, $padding_right, $padding_bottom, $padding_left) = $this->_split ( $padding);
$box_width = ( $width - ( $padding_left + $padding_right)) / $letters_no;
$box_height = $height - ( $padding_top + $padding_bottom);
$font_size = $this->_split ( $font_size);
$font_size_count = ( count ( $font_size) - 1);
$fonts = $this->_split ( $fonts);
$fonts_count = ( count ( $fonts) - 1);
// f****** safe-mode settings
if ( $no_putenv) {
foreach ( $fonts as $k => $v) {
$a[$k] = "$font_path/$v.ttf";
}
$fonts = $a;
unset ( $a);
}
// sem pridat podporu pro #xxx a #xxxxxx resolve_color()
$fg_colors_count = ( count ( $fg_colors) - 1);
foreach ( $fg_colors as $fg_color) {
$a[] = $this->_split ( $fg_color);
}
$fg_colors = $a;
unset ( $a);
for ( $i = 0; $i < $letters_no; ++$i) {
$size_index = rand ( 0, $font_size_count);
$size = $font_size[$size_index];
$angle = (( rand ( 0, ( $letter_precession * 2)) - $letter_precession) + 360) % 360;
$x = $padding_left + ( $box_width * $i);
$y = $padding_top + $size + ( ( $box_height - $size) / 2);
$color_index = ( rand ( 0, $fg_colors_count));
$color = $fg_colors[$color_index];
$color = imagecolorallocate ( $this->image, $color[0], $color[1], $color[2]);
$font_index = rand ( 0, $fonts_count);
$font = $fonts[$font_index];
imagettftext ( $this->image, $size, $angle, $x, $y, $color, $font, $this->letters[$i]);
}
}
/**
* Puts the md5 hash into session
*
* @access private
* @return void
*/
function _put_md5_into_session () {
extract ( $this->INI);
session_start();
$string = implode ( '', $this->letters);
if ( ! $case_sensitive) {
$string = strtolower ( $string);
}
$md5 = md5 ( $string);
$_SESSION['captcha'] = $md5;
}
/**
* Splits string into an array by comma and spaces
*
* @access private
* @param string $s to be split
* @return array
*/
function _split ( $s) {
$a = @preg_split ( '/\s?,\s?/', $s, -1, PREG_SPLIT_NO_EMPTY);
if ( is_array ( $a)) {
return $a;
}
}
}
?>