diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 40b14a9b54..8ad37047cb 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -235,8 +235,10 @@ class ucp_register // The CAPTCHA kicks in here. We can't help that the information gets lost on language change. if ($config['enable_confirm']) { - $captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']); - $captcha->init(CONFIRM_REG); + /** @var \phpbb\captcha\factory $captcha_factory */ + $captcha_factory = $phpbb_container->get('captcha.factory'); + $captcha = $captcha_factory->get_instance($config['captcha_plugin']); + $captcha->init(\phpbb\captcha\plugins\plugin_interface::CONFIRM_REGISTRATION); } $timezone = $config['board_timezone']; @@ -426,7 +428,7 @@ class ucp_register } // Okay, captcha, your job is done. - if ($config['enable_confirm'] && isset($captcha)) + if ($config['enable_confirm']) { $captcha->reset(); } diff --git a/phpBB/phpbb/captcha/factory.php b/phpBB/phpbb/captcha/factory.php index 2e75ce8667..971a7b2118 100644 --- a/phpBB/phpbb/captcha/factory.php +++ b/phpBB/phpbb/captcha/factory.php @@ -13,6 +13,9 @@ namespace phpbb\captcha; +use phpbb\captcha\plugins\legacy_wrapper; +use phpbb\captcha\plugins\plugin_interface; + class factory { /** @@ -41,11 +44,17 @@ class factory * Return a new instance of a given plugin * * @param $name - * @return object|null + * @return plugin_interface */ - public function get_instance($name) + public function get_instance($name): plugin_interface { - return $this->container->get($name); + $captcha = $this->container->get($name); + if ($captcha instanceof plugin_interface) + { + return $captcha; + } + + return new legacy_wrapper($name); } /** diff --git a/phpBB/phpbb/captcha/plugins/legacy_wrapper.php b/phpBB/phpbb/captcha/plugins/legacy_wrapper.php index 90ff01995b..bceb771800 100644 --- a/phpBB/phpbb/captcha/plugins/legacy_wrapper.php +++ b/phpBB/phpbb/captcha/plugins/legacy_wrapper.php @@ -17,6 +17,8 @@ class legacy_wrapper implements plugin_interface { private $legacy_captcha; + private string $last_error; + public function __construct($legacy_captcha) { $this->legacy_captcha = $legacy_captcha; @@ -72,11 +74,69 @@ class legacy_wrapper implements plugin_interface * @param int $type Type of captcha, should be one of the CONFIRMATION_* constants * @return void */ - public function show(int $type): void + public function init(int $type): void { if (method_exists($this->legacy_captcha, 'init')) { $this->legacy_captcha->init($type); } } -} \ No newline at end of file + + /** + * {@inheritDoc} + */ + public function validate(array $request_data): bool + { + if (method_exists($this->legacy_captcha, 'validate')) + { + $error = $this->legacy_captcha->validate($request_data); + if ($error) + { + $this->last_error = $error; + return false; + } + + return true; + } + + return false; + } + + /** + * {@inheritDoc} + */ + public function is_solved(): bool + { + if (method_exists($this->legacy_captcha, 'is_solved')) + { + return $this->legacy_captcha->is_solved(); + } + + return false; + } + + /** + * {@inheritDoc} + */ + public function reset(): void + { + if (method_exists($this->legacy_captcha, 'reset')) + { + $this->legacy_captcha->reset(); + } + } + + /** + * {@inheritDoc} + */ + public function get_attempt_count(): int + { + if (method_exists($this->legacy_captcha, 'get_attempt_count')) + { + return $this->legacy_captcha->get_attempt_count(); + } + + // Ensure this is deemed as too many attempts + return PHP_INT_MAX; + } +} diff --git a/phpBB/phpbb/captcha/plugins/plugin_interface.php b/phpBB/phpbb/captcha/plugins/plugin_interface.php index 51c8d3d23d..9d0b0cb4de 100644 --- a/phpBB/phpbb/captcha/plugins/plugin_interface.php +++ b/phpBB/phpbb/captcha/plugins/plugin_interface.php @@ -15,16 +15,17 @@ namespace phpbb\captcha\plugins; interface plugin_interface { - const CONFIRMATION_REGISTRATION = 1; - const CONFIRMATION_LOGIN = 2; + const CONFIRM_REGISTRATION = 1; + const CONFIRM_LOGIN = 2; - const CONFIRMATION_POST = 3; + const CONFIRM_POST = 3; - const CONFIRMATION_REPORT = 4; + const CONFIRM_REPORT = 4; /** * Check if the plugin is available + * * @return bool True if the plugin is available, false if not */ public function is_available(): bool; @@ -49,5 +50,34 @@ interface plugin_interface * @param int $type Type of captcha, should be one of the CONFIRMATION_* constants * @return void */ - public function show(int $type): void; + public function init(int $type): void; + + /** + * Validate the captcha with the given request data + * + * @param array $request_data Request data for the captcha + * @return bool True if request data was valid captcha reply, false if not + */ + public function validate(array $request_data): bool; + + /** + * Return whether captcha was solved + * + * @return bool True if captcha was solved, false if not + */ + public function is_solved(): bool; + + /** + * Reset captcha state, e.g. after checking if it's valid + * + * @return void + */ + public function reset(): void; + + /** + * Get attempt count for this captcha and user + * + * @return int Number of attempts + */ + public function get_attempt_count(): int; } diff --git a/phpBB/posting.php b/phpBB/posting.php index 63ca4fef97..988b7f03e2 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -455,8 +455,10 @@ if (!$is_authed || !empty($error)) if ($config['enable_post_confirm'] && !$user->data['is_registered']) { - $captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']); - $captcha->init(CONFIRM_POST); + /** @var \phpbb\captcha\factory $captcha_factory */ + $captcha_factory = $phpbb_container->get('captcha.factory'); + $captcha = $captcha_factory->get_instance($config['captcha_plugin']); + $captcha->init(\phpbb\captcha\plugins\plugin_interface::CONFIRM_POST); } // Is the user able to post within this forum? @@ -1600,7 +1602,7 @@ if ($submit || $preview || $refresh) ); extract($phpbb_dispatcher->trigger_event('core.posting_modify_submit_post_after', compact($vars))); - if ($config['enable_post_confirm'] && !$user->data['is_registered'] && (isset($captcha) && $captcha->is_solved() === true) && ($mode == 'post' || $mode == 'reply' || $mode == 'quote')) + if ($config['enable_post_confirm'] && !$user->data['is_registered'] && $captcha->is_solved() === true && ($mode == 'post' || $mode == 'reply' || $mode == 'quote')) { $captcha->reset(); }