![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/magento/module-captcha/Model/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ declare(strict_types=1); namespace Magento\Captcha\Model; use Magento\Authorization\Model\UserContextInterface; use Magento\Captcha\Helper\Data; use Magento\Framework\App\ObjectManager; use Magento\Framework\Math\Random; /** * Implementation of \Laminas\Captcha\Image * * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * * @api * @since 100.0.2 */ class DefaultModel extends \Laminas\Captcha\Image implements \Magento\Captcha\Model\CaptchaInterface { /** * Key in session for captcha code */ const SESSION_WORD = 'word'; /** * Min captcha lengths default value */ const DEFAULT_WORD_LENGTH_FROM = 3; /** * Max captcha lengths default value */ const DEFAULT_WORD_LENGTH_TO = 5; /** * @var Data * @since 100.2.0 */ protected $captchaData; /** * Captcha expire time * @var int * @since 100.2.0 */ protected $expiration; /** * Override default value to prevent a captcha cut off * @var int * @see \Laminas\Captcha\Image::$fsize * @since 100.2.0 */ protected $fsize = 22; /** * Captcha form id * @var string * @since 100.2.0 */ protected $formId; /** * @var \Magento\Captcha\Model\ResourceModel\LogFactory * @since 100.2.0 */ protected $resLogFactory; /** * Overrides parent parameter as session comes in constructor. * * @var bool * @since 100.2.0 */ protected $keepSession = true; /** * @var \Magento\Framework\Session\SessionManagerInterface * @since 100.2.0 */ protected $session; /** * @var string */ private $words; /** * @var Random */ private $randomMath; /** * @var UserContextInterface */ private $userContext; /** * @param \Magento\Framework\Session\SessionManagerInterface $session * @param \Magento\Captcha\Helper\Data $captchaData * @param ResourceModel\LogFactory $resLogFactory * @param string $formId * @param Random $randomMath * @param UserContextInterface|null $userContext * @throws \Laminas\Captcha\Exception\ExtensionNotLoadedException */ public function __construct( \Magento\Framework\Session\SessionManagerInterface $session, \Magento\Captcha\Helper\Data $captchaData, \Magento\Captcha\Model\ResourceModel\LogFactory $resLogFactory, $formId, Random $randomMath = null, ?UserContextInterface $userContext = null ) { parent::__construct(); $this->session = $session; $this->captchaData = $captchaData; $this->resLogFactory = $resLogFactory; $this->formId = $formId; $this->randomMath = $randomMath ?? ObjectManager::getInstance()->get(Random::class); $this->userContext = $userContext ?? ObjectManager::getInstance()->get(UserContextInterface::class); } /** * Returns key with respect of current form ID * * @param string $key * @return string */ private function getFormIdKey($key) { return $this->formId . '_' . $key; } /** * Get Block Name * * @return string */ public function getBlockName() { return \Magento\Captcha\Block\Captcha\DefaultCaptcha::class; } /** * Whether captcha is required to be inserted to this form * * @param null|string $login * @return bool */ public function isRequired($login = null) { if (($this->isUserAuth() && !$this->isShownToLoggedInUser()) || !$this->isEnabled() || !in_array( $this->formId, $this->getTargetForms() ) || $this->userContext->getUserType() === UserContextInterface::USER_TYPE_INTEGRATION ) { return false; } return $this->isShowAlways() || $this->isOverLimitAttempts($login) || $this->session->getData($this->getFormIdKey('show_captcha')); } /** * Check if CAPTCHA has to be shown to logged in user on this form * * @return bool */ public function isShownToLoggedInUser() { $forms = (array)$this->captchaData->getConfig('shown_to_logged_in_user'); foreach ($forms as $formId => $isShownToLoggedIn) { if ($isShownToLoggedIn && $this->formId == $formId) { return true; } } return false; } /** * Check is over limit attempts * * @param string $login * @return bool */ private function isOverLimitAttempts($login) { return $this->isOverLimitIpAttempt() || $this->isOverLimitLoginAttempts($login); } /** * Returns number of allowed attempts for same login * * @return int */ private function getAllowedAttemptsForSameLogin() { return (int)$this->captchaData->getConfig('failed_attempts_login'); } /** * Returns number of allowed attempts from same IP * * @return int */ private function getAllowedAttemptsFromSameIp() { return (int)$this->captchaData->getConfig('failed_attempts_ip'); } /** * Check is over limit saved attempts from one ip * * @return bool */ private function isOverLimitIpAttempt() { $countAttemptsByIp = $this->getResourceModel()->countAttemptsByRemoteAddress(); return $countAttemptsByIp >= $this->getAllowedAttemptsFromSameIp(); } /** * Is Over Limit Login Attempts * * @param string $login * @return bool */ private function isOverLimitLoginAttempts($login) { if ($login != false) { $countAttemptsByLogin = $this->getResourceModel()->countAttemptsByUserLogin($login); return $countAttemptsByLogin >= $this->getAllowedAttemptsForSameLogin(); } return false; } /** * Check is user auth * * @return bool */ private function isUserAuth() { return $this->session->isLoggedIn() || $this->userContext->getUserId(); } /** * Whether to respect case while checking the answer * * @return bool */ public function isCaseSensitive() { return (string)$this->captchaData->getConfig('case_sensitive'); } /** * Get font to use when generating captcha * * @return string */ public function getFont() { $font = (string)$this->captchaData->getConfig('font'); $fonts = $this->captchaData->getFonts(); if (isset($fonts[$font])) { $fontPath = $fonts[$font]['path']; } else { $fontData = array_shift($fonts); $fontPath = $fontData['path']; } return $fontPath; } /** * After this time isCorrect() is going to return FALSE even if word was guessed correctly * * @return int */ public function getExpiration() { if (!$this->expiration) { /** * as "timeout" configuration parameter specifies timeout in minutes - we multiply it on 60 to set * expiration in seconds */ $this->expiration = (int)$this->captchaData->getConfig('timeout') * 60; } return $this->expiration; } /** * Get timeout for session token * * @return int */ public function getTimeout() { return $this->getExpiration(); } /** * Get captcha image directory * * @return string */ public function getImgDir() { return $this->captchaData->getImgDir(); } /** * Get captcha image base URL * * @return string */ public function getImgUrl() { return $this->captchaData->getImgUrl(); } /** * Checks whether captcha was guessed correctly by user * * @param string $word * @return bool */ public function isCorrect($word) { $storedWords = $this->getWords(); $this->clearWord(); if (!$word || !$storedWords) { return false; } if (!$this->isCaseSensitive()) { $storedWords = strtolower($storedWords); $word = strtolower($word); } return in_array($word, explode(',', $storedWords)); } /** * Return full URL to captcha image * * @return string */ public function getImgSrc() { return $this->getImgUrl() . $this->getId() . $this->getSuffix(); } /** * Log attempt * * @param string $login * @return $this */ public function logAttempt($login) { if ($this->isEnabled() && in_array($this->formId, $this->getTargetForms())) { $this->getResourceModel()->logAttempt($login); if ($this->isOverLimitLoginAttempts($login)) { $this->setShowCaptchaInSession(true); } } return $this; } /** * Set show_captcha flag in session * * @param bool $value * @return void * @since 100.1.0 */ public function setShowCaptchaInSession($value = true) { if ($value !== true) { $value = false; } $this->session->setData($this->getFormIdKey('show_captcha'), $value); } /** * Generate word used for captcha render * * @return string * @throws \Magento\Framework\Exception\LocalizedException * @since 100.2.0 */ protected function generateWord() { $symbols = (string)$this->captchaData->getConfig('symbols'); $wordLen = $this->getWordLen(); return $this->randomMath->getRandomString($wordLen, $symbols); } /** * Returns length for generating captcha word. This value may be dynamic. * * @return int * @throws \Magento\Framework\Exception\LocalizedException * @since 100.2.0 */ public function getWordLen() { $from = 0; $to = 0; $length = (string)$this->captchaData->getConfig('length'); if (!is_numeric($length)) { if (preg_match('/(\d+)-(\d+)/', $length, $matches)) { $from = (int)$matches[1]; $to = (int)$matches[2]; } } else { $from = (int)$length; $to = (int)$length; } if ($to < $from || $from < 1 || $to < 1) { $from = self::DEFAULT_WORD_LENGTH_FROM; $to = self::DEFAULT_WORD_LENGTH_TO; } return Random::getRandomNumber($from, $to); } /** * Whether to show captcha for this form every time * * @return bool */ private function isShowAlways() { $captchaMode = (string)$this->captchaData->getConfig('mode'); if ($captchaMode === Data::MODE_ALWAYS) { return true; } if ($captchaMode === Data::MODE_AFTER_FAIL && $this->getAllowedAttemptsForSameLogin() === 0 ) { return true; } $alwaysFor = $this->captchaData->getConfig('always_for'); foreach ($alwaysFor as $nodeFormId => $isAlwaysFor) { if ($isAlwaysFor && $this->formId == $nodeFormId) { return true; } } return false; } /** * Whether captcha is enabled at this area * * @return bool */ private function isEnabled() { return (string)$this->captchaData->getConfig('enable'); } /** * Retrieve list of forms where captcha must be shown * * For frontend this list is based on current website * * @return array */ private function getTargetForms() { $formsString = (string)$this->captchaData->getConfig('forms'); return explode(',', $formsString); } /** * Get captcha word * * @return string|null */ public function getWord() { $sessionData = $this->session->getData($this->getFormIdKey(self::SESSION_WORD)); return time() < $sessionData['expires'] ? $sessionData['data'] : null; } /** * Get captcha words * * @return string */ private function getWords() { $sessionData = $this->session->getData($this->getFormIdKey(self::SESSION_WORD)); $words = ''; if (isset($sessionData['expires'], $sessionData['words']) && time() < $sessionData['expires']) { $words = $sessionData['words']; } return $words; } /** * Set captcha word * * @param string $word * @return $this * @since 100.2.0 */ protected function setWord($word) { $this->words = $this->words ? $this->words . ',' . $word : $word; $this->session->setData( $this->getFormIdKey(self::SESSION_WORD), ['data' => $word, 'words' => $this->words, 'expires' => time() + $this->getTimeout()] ); $this->word = $word; return $this; } /** * Set captcha word * * @return $this */ private function clearWord() { $this->session->unsetData($this->getFormIdKey(self::SESSION_WORD)); $this->word = null; return $this; } /** * Override function to generate less curly captcha that will not cut off * * @see \Laminas\Captcha\Image::_randomSize() * @return int * @throws \Magento\Framework\Exception\LocalizedException * @since 100.2.0 */ protected function randomSize() { return Random::getRandomNumber(280, 300) / 100; } /** * Overlap of the parent method * * @return void * * Now deleting old captcha images make crontab script * @see \Magento\Captcha\Cron\DeleteExpiredImages::execute * * Added SuppressWarnings since this method is declared in parent class and we can not use other method name. * @SuppressWarnings(PHPMD.ShortMethodName) * @since 100.2.0 */ protected function gc() { return; // required for static testing to pass } /** * Get resource model * * @return \Magento\Captcha\Model\ResourceModel\Log */ private function getResourceModel() { return $this->resLogFactory->create(); } }