mirror of
https://github.com/phpbb/phpbb.git
synced 2025-08-13 04:04:12 +02:00
Merge pull request #6737 from marc1706/feature/captcha_v2
[feature/captcha_v2] Refactor captcha classes and implement turnstile captcha
This commit is contained in:
@@ -176,9 +176,8 @@ class db extends base
|
||||
// Every auth module is able to define what to do by itself...
|
||||
if ($show_captcha)
|
||||
{
|
||||
$captcha->init(CONFIRM_LOGIN);
|
||||
$vc_response = $captcha->validate($row);
|
||||
if ($vc_response)
|
||||
$captcha->init(\phpbb\captcha\plugins\confirm_type::LOGIN);
|
||||
if ($captcha->validate() !== true)
|
||||
{
|
||||
return array(
|
||||
'status' => LOGIN_ERROR_ATTEMPTS,
|
||||
|
@@ -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($captcha);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,7 +65,7 @@ class factory
|
||||
function garbage_collect($name)
|
||||
{
|
||||
$captcha = $this->get_instance($name);
|
||||
$captcha->garbage_collect(0);
|
||||
$captcha->garbage_collect();
|
||||
}
|
||||
|
||||
/**
|
||||
|
256
phpBB/phpbb/captcha/plugins/base.php
Normal file
256
phpBB/phpbb/captcha/plugins/base.php
Normal file
@@ -0,0 +1,256 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\captcha\plugins;
|
||||
|
||||
use phpbb\config\config;
|
||||
use phpbb\db\driver\driver_interface;
|
||||
use phpbb\language\language;
|
||||
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 language */
|
||||
protected language $language;
|
||||
|
||||
/** @var request_interface */
|
||||
protected request_interface $request;
|
||||
|
||||
/** @var user */
|
||||
protected user $user;
|
||||
|
||||
/** @var int Attempts at solving the CAPTCHA */
|
||||
protected int $attempts = 0;
|
||||
|
||||
/** @var string Stored random CAPTCHA code */
|
||||
protected string $code = '';
|
||||
|
||||
/** @var bool Resolved state of captcha */
|
||||
protected bool $solved = false;
|
||||
|
||||
/** @var string User supplied 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 language $language
|
||||
* @param request_interface $request
|
||||
* @param user $user
|
||||
*/
|
||||
public function __construct(config $config, driver_interface $db, language $language, request_interface $request, user $user)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->db = $db;
|
||||
$this->language = $language;
|
||||
$this->request = $request;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function init(confirm_type $type): void
|
||||
{
|
||||
$this->confirm_id = $this->request->variable('confirm_id', '');
|
||||
$this->confirm_code = $this->request->variable('confirm_code', '');
|
||||
$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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function validate(): bool
|
||||
{
|
||||
if ($this->confirm_id && hash_equals($this->code, $this->confirm_code))
|
||||
{
|
||||
$this->solved = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->increment_attempts();
|
||||
$this->last_error = $this->language->lang('CONFIRM_CODE_WRONG');
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function reset(): void
|
||||
{
|
||||
$sql = 'DELETE FROM ' . CONFIRM_TABLE . "
|
||||
WHERE session_id = '" . $this->db->sql_escape($this->user->session_id) . "'
|
||||
AND confirm_type = " . $this->type->value;
|
||||
$this->db->sql_query($sql);
|
||||
|
||||
$this->generate_confirm_data();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_attempt_count(): int
|
||||
{
|
||||
return $this->attempts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up attempts from confirm table
|
||||
*/
|
||||
protected function load_confirm_data(): bool
|
||||
{
|
||||
$sql = 'SELECT code, 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 = " . $this->type->value;
|
||||
$result = $this->db->sql_query($sql);
|
||||
$row = $this->db->sql_fetchrow($result);
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
if ($row)
|
||||
{
|
||||
$this->attempts = $row['attempts'];
|
||||
$this->code = $row['code'];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate confirm data for tracking attempts
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function generate_confirm_data(): void
|
||||
{
|
||||
$this->code = gen_rand_string_friendly(CAPTCHA_MAX_CHARS);
|
||||
$this->confirm_id = md5(unique_id());
|
||||
$this->attempts = 0;
|
||||
|
||||
$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->value,
|
||||
'code' => $this->code,
|
||||
));
|
||||
$this->db->sql_query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment number of attempts for confirm ID and session
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function increment_attempts(): void
|
||||
{
|
||||
$sql = 'UPDATE ' . CONFIRM_TABLE . "
|
||||
SET attempts = attempts + 1
|
||||
WHERE confirm_id = '{$this->db->sql_escape($this->confirm_id)}'
|
||||
AND session_id = '{$this->db->sql_escape($this->user->session_id)}'";
|
||||
$this->db->sql_query($sql);
|
||||
|
||||
$this->attempts++;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_hidden_fields(): array
|
||||
{
|
||||
return [
|
||||
'confirm_id' => $this->confirm_id,
|
||||
'confirm_code' => $this->solved === true ? $this->confirm_code : '',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function is_solved(): bool
|
||||
{
|
||||
return $this->solved;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_error(): string
|
||||
{
|
||||
return $this->last_error;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function garbage_collect(confirm_type $confirm_type = confirm_type::UNDEFINED): void
|
||||
{
|
||||
$sql = 'SELECT DISTINCT c.session_id
|
||||
FROM ' . CONFIRM_TABLE . ' c
|
||||
LEFT JOIN ' . SESSIONS_TABLE . ' s ON (c.session_id = s.session_id)
|
||||
WHERE s.session_id IS NULL' .
|
||||
((empty($confirm_type)) ? '' : ' AND c.confirm_type = ' . $confirm_type->value);
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
if ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
$sql_in = [];
|
||||
do
|
||||
{
|
||||
$sql_in[] = (string) $row['session_id'];
|
||||
}
|
||||
while ($row = $this->db->sql_fetchrow($result));
|
||||
|
||||
if (count($sql_in))
|
||||
{
|
||||
$sql = 'DELETE FROM ' . CONFIRM_TABLE . '
|
||||
WHERE ' . $this->db->sql_in_set('session_id', $sql_in);
|
||||
$this->db->sql_query($sql);
|
||||
}
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function acp_page(mixed $id, mixed $module): void
|
||||
{
|
||||
}
|
||||
}
|
@@ -179,16 +179,6 @@ abstract class captcha_abstract
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
$this->garbage_collect(0);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
function validate()
|
||||
{
|
||||
global $user;
|
||||
|
25
phpBB/phpbb/captcha/plugins/confirm_type.php
Normal file
25
phpBB/phpbb/captcha/plugins/confirm_type.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
case REPORT = 4;
|
||||
}
|
@@ -14,25 +14,34 @@
|
||||
namespace phpbb\captcha\plugins;
|
||||
|
||||
use phpbb\config\config;
|
||||
use phpbb\exception\runtime_exception;
|
||||
use phpbb\db\driver\driver_interface;
|
||||
use phpbb\language\language;
|
||||
use phpbb\request\request_interface;
|
||||
use phpbb\template\template;
|
||||
use phpbb\user;
|
||||
|
||||
class incomplete extends captcha_abstract
|
||||
class incomplete extends base
|
||||
{
|
||||
/**
|
||||
* Constructor for incomplete captcha
|
||||
*
|
||||
* @param config $config
|
||||
* @param driver_interface $db
|
||||
* @param language $language
|
||||
* @param request_interface $request
|
||||
* @param template $template
|
||||
* @param user $user
|
||||
* @param string $phpbb_root_path
|
||||
* @param string $phpEx
|
||||
*/
|
||||
public function __construct(protected config $config, protected template $template,
|
||||
protected string $phpbb_root_path, protected string $phpEx)
|
||||
{}
|
||||
public function __construct(config $config, driver_interface $db, language $language, request_interface $request,
|
||||
protected template $template, user $user, protected string $phpbb_root_path, protected string $phpEx)
|
||||
{
|
||||
parent::__construct($config, $db, $language, $request, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool True if captcha is available, false if not
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function is_available(): bool
|
||||
{
|
||||
@@ -40,70 +49,45 @@ class incomplete extends captcha_abstract
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy implementation, not supported by this captcha
|
||||
*
|
||||
* @throws runtime_exception
|
||||
* @return void
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_generator_class(): void
|
||||
public function has_config(): bool
|
||||
{
|
||||
throw new runtime_exception('NO_GENERATOR_CLASS');
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CAPTCHA name language variable
|
||||
*
|
||||
* @return string Language variable
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function get_name(): string
|
||||
public function get_name(): string
|
||||
{
|
||||
return 'CAPTCHA_INCOMPLETE';
|
||||
}
|
||||
|
||||
/**
|
||||
* Init CAPTCHA
|
||||
*
|
||||
* @param int $type CAPTCHA type
|
||||
* @return void
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function init($type)
|
||||
public function set_name(string $name): void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute demo
|
||||
*
|
||||
* @return void
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function execute_demo()
|
||||
public function init(confirm_type $type): void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute CAPTCHA
|
||||
*
|
||||
* @return void
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get template data for demo
|
||||
*
|
||||
* @param int|string $id ACP module ID
|
||||
*
|
||||
* @return string Demo template file name
|
||||
*/
|
||||
public function get_demo_template($id): string
|
||||
public function get_demo_template(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get template data for CAPTCHA
|
||||
*
|
||||
* @return string CAPTCHA template file name
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_template(): string
|
||||
{
|
||||
@@ -118,9 +102,7 @@ class incomplete extends captcha_abstract
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate CAPTCHA
|
||||
*
|
||||
* @return false Incomplete CAPTCHA will never validate
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function validate(): bool
|
||||
{
|
||||
@@ -128,12 +110,26 @@ class incomplete extends captcha_abstract
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether CAPTCHA is solved
|
||||
*
|
||||
* @return false Incomplete CAPTCHA will never be solved
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_error(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function is_solved(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_attempt_count(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
221
phpBB/phpbb/captcha/plugins/legacy_wrapper.php
Normal file
221
phpBB/phpbb/captcha/plugins/legacy_wrapper.php
Normal file
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\captcha\plugins;
|
||||
|
||||
class legacy_wrapper implements plugin_interface
|
||||
{
|
||||
/** @var object Legacy CAPTCHA instance, should implement functionality as required in phpBB 3.3 */
|
||||
private $legacy_captcha;
|
||||
|
||||
/** @var string Last error */
|
||||
private string $last_error;
|
||||
|
||||
/**
|
||||
* Constructor for legacy CAPTCHA wrapper
|
||||
*
|
||||
* @param object $legacy_captcha
|
||||
*/
|
||||
public function __construct(object $legacy_captcha)
|
||||
{
|
||||
$this->legacy_captcha = $legacy_captcha;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function is_available(): bool
|
||||
{
|
||||
if (method_exists($this->legacy_captcha, 'is_available'))
|
||||
{
|
||||
return $this->legacy_captcha->is_available();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function has_config(): bool
|
||||
{
|
||||
if (method_exists($this->legacy_captcha, 'has_config'))
|
||||
{
|
||||
return $this->legacy_captcha->has_config();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_name(): string
|
||||
{
|
||||
if (method_exists($this->legacy_captcha, 'get_name'))
|
||||
{
|
||||
return $this->legacy_captcha->get_name();
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function set_name(string $name): void
|
||||
{
|
||||
if (method_exists($this->legacy_captcha, 'set_name'))
|
||||
{
|
||||
$this->legacy_captcha->set_name($name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function init(confirm_type $type): void
|
||||
{
|
||||
if (method_exists($this->legacy_captcha, 'init'))
|
||||
{
|
||||
$this->legacy_captcha->init($type->value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_hidden_fields(): array
|
||||
{
|
||||
if (method_exists($this->legacy_captcha, 'get_hidden_fields'))
|
||||
{
|
||||
return $this->legacy_captcha->get_hidden_fields();
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function validate(): bool
|
||||
{
|
||||
if (method_exists($this->legacy_captcha, 'validate'))
|
||||
{
|
||||
$error = $this->legacy_captcha->validate();
|
||||
if ($error)
|
||||
{
|
||||
$this->last_error = $error;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_error(): string
|
||||
{
|
||||
return $this->last_error;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_template(): string
|
||||
{
|
||||
if (method_exists($this->legacy_captcha, 'get_template'))
|
||||
{
|
||||
return $this->legacy_captcha->get_template();
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_demo_template(): string
|
||||
{
|
||||
if (method_exists($this->legacy_captcha, 'get_demo_template'))
|
||||
{
|
||||
return $this->legacy_captcha->get_demo_template(0);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function garbage_collect(confirm_type $confirm_type = confirm_type::UNDEFINED): void
|
||||
{
|
||||
if (method_exists($this->legacy_captcha, 'garbage_collect'))
|
||||
{
|
||||
$this->legacy_captcha->garbage_collect($confirm_type->value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function acp_page(mixed $id, mixed $module): void
|
||||
{
|
||||
if (method_exists($this->legacy_captcha, 'acp_page'))
|
||||
{
|
||||
$this->legacy_captcha->acp_page($id, $module);
|
||||
}
|
||||
}
|
||||
}
|
126
phpBB/phpbb/captcha/plugins/plugin_interface.php
Normal file
126
phpBB/phpbb/captcha/plugins/plugin_interface.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\captcha\plugins;
|
||||
|
||||
interface plugin_interface
|
||||
{
|
||||
/**
|
||||
* Check if the plugin is available
|
||||
*
|
||||
* @return bool True if the plugin is available, false if not
|
||||
*/
|
||||
public function is_available(): bool;
|
||||
|
||||
/**
|
||||
* Check if the plugin has a configuration
|
||||
*
|
||||
* @return bool True if the plugin has a configuration, false if not
|
||||
*/
|
||||
public function has_config(): bool;
|
||||
|
||||
/**
|
||||
* Get the name of the plugin, should be language variable
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name(): string;
|
||||
|
||||
/**
|
||||
* Set the service name of the plugin
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function set_name(string $name): void;
|
||||
|
||||
/**
|
||||
* Display the captcha for the specified type
|
||||
*
|
||||
* @param confirm_type $type Type of captcha, should be one of the CONFIRMATION_* constants
|
||||
* @return void
|
||||
*/
|
||||
public function init(confirm_type $type): void;
|
||||
|
||||
/**
|
||||
* Get hidden form fields for this captcha plugin
|
||||
*
|
||||
* @return array Hidden form fields
|
||||
*/
|
||||
public function get_hidden_fields(): array;
|
||||
|
||||
/**
|
||||
* Validate the captcha with the given request data
|
||||
*
|
||||
* @return bool True if request data was valid captcha reply, false if not
|
||||
*/
|
||||
public function validate(): bool;
|
||||
|
||||
/**
|
||||
* Get error string from captcha
|
||||
*
|
||||
* @return string Error string, empty string if there is no error
|
||||
*/
|
||||
public function get_error(): string;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Get template filename for captcha
|
||||
*
|
||||
* @return string Template file name
|
||||
*/
|
||||
public function get_template(): string;
|
||||
|
||||
/**
|
||||
* Get template filename for demo
|
||||
*
|
||||
* @return string Demo template file name
|
||||
*/
|
||||
public function get_demo_template(): string;
|
||||
|
||||
/**
|
||||
* Garbage collect captcha plugin
|
||||
*
|
||||
* @param confirm_type $confirm_type Confirm type to garbage collect, defaults to all (0)
|
||||
* @return void
|
||||
*/
|
||||
public function garbage_collect(confirm_type $confirm_type = confirm_type::UNDEFINED): void;
|
||||
|
||||
/**
|
||||
* Display acp page
|
||||
*
|
||||
* @param mixed $id ACP module id
|
||||
* @param mixed $module ACP module name
|
||||
* @return void
|
||||
*/
|
||||
public function acp_page(mixed $id, mixed $module): void;
|
||||
}
|
@@ -40,7 +40,7 @@ class qa
|
||||
protected $service_name;
|
||||
|
||||
/** @var int Question ID */
|
||||
protected $question = -1;
|
||||
private $question = -1;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@@ -323,71 +323,6 @@ class qa
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* API function - we don't drop the tables here, as that would cause the loss of all entered questions.
|
||||
*/
|
||||
function uninstall()
|
||||
{
|
||||
$this->garbage_collect(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* API function - set up shop
|
||||
*/
|
||||
function install()
|
||||
{
|
||||
global $phpbb_container;
|
||||
|
||||
$db_tool = $phpbb_container->get('dbal.tools');
|
||||
$schemas = array(
|
||||
$this->table_captcha_questions => array (
|
||||
'COLUMNS' => array(
|
||||
'question_id' => array('UINT', null, 'auto_increment'),
|
||||
'strict' => array('BOOL', 0),
|
||||
'lang_id' => array('UINT', 0),
|
||||
'lang_iso' => array('VCHAR:30', ''),
|
||||
'question_text' => array('TEXT_UNI', ''),
|
||||
),
|
||||
'PRIMARY_KEY' => 'question_id',
|
||||
'KEYS' => array(
|
||||
'lang' => array('INDEX', 'lang_iso'),
|
||||
),
|
||||
),
|
||||
$this->table_captcha_answers => array (
|
||||
'COLUMNS' => array(
|
||||
'question_id' => array('UINT', 0),
|
||||
'answer_text' => array('STEXT_UNI', ''),
|
||||
),
|
||||
'KEYS' => array(
|
||||
'qid' => array('INDEX', 'question_id'),
|
||||
),
|
||||
),
|
||||
$this->table_qa_confirm => array (
|
||||
'COLUMNS' => array(
|
||||
'session_id' => array('CHAR:32', ''),
|
||||
'confirm_id' => array('CHAR:32', ''),
|
||||
'lang_iso' => array('VCHAR:30', ''),
|
||||
'question_id' => array('UINT', 0),
|
||||
'attempts' => array('UINT', 0),
|
||||
'confirm_type' => array('USINT', 0),
|
||||
),
|
||||
'KEYS' => array(
|
||||
'session_id' => array('INDEX', 'session_id'),
|
||||
'lookup' => array('INDEX', array('confirm_id', 'session_id', 'lang_iso')),
|
||||
),
|
||||
'PRIMARY_KEY' => 'confirm_id',
|
||||
),
|
||||
);
|
||||
|
||||
foreach ($schemas as $table => $schema)
|
||||
{
|
||||
if (!$db_tool->sql_table_exists($table))
|
||||
{
|
||||
$db_tool->sql_create_table($table, $schema);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* API function - see what has to be done to validate
|
||||
*/
|
||||
@@ -647,11 +582,6 @@ class qa
|
||||
$user->add_lang('acp/board');
|
||||
$user->add_lang('captcha_qa');
|
||||
|
||||
if (!self::is_installed())
|
||||
{
|
||||
$this->install();
|
||||
}
|
||||
|
||||
$module->tpl_name = 'captcha_qa_acp';
|
||||
$module->page_title = 'ACP_VC_SETTINGS';
|
||||
$form_key = 'acp_captcha';
|
||||
|
@@ -179,16 +179,6 @@ class recaptcha extends captcha_abstract
|
||||
return $hidden_fields;
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
$this->garbage_collect(0);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
function validate()
|
||||
{
|
||||
if (!parent::validate())
|
||||
|
287
phpBB/phpbb/captcha/plugins/turnstile.php
Normal file
287
phpBB/phpbb/captcha/plugins/turnstile.php
Normal file
@@ -0,0 +1,287 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\captcha\plugins;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use phpbb\config\config;
|
||||
use phpbb\db\driver\driver_interface;
|
||||
use phpbb\language\language;
|
||||
use phpbb\log\log_interface;
|
||||
use phpbb\request\request_interface;
|
||||
use phpbb\template\template;
|
||||
use phpbb\user;
|
||||
|
||||
class turnstile extends base
|
||||
{
|
||||
/** @var string URL to cloudflare turnstile API javascript */
|
||||
private const SCRIPT_URL = 'https://challenges.cloudflare.com/turnstile/v0/api.js';
|
||||
|
||||
/** @var string API endpoint for turnstile verification */
|
||||
private const VERIFY_ENDPOINT = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
|
||||
|
||||
/** @var Client */
|
||||
protected Client $client;
|
||||
|
||||
/** @var language */
|
||||
protected language $language;
|
||||
|
||||
/** @var log_interface */
|
||||
protected log_interface $log;
|
||||
|
||||
/** @var template */
|
||||
protected template $template;
|
||||
|
||||
/** @var string Service name */
|
||||
protected string $service_name = '';
|
||||
|
||||
/** @var array|string[] Supported themes for Turnstile CAPTCHA */
|
||||
protected static array $supported_themes = [
|
||||
'light',
|
||||
'dark',
|
||||
'auto'
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor for turnstile captcha plugin
|
||||
*
|
||||
* @param config $config
|
||||
* @param driver_interface $db
|
||||
* @param language $language
|
||||
* @param log_interface $log
|
||||
* @param request_interface $request
|
||||
* @param template $template
|
||||
* @param user $user
|
||||
*/
|
||||
public function __construct(config $config, driver_interface $db, language $language, log_interface $log, request_interface $request, template $template, user $user)
|
||||
{
|
||||
parent::__construct($config, $db, $language, $request, $user);
|
||||
|
||||
$this->language = $language;
|
||||
$this->log = $log;
|
||||
$this->template = $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function is_available(): bool
|
||||
{
|
||||
$this->init($this->type);
|
||||
|
||||
return !empty($this->config->offsetGet('captcha_turnstile_sitekey'))
|
||||
&& !empty($this->config->offsetGet('captcha_turnstile_secret'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function has_config(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_name(): string
|
||||
{
|
||||
return 'CAPTCHA_TURNSTILE';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function set_name(string $name): void
|
||||
{
|
||||
$this->service_name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function init(confirm_type $type): void
|
||||
{
|
||||
parent::init($type);
|
||||
|
||||
$this->language->add_lang('captcha_turnstile');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function validate(): bool
|
||||
{
|
||||
if (parent::validate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$turnstile_response = $this->request->variable('cf-turnstile-response', '');
|
||||
if (!$turnstile_response)
|
||||
{
|
||||
// Return without checking against server without a turnstile response
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve form data for verification
|
||||
$form_data = [
|
||||
'secret' => $this->config['captcha_turnstile_secret'],
|
||||
'response' => $turnstile_response,
|
||||
'remoteip' => $this->user->ip,
|
||||
];
|
||||
|
||||
// Create guzzle client
|
||||
$client = $this->get_client();
|
||||
|
||||
// Check captcha with turnstile API
|
||||
try
|
||||
{
|
||||
$response = $client->request('POST', self::VERIFY_ENDPOINT, [
|
||||
'form_params' => $form_data,
|
||||
]);
|
||||
}
|
||||
catch (GuzzleException)
|
||||
{
|
||||
// Something went wrong during the request to Cloudflare, assume captcha was bad
|
||||
$this->solved = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decode the JSON response
|
||||
$result = json_decode($response->getBody(), true);
|
||||
|
||||
// Check if the response indicates success
|
||||
if (isset($result['success']) && $result['success'] === true)
|
||||
{
|
||||
$this->solved = true;
|
||||
$this->confirm_code = $this->code;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->last_error = $this->language->lang('CAPTCHA_TURNSTILE_INCORRECT');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Guzzle client
|
||||
*
|
||||
* @return Client
|
||||
*/
|
||||
protected function get_client(): Client
|
||||
{
|
||||
if (!isset($this->client))
|
||||
{
|
||||
$this->client = new Client();
|
||||
}
|
||||
|
||||
return $this->client;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_template(): string
|
||||
{
|
||||
if ($this->is_solved())
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
$this->template->assign_vars([
|
||||
'S_TURNSTILE_AVAILABLE' => $this->is_available(),
|
||||
'TURNSTILE_SITEKEY' => $this->config->offsetGet('captcha_turnstile_sitekey'),
|
||||
'TURNSTILE_THEME' => $this->config->offsetGet('captcha_turnstile_theme'),
|
||||
'U_TURNSTILE_SCRIPT' => self::SCRIPT_URL,
|
||||
'CONFIRM_TYPE_REGISTRATION' => $this->type->value,
|
||||
]);
|
||||
|
||||
return 'captcha_turnstile.html';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_demo_template(): string
|
||||
{
|
||||
$this->template->assign_vars([
|
||||
'TURNSTILE_THEME' => $this->config->offsetGet('captcha_turnstile_theme'),
|
||||
'U_TURNSTILE_SCRIPT' => self::SCRIPT_URL,
|
||||
]);
|
||||
|
||||
return 'captcha_turnstile_acp_demo.html';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function acp_page(mixed $id, mixed $module): void
|
||||
{
|
||||
$captcha_vars = [
|
||||
'captcha_turnstile_sitekey' => 'CAPTCHA_TURNSTILE_SITEKEY',
|
||||
'captcha_turnstile_secret' => 'CAPTCHA_TURNSTILE_SECRET',
|
||||
];
|
||||
|
||||
$module->tpl_name = 'captcha_turnstile_acp';
|
||||
$module->page_title = 'ACP_VC_SETTINGS';
|
||||
$form_key = 'acp_captcha';
|
||||
add_form_key($form_key);
|
||||
|
||||
$submit = $this->request->is_set_post('submit');
|
||||
|
||||
if ($submit && check_form_key($form_key))
|
||||
{
|
||||
$captcha_vars = array_keys($captcha_vars);
|
||||
foreach ($captcha_vars as $captcha_var)
|
||||
{
|
||||
$value = $this->request->variable($captcha_var, '');
|
||||
if ($value)
|
||||
{
|
||||
$this->config->set($captcha_var, $value);
|
||||
}
|
||||
}
|
||||
|
||||
$captcha_theme = $this->request->variable('captcha_turnstile_theme', self::$supported_themes[0]);
|
||||
if (in_array($captcha_theme, self::$supported_themes))
|
||||
{
|
||||
$this->config->set('captcha_turnstile_theme', $captcha_theme);
|
||||
}
|
||||
|
||||
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_VISUAL');
|
||||
trigger_error($this->language->lang('CONFIG_UPDATED') . adm_back_link($module->u_action));
|
||||
}
|
||||
else if ($submit)
|
||||
{
|
||||
trigger_error($this->language->lang('FORM_INVALID') . adm_back_link($module->u_action));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($captcha_vars as $captcha_var => $template_var)
|
||||
{
|
||||
$var = $this->request->is_set($captcha_var) ? $this->request->variable($captcha_var, '') : $this->config->offsetGet($captcha_var);
|
||||
$this->template->assign_var($template_var, $var);
|
||||
}
|
||||
|
||||
$this->template->assign_vars(array(
|
||||
'CAPTCHA_PREVIEW' => $this->get_demo_template(),
|
||||
'CAPTCHA_NAME' => $this->service_name,
|
||||
'CAPTCHA_TURNSTILE_THEME' => $this->config->offsetGet('captcha_turnstile_theme'),
|
||||
'CAPTCHA_TURNSTILE_THEMES' => self::$supported_themes,
|
||||
'U_ACTION' => $module->u_action,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
89
phpBB/phpbb/db/migration/data/v400/qa_captcha.php
Normal file
89
phpBB/phpbb/db/migration/data/v400/qa_captcha.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\db\migration\data\v400;
|
||||
|
||||
use phpbb\db\migration\migration;
|
||||
|
||||
class qa_captcha extends migration
|
||||
{
|
||||
public function effectively_installed(): bool
|
||||
{
|
||||
return $this->db_tools->sql_table_exists($this->tables['captcha_qa_questions'])
|
||||
&& $this->db_tools->sql_table_exists($this->tables['captcha_qa_answers'])
|
||||
&& $this->db_tools->sql_table_exists($this->tables['captcha_qa_confirm']);
|
||||
}
|
||||
|
||||
public static function depends_on(): array
|
||||
{
|
||||
return [
|
||||
'\phpbb\db\migration\data\v400\dev',
|
||||
];
|
||||
}
|
||||
|
||||
public function update_schema(): array
|
||||
{
|
||||
return [
|
||||
'add_tables' => [
|
||||
$this->tables['captcha_qa_questions'] => [
|
||||
'COLUMNS' => [
|
||||
'question_id' => ['UINT', null, 'auto_increment'],
|
||||
'strict' => ['BOOL', 0],
|
||||
'lang_id' => ['UINT', 0],
|
||||
'lang_iso' => ['VCHAR:30', ''],
|
||||
'question_text' => ['TEXT_UNI', ''],
|
||||
],
|
||||
'PRIMARY_KEY' => 'question_id',
|
||||
'KEYS' => [
|
||||
'lang' => ['INDEX', 'lang_iso'],
|
||||
],
|
||||
],
|
||||
$this->tables['captcha_qa_answers'] => [
|
||||
'COLUMNS' => [
|
||||
'question_id' => ['UINT', 0],
|
||||
'answer_text' => ['STEXT_UNI', ''],
|
||||
],
|
||||
'KEYS' => [
|
||||
'qid' => ['INDEX', 'question_id'],
|
||||
],
|
||||
],
|
||||
$this->tables['captcha_qa_confirm'] => [
|
||||
'COLUMNS' => [
|
||||
'session_id' => ['CHAR:32', ''],
|
||||
'confirm_id' => ['CHAR:32', ''],
|
||||
'lang_iso' => ['VCHAR:30', ''],
|
||||
'question_id' => ['UINT', 0],
|
||||
'attempts' => ['UINT', 0],
|
||||
'confirm_type' => ['USINT', 0],
|
||||
],
|
||||
'KEYS' => [
|
||||
'session_id' => ['INDEX', 'session_id'],
|
||||
'lookup' => ['INDEX', ['confirm_id', 'session_id', 'lang_iso']],
|
||||
],
|
||||
'PRIMARY_KEY' => 'confirm_id',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function revert_schema(): array
|
||||
{
|
||||
return [
|
||||
'drop_tables' => [
|
||||
$this->tables['captcha_qa_questions'],
|
||||
$this->tables['captcha_qa_answers'],
|
||||
$this->tables['captcha_qa_confirm']
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
51
phpBB/phpbb/db/migration/data/v400/turnstile_captcha.php
Normal file
51
phpBB/phpbb/db/migration/data/v400/turnstile_captcha.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\db\migration\data\v400;
|
||||
|
||||
use phpbb\db\migration\migration;
|
||||
|
||||
class turnstile_captcha extends migration
|
||||
{
|
||||
public function effectively_installed(): bool
|
||||
{
|
||||
return $this->config->offsetExists('captcha_turnstile_sitekey')
|
||||
&& $this->config->offsetExists('captcha_turnstile_secret')
|
||||
&& $this->config->offsetExists('captcha_turnstile_theme');
|
||||
}
|
||||
|
||||
public static function depends_on(): array
|
||||
{
|
||||
return [
|
||||
'\phpbb\db\migration\data\v400\dev',
|
||||
];
|
||||
}
|
||||
|
||||
public function update_data(): array
|
||||
{
|
||||
return [
|
||||
['config.add', ['captcha_turnstile_sitekey', '']],
|
||||
['config.add', ['captcha_turnstile_secret', '']],
|
||||
['config.add', ['captcha_turnstile_theme', 'light']],
|
||||
];
|
||||
}
|
||||
|
||||
public function revert_data(): array
|
||||
{
|
||||
return [
|
||||
['config.remove', ['captcha_turnstile_sitekey']],
|
||||
['config.remove', ['captcha_turnstile_secret']],
|
||||
['config.remove', ['captcha_turnstile_theme']],
|
||||
];
|
||||
}
|
||||
}
|
@@ -403,6 +403,7 @@ class language
|
||||
$this->lang['USER_LANG'] = $lang_values['user_lang'] ?? 'en-gb';
|
||||
$this->lang['PLURAL_RULE'] = $lang_values['plural_rule'] ?? 1;
|
||||
$this->lang['RECAPTCHA_LANG'] = $lang_values['recaptcha_lang'] ?? 'en-GB';
|
||||
$this->lang['TURNSTILE_LANG'] = $lang_values['turnstile_lang'] ?? 'auto'; // default to auto mode
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -110,16 +110,17 @@ class language_file_helper
|
||||
}
|
||||
|
||||
return [
|
||||
'iso' => $data['extra']['language-iso'],
|
||||
'name' => $data['extra']['english-name'],
|
||||
'local_name' => $data['extra']['local-name'],
|
||||
'author' => implode(', ', $authors),
|
||||
'version' => $data['version'],
|
||||
'phpbb_version' => $data['extra']['phpbb-version'],
|
||||
'direction' => $data['extra']['direction'],
|
||||
'user_lang' => $data['extra']['user-lang'],
|
||||
'plural_rule' => $data['extra']['plural-rule'],
|
||||
'recaptcha_lang'=> $data['extra']['recaptcha-lang'],
|
||||
'iso' => $data['extra']['language-iso'],
|
||||
'name' => $data['extra']['english-name'],
|
||||
'local_name' => $data['extra']['local-name'],
|
||||
'author' => implode(', ', $authors),
|
||||
'version' => $data['version'],
|
||||
'phpbb_version' => $data['extra']['phpbb-version'],
|
||||
'direction' => $data['extra']['direction'],
|
||||
'user_lang' => $data['extra']['user-lang'],
|
||||
'plural_rule' => $data['extra']['plural-rule'],
|
||||
'recaptcha_lang' => $data['extra']['recaptcha-lang'],
|
||||
'turnstile_lang' => $data['extra']['turnstile-lang'] ?? '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -13,6 +13,8 @@
|
||||
|
||||
namespace phpbb\report\controller;
|
||||
|
||||
use phpbb\captcha\plugins\confirm_type;
|
||||
use phpbb\captcha\plugins\plugin_interface;
|
||||
use phpbb\exception\http_exception;
|
||||
use phpbb\report\report_handler_interface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
@@ -131,7 +133,7 @@ class report
|
||||
if ($this->config['enable_post_confirm'] && !$this->user->data['is_registered'])
|
||||
{
|
||||
$captcha = $this->captcha_factory->get_instance($this->config['captcha_plugin']);
|
||||
$captcha->init(CONFIRM_REPORT);
|
||||
$captcha->init(confirm_type::REPORT);
|
||||
}
|
||||
|
||||
//Has the report been cancelled?
|
||||
@@ -140,7 +142,7 @@ class report
|
||||
return new RedirectResponse($redirect_url, 302);
|
||||
}
|
||||
|
||||
// Check CAPTCHA, if the form was submited
|
||||
// Check CAPTCHA, if the form was submitted
|
||||
if (!empty($submit) && isset($captcha))
|
||||
{
|
||||
$captcha_template_array = $this->check_captcha($captcha);
|
||||
@@ -298,18 +300,17 @@ class report
|
||||
/**
|
||||
* Check CAPTCHA
|
||||
*
|
||||
* @param object $captcha A phpBB CAPTCHA object
|
||||
* @param plugin_interface $captcha A phpBB CAPTCHA object
|
||||
* @return array template variables which ensures that CAPTCHA's work correctly
|
||||
*/
|
||||
protected function check_captcha($captcha)
|
||||
protected function check_captcha(plugin_interface $captcha)
|
||||
{
|
||||
$error = array();
|
||||
$captcha_hidden_fields = '';
|
||||
|
||||
$visual_confirmation_response = $captcha->validate();
|
||||
if ($visual_confirmation_response)
|
||||
if ($captcha->validate() !== true)
|
||||
{
|
||||
$error[] = $visual_confirmation_response;
|
||||
$error[] = $captcha->get_error();
|
||||
}
|
||||
|
||||
if (count($error) === 0)
|
||||
|
@@ -183,6 +183,7 @@ class forms extends AbstractExtension
|
||||
'GROUP_ONLY' => (bool) ($form_data['group_only'] ?? false),
|
||||
'SIZE' => (int) ($form_data['size'] ?? 0),
|
||||
'MULTIPLE' => (bool) ($form_data['multiple'] ?? false),
|
||||
'ONCHANGE' => (string) ($form_data['onchange'] ?? ''),
|
||||
]);
|
||||
}
|
||||
catch (\Twig\Error\Error $e)
|
||||
|
Reference in New Issue
Block a user