PageRenderTime 25ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/library/Zend/Captcha/Word.php

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