[Generator] Fingerprinting CAPTCHAs to keep the same image between two

requests (fixes #11)
This commit is contained in:
Gregwar 2011-12-02 19:26:31 +01:00
parent 726f21e2ad
commit a3ce06f263
3 changed files with 70 additions and 13 deletions

View File

@ -39,13 +39,26 @@ class CaptchaGenerator {
*/ */
public $expiration; public $expiration;
/**
* Random fingerprint
* Useful to be able to regenerate exactly the same image
* @var array
*/
public $fingerprint;
/**
* Should fingerprint be used ?
* @var boolean
*/
public $use_fingerprint;
/** /**
* The captcha code * The captcha code
* @var string * @var string
*/ */
public $value; public $value;
public function __construct($value, $imageFolder, $webPath, $gcFreq, $expiration, $font) public function __construct($value, $imageFolder, $webPath, $gcFreq, $expiration, $font, $fingerprint)
{ {
$this->value = $value; $this->value = $value;
$this->imageFolder = $imageFolder; $this->imageFolder = $imageFolder;
@ -53,6 +66,8 @@ class CaptchaGenerator {
$this->gcFreq = intval($gcFreq); $this->gcFreq = intval($gcFreq);
$this->expiration = intval($expiration); $this->expiration = intval($expiration);
$this->font = $font; $this->font = $font;
$this->fingerprint = $fingerprint;
$this->use_fingerprint = (bool)$fingerprint;
} }
/** /**
@ -80,6 +95,34 @@ class CaptchaGenerator {
return $this->generate($width, $height, true); return $this->generate($width, $height, true);
} }
/**
* Returns a random number or the next number in the
* fingerprint
*/
public function rand($min, $max)
{
if (!is_array($this->fingerprint)) {
$this->fingerprint = array();
}
if ($this->use_fingerprint) {
$value = current($this->fingerprint);
next($this->fingerprint);
} else {
$value = mt_rand($min, $max);
$this->fingerprint[] = $value;
}
return $value;
}
/**
* Get the CAPTCHA fingerprint
*/
public function getFingerprint()
{
return $this->fingerprint;
}
/** /**
* Deletes all images in the configured folder * Deletes all images in the configured folder
* that are older than 10 minutes * that are older than 10 minutes
@ -106,17 +149,17 @@ class CaptchaGenerator {
{ {
$i = imagecreatetruecolor($width,$height); $i = imagecreatetruecolor($width,$height);
$col = imagecolorallocate($i, mt_rand(0,110), mt_rand(0,110), mt_rand(0,110)); $col = imagecolorallocate($i, $this->rand(0,110), $this->rand(0,110), $this->rand(0,110));
imagefill($i, 0, 0, 0xFFFFFF); imagefill($i, 0, 0, 0xFFFFFF);
// Draw random lines // Draw random lines
for ($t=0; $t<10; $t++) { for ($t=0; $t<10; $t++) {
$tcol = imagecolorallocate($i, 100+mt_rand(0,150), 100+mt_rand(0,150), 100+mt_rand(0,150)); $tcol = imagecolorallocate($i, 100+$this->rand(0,150), 100+$this->rand(0,150), 100+$this->rand(0,150));
$Xa = mt_rand(0, $width); $Xa = $this->rand(0, $width);
$Ya = mt_rand(0, $height); $Ya = $this->rand(0, $height);
$Xb = mt_rand(0, $width); $Xb = $this->rand(0, $width);
$Yb = mt_rand(0, $height); $Yb = $this->rand(0, $height);
imageline($i, $Xa, $Ya, $Xb, $Yb, $tcol); imageline($i, $Xa, $Ya, $Xb, $Yb, $tcol);
} }
@ -130,11 +173,11 @@ class CaptchaGenerator {
imagettftext($i, $size, 0, ($width-$txt_width)/2, ($height-$txt_height)/2+$size, $col, $font, $this->value); imagettftext($i, $size, 0, ($width-$txt_width)/2, ($height-$txt_height)/2+$size, $col, $font, $this->value);
// Distort the image // Distort the image
$X = mt_rand(0, $width); $X = $this->rand(0, $width);
$Y = mt_rand(0, $height); $Y = $this->rand(0, $height);
$Phase=mt_rand(0,10); $Phase=$this->rand(0,10);
$Scale = 1.3 + mt_rand(0,10000)/30000; $Scale = 1.3 + $this->rand(0,10000)/30000;
$Amp=1+mt_rand(0,1000)/1000; $Amp=1+$this->rand(0,1000)/1000;
$out = imagecreatetruecolor($width, $height); $out = imagecreatetruecolor($width, $height);
for ($x=0; $x<$width; $x++) for ($x=0; $x<$width; $x++)

View File

@ -128,7 +128,13 @@ class CaptchaType extends AbstractType
public function buildView(FormView $view, FormInterface $form) public function buildView(FormView $view, FormInterface $form)
{ {
$generator = new CaptchaGenerator($this->generateCaptchaValue(), $this->imageFolder, $this->webPath, $this->gcFreq, $this->expiration, $this->font); $fingerprint = null;
if ($this->session->has($this->key.'_fingerprint')) {
$fingerprint = $this->session->get($this->key.'_fingerprint');
}
$generator = new CaptchaGenerator($this->generateCaptchaValue(), $this->imageFolder, $this->webPath, $this->gcFreq, $this->expiration, $this->font, $fingerprint);
if ($this->asFile) { if ($this->asFile) {
$view->set('captcha_code', $generator->getFile($this->width, $this->height)); $view->set('captcha_code', $generator->getFile($this->width, $this->height));
@ -137,6 +143,10 @@ class CaptchaType extends AbstractType
} }
$view->set('captcha_width', $this->width); $view->set('captcha_width', $this->width);
$view->set('captcha_height', $this->height); $view->set('captcha_height', $this->height);
if ($this->keepValue) {
$this->session->set($this->key.'_fingerprint', $generator->getFingerprint());
}
} }
public function getDefaultOptions(array $options = array()) public function getDefaultOptions(array $options = array())

View File

@ -41,6 +41,10 @@ class CaptchaValidator implements FormValidatorInterface
} }
$this->session->remove($this->key); $this->session->remove($this->key);
if ($this->session->has($this->key.'_fingerprint')) {
$this->session->remove($this->key.'_fingerprint');
}
} }
/** /**