[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;
/**
* 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
* @var string
*/
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->imageFolder = $imageFolder;
@ -53,6 +66,8 @@ class CaptchaGenerator {
$this->gcFreq = intval($gcFreq);
$this->expiration = intval($expiration);
$this->font = $font;
$this->fingerprint = $fingerprint;
$this->use_fingerprint = (bool)$fingerprint;
}
/**
@ -80,6 +95,34 @@ class CaptchaGenerator {
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
* that are older than 10 minutes
@ -106,17 +149,17 @@ class CaptchaGenerator {
{
$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);
// Draw random lines
for ($t=0; $t<10; $t++) {
$tcol = imagecolorallocate($i, 100+mt_rand(0,150), 100+mt_rand(0,150), 100+mt_rand(0,150));
$Xa = mt_rand(0, $width);
$Ya = mt_rand(0, $height);
$Xb = mt_rand(0, $width);
$Yb = mt_rand(0, $height);
$tcol = imagecolorallocate($i, 100+$this->rand(0,150), 100+$this->rand(0,150), 100+$this->rand(0,150));
$Xa = $this->rand(0, $width);
$Ya = $this->rand(0, $height);
$Xb = $this->rand(0, $width);
$Yb = $this->rand(0, $height);
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);
// Distort the image
$X = mt_rand(0, $width);
$Y = mt_rand(0, $height);
$Phase=mt_rand(0,10);
$Scale = 1.3 + mt_rand(0,10000)/30000;
$Amp=1+mt_rand(0,1000)/1000;
$X = $this->rand(0, $width);
$Y = $this->rand(0, $height);
$Phase=$this->rand(0,10);
$Scale = 1.3 + $this->rand(0,10000)/30000;
$Amp=1+$this->rand(0,1000)/1000;
$out = imagecreatetruecolor($width, $height);
for ($x=0; $x<$width; $x++)

View File

@ -128,7 +128,13 @@ class CaptchaType extends AbstractType
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) {
$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_height', $this->height);
if ($this->keepValue) {
$this->session->set($this->key.'_fingerprint', $generator->getFingerprint());
}
}
public function getDefaultOptions(array $options = array())

View File

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