Skip to content

Commit

Permalink
Merge pull request #234 from bamarni/recaptcha-validation-options
Browse files Browse the repository at this point in the history
[Recaptcha] allowed to configure validation options (fixes #233)
  • Loading branch information
bamarni committed Feb 10, 2013
2 parents 7a9406c + 835ffa2 commit cbdf559
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 34 deletions.
26 changes: 23 additions & 3 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,30 @@ private function addRecaptcha(ArrayNodeDefinition $rootNode)
->treatTrueLike(array('enabled' => true))
->children()
->booleanNode('enabled')->defaultTrue()->end()
->scalarNode('server_url')->defaultValue('http://api.recaptcha.net')->end()
->scalarNode('public_key')->isRequired()->end()
->scalarNode('private_key')->isRequired()->end()
->arrayNode('validation')
->canBeUnset()
->addDefaultsIfNotSet()
->children()
->scalarNode('host')->defaultValue('api-verify.recaptcha.net')->end()
->scalarNode('port')->defaultValue(80)->end()
->scalarNode('path')->defaultValue('/verify')->end()
->scalarNode('timeout')->defaultValue(10)->end()
->scalarNode('code')->defaultNull()->end()
->arrayNode('proxy')
->canBeUnset()
->children()
->scalarNode('host')->isRequired()->end()
->scalarNode('port')->defaultValue('80')->end()
->end()
->end()
->end()
->end()
->variableNode('configs')->defaultValue(array())->end()
/* TO BE DEPRECATED */
->scalarNode('code')->defaultNull()->end()
->scalarNode('server_url')->defaultValue('http://api.recaptcha.net')->end()
->arrayNode('ssl')
->canBeUnset()
->treatNullLike(array('use' => true))
Expand All @@ -147,8 +168,7 @@ private function addRecaptcha(ArrayNodeDefinition $rootNode)
->end()
->end()
->end()
->variableNode('configs')->defaultValue(array())->end()
->scalarNode('code')->defaultNull()->end()
/* END */
->end()
->end()
->end()
Expand Down
2 changes: 2 additions & 0 deletions DependencyInjection/GenemuFormExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ private function registerRecaptchaConfiguration(array $configs, ContainerBuilder
$container->setParameter('genemu.form.recaptcha.public_key', $configs['public_key']);
$container->setParameter('genemu.form.recaptcha.code', $configs['code']);
$container->setParameter('genemu.form.recaptcha.options', $configs['configs']);
$validationOptions = array_merge(array('code' => $configs['code']), $configs['validation']);
$container->setParameter('genemu.form.recaptcha.validation.options', $validationOptions);
}

/**
Expand Down
15 changes: 4 additions & 11 deletions Form/Core/Type/ReCaptchaType.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ public function __construct(EventSubscriberInterface $validator, $publicKey, $se
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->validator->addOptions($options['validator']);

$builder
->addEventSubscriber($this->validator)
->setAttribute('option_validator', $options['validator'])
->setAttribute('option_validator', $this->validator->getOptions())
;
}

Expand Down Expand Up @@ -97,16 +99,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
->setNormalizers(array(
'configs' => function (Options $options, $value) use ($configs) {
return array_merge($configs, $value);
},
'validator' => function (Options $options, $value) {
return array_merge(array(
'host' => 'api-verify.recaptcha.net',
'port' => 80,
'path' => '/verify',
'timeout' => 10,
), $value
);
},
}
))
;
}
Expand Down
34 changes: 24 additions & 10 deletions Form/Core/Validator/ReCaptchaValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,19 @@ class ReCaptchaValidator implements EventSubscriberInterface
private $httpRequest;
private $request;
private $privateKey;
private $code;
private $options;

/**
* @param Request $request
* @param string $privateKey
* @param null|string $code Predefined code to validate against (for testing)
* @param array $options Validation options
*/
public function __construct(Request $request, $privateKey, $code = null)
public function __construct(Request $request, $privateKey, array $options = array())
{
$this->code = $code;
$this->options = $options;
$this->request = $request;

if (empty($code)) {
if (empty($options['code'])) {
if (empty($privateKey)) {
throw new FormException('The child node "private_key" at path "genenu_form.captcha" must be configured.');
}
Expand All @@ -60,6 +60,16 @@ public function __construct(Request $request, $privateKey, $code = null)
}
}

public function addOptions(array $options)
{
$this->options = array_merge($this->options, $options);
}

public function getOptions()
{
return $this->options;
}

public function validate(DataEvent $event)
{
$form = $event->getForm();
Expand All @@ -75,13 +85,13 @@ public function validate(DataEvent $event)
'remoteip' => $server->get('REMOTE_ADDR')
);

if (empty($this->code)) {
if (empty($this->options['code'])) {
if (empty($datas['challenge']) || empty($datas['response'])) {
$error = 'The captcha is not valid.';
} elseif (true !== ($answer = $this->check($datas, $form->getAttribute('option_validator')))) {
$error = sprintf('Unable to check the captcha from the server. (%s)', $answer);
}
} elseif ($this->code != $datas['response']) {
} elseif ($this->options['code'] != $datas['response']) {
$error = "The captcha is not valid.";
}

Expand All @@ -100,14 +110,18 @@ public function validate(DataEvent $event)
*/
private function check(array $datas, array $options)
{
$options = array_merge($this->options, $options);
$response = '';
$datas = http_build_query($datas, null, '&');
$httpRequest = sprintf($this->httpRequest, $options['path'], $options['host'], strlen($datas), $datas);

$errno = 0;
$errstr = '';
if (false === ($fs = @fsockopen(
$options['host'],
$options['port'],
$errno, $errstr,
empty($options['proxy']) ? $options['host'] : $options['proxy']['host'],
empty($options['proxy']) ? $options['port'] : $options['proxy']['port'],
$errno,
$errstr,
$options['timeout']
))) {
return $errstr;
Expand Down
3 changes: 2 additions & 1 deletion Resources/config/form.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<parameter key="genemu.form.recaptcha.server_url" />
<parameter key="genemu.form.recaptcha.code" />
<parameter key="genemu.form.recaptcha.options" type="collection" />
<parameter key="genemu.form.recaptcha.validation.options" type="collection" />

<parameter key="genemu.form.captcha.options" type="collection" />
<parameter key="genemu.form.tinymce.configs" type="collection" />
Expand All @@ -19,7 +20,7 @@
<service id="genemu.form.type_recaptcha.validator" class="Genemu\Bundle\FormBundle\Form\Core\Validator\ReCaptchaValidator">
<argument type="service" id="request" strict="false" />
<argument>%genemu.form.recaptcha.private_key%</argument>
<argument>%genemu.form.recaptcha.code%</argument>
<argument>%genemu.form.recaptcha.validation.options%</argument>
</service>

<service id="genemu.form.core.type.recaptcha" class="Genemu\Bundle\FormBundle\Form\Core\Type\ReCaptchaType">
Expand Down
18 changes: 12 additions & 6 deletions Resources/doc/recaptcha/default.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@

``` yml
# app/config/config.yml
genemu_form:
genenu_form:
recaptcha:
enabled: true
server_url: 'http://api.recaptcha.net'
ssl:
use: true
server_url: 'https://api-secure.recaptcha.net'
enabled: true
public_key: ~ # Required
private_key: ~ # Required
validation:
host: api-verify.recaptcha.net
port: 80
path: /verify
timeout: 10
code: ~
proxy: ~
configs: []
```
3 changes: 2 additions & 1 deletion Resources/doc/recaptcha/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ You can define a static code for your test environment:
# app/config/config_test.yml
genemu_form:
recaptcha:
code: 1234
validation:
code: 1234
```
## Default Usage:
Expand Down
2 changes: 1 addition & 1 deletion Tests/Form/Core/Type/ReCaptchaTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function testCode($code, $isValid)
{
$request = new Request(array(), array('recaptcha_response_field' => $code));
$form = $this->factory->create(new ReCaptchaType(
new ReCaptchaValidator($request, 'privateKey', '1234'),
new ReCaptchaValidator($request, 'privateKey', array('code' => '1234')),
'publicKey',
'http://api.recaptcha.net',
array()
Expand Down
10 changes: 9 additions & 1 deletion Tests/Form/Extension/TypeExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,15 @@ protected function loadTypes()
'folder' => '/upload'
), __DIR__.'/../../Fixtures'),
new Form\Core\Type\ReCaptchaType(
new ReCaptchaValidator($this->request, 'privateKey'),
new ReCaptchaValidator(
$this->request,
'privateKey',
array(
'host' => 'api-verify.recaptcha.net',
'port' => 80,
'path' => '/verify',
'timeout' => 10
)),
'publicKey',
'http://api.recaptcha.net',
array()),
Expand Down

0 comments on commit cbdf559

Please sign in to comment.