Captcha component with PhpCaptcha

by spout
PhpCaptcha is a library for generating visual and audio CAPTCHAs (completely automated public Turing test to tell computers and humans apart).
Supported Features
  • Multiple random TrueType fonts
  • Character rotation
  • Optional chararacter shadow support
  • Optional site owner display text
  • Random custom background images
  • Font size selection
  • Greyscale or colour lines and characters
  • Character set selection
  • Integration of validation function for checking the user entered code with the generated code

NB: The audio CAPTCHA requires the Flite text to speech synthesis engine.


1.- Download PhpCaptcha http://www.ejeliot.com/pages/2 and unzip archive in /vendors/phpcaptcha directory
2.- Download Vera font files: http://ftp.gnome.org/pub/GNOME/sources/ttf-bitstream-vera/1.10/ttf-bitstream-vera-1.10.zip and unzip archive in /vendors/phpcaptcha/fonts/
3.- Create Captcha component:

Component Class:

<?php 
vendor
('phpcaptcha'.DS.'php-captcha.inc');

class 
CaptchaComponent extends Object
{
    var 
$controller;
 
    function 
startup( &$controller ) {
        
$this->controller = &$controller;
    }

    function 
image(){
        
        
$imagesPath realpath(VENDORS 'phpcaptcha').'/fonts/';
        
        
$aFonts = array(
            
$imagesPath.'VeraBd.ttf',
            
$imagesPath.'VeraIt.ttf',
            
$imagesPath.'Vera.ttf'
        
);
        
        
$oVisualCaptcha = new PhpCaptcha($aFonts20060);
        
$oVisualCaptcha->UseColour(true);
        
//$oVisualCaptcha->SetOwnerText('Source: '.FULL_BASE_URL);
        
$oVisualCaptcha->SetNumChars(6);
        
$oVisualCaptcha->Create();
    }
    
    function 
audio(){
        
$oAudioCaptcha = new AudioPhpCaptcha('/usr/bin/flite''/tmp/');
        
$oAudioCaptcha->Create();
    }
    
    function 
check($userCode$caseInsensitive true){
        if (
$caseInsensitive) {
            
$userCode strtoupper($userCode);
        }
        
        if (!empty(
$_SESSION[CAPTCHA_SESSION_ID]) && $userCode == $_SESSION[CAPTCHA_SESSION_ID]) {
            
// clear to prevent re-use
            
unset($_SESSION[CAPTCHA_SESSION_ID]);
            
            return 
true;
        }
        else return 
false;
        
    }
}
?>

4.- Use it in your Users controller

Controller Class:

<?php 
class UsersController extends AppController
{
    ...
    var 
$components = array('Captcha');
    ...
    function 
captcha_image()
    {
        
$this->Captcha->image();
    }
    
    function 
captcha_audio()
    {
        
$this->Captcha->audio();
    }
    ...
}
?>

5.- Display captcha image, in your template view:

View Template:


<img id="captcha" src="<?php echo $html->url('/users/captcha_image');?>" alt="" />
 <a href="javascript:void(0);" onclick="javascript:document.images.captcha.src='<?php echo $html->url('/users/captcha_image');?>?' + Math.round(Math.random(0)*1000)+1">Reload image</a>
Pretty cool, we can reload captcha image if unreadable ;o)

6.- Validate captcha code in your controllers with $this->Captcha->check() method.

With my cake apps I use the improved validation method explained on the bakery. http://bakery.cakephp.org/articles/view/more-improved-advanced-validation I've added this validation function to validation.php


function validateCaptcha($fieldName, $params){
        $caseInsensitive = true;
        
        $val = $this->data[$this->name][$fieldName];
        
        if ($caseInsensitive) {
            $val = strtoupper($val);
        }
        
        //php-captcha.inc.php
        if(!defined('CAPTCHA_SESSION_ID'))
            define('CAPTCHA_SESSION_ID', 'php_captcha');
         
         if (!empty($_SESSION[CAPTCHA_SESSION_ID]) && $val == $_SESSION[CAPTCHA_SESSION_ID]) {
            // clear to prevent re-use
            unset($_SESSION[CAPTCHA_SESSION_ID]);
            
            return true;
         }
         
         return false;
    }

And voil�

Report

More on Components

Advertising

