yf_captcha class

Class to handle CAPTCHA images (to prevent auto-registering, flooding etc).

Fileplugins/content/classes/yf_captcha.class.php
Use_class('captcha')

Public properties

A site sets them in its config with $PROJECT_CONF['captcha']['NAME'] = ...;

PropertyDefaultDescription
$ENABLED
CAPTCHA
true enabled
$add_ellipses
int
10 Number of random ellipses to add
$add_lines
int
15 Number of random lines to add
$add_pixels
int
500 Number of random pixels to add
$add_rects
int
15 Number of random rectangles to add
$already_used
bool
false Checking if once used
$bg_color
int
16777215 @conf_skip Image background color
$ellipse_colors
array
[1881832591, 1881690252, 1889611675, 1880711709, 1885481497] @conf_skip
$font_height
int
16 Middle value (will be bounced randomly with +2 and -2)
$image_height
int
30 Result image height (in pixels)
$image_width
int
110 Result image width (in pixels)
$line_colors
array
[539655311, 539512972] @conf_skip
$num_symbols
int
5 Number of symbols to generate
$pixel_colors
array
[539655311, 539512972] @conf_skip
$rect_colors
array
[1881832591, 1881690252, 1889611675, 1880711709, 1885481497] @conf_skip
$secret_key
string
'' Secret key (will be added to hash)
$symbols_array
array
[] Allowed symbols to use in randomizer
$text_colors
array
[371883151, 371740812, 379662235, 370762269, 375532057] @conf_skip Colors arrays
$ttf_font_path
string
'' Path to the True Type Font to use (could be array)
$use_cookies
bool
false Use cookies or session vars
$var_name
string
'image_hash' Cookie var name

Public methods 13

check

public function check($field_in_form = 'image_numbers', $input = null)

Show image with text.

    public function check($field_in_form = 'image_numbers', $input = null)
    {
        if ( ! $this->ENABLED) {
            return true;
        }
        $VALID_CODE = false;

        if ($this->already_used) {
            return true;
        }
        $this->already_used = true;

        if ( ! isset($input)) {
            $input = ($_POST[$field_in_form] ?? null) ?: ($_GET[$field_in_form] ?? null);
        }
        if (empty($input)) {
            _re('Please enter code', $field_in_form);
        } else {
            $hash = md5($this->secret_key . $input);
            $code_incorrect = null;
            if ($this->use_cookies) {
                if ($hash != ($_COOKIE[$this->var_name] ?? null)) {
                    $code_incorrect = true;
                }
            } else {
                if ($hash != ($_SESSION[$this->var_name] ?? null)) {
                    $code_incorrect = true;
                }
            }
            if ($code_incorrect) {
                _re('Code you entered is incorrect', $field_in_form);
            } else {
                $VALID_CODE = true;
            }
        }
        if ($this->use_cookies) {
            setcookie($this->var_name, '', time());
        } else {
            unset($_SESSION[$this->var_name]);
        }
        return $VALID_CODE;
    }

set_colors

public function set_colors($name = '', $input = '')

Set colors.

    public function set_colors($name = '', $input = '')
    {
        if ( ! empty($input) && in_array($name, ['text', 'rect', 'line', 'ellipse', 'pixel'])) {
            $this->{$name . '_colors'} = $input;
        }
    }

set_font_path

public function set_font_path($input = '')

Set font path ($input could be array or string).

    public function set_font_path($input = '')
    {
        if ( ! empty($input)) {
            $this->ttf_font_path = $input;
        }
    }
public function set_image_size($width = '', $height = '')

Set image size.

    public function set_image_size($width = '', $height = '')
    {
        if ( ! empty($width) && ! empty($height)) {
            $this->image_width = $width;
            $this->image_height = $height;
        }
    }
public function set_secret_key($input = '')

Set secret key.

    public function set_secret_key($input = '')
    {
        if (empty($input)) {
            $this->secret_key = substr(md5(REAL_PATH), 8, -8);
        } else {
            $this->secret_key = $input;
        }
    }
public function set_symbols_array($input = [])

Set symbols array contetns.

    public function set_symbols_array($input = [])
    {
        if (empty($input)) {
            return false;
        }
        // Try to assign predefined arrays
        if (is_numeric($input)) {
            if ($input == 1) {
                $this->symbols_array = range(0, 9);
            } elseif ($input == 2) {
                $this->symbols_array = array_flip(range('A', 'Z'));
            } elseif ($input == 3) {
                $this->symbols_array = array_merge(array_flip(range(0, 9)), array_flip(range('a', 'z')));
            }
            // Try to set custom array
        } elseif (is_array($input)) {
            $this->symbols_array = $input;
        }
    }

set_var_name

public function set_var_name($new_name = '')

Set new var name to use in session or in cookie.

    public function set_var_name($new_name = '')
    {
        if ( ! empty($new_name)) {
            $this->var_name = $new_name;
        }
    }

show_block

public function show_block($location = '', $stpl_name = '', $extra = [])

