Captcha component with Securimage

By Debugged Interactive Designs (debuggeddesigns)
Securimage is an open-source free PHP CAPTCHA script for generating complex images and CAPTCHA codes to protect forms from spam and abuse. It can be easily added into existing forms on your website to provide protection from spam bots. It can run on most any webserver as long as you have PHP installed, and GD support within PHP. Securimage does everything from generate complicated CAPTCHA images to making sure the code the user entered was correct.

Securimage Features

  • Show an image in just 3 lines of code
  • Validate submitted entries in less than 6 lines of code
  • Customizable code length
  • Choose the character set
  • TTF font support
  • Use custom GD fonts when TTF is not available
  • Easily add background images
  • Multi colored, angled, and transparent text options
  • Arched lines through text
  • Generates audible CAPTCHA files in wav format
  • Use a word list for creating CAPTCHA codes

Step 1: Download and unzip Securimage archive

Download a Securimage archive (either .zip or .tar.gz) at http://www.phpcaptcha.org/download/ and unzip the archive into the directory /app/vendors/securimage/


Step 2: Create captcha component

Filename: /app/controllers/components/captcha.php

Component Class:

Download code <?php 

/**
 * Securimage-Driven Captcha Component
 * @author debuggeddesigns.com
 * @license MIT
 * @version 0.1
 */
 
//cake's version of a require_once() call
vendor('securimage'.DS.'securimage'); //use this with the 1.1 core
//App::import('Vendor','Securimage' ,array('file'=>'securimage'.DS.'securimage.php')); //use this with the 1.2 core
  
 
//the local directory of the vendor used to retrieve files
define('CAPTCHA_VENDOR_DIR'APP 'vendors' DS 'securimage/');

class 
CaptchaComponent extends Object {

    var 
$controller;

    
//size configuration
    
var $_image_height 75//the height of the captcha image
    
var $_image_width 350//the width of the captcha image
    
    
    //background configuration
    
var $_draw_lines true//whether to draw horizontal and vertical lines on the image
    
var $_draw_lines_over_text false//whether to draw the lines over the text
    
var $_draw_angled_lines true//whether to draw angled lines on the image
    
    
var $_image_bg_color '#ffffff'//the background color for the image
    
var $_line_color '#cccccc'//the color of the lines drawn on the image
    
var $_line_distance 15//how far apart to space the lines from eachother in pixels
    
var $_line_thickness 2//how thick to draw the lines in pixels
    
var $_arc_line_colors '#999999,#cccccc'//the colors of arced lines
    
    
    //text configuration
    
var $_use_gd_font false//whether to use a gd font instead of a ttf font
    
var $_use_multi_text true//whether to use multiple colors for each character
    
var $_use_transparent_text true//whether to make characters appear transparent
    
var $_use_word_list false//whether to use a word list file instead of random code
    
    
var $_charset 'ABCDEFGHKLMNPRSTUVWYZ23456789'//the character set used in image
    
var $_code_length 5//the length of the code to generate
    
var $_font_size 45//the font size
    
var $_gd_font_size 50//the approxiate size of the font in pixels
    
var $_text_color '#000000'//the color of the text - ignored if $_multi_text_color set
    
var $_multi_text_color '#006699,#666666,#333333'//the colors of the text
    
var $_text_transparency_percentage 45//the percentage of transparency, 0 to 100
    
var $_text_angle_maximum 21//maximum angle of text in degrees
    
var $_text_angle_minimum = -21//minimum angle of text in degrees
    
var $_text_maximum_distance 70//maximum distance for spacing between letters in pixels
    
var $_text_minimum_distance 68//minimum distance for spacing between letters in pixels
    
var $_text_x_start 10//the x-position on the image where letter drawing will begin
    
    
    //filename and/or directory configuration
    
var $_audio_path 'audio/'//the full path to wav files used
    
var $_gd_font_file 'gdfonts/bubblebath.gdf'//the gd font to use
    
var $_ttf_file 'elephant.ttf'//the path to the ttf font file to load
    
var $_wordlist_file 'words/words.txt'//the wordlist to use
    
    
    
function startup( &$controller ) {

        
//add local directory name to paths
        
$this->_ttf_file CAPTCHA_VENDOR_DIR.$this->_ttf_file
        
$this->_gd_font_file CAPTCHA_VENDOR_DIR.$this->_gd_font_file;
        
$this->_audio_path CAPTCHA_VENDOR_DIR.$this->_audio_path;
        
$this->_wordlist_file CAPTCHA_VENDOR_DIR.$this->_wordlist_file
        
//CaptchaComponent instance of controller is replaced by a securimage instance
        
$controller->captcha =& new securimage();
        
$controller->captcha->arc_line_colors $this->_arc_line_colors;
        
$controller->captcha->audio_path $this->_audio_path;
        
$controller->captcha->charset $this->_charset;
        
$controller->captcha->code_length $this->_code_length;
        
$controller->captcha->draw_angled_lines $this->_draw_angled_lines;
        
$controller->captcha->draw_lines $this->_draw_lines;
        
$controller->captcha->draw_lines_over_text $this->_draw_lines_over_text;
        
$controller->captcha->font_size $this->_font_size;
        
$controller->captcha->gd_font_file $this->_gd_font_file;
        
$controller->captcha->gd_font_size $this->_gd_font_size;
        
$controller->captcha->image_bg_color $this->_image_bg_color;
        
$controller->captcha->image_height $this->_image_height;
        
$controller->captcha->image_width $this->_image_width;
        
$controller->captcha->line_color $this->_line_color;
        
$controller->captcha->line_distance $this->_line_distance;
        
$controller->captcha->line_thickness $this->_line_thickness;
        
$controller->captcha->multi_text_color $this->_multi_text_color;
        
$controller->captcha->text_angle_maximum $this->_text_angle_maximum;
        
$controller->captcha->text_angle_minimum $this->_text_angle_minimum;
        
$controller->captcha->text_color $this->_text_color;
        
$controller->captcha->text_maximum_distance $this->_text_maximum_distance;
        
$controller->captcha->text_minimum_distance $this->_text_minimum_distance;
        
$controller->captcha->text_transparency_percentage $this->_text_transparency_percentage;
        
$controller->captcha->text_x_start $this->_text_x_start;
        
$controller->captcha->ttf_file $this->_ttf_file;
        
$controller->captcha->use_gd_font $this->_use_gd_font;
        
$controller->captcha->use_multi_text $this->_use_multi_text;
        
$controller->captcha->use_transparent_text $this->_use_transparent_text;
        
$controller->captcha->use_word_list $this->_use_word_list;
        
$controller->captcha->wordlist_file $this->_wordlist_file;
        
$controller->set('captcha',$controller->captcha);
    }
}

