Browse files

Merged master into develop and added a check if the api response is e…

…mpty
  • Loading branch information...
2 parents 2223655 + a4fba8a commit 44cf45a79c8362ed42f48dac7e2d3b8e1c7d78eb @burzum burzum committed Nov 4, 2010
View
58 controllers/components/recaptcha.php
@@ -29,7 +29,7 @@ class RecaptchaComponent extends Object {
*
* @var string
*/
- public $apiUrl = 'http://api-verify.recaptcha.net/verify';
+ public $apiUrl = 'http://www.google.com/recaptcha/api/verify';
/**
* Private API Key
@@ -52,39 +52,56 @@ class RecaptchaComponent extends Object {
*/
public $actions = array();
+/**
+ * Settings
+ *
+ * @var array
+ */
+ public $settings = array();
+
/**
* Callback
*
* @param object Controller object
*/
- public function initialize(&$controller, $settings = array()) {
+ public function initialize(Controller $controller, $settings = array()) {
$this->privateKey = Configure::read('Recaptcha.privateKey');
$this->Controller = $controller;
- if ($this->enabled == true) {
- foreach ($settings as $setting => $value) {
- if (isset($this->{$setting})) {
- $this->{$setting} = $value;
- }
- }
-
- if (empty($this->privateKey)) {
- throw new Exception(__d('recaptcha', "You must set your private recaptcha key using Cofigure::write('Recaptcha.privateKey', 'your-key');!", true));
- }
-
- $controller->helpers[] = 'Recaptcha.Recaptcha';
+ if (empty($this->privateKey)) {
+ throw new Exception(__d('recaptcha', "You must set your private recaptcha key using Cofigure::write('Recaptcha.privateKey', 'your-key');!", true));
}
- if (in_array($this->Controller->action, $this->actions)) {
- if (!$this->verify()) {
- $this->Controller->{$this->Controller->modelClass}->invalidate('recaptcha', $this->error);
+ $defaults = array(
+ 'modelClass' => $this->Controller->modelClass,
+ 'errorField' => 'recaptcha',
+ 'actions' => array());
+
+ $this->settings = array_merge($defaults, $settings);
+ $this->actions = array_merge($this->actions, $this->settings['actions']);
+ extract($this->settings);
+
+ if ($this->enabled == true) {
+ $this->Controller->helpers[] = 'Recaptcha.Recaptcha';
+ $this->Controller->{$modelClass}->Behaviors->attach('Recaptcha.Recaptcha', array(
+ 'field' => $errorField));
+
+ $this->Controller->{$modelClass}->recaptcha = true;
+ if (in_array($this->Controller->action, $this->actions)) {
+ if (!$this->verify()) {
+ $this->Controller->{$modelClass}->recaptcha = false;
+ $this->Controller->{$modelClass}->recaptchaError = $this->error;
+ }
}
}
}
/**
* Verifies the recaptcha input
*
+ * Please note that you still have to pass the result to the model and do
+ * the validation there to make sure the data is not saved!
+ *
* @return boolean True if the response was correct
*/
public function verify() {
@@ -94,6 +111,11 @@ public function verify() {
$response = $this->_getApiResponse();
$response = explode("\n", $response);
+ if (empty($response[0])) {
+ $this->error = __d('recaptcha', 'Invalid API response, please contact the site admin.', true);
+ return false;
+ }
+
if ($response[0] == 'true') {
return true;
}
@@ -123,4 +145,4 @@ protected function _getApiResponse() {
'response' => $this->Controller->params['form']['recaptcha_response_field']));
}
-}
+}
View
71 models/behaviors/recaptcha.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
+ *
+ * Licensed under The MIT License
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
+ * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
+ */
+
+/**
+ * CakePHP Recaptcha Behavior
+ *
+ * @package recaptcha
+ * @subpackage recaptcha.models.behaviors
+ */
+class RecaptchaBehavior extends ModelBehavior {
+/**
+ * Settings array
+ *
+ * @var array
+ */
+ public $settings = array();
+
+/**
+ * Default settings
+ *
+ * @var array
+ */
+ public $defaults = array(
+ 'errorField' => 'recaptcha');
+
+/**
+ * Setup
+ *
+ * @param AppModel $model
+ * @param array $settings
+ */
+ public function setup(Model $Model, $settings = array()) {
+ if (!isset($this->settings[$Model->alias])) {
+ $this->settings[$Model->alias] = $this->defaults;
+ }
+ $this->settings[$Model->alias] = array_merge($this->settings[$Model->alias], ife(is_array($settings), $settings, array()));
+ }
+
+/**
+ * Validates the captcha responses status set by the component to the model
+ *
+ * @object Model instance
+ * @return boolean
+ * @see RecaptchaComponent::initialize()
+ */
+ public function validateCaptcha(Model $Model) {
+ if (isset($Model->recaptcha) && $Model->recaptcha === false) {
+ $Model->invalidate($this->settings[$Model->alias]['errorField'], $Model->recaptchaError);
+ }
+ return true;
+ }
+
+/**
+ * Validates the captcha
+ *
+ * @object Model instance
+ * @return void;
+ */
+ public function beforeValidate(Model $Model) {
+ $this->validateCaptcha($Model);
+ return true;
+ }
+}
View
2 readme.md
@@ -4,7 +4,7 @@ The Recaptcha plugin for CakePHP provides spam protection in an easy use helper.
## Usage ##
-To use the recaptcha plugin, include the following two lines in your `/app/config/bootstrap.php` file.
+To use the recaptcha plugin its required to include the following two lines in your `/app/config/bootstrap.php` file.
Configure::write('Recaptcha.publicKey', 'your-public-api-key');
Configure::write('Recaptcha.privateKey', 'your-private-api-key');
View
73 tests/cases/behaviors/recaptcha.test.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
+ *
+ * Licensed under The MIT License
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
+ * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
+ */
+
+App::import('Behavior', 'Recaptcha.Recaptcha');
+
+/**
+ * Slugged Article
+ */
+class RecaptchaArticle extends CakeTestModel {
+ public $name = 'RecaptchaArticle';
+ public $actsAs = array('Recaptcha.Recaptcha');
+ public $useTable = 'articles';
+}
+
+/**
+ * Recaptcha Test case
+ */
+class RecaptchaBehaviorTest extends CakeTestCase {
+
+/**
+ * fixtures property
+ *
+ * @var array
+ */
+ public $fixtures = array('plugin.recaptcha.article');
+
+/**
+ * Creates the model instance
+ *
+ * @return void
+ */
+ public function startTest() {
+ $this->Model = new RecaptchaArticle();
+ $this->Behavior = new RecaptchaBehavior();
+ }
+
+/**
+ * Destroy the model instance
+ *
+ * @return void
+ */
+ public function endTest() {
+ unset($this->Model);
+ unset($this->Behavior);
+ ClassRegistry::flush();
+ }
+
+/**
+ * testValidateCaptcha
+ *
+ * @return void
+ */
+ public function testValidateCaptcha() {
+ $this->Model->validateCaptcha();
+ $result = $this->Model->invalidFields();
+ $this->assertTrue(empty($result));
+
+ $this->Model->recaptcha = false;
+ $this->Model->recaptchaError = 'Invalid Recaptcha';
+ $this->Model->validateCaptcha();
+ $result = $this->Model->invalidFields();
+ $this->assertEqual($result, array('recaptcha' => 'Invalid Recaptcha'));
+ }
+
+}
View
30 tests/cases/components/recaptcha.test.php
@@ -9,41 +9,55 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
+App::import('Lib', 'AppTestCase');
App::import('Core', 'Controller');
App::import('Component', 'Recaptcha.Recaptcha');
Mock::generatePartial('Recaptcha', 'RecaptchaMock', array('_getApiResponse'));
-if (!class_exists('PostsTestController')) {
- class PostsTestController extends Controller {
- public $name = 'PostsTest';
+if (!class_exists('ArticlesTestController')) {
+ class ArticleTestController extends Controller {
+ public $name = 'ArticleTests';
public $components = array('Recaptcha.Recaptcha');
- public $uses = array();
+ public $uses = array('RecaptchaTestArticle');
public function test_captcha() {
}
}
}
+if (!class_exists('RecaptchaTestArticle')) {
+ class RecaptchaTestArticle extends CakeTestModel {
+ public $name = 'RecaptchaTestArticle';
+ public $actsAs = array('Recaptcha.Recaptcha');
+ public $useTable = 'articles';
+ }
+}
+
/**
* RecaptchaTestCase
*
* @package recaptcha
* @subpackage recaptcha.tests.cases.components
*/
-class RecaptchaTestCase extends CakeTestCase {
+class RecaptchaTestCase extends AppTestCase {
+/**
+ * fixtures property
+ *
+ * @var array
+ */
+ public $fixtures = array('plugin.recaptcha.article');
/**
* startTest
*
* @return void
*/
function startTest() {
- Configure::write('Recaptcha.privateKey', 'a-private-key');
- $this->Controller = new PostsTestController();
+ $this->Controller = new ArticleTestController();
$this->Controller->constructClasses();
+ //$this->Controller->modelClass = 'RecaptchaTestArticle';
$this->Controller->Component->init($this->Controller);
$this->Controller->Component->initialize($this->Controller);
- //$this->Controller->Recaptcha = new RecaptchaMock();
}
/**
View
45 tests/fixtures/article_fixture.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
+ *
+ * Licensed under The MIT License
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
+ * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
+ */
+
+/**
+ * Article Fixture
+ *
+ * @package recaptcha
+ * @subpackage recaptcha.tests.fixtures
+ */
+class ArticleFixture extends CakeTestFixture {
+
+/**
+ * name property
+ *
+ * @var string
+ */
+ public $name = 'Article';
+
+/**
+ * fields property
+ *
+ * @var array
+ */
+ public $fields = array(
+ 'id' => array('type' => 'integer', 'key' => 'primary'),
+ 'title' => array('type' => 'string', 'null' => false),
+ 'comments' => array('type' => 'integer', 'null' => false, 'default' => '0'));
+
+/**
+ * records property
+ *
+ * @var array
+ */
+ public $records = array(
+ array('title' => 'First Article', 'comments' => 2),
+ array('title' => 'Second Article', 'comments' => 0));
+}
View
87 views/helpers/recaptcha.php
@@ -36,7 +36,7 @@ class RecaptchaHelper extends AppHelper {
*
* @var array
*/
- public $helpers = array('Html');
+ public $helpers = array('Form', 'Html');
/**
* Displays the Recaptcha input
@@ -51,69 +51,49 @@ public function display($options = array()) {
'publicKey' => Configure::read('Recaptcha.publicKey'),
'error' => null,
'ssl' => true,
- 'theme' => 'white',
- 'lang' => 'en'
- );
+ 'error' => false,
+ 'div' => array(
+ 'class' => 'recaptcha'));
+ $options = array_merge($defaults, $options);
+ extract($options);
- if (Configure::read('Config.language')) {
- $defaults['lang'] = Configure::read('Config.language');
+ if ($ssl) {
+ $server = $this->secureApiUrl;
+ } else {
+ $server = $this->apiUrl;
+ }
+
+ $errorpart = "";
+ if ($error) {
+ $errorpart = "&amp;error=" . $error;
}
- $options = array_merge($defaults, $options);
- if (!empty($options['element'])) {
+ if (!empty($element)) {
$elementOptions = array();
- if (is_array($options['element'])) {
- $keys = array_keys($options['element']);
- $elementOptions = $options['element'][$keys[0]];
+ if (is_array($element)) {
+ $keys = array_keys($element);
+ $elementOptions = $element[$keys[0]];
}
$View = $this->__view();
- return $View->element($options['element'], $elementOptions);
+ return $View->element($element, $elementOptions);
}
- $result = $this->_buildOptions($options);
- $result .= $this->_buildScripts($options);
- return $result;
- }
+ $script = '<script type="text/javascript" src="'. $server . '/challenge?k=' . $publicKey . '"></script>
+ <noscript>
+ <iframe src="'. $server . '/noscript?k=' . $publicKey . '" height="300" width="500" frameborder="0"></iframe><br/>
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+ <input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
+ </noscript>';
-/**
- * Build the Recaptcha options, and return script block for output.
- *
- * @param array $options Options
- * @return string
- */
- protected function _buildOptions($options) {
- $js = <<<ENDJS
-var RecaptchaOptions = {
- theme: "${options['theme']}",
- lang: "${options['lang']}"
-};
-ENDJS;
- return $this->Html->scriptBlock($js);
- }
+ if (!empty($error)) {
+ $script .= $this->Form->error($error);
+ }
-/**
- * Build the script tags to show recaptcha
- *
- * @param array $options Options
- * @return string
- */
- protected function _buildScripts($options) {
- $errorpart = '';
- if ($options['error']) {
- $errorpart = '&amp;error=' . $options['error'];
+ if ($options['div'] != false) {
+ $script = $this->Html->tag('div', $script, $options['div']);
}
- $server = $options['ssl'] ? $this->secureApiUrl : $this->apiUrl;
- $query = '?k=' . $options['publicKey'] . $errorpart;
- $jsCode = $this->Html->script($server . '/challenge' . $query);
- $noJsCode = <<<ENDCODE
-<noscript>
- <iframe src="${server}/noscript${query}" height="300" width="500" frameborder="0"></iframe><br/>
- <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
- <input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
-</noscript>
-ENDCODE;
- return $jsCode . $noJsCode;
+ return $script;
}
/**
@@ -122,7 +102,7 @@ protected function _buildScripts($options) {
* @return string
*/
public function signupUrl($appname = null) {
- return "http://recaptcha.net/api/getkey?domain=" . WWW_ROOT . '&amp;app=' . urlencode($appname);
+ return "http://recaptcha.net/api/getkey?domain=" . WWW_ROOT . '&amp;app=' . urlencode($appName);
}
/**
@@ -231,4 +211,5 @@ private function __view() {
}
return ClassRegistry::getObject('view');
}
+
}

0 comments on commit 44cf45a

Please sign in to comment.