PageRenderTime 72ms CodeModel.GetById 17ms RepoModel.GetById 2ms app.codeStats 0ms

/magento/app/code/core/Mage/Captcha/Model/Zend.php

https://bitbucket.org/jit_bec/shopifine
PHP | 504 lines | 222 code | 49 blank | 233 comment | 32 complexity | 99428bc9078bb65913f6d4c4eafd6a61 MD5 | raw file
Possible License(s): LGPL-3.0
  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  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@magentocommerce.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magentocommerce.com for more information.
  20. *
  21. * @category Mage
  22. * @package Mage_Captcha
  23. * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. /**
  27. * Implementation of Zend_Captcha
  28. *
  29. * @category Mage
  30. * @package Mage_Captcha
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Mage_Captcha_Model_Zend extends Zend_Captcha_Image implements Mage_Captcha_Model_Interface
  34. {
  35. /**
  36. * Key in session for captcha code
  37. */
  38. const SESSION_WORD = 'word';
  39. /**
  40. * Min captcha lengths default value
  41. */
  42. const DEFAULT_WORD_LENGTH_FROM = 3;
  43. /**
  44. * Max captcha lengths default value
  45. */
  46. const DEFAULT_WORD_LENGTH_TO = 5;
  47. /**
  48. * Helper Instance
  49. * @var Mage_Captcha_Helper_Data
  50. */
  51. protected $_helper = null;
  52. /**
  53. * Captcha expire time
  54. * @var int
  55. */
  56. protected $_expiration;
  57. /**
  58. * Override default value to prevent a captcha cut off
  59. * @var int
  60. * @see Zend_Captcha_Image::$_fsize
  61. */
  62. protected $_fsize = 22;
  63. /**
  64. * Captcha form id
  65. * @var string
  66. */
  67. protected $_formId;
  68. /**
  69. * Zend captcha constructor
  70. *
  71. * @param array $params
  72. */
  73. public function __construct($params)
  74. {
  75. if (!isset($params['formId'])) {
  76. throw new Exception('formId is mandatory');
  77. }
  78. $this->_formId = $params['formId'];
  79. $this->setExpiration($this->getTimeout());
  80. }
  81. /**
  82. * Returns key with respect of current form ID
  83. *
  84. * @param string $key
  85. * @return string
  86. */
  87. protected function _getFormIdKey($key)
  88. {
  89. return $this->_formId . '_' . $key;
  90. }
  91. /**
  92. * Get Block Name
  93. *
  94. * @return string
  95. */
  96. public function getBlockName()
  97. {
  98. return 'captcha/captcha_zend';
  99. }
  100. /**
  101. * Whether captcha is required to be inserted to this form
  102. *
  103. * @param null|string $login
  104. * @return bool
  105. */
  106. public function isRequired($login = null)
  107. {
  108. if ($this->_isUserAuth() || !$this->_isEnabled() || !in_array($this->_formId, $this->_getTargetForms())) {
  109. return false;
  110. }
  111. return ($this->_isShowAlways() || $this->_isOverLimitAttempts($login)
  112. || $this->getSession()->getData($this->_getFormIdKey('show_captcha'))
  113. );
  114. }
  115. /**
  116. * Check is overlimit attempts
  117. *
  118. * @param string $login
  119. * @return bool
  120. */
  121. protected function _isOverLimitAttempts($login)
  122. {
  123. return ($this->_isOverLimitIpAttempt() || $this->_isOverLimitLoginAttempts($login));
  124. }
  125. /**
  126. * Returns number of allowed attempts for same login
  127. *
  128. * @return int
  129. */
  130. protected function _getAllowedAttemptsForSameLogin()
  131. {
  132. return (int)$this->_getHelper()->getConfigNode('failed_attempts_login');
  133. }
  134. /**
  135. * Returns number of allowed attempts from same IP
  136. *
  137. * @return int
  138. */
  139. protected function _getAllowedAttemptsFromSameIp()
  140. {
  141. return (int)$this->_getHelper()->getConfigNode('failed_attempts_ip');
  142. }
  143. /**
  144. * Check is overlimit saved attempts from one ip
  145. *
  146. * @return bool
  147. */
  148. protected function _isOverLimitIpAttempt()
  149. {
  150. $countAttemptsByIp = Mage::getResourceModel('captcha/log')->countAttemptsByRemoteAddress();
  151. return $countAttemptsByIp >= $this->_getAllowedAttemptsFromSameIp();
  152. }
  153. /**
  154. * Is Over Limit Login Attempts
  155. *
  156. * @param string $login
  157. * @return bool
  158. */
  159. protected function _isOverLimitLoginAttempts($login)
  160. {
  161. if ($login != false) {
  162. $countAttemptsByLogin = Mage::getResourceModel('captcha/log')->countAttemptsByUserLogin($login);
  163. return ($countAttemptsByLogin >= $this->_getAllowedAttemptsForSameLogin());
  164. }
  165. return false;
  166. }
  167. /**
  168. * Check is user auth
  169. *
  170. * @return bool
  171. */
  172. protected function _isUserAuth()
  173. {
  174. return Mage::app()->getStore()->isAdmin()
  175. ? Mage::getSingleton('admin/session')->isLoggedIn()
  176. : Mage::getSingleton('customer/session')->isLoggedIn();
  177. }
  178. /**
  179. * Whether to respect case while checking the answer
  180. *
  181. * @return bool
  182. */
  183. public function isCaseSensitive()
  184. {
  185. return (string)$this->_getHelper()->getConfigNode('case_sensitive');
  186. }
  187. /**
  188. * Get font to use when generating captcha
  189. *
  190. * @return string
  191. */
  192. public function getFont()
  193. {
  194. return $this->_getFontPath();
  195. }
  196. /**
  197. * After this time isCorrect() is going to return FALSE even if word was guessed correctly
  198. *
  199. * @return int
  200. */
  201. public function getTimeout()
  202. {
  203. if (!$this->_expiration) {
  204. /**
  205. * as "timeout" configuration parameter specifies timeout in minutes - we multiply it on 60 to set
  206. * expiration in seconds
  207. */
  208. $this->_expiration = (int)$this->_getHelper()->getConfigNode('timeout') * 60;
  209. }
  210. return $this->_expiration;
  211. }
  212. /**
  213. * Get captcha image directory
  214. *
  215. * @return string
  216. */
  217. public function getImgDir()
  218. {
  219. return $this->_helper->getImgDir();
  220. }
  221. /**
  222. * Get captcha image base URL
  223. *
  224. * @return string
  225. */
  226. public function getImgUrl()
  227. {
  228. return $this->_helper->getImgUrl();
  229. }
  230. /**
  231. * Checks whether captcha was guessed correctly by user
  232. *
  233. * @param string $word
  234. * @return bool
  235. */
  236. public function isCorrect($word)
  237. {
  238. $storedWord = $this->getWord();
  239. $this->_clearWord();
  240. if (!$word || !$storedWord){
  241. return false;
  242. }
  243. if (!$this->isCaseSensitive()) {
  244. $storedWord = strtolower($storedWord);
  245. $word = strtolower($word);
  246. }
  247. return $word == $storedWord;
  248. }
  249. /**
  250. * Returns session instance
  251. *
  252. * @return Mage_Customer_Model_Session
  253. */
  254. public function getSession()
  255. {
  256. return Mage::getSingleton('customer/session');
  257. }
  258. /**
  259. * Return full URL to captcha image
  260. *
  261. * @return string
  262. */
  263. public function getImgSrc()
  264. {
  265. return $this->getImgUrl() . $this->getId() . $this->getSuffix();
  266. }
  267. /**
  268. * log Attempt
  269. *
  270. * @param string $login
  271. * @return Mage_Captcha_Model_Zend
  272. */
  273. public function logAttempt($login)
  274. {
  275. if ($this->_isEnabled() && in_array($this->_formId, $this->_getTargetForms())) {
  276. Mage::getResourceModel('captcha/log')->logAttempt($login);
  277. if ($this->_isOverLimitLoginAttempts($login)) {
  278. $this->getSession()->setData($this->_getFormIdKey('show_captcha'), 1);
  279. }
  280. }
  281. return $this;
  282. }
  283. /**
  284. * Returns path for the font file, chosen to generate captcha
  285. *
  286. * @return string
  287. */
  288. protected function _getFontPath()
  289. {
  290. $font = (string)$this->_getHelper()->getConfigNode('font');
  291. $fonts = $this->_getHelper()->getFonts();
  292. if (isset($fonts[$font])) {
  293. $fontPath = $fonts[$font]['path'];
  294. } else {
  295. $fontData = array_shift($fonts);
  296. $fontPath = $fontData['path'];
  297. }
  298. return $fontPath;
  299. }
  300. /**
  301. * Returns captcha helper
  302. *
  303. * @return Mage_Captcha_Helper_Data
  304. */
  305. protected function _getHelper()
  306. {
  307. if (empty($this->_helper)) {
  308. $this->_helper = Mage::helper('captcha');
  309. }
  310. return $this->_helper;
  311. }
  312. /**
  313. * Generate word used for captcha render
  314. *
  315. * @return string
  316. */
  317. protected function _generateWord()
  318. {
  319. $word = '';
  320. $symbols = $this->_getSymbols();
  321. $wordLen = $this->_getWordLen();
  322. for ($i = 0; $i < $wordLen; $i++) {
  323. $word .= $symbols[array_rand($symbols)];
  324. }
  325. return $word;
  326. }
  327. /**
  328. * Get symbols array to use for word generation
  329. *
  330. * @return array
  331. */
  332. protected function _getSymbols()
  333. {
  334. return str_split((string)$this->_getHelper()->getConfigNode('symbols'));
  335. }
  336. /**
  337. * Returns length for generating captcha word. This value may be dynamic.
  338. *
  339. * @return int
  340. */
  341. protected function _getWordLen()
  342. {
  343. $from = 0;
  344. $to = 0;
  345. $length = (string)$this->_getHelper()->getConfigNode('length');
  346. if (!is_numeric($length)) {
  347. if (preg_match('/(\d+)-(\d+)/', $length, $matches)) {
  348. $from = (int)$matches[1];
  349. $to = (int)$matches[2];
  350. }
  351. } else {
  352. $from = (int)$length;
  353. $to = (int)$length;
  354. }
  355. if (($to < $from) || ($from < 1) || ($to < 1)) {
  356. $from = self::DEFAULT_WORD_LENGTH_FROM;
  357. $to = self::DEFAULT_WORD_LENGTH_TO;
  358. }
  359. return mt_rand($from, $to);
  360. }
  361. /**
  362. * Whether to show captcha for this form every time
  363. *
  364. * @return bool
  365. */
  366. protected function _isShowAlways()
  367. {
  368. if ((string)$this->_getHelper()->getConfigNode('mode') == Mage_Captcha_Helper_Data::MODE_ALWAYS) {
  369. return true;
  370. }
  371. $alwaysFor = $this->_getHelper()->getConfigNode('always_for');
  372. foreach ($alwaysFor as $nodeFormId => $isAlwaysFor) {
  373. if ($isAlwaysFor && $this->_formId == $nodeFormId) {
  374. return true;
  375. }
  376. }
  377. return false;
  378. }
  379. /**
  380. * Whether captcha is enabled at this area
  381. *
  382. * @return bool
  383. */
  384. protected function _isEnabled()
  385. {
  386. return (string)$this->_getHelper()->getConfigNode('enable');
  387. }
  388. /**
  389. * Retrieve list of forms where captcha must be shown
  390. *
  391. * For frontend this list is based on current website
  392. *
  393. * @return array
  394. */
  395. protected function _getTargetForms()
  396. {
  397. $formsString = (string) $this->_getHelper()->getConfigNode('forms');
  398. return explode(',', $formsString);
  399. }
  400. /**
  401. * Get captcha word
  402. *
  403. * @return string
  404. */
  405. public function getWord()
  406. {
  407. $sessionData = $this->getSession()->getData($this->_getFormIdKey(self::SESSION_WORD));
  408. return time() < $sessionData['expires'] ? $sessionData['data'] : null;
  409. }
  410. /**
  411. * Set captcha word
  412. *
  413. * @param string $word
  414. * @return Zend_Captcha_Word
  415. */
  416. protected function _setWord($word)
  417. {
  418. $this->getSession()->setData($this->_getFormIdKey(self::SESSION_WORD),
  419. array('data' => $word, 'expires' => time() + $this->getTimeout())
  420. );
  421. $this->_word = $word;
  422. return $this;
  423. }
  424. /**
  425. * Set captcha word
  426. *
  427. * @return Mage_Captcha_Model_Zend
  428. */
  429. protected function _clearWord()
  430. {
  431. $this->getSession()->unsetData($this->_getFormIdKey(self::SESSION_WORD));
  432. $this->_word = null;
  433. return $this;
  434. }
  435. /**
  436. * Override function to generate less curly captcha that will not cut off
  437. *
  438. * @see Zend_Captcha_Image::_randomSize()
  439. * @return int
  440. */
  441. protected function _randomSize()
  442. {
  443. return mt_rand(280, 300) / 100;
  444. }
  445. /**
  446. * Overlap of the parent method
  447. *
  448. * Now deleting old captcha images make crontab script
  449. * @see Mage_Captcha_Model_Observer::deleteExpiredImages
  450. */
  451. protected function _gc()
  452. {
  453. //do nothing
  454. }
  455. }