CCaptchaValidator.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <?php
  2. /**
  3. * CCaptchaValidator class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CCaptchaValidator validates that the attribute value is the same as the verification code displayed in the CAPTCHA.
  12. *
  13. * CCaptchaValidator should be used together with {@link CCaptchaAction}.
  14. *
  15. * @author Qiang Xue <qiang.xue@gmail.com>
  16. * @package system.validators
  17. * @since 1.0
  18. */
  19. class CCaptchaValidator extends CValidator
  20. {
  21. /**
  22. * @var boolean whether the comparison is case sensitive. Defaults to false.
  23. */
  24. public $caseSensitive=false;
  25. /**
  26. * @var string ID of the action that renders the CAPTCHA image. Defaults to 'captcha',
  27. * meaning the 'captcha' action declared in the current controller.
  28. * This can also be a route consisting of controller ID and action ID.
  29. */
  30. public $captchaAction='captcha';
  31. /**
  32. * @var boolean whether the attribute value can be null or empty.
  33. * Defaults to false, meaning the attribute is invalid if it is empty.
  34. */
  35. public $allowEmpty=false;
  36. /**
  37. * Validates the attribute of the object.
  38. * If there is any error, the error message is added to the object.
  39. * @param CModel $object the object being validated
  40. * @param string $attribute the attribute being validated
  41. */
  42. protected function validateAttribute($object,$attribute)
  43. {
  44. $value=$object->$attribute;
  45. if($this->allowEmpty && $this->isEmpty($value))
  46. return;
  47. $captcha=$this->getCaptchaAction();
  48. // reason of array checking is explained here: https://github.com/yiisoft/yii/issues/1955
  49. if(is_array($value) || !$captcha->validate($value,$this->caseSensitive))
  50. {
  51. $message=$this->message!==null?$this->message:Yii::t('yii','The verification code is incorrect.');
  52. $this->addError($object,$attribute,$message);
  53. }
  54. }
  55. /**
  56. * Returns the CAPTCHA action object.
  57. * @throws CException if {@link action} is invalid
  58. * @return CCaptchaAction the action object
  59. * @since 1.1.7
  60. */
  61. protected function getCaptchaAction()
  62. {
  63. if(($captcha=Yii::app()->getController()->createAction($this->captchaAction))===null)
  64. {
  65. if(strpos($this->captchaAction,'/')!==false) // contains controller or module
  66. {
  67. if(($ca=Yii::app()->createController($this->captchaAction))!==null)
  68. {
  69. list($controller,$actionID)=$ca;
  70. $captcha=$controller->createAction($actionID);
  71. }
  72. }
  73. if($captcha===null)
  74. throw new CException(Yii::t('yii','CCaptchaValidator.action "{id}" is invalid. Unable to find such an action in the current controller.',
  75. array('{id}'=>$this->captchaAction)));
  76. }
  77. return $captcha;
  78. }
  79. /**
  80. * Returns the JavaScript needed for performing client-side validation.
  81. * @param CModel $object the data object being validated
  82. * @param string $attribute the name of the attribute to be validated.
  83. * @return string the client-side validation script.
  84. * @see CActiveForm::enableClientValidation
  85. * @since 1.1.7
  86. */
  87. public function clientValidateAttribute($object,$attribute)
  88. {
  89. $captcha=$this->getCaptchaAction();
  90. $message=$this->message!==null ? $this->message : Yii::t('yii','The verification code is incorrect.');
  91. $message=strtr($message, array(
  92. '{attribute}'=>$object->getAttributeLabel($attribute),
  93. ));
  94. $code=$captcha->getVerifyCode(false);
  95. $hash=$captcha->generateValidationHash($this->caseSensitive ? $code : strtolower($code));
  96. $js="
  97. var hash = jQuery('body').data('{$this->captchaAction}.hash');
  98. if (hash == null)
  99. hash = $hash;
  100. else
  101. hash = hash[".($this->caseSensitive ? 0 : 1)."];
  102. for(var i=value.length-1, h=0; i >= 0; --i) h+=value.".($this->caseSensitive ? '' : 'toLowerCase().')."charCodeAt(i);
  103. if(h != hash) {
  104. messages.push(".CJSON::encode($message).");
  105. }
  106. ";
  107. if($this->allowEmpty)
  108. {
  109. $js="
  110. if(jQuery.trim(value)!='') {
  111. $js
  112. }
  113. ";
  114. }
  115. return $js;
  116. }
  117. }