Add dynamic captcha support

This commit is contained in:
Zankaria 2024-05-25 00:32:44 +02:00
parent 81f5c70681
commit 483d553fc0
4 changed files with 60 additions and 7 deletions

View file

@ -328,6 +328,9 @@
'answer' => '4' 'answer' => '4'
); );
*/ */
// The captcha is dynamically injected on the client if the server replies with the `captcha-required` cookie set to 1.
$config['dynamic_captcha'] = false;
// Enable reCaptcha to make spam even harder. Rarely necessary. // Enable reCaptcha to make spam even harder. Rarely necessary.
$config['recaptcha'] = false; $config['recaptcha'] = false;

View file

@ -74,14 +74,21 @@ function strip_markup($post_body)
*/ */
function check_recaptcha($secret, $response, $remote_ip) function check_recaptcha($secret, $response, $remote_ip)
{ {
$resp = json_decode(file_get_contents( if ($remote_ip !== null) {
sprintf( $req = sprintf(
'https://www.google.com/recaptcha/api/siteverify?secret=%s&response=%s&remoteip=%s', 'https://www.google.com/recaptcha/api/siteverify?secret=%s&response=%s&remoteip=%s',
$secret, $secret,
urlencode($response), urlencode($response),
$remote_ip $remote_ip
) );
), true); } else {
$req = sprintf(
'https://www.google.com/recaptcha/api/siteverify?secret=%s&response=%s&remoteip=%s',
$secret,
urlencode($response),
);
}
$resp = json_decode(file_get_contents($req), true);
return !!$resp['success']; return !!$resp['success'];
} }
@ -683,8 +690,17 @@ function handle_post()
if (!$dropped_post) { if (!$dropped_post) {
if ($config['dynamic_captcha'] && $_SERVER['REMOTE_ADDR'] === '127.0.0.1' && $config['recaptcha']) {
if (!isset($_POST['g-recaptcha-response'])) {
error($config['error']['bot']);
}
if (!check_recaptcha($config['recaptcha_private'], $_POST['g-recaptcha-response'], null)) {
error($config['error']['captcha']);
}
}
// Check for CAPTCHA right after opening the board so the "return" link is in there. // Check for CAPTCHA right after opening the board so the "return" link is in there.
if ($config['recaptcha']) { if (!$config['dynamic_captcha'] && $config['recaptcha']) {
if (!isset($_POST['g-recaptcha-response'])) { if (!isset($_POST['g-recaptcha-response'])) {
error($config['error']['bot']); error($config['error']['bot']);
} }

View file

@ -238,6 +238,36 @@ function get_cookie(cookie_name) {
return null; return null;
} }
{% endraw %}
{% if config.dynamic_captcha %}
function is_dynamic_captcha_enabled() {
let cookie = get_cookie('require-captcha');
return cookie === '1';
}
function get_captcha_pub_key() {
{% if config.recaptcha %}
return "{{ config.recaptcha_public }}";
{% else %}
return null;
{% endif %}
}
function init_dynamic_captcha() {
if (!is_dynamic_captcha_enabled()) {
let pub_key = get_captcha_pub_key();
if (!pub_key) {
console.error("Missing public captcha key!");
return;
}
let captcha_hook = document.getElementById('captcha');
captcha_hook.style = "";
}
}
{% endif %}
{% raw %}
function highlightReply(id) { function highlightReply(id) {
if (typeof window.event != "undefined" && event.which == 2) { if (typeof window.event != "undefined" && event.which == 2) {
// don't highlight on middle click // don't highlight on middle click

View file

@ -91,7 +91,11 @@
</td> </td>
</tr>{% endif %} </tr>{% endif %}
{% if config.recaptcha %} {% if config.recaptcha %}
{% if config.dynamic_captcha %}
<tr id="captcha" style="display: none;">
{% else %}
<tr> <tr>
{% endif %}
<th> <th>
{% trans %}Verification{% endtrans %} {% trans %}Verification{% endtrans %}
{{ antibot.html() }} {{ antibot.html() }}
@ -197,7 +201,7 @@
{{ antibot.html() }} {{ antibot.html() }}
</th> </th>
<td> <td>
<input type="text" name="password" value="" size="12" maxlength="18" autocomplete="off"> <input type="text" name="password" value="" size="12" maxlength="18" autocomplete="off">
<span class="unimportant">{% trans %}(For file deletion.){% endtrans %}</span> <span class="unimportant">{% trans %}(For file deletion.){% endtrans %}</span>
{{ antibot.html() }} {{ antibot.html() }}
</td> </td>
@ -208,7 +212,7 @@
{{ antibot.html() }} {{ antibot.html() }}
</th> </th>
<td> <td>
<input type="text" name="simple_spam" value="" size="12" maxlength="18" autocomplete="off"> <input type="text" name="simple_spam" value="" size="12" maxlength="18" autocomplete="off">
{{ antibot.html() }} {{ antibot.html() }}
</td> </td>
</tr>{% endif %} </tr>{% endif %}