From 1212c1861616e68f3e683a75d9ff58b96b1d1d85 Mon Sep 17 00:00:00 2001
From: fowr <89118232+perdedora@users.noreply.github.com>
Date: Thu, 9 Jan 2025 14:50:11 -0300
Subject: [PATCH 1/7] remove extra from being manipulated from query string;
use extra in rand_string;
---
inc/Service/SecureimageCaptchaQuery.php | 6 +-----
inc/context.php | 3 +--
js/captcha.js | 22 +++++++++++-----------
securimage.php | 18 +++++++-----------
4 files changed, 20 insertions(+), 29 deletions(-)
diff --git a/inc/Service/SecureimageCaptchaQuery.php b/inc/Service/SecureimageCaptchaQuery.php
index f5023899..90dcdbb6 100644
--- a/inc/Service/SecureimageCaptchaQuery.php
+++ b/inc/Service/SecureimageCaptchaQuery.php
@@ -10,19 +10,16 @@ class SecureImageCaptchaQuery {
private HttpDriver $http;
private string $domain;
private string $provider_check;
- private string $extra;
/**
* @param HttpDriver $http The http client.
* @param string $domain The server's domain.
* @param string $provider_check Path to the endpoint.
- * @param string $extra Extra http parameters.
*/
- function __construct(HttpDriver $http, string $domain, string $provider_check, string $extra) {
+ function __construct(HttpDriver $http, string $domain, string $provider_check) {
$this->http = $http;
$this->domain = $domain;
$this->provider_check = $provider_check;
- $this->extra = $extra;
}
/**
@@ -37,7 +34,6 @@ class SecureImageCaptchaQuery {
$data = [
'mode' => 'check',
'text' => $user_text,
- 'extra' => $this->extra,
'cookie' => $user_cookie
];
diff --git a/inc/context.php b/inc/context.php
index d1f74551..63557227 100644
--- a/inc/context.php
+++ b/inc/context.php
@@ -86,8 +86,7 @@ function build_context(array $config): Context {
return new SecureImageCaptchaQuery(
$c->get(HttpDriver::class),
$config['domain'],
- $config['captcha']['native']['provider_check'],
- $config['captcha']['native']['extra']
+ $config['captcha']['native']['provider_check']
);
},
CacheDriver::class => function($c) {
diff --git a/js/captcha.js b/js/captcha.js
index 5e0bcf53..b0589d24 100644
--- a/js/captcha.js
+++ b/js/captcha.js
@@ -1,27 +1,27 @@
var tout;
-function redo_events(provider, extra) {
- $('.captcha .captcha_text, textarea[id="body"]').off("focus").one("focus", function() { actually_load_captcha(provider, extra); });
+function redo_events(provider) {
+ $('.captcha .captcha_text, textarea[id="body"]').off("focus").one("focus", function() { actually_load_captcha(provider); });
}
-function actually_load_captcha(provider, extra) {
+function actually_load_captcha(provider) {
$('.captcha .captcha_text, textarea[id="body"]').off("focus");
if (tout !== undefined) {
clearTimeout(tout);
}
- $.getJSON(provider, {mode: 'get', extra: extra}, function(json) {
+ $.getJSON(provider, {mode: 'get'}, function(json) {
$(".captcha .captcha_cookie").val(json.cookie);
$(".captcha .captcha_html").html(json.captchahtml);
setTimeout(function() {
- redo_events(provider, extra);
+ redo_events(provider);
}, json.expires_in * 1000);
});
}
-function load_captcha(provider, extra) {
+function load_captcha(provider) {
$(function() {
$(".captcha>td").html(" "+
" "+
@@ -29,15 +29,15 @@ function load_captcha(provider, extra) {
$("#quick-reply .captcha .captcha_text").prop("placeholder", _("Verification"));
- $(".captcha .captcha_html").on("click", function() { actually_load_captcha(provider, extra); });
- $(document).on("ajax_after_post", function() { actually_load_captcha(provider, extra); });
- redo_events(provider, extra);
+ $(".captcha .captcha_html").on("click", function() { actually_load_captcha(provider); });
+ $(document).on("ajax_after_post", function() { actually_load_captcha(provider); });
+ redo_events(provider);
$(window).on("quick-reply", function() {
- redo_events(provider, extra);
+ redo_events(provider);
$("#quick-reply .captcha .captcha_html").html($("form:not(#quick-reply) .captcha .captcha_html").html());
$("#quick-reply .captcha .captcha_cookie").val($("form:not(#quick-reply) .captcha .captcha_cookie").html());
- $("#quick-reply .captcha .captcha_html").on("click", function() { actually_load_captcha(provider, extra); });
+ $("#quick-reply .captcha .captcha_html").on("click", function() { actually_load_captcha(provider); });
});
});
}
diff --git a/securimage.php b/securimage.php
index 324ffe44..2d06066e 100644
--- a/securimage.php
+++ b/securimage.php
@@ -19,13 +19,9 @@ function cleanup() {
$mode = @$_GET['mode'];
switch ($mode) {
case 'get':
- if (!isset ($_GET['extra'])) {
- $_GET['extra'] = $config['captcha']['extra'];
- }
-
header("Content-type: application/json");
- $extra = $_GET['extra'];
- $cookie = rand_string(20, "abcdefghijklmnopqrstuvwxyz");
+ $extra = $config['captcha']['native']['extra'];
+ $cookie = rand_string(20, $extra);
$i = new Securimage(['send_headers' => false, 'no_exit' => true]);
$i->createCode();
ob_start();
@@ -47,12 +43,12 @@ switch ($mode) {
break;
case 'check':
cleanup();
- if (!isset ($_GET['mode']) || !isset ($_GET['cookie']) || !isset ($_GET['extra']) || !isset ($_GET['text'])) {
+ if (!isset ($_GET['mode']) || !isset ($_GET['cookie']) || !isset ($_GET['text'])) {
die();
}
- $query = prepare("SELECT * FROM `captchas` WHERE `cookie` = ? AND `extra` = ?");
- $query->execute([$_GET['cookie'], $_GET['extra']]);
+ $query = prepare("SELECT * FROM `captchas` WHERE `cookie` = ?");
+ $query->execute([$_GET['cookie']]);
$ary = $query->fetchAll();
@@ -60,8 +56,8 @@ switch ($mode) {
echo "0";
break;
} else {
- $query = prepare("DELETE FROM `captchas` WHERE `cookie` = ? AND `extra` = ?");
- $query->execute([$_GET['cookie'], $_GET['extra']]);
+ $query = prepare("DELETE FROM `captchas` WHERE `cookie` = ?");
+ $query->execute([$_GET['cookie']]);
}
if ($ary[0]['text'] !== $_GET['text']) {
From 8ccf506e0ffc66594e1b92753e13d73f0675ccee Mon Sep 17 00:00:00 2001
From: fowr <89118232+perdedora@users.noreply.github.com>
Date: Thu, 9 Jan 2025 14:51:37 -0300
Subject: [PATCH 2/7] fix captcha being triggered when only new_thread_capt is
enabled
---
post.php | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/post.php b/post.php
index 2dcfe294..bb15781f 100644
--- a/post.php
+++ b/post.php
@@ -632,22 +632,22 @@ if (isset($_POST['delete'])) {
$dynamic = $config['captcha']['dynamic'];
// With our custom captcha provider
- if (($provider === 'native' && !$new_thread_capt)
- || ($provider === 'native' && $new_thread_capt && $post['op'])) {
- $query = $context->get(SecureImageCaptchaQuery::class);
- $success = $query->verify($_POST['captcha_text'], $_POST['captcha_cookie']);
+ if ($provider === 'native') {
+ if ((!$new_thread_capt && !$post['op']) || ($new_thread_capt && $post['op'])) {
+ $query = $context->get(SecureImageCaptchaQuery::class);
+ $success = $query->verify($_POST['captcha_text'], $_POST['captcha_cookie']);
- if (!$success) {
- error(
- "{$config['error']['captcha']}
- "
- );
+ if (!$success) {
+ error(
+ "{$config['error']['captcha']}
+ "
+ );
+ }
}
}
// Remote 3rd party captchas.
From 50339812b6c49bec329e35bf31c78e004a9c7629 Mon Sep 17 00:00:00 2001
From: fowr <89118232+perdedora@users.noreply.github.com>
Date: Thu, 9 Jan 2025 14:52:10 -0300
Subject: [PATCH 3/7] simplify template config for new_thread_capt and all
captcha
---
templates/post_form.html | 48 ++++++++++++++--------------------------
1 file changed, 16 insertions(+), 32 deletions(-)
diff --git a/templates/post_form.html b/templates/post_form.html
index b0377e03..1095b4ae 100644
--- a/templates/post_form.html
+++ b/templates/post_form.html
@@ -100,38 +100,22 @@
{% endif %}
- {% if config.captcha.provider == 'native' %}
-
-
- {% trans %}Verification{% endtrans %}
-
-
-
-
-
-
-
-
-
-
-
- {% elseif config.captcha.native.new_thread_capt %}
- {% if not id %}
-
-
- {% trans %}Verification{% endtrans %}
-
-
-
-
-
-
-
-
-
-
-
- {% endif %}
+ {% if (config.captcha.provider == 'native' and not config.captcha.native.new_thread_capt) or
+ (config.captcha.provider == 'native' and config.captcha.native.new_thread_capt and not id) %}
+
+
+ {% trans %}Verification{% endtrans %}
+
+
+
+
+
+
+
+
+
+
+
{% endif %}
{% if config.user_flag %}
From 0deae76002da0c6a23c8ca7987c4b19591d46379 Mon Sep 17 00:00:00 2001
From: fowr <89118232+perdedora@users.noreply.github.com>
Date: Thu, 9 Jan 2025 14:57:31 -0300
Subject: [PATCH 4/7] allow customization of securimage by captcha config
variable
---
inc/config.php | 5 ++++-
securimage.php | 2 +-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/inc/config.php b/inc/config.php
index f177f9e1..32766045 100644
--- a/inc/config.php
+++ b/inc/config.php
@@ -390,7 +390,10 @@
// Custom captcha extra field (eg. charset)
'extra' => 'abcdefghijklmnopqrstuvwxyz',
// New thread captcha. Require solving a captcha to post a thread.
- 'new_thread_capt' => false
+ 'new_thread_capt' => false,
+ // Securimage customization options
+ // https://github.com/dapphp/securimage/blob/nextgen/examples/securimage_show_example.php#L49
+ 'securimage_options' => ['send_headers' => false, 'no_exit' => true]
]
];
diff --git a/securimage.php b/securimage.php
index 2d06066e..f5e5a81c 100644
--- a/securimage.php
+++ b/securimage.php
@@ -22,7 +22,7 @@ switch ($mode) {
header("Content-type: application/json");
$extra = $config['captcha']['native']['extra'];
$cookie = rand_string(20, $extra);
- $i = new Securimage(['send_headers' => false, 'no_exit' => true]);
+ $i = new Securimage($config['captcha']['native']['securimage_options']);
$i->createCode();
ob_start();
$i->show();
From c6ade44962c21d4ec39c54393aa43305e339db35 Mon Sep 17 00:00:00 2001
From: fowr <89118232+perdedora@users.noreply.github.com>
Date: Thu, 9 Jan 2025 14:58:34 -0300
Subject: [PATCH 5/7] update config default to securimage
---
inc/config.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/inc/config.php b/inc/config.php
index 32766045..feecaca9 100644
--- a/inc/config.php
+++ b/inc/config.php
@@ -384,9 +384,9 @@
// To enable the native captcha you need to change a couple of settings. Read more at: /inc/captcha/readme.md
'native' => [
// Custom captcha get provider path (if not working get the absolute path aka your url).
- 'provider_get' => '../inc/captcha/entrypoint.php',
+ 'provider_get' => 'securimage.php',
// Custom captcha check provider path
- 'provider_check' => '../inc/captcha/entrypoint.php',
+ 'provider_check' => 'securimage.php',
// Custom captcha extra field (eg. charset)
'extra' => 'abcdefghijklmnopqrstuvwxyz',
// New thread captcha. Require solving a captcha to post a thread.
From 071de337eb592d2e4bbdcd8bff0e45e73a3766bc Mon Sep 17 00:00:00 2001
From: fowr <89118232+perdedora@users.noreply.github.com>
Date: Thu, 9 Jan 2025 15:13:50 -0300
Subject: [PATCH 6/7] trying to make securimage less messy
---
inc/Service/SecureimageCaptchaQuery.php | 4 +-
inc/config.php | 4 +-
securimage.php | 123 ++++++++++++++----------
3 files changed, 77 insertions(+), 54 deletions(-)
diff --git a/inc/Service/SecureimageCaptchaQuery.php b/inc/Service/SecureimageCaptchaQuery.php
index 90dcdbb6..0b33c059 100644
--- a/inc/Service/SecureimageCaptchaQuery.php
+++ b/inc/Service/SecureimageCaptchaQuery.php
@@ -38,6 +38,8 @@ class SecureImageCaptchaQuery {
];
$ret = $this->http->requestGet($this->domain . '/' . $this->provider_check, $data);
- return $ret === '1';
+ $resp = \json_decode($ret, true, 16, \JSON_THROW_ON_ERROR);
+
+ return isset($resp['success']) && $resp['success'];
}
}
diff --git a/inc/config.php b/inc/config.php
index feecaca9..5f9b7130 100644
--- a/inc/config.php
+++ b/inc/config.php
@@ -393,7 +393,9 @@
'new_thread_capt' => false,
// Securimage customization options
// https://github.com/dapphp/securimage/blob/nextgen/examples/securimage_show_example.php#L49
- 'securimage_options' => ['send_headers' => false, 'no_exit' => true]
+ 'securimage_options' => ['send_headers' => false, 'no_exit' => true],
+ // Captcha expires (in seconds)
+ 'expires_in' => 320
]
];
diff --git a/securimage.php b/securimage.php
index f5e5a81c..8ebfa154 100644
--- a/securimage.php
+++ b/securimage.php
@@ -1,69 +1,88 @@
execute([time() - $expires_in]);
}
+function handleGetRequestCaptcha(array $config): void {
+ $extra = $config['captcha']['native']['extra'];
+ $cookie = rand_string(20, $extra);
-$mode = @$_GET['mode'];
-switch ($mode) {
+ $securimage = new Securimage($config['captcha']['native']['securimage_options']);
+ $securimage->createCode();
+
+ ob_start();
+ $securimage->show();
+ $rawImage = ob_get_clean();
+
+ $base64Image = 'data:image/png;base64,' . base64_encode($rawImage);
+ $html = ' ';
+ $captchaCode = $securimage->getCode();
+
+ prepare("INSERT INTO `captchas` (`cookie`, `extra`, `text`, `created_at`) VALUES (?, ?, ?, ?)")
+ ->execute([$cookie, $extra, $captchaCode->code_display, $captchaCode->creationTime]);
+
+ if (isset($_GET['raw'])) {
+ $_SESSION['captcha_cookie'] = $cookie;
+ header('Content-Type: image/png');
+ echo $rawImage;
+ } else {
+ header("Content-Type: application/json");
+ echo json_encode([
+ "cookie" => $cookie,
+ "captchahtml" => $html,
+ "expires_in" => $config['captcha']['native']['expires_in'],
+ ]);
+ }
+}
+
+function handleCheckRequestCaptcha(int $expires_in): void {
+ cleanup($expires_in);
+
+ $cookie = $_GET['cookie'] ?? null;
+ $text = $_GET['text'] ?? null;
+
+ if (!$cookie || !$text) {
+ echo json_encode(["success" => false]);
+ return;
+ }
+
+ $query = prepare("SELECT * FROM `captchas` WHERE `cookie` = ?");
+ $query->execute([$cookie]);
+ $captchaData = $query->fetchAll();
+
+ if (!$captchaData) {
+ echo json_encode(["success" => false]);
+ return;
+ }
+
+ prepare("DELETE FROM `captchas` WHERE `cookie` = ?")->execute([$cookie]);
+
+ $isSuccessful = $captchaData[0]['text'] === $text;
+ echo json_encode(["success" => $isSuccessful]);
+}
+
+$mode = $_GET['mode'] ?? null;
+
+switch($mode) {
case 'get':
- header("Content-type: application/json");
- $extra = $config['captcha']['native']['extra'];
- $cookie = rand_string(20, $extra);
- $i = new Securimage($config['captcha']['native']['securimage_options']);
- $i->createCode();
- ob_start();
- $i->show();
- $rawimg = ob_get_contents();
- $b64img = 'data:image/png;base64,'.base64_encode($rawimg);
- $html = ' ';
- ob_end_clean();
- $cdata = $i->getCode();
- $query = prepare("INSERT INTO `captchas` (`cookie`, `extra`, `text`, `created_at`) VALUES (?, ?, ?, ?)");
- $query->execute([$cookie, $extra, $cdata->code_display, $cdata->creationTime]);
- if (isset($_GET['raw'])) {
- $_SESSION['captcha_cookie'] = $cookie;
- header('Content-Type: image/png');
- echo $rawimg;
- } else {
- echo json_encode(["cookie" => $cookie, "captchahtml" => $html, "expires_in" => $expires_in]);
- }
+ handleGetRequestCaptcha($config);
break;
case 'check':
- cleanup();
- if (!isset ($_GET['mode']) || !isset ($_GET['cookie']) || !isset ($_GET['text'])) {
- die();
- }
-
- $query = prepare("SELECT * FROM `captchas` WHERE `cookie` = ?");
- $query->execute([$_GET['cookie']]);
-
- $ary = $query->fetchAll();
-
- if (!$ary) { // captcha expired
- echo "0";
- break;
- } else {
- $query = prepare("DELETE FROM `captchas` WHERE `cookie` = ?");
- $query->execute([$_GET['cookie']]);
- }
-
- if ($ary[0]['text'] !== $_GET['text']) {
- echo "0";
- } else {
- echo "1";
- }
+ handleCheckRequestCaptcha($config['captcha']['native']['expires_in']);
break;
-}
+ case '':
+ default:
+ http_response_code(400);
+ echo json_encode(["success" => false, "error" => "Invalid mode"]);
+ break;
+}
\ No newline at end of file
From 8caf0f738b7d0983158dad073b35fc4f4278257b Mon Sep 17 00:00:00 2001
From: fowr <89118232+perdedora@users.noreply.github.com>
Date: Thu, 9 Jan 2025 15:57:07 -0300
Subject: [PATCH 7/7] update report captcha
---
post.php | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/post.php b/post.php
index bb15781f..17ee95c5 100644
--- a/post.php
+++ b/post.php
@@ -517,12 +517,7 @@ if (isset($_POST['delete'])) {
}
try {
- $query = new SecureImageCaptchaQuery(
- $context->get(HttpDriver::class),
- $config['domain'],
- $config['captcha']['provider_check'],
- $config['captcha']['extra']
- );
+ $query = $context->get(SecureImageCaptchaQuery::class);
$success = $query->verify(
$_POST['captcha_text'],
$_POST['captcha_cookie']