Files
2025-08-02 16:30:27 +02:00

101 lines
4.0 KiB
PHP

<?php
namespace KupShop\ContentBundle\Util;
use KupShop\ContentBundle\View\Exception\ValidationException;
use KupShop\KupShopBundle\Context\DomainContext;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\RecaptchaBundle\Util\RecaptchaGCloudUtil;
use ReCaptcha\ReCaptcha;
use ReCaptcha\RequestMethod\Post;
class Captcha
{
/**
* @param null $data
* @param null $type One of null, 'shared', 'invisible', 'default'
*
* @throws ValidationException
*/
public static function checkCaptcha($data = null, $type = null)
{
if (isFunctionalTests()) {
return true;
}
if ($captcha = getVal('captcha', $data)) {
if ($captcha != generateCaptcha(getVal('captcha_id', $data))) {
throw new ValidationException(translate('errorCaptcha', 'form'));
}
} elseif ($captcha = getVal('g-recaptcha-response', $data)) {
if (findModule(\Modules::RECAPTCHA, \Modules::SUB_GCLOUD)) {
$util = ServiceContainer::getService(RecaptchaGCloudUtil::class);
if (!$util->validate(token: $captcha, type: $type ?: getVal('recaptcha', $data))) {
throw new ValidationException(translate('errorCaptcha', 'form'));
}
} else {
$key = self::getCaptchaType($type ?: getVal('recaptcha', $data));
$recaptcha = new ReCaptcha(findModule('recaptcha', $key));
$resp = $recaptcha->verify($captcha, $_SERVER['REMOTE_ADDR']);
if (!$resp->isSuccess()) {
throw new ValidationException(translate('errorCaptcha', 'form'));
}
if ($type == 'shared' && isProduction()) {
$domainContext = ServiceContainer::getService(DomainContext::class);
if (array_search($resp->getHostname(), $domainContext->getSupported()) === false) {
throw new ValidationException('Invalid CAPTCHA domain');
}
}
}
} elseif ($captcha = getVal('wpj-captcha-response', $data)) {
$requestMethod = new Post('https://challenges.cloudflare.com/turnstile/v0/siteverify');
$recaptcha = new ReCaptcha(findModule('recaptcha', 'secret_cloudflare'), $requestMethod);
$resp = $recaptcha->verify($captcha, $_SERVER['REMOTE_ADDR']);
if (!$resp->isSuccess()) {
throw new ValidationException(translate('errorCaptcha', 'form'));
}
if (isProduction()) {
$domains = Contexts::get(DomainContext::class)->getSupported();
if (!in_array($resp->getHostname(), $domains)) {
throw new ValidationException('Invalid CAPTCHA domain');
}
}
} elseif ($captcha = getVal('wpj-captcha-invisible-response', $data)) {
$requestMethod = new Post('https://challenges.cloudflare.com/turnstile/v0/siteverify');
$recaptcha = new ReCaptcha(findModule('recaptcha', 'secret_cloudflare_invisible'), $requestMethod);
$resp = $recaptcha->verify($captcha, $_SERVER['REMOTE_ADDR']);
if (!$resp->isSuccess()) {
throw new ValidationException(translate('errorCaptcha', 'form'));
}
if (isProduction()) {
$domains = Contexts::get(DomainContext::class)->getSupported();
if (!in_array($resp->getHostname(), $domains)) {
throw new ValidationException('Invalid CAPTCHA domain');
}
}
} else {
throw new ValidationException(translate('errorCaptcha', 'form'));
}
}
protected static function getCaptchaType($type)
{
switch ($type) {
case 'invisible':
return 'secret_invisible';
case 'shared':
return 'secret_shared';
default:
return 'secret';
}
}
}