Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
742 changes: 742 additions & 0 deletions PROVIDER.md

Large diffs are not rendered by default.

242 changes: 58 additions & 184 deletions eicaptcha.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
use Eicaptcha\Module\ConfigForm;
use Eicaptcha\Module\Debugger;
use Eicaptcha\Module\Installer;
use ReCaptcha\ReCaptcha;
use Eicaptcha\Module\Factory\CaptchaFactory;
use Eicaptcha\Module\Provider\CaptchaProviderInterface;

class EiCaptcha extends Module
{
Expand All @@ -48,12 +49,17 @@ class EiCaptcha extends Module
*/
protected $captchaLang = 'en';

/**
* @var CaptchaProviderInterface
*/
protected $captchaProvider;

public function __construct()
{
$this->author = 'hhennes';
$this->name = 'eicaptcha';
$this->tab = 'front_office_features';
$this->version = '2.6.0';
$this->version = '3.0.0';
$this->need_instance = 1;

$this->bootstrap = true;
Expand Down Expand Up @@ -141,6 +147,28 @@ public function getContext()
return $this->context;
}

/**
* Get the current captcha provider
*
* @return CaptchaProviderInterface
*
* @since 3.0.0
*/
public function getCaptchaProvider()
{
if (null === $this->captchaProvider) {
try {
$this->captchaProvider = CaptchaFactory::create($this);
} catch (\Exception $e) {
$this->debugger->log('Error loading captcha provider: ' . $e->getMessage());
// Fallback to google_recaptcha
$this->captchaProvider = CaptchaFactory::create($this, 'google_recaptcha');
}
}

return $this->captchaProvider;
}

/**
* Module Configuration in Back Office
*
Expand All @@ -165,108 +193,15 @@ public function getContent()
*/
public function hookHeader(array $params)
{
if (!$this->shouldDisplayToCustomer()) {
return;
}

$captchaVersion = Configuration::get('CAPTCHA_VERSION');
//Add Content box to contact form page in order to display captcha
if ($this->context->controller instanceof ContactController
&& Configuration::get('CAPTCHA_ENABLE_CONTACT') == 1
) {
$this->context->controller->registerJavascript(
'modules-eicaptcha-contact-form',
'modules/' . $this->name . '/views/js/eicaptcha-contact-form-v' . $captchaVersion . '.js'
);
}
$provider = $this->getCaptchaProvider();

if ($captchaVersion == 2) {
return $this->renderHeaderV2();
} else {
return $this->renderHeaderV3();
if (!$provider->shouldDisplayToCustomer()) {
return;
}
}

/**
* Return content for (re)captcha v2
*
* @return string|void
*/
protected function renderHeaderV2()
{
if ((
(
$this->context->controller instanceof AuthController
|| $this->context->controller instanceof RegistrationController
)
&& Configuration::get('CAPTCHA_ENABLE_ACCOUNT') == 1
)
||
($this->context->controller instanceof ContactController
&& Configuration::get('CAPTCHA_ENABLE_CONTACT') == 1
)
|| Configuration::get('CAPTCHA_LOAD_EVERYWHERE') == 1
) {
$this->context->controller->registerStylesheet(
'module-eicaptcha',
'modules/' . $this->name . '/views/css/eicaptcha.css'
);
//Dynamic insertion of the content
$js = '<script type="text/javascript">
//Recaptcha CallBack Function
var onloadCallback = function() {
//Fix captcha box issue in ps 1.7.7
if ( ! document.getElementById("captcha-box")){
var container = document.createElement("div");
container.setAttribute("id","captcha-box");
if ( null !== document.querySelector(".form-fields") ){
document.querySelector(".form-fields").appendChild(container);
}
}
if ( document.getElementById("captcha-box")){
grecaptcha.render("captcha-box", {"theme" : "' . $this->themes[Configuration::get('CAPTCHA_THEME')] . '", "sitekey" : "' . Configuration::get('CAPTCHA_PUBLIC_KEY') . '"});
} else {
console.warn("eicaptcha: unable to add captcha-box placeholder to display captcha ( not an error when form is submited sucessfully )");
}
};
</script>';

if (($this->context->controller instanceof ContactController && Configuration::get('CAPTCHA_ENABLE_CONTACT') == 1)) {
$js .= '<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit&hl=' . $this->captchaLang . '" async defer></script>';
}

return $js;
}
return $provider->renderHeader(['controller' => $this->context->controller]);
}

/**
* Return content for recaptcha v3
*
* @return string|void
*/
public function renderHeaderV3()
{
if (
($this->context->controller instanceof ContactController
&& Configuration::get('CAPTCHA_ENABLE_CONTACT') == 1
)
|| Configuration::get('CAPTCHA_LOAD_EVERYWHERE') == 1
) {
$publicKey = Configuration::get('CAPTCHA_PUBLIC_KEY');
$js = '
<script src="https://www.google.com/recaptcha/api.js?render=' . $publicKey . '"></script>
<script>
grecaptcha.ready(function () {
grecaptcha.execute("' . $publicKey . '", {action: "contact"}).then(function (token) {
var recaptchaResponse = document.getElementById("captcha-box");
recaptchaResponse.value = token;
});
});
</script>';

return $js;
}
}

/**
* Add Captcha on the Customer Registration Form
Expand All @@ -280,12 +215,8 @@ public function hookDisplayCustomerAccountForm(array $params)
if ($this->context->controller->php_self != 'identity'
&& Configuration::get('CAPTCHA_ENABLE_ACCOUNT') == 1
) {
$this->context->smarty->assign([
'captchaVersion' => Configuration::get('CAPTCHA_VERSION'),
'publicKey' => Configuration::get('CAPTCHA_PUBLIC_KEY'),
'captchalang' => $this->captchaLang,
'captchatheme' => $this->themes[Configuration::get('CAPTCHA_THEME')],
]);
$provider = $this->getCaptchaProvider();
$this->context->smarty->assign($provider->getTemplateVars());

return $this->display(__FILE__, 'views/templates/hook/hookDisplayCustomerAccountForm.tpl');
}
Expand Down Expand Up @@ -398,17 +329,14 @@ public function hookActionAdminControllerSetMedia(array $params)
*/
public function hookDisplayNewsletterRegistration(array $params)
{
$provider = $this->getCaptchaProvider();

if (
Configuration::get('CAPTCHA_ENABLE_NEWSLETTER') == 1
&& $this->canUseCaptchaOnNewsletter()
&& $this->shouldDisplayToCustomer()
&& $provider->shouldDisplayToCustomer()
) {
$this->context->smarty->assign([
'captchaVersion' => Configuration::get('CAPTCHA_VERSION'),
'publicKey' => Configuration::get('CAPTCHA_PUBLIC_KEY'),
'captchalang' => $this->captchaLang,
'captchatheme' => $this->themes[Configuration::get('CAPTCHA_THEME')],
]);
$this->context->smarty->assign($provider->getTemplateVars());

return $this->display(__FILE__, 'views/templates/hook/hookDisplayNewsletterRegistration.tpl');
}
Expand All @@ -425,9 +353,11 @@ public function hookDisplayNewsletterRegistration(array $params)
*/
public function hookActionNewsletterRegistrationBefore(array $params)
{
$provider = $this->getCaptchaProvider();

if (Configuration::get('CAPTCHA_ENABLE_NEWSLETTER') == 1
&& $this->canUseCaptchaOnNewsletter()
&& $this->shouldDisplayToCustomer()
&& $provider->shouldDisplayToCustomer()
) {
if (!$this->_validateCaptcha()) {
$params['hookError'] = $this->l('Please validate the captcha field before submitting your request');
Expand All @@ -442,51 +372,22 @@ public function hookActionNewsletterRegistrationBefore(array $params)
*/
protected function _validateCaptcha()
{
if (!$this->shouldDisplayToCustomer()) {
$provider = $this->getCaptchaProvider();

if (!$provider->shouldDisplayToCustomer()) {
return true;
}

$context = Context::getContext();
$captchaVersion = Configuration::get('CAPTCHA_VERSION');
$captchaV3MinScore = (float) Configuration::get('CAPTCHA_V3_MINIMAL_SCORE');
//Fix issue if allow_url_open is set to 0
if (function_exists('ini_get') && !ini_get('allow_url_fopen')) {
$recaptchaMethod = new \ReCaptcha\RequestMethod\CurlPost();
} else {
$recaptchaMethod = null;
}
$captcha = new ReCaptcha(Configuration::get('CAPTCHA_PRIVATE_KEY'), $recaptchaMethod);
if ($captchaVersion == 3) {
$captcha->setScoreThreshold($captchaV3MinScore);
}
$result = $captcha->verify(
Tools::getValue('g-recaptcha-response'),
Tools::getRemoteAddr()
);

if (!$result->isSuccess()) {
$errorMessage = $this->l('Please validate the captcha field before submitting your request');
$this->debugger->log($errorMessage);
$this->debugger->log(sprintf($this->l('Recaptcha response %s'), print_r($result->getErrorCodes(), true)));
if ($captchaVersion == 3) {
if ($result->getScore() < $captchaV3MinScore) {
$errorMessageV3 =
sprintf(
'Your request has been blocked by the captcha system, due to a low score of %s, required score is %s',
$result->getScore(),
$captchaV3MinScore
);
$this->debugger->log($errorMessageV3);
}
}
$context->controller->errors[] = $errorMessage;
$response = Tools::getValue($provider->getResponseFieldName());
$remoteIp = Tools::getRemoteAddr();

return false;
}
$isValid = $provider->validate($response, $remoteIp);

$this->debugger->log($this->l('Captcha submited with success'));
if (!$isValid) {
$this->context->controller->errors[] = $provider->getLastError();
}

return true;
return $isValid;
}

/**
Expand All @@ -500,13 +401,9 @@ protected function _validateCaptcha()
*/
public function hookActionGetEicaptchaParams(array $params)
{
return [
'displayCaptcha' => $this->shouldDisplayToCustomer(),
'captchaVersion' => Configuration::get('CAPTCHA_VERSION'),
'publicKey' => Configuration::get('CAPTCHA_PUBLIC_KEY'),
'captchaforcelang' => Configuration::get('CAPTCHA_FORCE_LANG'),
'captchatheme' => $this->themes[Configuration::get('CAPTCHA_THEME')],
];
$provider = $this->getCaptchaProvider();

return $provider->getTemplateVars();
}

/**
Expand All @@ -518,13 +415,8 @@ public function hookActionGetEicaptchaParams(array $params)
*/
public function hookDisplayEicaptchaVerification(array $params)
{
$this->context->smarty->assign([
'displayCaptcha' => $this->shouldDisplayToCustomer(),
'captchaVersion' => Configuration::get('CAPTCHA_VERSION'),
'publicKey' => Configuration::get('CAPTCHA_PUBLIC_KEY'),
'captchalang' => $this->captchaLang,
'captchatheme' => $this->themes[Configuration::get('CAPTCHA_THEME')],
]);
$provider = $this->getCaptchaProvider();
$this->context->smarty->assign($provider->getTemplateVars());

return $this->display(__FILE__, 'views/templates/hook/hookDisplayEicaptchaVerification.tpl');
}
Expand Down Expand Up @@ -558,22 +450,4 @@ public function canUseCaptchaOnNewsletter()

return false;
}

/**
* Define if the captcha should be displayed to the customer
*
* @return bool
*/
protected function shouldDisplayToCustomer()
{
if (
Configuration::get('CAPTCHA_ENABLE_LOGGED_CUSTOMERS') == 0
&& $this->context->customer->id > 0
&& $this->context->customer->email != null
) {
return false;
}

return true;
}
}
Loading
Loading