?>


Step 3: Use the captcha component inside a controller

Filename: /app/controllers/contacts_controller.php

Controller Class:

Download code <?php 

class ContactsController extends AppController {
    
    var 
$name 'Contacts';
    var 
$components = array('Captcha');
     
    function 
securimage($random_number){
        
$this->autoLayout false//a blank layout

        //override variables set in the component - look in component for full list
        
$this->captcha->image_height 75;
        
$this->captcha->image_width 350;
        
$this->captcha->image_bg_color '#ffffff';
        
$this->captcha->line_color '#cccccc';
        
$this->captcha->arc_line_colors '#999999,#cccccc';
        
$this->captcha->code_length 5;
        
$this->captcha->font_size 45;
        
$this->captcha->text_color '#000000';

        
$this->set('captcha_data'$this->captcha->show()); //dynamically creates an image
    
}

    function 
index(){
        
$this->set('captcha_form_url'$this->webroot.'contacts/index'); //url for the form
        
$this->set('captcha_image_url'$this->webroot.'contacts/securimage/0'); //url for the captcha image

        
$captcha_success_msg 'The code you entered matched the captcha';
        
$captcha_error_msg 'The code you entered does not match';

        if( empty(
$this->data) ){ //form has not been submitted yet
            
$this->set('error_captcha'''); //error message displayed to user
            
$this->set('success_captcha'''); //success message displayed to user
            
$this->render(); //reload page
        
} else { //form was submitted     
            
if( $this->captcha->check($this->data['Contact']['captcha_code']) == false ) {
                
//the code was incorrect - display an error message to user
                
$this->set('error_captcha'$captcha_error_msg); //set error msg
                
$this->set('success_captcha'''); //set success msg
                
$this->render(); //reload page
            
} else {
                
//the code was correct - display a success message to user
                
$this->set('error_captcha'''); //set error msg
                
$this->set('success_captcha'$captcha_success_msg); //set success msg
                
$this->render(); //reload page

                //after testing is complete, you would process the other form data here and save it
            
}
        }
    }
}

?>


Step 4: Create a Contact model

Filename: /app/models/contact.php

View Template:

Download code
<?php
class Contact extends AppModel {
   var 
$useTable false;
}
?> 


Step 5: Create a view to hold the dynamic image

Filename: /app/views/contacts/securimage.thtml

View Template:

Download code
<?php echo $captcha_data?>


Step 6: Create a view to test the captcha with

Filename: /app/views/contacts/index.thtml

