420 lines
12 KiB
PHP
420 lines
12 KiB
PHP
|
<?php
|
||
|
if(!function_exists('add_filter')) exit;
|
||
|
class FANSUB_Captcha {
|
||
|
private $chars;
|
||
|
private $length;
|
||
|
private $fonts;
|
||
|
private $background;
|
||
|
private $foreground;
|
||
|
private $code;
|
||
|
private $uppercase;
|
||
|
private $lowercase;
|
||
|
private $size;
|
||
|
private $base;
|
||
|
private $font_size;
|
||
|
private $file_mode;
|
||
|
private $image_type;
|
||
|
private $font_char_width;
|
||
|
private $save_path;
|
||
|
private $save_url;
|
||
|
private $session_name;
|
||
|
private $expired_minutes;
|
||
|
private $pixel;
|
||
|
private $pixel_color;
|
||
|
private $line;
|
||
|
private $line_color;
|
||
|
|
||
|
public function set_expired_minutes($minutes) {
|
||
|
$this->expired_minutes = $minutes;
|
||
|
}
|
||
|
|
||
|
public function get_expired_minutes() {
|
||
|
return $this->expired_minutes;
|
||
|
}
|
||
|
|
||
|
public function set_session_name($name) {
|
||
|
$this->session_name = $name;
|
||
|
}
|
||
|
|
||
|
public function get_session_name() {
|
||
|
return $this->session_name;
|
||
|
}
|
||
|
|
||
|
public function set_save_path($path) {
|
||
|
$this->save_path = $path;
|
||
|
}
|
||
|
|
||
|
public function get_save_path() {
|
||
|
return $this->save_path;
|
||
|
}
|
||
|
|
||
|
public function set_save_url($url) {
|
||
|
$this->save_url = $url;
|
||
|
}
|
||
|
|
||
|
public function get_save_url() {
|
||
|
return $this->save_url;
|
||
|
}
|
||
|
|
||
|
public function set_font_char_width($width) {
|
||
|
$this->font_char_width = $width;
|
||
|
}
|
||
|
|
||
|
public function get_font_char_width() {
|
||
|
return $this->font_char_width;
|
||
|
}
|
||
|
|
||
|
public function set_image_type($type) {
|
||
|
$this->image_type = $type;
|
||
|
}
|
||
|
|
||
|
public function get_image_type() {
|
||
|
return $this->image_type;
|
||
|
}
|
||
|
|
||
|
public function set_file_mode($mode) {
|
||
|
$this->file_mode = $mode;
|
||
|
}
|
||
|
|
||
|
public function get_file_mode() {
|
||
|
return $this->file_mode;
|
||
|
}
|
||
|
|
||
|
public function set_font_size($font_size) {
|
||
|
$this->font_size = $font_size;
|
||
|
}
|
||
|
|
||
|
public function get_font_size() {
|
||
|
return $this->font_size;
|
||
|
}
|
||
|
|
||
|
public function set_base($base) {
|
||
|
$this->base = $base;
|
||
|
}
|
||
|
|
||
|
public function get_base() {
|
||
|
return $this->base;
|
||
|
}
|
||
|
|
||
|
public function set_size($size) {
|
||
|
$this->size = $size;
|
||
|
}
|
||
|
|
||
|
public function get_size() {
|
||
|
return $this->size;
|
||
|
}
|
||
|
|
||
|
public function set_width($width) {
|
||
|
$this->size[0] = $width;
|
||
|
}
|
||
|
|
||
|
public function set_height($height) {
|
||
|
$this->size[1] = $height;
|
||
|
}
|
||
|
|
||
|
public function set_uppercase($uppercase) {
|
||
|
$this->uppercase = $uppercase;
|
||
|
}
|
||
|
|
||
|
public function get_uppercase() {
|
||
|
return $this->uppercase;
|
||
|
}
|
||
|
|
||
|
public function set_lowercase($lowercase) {
|
||
|
$this->lowercase = $lowercase;
|
||
|
}
|
||
|
|
||
|
public function get_lowercase() {
|
||
|
return $this->lowercase;
|
||
|
}
|
||
|
|
||
|
public function set_code($code) {
|
||
|
$this->code = $code;
|
||
|
}
|
||
|
|
||
|
public function get_code() {
|
||
|
return $this->code;
|
||
|
}
|
||
|
|
||
|
public function set_foreground($fg) {
|
||
|
$this->foreground = $fg;
|
||
|
}
|
||
|
|
||
|
public function get_foreground() {
|
||
|
return $this->foreground;
|
||
|
}
|
||
|
|
||
|
public function set_background($bg) {
|
||
|
$this->background = $bg;
|
||
|
}
|
||
|
|
||
|
public function get_background() {
|
||
|
return $this->background;
|
||
|
}
|
||
|
|
||
|
public function set_fonts($fonts) {
|
||
|
$this->fonts = $fonts;
|
||
|
}
|
||
|
|
||
|
public function add_font($font) {
|
||
|
$this->fonts[] = $font;
|
||
|
}
|
||
|
|
||
|
public function get_fonts() {
|
||
|
return $this->fonts;
|
||
|
}
|
||
|
|
||
|
public function set_length($length) {
|
||
|
$this->length = $length;
|
||
|
}
|
||
|
|
||
|
public function get_length() {
|
||
|
return $this->length;
|
||
|
}
|
||
|
|
||
|
public function set_chars($chars) {
|
||
|
$this->chars = $chars;
|
||
|
}
|
||
|
|
||
|
public function get_chars() {
|
||
|
return $this->chars;
|
||
|
}
|
||
|
|
||
|
public function set_pixel($bool) {
|
||
|
$this->pixel = $bool;
|
||
|
}
|
||
|
|
||
|
public function get_pixel() {
|
||
|
return (bool)$this->pixel;
|
||
|
}
|
||
|
|
||
|
public function set_pixel_color($color) {
|
||
|
$this->pixel_color = $color;
|
||
|
}
|
||
|
|
||
|
public function get_pixel_color() {
|
||
|
return $this->pixel_color;
|
||
|
}
|
||
|
|
||
|
public function set_line($bool) {
|
||
|
$this->line = $bool;
|
||
|
}
|
||
|
|
||
|
public function get_line() {
|
||
|
return (bool)$this->line;
|
||
|
}
|
||
|
|
||
|
public function set_line_color($color) {
|
||
|
$this->line_color = $color;
|
||
|
}
|
||
|
|
||
|
public function get_line_color() {
|
||
|
return $this->line_color;
|
||
|
}
|
||
|
|
||
|
public function __construct() {
|
||
|
$defaults = array(
|
||
|
'chars' => fansub_get_safe_captcha_characters(),
|
||
|
'length' => 5,
|
||
|
'uppercase' => true,
|
||
|
'lowercase' => true,
|
||
|
'size' => array(87, 25),
|
||
|
'background' => array(255, 255, 255),
|
||
|
'foreground' => array(138, 200, 67),
|
||
|
'pixel' => true,
|
||
|
'pixel_color' => array(205, 255, 205),
|
||
|
'line' => true,
|
||
|
'line_color' => array(205, 215, 205),
|
||
|
'font_char_width' => 14,
|
||
|
'file_mode' => 0444,
|
||
|
'image_type' => 'png',
|
||
|
'font_size' => 13,
|
||
|
'base' => array(10, 20),
|
||
|
'save_path' => FANSUB_CONTENT_PATH . '/captcha',
|
||
|
'save_url' => content_url('fansub/captcha'),
|
||
|
'session_name' => 'fansub_captcha',
|
||
|
'expired_minutes' => 3,
|
||
|
'fonts' => array(FANSUB_PATH . '/fonts/Tahoma.ttf')
|
||
|
);
|
||
|
$args = apply_filters('fansub_captcha_default_args', array());
|
||
|
$args = wp_parse_args($args, $defaults);
|
||
|
$this->set_chars($args['chars']);
|
||
|
$this->set_length($args['length']);
|
||
|
$this->set_uppercase($args['uppercase']);
|
||
|
$this->set_lowercase($args['lowercase']);
|
||
|
$this->set_size($args['size']);
|
||
|
$this->set_background($args['background']);
|
||
|
$this->set_foreground($args['foreground']);
|
||
|
$this->set_line($args['line']);
|
||
|
$this->set_line_color($args['line_color']);
|
||
|
$this->set_pixel($args['pixel']);
|
||
|
$this->set_pixel_color($args['pixel_color']);
|
||
|
$this->set_font_char_width($args['font_char_width']);
|
||
|
$this->set_file_mode($args['file_mode']);
|
||
|
$this->set_image_type($args['image_type']);
|
||
|
$this->set_font_size($args['font_size']);
|
||
|
$this->set_base($args['base']);
|
||
|
$this->set_save_path($args['save_path']);
|
||
|
$this->set_save_url($args['save_url']);
|
||
|
$this->set_session_name($args['session_name']);
|
||
|
$this->set_fonts($args['fonts']);
|
||
|
$this->set_expired_minutes($args['expired_minutes']);
|
||
|
}
|
||
|
|
||
|
public function generate_image() {
|
||
|
$dir = wp_normalize_path($this->get_save_path());
|
||
|
if(!wp_mkdir_p($dir)) {
|
||
|
return false;
|
||
|
}
|
||
|
$this->cleanup_expired();
|
||
|
$code = fansub_random_string($this->get_length(), $this->get_chars());
|
||
|
$filename = '';
|
||
|
$dir = trailingslashit($dir);
|
||
|
if($this->get_uppercase()) {
|
||
|
$code = strtoupper($code);
|
||
|
}
|
||
|
$size = $this->get_size();
|
||
|
if($im = @imagecreatetruecolor($size[0], $size[1])) {
|
||
|
$fonts = $this->get_fonts();
|
||
|
if(!fansub_array_has_value($fonts)) {
|
||
|
return false;
|
||
|
}
|
||
|
$filename = md5(fansub_random_string());
|
||
|
$background = $this->get_background();
|
||
|
$foreground = $this->get_foreground();
|
||
|
$bg = @imagecolorallocate($im, $background[0], $background[1], $background[2]);
|
||
|
$fg = @imagecolorallocate($im, $foreground[0], $foreground[1], $foreground[2]);
|
||
|
@imagefill($im, 0, 0, $bg);
|
||
|
|
||
|
if($this->get_pixel()) {
|
||
|
$pixel_colors = $this->get_pixel_color();
|
||
|
$pixel_color = @imagecolorallocate($im, $pixel_colors[0], $pixel_colors[1], $pixel_colors[2]);
|
||
|
$pixels = rand(300, 600);
|
||
|
for($i = 0; $i < $pixels; $i++) {
|
||
|
@imagesetpixel($im, rand(1, 100), rand(1, 100), $pixel_color);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$base = $this->get_base();
|
||
|
$x = $base[0] + mt_rand(-2, 2);
|
||
|
for($i = 0; $i < strlen($code); $i++) {
|
||
|
$font = $fonts[array_rand($fonts)];
|
||
|
$font = wp_normalize_path($font);
|
||
|
$y = $base[1] + mt_rand(-2, 2);
|
||
|
$angle = mt_rand(-20, 20);
|
||
|
@imagettftext($im, $this->get_font_size(), $angle, $x, $y, $fg, $font, $code[$i]);
|
||
|
$x += $this->get_font_char_width();
|
||
|
}
|
||
|
|
||
|
if($this->get_line()) {
|
||
|
$lines = rand(5, 10);
|
||
|
$line_colors = $this->get_line_color();
|
||
|
$line_color = @imagecolorallocate($im, $line_colors[0], $line_colors[1], $line_colors[2]);
|
||
|
for($i = 0; $i < $lines; $i++) {
|
||
|
@imageline($im, rand(1, 100), rand(1, 100), rand(1, 100), rand(1, 100), $line_color);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
switch($this->get_image_type()) {
|
||
|
case 'jpeg':
|
||
|
$filename = sanitize_file_name($filename. '.jpeg');
|
||
|
$file = wp_normalize_path($dir . $filename);
|
||
|
@imagejpeg($im, $file);
|
||
|
break;
|
||
|
case 'gif':
|
||
|
$filename = sanitize_file_name($filename . '.gif');
|
||
|
$file = wp_normalize_path($dir . $filename);
|
||
|
@imagegif($im, $file);
|
||
|
break;
|
||
|
case 'png':
|
||
|
default:
|
||
|
$filename = sanitize_file_name($filename . '.png');
|
||
|
$file = wp_normalize_path($dir . $filename);
|
||
|
@imagepng($im, $file);
|
||
|
}
|
||
|
@imagedestroy($im);
|
||
|
@chmod($file, $this->get_file_mode());
|
||
|
}
|
||
|
if(!empty($filename)) {
|
||
|
if($this->get_lowercase()) {
|
||
|
$code = strtolower($code);
|
||
|
}
|
||
|
$data = array(
|
||
|
'hashed' => wp_hash_password($code),
|
||
|
'timestamp' => strtotime(fansub_get_current_date('Y-m-d H:i:s'))
|
||
|
);
|
||
|
$this->set_session_data($data);
|
||
|
}
|
||
|
$this->set_code($code);
|
||
|
return trailingslashit($this->get_save_url()) . $filename;
|
||
|
}
|
||
|
|
||
|
public function get_session_data() {
|
||
|
$session_name = $this->get_session_name();
|
||
|
$captcha_session = isset($_SESSION[$session_name]) ? maybe_unserialize($_SESSION[$session_name]) : array();
|
||
|
return $captcha_session;
|
||
|
}
|
||
|
|
||
|
public function set_session_data($data) {
|
||
|
$session_name = $this->get_session_name();
|
||
|
$_SESSION[$session_name] = maybe_serialize($data);
|
||
|
}
|
||
|
|
||
|
public function check($code) {
|
||
|
$current_datetime = fansub_get_current_date('Y-m-d H:i:s');
|
||
|
$captcha_session = $this->get_session_data();
|
||
|
$timestamp = fansub_get_value_by_key($captcha_session, 'timestamp');
|
||
|
if(!is_numeric($timestamp)) {
|
||
|
return false;
|
||
|
}
|
||
|
if(strtotime('+' . strval($this->get_expired_minutes()) . ' minutes', $timestamp) < strtotime($current_datetime)) {
|
||
|
return false;
|
||
|
}
|
||
|
if($this->get_lowercase()) {
|
||
|
$code = strtolower($code);
|
||
|
}
|
||
|
$save_code = fansub_get_value_by_key($captcha_session, 'hashed');
|
||
|
return wp_check_password($code, $save_code);
|
||
|
}
|
||
|
|
||
|
public function remove($prefix) {
|
||
|
$suffixes = array('.jpeg', '.gif', '.png', '.php', '.txt');
|
||
|
foreach($suffixes as $suffix) {
|
||
|
$dir = trailingslashit($this->get_save_path());
|
||
|
$filename = sanitize_file_name($prefix . $suffix);
|
||
|
$file = wp_normalize_path($dir . $filename);
|
||
|
if(@is_file($file)) {
|
||
|
@unlink($file);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function cleanup_expired($minutes = 60) {
|
||
|
$dir = trailingslashit($this->get_save_path());
|
||
|
$dir = wp_normalize_path($dir);
|
||
|
if(!@is_dir($dir) || !@is_readable($dir)) {
|
||
|
return false;
|
||
|
}
|
||
|
$is_win = ('WIN' === strtoupper(substr(PHP_OS, 0, 3)));
|
||
|
if(!($is_win ? win_is_writable($dir) : @is_writable($dir))) {
|
||
|
return false;
|
||
|
}
|
||
|
fansub_delete_old_file($dir, $minutes * MINUTE_IN_SECONDS);
|
||
|
$count = 0;
|
||
|
if($handle = @opendir($dir)) {
|
||
|
while(false !== ($filename = readdir($handle))) {
|
||
|
if(!preg_match('/^[0-9]+\.(php|txt|png|gif|jpeg)$/', $filename)) {
|
||
|
continue;
|
||
|
}
|
||
|
$file = wp_normalize_path($dir . $filename);
|
||
|
$stat = @stat($file);
|
||
|
if(($stat['mtime'] + $minutes * MINUTE_IN_SECONDS) < time()) {
|
||
|
@unlink($file);
|
||
|
$count += 1;
|
||
|
}
|
||
|
}
|
||
|
closedir($handle);
|
||
|
}
|
||
|
return $count;
|
||
|
}
|
||
|
}
|