Cleaning session usage to keep options during as_url (fixes #41)

This commit is contained in:
Gregwar 2013-01-21 15:18:36 +01:00
parent 2e17d9c035
commit 42f6e92560
5 changed files with 86 additions and 65 deletions

View File

@ -42,7 +42,15 @@ class CaptchaController extends Controller
/* @var \Gregwar\CaptchaBundle\Generator\CaptchaGenerator $generator */ /* @var \Gregwar\CaptchaBundle\Generator\CaptchaGenerator $generator */
$generator = $this->container->get('gregwar_captcha.generator'); $generator = $this->container->get('gregwar_captcha.generator');
$response = new Response($generator->generate($key, $options)); $persistedOptions = $session->get($key, array());
$options = array_merge($options, $persistedOptions);
$phrase = $generator->getPhrase($options);
$generator->setPhrase($phrase);
$persistedOptions['phrase'] = $phrase;
$session->set($key, $persistedOptions);
$response = new Response($generator->generate($options));
$response->headers->set('Content-type', 'image/jpeg'); $response->headers->set('Content-type', 'image/jpeg');
return $response; return $response;

View File

@ -17,17 +17,6 @@ use Gregwar\Captcha\PhraseBuilderInterface;
*/ */
class CaptchaGenerator class CaptchaGenerator
{ {
/**
* @var \Symfony\Component\HttpFoundation\Session\SessionInterface
*/
protected $session;
/**
* Name of the whitelist key
* @var string
*/
protected $whitelistKey;
/** /**
* @var \Symfony\Component\Routing\RouterInterface * @var \Symfony\Component\Routing\RouterInterface
*/ */
@ -49,20 +38,16 @@ class CaptchaGenerator
protected $imageFileHandler; protected $imageFileHandler;
/** /**
* @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
* @param \Symfony\Component\Routing\RouterInterface $router * @param \Symfony\Component\Routing\RouterInterface $router
* @param CaptchaBuilderInterface $builder * @param CaptchaBuilderInterface $builder
* @param ImageFileHandlerInterface $imageFileHandler * @param ImageFileHandlerInterface $imageFileHandler
* @param string $whitelistKey
*/ */
public function __construct(SessionInterface $session, RouterInterface $router, CaptchaBuilderInterface $builder, PhraseBuilderInterface $phraseBuilder, ImageFileHandler $imageFileHandler, $whitelistKey) public function __construct(RouterInterface $router, CaptchaBuilderInterface $builder, PhraseBuilderInterface $phraseBuilder, ImageFileHandler $imageFileHandler)
{ {
$this->session = $session;
$this->router = $router; $this->router = $router;
$this->builder = $builder; $this->builder = $builder;
$this->phraseBuilder = $phraseBuilder; $this->phraseBuilder = $phraseBuilder;
$this->imageFileHandler = $imageFileHandler; $this->imageFileHandler = $imageFileHandler;
$this->whitelistKey = $whitelistKey;
} }
/** /**
@ -73,26 +58,31 @@ class CaptchaGenerator
* *
* @return array * @return array
*/ */
public function getCaptchaCode($key, array $options) public function getCaptchaCode(array &$options)
{ {
$this->builder->setPhrase($this->getPhrase($options));
// Randomly execute garbage collection and returns the image filename // Randomly execute garbage collection and returns the image filename
if ($options['as_file']) { if ($options['as_file']) {
$this->imageFileHandler->collectGarbage(); $this->imageFileHandler->collectGarbage();
return $this->generate($key, $options); return $this->generate($options);
} }
// Returns the image generation URL // Returns the image generation URL
if ($options['as_url']) { if ($options['as_url']) {
$keys = $this->session->get($this->whitelistKey, array()); return $this->router->generate('gregwar_captcha.generate_captcha', array('key' => $options['session_key']));
if (!in_array($key, $keys)) {
$keys[] = $key;
}
$this->session->set($this->whitelistKey, $keys);
return $this->router->generate('gregwar_captcha.generate_captcha', array('key' => $key));
} }
return 'data:image/jpeg;base64,' . base64_encode($this->generate($key, $options)); return 'data:image/jpeg;base64,' . base64_encode($this->generate($options));
}
/**
* Sets the phrase to the builder
*/
public function setPhrase($phrase)
{
$this->builder->setPhrase($phrase);
} }
/** /**
@ -101,12 +91,12 @@ class CaptchaGenerator
* *
* @return string * @return string
*/ */
public function generate($key, array $options) public function generate(array &$options)
{ {
$fingerprint = $this->getFingerprint($key, $options);
$this->builder->setDistortion($options['distortion']); $this->builder->setDistortion($options['distortion']);
$fingerprint = isset($options['fingerprint']) ? $options['fingerprint'] : null;
$content = $this->builder->build( $content = $this->builder->build(
$options['width'], $options['width'],
$options['height'], $options['height'],
@ -115,7 +105,7 @@ class CaptchaGenerator
)->getGd(); )->getGd();
if ($options['keep_value']) { if ($options['keep_value']) {
$this->session->set($key . '_fingerprint', $this->builder->getFingerprint()); $options['fingerprint'] = $this->builder->getFingerprint();
} }
if (!$options['as_file']) { if (!$options['as_file']) {
@ -134,33 +124,17 @@ class CaptchaGenerator
* *
* @return string * @return string
*/ */
protected function getPhrase($key, array $options) public function getPhrase(array &$options)
{ {
// Get the phrase that we'll use for this image // Get the phrase that we'll use for this image
if ($options['keep_value'] && $this->session->has($key)) { if ($options['keep_value'] && isset($options['phrase'])) {
return $this->session->get($key); $phrase = $options['phrase'];
} else {
$phrase = $this->phraseBuilder->build($options['length'], $options['charset']);
$options['phrase'] = $phrase;
} }
$phrase = $this->phraseBuilder->build($options['length'], $options['charset']);
$this->session->set($key, $phrase);
$this->captchaBuilder->setPhrase($phrase);
return $phrase; return $phrase;
} }
/**
* @param string $key
* @param array $options
*
* @return array|null
*/
protected function getFingerprint($key, array $options)
{
if ($options['keep_value'] && $this->session->has($key . '_fingerprint')) {
return $this->session->get($key . '_fingerprint');
}
return null;
}
} }

View File

@ -11,12 +11,10 @@ services:
gregwar_captcha.generator: gregwar_captcha.generator:
class: Gregwar\CaptchaBundle\Generator\CaptchaGenerator class: Gregwar\CaptchaBundle\Generator\CaptchaGenerator
arguments: arguments:
- @session
- @router - @router
- @gregwar_captcha.captcha_builder - @gregwar_captcha.captcha_builder
- @gregwar_captcha.phrase_builder - @gregwar_captcha.phrase_builder
- @gregwar_captcha.image_file_handler - @gregwar_captcha.image_file_handler
- %gregwar_captcha.config.whitelist_key%
gregwar_captcha.image_file_handler: gregwar_captcha.image_file_handler:
class: Gregwar\CaptchaBundle\Generator\ImageFileHandler class: Gregwar\CaptchaBundle\Generator\ImageFileHandler

View File

@ -89,15 +89,32 @@ class CaptchaType extends AbstractType
} }
} }
if ($options['as_url']) {
$key = $this->key;
$keys = $this->session->get($options['whitelist_key'], array());
if (!in_array($key, $keys)) {
$keys[] = $key;
}
$this->session->set($options['whitelist_key'], $keys);
$options['session_key'] = $this->key;
}
$view->vars = array_merge($view->vars, array( $view->vars = array_merge($view->vars, array(
'captcha_width' => $options['width'], 'captcha_width' => $options['width'],
'captcha_height' => $options['height'], 'captcha_height' => $options['height'],
'reload' => $options['reload'], 'reload' => $options['reload'],
'image_id' => uniqid('captcha_'), 'image_id' => uniqid('captcha_'),
'captcha_code' => $this->generator->getCaptchaCode($this->key, $options), 'captcha_code' => $this->generator->getCaptchaCode($options),
'value' => '', 'value' => '',
'is_human' => $isHuman 'is_human' => $isHuman
)); ));
$persistOptions = array();
foreach (array('phrase', 'width', 'height', 'distortion', 'quality') as $key) {
$persistOptions[$key] = $options[$key];
}
$this->session->set($this->key, $persistOptions);
} }
/** /**

View File

@ -60,17 +60,15 @@ class CaptchaValidator
public function validate(FormEvent $event) public function validate(FormEvent $event)
{ {
$form = $form = $event->getForm(); $form = $form = $event->getForm();
$humanityKey = $this->key . '_humanity';
$code = $form->getData(); $code = $form->getData();
$expectedCode = $this->getExpectedCode(); $expectedCode = $this->getExpectedCode();
if ($this->humanity > 0) { if ($this->humanity > 0) {
if ($this->session->get($humanityKey, 0) > 0) { $humanity = $this->getHumanity();
$this->session->set($humanityKey, $this->session->get($humanityKey, 0)-1); if ($humanity > 0) {
$this->updateHumanity($humanity-1);
return; return;
} else {
$this->session->remove($humanityKey);
} }
} }
@ -78,7 +76,7 @@ class CaptchaValidator
$form->addError(new FormError($this->invalidMessage)); $form->addError(new FormError($this->invalidMessage));
} else { } else {
if ($this->humanity > 0) { if ($this->humanity > 0) {
$this->session->set($humanityKey, $this->humanity); $this->updateHumanity($this->humanity);
} }
} }
@ -96,8 +94,34 @@ class CaptchaValidator
*/ */
protected function getExpectedCode() protected function getExpectedCode()
{ {
if ($this->session->has($this->key)) { $options = $this->session->get($this->key, array());
return $this->session->get($this->key);
if (is_array($options) && isset($options['phrase'])) {
return $options['phrase'];
}
return null;
}
/**
* Retreive the humanity
*
* @return mixed|null
*/
protected function getHumanity()
{
return $this->session->get($this->key . '_humanity', 0);
}
/**
* Updates the humanity
*/
protected function updateHumanity($newValue)
{
if ($newValue > 0) {
$this->session->set($this->key . '_humanity', $newValue);
} else {
$this->session->remove($this->key . '_humanity');
} }
return null; return null;