Show HTML block for the CAPTCHA image (complete, with input and it's validation).

    public function show_block($location = '', $stpl_name = '', $extra = [])
    {
        if ( ! $this->ENABLED) {
            return false;
        }
        if (is_array($stpl_name)) {
            $extra += $stpl_name;
            $stpl_name = $extra['captcha_stpl_name'];
        }
        $stpl_name = ($extra['captcha_stpl_name'] ?? null) ?: $stpl_name;
        if (empty($location)) {
            $location = './?object=' . ($_GET['object'] ?? null) . '&action=show_image';
        }
        $uid = '__captcha_id__';
        if (false === strpos($location, $uid)) {
            $location .= '&id=' . $uid;
        }
        if (empty($stpl_name)) {
            $stpl_name = 'system/captcha_block';
        }
        $replace = [
            'img_src' => process_url($location),
            'num_symbols' => (int) ($this->num_symbols),
            'input_attrs' => $extra['input_attrs'],
            'value' => '',
        ];
        return tpl()->parse($stpl_name, $replace);
    }

show_html

public function show_html($location = '', $add_style = ' border="1" ')

Show HTML code for the CAPTCHA image.

    public function show_html($location = '', $add_style = ' border="1" ')
    {
        if ( ! $this->ENABLED) {
            return false;
        }
        if (empty($location)) {
            $location = process_url('./?object=' . __CLASS__ . '&action=show_image');
        }
        return '<img src="' . $location . '" ' . $add_style . ' />';
    }

show_image

public function show_image($no_header = false, $no_exit = false)

Show image with text.

    public function show_image($no_header = false, $no_exit = false)
    {
        $random_string = null;
        if (function_exists('main')) {
            main()->NO_GRAPHICS = true;
        }
        if ( ! $this->ENABLED) {
            return false;
        }
        // Create image
        $image = imagecreatetruecolor($this->image_width, $this->image_height);
        // Calculate average width for the one font symbol
        $font_width = $this->image_width / $this->num_symbols;
        // Set font path
        $ttf_font = is_array($this->ttf_font_path) ? array_rand(array_flip($this->ttf_font_path)) : $this->ttf_font_path;
        // Set image background color
        imagefilledrectangle($image, 0, 0, $this->image_width, $this->image_height, $this->bg_color);
        // Draw text
        $random_string = '';
        for ($i = 0; $i < $this->num_symbols; $i++) {
            $random_string .= array_rand($this->symbols_array);
            imagettftext($image, round(rand($this->font_height - 2, $this->font_height + 2), 0), rand(-30, 30), $i * $font_width + 5 + rand(-2, 2), $this->image_height / 2 + 5 + rand(-4, 4), array_rand(array_flip($this->text_colors)), $ttf_font, $random_string[$i]);
        }
        // Draw random rectangles
        for ($i = 0; $i < $this->add_rects; $i++) {
            imagefilledrectangle($image, rand(-$this->image_width, $this->image_width), rand(-$this->image_height, $this->image_height), rand(-$this->image_width, $this->image_width), rand(-$this->image_height, $this->image_height), array_rand(array_flip($this->rect_colors)));
        }
        // Draw random lines
        for ($i = 0; $i < $this->add_lines; $i++) {
            imageline($image, rand(-$this->image_width, $this->image_width), rand(-$this->image_height, $this->image_height), rand(-$this->image_width, $this->image_width), rand(-$this->image_height, $this->image_height), array_rand(array_flip($this->line_colors)));
        }
        // Draw random ellipses
        for ($i = 0; $i < $this->add_ellipses; $i++) {
            imagefilledellipse($image, rand(-$this->image_height, $this->image_width), rand(-$this->image_height, $this->image_height), rand(20, $this->image_width), rand(10, $this->image_width), array_rand(array_flip($this->ellipse_colors)));
        }
        // Draw random pixels
        for ($i = 0; $i < $this->add_pixels; $i++) {
            imagesetpixel($image, rand(0, $this->image_width), rand(0, $this->image_height), array_rand(array_flip($this->pixel_colors)));
        }
        // Calculate hash
        $hash = md5($this->secret_key . $random_string);
        // Store secure data
        if ($this->use_cookies) {
            setcookie($this->var_name, $hash, time() + $this->cookie_ttl);
        } else {
            $_SESSION[$this->var_name] = $hash;
        }
        ob_start();
        imagepng($image);
        unset($image);
        $data = ob_get_clean();
        // Throw image to the user
        if ( ! $no_header) {
            header_remove('Set-Cookie');
            header('Content-Type: image/png', true);
            header('Content-Length: ' . strlen($data), true);
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT', true); // Date in the past
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT', true); // always modified
            header('Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0');
            header('Pragma: no-cache', true); // HTTP/1.0
            header('X-Robots-Tag: noindex,nofollow,noarchive,nosnippet', true);
        }
        echo $data;
        if ( ! $no_exit) {
            exit;
        }
    }

Methods starting with _ hooks and helpers; not routable as page actions

__call

public function __call($name, $args)

Catch missing method call.

    public function __call($name, $args)
    {
        return main()->extend_call($this, $name, $args);
    }

_init

public function _init()

Framework constructor.

    public function _init()
    {
        $this->_is_enabled_hook();
        if ( ! $this->ENABLED) {
            return false;
        }
        $this->set_secret_key();
        $lib_path = PROJECT_PATH . 'fonts/';
        $fwork_path = dirname(__DIR__) . '/fonts/';
        $path = file_exists($lib_path) ? $lib_path : $fwork_path;
        $this->set_font_path([
            $path . 'pioneer.ttf',
            $path . 'banco.ttf',
            $path . 'glast.ttf',
        ]);
        $this->set_symbols_array(1);
    }
public function _is_enabled_hook()

Allows you to override $this->ENABLED option for some cases.

    public function _is_enabled_hook()
    {
    }