From e542ea49ceb77ad48f144a9f4ab1eaaafe4dc198 Mon Sep 17 00:00:00 2001 From: "ctrlaltca@gmail.com" <> Date: Mon, 19 Dec 2011 13:20:38 +0000 Subject: committed patch from #378 --- HISTORY | 1 + .../source/prado/validator/validation3.js | 45 +++++++++++++++- framework/Web/UI/WebControls/TReCaptcha.php | 33 ++++++++++-- .../Web/UI/WebControls/TReCaptchaValidator.php | 63 +++++++++++++++++++--- 4 files changed, 131 insertions(+), 11 deletions(-) diff --git a/HISTORY b/HISTORY index 455b14fc..94544c07 100644 --- a/HISTORY +++ b/HISTORY @@ -56,6 +56,7 @@ CHG: Issue #370 - Deprecated TSqliteCache since it's based on php's sqlite exten BUG: Issue #371 - Sorting on TActiveDataGrid autogenerated column not work (ctrlaltca) ENH: Issue #372 - ActiveControls's Visible property should be reflected clientside on ajax requests (ctrlaltca) BUG: Issue #375 - Iconv error using htmlarea in TActiveDataList and chars like "áéíóúñ" (ctrlaltca) +BUG: Issue #377 - THtmlArea Template Pluggin Options Parse Error (ctrlaltca) Version 3.1.10 Jul 17, 2011 BUG: Added missing timeout on TCacheHttpSession (ctrlaltca) diff --git a/framework/Web/Javascripts/source/prado/validator/validation3.js b/framework/Web/Javascripts/source/prado/validator/validation3.js index c0f770cf..bbf3929a 100644 --- a/framework/Web/Javascripts/source/prado/validator/validation3.js +++ b/framework/Web/Javascripts/source/prado/validator/validation3.js @@ -790,7 +790,6 @@ Prado.WebUI.TBaseValidator.prototype = options.OnSuccess = options.OnSuccess || Prototype.emptyFunction; options.OnError = options.OnError || Prototype.emptyFunction; */ - /** * Wether the validator is enabled (default true) * @var {boolean} enabled @@ -839,6 +838,9 @@ Prado.WebUI.TBaseValidator.prototype = this.message = $(options.ID); Prado.Registry.set(options.ID, this); + + if (this.onInit) this.onInit(); + if(this.control && this.message) { this.group = options.ValidationGroup; @@ -1940,3 +1942,44 @@ Prado.WebUI.TCaptchaValidator = Class.extend(Prado.WebUI.TBaseValidator, return crc ^ (-1); } }); + + +/** + * TReCaptchaValidator client-side control. + * + * @class Prado.WebUI.TReCaptchaValidator + * @extends Prado.WebUI.TBaseValidator + */ +Prado.WebUI.TReCaptchaValidator = Class.extend(Prado.WebUI.TBaseValidator, +{ + onInit : function() + { + var obj = this; + var elements = document.getElementsByName(this.options.ResponseFieldName); + if (elements) + if (elements.length>=1) + { + Event.observe(elements[0],'change',function() { obj.responseChanged() }); + Event.observe(elements[0],'keydown',function() { obj.responseChanged() }); + } + }, + + responseChanged: function() + { + var field = $(this.options.ID+'_1'); + if (field.value=='1') return; + field.value = '1'; + Prado.Validation.validateControl(this.options.ID); + }, + + /** + * Evaluate validation state + * @function {boolean} ? + * @return True if the captcha has validate, False otherwise. + */ + evaluateIsValid : function() + { + return ($(this.options.ID+'_1').value=='1'); + } +}); + diff --git a/framework/Web/UI/WebControls/TReCaptcha.php b/framework/Web/UI/WebControls/TReCaptcha.php index bb956bcb..50886276 100644 --- a/framework/Web/UI/WebControls/TReCaptcha.php +++ b/framework/Web/UI/WebControls/TReCaptcha.php @@ -51,12 +51,17 @@ * @package System.Web.UI.WebControls * @since 3.2 */ -class TReCaptcha extends TControl implements IValidatable +class TReCaptcha extends TWebControl implements IValidatable { private $_isValid=true; const ChallengeFieldName = 'recaptcha_challenge_field'; const ResponseFieldName = 'recaptcha_response_field'; + + public function getTagName() + { + return 'span'; + } /** * Returns true if this control validated successfully. @@ -135,7 +140,7 @@ class TReCaptcha extends TControl implements IValidatable return /*$this->ClientID.'_'.*/self::ChallengeFieldName; } - protected function getResponseFieldName() + public function getResponseFieldName() { return /*$this->ClientID.'_'.*/self::ResponseFieldName; } @@ -170,18 +175,38 @@ class TReCaptcha extends TControl implements IValidatable public function onPreRender($param) { parent::onPreRender($param); + if("" == $this->getPublicKey()) throw new TConfigurationException('recaptcha_publickey_unknown'); if("" == $this->getPrivateKey()) throw new TConfigurationException('recaptcha_privatekey_unknown'); + + // need to register captcha fields so they will be sent back also in callbacks + $page = $this->getPage(); + $page->registerRequiresPostData($this->getChallengeFieldName()); + $page->registerRequiresPostData($this->getResponseFieldName()); } - public function render($writer) + protected function addAttributesToRender($writer) + { + parent::addAttributesToRender($writer); + $writer->addAttribute('id',$this->getClientID()); + } + + public function regenerateToken() + { + // if we're in a callback, then schedule re-rendering of the control + // if not, don't do anything, because a new challenge will be rendered anyway + if ($this->Page->IsCallback) + $this->Page->ClientScript->registerEndScript($this->getClientID().'::refresh','Recaptcha.reload();'); + } + + public function renderContents($writer) { $writer->write(TJavaScript::renderScriptBlock( 'var RecaptchaOptions = '.TJavaScript::jsonEncode($this->getClientSideOptions()).';' )); - + $html = recaptcha_get_html($this->getPublicKey()); /* reCAPTCHA currently does not support multiple validations per page diff --git a/framework/Web/UI/WebControls/TReCaptchaValidator.php b/framework/Web/UI/WebControls/TReCaptchaValidator.php index ae94ea59..2898a913 100644 --- a/framework/Web/UI/WebControls/TReCaptchaValidator.php +++ b/framework/Web/UI/WebControls/TReCaptchaValidator.php @@ -39,12 +39,29 @@ class TReCaptchaValidator extends TBaseValidator */ protected function getClientClassName() { - return ''; + return 'Prado.WebUI.TReCaptchaValidator'; } public function getEnableClientScript() { - return false; + return true; + } + + protected function getCaptchaControl() + { + $control = $this->getValidationTarget(); + if (!$control) + throw new Exception('No target control specified for TReCaptchaValidator'); + if (!($control instanceof TReCaptcha)) + throw new Exception('TReCaptchaValidator only works with TReCaptcha controls'); + return $control; + } + + public function getClientScriptOptions() + { + $options = parent::getClientScriptOptions(); + $options['ResponseFieldName'] = $this->getCaptchaControl()->getResponseFieldName(); + return $options; } /** @@ -56,17 +73,51 @@ class TReCaptchaValidator extends TBaseValidator */ protected function evaluateIsValid() { - // check validity only once (if trying to evaluate multiple times, all redundant checks would fail) + // check validity only once (if trying to evaulate multiple times, all redundant checks would fail) if (is_null($this->_isvalid)) { - $control = $this->getValidationTarget(); - if(!($control instanceof TCaptcha)) - throw new TConfigurationException('recaptchavalidator_captchacontrol_invalid'); + $control = $this->getCaptchaControl(); $this->_isvalid = $control->validate(); } return ($this->_isvalid==true); } + public function onPreRender($param) + { + parent::onPreRender($param); + + $cs = $this->Page->getClientScript(); + + // communicate validation status to the client side + $value = $this->_isvalid===false ? '0' : '1'; + $cs->registerHiddenField($this->getClientID().'_1',$value); + + // check if we need to request a new captcha too + if ($this->Page->IsCallback) + { + // force update of validator display + if ($control = $this->getValidationTarget()) + { + $cs->registerEndScript( + $this->getClientID().'::validate', + '$(\''.TJavaScript::quoteString($this->getClientID().'_1').'\').value = \''.TJavaScript::quoteString($value).'\';'. + 'Prado.Validation.validateControl(\''.TJavaScript::quoteString($control->ClientID).'\');' + ); + + if ($control->getVisible(true)) + if ($this->_isvalid) + { + // if the challenge has been solved + we're in a callback and we still reach prerender phase, + // that means that some other validator failed and the user will be sent back to the page/form with + // the captcha control. in this case we need to force re-rendering of the control, because once + // solved, the old challenge won't validate anymore anyway + + $control->regenerateToken(); + } + } + } + } + } ?> \ No newline at end of file -- cgit v1.2.3