View Template:

Download code
<form action="<?php echo $captcha_form_url?>" method="post">
<div>Verify :</div>
<div><img src="<?php echo $captcha_image_url?>" id="captcha" alt="CAPTCHA Image" /></div>
<div><input type="text" name="data[Contact][captcha_code]" size="10" maxlength="6" value="" /></div>
<div><a href="#" onclick="document.getElementById('captcha').src = '<?php echo $this->webroot;?>contact/securimage/' + Math.random(); return false">Reload Image</a></div>
<div style="color:red;"><?php echo $error_captcha?></div>
<div style="color:green;"><?php echo $success_captcha?></div>
<div><input type="submit" value="CLICK HERE TEST THE CAPTCHA" /></div>
</form>

 

Comments 814

CakePHP Team Comments Author Comments
 

Comment

1 Not working

Hi,

Thanks for the code but I can't get the CAPTCHA image to show any characters. All I see in the image is a couple of arc lines. Any ideas what the problem is?

Also, shouldn't the views in Steps 4-6 have the .CTP extension?
Posted Oct 22, 2008 by Mike Dowson
 

Comment

2 captcha image reload via ajax call?

Hi, is it possible to reload the generated captcha image via an ajax-link in the view? I've tried without success..
Posted Oct 28, 2008 by skep
 

Comment

3 Thanks!

Thanks a lot mate! It works like charm!
Posted Nov 6, 2008 by Ramiro Araujo
 

Comment

4 Re: Not working

Hi Mike,

Have you tried using a gd font? ($_use_gd_font var in captcha.php)
Or made sure the code length is > 1? ($_code_length var in captcha.php)
Or made sure the font files exist in the vendors/securimage directory? ($_gd_font_file and $ttf_file vars in captcha.php)

Yes, I probably should have used .ctp - the .thtml extension was used in the cake 1.1 core - old habits.

Hope that helped.
Posted Nov 21, 2008 by Debugged Interactive Designs
 

Question

5 Awsome!

This component installed like a piece of cake!

Looks great to.

Well I got it up and running with no problems but I'd like to add the reload button. I cant seem to find the function for it. Any one figured this one out?

Thanks!

justclint
Posted Dec 22, 2008 by Clint Avalos
 

Question

6 img src empty

I've installed as described on the page and when going to my Captcha test page the Captcha image is not being displayed. Only the "alt" image is shown. Doing a 'view source' shows that img src is blank (i.e. img src=""). I've double-checked the "captcha_image_url" in the contacts_controller.php file and even tried to modify it, but I can't seem to get the img src url inserted.

Anyone have any ideas what I'm doing wrong?
Posted Dec 30, 2008 by Martin
 

Comment

7 Re:

I've installed as described on the page and when going to my Captcha test page the Captcha image is not being displayed. Only the "alt" image is shown. Doing a 'view source' shows that img src is blank (i.e. img src=""). I've double-checked the "captcha_image_url" in the contacts_controller.php file and even tried to modify it, but I can't seem to get the img src url inserted.

Anyone have any ideas what I'm doing wrong?

Hello, if you are using the 1.2 version be sure that you change the line in the component:
//App::import('Vendor','Securimage' ,array('file'=>'securimage/securimage.php')); //use this with the 1.2 core  you have to uncomment that line and comment the other one.
Second be sure that you are using all the call to the controller well, if you have your own controller like users change contacts to user.
Third if you have a Auth component you have to add this actions ('index', 'securimage') to the allow. pd: index change for your action.
    function beforeFilter(){
        $this->Auth->allow('signup', 'home', 'update_select', 'confirm', 'index', 'securimage');
    }
something like that could be.
good luck.
Posted Jan 12, 2009 by David
 

Comment

8 Alternate for using blank layout

Instead of using blank layout, if you set $this->autoLayout to false in controller's action then it will just return current page's content (not with layout content)
Posted Jan 17, 2009 by Amit Badkas
 

Comment

9 Add this Contact model...

For noobs like me who are getting an error that it can't find the Contact table:

Create /app/models/contact.php:

<?php

class Contact extends AppModel {
   var 
$useTable false;
}

?>


Once I did this the demo worked perfectly with no other changes.
Posted Feb 9, 2009 by Steve Kehlet
 

Comment

10 Updated article

I added a reload button that uses javascript to update the image. I also added the Contact model and removed the blank view.
Posted Feb 18, 2009 by Debugged Interactive Designs
 

Question

11 Word problem

HI,

everything works fine but: when i reload the page, the same letters are displayed. I thought everytime the page is reloaded or the user captcha code is false, an another word will be displayed. I have the word list in an Words - Folder, and i runned the server_test file and everything looks ok
Need some help with that.

