diff options
Diffstat (limited to 'phpBB')
30 files changed, 1254 insertions, 1221 deletions
diff --git a/phpBB/config/auth_providers.yml b/phpBB/config/auth_providers.yml index d2f22ec477..db7c603bcd 100644 --- a/phpBB/config/auth_providers.yml +++ b/phpBB/config/auth_providers.yml @@ -14,6 +14,7 @@ services:              - @passwords.manager              - @request              - @user +            - @service_container              - %core.root_path%              - %core.php_ext%          tags: diff --git a/phpBB/config/captcha.yml b/phpBB/config/captcha.yml new file mode 100644 index 0000000000..bca37767af --- /dev/null +++ b/phpBB/config/captcha.yml @@ -0,0 +1,62 @@ +parameters: +    tables.captcha_qa_questions: %core.table_prefix%captcha_questions +    tables.captcha_qa_answers: %core.table_prefix%captcha_answers +    tables.captcha_qa_confirm: %core.table_prefix%qa_confirm + +services: +    captcha.factory: +        class: phpbb\captcha\factory +        arguments: +            - @service_container +            - @captcha.plugins.service_collection + +    captcha.plugins.service_collection: +        class: phpbb\di\service_collection +        arguments: +            - @service_container +        tags: +            - { name: service_collection, tag: captcha.plugins } + +    core.captcha.plugins.gd: +        class: phpbb\captcha\plugins\gd +        scope: prototype # scope MUST be prototype for this to work! +        calls: +            - [set_name, [core.captcha.plugins.gd]] +        tags: +            - { name: captcha.plugins } + +    core.captcha.plugins.gd_wave: +        class: phpbb\captcha\plugins\gd_wave +        scope: prototype # scope MUST be prototype for this to work! +        calls: +            - [set_name, [core.captcha.plugins.gd_wave]] +        tags: +            - { name: captcha.plugins } + +    core.captcha.plugins.nogd: +        class: phpbb\captcha\plugins\nogd +        scope: prototype # scope MUST be prototype for this to work! +        calls: +            - [set_name, [core.captcha.plugins.nogd]] +        tags: +            - { name: captcha.plugins } + +    core.captcha.plugins.qa: +        class: phpbb\captcha\plugins\qa +        scope: prototype # scope MUST be prototype for this to work! +        arguments: +            - %tables.captcha_qa_questions% +            - %tables.captcha_qa_answers% +            - %tables.captcha_qa_confirm% +        calls: +            - [set_name, [core.captcha.plugins.qa]] +        tags: +            - { name: captcha.plugins } + +    core.captcha.plugins.recaptcha: +        class: phpbb\captcha\plugins\recaptcha +        scope: prototype # scope MUST be prototype for this to work! +        calls: +            - [set_name, [core.captcha.plugins.recaptcha]] +        tags: +            - { name: captcha.plugins } diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml index 6b06deb256..a588046245 100644 --- a/phpBB/config/services.yml +++ b/phpBB/config/services.yml @@ -10,6 +10,7 @@ imports:      - { resource: mimetype_guessers.yml }      - { resource: passwords.yml }      - { resource: profilefields.yml } +    - { resource: captcha.yml }      - { resource: parameters.yml }  services: diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php index a625005bf8..fa8d8fb6a9 100644 --- a/phpBB/includes/acp/acp_captcha.php +++ b/phpBB/includes/acp/acp_captcha.php @@ -26,12 +26,11 @@ class acp_captcha  	function main($id, $mode)  	{  		global $db, $user, $auth, $template; -		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; +		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container;  		$user->add_lang('acp/board'); -		include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); -		$factory = new phpbb_captcha_factory(); +		$factory = $phpbb_container->get('captcha.factory');  		$captchas = $factory->get_captcha_types();  		$selected = request_var('select_captcha', $config['captcha_plugin']); @@ -47,7 +46,7 @@ class acp_captcha  		// Delegate  		if ($configure)  		{ -			$config_captcha = phpbb_captcha_factory::get_instance($selected); +			$config_captcha = $factory->get_instance($selected);  			$config_captcha->acp_page($id, $this);  		}  		else @@ -79,11 +78,11 @@ class acp_captcha  					// sanity check  					if (isset($captchas['available'][$selected]))  					{ -						$old_captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); +						$old_captcha = $factory->get_instance($config['captcha_plugin']);  						$old_captcha->uninstall();  						set_config('captcha_plugin', $selected); -						$new_captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); +						$new_captcha = $factory->get_instance($config['captcha_plugin']);  						$new_captcha->install();  						add_log('admin', 'LOG_CONFIG_VISUAL'); @@ -114,7 +113,7 @@ class acp_captcha  					$captcha_select .= '<option value="' . $value . '"' . $current . ' class="disabled-option">' . $user->lang($title) . '</option>';  				} -				$demo_captcha = phpbb_captcha_factory::get_instance($selected); +				$demo_captcha = $factory->get_instance($selected);  				foreach ($config_vars as $config_var => $options)  				{ @@ -137,9 +136,9 @@ class acp_captcha  	*/  	function deliver_demo($selected)  	{ -		global $db, $user, $config; +		global $db, $user, $config, $phpbb_container; -		$captcha = phpbb_captcha_factory::get_instance($selected); +		$captcha = $phpbb_container->get('captcha.factory')->get_instance($selected);  		$captcha->init(CONFIRM_REG);  		$captcha->execute_demo(); diff --git a/phpBB/includes/captcha/captcha_factory.php b/phpBB/includes/captcha/captcha_factory.php deleted file mode 100644 index ebeb695282..0000000000 --- a/phpBB/includes/captcha/captcha_factory.php +++ /dev/null @@ -1,100 +0,0 @@ -<?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. -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ -	exit; -} - -/** -* A small class for 3.0.x (no autoloader in 3.0.x) -*/ -class phpbb_captcha_factory -{ -	/** -	* return an instance of class $name in file $name_plugin.php -	*/ -	static public function get_instance($name) -	{ -		global $phpbb_root_path, $phpEx; - -		$name = basename($name); -		if (!class_exists($name)) -		{ -			include($phpbb_root_path . "includes/captcha/plugins/{$name}_plugin." . $phpEx); -		} -		$instance = call_user_func(array($name, 'get_instance')); -		return $instance; -	} - -	/** -	* Call the garbage collector -	*/ -	function garbage_collect($name) -	{ -		global $phpbb_root_path, $phpEx; - -		$name = basename($name); -		if (!class_exists($name)) -		{ -			include($phpbb_root_path . "includes/captcha/plugins/{$name}_plugin." . $phpEx); -		} -		$captcha = self::get_instance($name); -		$captcha->garbage_collect(0); -	} - -	/** -	* return a list of all discovered CAPTCHA plugins -	*/ -	function get_captcha_types() -	{ -		global $phpbb_root_path, $phpEx, $phpbb_extension_manager; - -		$captchas = array( -			'available'		=> array(), -			'unavailable'	=> array(), -		); - -		$finder = $phpbb_extension_manager->get_finder(); -		$captcha_plugin_classes = $finder -			->extension_directory('/captcha') -			->suffix('_plugin') -			->core_path('includes/captcha/plugins/') -			->get_classes(); - -		foreach ($captcha_plugin_classes as $class) -		{ -			// check if this class needs to be loaded in legacy mode -			$old_class = preg_replace('/^phpbb_captcha_plugins_/', '', $class); -			if (file_exists($phpbb_root_path . "includes/captcha/plugins/$old_class.$phpEx") && !class_exists($old_class)) -			{ -				include($phpbb_root_path . "includes/captcha/plugins/$old_class.$phpEx"); -				$class = preg_replace('/_plugin$/', '', $old_class); -			} - -			if (call_user_func(array($class, 'is_available'))) -			{ -				$captchas['available'][$class] = call_user_func(array($class, 'get_name')); -			} -			else -			{ -				$captchas['unavailable'][$class] = call_user_func(array($class, 'get_name')); -			} -		} - -		return $captchas; -	} -} diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php deleted file mode 100644 index b6ccabaa2e..0000000000 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php +++ /dev/null @@ -1,69 +0,0 @@ -<?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. -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ -	exit; -} - -/** -* Placeholder for autoload -*/ -if (!class_exists('phpbb_default_captcha', false)) -{ -	include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); -} - -class phpbb_captcha_gd_wave extends phpbb_default_captcha -{ - -	function phpbb_captcha_gd_wave() -	{ -		global $phpbb_root_path, $phpEx; - -		if (!class_exists('captcha')) -		{ -			include_once($phpbb_root_path . 'includes/captcha/captcha_gd_wave.' . $phpEx); -		} -	} - -	static public function get_instance() -	{ -		return new phpbb_captcha_gd_wave(); -	} - -	static public function is_available() -	{ -		return @extension_loaded('gd'); -	} - -	static public function get_name() -	{ -		return 'CAPTCHA_GD_3D'; -	} - -	function get_class_name() -	{ -		return 'phpbb_captcha_gd_wave'; -	} - -	function acp_page($id, &$module) -	{ -		global $config, $db, $template, $user; - -		trigger_error($user->lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action)); -	} -} diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php deleted file mode 100644 index 64f788a659..0000000000 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php +++ /dev/null @@ -1,70 +0,0 @@ -<?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. -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ -	exit; -} - -/** -* Placeholder for autoload -*/ -if (!class_exists('phpbb_default_captcha', false)) -{ -	include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); -} - -class phpbb_captcha_nogd extends phpbb_default_captcha -{ - -	function phpbb_captcha_nogd() -	{ -		global $phpbb_root_path, $phpEx; - -		if (!class_exists('captcha')) -		{ -			include_once($phpbb_root_path . 'includes/captcha/captcha_non_gd.' . $phpEx); -		} -	} - -	static public function get_instance() -	{ -		$instance = new phpbb_captcha_nogd(); -		return $instance; -	} - -	static public function is_available() -	{ -		return true; -	} - -	static public function get_name() -	{ -		return 'CAPTCHA_NO_GD'; -	} - -	function get_class_name() -	{ -		return 'phpbb_captcha_nogd'; -	} - -	function acp_page($id, &$module) -	{ -		global $user; - -		trigger_error($user->lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action)); -	} -} diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index dcdaf684c0..c838876ddd 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -2751,11 +2751,6 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa  	global $db, $user, $template, $auth, $phpEx, $phpbb_root_path, $config;  	global $request, $phpbb_container; -	if (!class_exists('phpbb_captcha_factory', false)) -	{ -		include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); -	} -  	$err = '';  	// Make sure user->setup() has been called @@ -2865,7 +2860,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa  		{  			case LOGIN_ERROR_ATTEMPTS: -				$captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); +				$captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']);  				$captcha->init(CONFIRM_LOGIN);  				// $captcha->reset(); diff --git a/phpBB/includes/ucp/ucp_confirm.php b/phpBB/includes/ucp/ucp_confirm.php index bcba32cdf6..7392f8dea8 100644 --- a/phpBB/includes/ucp/ucp_confirm.php +++ b/phpBB/includes/ucp/ucp_confirm.php @@ -36,10 +36,9 @@ class ucp_confirm  	function main($id, $mode)  	{ -		global $db, $user, $phpbb_root_path, $config, $phpEx; +		global $db, $user, $phpbb_root_path, $config, $phpEx, $phpbb_container; -		include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); -		$captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); +		$captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']);  		$captcha->init(request_var('type', 0));  		$captcha->execute(); diff --git a/phpBB/includes/ucp/ucp_login_link.php b/phpBB/includes/ucp/ucp_login_link.php index a8762313fd..5ca5df00f7 100644 --- a/phpBB/includes/ucp/ucp_login_link.php +++ b/phpBB/includes/ucp/ucp_login_link.php @@ -181,7 +181,7 @@ class ucp_login_link  	*/  	protected function process_login_result($result)  	{ -		global $config, $request, $template, $user; +		global $config, $request, $template, $user, $phpbb_container;  		$login_error = null; @@ -197,7 +197,7 @@ class ucp_login_link  			{  				case LOGIN_ERROR_ATTEMPTS: -					$captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); +					$captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']);  					$captcha->init(CONFIRM_LOGIN);  					$template->assign_vars(array( diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 97934fc32d..a303197563 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -182,8 +182,7 @@ class ucp_register  		// The CAPTCHA kicks in here. We can't help that the information gets lost on language change.  		if ($config['enable_confirm'])  		{ -			include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); -			$captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); +			$captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']);  			$captcha->init(CONFIRM_REG);  		} diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index b82df84a00..20b211dde9 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -1382,7 +1382,7 @@ class install_install extends module  		if (@extension_loaded('gd'))  		{  			$sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config -				SET config_value = 'phpbb_captcha_gd' +				SET config_value = 'core.captcha.plugins.gd'  				WHERE config_name = 'captcha_plugin'";  			$sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 9cc151f728..5589e10243 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -70,7 +70,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('browser_check', '1  INSERT INTO phpbb_config (config_name, config_value) VALUES ('bump_interval', '10');  INSERT INTO phpbb_config (config_name, config_value) VALUES ('bump_type', 'd');  INSERT INTO phpbb_config (config_name, config_value) VALUES ('cache_gc', '7200'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_plugin', 'phpbb_captcha_nogd'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_plugin', 'core.captcha.plugins.nogd');  INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd', '0');  INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_foreground_noise', '0');  INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_x_grid', '25'); diff --git a/phpBB/phpbb/auth/provider/db.php b/phpBB/phpbb/auth/provider/db.php index 142a47247f..722eeffa9a 100644 --- a/phpBB/phpbb/auth/provider/db.php +++ b/phpBB/phpbb/auth/provider/db.php @@ -27,6 +27,13 @@ class db extends \phpbb\auth\provider\base  	protected $passwords_manager;  	/** +	* DI container +	* +	* @var \Symfony\Component\DependencyInjection\ContainerInterface +	*/ +	protected $phpbb_container; + +	/**  	 * Database Authentication Constructor  	 *  	 * @param	\phpbb\db\driver\driver_interface		$db @@ -34,10 +41,11 @@ class db extends \phpbb\auth\provider\base  	 * @param	\phpbb\passwords\manager	$passwords_manager  	 * @param	\phpbb\request\request		$request  	 * @param	\phpbb\user			$user +	 * @param	\Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container DI container  	 * @param	string				$phpbb_root_path  	 * @param	string				$php_ext  	 */ -	public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request $request, \phpbb\user $user, $phpbb_root_path, $php_ext) +	public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request $request, \phpbb\user $user, \Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container, $phpbb_root_path, $php_ext)  	{  		$this->db = $db;  		$this->config = $config; @@ -46,6 +54,7 @@ class db extends \phpbb\auth\provider\base  		$this->user = $user;  		$this->phpbb_root_path = $phpbb_root_path;  		$this->php_ext = $php_ext; +		$this->phpbb_container = $phpbb_container;  	}  	/** @@ -146,13 +155,8 @@ class db extends \phpbb\auth\provider\base  		// Every auth module is able to define what to do by itself...  		if ($show_captcha)  		{ -			// Visual Confirmation handling -			if (!class_exists('phpbb_captcha_factory', false)) -			{ -				include ($this->phpbb_root_path . 'includes/captcha/captcha_factory.' . $this->php_ext); -			} - -			$captcha = \phpbb_captcha_factory::get_instance($this->config['captcha_plugin']); +			$captcha_factory = $this->phpbb_container->get('captcha.factory'); +			$captcha = $captcha_factory->get_instance($this->config['captcha_plugin']);  			$captcha->init(CONFIRM_LOGIN);  			$vc_response = $captcha->validate($row);  			if ($vc_response) diff --git a/phpBB/phpbb/captcha/char_cube3d.php b/phpBB/phpbb/captcha/char_cube3d.php new file mode 100644 index 0000000000..a712b16dce --- /dev/null +++ b/phpBB/phpbb/captcha/char_cube3d.php @@ -0,0 +1,277 @@ +<?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; + +class char_cube3d +{ +	var $bitmap; +	var $bitmap_width; +	var $bitmap_height; + +	var $basis_matrix = array(array(1, 0, 0), array(0, 1, 0), array(0, 0, 1)); +	var $abs_x = array(1, 0); +	var $abs_y = array(0, 1); +	var $x = 0; +	var $y = 1; +	var $z = 2; +	var $letter = ''; + +	/** +	*/ +	function __construct(&$bitmaps, $letter) +	{ +		$this->bitmap			= $bitmaps['data'][$letter]; +		$this->bitmap_width		= $bitmaps['width']; +		$this->bitmap_height	= $bitmaps['height']; + +		$this->basis_matrix[0][0] = mt_rand(-600, 600); +		$this->basis_matrix[0][1] = mt_rand(-600, 600); +		$this->basis_matrix[0][2] = (mt_rand(0, 1) * 2000) - 1000; +		$this->basis_matrix[1][0] = mt_rand(-1000, 1000); +		$this->basis_matrix[1][1] = mt_rand(-1000, 1000); +		$this->basis_matrix[1][2] = mt_rand(-1000, 1000); + +		$this->normalize($this->basis_matrix[0]); +		$this->normalize($this->basis_matrix[1]); +		$this->basis_matrix[2] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[1]); +		$this->normalize($this->basis_matrix[2]); + +		// $this->basis_matrix[1] might not be (probably isn't) orthogonal to $basis_matrix[0] +		$this->basis_matrix[1] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[2]); +		$this->normalize($this->basis_matrix[1]); + +		// Make sure our cube is facing into the canvas (assuming +z == in) +		for ($i = 0; $i < 3; ++$i) +		{ +			if ($this->basis_matrix[$i][2] < 0) +			{ +				$this->basis_matrix[$i][0] *= -1; +				$this->basis_matrix[$i][1] *= -1; +				$this->basis_matrix[$i][2] *= -1; +			} +		} + +		// Force our "z" basis vector to be the one with greatest absolute z value +		$this->x = 0; +		$this->y = 1; +		$this->z = 2; + +		// Swap "y" with "z" +		if ($this->basis_matrix[1][2] > $this->basis_matrix[2][2]) +		{ +			$this->z = 1; +			$this->y = 2; +		} + +		// Swap "x" with "z" +		if ($this->basis_matrix[0][2] > $this->basis_matrix[$this->z][2]) +		{ +			$this->x = $this->z; +			$this->z = 0; +		} + +		// Still need to determine which of $x,$y are which. +		// wrong orientation if y's y-component is less than it's x-component +		// likewise if x's x-component is less than it's y-component +		// if they disagree, go with the one with the greater weight difference. +		// rotate if positive +		$weight = (abs($this->basis_matrix[$this->x][1]) - abs($this->basis_matrix[$this->x][0])) + (abs($this->basis_matrix[$this->y][0]) - abs($this->basis_matrix[$this->y][1])); + +		// Swap "x" with "y" +		if ($weight > 0) +		{ +			list($this->x, $this->y) = array($this->y, $this->x); +		} + +		$this->abs_x = array($this->basis_matrix[$this->x][0], $this->basis_matrix[$this->x][1]); +		$this->abs_y = array($this->basis_matrix[$this->y][0], $this->basis_matrix[$this->y][1]); + +		if ($this->abs_x[0] < 0) +		{ +			$this->abs_x[0] *= -1; +			$this->abs_x[1] *= -1; +		} + +		if ($this->abs_y[1] > 0) +		{ +			$this->abs_y[0] *= -1; +			$this->abs_y[1] *= -1; +		} + +		$this->letter = $letter; +	} + +	/** +	* Draw a character +	*/ +	function drawchar($scale, $xoff, $yoff, $img, $background, $colours) +	{ +		$width	= $this->bitmap_width; +		$height	= $this->bitmap_height; +		$bitmap	= $this->bitmap; + +		$colour1 = $colours[array_rand($colours)]; +		$colour2 = $colours[array_rand($colours)]; + +		$swapx = ($this->basis_matrix[$this->x][0] > 0); +		$swapy = ($this->basis_matrix[$this->y][1] < 0); + +		for ($y = 0; $y < $height; ++$y) +		{ +			for ($x = 0; $x < $width; ++$x) +			{ +				$xp = ($swapx) ? ($width - $x - 1) : $x; +				$yp = ($swapy) ? ($height - $y - 1) : $y; + +				if ($bitmap[$height - $yp - 1][$xp]) +				{ +					$dx = $this->scale($this->abs_x, ($xp - ($swapx ? ($width / 2) : ($width / 2) - 1)) * $scale); +					$dy = $this->scale($this->abs_y, ($yp - ($swapy ? ($height / 2) : ($height / 2) - 1)) * $scale); +					$xo = $xoff + $dx[0] + $dy[0]; +					$yo = $yoff + $dx[1] + $dy[1]; + +					$origin = array(0, 0, 0); +					$xvec = $this->scale($this->basis_matrix[$this->x], $scale); +					$yvec = $this->scale($this->basis_matrix[$this->y], $scale); +					$face_corner = $this->sum2($xvec, $yvec); + +					$zvec = $this->scale($this->basis_matrix[$this->z], $scale); +					$x_corner = $this->sum2($xvec, $zvec); +					$y_corner = $this->sum2($yvec, $zvec); + +					imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $xvec, $x_corner,$zvec), 4, $colour1); +					imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $yvec, $y_corner,$zvec), 4, $colour2); + +					$face = $this->gen_poly($xo, $yo, $origin, $xvec, $face_corner, $yvec); + +					imagefilledpolygon($img, $face, 4, $background); +					imagepolygon($img, $face, 4, $colour1); +				} +			} +		} +	} + +	/* +	* return a roughly acceptable range of sizes for rendering with this texttype +	*/ +	function range() +	{ +		return array(3, 4); +	} + +	/** +	* Vector length +	*/ +	function vectorlen($vector) +	{ +		return sqrt(pow($vector[0], 2) + pow($vector[1], 2) + pow($vector[2], 2)); +	} + +	/** +	* Normalize +	*/ +	function normalize(&$vector, $length = 1) +	{ +		$length = (( $length < 1) ? 1 : $length); +		$length /= $this->vectorlen($vector); +		$vector[0] *= $length; +		$vector[1] *= $length; +		$vector[2] *= $length; +	} + +	/** +	*/ +	function cross_product($vector1, $vector2) +	{ +		$retval = array(0, 0, 0); +		$retval[0] =  (($vector1[1] * $vector2[2]) - ($vector1[2] * $vector2[1])); +		$retval[1] = -(($vector1[0] * $vector2[2]) - ($vector1[2] * $vector2[0])); +		$retval[2] =  (($vector1[0] * $vector2[1]) - ($vector1[1] * $vector2[0])); + +		return $retval; +	} + +	/** +	*/ +	function sum($vector1, $vector2) +	{ +		return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1], $vector1[2] + $vector2[2]); +	} + +	/** +	*/ +	function sum2($vector1, $vector2) +	{ +		return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1]); +	} + +	/** +	*/ +	function scale($vector, $length) +	{ +		if (sizeof($vector) == 2) +		{ +			return array($vector[0] * $length, $vector[1] * $length); +		} + +		return array($vector[0] * $length, $vector[1] * $length, $vector[2] * $length); +	} + +	/** +	*/ +	function gen_poly($xoff, $yoff, &$vec1, &$vec2, &$vec3, &$vec4) +	{ +		$poly = array(); +		$poly[0] = $xoff + $vec1[0]; +		$poly[1] = $yoff + $vec1[1]; +		$poly[2] = $xoff + $vec2[0]; +		$poly[3] = $yoff + $vec2[1]; +		$poly[4] = $xoff + $vec3[0]; +		$poly[5] = $yoff + $vec3[1]; +		$poly[6] = $xoff + $vec4[0]; +		$poly[7] = $yoff + $vec4[1]; + +		return $poly; +	} + +	/** +	* dimensions +	*/ +	function dimensions($size) +	{ +		$xn = $this->scale($this->basis_matrix[$this->x], -($this->bitmap_width / 2) * $size); +		$xp = $this->scale($this->basis_matrix[$this->x], ($this->bitmap_width / 2) * $size); +		$yn = $this->scale($this->basis_matrix[$this->y], -($this->bitmap_height / 2) * $size); +		$yp = $this->scale($this->basis_matrix[$this->y], ($this->bitmap_height / 2) * $size); + +		$p = array(); +		$p[0] = $this->sum2($xn, $yn); +		$p[1] = $this->sum2($xp, $yn); +		$p[2] = $this->sum2($xp, $yp); +		$p[3] = $this->sum2($xn, $yp); + +		$min_x = $max_x = $p[0][0]; +		$min_y = $max_y = $p[0][1]; + +		for ($i = 1; $i < 4; ++$i) +		{ +			$min_x = ($min_x > $p[$i][0]) ? $p[$i][0] : $min_x; +			$min_y = ($min_y > $p[$i][1]) ? $p[$i][1] : $min_y; +			$max_x = ($max_x < $p[$i][0]) ? $p[$i][0] : $max_x; +			$max_y = ($max_y < $p[$i][1]) ? $p[$i][1] : $max_y; +		} + +		return array($min_x, $min_y, $max_x, $max_y); +	} +} diff --git a/phpBB/phpbb/captcha/colour_manager.php b/phpBB/phpbb/captcha/colour_manager.php new file mode 100644 index 0000000000..6ca3c3fd2c --- /dev/null +++ b/phpBB/phpbb/captcha/colour_manager.php @@ -0,0 +1,527 @@ +<?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; + +class colour_manager +{ +	var $img; +	var $mode; +	var $colours; +	var $named_colours; + +	/** +	* Create the colour manager, link it to the image resource +	*/ +	function __construct($img, $background = false, $mode = 'ahsv') +	{ +		$this->img = $img; +		$this->mode = $mode; +		$this->colours = array(); +		$this->named_colours = array(); + +		if ($background !== false) +		{ +			$bg = $this->allocate_named('background', $background); +			imagefill($this->img, 0, 0, $bg); +		} +	} + +	/** +	* Lookup a named colour resource +	*/ +	function get_resource($named_colour) +	{ +		if (isset($this->named_colours[$named_colour])) +		{ +			return $this->named_colours[$named_colour]; +		} + +		if (isset($this->named_rgb[$named_colour])) +		{ +			return $this->allocate_named($named_colour, $this->named_rgb[$named_colour], 'rgb'); +		} + +		return false; +	} + +	/** +	* Assign a name to a colour resource +	*/ +	function name_colour($name, $resource) +	{ +		$this->named_colours[$name] = $resource; +	} + +	/** +	* names and allocates a colour resource +	*/ +	function allocate_named($name, $colour, $mode = false) +	{ +		$resource = $this->allocate($colour, $mode); + +		if ($resource !== false) +		{ +			$this->name_colour($name, $resource); +		} +		return $resource; +	} + +	/** +	* allocates a specified colour into the image +	*/ +	function allocate($colour, $mode = false) +	{ +		if ($mode === false) +		{ +			$mode = $this->mode; +		} + +		if (!is_array($colour)) +		{ +			if (isset($this->named_rgb[$colour])) +			{ +				return $this->allocate_named($colour, $this->named_rgb[$colour], 'rgb'); +			} + +			if (!is_int($colour)) +			{ +				return false; +			} + +			$mode = 'rgb'; +			$colour = array(255 & ($colour >> 16), 255 & ($colour >>  8), 255 & $colour); +		} + +		if (isset($colour['mode'])) +		{ +			$mode = $colour['mode']; +			unset($colour['mode']); +		} + +		if (isset($colour['random'])) +		{ +			unset($colour['random']); +			// everything else is params +			return $this->random_colour($colour, $mode); +		} + +		$rgb		= $this->model_convert($colour, $mode, 'rgb'); +		$store		= ($this->mode == 'rgb') ? $rgb : $this->model_convert($colour, $mode, $this->mode); +		$resource	= imagecolorallocate($this->img, $rgb[0], $rgb[1], $rgb[2]); +		$this->colours[$resource] = $store; + +		return $resource; +	} + +	/** +	* randomly generates a colour, with optional params +	*/ +	function random_colour($params = array(), $mode = false) +	{ +		if ($mode === false) +		{ +			$mode = $this->mode; +		} + +		switch ($mode) +		{ +			case 'rgb': +				// @TODO random rgb generation. do we intend to do this, or is it just too tedious? +				break; + +			case 'ahsv': +			case 'hsv': +			default: + +				$default_params = array( +					'hue_bias'			=> false,	// degree / 'r'/'g'/'b'/'c'/'m'/'y'   /'o' +					'hue_range'			=> false,	// if hue bias, then difference range +/- from bias +					'min_saturation'	=> 30,		// 0 - 100 +					'max_saturation'	=> 80,		// 0 - 100 +					'min_value'			=> 30,		// 0 - 100 +					'max_value'			=> 80,		// 0 - 100 +				); + +				$alt = ($mode == 'ahsv') ? true : false; +				$params = array_merge($default_params, $params); + +				$min_hue		= 0; +				$max_hue		= 359; +				$min_saturation	= max(0, $params['min_saturation']); +				$max_saturation	= min(100, $params['max_saturation']); +				$min_value		= max(0, $params['min_value']); +				$max_value		= min(100, $params['max_value']); + +				if ($params['hue_bias'] !== false) +				{ +					if (is_numeric($params['hue_bias'])) +					{ +						$h = intval($params['hue_bias']) % 360; +					} +					else +					{ +						switch ($params['hue_bias']) +						{ +							case 'o': +								$h = $alt ?  60 :  30; +								break; + +							case 'y': +								$h = $alt ? 120 :  60; +								break; + +							case 'g': +								$h = $alt ? 180 : 120; +								break; + +							case 'c': +								$h = $alt ? 210 : 180; +								break; + +							case 'b': +								$h = 240; +								break; + +							case 'm': +								$h = 300; +								break; + +							case 'r': +							default: +								$h = 0; +								break; +						} +					} + +					$min_hue = $h + 360; +					$max_hue = $h + 360; + +					if ($params['hue_range']) +					{ +						$min_hue -= min(180, $params['hue_range']); +						$max_hue += min(180, $params['hue_range']); +					} +				} + +				$h = mt_rand($min_hue, $max_hue); +				$s = mt_rand($min_saturation, $max_saturation); +				$v = mt_rand($min_value, $max_value); + +				return $this->allocate(array($h, $s, $v), $mode); + +				break; +		} +	} + +	/** +	*/ +	function colour_scheme($resource, $include_original = true) +	{ +		$mode = 'hsv'; + +		if (($pre = $this->get_resource($resource)) !== false) +		{ +			$resource = $pre; +		} + +		$colour = $this->model_convert($this->colours[$resource], $this->mode, $mode); +		$results = ($include_original) ? array($resource) : array(); +		$colour2 = $colour3 = $colour4 = $colour; +		$colour2[0] += 150; +		$colour3[0] += 180; +		$colour4[0] += 210; + +		$results[] = $this->allocate($colour2, $mode); +		$results[] = $this->allocate($colour3, $mode); +		$results[] = $this->allocate($colour4, $mode); + +		return $results; +	} + +	/** +	*/ +	function mono_range($resource, $count = 5, $include_original = true) +	{ +		if (is_array($resource)) +		{ +			$results = array(); +			for ($i = 0, $size = sizeof($resource); $i < $size; ++$i) +			{ +				$results = array_merge($results, $this->mono_range($resource[$i], $count, $include_original)); +			} +			return $results; +		} + +		$mode = (in_array($this->mode, array('hsv', 'ahsv'), true) ? $this->mode : 'ahsv'); +		if (($pre = $this->get_resource($resource)) !== false) +		{ +			$resource = $pre; +		} + +		$colour = $this->model_convert($this->colours[$resource], $this->mode, $mode); + +		$results = array(); +		if ($include_original) +		{ +			$results[] = $resource; +			$count--; +		} + +		// This is a hard problem. I chicken out and try to maintain readability at the cost of less randomness. + +		while ($count > 0) +		{ +			$colour[1] = ($colour[1] + mt_rand(40,60)) % 99; +			$colour[2] = ($colour[2] + mt_rand(40,60)); +			$results[] = $this->allocate($colour, $mode); +			$count--; +		} +		return $results; +	} + +	/** +	* Convert from one colour model to another +	*/ +	function model_convert($colour, $from_model, $to_model) +	{ +		if ($from_model == $to_model) +		{ +			return $colour; +		} + +		switch ($to_model) +		{ +			case 'hsv': + +				switch ($from_model) +				{ +					case 'ahsv': +						return $this->ah2h($colour); +						break; + +					case 'rgb': +						return $this->rgb2hsv($colour); +						break; +				} +				break; + +			case 'ahsv': + +				switch ($from_model) +				{ +					case 'hsv': +						return $this->h2ah($colour); +						break; + +					case 'rgb': +						return $this->h2ah($this->rgb2hsv($colour)); +						break; +				} +				break; + +			case 'rgb': +				switch ($from_model) +				{ +					case 'hsv': +						return $this->hsv2rgb($colour); +						break; + +					case 'ahsv': +						return $this->hsv2rgb($this->ah2h($colour)); +						break; +				} +				break; +		} +		return false; +	} + +	/** +	* Slightly altered from wikipedia's algorithm +	*/ +	function hsv2rgb($hsv) +	{ +		$this->normalize_hue($hsv[0]); + +		$h = $hsv[0]; +		$s = min(1, max(0, $hsv[1] / 100)); +		$v = min(1, max(0, $hsv[2] / 100)); + +		// calculate hue sector +		$hi = floor($hsv[0] / 60); + +		// calculate opposite colour +		$p = $v * (1 - $s); + +		// calculate distance between hex vertices +		$f = ($h / 60) - $hi; + +		// coming in or going out? +		if (!($hi & 1)) +		{ +			$f = 1 - $f; +		} + +		// calculate adjacent colour +		$q = $v * (1 - ($f * $s)); + +		switch ($hi) +		{ +			case 0: +				$rgb = array($v, $q, $p); +				break; + +			case 1: +				$rgb = array($q, $v, $p); +				break; + +			case 2: +				$rgb = array($p, $v, $q); +				break; + +			case 3: +				$rgb = array($p, $q, $v); +				break; + +			case 4: +				$rgb = array($q, $p, $v); +				break; + +			case 5: +				$rgb = array($v, $p, $q); +				break; + +			default: +				return array(0, 0, 0); +				break; +		} + +		return array(255 * $rgb[0], 255 * $rgb[1], 255 * $rgb[2]); +	} + +	/** +	* (more than) Slightly altered from wikipedia's algorithm +	*/ +	function rgb2hsv($rgb) +	{ +		$r = min(255, max(0, $rgb[0])); +		$g = min(255, max(0, $rgb[1])); +		$b = min(255, max(0, $rgb[2])); +		$max = max($r, $g, $b); +		$min = min($r, $g, $b); + +		$v = $max / 255; +		$s = (!$max) ? 0 : 1 - ($min / $max); + +		// if max - min is 0, we want hue to be 0 anyway. +		$h = $max - $min; + +		if ($h) +		{ +			switch ($max) +			{ +				case $g: +					$h = 120 + (60 * ($b - $r) / $h); +					break; + +				case $b: +					$h = 240 + (60 * ($r - $g) / $h); +					break; + +				case $r: +					$h = 360 + (60 * ($g - $b) / $h); +					break; +			} +		} +		$this->normalize_hue($h); + +		return array($h, $s * 100, $v * 100); +	} + +	/** +	*/ +	function normalize_hue(&$hue) +	{ +		$hue %= 360; + +		if ($hue < 0) +		{ +			$hue += 360; +		} +	} + +	/** +	* Alternate hue to hue +	*/ +	function ah2h($ahue) +	{ +		if (is_array($ahue)) +		{ +			$ahue[0] = $this->ah2h($ahue[0]); +			return $ahue; +		} +		$this->normalize_hue($ahue); + +		// blue through red is already ok +		if ($ahue >= 240) +		{ +			return $ahue; +		} + +		// ahue green is at 180 +		if ($ahue >= 180) +		{ +			// return (240 - (2 * (240 - $ahue))); +			return (2 * $ahue) - 240; // equivalent +		} + +		// ahue yellow is at 120   (RYB rather than RGB) +		if ($ahue >= 120) +		{ +			return $ahue - 60; +		} + +		return $ahue / 2; +	} + +	/** +	* hue to Alternate hue +	*/ +	function h2ah($hue) +	{ +		if (is_array($hue)) +		{ +			$hue[0] = $this->h2ah($hue[0]); +			return $hue; +		} +		$this->normalize_hue($hue); + +		// blue through red is already ok +		if ($hue >= 240) +		{ +			return $hue; +		} +		else if ($hue <= 60) +		{ +			return $hue * 2; +		} +		else if ($hue <= 120) +		{ +			return $hue + 60; +		} +		else +		{ +			return ($hue + 240) / 2; +		} +	} +} diff --git a/phpBB/phpbb/captcha/factory.php b/phpBB/phpbb/captcha/factory.php new file mode 100644 index 0000000000..dd44aca8bb --- /dev/null +++ b/phpBB/phpbb/captcha/factory.php @@ -0,0 +1,88 @@ +<?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; + +class factory +{ +	/** +	* @var \Symfony\Component\DependencyInjection\ContainerInterface +	*/ +	private $container; + +	/** +	* @var \phpbb\di\service_collection +	*/ +	private $plugins; + +	/** +	* Constructor +	* +	* @param \Symfony\Component\DependencyInjection\ContainerInterface $container +	* @param \phpbb\di\service_collection                              $plugins +	*/ +	public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, \phpbb\di\service_collection $plugins) +	{ +		$this->container = $container; +		$this->plugins = $plugins; +	} + +	/** +	* Return a new instance of a given plugin +	* +	* @param $name +	* @return object +	*/ +	public function get_instance($name) +	{ +		return $this->container->get($name); +	} + +	/** +	* Call the garbage collector +	* +	* @param string $name The name to the captcha service. +	*/ +	function garbage_collect($name) +	{ +		$captcha = $this->get_instance($name); +		$captcha->garbage_collect(0); +	} + +	/** +	* Return a list of all registered CAPTCHA plugins +	* +	* @returns array +	*/ +	function get_captcha_types() +	{ +		$captchas = array( +			'available'		=> array(), +			'unavailable'	=> array(), +		); + +		foreach ($this->plugins as $plugin => $plugin_instance) +		{ +			if ($plugin_instance->is_available()) +			{ +				$captchas['available'][$plugin] = $plugin_instance->get_name(); +			} +			else +			{ +				$captchas['unavailable'][$plugin] = $plugin_instance->get_name(); +			} +		} + +		return $captchas; +	} +} diff --git a/phpBB/includes/captcha/captcha_gd.php b/phpBB/phpbb/captcha/gd.php index 7e37cc33f9..652df28f8a 100644 --- a/phpBB/includes/captcha/captcha_gd.php +++ b/phpBB/phpbb/captcha/gd.php @@ -11,15 +11,9 @@  *  */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ -	exit; -} +namespace phpbb\captcha; -class captcha +class gd  {  	var $width = 360;  	var $height = 96; @@ -1851,779 +1845,3 @@ class captcha  		);  	}  } - -class char_cube3d -{ -	var $bitmap; -	var $bitmap_width; -	var $bitmap_height; - -	var $basis_matrix = array(array(1, 0, 0), array(0, 1, 0), array(0, 0, 1)); -	var $abs_x = array(1, 0); -	var $abs_y = array(0, 1); -	var $x = 0; -	var $y = 1; -	var $z = 2; -	var $letter = ''; - -	/** -	*/ -	function char_cube3d(&$bitmaps, $letter) -	{ -		$this->bitmap			= $bitmaps['data'][$letter]; -		$this->bitmap_width		= $bitmaps['width']; -		$this->bitmap_height	= $bitmaps['height']; - -		$this->basis_matrix[0][0] = mt_rand(-600, 600); -		$this->basis_matrix[0][1] = mt_rand(-600, 600); -		$this->basis_matrix[0][2] = (mt_rand(0, 1) * 2000) - 1000; -		$this->basis_matrix[1][0] = mt_rand(-1000, 1000); -		$this->basis_matrix[1][1] = mt_rand(-1000, 1000); -		$this->basis_matrix[1][2] = mt_rand(-1000, 1000); - -		$this->normalize($this->basis_matrix[0]); -		$this->normalize($this->basis_matrix[1]); -		$this->basis_matrix[2] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[1]); -		$this->normalize($this->basis_matrix[2]); - -		// $this->basis_matrix[1] might not be (probably isn't) orthogonal to $basis_matrix[0] -		$this->basis_matrix[1] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[2]); -		$this->normalize($this->basis_matrix[1]); - -		// Make sure our cube is facing into the canvas (assuming +z == in) -		for ($i = 0; $i < 3; ++$i) -		{ -			if ($this->basis_matrix[$i][2] < 0) -			{ -				$this->basis_matrix[$i][0] *= -1; -				$this->basis_matrix[$i][1] *= -1; -				$this->basis_matrix[$i][2] *= -1; -			} -		} - -		// Force our "z" basis vector to be the one with greatest absolute z value -		$this->x = 0; -		$this->y = 1; -		$this->z = 2; - -		// Swap "y" with "z" -		if ($this->basis_matrix[1][2] > $this->basis_matrix[2][2]) -		{ -			$this->z = 1; -			$this->y = 2; -		} - -		// Swap "x" with "z" -		if ($this->basis_matrix[0][2] > $this->basis_matrix[$this->z][2]) -		{ -			$this->x = $this->z; -			$this->z = 0; -		} - -		// Still need to determine which of $x,$y are which. -		// wrong orientation if y's y-component is less than it's x-component -		// likewise if x's x-component is less than it's y-component -		// if they disagree, go with the one with the greater weight difference. -		// rotate if positive -		$weight = (abs($this->basis_matrix[$this->x][1]) - abs($this->basis_matrix[$this->x][0])) + (abs($this->basis_matrix[$this->y][0]) - abs($this->basis_matrix[$this->y][1])); - -		// Swap "x" with "y" -		if ($weight > 0) -		{ -			list($this->x, $this->y) = array($this->y, $this->x); -		} - -		$this->abs_x = array($this->basis_matrix[$this->x][0], $this->basis_matrix[$this->x][1]); -		$this->abs_y = array($this->basis_matrix[$this->y][0], $this->basis_matrix[$this->y][1]); - -		if ($this->abs_x[0] < 0) -		{ -			$this->abs_x[0] *= -1; -			$this->abs_x[1] *= -1; -		} - -		if ($this->abs_y[1] > 0) -		{ -			$this->abs_y[0] *= -1; -			$this->abs_y[1] *= -1; -		} - -		$this->letter = $letter; -	} - -	/** -	* Draw a character -	*/ -	function drawchar($scale, $xoff, $yoff, $img, $background, $colours) -	{ -		$width	= $this->bitmap_width; -		$height	= $this->bitmap_height; -		$bitmap	= $this->bitmap; - -		$colour1 = $colours[array_rand($colours)]; -		$colour2 = $colours[array_rand($colours)]; - -		$swapx = ($this->basis_matrix[$this->x][0] > 0); -		$swapy = ($this->basis_matrix[$this->y][1] < 0); - -		for ($y = 0; $y < $height; ++$y) -		{ -			for ($x = 0; $x < $width; ++$x) -			{ -				$xp = ($swapx) ? ($width - $x - 1) : $x; -				$yp = ($swapy) ? ($height - $y - 1) : $y; - -				if ($bitmap[$height - $yp - 1][$xp]) -				{ -					$dx = $this->scale($this->abs_x, ($xp - ($swapx ? ($width / 2) : ($width / 2) - 1)) * $scale); -					$dy = $this->scale($this->abs_y, ($yp - ($swapy ? ($height / 2) : ($height / 2) - 1)) * $scale); -					$xo = $xoff + $dx[0] + $dy[0]; -					$yo = $yoff + $dx[1] + $dy[1]; - -					$origin = array(0, 0, 0); -					$xvec = $this->scale($this->basis_matrix[$this->x], $scale); -					$yvec = $this->scale($this->basis_matrix[$this->y], $scale); -					$face_corner = $this->sum2($xvec, $yvec); - -					$zvec = $this->scale($this->basis_matrix[$this->z], $scale); -					$x_corner = $this->sum2($xvec, $zvec); -					$y_corner = $this->sum2($yvec, $zvec); - -					imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $xvec, $x_corner,$zvec), 4, $colour1); -					imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $yvec, $y_corner,$zvec), 4, $colour2); - -					$face = $this->gen_poly($xo, $yo, $origin, $xvec, $face_corner, $yvec); - -					imagefilledpolygon($img, $face, 4, $background); -					imagepolygon($img, $face, 4, $colour1); -				} -			} -		} -	} - -	/* -	* return a roughly acceptable range of sizes for rendering with this texttype -	*/ -	function range() -	{ -		return array(3, 4); -	} - -	/** -	* Vector length -	*/ -	function vectorlen($vector) -	{ -		return sqrt(pow($vector[0], 2) + pow($vector[1], 2) + pow($vector[2], 2)); -	} - -	/** -	* Normalize -	*/ -	function normalize(&$vector, $length = 1) -	{ -		$length = (( $length < 1) ? 1 : $length); -		$length /= $this->vectorlen($vector); -		$vector[0] *= $length; -		$vector[1] *= $length; -		$vector[2] *= $length; -	} - -	/** -	*/ -	function cross_product($vector1, $vector2) -	{ -		$retval = array(0, 0, 0); -		$retval[0] =  (($vector1[1] * $vector2[2]) - ($vector1[2] * $vector2[1])); -		$retval[1] = -(($vector1[0] * $vector2[2]) - ($vector1[2] * $vector2[0])); -		$retval[2] =  (($vector1[0] * $vector2[1]) - ($vector1[1] * $vector2[0])); - -		return $retval; -	} - -	/** -	*/ -	function sum($vector1, $vector2) -	{ -		return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1], $vector1[2] + $vector2[2]); -	} - -	/** -	*/ -	function sum2($vector1, $vector2) -	{ -		return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1]); -	} - -	/** -	*/ -	function scale($vector, $length) -	{ -		if (sizeof($vector) == 2) -		{ -			return array($vector[0] * $length, $vector[1] * $length); -		} - -		return array($vector[0] * $length, $vector[1] * $length, $vector[2] * $length); -	} - -	/** -	*/ -	function gen_poly($xoff, $yoff, &$vec1, &$vec2, &$vec3, &$vec4) -	{ -		$poly = array(); -		$poly[0] = $xoff + $vec1[0]; -		$poly[1] = $yoff + $vec1[1]; -		$poly[2] = $xoff + $vec2[0]; -		$poly[3] = $yoff + $vec2[1]; -		$poly[4] = $xoff + $vec3[0]; -		$poly[5] = $yoff + $vec3[1]; -		$poly[6] = $xoff + $vec4[0]; -		$poly[7] = $yoff + $vec4[1]; - -		return $poly; -	} - -	/** -	* dimensions -	*/ -	function dimensions($size) -	{ -		$xn = $this->scale($this->basis_matrix[$this->x], -($this->bitmap_width / 2) * $size); -		$xp = $this->scale($this->basis_matrix[$this->x], ($this->bitmap_width / 2) * $size); -		$yn = $this->scale($this->basis_matrix[$this->y], -($this->bitmap_height / 2) * $size); -		$yp = $this->scale($this->basis_matrix[$this->y], ($this->bitmap_height / 2) * $size); - -		$p = array(); -		$p[0] = $this->sum2($xn, $yn); -		$p[1] = $this->sum2($xp, $yn); -		$p[2] = $this->sum2($xp, $yp); -		$p[3] = $this->sum2($xn, $yp); - -		$min_x = $max_x = $p[0][0]; -		$min_y = $max_y = $p[0][1]; - -		for ($i = 1; $i < 4; ++$i) -		{ -			$min_x = ($min_x > $p[$i][0]) ? $p[$i][0] : $min_x; -			$min_y = ($min_y > $p[$i][1]) ? $p[$i][1] : $min_y; -			$max_x = ($max_x < $p[$i][0]) ? $p[$i][0] : $max_x; -			$max_y = ($max_y < $p[$i][1]) ? $p[$i][1] : $max_y; -		} - -		return array($min_x, $min_y, $max_x, $max_y); -	} -} - -class colour_manager -{ -	var $img; -	var $mode; -	var $colours; -	var $named_colours; - -	/** -	* Create the colour manager, link it to the image resource -	*/ -	function colour_manager($img, $background = false, $mode = 'ahsv') -	{ -		$this->img = $img; -		$this->mode = $mode; -		$this->colours = array(); -		$this->named_colours = array(); - -		if ($background !== false) -		{ -			$bg = $this->allocate_named('background', $background); -			imagefill($this->img, 0, 0, $bg); -		} -	} - -	/** -	* Lookup a named colour resource -	*/ -	function get_resource($named_colour) -	{ -		if (isset($this->named_colours[$named_colour])) -		{ -			return $this->named_colours[$named_colour]; -		} - -		if (isset($this->named_rgb[$named_colour])) -		{ -			return $this->allocate_named($named_colour, $this->named_rgb[$named_colour], 'rgb'); -		} - -		return false; -	} - -	/** -	* Assign a name to a colour resource -	*/ -	function name_colour($name, $resource) -	{ -		$this->named_colours[$name] = $resource; -	} - -	/** -	* names and allocates a colour resource -	*/ -	function allocate_named($name, $colour, $mode = false) -	{ -		$resource = $this->allocate($colour, $mode); - -		if ($resource !== false) -		{ -			$this->name_colour($name, $resource); -		} -		return $resource; -	} - -	/** -	* allocates a specified colour into the image -	*/ -	function allocate($colour, $mode = false) -	{ -		if ($mode === false) -		{ -			$mode = $this->mode; -		} - -		if (!is_array($colour)) -		{ -			if (isset($this->named_rgb[$colour])) -			{ -				return $this->allocate_named($colour, $this->named_rgb[$colour], 'rgb'); -			} - -			if (!is_int($colour)) -			{ -				return false; -			} - -			$mode = 'rgb'; -			$colour = array(255 & ($colour >> 16), 255 & ($colour >>  8), 255 & $colour); -		} - -		if (isset($colour['mode'])) -		{ -			$mode = $colour['mode']; -			unset($colour['mode']); -		} - -		if (isset($colour['random'])) -		{ -			unset($colour['random']); -			// everything else is params -			return $this->random_colour($colour, $mode); -		} - -		$rgb		= $this->model_convert($colour, $mode, 'rgb'); -		$store		= ($this->mode == 'rgb') ? $rgb : $this->model_convert($colour, $mode, $this->mode); -		$resource	= imagecolorallocate($this->img, $rgb[0], $rgb[1], $rgb[2]); -		$this->colours[$resource] = $store; - -		return $resource; -	} - -	/** -	* randomly generates a colour, with optional params -	*/ -	function random_colour($params = array(), $mode = false) -	{ -		if ($mode === false) -		{ -			$mode = $this->mode; -		} - -		switch ($mode) -		{ -			case 'rgb': -				// @TODO random rgb generation. do we intend to do this, or is it just too tedious? -			break; - -			case 'ahsv': -			case 'hsv': -			default: - -				$default_params = array( -					'hue_bias'			=> false,	// degree / 'r'/'g'/'b'/'c'/'m'/'y'   /'o' -					'hue_range'			=> false,	// if hue bias, then difference range +/- from bias -					'min_saturation'	=> 30,		// 0 - 100 -					'max_saturation'	=> 80,		// 0 - 100 -					'min_value'			=> 30,		// 0 - 100 -					'max_value'			=> 80,		// 0 - 100 -				); - -				$alt = ($mode == 'ahsv') ? true : false; -				$params = array_merge($default_params, $params); - -				$min_hue		= 0; -				$max_hue		= 359; -				$min_saturation	= max(0, $params['min_saturation']); -				$max_saturation	= min(100, $params['max_saturation']); -				$min_value		= max(0, $params['min_value']); -				$max_value		= min(100, $params['max_value']); - -				if ($params['hue_bias'] !== false) -				{ -					if (is_numeric($params['hue_bias'])) -					{ -						$h = intval($params['hue_bias']) % 360; -					} -					else -					{ -						switch ($params['hue_bias']) -						{ -							case 'o': -								$h = $alt ?  60 :  30; -							break; - -							case 'y': -								$h = $alt ? 120 :  60; -							break; - -							case 'g': -								$h = $alt ? 180 : 120; -							break; - -							case 'c': -								$h = $alt ? 210 : 180; -							break; - -							case 'b': -								$h = 240; -							break; - -							case 'm': -								$h = 300; -							break; - -							case 'r': -							default: -								$h = 0; -							break; -						} -					} - -					$min_hue = $h + 360; -					$max_hue = $h + 360; - -					if ($params['hue_range']) -					{ -						$min_hue -= min(180, $params['hue_range']); -						$max_hue += min(180, $params['hue_range']); -					} -				} - -				$h = mt_rand($min_hue, $max_hue); -				$s = mt_rand($min_saturation, $max_saturation); -				$v = mt_rand($min_value, $max_value); - -				return $this->allocate(array($h, $s, $v), $mode); - -			break; -		} -	} - -	/** -	*/ -	function colour_scheme($resource, $include_original = true) -	{ -		$mode = 'hsv'; - -		if (($pre = $this->get_resource($resource)) !== false) -		{ -			$resource = $pre; -		} - -		$colour = $this->model_convert($this->colours[$resource], $this->mode, $mode); -		$results = ($include_original) ? array($resource) : array(); -		$colour2 = $colour3 = $colour4 = $colour; -		$colour2[0] += 150; -		$colour3[0] += 180; -		$colour4[0] += 210; - -		$results[] = $this->allocate($colour2, $mode); -		$results[] = $this->allocate($colour3, $mode); -		$results[] = $this->allocate($colour4, $mode); - -		return $results; -	} - -	/** -	*/ -	function mono_range($resource, $count = 5, $include_original = true) -	{ -		if (is_array($resource)) -		{ -			$results = array(); -			for ($i = 0, $size = sizeof($resource); $i < $size; ++$i) -			{ -				$results = array_merge($results, $this->mono_range($resource[$i], $count, $include_original)); -			} -			return $results; -		} - -		$mode = (in_array($this->mode, array('hsv', 'ahsv'), true) ? $this->mode : 'ahsv'); -		if (($pre = $this->get_resource($resource)) !== false) -		{ -			$resource = $pre; -		} - -		$colour = $this->model_convert($this->colours[$resource], $this->mode, $mode); - -		$results = array(); -		if ($include_original) -		{ -			$results[] = $resource; -			$count--; -		} - -		// This is a hard problem. I chicken out and try to maintain readability at the cost of less randomness. - -		while ($count > 0) -		{ -			$colour[1] = ($colour[1] + mt_rand(40,60)) % 99; -			$colour[2] = ($colour[2] + mt_rand(40,60)); -			$results[] = $this->allocate($colour, $mode); -			$count--; -		} -		return $results; -	} - -	/** -	* Convert from one colour model to another -	*/ -	function model_convert($colour, $from_model, $to_model) -	{ -		if ($from_model == $to_model) -		{ -			return $colour; -		} - -		switch ($to_model) -		{ -			case 'hsv': - -				switch ($from_model) -				{ -					case 'ahsv': -						return $this->ah2h($colour); -					break; - -					case 'rgb': -						return $this->rgb2hsv($colour); -					break; -				} -			break; - -			case 'ahsv': - -				switch ($from_model) -				{ -					case 'hsv': -						return $this->h2ah($colour); -					break; - -					case 'rgb': -						return $this->h2ah($this->rgb2hsv($colour)); -					break; -				} -			break; - -			case 'rgb': -				switch ($from_model) -				{ -					case 'hsv': -						return $this->hsv2rgb($colour); -					break; - -					case 'ahsv': -						return $this->hsv2rgb($this->ah2h($colour)); -					break; -				} -			break; -		} -		return false; -	} - -	/** -	* Slightly altered from wikipedia's algorithm -	*/ -	function hsv2rgb($hsv) -	{ -		$this->normalize_hue($hsv[0]); - -		$h = $hsv[0]; -		$s = min(1, max(0, $hsv[1] / 100)); -		$v = min(1, max(0, $hsv[2] / 100)); - -		// calculate hue sector -		$hi = floor($hsv[0] / 60); - -		// calculate opposite colour -		$p = $v * (1 - $s); - -		// calculate distance between hex vertices -		$f = ($h / 60) - $hi; - -		// coming in or going out? -		if (!($hi & 1)) -		{ -			$f = 1 - $f; -		} - -		// calculate adjacent colour -		$q = $v * (1 - ($f * $s)); - -		switch ($hi) -		{ -			case 0: -				$rgb = array($v, $q, $p); -			break; - -			case 1: -				$rgb = array($q, $v, $p); -			break; - -			case 2: -				$rgb = array($p, $v, $q); -			break; - -			case 3: -				$rgb = array($p, $q, $v); -			break; - -			case 4: -				$rgb = array($q, $p, $v); -			break; - -			case 5: -				$rgb = array($v, $p, $q); -			break; - -			default: -				return array(0, 0, 0); -			break; -		} - -		return array(255 * $rgb[0], 255 * $rgb[1], 255 * $rgb[2]); -	} - -	/** -	* (more than) Slightly altered from wikipedia's algorithm -	*/ -	function rgb2hsv($rgb) -	{ -		$r = min(255, max(0, $rgb[0])); -		$g = min(255, max(0, $rgb[1])); -		$b = min(255, max(0, $rgb[2])); -		$max = max($r, $g, $b); -		$min = min($r, $g, $b); - -		$v = $max / 255; -		$s = (!$max) ? 0 : 1 - ($min / $max); - -		// if max - min is 0, we want hue to be 0 anyway. -		$h = $max - $min; - -		if ($h) -		{ -			switch ($max) -			{ -				case $g: -					$h = 120 + (60 * ($b - $r) / $h); -				break; - -				case $b: -					$h = 240 + (60 * ($r - $g) / $h); -				break; - -				case $r: -					$h = 360 + (60 * ($g - $b) / $h); -				break; -			} -		} -		$this->normalize_hue($h); - -		return array($h, $s * 100, $v * 100); -	} - -	/** -	*/ -	function normalize_hue(&$hue) -	{ -		$hue %= 360; - -		if ($hue < 0) -		{ -			$hue += 360; -		} -	} - -	/** -	* Alternate hue to hue -	*/ -	function ah2h($ahue) -	{ -		if (is_array($ahue)) -		{ -			$ahue[0] = $this->ah2h($ahue[0]); -			return $ahue; -		} -		$this->normalize_hue($ahue); - -		// blue through red is already ok -		if ($ahue >= 240) -		{ -			return $ahue; -		} - -		// ahue green is at 180 -		if ($ahue >= 180) -		{ -			// return (240 - (2 * (240 - $ahue))); -			return (2 * $ahue) - 240; // equivalent -		} - -		// ahue yellow is at 120   (RYB rather than RGB) -		if ($ahue >= 120) -		{ -			return $ahue - 60; -		} - -		return $ahue / 2; -	} - -	/** -	* hue to Alternate hue -	*/ -	function h2ah($hue) -	{ -		if (is_array($hue)) -		{ -			$hue[0] = $this->h2ah($hue[0]); -			return $hue; -		} -		$this->normalize_hue($hue); - -		// blue through red is already ok -		if ($hue >= 240) -		{ -			return $hue; -		} -		else if ($hue <= 60) -		{ -			return $hue * 2; -		} -		else if ($hue <= 120) -		{ -			return $hue + 60; -		} -		else -		{ -			return ($hue + 240) / 2; -		} -	} -} diff --git a/phpBB/includes/captcha/captcha_gd_wave.php b/phpBB/phpbb/captcha/gd_wave.php index c2a4d3a31e..d48fc753a5 100644 --- a/phpBB/includes/captcha/captcha_gd_wave.php +++ b/phpBB/phpbb/captcha/gd_wave.php @@ -11,10 +11,12 @@  *  */ +namespace phpbb\captcha; +  /**  * Wave3D CAPTCHA  */ -class captcha +class gd_wave  {  	var $width		= 360;  	var $height		= 96; diff --git a/phpBB/includes/captcha/captcha_non_gd.php b/phpBB/phpbb/captcha/non_gd.php index 91970ea7a4..3818672f17 100644 --- a/phpBB/includes/captcha/captcha_non_gd.php +++ b/phpBB/phpbb/captcha/non_gd.php @@ -11,19 +11,13 @@  *  */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ -	exit; -} +namespace phpbb\captcha;  /**  * Main non-gd captcha class  * @ignore  */ -class captcha +class non_gd  {  	var $filtered_pngs;  	var $width = 320; @@ -32,7 +26,7 @@ class captcha  	/**  	* Define filtered pngs on init  	*/ -	function captcha() +	function __construct()  	{  		// If we can we will generate a single filtered png, we avoid nastiness via emulation of some Zlib stuff  		$this->define_filtered_pngs(); diff --git a/phpBB/includes/captcha/plugins/captcha_abstract.php b/phpBB/phpbb/captcha/plugins/captcha_abstract.php index 8e1e61bdb7..24ed7f939d 100644 --- a/phpBB/includes/captcha/plugins/captcha_abstract.php +++ b/phpBB/phpbb/captcha/plugins/captcha_abstract.php @@ -11,18 +11,12 @@  *  */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ -	exit; -} +namespace phpbb\captcha\plugins;  /**  * This class holds the code shared by the two default 3.0.x CAPTCHAs.  */ -class phpbb_captcha_plugins_captcha_abstract +abstract class captcha_abstract  {  	var $confirm_id;  	var $confirm_code; @@ -33,6 +27,11 @@ class phpbb_captcha_plugins_captcha_abstract  	var $solved = 0;  	var $captcha_vars = false; +	/** +	* @var string name of the service. +	*/ +	protected $service_name; +  	function init($type)  	{  		global $config, $db, $user; @@ -65,7 +64,8 @@ class phpbb_captcha_plugins_captcha_abstract  		// compute $seed % 0x7fffffff  		$this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff); -		$captcha = new captcha(); +		$generator = $this->get_generator_class(); +		$captcha = new $generator();  		define('IMAGE_OUTPUT', 1);  		$captcha->execute($this->code, $this->seed);  	} @@ -80,7 +80,8 @@ class phpbb_captcha_plugins_captcha_abstract  				return false;  			}  		} -		$captcha = new captcha(); +		$generator = $this->get_generator_class(); +		$captcha = new $generator();  		define('IMAGE_OUTPUT', 1);  		$captcha->execute($this->code, $this->seed);  	} @@ -130,7 +131,7 @@ class phpbb_captcha_plugins_captcha_abstract  		// acp_captcha has a delivery function; let's use it  		$template->assign_vars(array( -			'CONFIRM_IMAGE'		=> append_sid($phpbb_admin_path . 'index.' . $phpEx, 'captcha_demo=1&mode=visual&i=' . $id . '&select_captcha=' . $this->get_class_name()) . $variables, +			'CONFIRM_IMAGE'		=> append_sid($phpbb_admin_path . 'index.' . $phpEx, 'captcha_demo=1&mode=visual&i=' . $id . '&select_captcha=' . $this->get_service_name()) . $variables,  			'CONFIRM_ID'		=> $this->confirm_id,  		)); @@ -364,11 +365,26 @@ class phpbb_captcha_plugins_captcha_abstract  		return false;  	} -} +	/** +	* @return string the name of the service corresponding to the plugin +	*/ +	function get_service_name() +	{ +		return $this->service_name; +	} -/** -* Old class name for legacy use. The new class name is auto loadable. -*/ -class phpbb_default_captcha extends phpbb_captcha_plugins_captcha_abstract -{ +	/** +	* Set the name of the plugin +	* +	* @param string $name +	*/ +	public function set_name($name) +	{ +		$this->service_name = $name; +	} + +	/** +	* @return string the name of the class used to generate the captcha +	*/ +	abstract function get_generator_class();  } diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php b/phpBB/phpbb/captcha/plugins/gd.php index 8dbd458ede..f6200b5b2f 100644 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php +++ b/phpBB/phpbb/captcha/plugins/gd.php @@ -11,25 +11,10 @@  *  */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ -	exit; -} - -/** -* Placeholder for autoload -*/ -if (!class_exists('phpbb_default_captcha', false)) -{ -	include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); -} +namespace phpbb\captcha\plugins; -class phpbb_captcha_gd extends phpbb_default_captcha +class gd extends captcha_abstract  { -  	var $captcha_vars = array(  		'captcha_gd_x_grid'				=> 'CAPTCHA_GD_X_GRID',  		'captcha_gd_y_grid'				=> 'CAPTCHA_GD_Y_GRID', @@ -40,25 +25,17 @@ class phpbb_captcha_gd extends phpbb_default_captcha  		'captcha_gd_fonts'				=> 'CAPTCHA_GD_FONTS',  	); -	function phpbb_captcha_gd() +	public function is_available()  	{ -		global $phpbb_root_path, $phpEx; - -		if (!class_exists('captcha')) -		{ -			include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx); -		} -	} - -	static public function get_instance() -	{ -		$instance = new phpbb_captcha_gd(); -		return $instance; +		return @extension_loaded('gd');  	} -	static public function is_available() +	/** +	* @return string the name of the class used to generate the captcha +	*/ +	function get_generator_class()  	{ -		return @extension_loaded('gd'); +		return '\\phpbb\\captcha\\gd';  	}  	/** @@ -69,16 +46,11 @@ class phpbb_captcha_gd extends phpbb_default_captcha  		return true;  	} -	static public function get_name() +	public function get_name()  	{  		return 'CAPTCHA_GD';  	} -	function get_class_name() -	{ -		return 'phpbb_captcha_gd'; -	} -  	function acp_page($id, &$module)  	{  		global $db, $user, $auth, $template; @@ -129,7 +101,7 @@ class phpbb_captcha_gd extends phpbb_default_captcha  			$template->assign_vars(array(  				'CAPTCHA_PREVIEW'	=> $this->get_demo_template($id), -				'CAPTCHA_NAME'		=> $this->get_class_name(), +				'CAPTCHA_NAME'		=> $this->get_service_name(),  				'U_ACTION'			=> $module->u_action,  			));  		} diff --git a/phpBB/phpbb/captcha/plugins/gd_wave.php b/phpBB/phpbb/captcha/plugins/gd_wave.php new file mode 100644 index 0000000000..e1d44df778 --- /dev/null +++ b/phpBB/phpbb/captcha/plugins/gd_wave.php @@ -0,0 +1,42 @@ +<?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 gd_wave extends captcha_abstract +{ +	public function is_available() +	{ +		return @extension_loaded('gd'); +	} + +	public function get_name() +	{ +		return 'CAPTCHA_GD_3D'; +	} + +	/** +	* @return string the name of the class used to generate the captcha +	*/ +	function get_generator_class() +	{ +		return '\\phpbb\\captcha\\gd_wave'; +	} + +	function acp_page($id, &$module) +	{ +		global $config, $db, $template, $user; + +		trigger_error($user->lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action)); +	} +} diff --git a/phpBB/phpbb/captcha/plugins/nogd.php b/phpBB/phpbb/captcha/plugins/nogd.php new file mode 100644 index 0000000000..6845e5935c --- /dev/null +++ b/phpBB/phpbb/captcha/plugins/nogd.php @@ -0,0 +1,42 @@ +<?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 nogd extends captcha_abstract +{ +	public function is_available() +	{ +		return true; +	} + +	public function get_name() +	{ +		return 'CAPTCHA_NO_GD'; +	} + +	/** +	* @return string the name of the class used to generate the captcha +	*/ +	function get_generator_class() +	{ +		return '\\phpbb\\captcha\\non_gd'; +	} + +	function acp_page($id, &$module) +	{ +		global $user; + +		trigger_error($user->lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action)); +	} +} diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php b/phpBB/phpbb/captcha/plugins/qa.php index 5a44755365..a7ba994cc3 100644 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -11,25 +11,13 @@  *  */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ -	exit; -} - -global $table_prefix; - -define('CAPTCHA_QUESTIONS_TABLE',	$table_prefix . 'captcha_questions'); -define('CAPTCHA_ANSWERS_TABLE',		$table_prefix . 'captcha_answers'); -define('CAPTCHA_QA_CONFIRM_TABLE',	$table_prefix . 'qa_confirm'); +namespace phpbb\captcha\plugins;  /**  * And now to something completely different. Let's make a captcha without extending the abstract class.  * QA CAPTCHA sample implementation  */ -class phpbb_captcha_qa +class qa  {  	var $confirm_id;  	var $answer; @@ -42,6 +30,29 @@ class phpbb_captcha_qa  	// dirty trick: 0 is false, but can still encode that the captcha is not yet validated  	var $solved = 0; +	protected $table_captcha_questions; +	protected $table_captcha_answers; +	protected $table_qa_confirm; + +	/** +	* @var string name of the service. +	*/ +	protected $service_name; + +	/** +	* Constructor +	* +	* @param string $table_captcha_questions +	* @param string $table_captcha_answers +	* @param string $table_qa_confirm +	*/ +	function __construct($table_captcha_questions, $table_captcha_answers, $table_qa_confirm) +	{ +		$this->table_captcha_questions = $table_captcha_questions; +		$this->table_captcha_answers = $table_captcha_answers; +		$this->table_qa_confirm = $table_qa_confirm; +	} +  	/**  	* @param int $type  as per the CAPTCHA API docs, the type  	*/ @@ -62,7 +73,7 @@ class phpbb_captcha_qa  		// we need all defined questions - shouldn't be too many, so we can just grab them  		// try the user's lang first  		$sql = 'SELECT question_id -			FROM ' . CAPTCHA_QUESTIONS_TABLE . " +			FROM ' . $this->table_captcha_questions . "  			WHERE lang_iso = '" . $db->sql_escape($user->lang_name) . "'";  		$result = $db->sql_query($sql, 3600); @@ -78,7 +89,7 @@ class phpbb_captcha_qa  			$this->question_lang = $config['default_lang'];  			$sql = 'SELECT question_id -				FROM ' . CAPTCHA_QUESTIONS_TABLE . " +				FROM ' . $this->table_captcha_questions . "  				WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";  			$result = $db->sql_query($sql, 7200); @@ -98,44 +109,34 @@ class phpbb_captcha_qa  	}  	/** -	*  API function -	*/ -	static public function get_instance() -	{ -		$instance = new phpbb_captcha_qa(); - -		return $instance; -	} - -	/**  	* See if the captcha has created its tables.  	*/ -	static public function is_installed() +	public function is_installed()  	{  		global $db;  		$db_tool = new \phpbb\db\tools($db); -		return $db_tool->sql_table_exists(CAPTCHA_QUESTIONS_TABLE); +		return $db_tool->sql_table_exists($this->table_captcha_questions);  	}  	/**  	*  API function - for the captcha to be available, it must have installed itself and there has to be at least one question in the board's default lang  	*/ -	static public function is_available() +	public function is_available()  	{  		global $config, $db, $phpbb_root_path, $phpEx, $user;  		// load language file for pretty display in the ACP dropdown  		$user->add_lang('captcha_qa'); -		if (!self::is_installed()) +		if (!$this->is_installed())  		{  			return false;  		}  		$sql = 'SELECT COUNT(question_id) AS question_count -			FROM ' . CAPTCHA_QUESTIONS_TABLE . " +			FROM ' . $this->table_captcha_questions . "  			WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";  		$result = $db->sql_query($sql);  		$row = $db->sql_fetchrow($result); @@ -161,11 +162,21 @@ class phpbb_captcha_qa  	}  	/** -	*  API function +	* @return string the name of the service corresponding to the plugin +	*/ +	function get_service_name() +	{ +		return $this->service_name; +	} + +	/** +	* Set the name of the plugin +	* +	* @param string $name  	*/ -	function get_class_name() +	public function set_name($name)  	{ -		return 'phpbb_captcha_qa'; +		$this->service_name = $name;  	}  	/** @@ -216,7 +227,7 @@ class phpbb_captcha_qa  		if ($this->is_available())  		{  			$sql = 'SELECT question_text -				FROM ' . CAPTCHA_QUESTIONS_TABLE . " +				FROM ' . $this->table_captcha_questions . "  				WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";  			$result = $db->sql_query_limit($sql, 1);  			if ($row = $db->sql_fetchrow($result)) @@ -255,7 +266,7 @@ class phpbb_captcha_qa  		global $db, $config;  		$sql = 'SELECT c.confirm_id -			FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' c +			FROM ' . $this->table_qa_confirm . ' c  			LEFT JOIN ' . SESSIONS_TABLE . ' s  				ON (c.session_id = s.session_id)  			WHERE s.session_id IS NULL' . @@ -274,7 +285,7 @@ class phpbb_captcha_qa  			if (sizeof($sql_in))  			{ -				$sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' +				$sql = 'DELETE FROM ' . $this->table_qa_confirm . '  					WHERE ' . $db->sql_in_set('confirm_id', $sql_in);  				$db->sql_query($sql);  			} @@ -299,12 +310,12 @@ class phpbb_captcha_qa  		$db_tool = new \phpbb\db\tools($db); -		$tables = array(CAPTCHA_QUESTIONS_TABLE, CAPTCHA_ANSWERS_TABLE, CAPTCHA_QA_CONFIRM_TABLE); +		$tables = array($this->table_captcha_questions, $this->table_captcha_answers, $this->table_qa_confirm);  		$schemas = array( -				CAPTCHA_QUESTIONS_TABLE		=> array ( +				$this->table_captcha_questions		=> array (  					'COLUMNS' => array( -						'question_id'	=> array('UINT', Null, 'auto_increment'), +						'question_id'	=> array('UINT', null, 'auto_increment'),  						'strict'		=> array('BOOL', 0),  						'lang_id'		=> array('UINT', 0),  						'lang_iso'		=> array('VCHAR:30', ''), @@ -315,7 +326,7 @@ class phpbb_captcha_qa  						'lang'			=> array('INDEX', 'lang_iso'),  					),  				), -				CAPTCHA_ANSWERS_TABLE		=> array ( +				$this->table_captcha_answers		=> array (  					'COLUMNS' => array(  						'question_id'	=> array('UINT', 0),  						'answer_text'	=> array('STEXT_UNI', ''), @@ -324,7 +335,7 @@ class phpbb_captcha_qa  						'qid'			=> array('INDEX', 'question_id'),  					),  				), -				CAPTCHA_QA_CONFIRM_TABLE		=> array ( +				$this->table_qa_confirm		=> array (  					'COLUMNS' => array(  						'session_id'	=> array('CHAR:32', ''),  						'confirm_id'	=> array('CHAR:32', ''), @@ -408,7 +419,7 @@ class phpbb_captcha_qa  		$this->confirm_id = md5(unique_id($user->ip));  		$this->question = (int) array_rand($this->question_ids); -		$sql = 'INSERT INTO ' . CAPTCHA_QA_CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array( +		$sql = 'INSERT INTO ' . $this->table_qa_confirm . ' ' . $db->sql_build_array('INSERT', array(  			'confirm_id'	=> (string) $this->confirm_id,  			'session_id'	=> (string) $user->session_id,  			'lang_iso'		=> (string) $this->question_lang, @@ -435,7 +446,7 @@ class phpbb_captcha_qa  		$this->question = (int) array_rand($this->question_ids);  		$this->solved = 0; -		$sql = 'UPDATE ' . CAPTCHA_QA_CONFIRM_TABLE . ' +		$sql = 'UPDATE ' . $this->table_qa_confirm . '  			SET question_id = ' . (int) $this->question . "  			WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "'  				AND session_id = '" . $db->sql_escape($user->session_id) . "'"; @@ -455,7 +466,7 @@ class phpbb_captcha_qa  		$this->question = (int) array_rand($this->question_ids);  		$this->solved = 0; -		$sql = 'UPDATE ' . CAPTCHA_QA_CONFIRM_TABLE . ' +		$sql = 'UPDATE ' . $this->table_qa_confirm . '  			SET question_id = ' . (int) $this->question . ",  				attempts = attempts + 1  			WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "' @@ -474,7 +485,7 @@ class phpbb_captcha_qa  		global $db, $user;  		$sql = 'SELECT confirm_id -			FROM ' . CAPTCHA_QA_CONFIRM_TABLE . " +			FROM ' . $this->table_qa_confirm . "  			WHERE  				session_id = '" . $db->sql_escape($user->session_id) . "'  				AND lang_iso = '" . $db->sql_escape($this->question_lang) . "' @@ -504,7 +515,7 @@ class phpbb_captcha_qa  		}  		$sql = 'SELECT con.question_id, attempts, question_text, strict -			FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' con, ' . CAPTCHA_QUESTIONS_TABLE . " qes +			FROM ' . $this->table_qa_confirm . ' con, ' . $this->table_captcha_questions . " qes  			WHERE con.question_id = qes.question_id  				AND confirm_id = '" . $db->sql_escape($this->confirm_id) . "'  				AND session_id = '" . $db->sql_escape($user->session_id) . "' @@ -538,7 +549,7 @@ class phpbb_captcha_qa  		$answer = ($this->question_strict) ? utf8_normalize_nfc(request_var('qa_answer', '', true)) : utf8_clean_string(utf8_normalize_nfc(request_var('qa_answer', '', true)));  		$sql = 'SELECT answer_text -			FROM ' . CAPTCHA_ANSWERS_TABLE . ' +			FROM ' . $this->table_captcha_answers . '  			WHERE question_id = ' . (int) $this->question;  		$result = $db->sql_query($sql); @@ -573,7 +584,7 @@ class phpbb_captcha_qa  	{  		global $db, $user; -		$sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . " +		$sql = 'DELETE FROM ' . $this->table_qa_confirm . "  			WHERE session_id = '" . $db->sql_escape($user->session_id) . "'  				AND confirm_type = " . (int) $this->type;  		$db->sql_query($sql); @@ -621,12 +632,12 @@ class phpbb_captcha_qa  		$action = request_var('action', '');  		// we have two pages, so users might want to navigate from one to the other -		$list_url = $module->u_action . "&configure=1&select_captcha=" . $this->get_class_name(); +		$list_url = $module->u_action . "&configure=1&select_captcha=" . $this->get_service_name();  		$template->assign_vars(array(  			'U_ACTION'		=> $module->u_action,  			'QUESTION_ID'	=> $question_id , -			'CLASS'			=> $this->get_class_name(), +			'CLASS'			=> $this->get_service_name(),  		));  		// show the list? @@ -636,7 +647,7 @@ class phpbb_captcha_qa  		}  		else if ($question_id && $action == 'delete')  		{ -			if ($this->get_class_name() !== $config['captcha_plugin'] || !$this->acp_is_last($question_id)) +			if ($this->get_service_name() !== $config['captcha_plugin'] || !$this->acp_is_last($question_id))  			{  				if (confirm_box(true))  				{ @@ -650,7 +661,7 @@ class phpbb_captcha_qa  						'question_id'		=> $question_id,  						'action'			=> $action,  						'configure'			=> 1, -						'select_captcha'	=> $this->get_class_name(), +						'select_captcha'	=> $this->get_service_name(),  						))  					);  				} @@ -750,7 +761,7 @@ class phpbb_captcha_qa  		global $db, $template;  		$sql = 'SELECT * -			FROM ' . CAPTCHA_QUESTIONS_TABLE; +			FROM ' . $this->table_captcha_questions;  		$result = $db->sql_query($sql);  		$template->assign_vars(array( @@ -759,7 +770,7 @@ class phpbb_captcha_qa  		while ($row = $db->sql_fetchrow($result))  		{ -			$url = $module->u_action . "&question_id={$row['question_id']}&configure=1&select_captcha=" . $this->get_class_name() . '&'; +			$url = $module->u_action . "&question_id={$row['question_id']}&configure=1&select_captcha=" . $this->get_service_name() . '&';  			$template->assign_block_vars('questions', array(  				'QUESTION_TEXT'		=> $row['question_text'], @@ -782,7 +793,7 @@ class phpbb_captcha_qa  		if ($question_id)  		{  			$sql = 'SELECT * -				FROM ' . CAPTCHA_QUESTIONS_TABLE . ' +				FROM ' . $this->table_captcha_questions . '  				WHERE question_id = ' . $question_id;  			$result = $db->sql_query($sql);  			$question = $db->sql_fetchrow($result); @@ -796,7 +807,7 @@ class phpbb_captcha_qa  			$question['answers'] = array();  			$sql = 'SELECT * -				FROM ' . CAPTCHA_ANSWERS_TABLE . ' +				FROM ' . $this->table_captcha_answers . '  				WHERE question_id = ' . $question_id;  			$result = $db->sql_query($sql); @@ -835,7 +846,7 @@ class phpbb_captcha_qa  		global $db, $cache;  		// easier to delete all answers than to figure out which to update -		$sql = 'DELETE FROM ' . CAPTCHA_ANSWERS_TABLE . " WHERE question_id = $question_id"; +		$sql = 'DELETE FROM ' . $this->table_captcha_answers . " WHERE question_id = $question_id";  		$db->sql_query($sql);  		$langs = $this->get_languages(); @@ -843,14 +854,14 @@ class phpbb_captcha_qa  		$question_ary['lang_id'] = $langs[$question_ary['lang_iso']]['id'];  		unset($question_ary['answers']); -		$sql = 'UPDATE ' . CAPTCHA_QUESTIONS_TABLE . ' +		$sql = 'UPDATE ' . $this->table_captcha_questions . '  			SET ' . $db->sql_build_array('UPDATE', $question_ary) . "  			WHERE question_id = $question_id";  		$db->sql_query($sql);  		$this->acp_insert_answers($data, $question_id); -		$cache->destroy('sql', CAPTCHA_QUESTIONS_TABLE); +		$cache->destroy('sql', $this->table_captcha_questions);  	}  	/** @@ -867,14 +878,14 @@ class phpbb_captcha_qa  		$question_ary['lang_id'] = $langs[$data['lang_iso']]['id'];  		unset($question_ary['answers']); -		$sql = 'INSERT INTO ' . CAPTCHA_QUESTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $question_ary); +		$sql = 'INSERT INTO ' . $this->table_captcha_questions . ' ' . $db->sql_build_array('INSERT', $question_ary);  		$db->sql_query($sql);  		$question_id = $db->sql_nextid();  		$this->acp_insert_answers($data, $question_id); -		$cache->destroy('sql', CAPTCHA_QUESTIONS_TABLE); +		$cache->destroy('sql', $this->table_captcha_questions);  	}  	/** @@ -892,11 +903,11 @@ class phpbb_captcha_qa  				'answer_text'	=> $answer,  			); -			$sql = 'INSERT INTO ' . CAPTCHA_ANSWERS_TABLE . ' ' . $db->sql_build_array('INSERT', $answer_ary); +			$sql = 'INSERT INTO ' . $this->table_captcha_answers . ' ' . $db->sql_build_array('INSERT', $answer_ary);  			$db->sql_query($sql);  		} -		$cache->destroy('sql', CAPTCHA_ANSWERS_TABLE); +		$cache->destroy('sql', $this->table_captcha_answers);  	}  	/** @@ -906,7 +917,7 @@ class phpbb_captcha_qa  	{  		global $db, $cache; -		$tables = array(CAPTCHA_QUESTIONS_TABLE, CAPTCHA_ANSWERS_TABLE); +		$tables = array($this->table_captcha_questions, $this->table_captcha_answers);  		foreach ($tables as $table)  		{ @@ -981,7 +992,7 @@ class phpbb_captcha_qa  		if ($question_id)  		{  			$sql = 'SELECT question_id -				FROM ' . CAPTCHA_QUESTIONS_TABLE . " +				FROM ' . $this->table_captcha_questions . "  				WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'  					AND  question_id <> " .  (int) $question_id;  			$result = $db->sql_query_limit($sql, 1); diff --git a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php b/phpBB/phpbb/captcha/plugins/recaptcha.php index 12cc49ef9b..ea446d7bc3 100644 --- a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php +++ b/phpBB/phpbb/captcha/plugins/recaptcha.php @@ -11,21 +11,9 @@  *  */ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ -	exit; -} - -if (!class_exists('phpbb_default_captcha', false)) -{ -	// we need the classic captcha code for tracking solutions and attempts -	include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); -} +namespace phpbb\captcha\plugins; -class phpbb_recaptcha extends phpbb_default_captcha +class recaptcha extends captcha_abstract  {  	var $recaptcha_server = 'http://www.google.com/recaptcha/api';  	var $recaptcha_server_secure = 'https://www.google.com/recaptcha/api'; // class constants :( @@ -55,13 +43,7 @@ class phpbb_recaptcha extends phpbb_default_captcha  		$this->response = request_var('recaptcha_response_field', '');  	} -	static public function get_instance() -	{ -		$instance = new phpbb_recaptcha(); -		return $instance; -	} - -	static public function is_available() +	public function is_available()  	{  		global $config, $user;  		$user->add_lang('captcha_recaptcha'); @@ -81,9 +63,12 @@ class phpbb_recaptcha extends phpbb_default_captcha  		return 'CAPTCHA_RECAPTCHA';  	} -	function get_class_name() +	/** +	* This function is implemented because required by the upper class, but is never used for reCaptcha. +	*/ +	function get_generator_class()  	{ -		return 'phpbb_recaptcha'; +		throw new \Exception('No generator class given.');  	}  	function acp_page($id, &$module) @@ -131,7 +116,7 @@ class phpbb_recaptcha extends phpbb_default_captcha  			$template->assign_vars(array(  				'CAPTCHA_PREVIEW'	=> $this->get_demo_template($id), -				'CAPTCHA_NAME'		=> $this->get_class_name(), +				'CAPTCHA_NAME'		=> $this->get_service_name(),  				'U_ACTION'			=> $module->u_action,  			)); diff --git a/phpBB/phpbb/db/migration/data/v310/captcha_plugins.php b/phpBB/phpbb/db/migration/data/v310/captcha_plugins.php new file mode 100644 index 0000000000..13071e9891 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/captcha_plugins.php @@ -0,0 +1,44 @@ +<?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\v310; + +class captcha_plugins extends \phpbb\db\migration\migration +{ +	static public function depends_on() +	{ +		return array( +			'\phpbb\db\migration\data\v310\rc2', +		); +	} + +	public function update_data() +	{ +		$captcha_plugin = $this->config['captcha_plugin']; +		if (strpos($this->config['captcha_plugin'], 'phpbb_captcha_') === 0) +		{ +			$captcha_plugin = substr($this->config['captcha_plugin'], strlen('phpbb_captcha_')); +		} + +		return array( +			array('if', array( +				(is_file($this->phpbb_root_path . 'phpbb/captcha/plugins/' . $captcha_plugin . '.' . $this->php_ext)), +				array('config.update', array('captcha_plugin', 'core.captcha.plugins.' . $captcha_plugin)), +			)), +			array('if', array( +				(!is_file($this->phpbb_root_path . 'phpbb/captcha/plugins/' . $captcha_plugin . '.' . $this->php_ext)), +				array('config.update', array('captcha_plugin', 'core.captcha.plugins.nogd')), +			)), +		); +	} +} diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index 5a0d7c0031..7d564742af 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -962,7 +962,7 @@ class session  	*/  	function session_gc()  	{ -		global $db, $config, $phpbb_root_path, $phpEx; +		global $db, $config, $phpbb_root_path, $phpEx, $phpbb_container;  		$batch_size = 10; @@ -1022,11 +1022,7 @@ class session  			}  			// only called from CRON; should be a safe workaround until the infrastructure gets going -			if (!class_exists('phpbb_captcha_factory', false)) -			{ -				include($phpbb_root_path . "includes/captcha/captcha_factory." . $phpEx); -			} -			$captcha_factory = new \phpbb_captcha_factory(); +			$captcha_factory = $phpbb_container->get('captcha.factory');  			$captcha_factory->garbage_collect($config['captcha_plugin']);  			$sql = 'DELETE FROM ' . LOGIN_ATTEMPT_TABLE . ' diff --git a/phpBB/posting.php b/phpBB/posting.php index 6638caa94b..4c3d012ca5 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -241,8 +241,7 @@ $user->setup(array('posting', 'mcp', 'viewtopic'), $post_data['forum_style']);  if ($config['enable_post_confirm'] && !$user->data['is_registered'])  { -	include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); -	$captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); +	$captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']);  	$captcha->init(CONFIRM_POST);  } diff --git a/phpBB/report.php b/phpBB/report.php index 3684c2162f..fd6fab6645 100644 --- a/phpBB/report.php +++ b/phpBB/report.php @@ -151,8 +151,7 @@ else  if ($config['enable_post_confirm'] && !$user->data['is_registered'])  { -	include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); -	$captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); +	$captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']);  	$captcha->init(CONFIRM_REPORT);  }  | 
