843f367540
When the bypass code is given the value of '0', PHP equates it to boolean false causing the validation to fail.
165 lines
4.0 KiB
PHP
165 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace Gregwar\CaptchaBundle\Validator;
|
|
|
|
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
|
use Symfony\Component\Form\FormError;
|
|
use Symfony\Component\Form\FormEvent;
|
|
use Symfony\Component\Translation\TranslatorInterface;
|
|
|
|
/**
|
|
* Captcha validator
|
|
*
|
|
* @author Gregwar <g.passault@gmail.com>
|
|
*/
|
|
class CaptchaValidator
|
|
{
|
|
/**
|
|
* @var SessionInterface
|
|
*/
|
|
private $session;
|
|
|
|
/**
|
|
* Session key to store the code
|
|
*/
|
|
private $key;
|
|
|
|
/**
|
|
* Error message text for non-matching submissions
|
|
*/
|
|
private $invalidMessage;
|
|
|
|
/**
|
|
* Configuration parameter used to bypass a required code match
|
|
*/
|
|
private $bypassCode;
|
|
|
|
/**
|
|
* Number of form that the user can submit without captcha
|
|
* @var int
|
|
*/
|
|
private $humanity;
|
|
|
|
/**
|
|
* Translator
|
|
* @var TranslatorInterface
|
|
*/
|
|
private $translator;
|
|
|
|
/**
|
|
* @param TranslatorInterface $translator
|
|
* @param SessionInterface $session
|
|
* @param string $key
|
|
* @param string $invalidMessage
|
|
* @param string $bypassCode
|
|
* @param int $humanity
|
|
*/
|
|
public function __construct(TranslatorInterface $translator, SessionInterface $session, $key, $invalidMessage, $bypassCode, $humanity)
|
|
{
|
|
$this->translator = $translator;
|
|
$this->session = $session;
|
|
$this->key = $key;
|
|
$this->invalidMessage = $invalidMessage;
|
|
$this->bypassCode = $bypassCode;
|
|
$this->humanity = $humanity;
|
|
}
|
|
|
|
/**
|
|
* @param FormEvent $event
|
|
*/
|
|
public function validate(FormEvent $event)
|
|
{
|
|
$form = $event->getForm();
|
|
|
|
$code = $form->getData();
|
|
$expectedCode = $this->getExpectedCode();
|
|
|
|
if ($this->humanity > 0) {
|
|
$humanity = $this->getHumanity();
|
|
if ($humanity > 0) {
|
|
$this->updateHumanity($humanity-1);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!($code !== null && is_string($code) && ($this->compare($code, $expectedCode) || $this->compare($code, $this->bypassCode)))) {
|
|
$form->addError(new FormError($this->translator->trans($this->invalidMessage, array(), 'validators')));
|
|
} else {
|
|
if ($this->humanity > 0) {
|
|
$this->updateHumanity($this->humanity);
|
|
}
|
|
}
|
|
|
|
$this->session->remove($this->key);
|
|
|
|
if ($this->session->has($this->key . '_fingerprint')) {
|
|
$this->session->remove($this->key . '_fingerprint');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieve the expected CAPTCHA code
|
|
*
|
|
* @return mixed|null
|
|
*/
|
|
protected function getExpectedCode()
|
|
{
|
|
$options = $this->session->get($this->key, array());
|
|
|
|
if (is_array($options) && isset($options['phrase'])) {
|
|
return $options['phrase'];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Retrieve 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;
|
|
}
|
|
|
|
/**
|
|
* Process the codes
|
|
*
|
|
* @param $code
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function niceize($code)
|
|
{
|
|
return strtr(strtolower($code), 'oil', '01l');
|
|
}
|
|
|
|
/**
|
|
* Run a match comparison on the provided code and the expected code
|
|
*
|
|
* @param $code
|
|
* @param $expectedCode
|
|
*
|
|
* @return bool
|
|
*/
|
|
protected function compare($code, $expectedCode)
|
|
{
|
|
return ($expectedCode !== null && is_string($expectedCode) && $this->niceize($code) == $this->niceize($expectedCode));
|
|
}
|
|
}
|