ФорумПрограммированиеПыхнуть хотите?Готовые решения → Капчо креатор

Капчо креатор

  • Josh

    Сообщения: 2008 Репутация: N Группа: Кто попало

    Spritz 2 июня 2009 г. 12:14

    <?php

    /**
    * Usage
    * ReCaptcha('generate') - generate Captcha, return array('key'=>PUBLIC_KEY, 'image'=> IMAGE_FILE_NAME)
    * ReCaptcha('check', array('public'=>PUBLIC_KEY, 'private'=>PRIVATE_KEY[user_input_value] )) - check captcha, return true/false
    * ReCaptcha('change', array('public'=>PUBLIC_KEY) - generate Captcha, return array('key'=>PUBLIC_KEY, 'image'=> IMAGE_FILE_NAME), and delete old cartcha image
    */
          define('SITE_PATH_DOCROOT', dirname(__FILE__));
    function ReCaptcha($do, $params = array())
    {
    $captcha = null;
    switch ($do){
    case 'generate':
    $captcha = new ReCaptchaClass;
    return array('key'=>$captcha->PublicKey, 'image'=>$captcha->CaptchaFileName);
    break;
    case 'check':
    if((array_key_exists('public', $params))&&(array_key_exists('private', $params))){
    $captcha = new ReCaptchaClass(false);
    return $captcha->CheckCaptcha($params['public'], $params['private']);
    } else {
    return false;
    }
    break;
    case 'change':
    if(array_key_exists('public_key', $params)){
    $captcha = new ReCaptchaClass(false);
    $fname = $captcha->GetFileName($params['public_key']);
    if(is_file($fname)){
    @unlink($fname);
    }
    $captcha = new ReCaptchaClass;
    return array('key'=>$captcha->PublicKey, 'image'=>$captcha->CaptchaFileName);
    }
    break;
    }
    }

    class ReCaptchaClass
    {
    public $CaptchaFileName = null;
    public $Directory = 'temp_captcha';
    public $FontDirectory = 'fonts';
    public $TTFRange = array('comic.ttf','impact.ttf');
    public $MaxChars = 5;
    public $MinSize = 10;
    public $MaxSize = 18;
    public $MaxRotation = 20; // [-30 .. 30]
    public $NoiseChars = false;
    public $WebSafeColors = false;
    public $SecretString = 'MY SECRET CODE!!!';
    public $SecretPosition = 15; // [1 .. 32]
    public $OutOfDateTime = 86400; // One day
    public $PublicKey = null;

    private $lx;
    private $ly;
    private $jpg_quality = 40;
    private $noise_factor = 9;
    private $nb_noise = null;
    private $key = null;
    private $privateKey = null;
    private $filename = null;
    private $gdVersion = 0;
    private $r = null;
    private $g = null;
    private $b = null;
    private $TTFfile = null;

    public function __construct($generate = true){
    $gd_info = gd_info();
    $this->gdVersion = $gd_info['GD Version'];
    $this->_mandatory = true;

    if(empty($this->gdVersion))
    {
    throw new Exception('ТЕПЕРЬ Я ПРАВИЛЬНО УПАЛ');
    }

    foreach($this->TTFRange as $key => $font)
    {
    if(!IsReadable($this->FontDirectory . DIRECTORY_SEPARATOR . $font))
    {
    unset($this->TTFRange[$key]);
    }
    }

    if(count($this->TTFRange) < 1)
    {
    throw new Exception('No Truetypefont available');
    }

    $this->ChangeFont();

    $this->nb_noise = $this->NoiseChars ? ($this->MaxChars * $this->noise_factor) : null;
    $this->lx = ($this->MaxChars + 1) * (int)(($this->MaxSize + $this->MinSize) / 1.5);
    $this->ly = (int)(2.4 * $this->MaxSize);

    $this->key = md5($this->SecretString);
    $this->PublicKey = substr(md5(uniqid(rand(),true)), 0, $this->MaxChars);

    $this->GarbageCollector();
    if($generate){
    $this->GenerateCaptchaImage();
    }
    }

    public function CheckCaptcha($public, $private)
    {
    $res = false;
    // when check, destroy picture on disk
    if(IsReadable($this->GetFileName($public)))
    {
    //$res = @unlink($this->GetFileName($public)) ? true : false;
    $res = (strtolower($private) == strtolower($this->GeneratePrivateKey($public))) ? true : false;
    }
    return $res;
    }

    public function GenerateCaptchaImage()
    {
    $private_key = $this->GeneratePrivateKey();
    // create Image and set the apropriate function depending on GD-Version & websafecolor-value
    if($this->gdVersion >= 2 && !$this->WebSafeColors)
    {
    $func1 = 'imagecreatetruecolor';
    $func2 = 'imagecolorallocate';
    }
    else
    {
    $func1 = 'imageCreate';
    $func2 = 'imagecolorclosest';
    }
    $image = $func1($this->lx,$this->ly);

    // Set Backgroundcolor
    $this->RandomColor(220, 255);
    $back = @imagecolorallocate($image, $this->r, $this->g, $this->b);
    @ImageFilledRectangle($image, 0, 0, $this->lx, $this->ly, $back);

    // allocates the 216 websafe color palette to the image
    if($this->gdVersion < 2 || $this->WebSafeColors) $this->MakeWebSafeColors($image);


    // fill with noise or grid
    if($this->nb_noise > 0)
    {
    // random characters in background with random position, angle, color
    for($i=0; $i < $this->nb_noise; $i++)
    {
    srand((double)microtime()*1000000);
    $size = intval(rand((int)($this->MinSize / 2.3), (int)($this->MaxSize / 1.7)));

    srand((double)microtime()*1000000);
    $angle = intval(rand(0, 360));

    srand((double)microtime()*1000000);
    $x = intval(rand(0, $this->lx));

    srand((double)microtime()*1000000);
    $y = intval(rand(0, (int)($this->ly - ($size / 5))));

    $this->RandomColor(160, 224);
    $color = $func2($image, $this->r, $this->g, $this->b);
    srand((double)microtime()*1000000);

    $text = chr(intval(rand(45,250)));
    @ImageTTFText($image, $size, $angle, $x, $y, $color, $this->ChangeFont(), $text);
    }
    }
    else
    {
    // generate grid
    for($i=0; $i < $this->lx; $i += (int)($this->MinSize / 1.5))
    {
    $this->RandomColor(160, 224);
    $color = $func2($image, $this->r, $this->g, $this->b);
    @imageline($image, $i, 0, $i, $this->ly, $color);
    }
    for($i=0 ; $i < $this->ly; $i += (int)($this->MaxSize / 1.8))
    {
    $this->RandomColor(160, 224);
    $color = $func2($image, $this->r, $this->g, $this->b);
    @imageline($image, 0, $i, $this->lx, $i, $color);
    }
    }

    // generate Text
    for($i=0, $x = intval(rand($this->MinSize, $this->MaxSize)); $i < $this->MaxChars; $i++)
    {
    $text = strtoupper(substr($private_key, $i, 1));

    srand((double)microtime()*1000000);
    $angle = intval(rand(($this->MaxRotation * -1), $this->MaxRotation));

    srand((double)microtime()*1000000);
    $size = intval(rand($this->MinSize, $this->MaxSize));

    srand((double)microtime()*1000000);
    $y = intval(rand((int)($size * 1.5), (int)($this->ly - ($size / 7))));

    $this->RandomColor(0, 127);
    $color =  $func2($image, $this->r, $this->g, $this->b);

    $this->RandomColor(0, 127);
    $shadow = $func2($image, $this->r + 127, $this->g + 127, $this->b + 127);

    @ImageTTFText($image, $size, $angle, $x + (int)($size / 15), $y, $shadow, $this->ChangeFont(), $text);
    @ImageTTFText($image, $size, $angle, $x, $y - (int)($size / 15), $color, $this->TTFfile, $text);
    $x += (int)($size + ($this->MinSize / 5));
    }
    @ImageJPEG($image, $this->GetFileName(), $this->jpg_quality);

    $res = IsReadable($this->GetFileName());
    @ImageDestroy($image);
    if(!$res)
    {
    throw new Exception(sprintf('Unable to safe captcha-image.'));
    }

    $this->CaptchaFileName = $this->GetRelativePath();
    }

    private function GarbageCollector()
    {
    $d = opendir($this->Directory);

    while (false !== ($file = readdir($d)))
    {
    $fmtime = filemtime($this->Directory . DIRECTORY_SEPARATOR . $file) + $this->OutOfDateTime;
    if($fmtime < time() && strstr($file, 'captcha_'))
    {
    @unlink($this->Directory . DIRECTORY_SEPARATOR . $file);
    }
    }
    }

    private function ChangeFont()
    {
    if(is_array($this->TTFRange))
    {
    srand((float)microtime() * 10000000);
    $key = array_rand($this->TTFRange);
    $this->TTFfile = $this->FontDirectory . DIRECTORY_SEPARATOR . $this->TTFRange[$key];
    }
    else
    {
    $this->TTFfile = $this->FontDirectory . DIRECTORY_SEPARATOR . $this->TTFRange;
    }
    return $this->TTFfile;
    }

    private function GeneratePrivateKey($public = '')
    {
    $public = empty($public) ? $this->PublicKey : $public;
    $key = substr(md5($this->key . $public), 16 - $this->MaxChars / 2, $this->MaxChars);
    $arr = str_split($key);
    $key = '';
    foreach($arr as $value)
    {
    $key .= substr(ord($value), strlen(ord($value)) - 1);
    }
    $key = substr($key, 0, $this->MaxChars);
    return $key;
    }

    public function GetFileName($public = '')
    {
    $public = empty($public) ? $this->PublicKey : $public;
    return $this->Directory . DIRECTORY_SEPARATOR . 'captcha_' . $public . ".jpg";
    }

    private function GetRelativePath()
    {
    return str_replace("\\", '/', str_replace(SITE_PATH_DOCROOT, '', $this->GetFileName()));
    }

    private function RandomColor($min, $max)
    {
    srand((double)microtime() * 1000000);
    $this->r = intval(rand($min,$max));
    srand((double)microtime() * 1000000);
    $this->g = intval(rand($min,$max));
    srand((double)microtime() * 1000000);
    $this->b = intval(rand($min,$max));
    }

    private function MakeWebSafeColors(&$image)
    {
    for($r = 0; $r <= 255; $r += 51)
    {
    for($g = 0; $g <= 255; $g += 51)
    {
    for($b = 0; $b <= 255; $b += 51)
    {
    $color = imagecolorallocate($image, $r, $g, $b);
    }
    }
    }
    }

    }

    function IsReadable($fileName)
    {
    $fp = @fopen($fileName, "r", true);
    $is_readable = is_resource($fp);
    if($is_readable)
    {
    fclose($fp);
    }

    return $is_readable;
    }

    ?>


    Создаём 2 папки в этом же каталоге:  "temp_captcha" - туда складываем картинки и "fonts", туда ложим фонты. Либо сами смотрим по конфигу класса. Фонты прилагаю. Хотите юзать свои - юзайте, только конф класса подправьте.

    p.s. функцию IsReadable тупо вырезал, потому как и класс надо было вырезать. Хотите - перенесите в класс. Да и саму функцию ReCaptcha можно убрать, но это так у меня - чтобы удобней было xD
  • md5

    Сообщения: 11960 Репутация: N Группа: в ухо

    Spritz 2 июня 2009 г. 12:23, спустя 9 минут 12 секунд

    а пример работы? )
    все умрут, а я изумруд
  • Josh

    Сообщения: 2008 Репутация: N Группа: Кто попало

    Spritz 2 июня 2009 г. 12:51, спустя 28 минут 35 секунд

    ДА сверхуж читай
    /
    **
    * Usage
    * ReCaptcha('generate') - generate Captcha, return array('key'=>PUBLIC_KEY, 'image'=> IMAGE_FILE_NAME)
    * ReCaptcha('check', array('public'=>PUBLIC_KEY, 'private'=>PRIVATE_KEY[user_input_value] )) - check captcha, return true/false
    * ReCaptcha('change', array('public'=>PUBLIC_KEY) - generate Captcha, return array('key'=>PUBLIC_KEY, 'image'=> IMAGE_FILE_NAME), and delete old cartcha image
    */

    Или на русском переписать? :)
    Картинки с текущими настройками держи, но там конфигом класса можно много чего поменять, в том числе и размер и кол-во цифр
  • md5

    Сообщения: 11960 Репутация: N Группа: в ухо

    Spritz 2 июня 2009 г. 12:56, спустя 4 минуты 27 секунд

    Josh, usage это понятно
    я имел ввиду картинки, да )
    все умрут, а я изумруд
  • md5

    Сообщения: 11960 Репутация: N Группа: в ухо

    Spritz 2 июня 2009 г. 12:57, спустя 1 минуту 19 секунд

    и че? прям непробиваемые?
    имхо, посложнее будет
    все умрут, а я изумруд
  • Professor

    Сообщения: 2089 Репутация: N Группа: Адекваты

    Spritz 2 июня 2009 г. 13:03, спустя 5 минут 53 секунды

    Моя круче =)

    http://ordenel.ru/mail/
  • Josh

    Сообщения: 2008 Репутация: N Группа: Кто попало

    Spritz 2 июня 2009 г. 13:05, спустя 2 минуты 12 секунд

    ну давай немного поиграемся с настройками. Так пойдёт? xD
  • Josh

    Сообщения: 2008 Репутация: N Группа: Кто попало

    Spritz 2 июня 2009 г. 13:06, спустя 49 секунд


    Моя круче =)


    твоя красивше :D
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 2 июня 2009 г. 13:07, спустя 41 секунду


    и че? прям непробиваемые?
    имхо, посложнее будет
    регу на гугль делал. там в дополнение к извращенной картинке идет извращенный алгоритм обработки - если с первого раза не угадываешь, то на след раз тебе точно скажут "неправильно" … и тп. часто говорят неправильно даже с первого раза))) гугль жжет. я капчу раз по 8 на аккаунт вбивал
    Сапожник без сапог
  • Josh

    Сообщения: 2008 Репутация: N Группа: Кто попало

    Spritz 2 июня 2009 г. 13:11, спустя 4 минуты 16 секунд

    Ору. При каждом открытии этой странички перегенеряться капчи на ordenel.ru и jeck.ru. И не по одному разу. Цитаты, етк. Кто то рад будет xD
  • md5

    Сообщения: 11960 Репутация: N Группа: в ухо

    Spritz 2 июня 2009 г. 13:20, спустя 8 минут 59 секунд


    Ору. При каждом открытии этой странички перегенеряться капчи на ordenel.ru и jeck.ru. И не по одному разу. Цитаты, етк. Кто то рад будет xD
    shit happens :)
    все умрут, а я изумруд
  • sap

    Сообщения: 2701 Репутация: N Группа: Кто попало

    Spritz 2 июня 2009 г. 13:21, спустя 41 секунду

    Думал пообсирать, но «капчокреатор» оказался очень даже ничего =)
  • Professor

    Сообщения: 2089 Репутация: N Группа: Адекваты

    Spritz 2 июня 2009 г. 13:30, спустя 9 минут 34 секунды

    да, хороший получился =)
  • Josh

    Сообщения: 2008 Репутация: N Группа: Кто попало

    Spritz 2 июня 2009 г. 13:50, спустя 19 минут 44 секунды


    Думал пообсирать, но «капчокреатор» оказался очень даже ничего =)
    o0 Поражён. А что даже без этого можно? xD
  • sap

    Сообщения: 2701 Репутация: N Группа: Кто попало

    Spritz 2 июня 2009 г. 15:57, спустя 2 часа 7 минут 3 секунды



    Думал пообсирать, но «капчокреатор» оказался очень даже ничего =)
    o0 Поражён. А что даже без этого можно? xD

    Не, ну могу доебаться)

    if(empty($this->gdVersion))
    {
    die();
    }

    Например, вот это считается хуевым стилем написания =) Функции именовать с большой буквы — тоже =)

    srand((double)microtime() * 1000000);

    RTFM
    Замечание: Начиная с PHP 4.2.0, больше нет необходимости инициализировать генератор случайных чисел функциями srand() или mt_srand(), поскольку теперь это происходит автоматически.


    Подавление ошибок (@) юзать вообще дурной тон.

    throw new Exception('No Truetypefont available');

    По-хорошему, нужно определять свой класс исключений.

    $key = substr($key, 0, $this->MaxChars);

    Может, я чего-то не понял, но зачем обрезать, нельзя сразу сгенерить нужной длины?

Пожалуйста, авторизуйтесь, чтобы написать комментарий!