Comments

  • frances posted on 01/10/11 03:33:34 AM
    To the user who cannot get any image rendered in any browser, I had the same initially

    Can I suggest that you have white space in a php after the end of php declaration
    ( ie ?> ) I had this and it was inserting blank spaced as the first byte in the jpeg file
    so all browser declared the image corrupt. ( the result of a bad cut and paste !!!)

    You can check if this is the case by altering the controller action

    function captcha_image()
    {
    Configure::write( 'debug', 0 );
    //$this->Captcha->image(); // comment this line out for testing !!!!!
    $this->autoRender = false;

    }

    With the line commented out - check in fire-bug and look at the size of the payload, in my case it was 1 byte .... and should be zero..

    Hope this helps
  • imaanand posted on 12/25/10 08:55:00 AM
    I wasted a lot of time to implement the captcha , but this article was useless at all ... also there is not reply for the problems ..
    I am also facing the problems as the others are facing
    1) The captcha is not being generate in any version of cakephp
    2) If i am using it from the webroot folder the images is being generate but the session is not working then for captcha ... and the session is being unset for the captcha .....

    At last this article wasted a lot of time of mine and was useless at all ......
  • Jbordignon posted on 08/09/10 02:54:38 PM
    somebody have the complete source code?
    i am begginer in cakePHP, i can show the image but i not understand the validation..

    thanks
  • XanderSX posted on 04/16/10 02:31:29 AM
    I can't get the captcha image too. I just have the link to refresh the image.

    I know I'm starting with CakePHP, but I think the installation of this component need more comments and infos. It'll be helpful ;) !
  • Brightsolns posted on 02/18/10 06:16:58 AM
    I have used for contact form.
    Captcha is not displayed in that form
  • voidet posted on 09/17/09 07:17:12 PM
    After seeing white characters being displayed in the captcha image going through the php-captcha.php code i found they weren't deallocating colours.

    And on line 316 imagecolordeallocate($this->oImage, $iTextColour);

    This sorted the white text issue for me!
  • madhan posted on 06/05/09 06:46:39 AM
    i also get the same problem, Image is not shown in myn browser only image reload link only shown..

    Can anyone pleasce help me out....
  • meekamoo posted on 05/17/09 08:48:38 AM
    I'm having problems getting this working in 1.2

    Checklist:
    - vendors/phpcaptcha
    - vendors/phpcaptcha/fonts
    - rename phpcaptcha.inc.php to phpcaptcha.php
    - update the App:import
    - update the $imagesPath variable

    When I run /controller/captcha_image I get an error saying that the view does not exist.

    Do I need to create a views/controller/captcha_image.ctp ? If so what do I need to insert into that?

    Great plugin though - just wish I could get it to work :(
  • mohan_agadkar posted on 05/11/09 01:42:21 PM
    1) Rename vendors/phpcaptcha/php-captcha.inc.php file to phpcaptcha.php

    2) In controllers/components/captcha.php change the line
    vendor('phpcaptcha'.DS.'php-captcha.inc');
    to
    App::import('Vendor', 'phpcaptcha/phpcaptcha');

    Hope that works.
  • jamezrsanchez posted on 04/14/09 04:05:37 PM
    What should i name my component..

    Only the reload image is shown.. help pls
  • vikaspt9 posted on 03/02/09 09:28:51 AM
    I follow all the rules for creating components but still cant get image..
    It shows me imagebox but I cant found image..

    I tried almost every thing but cant get image..

    Please help me out..
  • amarradi posted on 12/17/08 09:02:19 AM
    Hello together,

    i used this code in cakePHP 1.2
    in my template.

    <img id="captcha" src="<?php echo $html->url('/users/captcha_image');?>" alt="" />
     <a href="javascript:void(0);" onclick="javascript:document.images.captcha.src='<?php echo $html->url('/users/captcha_image');?>?' + Math.round(Math.random(0)*1000)+1">Reload image</a> 

    But i get no Picture there ar only a link 'Reload Image'. But No Pict. I allowed all scripts and use ff. What sould i do now. In Konqueror it doesn't run.
  • amarradi posted on 12/17/08 08:32:48 AM
    Hello together,

    i started to develop PHP5. And i started also with cakephp. Its very good how fast and easy i get an result. But now i tried to use this captcha with CakePHP 1.2.0.7692. I'm at that point that i want to try out i had copied it into Netbeans 6.5 and uploaded it on my Apache...
    This is my Strukture

    app
    -vendors
    --phpcaptcha
    ---fonts
    --+php-captcha.inc

    -controllers
    +mycontrollerclass.php
    --components
    --+captcha.php
    -models
    +mymodelclass.php
    -views
    --myviews
    --+myviews.ctp

    in the vendors folder(not under app) are the files

    when i try to call my application i get such error
    Fatal error: Call to undefined function vendor() in /opt/lampp/htdocs/cakePHP/app/controllers/components/captcha.php on line 2
    all files of the captcha Components are copied from this page and pasted into my cakePHP environmemt.
    Where should is the place for the phpcaptcha and the fonts? In the app folder or in the cakePHP Folder?

    thanks for the help.

    Many greetings

    Marcus Radisch
    • amarradi posted on 12/17/08 08:54:22 AM
      I solved it, because there are a solution for cake 1.2

      • Mutdogus posted on 02/02/09 01:48:08 AM
        I solved it, because there are a solution for cake 1.2


        The solution to this problem is to replace (in captcha.php),

        vendor('phpcaptcha'.DS.'php-captcha.inc');

        with

        App::import('Vendor', 'phpcaptcha/php-captcha.inc');

        since vendor(); is depreciated.
  • kumar posted on 10/29/08 09:49:52 PM
    good job, this is exactly what am looking for
  • limule posted on 07/17/08 06:42:25 AM
    Hi,
    When I try something like http://localhost/myapplication/webusers/captcha_image?1234, it works well but I always get the same picture, whatever the number I use.
    What could I do ? An idea ?
  • martijngh posted on 06/16/08 12:43:18 PM
    Hi,

    I have another problem with keeping the S_SESSION variables. I found out that in some circumstances, the $_SESSION varialbes are unset when vendor phpcaprcha.php send a header request, telling the browser that a jpeg file is send. Commenting out this line, and the $_SESSION variables can be retrieved later on.

    The strange thing is that it happens not always. I have a test and a stage environment, on the test environment the issue does not occur, while the ocde is the same. Aslo it worked on the stage environment, until today.

    Anybody has a clue why this is happening ?

    Thanks in advance,

    Martijn
  • martijngh posted on 06/16/08 12:36:01 PM
    Hi,

    I had basically the same problem. When I noticed that the problem only occured with e-mail component, I realized that I copied and pasted the code of the e-mail component from the cakebaker website.

    Another component did not have the issue. So I took the file of this component, copied the code for the captcha component into this file, removed the original code and renamed the file to captcha.php. And guess what .. it worked.

    Really strange.
  • projjwal135 posted on 05/28/08 07:12:52 AM
    Hi All

    I am facing a problem with adding multiple component.

    I am giving my Controller code....


    class ContactsController extends AppController
    {
    var $name = 'Contacts';
    var $layout = 'contact_template';
    var $components = array('Captcha','Email');
    // use component email

    function index()
    {
    if (!empty($this->data))
    {
    $this->Contact->set($this->data);

    if($this->Contact->validates())
    {
    $postValid = TRUE;
    if(!empty($this->data['Contact']['captcha']))
    {
    $trfl = $this->Captcha->check($this->data['Contact']['captcha']);
    if($trfl == false)
    {
    $this->Contact->invalidate('captcha');
    $postValid = FALSE;
    }
    }
    if($postValid)
    {
    $tr = $this->Contact->sendmail($this->data['Contact']);
    if($tr)
    {

    //@mail("projjwal@indusnet.co.in",$sub,$massage,"From: Projjwal ");
    //$this->set('data', $this->data);
    $this->Email->to = 'projjwal@indusnet.co.in';
    $this->Email->subject = 'your new Contact';

    $result = $this->Email->send();
    $this->flash('A mail has been send to admin.','/contacts',2);
    }else
    {
    $this->render();
    }
    }else
    {

    $this->render();
    }
    }else
    {
    $this->render();
    }
    }else
    {
    $this->render();
    }

    }
    function captcha_image()
    {
    $this->Captcha->image();

    }

    function captcha_audio()
    {
    $this->Captcha->audio();
    }

    }
    ?>
    When I am using this code the Captcha is not working.
    When I am removing the Email from the $components array
    it's working fine.

    Can any one tell me why it's happenning?

    Thanks in advance.

    Projjwal
  • projjwal135 posted on 05/27/08 12:56:48 AM
    Hi,

    I am facing a big problem with show error massage while validating the Captcha code.

    I am giving my code...

    var $validate = array('captcha' => array('checkv' => array ('rule' =>'checkv','message' => 'put correct value')));

    and my validation model function is

    function checkv($userCode1){
    $userCode = $userCode1['captcha'];
    $caseInsensitive = true;
    if ($caseInsensitive) {
    $userCode = strtoupper($userCode);
    }
    //echo $userCode." ".$_SESSION[CAPTCHA_SESSION_ID];
    if (!empty($_SESSION[CAPTCHA_SESSION_ID]) && $userCode == $_SESSION[CAPTCHA_SESSION_ID]) {
    // clear to prevent re-use
    unset($_SESSION[CAPTCHA_SESSION_ID]);

    return true;
    }
    else return false;

    }

    But this code is giving an error massage...


    Warning: preg_match() expects parameter 1 to be string, array given in cake/libs/model/model_php5.php on line 1385

    And this is actually not validate when I am giving correct code for captche.

    Please help me.

    Thanks
    Projjwal
  • fuzz posted on 05/12/08 03:36:11 PM
    Hi, I see that many people have problems with phpcaptcha working on cakephp 1.2 so I paste here version which runs perfectly:

    Component Class:

    <?php 
    App
    ::import('Vendor','PhpCaptcha' ,array('file'=>'phpcaptcha/php-captcha.php'));
            
    class 
    CaptchaComponent extends Object
    {
        var 
    $controller;
     
        function 
    startup( &$controller ) {
            
    $this->controller = &$controller;
        }

        function 
    image(){
            
            
    $imagesPath APP 'vendors' DS 'phpcaptcha'.'/fonts/';
            
            
    $aFonts = array(
                
    $imagesPath.'VeraBd.ttf',
                
    $imagesPath.'VeraIt.ttf',
                
    $imagesPath.'Vera.ttf'
            
    );
            
            
    $oVisualCaptcha = new PhpCaptcha($aFonts20060);
            
            
    $oVisualCaptcha->UseColour(true);
            
    //$oVisualCaptcha->SetOwnerText('Source: '.FULL_BASE_URL);
            //$oVisualCaptcha->SetNumChars(6);
            
    $oVisualCaptcha->Create();
        }
        
        function 
    audio(){
            
    $oAudioCaptcha = new AudioPhpCaptcha('/usr/bin/flite''/tmp/');
            
    $oAudioCaptcha->Create();
        }
        
        function 
    check($userCode$caseInsensitive true){
            if (
    $caseInsensitive) {
                
    $userCode strtoupper($userCode);
            }
            
            if (!empty(
    $_SESSION[CAPTCHA_SESSION_ID]) && $userCode == $_SESSION[CAPTCHA_SESSION_ID]) {
                
    // clear to prevent re-use
                
    unset($_SESSION[CAPTCHA_SESSION_ID]);
                
                return 
    true;
            }
            else return 
    false;
            
        }
    }
    ?>

    This is action which renders captcha:


      function captcha_image()
      {
        Configure::write('debug',0);
        $this->layout = null;  
        $this->Captcha2->image();
        $this->render();
      } 
  • djspark posted on 04/29/08 12:36:28 PM
    I'm not seeing where I can download this component, something wrong with the bakery?
  • yagemi posted on 03/31/08 04:07:53 PM
    hi ! first thanks for this great component.
    phpcaptcha works fine on mine server as standalone. so all libs a working properly.

    if i want to use it within my controller, i just got an "broken-image" in IE or the url in Firefox.
    when viewing the source i noticed, that there are html-elements.. looks like some parts of my layout...
    maybe this causes the failure?

    i got absolutely no idea why my layout is used.
    even a

    Controller Class:

    <?php 
        
    function captcha_image()
        {    
            
    $this->layout FALSE;
            
    $this->Captcha->image();
        }
    ?>

    won't work.. any ideas on that?
    • yagemi posted on 04/01/08 10:52:44 AM
      i just noticed that before output, starts, there are
      THREE BLANK SPACES and i can't explain where they are from. even with no layout - these spaces are there..

      but guess what: they are on every page generated within cakephp. on every site 3 blank spaces at the beginning. anyone has an idea which scripts generates them? maybe because of them already html output has been startet and the image could be displayed.

      thx in advance for every help ( if i get some ^^ )
  • lecterror posted on 12/17/07 07:51:06 AM
    Thanks for the submission, I had captcha working within minutes with no trouble at all!

    p.s. it seems I'm not able to rate anything on Bakery, as soon as this issue is fixed I'll give it a 5 :-)
  • cartv posted on 11/05/07 06:21:08 AM
    also trying to get it work on 1.2.
    seems like the response headers are already sent and php-captcha.inc.php kannt set the mime-type header to image/jpg
    • cartv posted on 11/05/07 06:44:03 AM
      hehe

      der was an space after my closing ?> tag in captcha.php which caused the headers to be send...

      :-)
  • wendellm posted on 10/14/07 09:01:55 AM
    I tried it on Windows using CakePHP 1.2alpha and PHP 5. It's giving me an "X" image on IE and FF. I've read the post by Manuel Dorado but my gd library is already working.

    Your help is greatly appreciated.

    Thank you.
  • sivaprasad posted on 08/28/07 04:09:37 AM
    My captcha validation is working properly in FF,but the Reload Image link is not working in the internet explorer.

    Can any body suggest me actualy where i am wrong

    Waiting for a reply
  • sam.contesse posted on 07/28/07 07:15:02 AM
    This is what I had to do to get Captcha component working with validator (CakePHP 1.2). It is quiet easy but I had some troubles to understand the new validation process. Hope it will help somebody else.

    Model Class:

    <?php 

        $validate 
    = array(
            
    'captcha' => array (
                
    'validateCaptcha' => array (
                    
    'rule' => 'validateCaptcha',
                    
    'message' => 'Your captcha error message'
                
    )
            )
        );

        function 
    validateCaptcha($check) {
            if (!
    defined('CAPTCHA_SESSION_ID')) {
                
    define('CAPTCHA_SESSION_ID''php_captcha');
            }

            if (!empty (
    $_SESSION[CAPTCHA_SESSION_ID]) && $check == $_SESSION[CAPTCHA_SESSION_ID]) {
                unset (
    $_SESSION[CAPTCHA_SESSION_ID]);
                return 
    true;
            }
            return 
    false;
        }
    ?>

    Note that the field $validate has been declared in my child model class called "Post" and the method validateCaptcha is in the parent AppModel class.
  • louiemiranda posted on 07/26/07 12:50:38 AM

    Ok, i was able to make this work.

    Although, i am a bit clueless. On how will i add an error message on the template itself. Here are sample of my codes.

    Controller Class:

    <?php 
    ...
    if (empty(
    $this->data))
    {
        
    $this->render();
    }
    else
    {

        if (
    $this->Email->save($this->data))
        {
        if (
    $this->Captcha->check($this->data['Email']['userCode'])) { 
            
        
    // Flash that it has been sent
        
    $this->flash('Your email has been sent.','/emails');
                
        }
            
        }
        else
        {
            
    $this->set('errorMessage''Please correct errors below.');
            
    $this->render();
        }

    }
    ...
    ?>
    I was able to validate the usual fields i added:

    View Template:


    ...
    <label>Name:</label>
    <?php echo $html->input('Email/name', array('class' => 'input''style' => 'width: 200px;')); ?>
    <?php 
    echo $html->tagErrorMsg('Email/name''Name is required.'); ?>
    <label>Message:</label>
    <?php echo $html->textarea('Email/message', array('rows'=>'10''cols'=>'40')); ?>
    <?php 
    echo $html->tagErrorMsg('Email/message''Message is required.'); ?>

    <label>Captcha:</label>
    <?php echo $html->input('Email/userCode', array('class' => 'input''style' => 'width: 200px;')); ?>
    <?php 
    echo $html->tagErrorMsg('Email/userCode''Captcha is required.'); ?>
    ...

    which is name and message and captcha (if its empty only).

    But to show that what you typed is wrong, i don't know what to do.
    Please help!

  • ryoko_vegetable posted on 07/11/07 04:38:10 AM
    Have anybody got solution.
    Thank!!
  • mdorado posted on 06/21/07 03:39:27 PM
    i tried in windows and linux, and i couldn't get it to work, gives me an 'X' image on IE and blank on FF.

    when i am trying to debug by accesing directly to the url /users/captcha_image says that the view is missing.

    what should i do?

    • mdorado posted on 06/21/07 04:47:52 PM
      i tried in windows and linux, and i couldn't get it to work, gives me an 'X' image on IE and blank on FF.

      when i am trying to debug by accesing directly to the url /users/captcha_image says that the view is missing.

      what should i do?

      i shold recompile my php to support gd libraries, and be carefull with the imagesPath directory...

      very great component! thanks Spout.

      i realize that after debug step by step the vendor captcha php.

  • darius posted on 06/13/07 06:06:52 PM
    Hey, this is a handy component. I was just looking for this.

    Here are a few things i noticed:

    on line 14 of captcha.php:
    $imagesPath = realpath(VENDORS . 'phpcaptcha').'/fonts/';
    if your vendors path is inside your app directory, you need something like this:

    $imagesPath = APP . 'vendors' . DS . 'phpcaptcha'.'/fonts/';

    also, for the validation, i changed:

    function validateCaptcha($fieldName, $params){
            $caseInsensitive = true;

    to :

    function validateCaptcha($fieldName, $caseInsensitive = true){

    since the $params var is not used in the function, and it's handy to have the case sensitivity as a parameter.

    Also, for anyone using this who is also using sessions (either Cake's or your own), be sure to look at the vendor file php-captcha.inc and comment out line 46, where the script calls session_start() , or you will definitely experience some session problems.

    Thanks for the work, Spout.

    dd
login to post a comment.