File indexing completed on 2024-12-22 05:36:30
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Captcha 0017 * @subpackage Adapter 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 */ 0021 0022 /** @see Zend_Captcha_Base */ 0023 // require_once 'Zend/Captcha/Base.php'; 0024 0025 /** @see Zend_Crypt_Math */ 0026 // require_once 'Zend/Crypt/Math.php'; 0027 0028 /** 0029 * Word-based captcha adapter 0030 * 0031 * Generates random word which user should recognise 0032 * 0033 * @category Zend 0034 * @package Zend_Captcha 0035 * @subpackage Adapter 0036 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0037 * @license http://framework.zend.com/license/new-bsd New BSD License 0038 * @version $Id$ 0039 */ 0040 abstract class Zend_Captcha_Word extends Zend_Captcha_Base 0041 { 0042 /**#@+ 0043 * @var array Character sets 0044 */ 0045 static public $V = array("a", "e", "i", "o", "u", "y"); 0046 static public $VN = array("a", "e", "i", "o", "u", "y","2","3","4","5","6","7","8","9"); 0047 static public $C = array("b","c","d","f","g","h","j","k","m","n","p","q","r","s","t","u","v","w","x","z"); 0048 static public $CN = array("b","c","d","f","g","h","j","k","m","n","p","q","r","s","t","u","v","w","x","z","2","3","4","5","6","7","8","9"); 0049 /**#@-*/ 0050 0051 /** 0052 * Random session ID 0053 * 0054 * @var string 0055 */ 0056 protected $_id; 0057 0058 /** 0059 * Generated word 0060 * 0061 * @var string 0062 */ 0063 protected $_word; 0064 0065 /** 0066 * Session 0067 * 0068 * @var Zend_Session_Namespace 0069 */ 0070 protected $_session; 0071 0072 /** 0073 * Class name for sessions 0074 * 0075 * @var string 0076 */ 0077 protected $_sessionClass = 'Zend_Session_Namespace'; 0078 0079 /** 0080 * Should the numbers be used or only letters 0081 * 0082 * @var boolean 0083 */ 0084 protected $_useNumbers = true; 0085 0086 /** 0087 * Should both cases be used or only lowercase 0088 * 0089 * @var boolean 0090 */ 0091 // protected $_useCase = false; 0092 0093 /** 0094 * Session lifetime for the captcha data 0095 * 0096 * @var integer 0097 */ 0098 protected $_timeout = 300; 0099 0100 /** 0101 * Should generate() keep session or create a new one? 0102 * 0103 * @var boolean 0104 */ 0105 protected $_keepSession = false; 0106 0107 /**#@+ 0108 * Error codes 0109 */ 0110 const MISSING_VALUE = 'missingValue'; 0111 const MISSING_ID = 'missingID'; 0112 const BAD_CAPTCHA = 'badCaptcha'; 0113 /**#@-*/ 0114 0115 /** 0116 * Error messages 0117 * @var array 0118 */ 0119 protected $_messageTemplates = array( 0120 self::MISSING_VALUE => 'Empty captcha value', 0121 self::MISSING_ID => 'Captcha ID field is missing', 0122 self::BAD_CAPTCHA => 'Captcha value is wrong', 0123 ); 0124 0125 /** 0126 * Length of the word to generate 0127 * 0128 * @var integer 0129 */ 0130 protected $_wordlen = 8; 0131 0132 /** 0133 * Retrieve session class to utilize 0134 * 0135 * @return string 0136 */ 0137 public function getSessionClass() 0138 { 0139 return $this->_sessionClass; 0140 } 0141 0142 /** 0143 * Set session class for persistence 0144 * 0145 * @param string $_sessionClass 0146 * @return Zend_Captcha_Word 0147 */ 0148 public function setSessionClass($_sessionClass) 0149 { 0150 $this->_sessionClass = $_sessionClass; 0151 return $this; 0152 } 0153 0154 /** 0155 * Retrieve word length to use when genrating captcha 0156 * 0157 * @return integer 0158 */ 0159 public function getWordlen() 0160 { 0161 return $this->_wordlen; 0162 } 0163 0164 /** 0165 * Set word length of captcha 0166 * 0167 * @param integer $wordlen 0168 * @return Zend_Captcha_Word 0169 */ 0170 public function setWordlen($wordlen) 0171 { 0172 $this->_wordlen = $wordlen; 0173 return $this; 0174 } 0175 0176 /** 0177 * Retrieve captcha ID 0178 * 0179 * @return string 0180 */ 0181 public function getId() 0182 { 0183 if (null === $this->_id) { 0184 $this->_setId($this->_generateRandomId()); 0185 } 0186 return $this->_id; 0187 } 0188 0189 /** 0190 * Set captcha identifier 0191 * 0192 * @param string $id 0193 * @return Zend_Captcha_Word 0194 */ 0195 protected function _setId($id) 0196 { 0197 $this->_id = $id; 0198 return $this; 0199 } 0200 0201 /** 0202 * Set timeout for session token 0203 * 0204 * @param int $ttl 0205 * @return Zend_Captcha_Word 0206 */ 0207 public function setTimeout($ttl) 0208 { 0209 $this->_timeout = (int) $ttl; 0210 return $this; 0211 } 0212 0213 /** 0214 * Get session token timeout 0215 * 0216 * @return int 0217 */ 0218 public function getTimeout() 0219 { 0220 return $this->_timeout; 0221 } 0222 0223 /** 0224 * Sets if session should be preserved on generate() 0225 * 0226 * @param bool $keepSession Should session be kept on generate()? 0227 * @return Zend_Captcha_Word 0228 */ 0229 public function setKeepSession($keepSession) 0230 { 0231 $this->_keepSession = $keepSession; 0232 return $this; 0233 } 0234 0235 /** 0236 * Numbers should be included in the pattern? 0237 * 0238 * @return bool 0239 */ 0240 public function getUseNumbers() 0241 { 0242 return $this->_useNumbers; 0243 } 0244 0245 /** 0246 * Set if numbers should be included in the pattern 0247 * 0248 * @param bool $_useNumbers numbers should be included in the pattern? 0249 * @return Zend_Captcha_Word 0250 */ 0251 public function setUseNumbers($_useNumbers) 0252 { 0253 $this->_useNumbers = $_useNumbers; 0254 return $this; 0255 } 0256 0257 /** 0258 * Get session object 0259 * 0260 * @return Zend_Session_Namespace 0261 */ 0262 public function getSession() 0263 { 0264 if (!isset($this->_session) || (null === $this->_session)) { 0265 $id = $this->getId(); 0266 if (!class_exists($this->_sessionClass)) { 0267 // require_once 'Zend/Loader.php'; 0268 Zend_Loader::loadClass($this->_sessionClass); 0269 } 0270 $this->_session = new $this->_sessionClass('Zend_Form_Captcha_' . $id); 0271 $this->_session->setExpirationHops(1, null, true); 0272 $this->_session->setExpirationSeconds($this->getTimeout()); 0273 } 0274 return $this->_session; 0275 } 0276 0277 /** 0278 * Set session namespace object 0279 * 0280 * @param Zend_Session_Namespace $session 0281 * @return Zend_Captcha_Word 0282 */ 0283 public function setSession(Zend_Session_Namespace $session) 0284 { 0285 $this->_session = $session; 0286 if ($session) { 0287 $this->_keepSession = true; 0288 } 0289 return $this; 0290 } 0291 0292 /** 0293 * Get captcha word 0294 * 0295 * @return string 0296 */ 0297 public function getWord() 0298 { 0299 if (empty($this->_word)) { 0300 $session = $this->getSession(); 0301 $this->_word = $session->word; 0302 } 0303 return $this->_word; 0304 } 0305 0306 /** 0307 * Set captcha word 0308 * 0309 * @param string $word 0310 * @return Zend_Captcha_Word 0311 */ 0312 protected function _setWord($word) 0313 { 0314 $session = $this->getSession(); 0315 $session->word = $word; 0316 $this->_word = $word; 0317 return $this; 0318 } 0319 0320 /** 0321 * Generate new random word 0322 * 0323 * @return string 0324 */ 0325 protected function _generateWord() 0326 { 0327 $word = ''; 0328 $wordLen = $this->getWordLen(); 0329 $vowels = $this->_useNumbers ? self::$VN : self::$V; 0330 $consonants = $this->_useNumbers ? self::$CN : self::$C; 0331 0332 $totIndexCon = count($consonants) - 1; 0333 $totIndexVow = count($vowels) - 1; 0334 for ($i=0; $i < $wordLen; $i = $i + 2) { 0335 // generate word with mix of vowels and consonants 0336 $consonant = $consonants[Zend_Crypt_Math::randInteger(0, $totIndexCon, true)]; 0337 $vowel = $vowels[Zend_Crypt_Math::randInteger(0, $totIndexVow, true)]; 0338 $word .= $consonant . $vowel; 0339 } 0340 0341 if (strlen($word) > $wordLen) { 0342 $word = substr($word, 0, $wordLen); 0343 } 0344 0345 return $word; 0346 } 0347 0348 /** 0349 * Generate new session ID and new word 0350 * 0351 * @return string session ID 0352 */ 0353 public function generate() 0354 { 0355 if (!$this->_keepSession) { 0356 $this->_session = null; 0357 } 0358 $id = $this->_generateRandomId(); 0359 $this->_setId($id); 0360 $word = $this->_generateWord(); 0361 $this->_setWord($word); 0362 return $id; 0363 } 0364 0365 protected function _generateRandomId() 0366 { 0367 return md5(Zend_Crypt_Math::randBytes(32)); 0368 } 0369 0370 /** 0371 * Validate the word 0372 * 0373 * @see Zend_Validate_Interface::isValid() 0374 * @param mixed $value 0375 * @param array|null $context 0376 * @return boolean 0377 */ 0378 public function isValid($value, $context = null) 0379 { 0380 if (!is_array($value) && !is_array($context)) { 0381 $this->_error(self::MISSING_VALUE); 0382 return false; 0383 } 0384 if (!is_array($value) && is_array($context)) { 0385 $value = $context; 0386 } 0387 0388 $name = $this->getName(); 0389 0390 if (isset($value[$name])) { 0391 $value = $value[$name]; 0392 } 0393 0394 if (!isset($value['input'])) { 0395 $this->_error(self::MISSING_VALUE); 0396 return false; 0397 } 0398 $input = strtolower($value['input']); 0399 $this->_setValue($input); 0400 0401 if (!isset($value['id'])) { 0402 $this->_error(self::MISSING_ID); 0403 return false; 0404 } 0405 0406 $this->_id = $value['id']; 0407 if ($input !== $this->getWord()) { 0408 $this->_error(self::BAD_CAPTCHA); 0409 return false; 0410 } 0411 0412 return true; 0413 } 0414 0415 /** 0416 * Get captcha decorator 0417 * 0418 * @return string 0419 */ 0420 public function getDecorator() 0421 { 0422 return "Captcha_Word"; 0423 } 0424 }