diff --git a/Controller/CaptchaController.php b/Controller/CaptchaController.php index 636e163..06e651a 100644 --- a/Controller/CaptchaController.php +++ b/Controller/CaptchaController.php @@ -42,7 +42,15 @@ class CaptchaController extends Controller /* @var \Gregwar\CaptchaBundle\Generator\CaptchaGenerator $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'); return $response; diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 7e73c6a..30f65cb 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -21,8 +21,8 @@ class Configuration implements ConfigurationInterface ->addDefaultsIfNotSet() ->children() ->scalarNode('length')->defaultValue(5)->end() - ->scalarNode('width')->defaultValue(120)->end() - ->scalarNode('height')->defaultValue(40)->end() + ->scalarNode('width')->defaultValue(130)->end() + ->scalarNode('height')->defaultValue(50)->end() ->scalarNode('font')->defaultValue(__DIR__.'/../Generator/Font/captcha.ttf')->end() ->scalarNode('keep_value')->defaultValue(false)->end() ->scalarNode('charset')->defaultValue('abcdefhjkmnprstuvwxyz23456789')->end() @@ -33,7 +33,7 @@ class Configuration implements ConfigurationInterface ->scalarNode('web_path')->defaultValue('%kernel.root_dir%/../web')->end() ->scalarNode('gc_freq')->defaultValue(100)->end() ->scalarNode('expiration')->defaultValue(60)->end() - ->scalarNode('quality')->defaultValue(15)->end() + ->scalarNode('quality')->defaultValue(30)->end() ->scalarNode('invalid_message')->defaultValue('Bad code value')->end() ->scalarNode('bypass_code')->defaultValue(null)->end() ->scalarNode('whitelist_key')->defaultValue('captcha_whitelist_key')->end() diff --git a/Generator/CaptchaGenerator.php b/Generator/CaptchaGenerator.php index 2731d00..bd99ca8 100644 --- a/Generator/CaptchaGenerator.php +++ b/Generator/CaptchaGenerator.php @@ -17,17 +17,6 @@ use Gregwar\Captcha\PhraseBuilderInterface; */ class CaptchaGenerator { - /** - * @var \Symfony\Component\HttpFoundation\Session\SessionInterface - */ - protected $session; - - /** - * Name of the whitelist key - * @var string - */ - protected $whitelistKey; - /** * @var \Symfony\Component\Routing\RouterInterface */ @@ -49,20 +38,16 @@ class CaptchaGenerator protected $imageFileHandler; /** - * @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session * @param \Symfony\Component\Routing\RouterInterface $router * @param CaptchaBuilderInterface $builder * @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->builder = $builder; $this->phraseBuilder = $phraseBuilder; - $this->imageFileHandler = $imageFileHandler; - $this->whitelistKey = $whitelistKey; + $this->imageFileHandler = $imageFileHandler; } /** @@ -73,26 +58,31 @@ class CaptchaGenerator * * @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 if ($options['as_file']) { $this->imageFileHandler->collectGarbage(); - return $this->generate($key, $options); + return $this->generate($options); } // Returns the image generation URL if ($options['as_url']) { - $keys = $this->session->get($this->whitelistKey, array()); - 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 $this->router->generate('gregwar_captcha.generate_captcha', array('key' => $options['session_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 */ - public function generate($key, array $options) + public function generate(array &$options) { - $fingerprint = $this->getFingerprint($key, $options); - $this->builder->setDistortion($options['distortion']); + $fingerprint = isset($options['fingerprint']) ? $options['fingerprint'] : null; + $content = $this->builder->build( $options['width'], $options['height'], @@ -115,7 +105,7 @@ class CaptchaGenerator )->getGd(); if ($options['keep_value']) { - $this->session->set($key . '_fingerprint', $this->builder->getFingerprint()); + $options['fingerprint'] = $this->builder->getFingerprint(); } if (!$options['as_file']) { @@ -134,33 +124,17 @@ class CaptchaGenerator * * @return string */ - protected function getPhrase($key, array $options) + public function getPhrase(array &$options) { // Get the phrase that we'll use for this image - if ($options['keep_value'] && $this->session->has($key)) { - return $this->session->get($key); + if ($options['keep_value'] && isset($options['phrase'])) { + $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; } - - /** - * @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; - } } diff --git a/Resources/config/services.yml b/Resources/config/services.yml index faa9af3..d675854 100755 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -11,12 +11,10 @@ services: gregwar_captcha.generator: class: Gregwar\CaptchaBundle\Generator\CaptchaGenerator arguments: - - @session - @router - @gregwar_captcha.captcha_builder - @gregwar_captcha.phrase_builder - @gregwar_captcha.image_file_handler - - %gregwar_captcha.config.whitelist_key% gregwar_captcha.image_file_handler: class: Gregwar\CaptchaBundle\Generator\ImageFileHandler diff --git a/Type/CaptchaType.php b/Type/CaptchaType.php index 4c99549..e7386ff 100644 --- a/Type/CaptchaType.php +++ b/Type/CaptchaType.php @@ -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( 'captcha_width' => $options['width'], 'captcha_height' => $options['height'], 'reload' => $options['reload'], 'image_id' => uniqid('captcha_'), - 'captcha_code' => $this->generator->getCaptchaCode($this->key, $options), + 'captcha_code' => $this->generator->getCaptchaCode($options), 'value' => '', 'is_human' => $isHuman )); + + $persistOptions = array(); + foreach (array('phrase', 'width', 'height', 'distortion', 'quality') as $key) { + $persistOptions[$key] = $options[$key]; + } + + $this->session->set($this->key, $persistOptions); } /** diff --git a/Validator/CaptchaValidator.php b/Validator/CaptchaValidator.php index dcfe520..62beac3 100644 --- a/Validator/CaptchaValidator.php +++ b/Validator/CaptchaValidator.php @@ -60,17 +60,15 @@ class CaptchaValidator public function validate(FormEvent $event) { $form = $form = $event->getForm(); - $humanityKey = $this->key . '_humanity'; $code = $form->getData(); $expectedCode = $this->getExpectedCode(); if ($this->humanity > 0) { - if ($this->session->get($humanityKey, 0) > 0) { - $this->session->set($humanityKey, $this->session->get($humanityKey, 0)-1); + $humanity = $this->getHumanity(); + if ($humanity > 0) { + $this->updateHumanity($humanity-1); return; - } else { - $this->session->remove($humanityKey); } } @@ -78,7 +76,7 @@ class CaptchaValidator $form->addError(new FormError($this->invalidMessage)); } else { if ($this->humanity > 0) { - $this->session->set($humanityKey, $this->humanity); + $this->updateHumanity($this->humanity); } } @@ -96,8 +94,34 @@ class CaptchaValidator */ protected function getExpectedCode() { - if ($this->session->has($this->key)) { - return $this->session->get($this->key); + $options = $this->session->get($this->key, array()); + + 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;