PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Captcha/Word.php

https://github.com/sidealice/zf2
PHP | 420 lines | 179 code | 42 blank | 199 comment | 17 complexity | 0f4929715aecb5c213d0f92aa7727910 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Captcha
  17. * @subpackage Adapter
  18. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. */
  21. /**
  22. * @namespace
  23. */
  24. namespace Zend\Captcha;
  25. /**
  26. * Word-based captcha adapter
  27. *
  28. * Generates random word which user should recognise
  29. *
  30. * @uses Zend\Captcha\AbstractAdapter
  31. * @uses Zend\Loader
  32. * @category Zend
  33. * @package Zend_Captcha
  34. * @subpackage Adapter
  35. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  36. * @license http://framework.zend.com/license/new-bsd New BSD License
  37. */
  38. abstract class Word extends AbstractAdapter
  39. {
  40. /**#@+
  41. * @var array Character sets
  42. */
  43. static $V = array("a", "e", "i", "o", "u", "y");
  44. static $VN = array("a", "e", "i", "o", "u", "y","2","3","4","5","6","7","8","9");
  45. static $C = array("b","c","d","f","g","h","j","k","m","n","p","q","r","s","t","u","v","w","x","z");
  46. static $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");
  47. /**#@-*/
  48. /**
  49. * Random session ID
  50. *
  51. * @var string
  52. */
  53. protected $_id;
  54. /**
  55. * Generated word
  56. *
  57. * @var string
  58. */
  59. protected $_word;
  60. /**
  61. * Session
  62. *
  63. * @var \Zend\Session\Container
  64. */
  65. protected $_session;
  66. /**
  67. * Class name for sessions
  68. *
  69. * @var string
  70. */
  71. protected $_sessionClass = 'Zend\\Session\\Container';
  72. /**
  73. * Should the numbers be used or only letters
  74. *
  75. * @var boolean
  76. */
  77. protected $_useNumbers = true;
  78. /**
  79. * Should both cases be used or only lowercase
  80. *
  81. * @var boolean
  82. */
  83. // protected $_useCase = false;
  84. /**
  85. * Session lifetime for the captcha data
  86. *
  87. * @var integer
  88. */
  89. protected $_timeout = 300;
  90. /**
  91. * Should generate() keep session or create a new one?
  92. *
  93. * @var boolean
  94. */
  95. protected $_keepSession = false;
  96. /**#@+
  97. * Error codes
  98. */
  99. const MISSING_VALUE = 'missingValue';
  100. const MISSING_ID = 'missingID';
  101. const BAD_CAPTCHA = 'badCaptcha';
  102. /**#@-*/
  103. /**
  104. * Error messages
  105. * @var array
  106. */
  107. protected $_messageTemplates = array(
  108. self::MISSING_VALUE => 'Empty captcha value',
  109. self::MISSING_ID => 'Captcha ID field is missing',
  110. self::BAD_CAPTCHA => 'Captcha value is wrong',
  111. );
  112. /**
  113. * Length of the word to generate
  114. *
  115. * @var integer
  116. */
  117. protected $_wordlen = 8;
  118. /**
  119. * Retrieve session class to utilize
  120. *
  121. * @return string
  122. */
  123. public function getSessionClass()
  124. {
  125. return $this->_sessionClass;
  126. }
  127. /**
  128. * Set session class for persistence
  129. *
  130. * @param string $_sessionClass
  131. * @return \Zend\Captcha\Word
  132. */
  133. public function setSessionClass($_sessionClass)
  134. {
  135. $this->_sessionClass = $_sessionClass;
  136. return $this;
  137. }
  138. /**
  139. * Retrieve word length to use when genrating captcha
  140. *
  141. * @return integer
  142. */
  143. public function getWordlen()
  144. {
  145. return $this->_wordlen;
  146. }
  147. /**
  148. * Set word length of captcha
  149. *
  150. * @param integer $wordlen
  151. * @return \Zend\Captcha\Word
  152. */
  153. public function setWordlen($wordlen)
  154. {
  155. $this->_wordlen = $wordlen;
  156. return $this;
  157. }
  158. /**
  159. * Retrieve captcha ID
  160. *
  161. * @return string
  162. */
  163. public function getId ()
  164. {
  165. if (null === $this->_id) {
  166. $this->_setId($this->_generateRandomId());
  167. }
  168. return $this->_id;
  169. }
  170. /**
  171. * Set captcha identifier
  172. *
  173. * @param string $id
  174. * return Zend_Captcha_Word
  175. */
  176. protected function _setId ($id)
  177. {
  178. $this->_id = $id;
  179. return $this;
  180. }
  181. /**
  182. * Set timeout for session token
  183. *
  184. * @param int $ttl
  185. * @return \Zend\Captcha\Word
  186. */
  187. public function setTimeout($ttl)
  188. {
  189. $this->_timeout = (int) $ttl;
  190. return $this;
  191. }
  192. /**
  193. * Get session token timeout
  194. *
  195. * @return int
  196. */
  197. public function getTimeout()
  198. {
  199. return $this->_timeout;
  200. }
  201. /**
  202. * Sets if session should be preserved on generate()
  203. *
  204. * @param $keepSession Should session be kept on generate()?
  205. * @return \Zend\Captcha\Word
  206. */
  207. public function setKeepSession($keepSession)
  208. {
  209. $this->_keepSession = $keepSession;
  210. return $this;
  211. }
  212. /**
  213. * Numbers should be included in the pattern?
  214. *
  215. * @return bool
  216. */
  217. public function getUseNumbers()
  218. {
  219. return $this->_useNumbers;
  220. }
  221. /**
  222. * Set if numbers should be included in the pattern
  223. *
  224. * @param $_useNumbers numbers should be included in the pattern?
  225. * @return Zend_Captcha_Word
  226. */
  227. public function setUseNumbers($_useNumbers)
  228. {
  229. $this->_useNumbers = $_useNumbers;
  230. return $this;
  231. }
  232. /**
  233. * Get session object
  234. *
  235. * @return \Zend\Session\Container
  236. */
  237. public function getSession()
  238. {
  239. if (!isset($this->_session) || (null === $this->_session)) {
  240. $id = $this->getId();
  241. if (!class_exists($this->_sessionClass)) {
  242. \Zend\Loader::loadClass($this->_sessionClass);
  243. }
  244. $this->_session = new $this->_sessionClass('Zend_Form_Captcha_' . $id);
  245. $this->_session->setExpirationHops(1, null, true);
  246. $this->_session->setExpirationSeconds($this->getTimeout());
  247. }
  248. return $this->_session;
  249. }
  250. /**
  251. * Set session namespace object
  252. *
  253. * @param \Zend\Session\Container $session
  254. * @return \Zend\Captcha\Word
  255. */
  256. public function setSession(\Zend\Session\Container $session)
  257. {
  258. $this->_session = $session;
  259. if($session) {
  260. $this->_keepSession = true;
  261. }
  262. return $this;
  263. }
  264. /**
  265. * Get captcha word
  266. *
  267. * @return string
  268. */
  269. public function getWord()
  270. {
  271. if (empty($this->_word)) {
  272. $session = $this->getSession();
  273. $this->_word = $session->word;
  274. }
  275. return $this->_word;
  276. }
  277. /**
  278. * Set captcha word
  279. *
  280. * @param string $word
  281. * @return \Zend\Captcha\Word
  282. */
  283. protected function _setWord($word)
  284. {
  285. $session = $this->getSession();
  286. $session->word = $word;
  287. $this->_word = $word;
  288. return $this;
  289. }
  290. /**
  291. * Generate new random word
  292. *
  293. * @return string
  294. */
  295. protected function _generateWord()
  296. {
  297. $word = '';
  298. $wordLen = $this->getWordLen();
  299. $vowels = $this->_useNumbers ? self::$VN : self::$V;
  300. $consonants = $this->_useNumbers ? self::$CN : self::$C;
  301. for ($i=0; $i < $wordLen; $i = $i + 2) {
  302. // generate word with mix of vowels and consonants
  303. $consonant = $consonants[array_rand($consonants)];
  304. $vowel = $vowels[array_rand($vowels)];
  305. $word .= $consonant . $vowel;
  306. }
  307. if (strlen($word) > $wordLen) {
  308. $word = substr($word, 0, $wordLen);
  309. }
  310. return $word;
  311. }
  312. /**
  313. * Generate new session ID and new word
  314. *
  315. * @return string session ID
  316. */
  317. public function generate()
  318. {
  319. if(!$this->_keepSession) {
  320. $this->_session = null;
  321. }
  322. $id = $this->_generateRandomId();
  323. $this->_setId($id);
  324. $word = $this->_generateWord();
  325. $this->_setWord($word);
  326. return $id;
  327. }
  328. protected function _generateRandomId()
  329. {
  330. return md5(mt_rand(0, 1000) . microtime(true));
  331. }
  332. /**
  333. * Validate the word
  334. *
  335. * @see Zend\Validator\Validator::isValid()
  336. * @param mixed $value
  337. * @return boolean
  338. */
  339. public function isValid($value, $context = null)
  340. {
  341. if (!is_array($value) && !is_array($context)) {
  342. $this->_error(self::MISSING_VALUE);
  343. return false;
  344. }
  345. if (!is_array($value) && is_array($context)) {
  346. $value = $context;
  347. }
  348. $name = $this->getName();
  349. if (isset($value[$name])) {
  350. $value = $value[$name];
  351. }
  352. if (!isset($value['input'])) {
  353. $this->_error(self::MISSING_VALUE);
  354. return false;
  355. }
  356. $input = strtolower($value['input']);
  357. $this->_setValue($input);
  358. if (!isset($value['id'])) {
  359. $this->_error(self::MISSING_ID);
  360. return false;
  361. }
  362. $this->_id = $value['id'];
  363. if ($input !== $this->getWord()) {
  364. $this->_error(self::BAD_CAPTCHA);
  365. return false;
  366. }
  367. return true;
  368. }
  369. /**
  370. * Get captcha decorator
  371. *
  372. * @return string
  373. */
  374. public function getDecorator()
  375. {
  376. return "Captcha\Word";
  377. }
  378. }