Thanks
Posted Mar 11, 2009 by Florin
 

Comment

12 solution to this

HI,

everything works fine but: when i reload the page, the same letters are displayed. I thought everytime the page is reloaded or the user captcha code is false, an another word will be displayed. I have the word list in an Words - Folder, and i runned the server_test file and everything looks ok
Need some help with that.

Thanks

That's a bug in some PHP versions. Yo should replace all the instances to "rand(xxxx,xxxx)" function in the file secureimage.php by "mt_rand(xxxx,xxxx)". This worked for me.
Posted Mar 14, 2009 by Igor
 

Comment

13 ob_clean() to showing the captcha image

Hi, after installing I had a problem: the image was not displayed.
I have added in contacts_controller.php before the line
$this->set('captcha_data', $this->captcha->show()); //dynamically creates an image 
the function
ob_clean(); to cleaning output buffer.
Now it works perfect. Thanks for the code, it is very useful.
Posted Mar 24, 2009 by Victor Petrov
 

Comment

14 It Works

Hi Igor,

thanks a lot man, this has resolved my problem!

Flowreen
Posted Apr 7, 2009 by Florin
 

Question

15 Problem

First thanks for this useful tutorials ..

I have 2 problem when excute :

first one :
Warning (2): session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at C:\xampp\htdocs\cakephp\app\controllers\contacts_controller.php:53) [APP\vendors\securimage\securimage.php, line 422]
second the image not display

Any idea .... Thank
Posted Apr 7, 2009 by soma
 

Comment

16 might be white spaces

First thanks for this useful tutorials ..

I have 2 problem when excute :

first one :
Warning (2): session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at C:\xampp\htdocs\cakephp\app\controllers\contacts_controller.php:53) [APP\vendors\securimage\securimage.php, line 422]
second the image not display

Any idea .... Thank

Do you have any white spaces outside the php tags in your controller class? When I copy the contacts_controller code into my SDK I always have a trailing extra line at the end.

Posted Apr 7, 2009 by Debugged Interactive Designs
 

Question

17 Captcha validation using model

Hello...

Thanks for this useful tutorial. I have used it in my user registration form and it works like charm. However I have one doubt. (Apologies if this question is felt to be slightly off topic)

I use the model to validate the rest of the fields of the registration form i.e by defining an array $ validates. I wanted my captcha to also work through the model (using a function) rather than the controller as described by this example.

I have tried writing one. However I have been unsuccessful. I face errors with "$this->captcha->check($this->data['User']['captcha_code'])"

I am unable to get captcha->check to work in the model... any help with reg to same will be appreciated...

regards
nikhil
Posted Apr 13, 2009 by Nikhil
 

Comment

18 Can't get the CAPTCHA image

Hi, I got the same problem as Mike. I've tried everything you mentioned in last reply, but they didn't work. The output of securimage.thtml was something like "‰PNG  ��� IHDR���¯". It looks like that's the binary code of the image. Please help.


Hi Mike,

Have you tried using a gd font? ($_use_gd_font var in captcha.php)
Or made sure the code length is > 1? ($_code_length var in captcha.php)
Or made sure the font files exist in the vendors/securimage directory? ($_gd_font_file and $ttf_file vars in captcha.php)

Yes, I probably should have used .ctp - the .thtml extension was used in the cake 1.1 core - old habits.

Hope that helped.
Posted May 12, 2009 by Lei Sun
 

Comment

19 Perfect

This worked in 5 mins, Thank you !!

Controller name is mistyped the index view at Reload Image:

webroot;?>contact/securimage/

should be contacts


Thanks,

Andras
Posted May 12, 2009 by Andras Kende
 

Comment

20 Session_start

I also encounter this error. Can anybody help?

Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at D:\MySiteapp\controllers\components\captcha.php:109) in D:\MySite\app\vendors\securimage\securimage.php on line 422...

If I will comment the session_start() (at securimage.php), it will not display the error but still the image will not display...

By the way, it would be better if you send us a sample working script using the cakephp.. :).. Please help the junins!!! :)
Posted May 15, 2009 by Pareng Erns
 

Comment

21 working code

http://www.debuggeddesigns.com/files/app.zip
this app configuration uses the latest cake release and has the latest secure image download... hope this helps
Posted May 18, 2009 by Debugged Interactive Designs
 

Comment

22 working code

http://www.debuggeddesigns.com/files/app.zip
this app configuration uses the latest cake release and has the latest secure image download... hope this helps


Thanks for the app.zip ...it's working now...
Posted Jun 7, 2009 by Pareng Erns