forked from leftypol/leftypol
Add hcaptcha support (#166)
Co-authored-by: RealAngeleno <angeleno@screamer.wiki> Reviewed-on: https://git.leftypol.org/leftypol/leftypol/pulls/166 Co-authored-by: Zankaria <zankaria.auxa@skiff.com> Co-committed-by: Zankaria <zankaria.auxa@skiff.com>
This commit is contained in:
parent
25089f5cbb
commit
d8c5c600a8
5 changed files with 107 additions and 19 deletions
|
@ -302,6 +302,7 @@
|
||||||
'raw',
|
'raw',
|
||||||
'embed',
|
'embed',
|
||||||
'g-recaptcha-response',
|
'g-recaptcha-response',
|
||||||
|
'h-captcha-response',
|
||||||
'cf-turnstile-response',
|
'cf-turnstile-response',
|
||||||
'spoiler',
|
'spoiler',
|
||||||
'page',
|
'page',
|
||||||
|
@ -343,10 +344,17 @@
|
||||||
$config['recaptcha_public'] = '6LcXTcUSAAAAAKBxyFWIt2SO8jwx4W7wcSMRoN3f';
|
$config['recaptcha_public'] = '6LcXTcUSAAAAAKBxyFWIt2SO8jwx4W7wcSMRoN3f';
|
||||||
$config['recaptcha_private'] = '6LcXTcUSAAAAAOGVbVdhmEM1_SyRF4xTKe8jbzf_';
|
$config['recaptcha_private'] = '6LcXTcUSAAAAAOGVbVdhmEM1_SyRF4xTKe8jbzf_';
|
||||||
|
|
||||||
|
// Enable hCaptcha.
|
||||||
|
$config['hcaptcha'] = false;
|
||||||
|
|
||||||
|
// Public and private key pair for using hCaptcha.
|
||||||
|
$config['hcaptcha_public'] = '7a4b21e0-dc53-46f2-a9f8-91d2e74b63a0';
|
||||||
|
$config['hcaptcha_private'] = '0x4e9A01bE637b51dC41a7Ea9865C3fDe4aB72Cf17';
|
||||||
|
|
||||||
// Enable Cloudflare's Turnstile captcha.
|
// Enable Cloudflare's Turnstile captcha.
|
||||||
$config['turnstile'] = false;
|
$config['turnstile'] = false;
|
||||||
|
|
||||||
// Public and private key pair.
|
// Public and private key pair for turnstile.
|
||||||
$config['turnstile_public'] = '';
|
$config['turnstile_public'] = '';
|
||||||
$config['turnstile_private'] = '';
|
$config['turnstile_private'] = '';
|
||||||
|
|
||||||
|
|
52
post.php
52
post.php
|
@ -92,6 +92,44 @@ function check_recaptcha($secret, $response, $remote_ip)
|
||||||
return !!$resp['success'];
|
return !!$resp['success'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function check_hcaptcha($secret, $response, $remote_ip, $public_key)
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'secret' => $secret,
|
||||||
|
'response' => $response,
|
||||||
|
'sitekey' => $public_key,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($remote_ip !== null) {
|
||||||
|
$data['remoteip'] = $remote_ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = curl_init();
|
||||||
|
curl_setopt_array($c, [
|
||||||
|
CURLOPT_URL => 'https://api.hcaptcha.com/siteverify',
|
||||||
|
CURLOPT_CUSTOMREQUEST => "POST",
|
||||||
|
CURLOPT_POSTFIELDS => $data,
|
||||||
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
|
]);
|
||||||
|
$c_ret = curl_exec($c);
|
||||||
|
if ($c_ret === false) {
|
||||||
|
$err_no = curl_errno($c);
|
||||||
|
$err_str = curl_error($c);
|
||||||
|
|
||||||
|
curl_close($c);
|
||||||
|
error_log("hCaptcha call failed. Curl returned: $err_no ($err_str)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
curl_close($c);
|
||||||
|
|
||||||
|
$json_ret = json_decode($c_ret, true);
|
||||||
|
if ($json_ret === null) {
|
||||||
|
error_log("hCaptcha call failed. Malformed json: $c_ret");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $json_ret['success'] === true;
|
||||||
|
}
|
||||||
|
|
||||||
function check_turnstile($secret, $response, $remote_ip, $expected_action)
|
function check_turnstile($secret, $response, $remote_ip, $expected_action)
|
||||||
{
|
{
|
||||||
$data = [
|
$data = [
|
||||||
|
@ -736,6 +774,13 @@ function handle_post()
|
||||||
if (!check_recaptcha($config['recaptcha_private'], $_POST['g-recaptcha-response'], null)) {
|
if (!check_recaptcha($config['recaptcha_private'], $_POST['g-recaptcha-response'], null)) {
|
||||||
error($config['error']['captcha']);
|
error($config['error']['captcha']);
|
||||||
}
|
}
|
||||||
|
} elseif ($config['hcaptcha']) {
|
||||||
|
if (!isset($_POST['h-captcha-response'])) {
|
||||||
|
error($config['error']['bot']);
|
||||||
|
}
|
||||||
|
if (!check_hcaptcha($config['hcaptcha_private'], $_POST['h-captcha-response'], null, $config['hcaptcha_public'])) {
|
||||||
|
error($config['error']['captcha']);
|
||||||
|
}
|
||||||
} elseif ($config['turnstile']) {
|
} elseif ($config['turnstile']) {
|
||||||
if (!isset($_POST['cf-turnstile-response'])) {
|
if (!isset($_POST['cf-turnstile-response'])) {
|
||||||
error($config['error']['bot']);
|
error($config['error']['bot']);
|
||||||
|
@ -755,6 +800,13 @@ function handle_post()
|
||||||
if (!check_recaptcha($config['recaptcha_private'], $_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR'])) {
|
if (!check_recaptcha($config['recaptcha_private'], $_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR'])) {
|
||||||
error($config['error']['captcha']);
|
error($config['error']['captcha']);
|
||||||
}
|
}
|
||||||
|
} elseif ($config['hcaptcha']) {
|
||||||
|
if (!isset($_POST['h-captcha-response'])) {
|
||||||
|
error($config['error']['bot']);
|
||||||
|
}
|
||||||
|
if (!check_hcaptcha($config['hcaptcha_private'], $_POST['h-captcha-response'], $_SERVER['REMOTE_ADDR'], $config['hcaptcha_public'])) {
|
||||||
|
error($config['error']['captcha']);
|
||||||
|
}
|
||||||
} elseif ($config['turnstile']) {
|
} elseif ($config['turnstile']) {
|
||||||
if (!isset($_POST['cf-turnstile-response'])) {
|
if (!isset($_POST['cf-turnstile-response'])) {
|
||||||
error($config['error']['bot']);
|
error($config['error']['bot']);
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
{% if config.hcaptcha %}
|
||||||
|
<script src="https://js.hcaptcha.com/1/api.js?recaptchacompat=off&render=explicit&onload=onCaptchaLoadHcaptcha" async defer></script>
|
||||||
|
{% endif %}
|
||||||
{% if config.turnstile %}
|
{% if config.turnstile %}
|
||||||
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit&onload=onCaptchaLoadTurnstile_{{ form_action_type }}" async defer></script>
|
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit&onload=onCaptchaLoadTurnstile_{{ form_action_type }}" async defer></script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -245,11 +245,39 @@ function getCookie(cookie_name) {
|
||||||
{% endraw %}
|
{% endraw %}
|
||||||
|
|
||||||
/* BEGIN CAPTCHA REGION */
|
/* BEGIN CAPTCHA REGION */
|
||||||
|
{% if config.hcaptcha or config.turnstile %} // If any captcha
|
||||||
{% if config.turnstile %}
|
|
||||||
// Global captcha object. Assigned by `onCaptchaLoad()`.
|
// Global captcha object. Assigned by `onCaptchaLoad()`.
|
||||||
var captcha_renderer = null;
|
var captcha_renderer = null;
|
||||||
|
|
||||||
|
{% if config.hcaptcha %} // If hcaptcha
|
||||||
|
function onCaptchaLoadHcaptcha() {
|
||||||
|
if (captcha_renderer === null) {
|
||||||
|
let renderer = {
|
||||||
|
renderOn: (container) => hcaptcha.render(container, {
|
||||||
|
sitekey: "{{ config.hcaptcha_public }}",
|
||||||
|
}),
|
||||||
|
remove: (widgetId) => { /* Not supported */ },
|
||||||
|
reset: (widgetId) => hcaptcha.reset(widgetId)
|
||||||
|
};
|
||||||
|
|
||||||
|
onCaptchaLoad(renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initCaptchaImpl() {
|
||||||
|
/*
|
||||||
|
* hcaptcha is set but the captcha_renderer is null? hcaptcha loaded before main.js could set up the callbacks.
|
||||||
|
* Init now.
|
||||||
|
*/
|
||||||
|
if (hcaptcha && captcha_renderer === null) {
|
||||||
|
if (active_page === 'index' || active_page === 'catalog' || active_page === 'thread') {
|
||||||
|
onCaptchaLoadHcaptcha();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{% endif %} // End if hcaptcha
|
||||||
|
{% if config.turnstile %} // If turnstile
|
||||||
|
|
||||||
// Wrapper function to be called from thread.html
|
// Wrapper function to be called from thread.html
|
||||||
window.onCaptchaLoadTurnstile_post_reply = function() {
|
window.onCaptchaLoadTurnstile_post_reply = function() {
|
||||||
onCaptchaLoadTurnstile('post-reply');
|
onCaptchaLoadTurnstile('post-reply');
|
||||||
|
@ -265,7 +293,7 @@ function onCaptchaLoadTurnstile(action) {
|
||||||
if (captcha_renderer === null) {
|
if (captcha_renderer === null) {
|
||||||
let renderer = {
|
let renderer = {
|
||||||
renderOn: function(container) {
|
renderOn: function(container) {
|
||||||
let widgetId = turnstile.render(container, {
|
let widgetId = turnstile.render('#' + container, {
|
||||||
sitekey: "{{ config.turnstile_public }}",
|
sitekey: "{{ config.turnstile_public }}",
|
||||||
action: action,
|
action: action,
|
||||||
});
|
});
|
||||||
|
@ -274,12 +302,8 @@ function onCaptchaLoadTurnstile(action) {
|
||||||
}
|
}
|
||||||
return widgetId;
|
return widgetId;
|
||||||
},
|
},
|
||||||
remove: function(widgetId) {
|
remove: (widgetId) => turnstile.remove(widgetId),
|
||||||
turnstile.remove(widgetId);
|
reset: (widgetId) => turnstile.reset(widgetId)
|
||||||
},
|
|
||||||
reset: function(widgetId) {
|
|
||||||
turnstile.reset(widgetId);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onCaptchaLoad(renderer);
|
onCaptchaLoad(renderer);
|
||||||
|
@ -299,12 +323,12 @@ function initCaptchaImpl() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %} // End if turnstile
|
||||||
|
|
||||||
function onCaptchaLoad(renderer) {
|
function onCaptchaLoad(renderer) {
|
||||||
captcha_renderer = renderer;
|
captcha_renderer = renderer;
|
||||||
|
|
||||||
let widgetId = renderer.renderOn('#captcha-container');
|
let widgetId = renderer.renderOn('captcha-container');
|
||||||
if (widgetId === null) {
|
if (widgetId === null) {
|
||||||
console.error('Could not render captcha!');
|
console.error('Could not render captcha!');
|
||||||
}
|
}
|
||||||
|
@ -314,23 +338,24 @@ function onCaptchaLoad(renderer) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
{% if config.dynamic_captcha %}
|
{% if config.dynamic_captcha %} // If dynamic captcha
|
||||||
function isDynamicCaptchaEnabled() {
|
function isDynamicCaptchaEnabled() {
|
||||||
let cookie = getCookie('captcha-required');
|
let cookie = getCookie('captcha-required');
|
||||||
return cookie === '1';
|
return cookie === '1';
|
||||||
}
|
}
|
||||||
|
|
||||||
function initDynamicCaptcha() {
|
function initCaptcha() {
|
||||||
if (isDynamicCaptchaEnabled()) {
|
if (isDynamicCaptchaEnabled()) {
|
||||||
let captcha_hook = document.getElementById('captcha');
|
let captcha_hook = document.getElementById('captcha');
|
||||||
captcha_hook.style = "";
|
captcha_hook.style = "";
|
||||||
initCaptchaImpl();
|
initCaptchaImpl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{% else %}
|
{% endif %} // End if dynamic captcha
|
||||||
|
{% else %} // Else if any captcha
|
||||||
// No-op for `init()`.
|
// No-op for `init()`.
|
||||||
function initDynamicCaptcha() {}
|
function initCaptcha() {}
|
||||||
{% endif %}
|
{% endif %} // End if any captcha
|
||||||
|
|
||||||
/* END CAPTCHA REGION */
|
/* END CAPTCHA REGION */
|
||||||
|
|
||||||
|
@ -500,7 +525,7 @@ var script_settings = function(script_name) {
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
initStyleChooser();
|
initStyleChooser();
|
||||||
initDynamicCaptcha();
|
initCaptcha();
|
||||||
|
|
||||||
{% endraw %}
|
{% endraw %}
|
||||||
{% if config.allow_delete %}
|
{% if config.allow_delete %}
|
||||||
|
|
|
@ -106,7 +106,7 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if config.turnstile %}
|
{% if config.hcaptcha or config.turnstile %}
|
||||||
{% if config.dynamic_captcha %}
|
{% if config.dynamic_captcha %}
|
||||||
<tr id="captcha" style="display: none;">
|
<tr id="captcha" style="display: none;">
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue