Last active
July 8, 2017 11:50
-
-
Save gmazzap/9977153 to your computer and use it in GitHub Desktop.
Captcha implementation for WordPress. See http://wordpress.stackexchange.com/questions/139907/session-problem-in-php-trying-to-simple-captcha
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// require the class | |
@require_once __DIR__ . '/mycaptcha.php'; | |
// defaults | |
$w = 110; | |
$h = 35; | |
$random_dots = 0; | |
$random_lines = 20; | |
$captcha_text_color = "0x#B9B098"; | |
$captcha_noice_color = "0x#CEC7BA"; | |
/* get code */ | |
$code = filter_input( INPUT_GET, 'c', FILTER_SANITIZE_STRING ); | |
if ( empty( $code ) ) die( '' ); | |
$code = MyCaptcha::decode( $code ); | |
/* get settings */ | |
$sizes = filter_input( INPUT_GET, 'size', FILTER_SANITIZE_STRING ); | |
if ( ! empty( $sizes ) ) { | |
$s = explode( 'x', $sizes ); | |
if ( is_numeric($s[0]) && (int) $s[0] > 0 ) $w = (int) $s[0]; | |
if ( isset($s[1]) && is_numeric($s[1]) && (int) $s[1] > 0 ) $h = (int) $s[1]; | |
} | |
$dots = (int) filter_input( INPUT_GET, 'dots', FILTER_SANITIZE_NUMBER_INT ); | |
if ( $dots > 0 ) $random_dots = $dots; | |
$lines = (int) filter_input( INPUT_GET, 'lines', FILTER_SANITIZE_NUMBER_INT ); | |
if ( $dots > 0 ) $random_lines = $lines; | |
$tcolor = (string) filter_input( INPUT_GET, 'tcolor', FILTER_SANITIZE_STRING ); | |
if ( strlen($tcolor) === 6 ) $captcha_text_color = "0x#{$tcolor}"; | |
$ncolor = (string) filter_input( INPUT_GET, 'ncolor', FILTER_SANITIZE_STRING ); | |
if ( strlen($ncolor) === 6 ) $captcha_noice_color = "0x#{$ncolor}"; | |
/* prepare image */ | |
$font = './monofont.ttf'; | |
$font_size = $h * 0.75; | |
$image = @imagecreate($w, $h); | |
$bg_color = imagecolorallocate($image, 255, 255, 255); | |
$arr_text_color = MyCaptcha::hexrgb($captcha_text_color); | |
$text_color = imagecolorallocate( | |
$image, | |
$arr_text_color['red'], | |
$arr_text_color['green'], | |
$arr_text_color['blue'] | |
); | |
$arr_noice_color = MyCaptcha::hexrgb($captcha_noice_color); | |
$image_noise_color = imagecolorallocate( | |
$image, | |
$arr_noice_color['red'], | |
$arr_noice_color['green'], | |
$arr_noice_color['blue'] | |
); | |
/* generating dots randomly in background of image */ | |
for( $i=0; $i < $random_dots; $i++ ) { | |
imagefilledellipse( | |
$image, | |
mt_rand(0, $w), mt_rand(0, $h), | |
2, 3, | |
$image_noise_color | |
); | |
} | |
/* generating lines randomly in background of image */ | |
for( $i=0; $i < $random_lines; $i++ ) { | |
imageline( | |
$image, | |
mt_rand(0, $w), mt_rand(0, $h), | |
mt_rand(0, $w), mt_rand(0, $h), | |
$image_noise_color | |
); | |
} | |
/* create a text box and add 6 letters code in it */ | |
$textbox = imagettfbbox( $font_size, 0, $font, $code ); | |
$x = ( $w - $textbox[4] ) / 2; | |
$y = ( $h - $textbox[5] ) / 2; | |
imagettftext( $image, $font_size, 0, $x, $y, $text_color, $font , $code); | |
/* output captcha image */ | |
header('Content-Type: image/jpeg'); | |
imagejpeg($image); | |
imagedestroy($image); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class MyCaptcha { | |
protected $code = ''; | |
protected $letters = '23456789bcdfghjkmnpqrstvwxyz'; | |
protected $chars_num; | |
protected $tcolor; | |
protected $ncolor; | |
protected $width; | |
protected $height; | |
/** | |
* Allow to configure some options, generate a random code and print the fields | |
*/ | |
function __construct( $args = array() ) { | |
$defaults = array( | |
'chars_num' => 6, | |
'dots' => 0, | |
'lines' => 20, | |
'width' => 110, | |
'height' => 35, | |
'tcolor' => 'B9B098', | |
'ncolor' => 'CEC7BA' | |
); | |
$args = wp_parse_args( $args, $defaults ); | |
foreach ( $args as $k => $v ) { | |
$this->$k = $v; | |
} | |
$this->setCode(); | |
$this->fields(); | |
} | |
/** | |
* Print the fields | |
*/ | |
protected function fields() { | |
echo $this->getHidden(); | |
echo $this->getImg(); | |
echo $this->getText(); | |
} | |
/** | |
* Generate a random code | |
*/ | |
protected function setCode() { | |
$i = 0; | |
$len = strlen( $this->letters ) - 1; | |
while ( $i < $this->chars_num ) { | |
$this->code .= substr( $this->letters, mt_rand( 0, $len ), 1 ); | |
$i++; | |
} | |
} | |
/** | |
* Print hidden field | |
*/ | |
protected function getHidden() { | |
return wp_nonce_field( $this->code , md5(__CLASS__) . '_n', FALSE, FALSE ); | |
} | |
/** | |
* Print text field | |
*/ | |
protected function getText() { | |
$f = '<label>%s<input type="text" name="%s" value="" autocomplete="off" /></label>'; | |
return sprintf( $f, __('Type the captcha:', 'your-textdomain'), md5(__CLASS__) ); | |
} | |
/** | |
* Print captcha image | |
*/ | |
protected function getImg() { | |
$f = '<img src="%s" width="%d" height="%d" alt="" />'; | |
$data = array( | |
'c' => self::encode( $this->code ), | |
'size' => "{$this->width}x{$this->height}", | |
'dots' => "{$this->dots}", | |
'lines' => "{$this->lines}", | |
'tcolor' => "{$this->tcolor}", | |
'ncolor' => "{$this->ncolor}" | |
); | |
$url = add_query_arg( $data, get_template_directory_uri() . '/captcha_img.php' ); | |
return sprintf( $f, $url, $this->width, $this->height ); | |
} | |
/** | |
* Verify the nonce | |
*/ | |
static function verify() { | |
$method = filter_input( INPUT_SERVER, 'REQUEST_METHOD', FILTER_SANITIZE_STRING ); | |
$type = strtoupper( $method ) === 'GET' ? INPUT_GET : INPUT_POST; | |
$nonce = filter_input( $type, md5(__CLASS__) . '_n', FILTER_SANITIZE_STRING ); | |
$code = filter_input( $type, md5(__CLASS__), FILTER_SANITIZE_STRING ); | |
return ! empty($code) && ! empty($nonce) && wp_create_nonce( $code ) === $nonce; | |
} | |
/** | |
* Convert an hexadecimal color to an rgb array color | |
*/ | |
static function hexrgb( $hex ) { | |
$int = hexdec( $hex ); | |
return array( | |
"red" => 0xFF & ($int >> 0x10), | |
"green" => 0xFF & ($int >> 0x8), | |
"blue" => 0xFF & $int | |
); | |
} | |
/** | |
* encode the code to avoid put plan code in image url | |
*/ | |
private static function encode( $code ) { | |
$iv_size = mcrypt_get_iv_size( MCRYPT_BLOWFISH , MCRYPT_MODE_ECB ); | |
$iv = mcrypt_create_iv( $iv_size, MCRYPT_RAND ); | |
$key = md5( __CLASS__ ); | |
$enc = mcrypt_encrypt( MCRYPT_BLOWFISH , $key, $code, MCRYPT_MODE_ECB, $iv); | |
return urlencode( base64_encode( $enc ) ); | |
} | |
/** | |
* Decode the code | |
*/ | |
static function decode( $encoded ) { | |
$code = urldecode( base64_decode( $encoded ) ); | |
$iv_size = mcrypt_get_iv_size( MCRYPT_BLOWFISH , MCRYPT_MODE_ECB ); | |
$iv = mcrypt_create_iv( $iv_size, MCRYPT_RAND ); | |
$key = md5( __CLASS__ ); | |
return mcrypt_decrypt( MCRYPT_BLOWFISH , $key, $code, MCRYPT_MODE_ECB, $iv ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment