I am using the captcha component.
<?php
function create($width='120',$height='40',$characters='6') {
$code = $this->generateCode($characters);
/* font size will be 75% of the image height */
$font_size = $height * 0.70;
$image = #imagecreate($width, $height) or die('Cannot initialize new GD image stream');
/* set the colours */
$background_color = imagecolorallocate($image, 220, 220, 220);
$text_color = imagecolorallocate($image, 10, 30, 80);
$noise_color = imagecolorallocate($image, 150, 180, 220);
/* generate random dots in background */
for( $i=0; $i<($width*$height)/3; $i++ ) {
imagefilledellipse($image, mt_rand(0,$width), mt_rand(0,$height), 1, 1, $noise_color);
}
/* generate random lines in background */
for( $i=0; $i<($width*$height)/150; $i++ ) {
imageline($image, mt_rand(0,$width), mt_rand(0,$height), mt_rand(0,$width), mt_rand(0,$height), $noise_color);
}
/* create textbox and add text */
$textbox = imagettfbbox($font_size, 0, dirname(__FILE__).'/'.$this->font, $code) or die('Error in imagettfbbox function');
$x = ($width - $textbox[4])/2;
$y = ($height - $textbox[5])/2;
$y -= 5;
imagettftext($image, $font_size, 0, $x, $y, $text_color, dirname(__FILE__).'/'.$this->font , $code) or die('Error in imagettftext function');
/* output captcha image to browser */
header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
$this->Controller->Session->write('security_code',$code);
}
The captca is created successfully, but when I try to validate it I got an error because $code is not stored in the session. I do not understand why this is happening.
Change:
$this->Controller->Session->write('security_code', $code);
to this:
$this->Session->write('security_code', $code);
Also, ensure that you've added the SessionHelper to your $helpers array.
If you are using CakePHP 1.x, it seems that your application is sending output to browser before the header() function being called to generate image. In that case you need to move the session creation line to above header('Content-Type: image/jpeg'); to look like the following:
imagettftext($image, $font_size, 0, $x, $y, $text_color, $this->font , $code) or die('Error in imagettftext function');
/* output captcha image to browser */
$this->Controller->Session->write('security_code',$code);
#ob_end_clean(); //clean buffers, as a fix for 'headers already sent errors..'
header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
If you are using CakePHP 2.x download updated version of captcha component from author's website www.devarticles.in/cakephp/simple-captcha-component-for-cakephp/
I have faced some issue and get rid of that by changing location of session storing line
function create($width='120',$height='40',$characters='6') {
$code = $this->generateCode($characters);
$this->Controller->Session->write('security_code',$code);
//.....rest of code will remain same
}
Related
I am developing an HTML user form where I am using a PHP captcha script:
<?php
session_start();
class CaptchaSecurityImages {
var $font = 'php/monofont.ttf';
function generateCode($characters) {
/* list all possible characters, similar looking characters and vowels have been removed */
$possible = '23456789bcdfghjkmnpqrstvwxyz';
$code = '';
$i = 0;
while ($i < $characters) {
$code .= substr($possible, mt_rand(0, strlen($possible)-1), 1);
$i++;
}
return $code;
}
function CaptchaSecurityImages($width='120',$height='40',$characters='6') {
$code = $this->generateCode($characters);
/* font size will be 75% of the image height */
$font_size = $height * 0.75;
$image = #imagecreate($width, $height) or die('Cannot initialize new GD image stream');
/* set the colours */
$background_color = imagecolorallocate($image, 255, 255, 255);
$text_color = imagecolorallocate($image, 20, 40, 100);
$noise_color = imagecolorallocate($image, 100, 120, 180);
/* generate random dots in background */
for( $i=0; $i<($width*$height)/3; $i++ ) {
imagefilledellipse($image, mt_rand(0,$width), mt_rand(0,$height), 1, 1, $noise_color);
}
/* generate random lines in background */
for( $i=0; $i<($width*$height)/150; $i++ ) {
imageline($image, mt_rand(0,$width), mt_rand(0,$height), mt_rand(0,$width), mt_rand(0,$height), $noise_color);
}
/* create textbox and add text */
$textbox = imagettfbbox($font_size, 0, $this->font, $code) or die('Error in imagettfbbox function');
$x = ($width - $textbox[4])/2;
$y = ($height - $textbox[5])/2;
imagettftext($image, $font_size, 0, $x, $y, $text_color, $this->font , $code) or die('Error in imagettftext function');
/* output captcha image to browser */
header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
$_SESSION['security_code'] = $code;
}
}
$width = isset($_GET['width']) ? $_GET['width'] : '120';
$height = isset($_GET['height']) ? $_GET['height'] : '40';
$characters = isset($_GET['characters']) && $_GET['characters'] > 1 ? $_GET['characters'] : '6';
$captcha = new CaptchaSecurityImages($width,$height,$characters);
?>
my form looks like:
it used to work like charm and all the sudden on form submission I am getting a frequent error that the user entered CAPTCHA doesn't match the picture,
Investigating further I found that: in chrome once I click any field in the form without typing the $_SESSION['security_code'] value was changed on on its own on the server and ofcourse the photo was never updated, investigating further I found that there are some eventlisteners were set in chrome by my Kaspersky which seems they were the root cause of the problem as they were querying the Captcha photo link once I click on the form and start type in any field before submission (They look like that:-
, please note that my HTML file doesn't use any javascript that could have cause such event firing, as a double check I did try from another computer without Kaspersky and it works.
Now the question is how do I fix this for potential users that use kaspersky and wants to use my form?
I have a php captcha image script that passes back the captcha code using a session variable, but this won't work if cookies are switched off.
I want to try cover all eventualities, so my form will work even if cookies are switched off.
I was wondering if there was a way to pass $code back from captcha.php to contactus.php without using session variables.
I doubt it, but I thought I'd ask to see if I was missing anything.
captcha.php
session_start();
class CaptchaSecurityImages {
var $font = 'monofont.ttf';
function generateCode($characters) {
/* list all possible characters, similar looking characters and vowels have been removed */
$possible = '23456789bcdfghjkmnpqrstvwxyz';
$code = '';
$i = 0;
while ($i < $characters) {
$code .= substr($possible, mt_rand(0, strlen($possible)-1), 1);
$i++;
}
return $code;
}
function CaptchaSecurityImages($width='120',$height='40',$characters='6') {
$code = $this->generateCode($characters);
/* font size will be 75% of the image height */
$font_size = $height * 0.75;
$image = #imagecreate($width, $height) or die('Cannot initialize new GD image stream');
/* set the colours */
$background_color = imagecolorallocate($image, 255, 255, 255);
$text_color = imagecolorallocate($image, 20, 40, 100);
$noise_color = imagecolorallocate($image, 20, 40, 100);
/* generate random dots in background */
for( $i=0; $i<($width*$height)/3; $i++ ) {
imagefilledellipse($image, mt_rand(0,$width), mt_rand(0,$height), 1, 1, $noise_color);
}
/* generate random lines in background */
for( $i=0; $i<($width*$height)/150; $i++ ) {
imageline($image, mt_rand(0,$width), mt_rand(0,$height), mt_rand(0,$width), mt_rand(0,$height), $noise_color);
}
/* create textbox and add text */
$textbox = imagettfbbox($font_size, 0, $this->font, $code) or die('Error in imagettfbbox function');
$x = ($width - $textbox[4])/2;
$y = ($height - $textbox[5])/2;
imagettftext($image, $font_size, 0, $x, $y, $text_color, $this->font , $code) or die('Error in imagettftext function');
/* output captcha image to browser */
header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
$_SESSION['six_letters_code'] = $code;
}
}
$width = isset($_GET['width']) ? $_GET['width'] : '120';
$height = isset($_GET['height']) ? $_GET['height'] : '40';
$characters = isset($_GET['characters']) && $_GET['characters'] > 1 ? $_GET['characters'] : '6';
$captcha = new CaptchaSecurityImages($width,$height,$characters);
Contactus.php
<img id="captchaimg" alt="captchaimg" src="<?php echo htmlentities(getSiteURL() . '/server/includes/captcha.php'); ?>"
Your question is more about managing session without having a cookie support, read this article of how to handle session without using cookie
I have a CAPTCHA class which it has a function to generate the CAPTCHA. As you know when the CAPTCHA is generated, it should be returned like an image so the page should change its Content-type to image mime-type. The CAPTCHA class itself works great, but I wanted to include its class in another class and handle the CAPTCHA generating by myself with calling the relative function. I know there is something really wrong in my code but I can't figure it out, whenever I call the function from the alternative class which is the controller of CAPTCHA generator, PHP pops me an error which it says 'The generated image contains error and cannot be shown'. I know it's because of the header changing but I want to find a way to solve this.
Can someone tell me how to implement this?
My CAPTCHA class:
class CaptchaSecurityImages {
public function MakeCaptcha($width='120', $height='40', $session='CaptchaCode', $characters='6') {
$code = $this->generateCode($characters);
/* font size will be 75% of the image height */
$font_size = $height * 0.85;
$image = #imagecreate($width, $height) or die('Cannot initialize new GD image stream');
/* set the colours */
$background_color = imagecolorallocate($image, 255, 255, 255);
$text_color = imagecolorallocate($image, 20, 40, 100);
$noise_color = imagecolorallocate($image, 100, 120, 180);
/* generate random dots in background */
for( $i=0; $i<($width*$height)/3; $i++ ) {
imagefilledellipse($image, mt_rand(0,$width), mt_rand(0,$height), 1, 1, $noise_color);
}
/* generate random lines in background */
for( $i=0; $i<($width*$height)/150; $i++ ) {
imageline($image, mt_rand(0,$width), mt_rand(0,$height), mt_rand(0,$width), mt_rand(0,$height), $noise_color);
}
/* create textbox and add text */
$textbox = imagettfbbox($font_size, 0, $this->font, $code) or die('Error in imagettfbbox function');
$x = ($width - $textbox[4])/2;
$y = ($height - $textbox[5])/2;
imagettftext($image, $font_size, 0, $x, $y, $text_color, $this->font , $code) or die('Error in imagettftext function');
/* output captcha image to browser */
header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
$_SESSION[$session] = $code;
}
}
My CAPTCHA controller:
class CaptchaController
{
/// Constructor
public function __construct() { }
/// Generate captcha
public function Generate($width = '120', $height = '40', $session = 'CaptchaCode', $chars = '6')
{
include('captcha.php');
$captcha = new CaptchaSecurityImages();
$captcha->MakeCaptcha();
}
}
First you have to make shure, that there is NOTHING (not even a space) send, before calling the function, because afterwards you won't be able to send headers.
Second, just remove your "header(...)" stuff, and call the page itself, so it tells you some binary-image stuff.
I got your error everytime, when in the image there is a PHP-Error / Notice / Whatever, wich is destroying your image. Just try to see the output plain and you can read what has happened!
I am a little bit confused about your method declarations: You expect parameters to your "Generate" function, but never use them? and you redefine these Parameters in the MakeCaptcha function. That can cause errors in later use of this Captcha-lib (or maybe now?)
With your error description i cannot help you any further than that, maybe you can post a link, where this captcha is used (with the error) so we can find your mistake for you.
I'm trying to create a captcha code but the code that is being created isn't being stored in the session variable. Here is the file I'm using to create the code and store the value. I have a session_start() on my php page that will display the captcha as well.
<?php session_start();
class CaptchaSecurityImages {
var $font = './monofont.ttf';
function generateCode($characters) {
/* list all possible characters, similar looking characters and vowels have been removed */
$possible = '23456789bcdfghjkmnpqrstvwxyz';
$code = '';
$i = 0;
while ($i < $characters) {
$code .= substr($possible, mt_rand(0, strlen($possible)-1), 1);
$i++;
}
return $code;
}
function CaptchaSecurityImages($width='120',$height='40',$characters='6') {
$code = $this->generateCode($characters);
/* font size will be 75% of the image height */
$_SESSION['security_code'] = $code;
$font_size = $height * 0.75;
$image = #imagecreate($width, $height) or die('Cannot initialize new GD image stream');
/* set the colours */
$background_color = imagecolorallocate($image, 255, 255, 255);
$text_color = imagecolorallocate($image, 20, 40, 100);
$noise_color = imagecolorallocate($image, 100, 120, 180);
/* generate random dots in background */
for( $i=0; $i<($width*$height)/3; $i++ ) {
imagefilledellipse($image, mt_rand(0,$width), mt_rand(0,$height), 1, 1, $noise_color);
}
/* generate random lines in background */
for( $i=0; $i<($width*$height)/150; $i++ ) {
imageline($image, mt_rand(0,$width), mt_rand(0,$height), mt_rand(0,$width), mt_rand(0,$height), $noise_color);
}
/* create textbox and add text */
$textbox = imagettfbbox($font_size, 0, $this->font, $code) or die('Error in imagettfbbox function');
$x = ($width - $textbox[4])/2;
$y = ($height - $textbox[5])/2;
imagettftext($image, $font_size, 0, $x, $y, $text_color, $this->font , $code) or die('Error in imagettftext function');
/* output captcha image to browser */
header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
}
}
$width = isset($_GET['width']) ? $_GET['width'] : '120';
$height = isset($_GET['height']) ? $_GET['height'] : '40';
$characters = isset($_GET['characters']) && $_GET['characters'] > 1 ? $_GET['characters'] : '6';
$captcha = new CaptchaSecurityImages($width,$height,$characters);
?>
I can store other items in sessions and they work just fine. I'm not sure why this value won't store. I've found other posts about getting captcha's working but nothing about issues with storing the value in sessions. Any suggestions?
Thanks
Robert
I did end up using reCAPTCHA to accomplish this task.
How is your image being loaded into the user's browser? Is it on the same domain? If it is not, the problem most likely is that your cookie is being excluded because it's a "3rd party cookie." To get the browser to save this cookie, you have to set a P3P header, so the browser knows it's okay to save the cookie.
An example of a valid P3P header would be:
header('P3P: CP="CAO PSA OUR"');
Hope this helps.
I have a Joomla component which calls a helper function to create a captcha image. Everything works fine when sh404 is disabled, but when sh404 is enabled the session variable for the security image isn't being set correctly so when you submit the form you get 'Invalid Captcha' message. The funny thing is if you submit another 5-6 times, it validates fine and submits. I've tried just about everything I can think of - when I echo the session variable and submitted captcha code it appears that the session is a step behind - for example:
If I submit the form the first time and echo the session variable and submitted code, it looks like the session variable is not being set in time - I get a blank value for the session variable. Then I submit the form again and the session variable is the value of the previous captcha image. Here's the code that generates and validates the captcha. Thanks!
//Generate Captcha image link
function Captchalink($capid = ''){
return 'index.php?option=com_mycomponent&view=home&task=newCaptcha&capid='.$capid;
}
function generateCode($characters) {
/* list all possible characters, similar looking characters and vowels have been removed */
$possible = '23456789bcdfghjkmnpqrstvwxyz';
$code = '';
$i = 0;
while ($i < $characters) {
$code .= substr($possible, mt_rand(0, strlen($possible)-1), 1);
$i++;
}
return $code;
}
function CaptchaSecurityImages($capid = '') {
$font = dirname(__FILE__).DS."monofont.ttf";
$width = 90;
$height = 30;
$characters = 6;
$session =& JFactory::getSession();
//Clean buffers
while (ob_get_level()) {
ob_end_clean();
}
// start output buffering
if (ob_get_length() === false) {
ob_start();
}
$code = mycomponentHTML::generateCode($characters);
/* font size will be 75% of the image height */
$font_size = $height * 0.75;
$image = #imagecreate($width, $height) or die('Cannot initialize new GD image stream');
/* set the colors */
$background_color = imagecolorallocate($image, 255, 255, 255);
$text_color = imagecolorallocate($image, 20, 40, 100);
$noise_color = imagecolorallocate($image, 100, 120, 180);
/* generate random dots in background */
for( $i=0; $i<($width*$height)/3; $i++ ) {
imagefilledellipse($image, mt_rand(0,$width), mt_rand(0,$height), 1, 1, $noise_color);
}
/* generate random lines in background */
for( $i=0; $i<($width*$height)/150; $i++ ) {
imageline($image, mt_rand(0,$width), mt_rand(0,$height), mt_rand(0,$width), mt_rand(0,$height), $noise_color);
}
/* create textbox and add text */
$textbox = imagettfbbox($font_size, 0, $font, $code) or die('Error in imagettfbbox function');
$x = ($width - $textbox[4])/2;
$y = ($height - $textbox[5])/2;
imagettftext($image, $font_size, 0, $x, $y, $text_color, $font , $code) or die('Error in imagettftext function');
/* output captcha image to browser */
header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
/* set session variable for newly created code */
$session->set('security_code_'.$capid, md5($code));
ob_end_flush();
die();
}
function CaptchaValidate($capid = ''){
$session =& JFactory::getSession();
if( $session->get('security_code_'.$capid) == md5(JRequest::getVar('security_code_'.$capid)) ) {
$session->clear('security_code_'.$capid);
return true;
}else{
return false;
}
}