From cf16a76f0c710057cf2c30bcdccdc4f8fa00adea Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 13 Oct 2024 21:41:11 +0200 Subject: [PATCH] [ticket/17414] Move more functionality to base and fix turnstile language PHPBB-17414 --- phpBB/phpbb/captcha/plugins/base.php | 94 ++++++++++++++++++- phpBB/phpbb/captcha/plugins/confirm_type.php | 1 + .../phpbb/captcha/plugins/legacy_wrapper.php | 9 +- phpBB/phpbb/captcha/plugins/turnstile.php | 36 +------ .../prosilver/template/captcha_turnstile.html | 2 +- 5 files changed, 103 insertions(+), 39 deletions(-) diff --git a/phpBB/phpbb/captcha/plugins/base.php b/phpBB/phpbb/captcha/plugins/base.php index be3b77ade1..a22336b1e5 100644 --- a/phpBB/phpbb/captcha/plugins/base.php +++ b/phpBB/phpbb/captcha/plugins/base.php @@ -2,34 +2,118 @@ namespace phpbb\captcha\plugins; -use phpbb\captcha\plugins\plugin_interface; +use phpbb\config\config; use phpbb\db\driver\driver_interface; +use phpbb\request\request_interface; +use phpbb\user; abstract class base implements plugin_interface { + /** @var config */ + protected config $config; + /** @var driver_interface */ protected driver_interface $db; + /** @var request_interface */ + protected request_interface $request; + + /** @var user */ + protected user $user; + + /** @var int Attempts at solving the CAPTCHA */ + protected int $attempts = 0; + /** @var bool Resolved state of captcha */ protected bool $solved = false; - /** @var string Confirm code */ - protected string $confirm_code = ''; - /** @var string Confirm id hash */ protected string $confirm_id = ''; + /** @var confirm_type Confirmation type */ + protected confirm_type $type = confirm_type::UNDEFINED; + /** @var string Last error message */ protected string $last_error = ''; /** * Constructor for abstract captcha base class * + * @param config $config * @param driver_interface $db + * @param request_interface $request + * @param user $user */ - public function __construct(driver_interface $db) + public function __construct(config $config, driver_interface $db, request_interface $request, user $user) { + $this->config = $config; $this->db = $db; + $this->request = $request; + $this->user = $user; + } + + /** + * {@inheritDoc} + */ + public function init(confirm_type $type): void + { + $this->confirm_id = $this->request->variable('confirm_id', ''); + $this->type = $type; + + if (empty($this->confirm_id) || !$this->load_confirm_data()) + { + // we have no confirm ID, better get ready to display something + $this->generate_confirm_data(); + } + } + + /** + * Look up attempts from confirm table + */ + protected function load_confirm_data(): bool + { + $sql = 'SELECT attempts + FROM ' . CONFIRM_TABLE . " + WHERE confirm_id = '" . $this->db->sql_escape($this->confirm_id) . "' + AND session_id = '" . $this->db->sql_escape($this->user->session_id) . "' + AND confirm_type = " . (int) $this->type; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + if ($row) + { + $this->attempts = $row['attempts']; + + return true; + } + + return false; + } + + /** + * Generate confirm data for tracking attempts + * + * @return void + */ + protected function generate_confirm_data(): void + { + $this->confirm_id = md5(unique_id()); + + $sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $this->db->sql_build_array('INSERT', array( + 'confirm_id' => $this->confirm_id, + 'session_id' => (string) $this->user->session_id, + 'confirm_type' => $this->type + )); + $this->db->sql_query($sql); + } + + /** + * {@inheritDoc} + */ + public function get_hidden_fields(): array + { + return ['confirm_id' => $this->confirm_id]; } /** diff --git a/phpBB/phpbb/captcha/plugins/confirm_type.php b/phpBB/phpbb/captcha/plugins/confirm_type.php index db8bb54bd2..e3e11edf77 100644 --- a/phpBB/phpbb/captcha/plugins/confirm_type.php +++ b/phpBB/phpbb/captcha/plugins/confirm_type.php @@ -17,6 +17,7 @@ namespace phpbb\captcha\plugins; * Confirmation types for CAPTCHA plugins */ enum confirm_type: int { + case UNDEFINED = 0; case REGISTRATION = 1; case LOGIN = 2; case POST = 3; diff --git a/phpBB/phpbb/captcha/plugins/legacy_wrapper.php b/phpBB/phpbb/captcha/plugins/legacy_wrapper.php index 48b91ef3d2..48575733cc 100644 --- a/phpBB/phpbb/captcha/plugins/legacy_wrapper.php +++ b/phpBB/phpbb/captcha/plugins/legacy_wrapper.php @@ -19,7 +19,12 @@ class legacy_wrapper implements plugin_interface private string $last_error; - public function __construct($legacy_captcha) + /** + * Constructor for legacy CAPTCHA wrapper + * + * @param object $legacy_captcha + */ + public function __construct(object $legacy_captcha) { $this->legacy_captcha = $legacy_captcha; } @@ -77,7 +82,7 @@ class legacy_wrapper implements plugin_interface /** * {@inheritDoc} */ - public function init(int $type): void + public function init(confirm_type $type): void { if (method_exists($this->legacy_captcha, 'init')) { diff --git a/phpBB/phpbb/captcha/plugins/turnstile.php b/phpBB/phpbb/captcha/plugins/turnstile.php index f5bd22602b..1a42c7adbf 100644 --- a/phpBB/phpbb/captcha/plugins/turnstile.php +++ b/phpBB/phpbb/captcha/plugins/turnstile.php @@ -16,7 +16,6 @@ namespace phpbb\captcha\plugins; use GuzzleHttp\Client; use GuzzleHttp\Exception\GuzzleException; use phpbb\config\config; -use phpbb\db\driver\driver; use phpbb\db\driver\driver_interface; use phpbb\language\language; use phpbb\log\log_interface; @@ -32,24 +31,15 @@ class turnstile extends base /** @var string API endpoint for turnstile verification */ private const VERIFY_ENDPOINT = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'; - /** @var config */ - protected config $config; - /** @var language */ protected language $language; /** @var log_interface */ protected log_interface $log; - /** @var request_interface */ - protected request_interface $request; - /** @var template */ protected template $template; - /** @var user */ - protected user $user; - /** @var string Service name */ protected string $service_name = ''; @@ -73,14 +63,11 @@ class turnstile extends base */ public function __construct(config $config, driver_interface $db, language $language, log_interface $log, request_interface $request, template $template, user $user) { - parent::__construct($db); + parent::__construct($config, $db, $request, $user); - $this->config = $config; $this->language = $language; $this->log = $log; - $this->request = $request; $this->template = $template; - $this->user = $user; } /** @@ -88,7 +75,7 @@ class turnstile extends base */ public function is_available(): bool { - $this->init(0); + $this->init(confirm_type::UNDEFINED); return !empty($this->config->offsetGet('captcha_turnstile_sitekey')) && !empty($this->config->offsetGet('captcha_turnstile_secret')); @@ -126,22 +113,6 @@ class turnstile extends base $this->language->add_lang('captcha_turnstile'); } - /** - * {@inheritDoc} - */ - public function get_hidden_fields(): array - { - $hidden_fields = []; - - // Required for posting page to store solved state - if ($this->solved) - { - $hidden_fields['confirm_code'] = $this->confirm_code; - } - $hidden_fields['confirm_id'] = $this->confirm_id; - return $hidden_fields; - } - /** * {@inheritDoc} */ @@ -196,6 +167,9 @@ class turnstile extends base // TODO: Implement reset() method. } + /** + * {@inheritDoc} + */ public function get_attempt_count(): int { // TODO: Implement get_attempt_count() method. diff --git a/phpBB/styles/prosilver/template/captcha_turnstile.html b/phpBB/styles/prosilver/template/captcha_turnstile.html index f20d53e539..b8c8855502 100644 --- a/phpBB/styles/prosilver/template/captcha_turnstile.html +++ b/phpBB/styles/prosilver/template/captcha_turnstile.html @@ -6,7 +6,7 @@ {# The cf-turnstile class is used in JavaScript #} -
+
{% else %} {{ lang('CAPTCHA_TURNSTILE_NOT_AVAILABLE') }} {% endif %}