diff options
Diffstat (limited to 'phpBB/phpbb')
142 files changed, 3528 insertions, 2613 deletions
| diff --git a/phpBB/phpbb/auth/provider/apache.php b/phpBB/phpbb/auth/provider/apache.php index aa5bf64335..a713674657 100644 --- a/phpBB/phpbb/auth/provider/apache.php +++ b/phpBB/phpbb/auth/provider/apache.php @@ -13,34 +13,55 @@  namespace phpbb\auth\provider; +use phpbb\config\config; +use phpbb\db\driver\driver_interface; +use phpbb\language\language; +use phpbb\request\request_interface; +use phpbb\request\type_cast_helper; +use phpbb\user; +  /**  * Apache authentication provider for phpBB3  */ -class apache extends \phpbb\auth\provider\base +class apache extends base  { -	/** -	* phpBB passwords manager -	* -	* @var \phpbb\passwords\manager -	*/ -	protected $passwords_manager; +	/** @var config phpBB config */ +	protected $config; + +	/** @var driver_interface Database object */ +	protected $db; + +	/** @var language Language object */ +	protected $language; + +	/** @var request_interface Request object */ +	protected $request; + +	/** @var user User object */ +	protected $user; + +	/** @var string Relative path to phpBB root */ +	protected $phpbb_root_path; + +	/** @var string PHP file extension */ +	protected $php_ext;  	/**  	 * Apache Authentication Constructor  	 * -	 * @param	\phpbb\db\driver\driver_interface 	$db		Database object -	 * @param	\phpbb\config\config 		$config		Config object -	 * @param	\phpbb\passwords\manager	$passwords_manager		Passwords Manager object -	 * @param	\phpbb\request\request 		$request		Request object -	 * @param	\phpbb\user 			$user		User object +	 * @param	config 				$config		Config object +	 * @param	driver_interface 	$db		Database object +	 * @param	language			$language Language object +	 * @param	request_interface 	$request		Request object +	 * @param	user 				$user		User object  	 * @param	string 				$phpbb_root_path		Relative path to phpBB root  	 * @param	string 				$php_ext		PHP file extension  	 */ -	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(config $config, driver_interface $db, language $language, request_interface $request, user $user, $phpbb_root_path, $php_ext)  	{ -		$this->db = $db;  		$this->config = $config; -		$this->passwords_manager = $passwords_manager; +		$this->db = $db; +		$this->language = $language;  		$this->request = $request;  		$this->user = $user;  		$this->phpbb_root_path = $phpbb_root_path; @@ -52,9 +73,9 @@ class apache extends \phpbb\auth\provider\base  	 */  	public function init()  	{ -		if (!$this->request->is_set('PHP_AUTH_USER', \phpbb\request\request_interface::SERVER) || $this->user->data['username'] !== htmlspecialchars_decode($this->request->server('PHP_AUTH_USER'))) +		if (!$this->request->is_set('PHP_AUTH_USER', request_interface::SERVER) || $this->user->data['username'] !== htmlspecialchars_decode($this->request->server('PHP_AUTH_USER')))  		{ -			return $this->user->lang['APACHE_SETUP_BEFORE_USE']; +			return $this->language->lang('APACHE_SETUP_BEFORE_USE');  		}  		return false;  	} @@ -83,7 +104,7 @@ class apache extends \phpbb\auth\provider\base  			);  		} -		if (!$this->request->is_set('PHP_AUTH_USER', \phpbb\request\request_interface::SERVER)) +		if (!$this->request->is_set('PHP_AUTH_USER', request_interface::SERVER))  		{  			return array(  				'status'		=> LOGIN_ERROR_EXTERNAL_AUTH, @@ -137,7 +158,7 @@ class apache extends \phpbb\auth\provider\base  			return array(  				'status'		=> LOGIN_SUCCESS_CREATE_PROFILE,  				'error_msg'		=> false, -				'user_row'		=> $this->user_row($php_auth_user, $php_auth_pw), +				'user_row'		=> $this->user_row($php_auth_user),  			);  		} @@ -154,7 +175,7 @@ class apache extends \phpbb\auth\provider\base  	 */  	public function autologin()  	{ -		if (!$this->request->is_set('PHP_AUTH_USER', \phpbb\request\request_interface::SERVER)) +		if (!$this->request->is_set('PHP_AUTH_USER', request_interface::SERVER))  		{  			return array();  		} @@ -164,8 +185,8 @@ class apache extends \phpbb\auth\provider\base  		if (!empty($php_auth_user) && !empty($php_auth_pw))  		{ -			set_var($php_auth_user, $php_auth_user, 'string', true); -			set_var($php_auth_pw, $php_auth_pw, 'string', true); +			$type_cast_helper = new type_cast_helper(); +			$type_cast_helper->set_var($php_auth_user, $php_auth_user, 'string', true);  			$sql = 'SELECT *  				FROM ' . USERS_TABLE . " @@ -185,7 +206,7 @@ class apache extends \phpbb\auth\provider\base  			}  			// create the user if he does not exist yet -			user_add($this->user_row($php_auth_user, $php_auth_pw)); +			user_add($this->user_row($php_auth_user));  			$sql = 'SELECT *  				FROM ' . USERS_TABLE . " @@ -208,11 +229,11 @@ class apache extends \phpbb\auth\provider\base  	 * function in order to create a user  	 *  	 * @param 	string	$username 	The username of the new user. -	 * @param 	string	$password 	The password of the new user. +	 *  	 * @return 	array 				Contains data that can be passed directly to  	 *								the user_add function.  	 */ -	private function user_row($username, $password) +	private function user_row($username)  	{  		// first retrieve default group id  		$sql = 'SELECT group_id @@ -231,7 +252,7 @@ class apache extends \phpbb\auth\provider\base  		// generate user account data  		return array(  			'username'		=> $username, -			'user_password'	=> $this->passwords_manager->hash($password), +			'user_password'	=> '',  			'user_email'	=> '',  			'group_id'		=> (int) $row['group_id'],  			'user_type'		=> USER_NORMAL, @@ -246,7 +267,7 @@ class apache extends \phpbb\auth\provider\base  	public function validate_session($user)  	{  		// Check if PHP_AUTH_USER is set and handle this case -		if ($this->request->is_set('PHP_AUTH_USER', \phpbb\request\request_interface::SERVER)) +		if ($this->request->is_set('PHP_AUTH_USER', request_interface::SERVER))  		{  			$php_auth_user = $this->request->server('PHP_AUTH_USER'); diff --git a/phpBB/phpbb/auth/provider/base.php b/phpBB/phpbb/auth/provider/base.php index dea27ccc25..30e0a0fe2d 100644 --- a/phpBB/phpbb/auth/provider/base.php +++ b/phpBB/phpbb/auth/provider/base.php @@ -16,7 +16,7 @@ namespace phpbb\auth\provider;  /**  * Base authentication provider class that all other providers should implement  */ -abstract class base implements \phpbb\auth\provider\provider_interface +abstract class base implements provider_interface  {  	/**  	* {@inheritdoc} diff --git a/phpBB/phpbb/auth/provider/db.php b/phpBB/phpbb/auth/provider/db.php index 1adf85ee05..a70734fcbe 100644 --- a/phpBB/phpbb/auth/provider/db.php +++ b/phpBB/phpbb/auth/provider/db.php @@ -13,48 +13,69 @@  namespace phpbb\auth\provider; +use phpbb\captcha\factory; +use phpbb\config\config; +use phpbb\db\driver\driver_interface; +use phpbb\passwords\manager; +use phpbb\request\request_interface; +use phpbb\user; +  /**   * Database authentication provider for phpBB3   * This is for authentication via the integrated user table   */ -class db extends \phpbb\auth\provider\base +class db extends base  { +	/** @var factory CAPTCHA factory */ +	protected $captcha_factory; + +	/** @var config phpBB config */ +	protected $config; + +	/** @var driver_interface DBAL driver instance */ +	protected $db; + +	/** @var request_interface Request object */ +	protected $request; + +	/** @var user User object */ +	protected $user; + +	/** @var string phpBB root path */ +	protected $phpbb_root_path; + +	/** @var string PHP file extension */ +	protected $php_ext; +  	/**  	* phpBB passwords manager  	* -	* @var \phpbb\passwords\manager +	* @var manager  	*/  	protected $passwords_manager;  	/** -	* DI container -	* -	* @var \Symfony\Component\DependencyInjection\ContainerInterface -	*/ -	protected $phpbb_container; - -	/**  	 * Database Authentication Constructor  	 * -	 * @param	\phpbb\db\driver\driver_interface		$db -	 * @param	\phpbb\config\config 		$config -	 * @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 factory $captcha_factory +	 * @param	config 		$config +	 * @param	driver_interface		$db +	 * @param	manager	$passwords_manager +	 * @param	request_interface		$request +	 * @param	user			$user  	 * @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, \Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container, $phpbb_root_path, $php_ext) +	public function __construct(factory $captcha_factory, config $config, driver_interface $db, manager $passwords_manager, request_interface $request, user $user, $phpbb_root_path, $php_ext)  	{ -		$this->db = $db; +		$this->captcha_factory = $captcha_factory;  		$this->config = $config; +		$this->db = $db;  		$this->passwords_manager = $passwords_manager;  		$this->request = $request;  		$this->user = $user;  		$this->phpbb_root_path = $phpbb_root_path;  		$this->php_ext = $php_ext; -		$this->phpbb_container = $phpbb_container;  	}  	/** @@ -155,9 +176,7 @@ class db extends \phpbb\auth\provider\base  		// Every auth module is able to define what to do by itself...  		if ($show_captcha)  		{ -			/* @var $captcha_factory \phpbb\captcha\factory */ -			$captcha_factory = $this->phpbb_container->get('captcha.factory'); -			$captcha = $captcha_factory->get_instance($this->config['captcha_plugin']); +			$captcha = $this->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/auth/provider/ldap.php b/phpBB/phpbb/auth/provider/ldap.php index 0789a6234d..43699f7d6e 100644 --- a/phpBB/phpbb/auth/provider/ldap.php +++ b/phpBB/phpbb/auth/provider/ldap.php @@ -1,4 +1,5 @@  <?php +  /**  *  * This file is part of the phpBB Forum Software package. @@ -13,32 +14,42 @@  namespace phpbb\auth\provider; +use phpbb\config\config; +use phpbb\db\driver\driver_interface; +use phpbb\language\language; +use phpbb\user; +  /**   * Database authentication provider for phpBB3   * This is for authentication via the integrated user table   */ -class ldap extends \phpbb\auth\provider\base +class ldap extends base  { -	/** -	* phpBB passwords manager -	* -	* @var \phpbb\passwords\manager -	*/ -	protected $passwords_manager; +	/** @var config phpBB config */ +	protected $config; + +	/** @var driver_interface DBAL driver interface */ +	protected $db; + +	/** @var language phpBB language class */ +	protected $language; + +	/** @var user phpBB user */ +	protected $user;  	/**  	 * LDAP Authentication Constructor  	 * -	 * @param	\phpbb\db\driver\driver_interface		$db		Database object -	 * @param	\phpbb\config\config		$config		Config object -	 * @param	\phpbb\passwords\manager	$passwords_manager		Passwords manager object -	 * @param	\phpbb\user			$user		User object +	 * @param	config				$config		Config object +	 * @param	driver_interface	$db			DBAL driver interface +	 * @param	language			$language	Language object +	 * @param	user				$user		User object  	 */ -	public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\user $user) +	public function __construct(config $config, driver_interface $db, language $language, user $user)  	{ -		$this->db = $db;  		$this->config = $config; -		$this->passwords_manager = $passwords_manager; +		$this->db = $db; +		$this->language = $language;  		$this->user = $user;  	} @@ -49,7 +60,7 @@ class ldap extends \phpbb\auth\provider\base  	{  		if (!@extension_loaded('ldap'))  		{ -			return $this->user->lang['LDAP_NO_LDAP_EXTENSION']; +			return $this->language->lang('LDAP_NO_LDAP_EXTENSION');  		}  		$this->config['ldap_port'] = (int) $this->config['ldap_port']; @@ -64,7 +75,7 @@ class ldap extends \phpbb\auth\provider\base  		if (!$ldap)  		{ -			return $this->user->lang['LDAP_NO_SERVER_CONNECTION']; +			return $this->language->lang('LDAP_NO_SERVER_CONNECTION');  		}  		@ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); @@ -74,7 +85,7 @@ class ldap extends \phpbb\auth\provider\base  		{  			if (!@ldap_bind($ldap, htmlspecialchars_decode($this->config['ldap_user']), htmlspecialchars_decode($this->config['ldap_password'])))  			{ -				return $this->user->lang['LDAP_INCORRECT_USER_PASSWORD']; +				return $this->language->lang('LDAP_INCORRECT_USER_PASSWORD');  			}  		} @@ -92,7 +103,7 @@ class ldap extends \phpbb\auth\provider\base  		if ($search === false)  		{ -			return $this->user->lang['LDAP_SEARCH_FAILED']; +			return $this->language->lang('LDAP_SEARCH_FAILED');  		}  		$result = @ldap_get_entries($ldap, $search); @@ -101,12 +112,12 @@ class ldap extends \phpbb\auth\provider\base  		if (!is_array($result) || count($result) < 2)  		{ -			return sprintf($this->user->lang['LDAP_NO_IDENTITY'], $this->user->data['username']); +			return $this->language->lang('LDAP_NO_IDENTITY', $this->user->data['username']);  		}  		if (!empty($this->config['ldap_email']) && !isset($result[0][htmlspecialchars_decode($this->config['ldap_email'])]))  		{ -			return $this->user->lang['LDAP_NO_EMAIL']; +			return $this->language->lang('LDAP_NO_EMAIL');  		}  		return false; @@ -245,7 +256,7 @@ class ldap extends \phpbb\auth\provider\base  					// generate user account data  					$ldap_user_row = array(  						'username'		=> $username, -						'user_password'	=> $this->passwords_manager->hash($password), +						'user_password'	=> '',  						'user_email'	=> (!empty($this->config['ldap_email'])) ? utf8_htmlspecialchars($ldap_result[0][htmlspecialchars_decode($this->config['ldap_email'])][0]) : '',  						'group_id'		=> (int) $row['group_id'],  						'user_type'		=> USER_NORMAL, diff --git a/phpBB/phpbb/auth/provider/oauth/oauth.php b/phpBB/phpbb/auth/provider/oauth/oauth.php index e3f8394bba..29ffe6d591 100644 --- a/phpBB/phpbb/auth/provider/oauth/oauth.php +++ b/phpBB/phpbb/auth/provider/oauth/oauth.php @@ -1,169 +1,137 @@  <?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. -* -*/ + * + * 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\auth\provider\oauth; +use OAuth\Common\Http\Exception\TokenResponseException; +use OAuth\ServiceFactory;  use OAuth\Common\Consumer\Credentials; +use OAuth\Common\Service\ServiceInterface; +use OAuth\OAuth1\Service\AbstractService as OAuth1Service; +use OAuth\OAuth2\Service\AbstractService as OAuth2Service; +use phpbb\auth\provider\base; +use phpbb\auth\provider\db; +use phpbb\auth\provider\oauth\service\exception; +use phpbb\config\config; +use phpbb\db\driver\driver_interface; +use phpbb\di\service_collection; +use phpbb\event\dispatcher; +use phpbb\language\language; +use phpbb\request\request_interface; +use phpbb\user;  /** -* OAuth authentication provider for phpBB3 -*/ -class oauth extends \phpbb\auth\provider\base + * OAuth authentication provider for phpBB3 + */ +class oauth extends base  { -	/** -	* Database driver -	* -	* @var \phpbb\db\driver\driver_interface -	*/ -	protected $db; - -	/** -	* phpBB config -	* -	* @var \phpbb\config\config -	*/ +	/** @var config */  	protected $config; -	/** -	* phpBB passwords manager -	* -	* @var \phpbb\passwords\manager -	*/ -	protected $passwords_manager; - -	/** -	* phpBB request object -	* -	* @var \phpbb\request\request_interface -	*/ -	protected $request; +	/** @var driver_interface */ +	protected $db; -	/** -	* phpBB user -	* -	* @var \phpbb\user -	*/ -	protected $user; +	/** @var db */ +	protected $db_auth; -	/** -	* OAuth token table -	* -	* @var string -	*/ -	protected $auth_provider_oauth_token_storage_table; +	/** @var dispatcher */ +	protected $dispatcher; -	/** -	* OAuth state table -	* -	* @var string -	*/ -	protected $auth_provider_oauth_state_table; +	/** @var language */ +	protected $language; -	/** -	* OAuth account association table -	* -	* @var string -	*/ -	protected $auth_provider_oauth_token_account_assoc; +	/** @var request_interface */ +	protected $request; -	/** -	* All OAuth service providers -	* -	* @var \phpbb\di\service_collection Contains \phpbb\auth\provider\oauth\service_interface -	*/ +	/** @var service_collection */  	protected $service_providers; -	/** -	* Users table -	* -	* @var string -	*/ -	protected $users_table; +	/** @var user */ +	protected $user; -	/** -	* Cached current uri object -	* -	* @var \OAuth\Common\Http\Uri\UriInterface|null -	*/ -	protected $current_uri; +	/** @var string OAuth table: token storage */ +	protected $oauth_token_table; -	/** -	* DI container -	* -	* @var \Symfony\Component\DependencyInjection\ContainerInterface -	*/ -	protected $phpbb_container; +	/** @var string OAuth table: state */ +	protected $oauth_state_table; -	/** -	* phpBB event dispatcher -	* -	* @var \phpbb\event\dispatcher_interface -	*/ -	protected $dispatcher; +	/** @var string OAuth table: account association */ +	protected $oauth_account_table; -	/** -	* phpBB root path -	* -	* @var string -	*/ -	protected $phpbb_root_path; +	/** @var string Users table */ +	protected $users_table; -	/** -	* PHP file extension -	* -	* @var string -	*/ +	/** @var string phpBB root path */ +	protected $root_path; + +	/** @var string php File extension */  	protected $php_ext;  	/** -	* OAuth Authentication Constructor -	* -	* @param	\phpbb\db\driver\driver_interface	$db -	* @param	\phpbb\config\config	$config -	* @param	\phpbb\passwords\manager	$passwords_manager -	* @param	\phpbb\request\request_interface	$request -	* @param	\phpbb\user		$user -	* @param	string			$auth_provider_oauth_token_storage_table -	* @param	string			$auth_provider_oauth_state_table -	* @param	string			$auth_provider_oauth_token_account_assoc -	* @param	\phpbb\di\service_collection	$service_providers Contains \phpbb\auth\provider\oauth\service_interface -	* @param	string			$users_table -	* @param	\Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container DI container -	* @param	\phpbb\event\dispatcher_interface $dispatcher phpBB event dispatcher -	* @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_interface $request, \phpbb\user $user, $auth_provider_oauth_token_storage_table, $auth_provider_oauth_state_table, $auth_provider_oauth_token_account_assoc, \phpbb\di\service_collection $service_providers, $users_table, \Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container, \phpbb\event\dispatcher_interface $dispatcher, $phpbb_root_path, $php_ext) +	 * Constructor. +	 * +	 * @param config				$config					Config object +	 * @param driver_interface	$db						Database object +	 * @param db			$db_auth				DB auth provider +	 * @param dispatcher			$dispatcher				Event dispatcher object +	 * @param language			$language				Language object +	 * @param request_interface	$request				Request object +	 * @param service_collection		$service_providers		OAuth providers service collection +	 * @param user						$user					User object +	 * @param string							$oauth_token_table		OAuth table: token storage +	 * @param string							$oauth_state_table		OAuth table: state +	 * @param string							$oauth_account_table	OAuth table: account association +	 * @param string							$users_table			User table +	 * @param string							$root_path				phpBB root path +	 * @param string							$php_ext				php File extension +	 */ +	public function __construct( +		config $config, +		driver_interface $db, +		db $db_auth, +		dispatcher $dispatcher, +		language $language, +		request_interface $request, +		service_collection $service_providers, +		user $user, +		$oauth_token_table, +		$oauth_state_table, +		$oauth_account_table, +		$users_table, +		$root_path, +		$php_ext +	)  	{ -		$this->db = $db; -		$this->config = $config; -		$this->passwords_manager = $passwords_manager; -		$this->request = $request; -		$this->user = $user; -		$this->auth_provider_oauth_token_storage_table = $auth_provider_oauth_token_storage_table; -		$this->auth_provider_oauth_state_table = $auth_provider_oauth_state_table; -		$this->auth_provider_oauth_token_account_assoc = $auth_provider_oauth_token_account_assoc; -		$this->service_providers = $service_providers; -		$this->users_table = $users_table; -		$this->phpbb_container = $phpbb_container; -		$this->dispatcher = $dispatcher; -		$this->phpbb_root_path = $phpbb_root_path; -		$this->php_ext = $php_ext; +		$this->config				= $config; +		$this->db					= $db; +		$this->db_auth				= $db_auth; +		$this->dispatcher			= $dispatcher; +		$this->language				= $language; +		$this->service_providers	= $service_providers; +		$this->request				= $request; +		$this->user					= $user; + +		$this->oauth_token_table	= $oauth_token_table; +		$this->oauth_state_table	= $oauth_state_table; +		$this->oauth_account_table	= $oauth_account_table; +		$this->users_table			= $users_table; +		$this->root_path			= $root_path; +		$this->php_ext				= $php_ext;  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function init()  	{  		// This does not test whether or not the key and secret provided are valid. @@ -173,61 +141,85 @@ class oauth extends \phpbb\auth\provider\base  			if (($credentials['key'] && !$credentials['secret']) || (!$credentials['key'] && $credentials['secret']))  			{ -				return $this->user->lang['AUTH_PROVIDER_OAUTH_ERROR_ELEMENT_MISSING']; +				return $this->language->lang('AUTH_PROVIDER_OAUTH_ERROR_ELEMENT_MISSING');  			}  		} +  		return false;  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function login($username, $password)  	{  		// Temporary workaround for only having one authentication provider available  		if (!$this->request->is_set('oauth_service'))  		{ -			$provider = new \phpbb\auth\provider\db($this->db, $this->config, $this->passwords_manager, $this->request, $this->user, $this->phpbb_container, $this->phpbb_root_path, $this->php_ext); -			return $provider->login($username, $password); +			return $this->db_auth->login($username, $password);  		}  		// Request the name of the OAuth service -		$service_name_original = $this->request->variable('oauth_service', '', false); -		$service_name = 'auth.provider.oauth.service.' . strtolower($service_name_original); -		if ($service_name_original === '' || !array_key_exists($service_name, $this->service_providers)) +		$provider = $this->request->variable('oauth_service', '', false); +		$service_name = $this->get_service_name($provider); + +		if ($provider === '' || !array_key_exists($service_name, $this->service_providers))  		{ -			return array( +			return [  				'status'		=> LOGIN_ERROR_EXTERNAL_AUTH,  				'error_msg'		=> 'LOGIN_ERROR_OAUTH_SERVICE_DOES_NOT_EXIST', -				'user_row'		=> array('user_id' => ANONYMOUS), -			); +				'user_row'		=> ['user_id' => ANONYMOUS], +			];  		}  		// Get the service credentials for the given service -		$service_credentials = $this->service_providers[$service_name]->get_service_credentials(); +		$storage = new token_storage($this->db, $this->user, $this->oauth_token_table, $this->oauth_state_table); +		$query = 'mode=login&login=external&oauth_service=' . $provider; -		$storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table, $this->auth_provider_oauth_state_table); -		$query = 'mode=login&login=external&oauth_service=' . $service_name_original; -		$service = $this->get_service($service_name_original, $storage, $service_credentials, $query, $this->service_providers[$service_name]->get_auth_scope()); +		try +		{ +			/** @var OAuth1Service|OAuth2Service $service */ +			$service = $this->get_service($provider, $storage, $query); +		} +		catch (\Exception $e) +		{ +			return [ +				'status'		=> LOGIN_ERROR_EXTERNAL_AUTH, +				'error_msg'		=> $e->getMessage(), +				'user_row'		=> ['user_id' => ANONYMOUS], +			]; +		} -		if (($service::OAUTH_VERSION === 2 && $this->request->is_set('code', \phpbb\request\request_interface::GET)) -			|| ($service::OAUTH_VERSION === 1 && $this->request->is_set('oauth_token', \phpbb\request\request_interface::GET))) +		if ($this->is_set_code($service))  		{  			$this->service_providers[$service_name]->set_external_service_provider($service); -			$unique_id = $this->service_providers[$service_name]->perform_auth_login(); + +			try +			{ +				$unique_id = $this->service_providers[$service_name]->perform_auth_login(); +			} +			catch (exception $e) +			{ +				return [ +					'status'		=> LOGIN_ERROR_EXTERNAL_AUTH, +					'error_msg'		=> $e->getMessage(), +					'user_row'		=> ['user_id' => ANONYMOUS], +				]; +			}  			/**  			 * Check to see if this provider is already associated with an account.  			 * -			 * Enforcing a data type to make data contains strings and not integers, +			 * Enforcing a data type to make sure it are strings and not integers,  			 * so values are quoted in the SQL WHERE statement.  			 */ -			$data = array( -				'provider'			=> (string) $service_name_original, +			$data = [ +				'provider'			=> (string) utf8_strtolower($provider),  				'oauth_provider_id'	=> (string) $unique_id -			); +			]; -			$sql = 'SELECT user_id FROM ' . $this->auth_provider_oauth_token_account_assoc . ' +			$sql = 'SELECT user_id  +				FROM ' . $this->oauth_account_table . '  				WHERE ' . $this->db->sql_build_array('SELECT', $data);  			$result = $this->db->sql_query($sql);  			$row = $this->db->sql_fetchrow($result); @@ -235,204 +227,134 @@ class oauth extends \phpbb\auth\provider\base  			$redirect_data = array(  				'auth_provider'				=> 'oauth', -				'login_link_oauth_service'	=> $service_name_original, +				'login_link_oauth_service'	=> $provider,  			);  			/** -			* Event is triggered before check if provider is already associated with an account -			* -			* @event core.oauth_login_after_check_if_provider_id_has_match -			* @var	array									row				User row -			* @var	array									data			Provider data -			* @var	array									redirect_data	Data to be appended to the redirect url -			* @var	\OAuth\Common\Service\ServiceInterface	service			OAuth service -			* @since 3.2.3-RC1 -			* @changed 3.2.6-RC1 Added redirect_data -			*/ -			$vars = array( +			 * Event is triggered before check if provider is already associated with an account +			 * +			 * @event core.oauth_login_after_check_if_provider_id_has_match +			 * @var array				row				User row +			 * @var array				data			Provider data +			 * @var	array				redirect_data	Data to be appended to the redirect url +			 * @var ServiceInterface	service			OAuth service +			 * @since 3.2.3-RC1 +			 * @changed 3.2.6-RC1						Added redirect_data +			 */ +			$vars = [  				'row',  				'data',  				'redirect_data',  				'service', -			); +			];  			extract($this->dispatcher->trigger_event('core.oauth_login_after_check_if_provider_id_has_match', compact($vars)));  			if (!$row)  			{  				// The user does not yet exist, ask to link or create profile -				return array( +				return [  					'status'		=> LOGIN_SUCCESS_LINK_PROFILE,  					'error_msg'		=> 'LOGIN_OAUTH_ACCOUNT_NOT_LINKED', -					'user_row'		=> array(), +					'user_row'		=> [],  					'redirect_data'	=> $redirect_data, -				); +				];  			}  			// Retrieve the user's account  			$sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_ip, user_type, user_login_attempts  				FROM ' . $this->users_table . ' -					WHERE user_id = ' . (int) $row['user_id']; +				WHERE user_id = ' . (int) $row['user_id'];  			$result = $this->db->sql_query($sql);  			$row = $this->db->sql_fetchrow($result);  			$this->db->sql_freeresult($result);  			if (!$row)  			{ -				throw new \Exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_ENTRY'); +				return [ +					'status'		=> LOGIN_ERROR_EXTERNAL_AUTH, +					'error_msg'		=> 'AUTH_PROVIDER_OAUTH_ERROR_INVALID_ENTRY', +					'user_row'		=> ['user_id' => ANONYMOUS], +				];  			}  			/**  			 * Check if the user is banned. -			 * The fourth parameter, return, has to be true, -			 * otherwise the OAuth login is still called and -			 * an uncaught exception is thrown as there is no -			 * token stored in the database. +			 * The fourth parameter (return) has to be true, otherwise the OAuth login is still called and +			 * an uncaught exception is thrown as there is no token stored in the database.  			 */  			$ban = $this->user->check_ban($row['user_id'], $row['user_ip'], $row['user_email'], true); +  			if (!empty($ban))  			{  				$till_date = !empty($ban['ban_end']) ? $this->user->format_date($ban['ban_end']) : '';  				$message = !empty($ban['ban_end']) ? 'BOARD_BAN_TIME' : 'BOARD_BAN_PERM'; -				$contact_link = phpbb_get_board_contact_link($this->config, $this->phpbb_root_path, $this->php_ext); -				$message = $this->user->lang($message, $till_date, '<a href="' . $contact_link . '">', '</a>'); -				$message .= !empty($ban['ban_give_reason']) ? '<br /><br />' . $this->user->lang('BOARD_BAN_REASON', $ban['ban_give_reason']) : ''; -				$message .= !empty($ban['ban_triggered_by']) ? '<br /><br /><em>' . $this->user->lang('BAN_TRIGGERED_BY_' . strtoupper($ban['ban_triggered_by'])) . '</em>' : ''; +				$contact_link = phpbb_get_board_contact_link($this->config, $this->root_path, $this->php_ext); + +				$message = $this->language->lang($message, $till_date, '<a href="' . $contact_link . '">', '</a>'); +				$message .= !empty($ban['ban_give_reason']) ? '<br /><br />' . $this->language->lang('BOARD_BAN_REASON', $ban['ban_give_reason']) : ''; +				$message .= !empty($ban['ban_triggered_by']) ? '<br /><br /><em>' . $this->language->lang('BAN_TRIGGERED_BY_' . utf8_strtoupper($ban['ban_triggered_by'])) . '</em>' : ''; -				return array( +				return [  					'status'	=> LOGIN_BREAK,  					'error_msg'	=> $message,  					'user_row'	=> $row, -				); +				];  			}  			// Update token storage to store the user_id  			$storage->set_user_id($row['user_id']);  			/** -			* Event is triggered after user is successfully logged in via OAuth. -			* -			* @event core.auth_oauth_login_after -			* @var    array    row    User row -			* @since 3.1.11-RC1 -			*/ -			$vars = array( +			 * Event is triggered after user is successfully logged in via OAuth. +			 * +			 * @event core.auth_oauth_login_after +			 * @var array	row		User row +			 * @since 3.1.11-RC1 +			 */ +			$vars = [  				'row', -			); +			];  			extract($this->dispatcher->trigger_event('core.auth_oauth_login_after', compact($vars)));  			// The user is now authenticated and can be logged in -			return array( +			return [  				'status'		=> LOGIN_SUCCESS,  				'error_msg'		=> false,  				'user_row'		=> $row, -			); +			];  		}  		else  		{ -			if ($service::OAUTH_VERSION === 1) -			{ -				$token = $service->requestRequestToken(); -				$url = $service->getAuthorizationUri(array('oauth_token' => $token->getRequestToken())); -			} -			else -			{ -				$url = $service->getAuthorizationUri(); -			} -			header('Location: ' . $url); -		} -	} - -	/** -	* Returns the cached current_uri object or creates and caches it if it is -	* not already created. In each case the query string is updated based on -	* the $query parameter. -	* -	* @param	string	$service_name	The name of the service -	* @param	string	$query			The query string of the current_uri -	*									used in redirects -	* @return	\OAuth\Common\Http\Uri\UriInterface -	*/ -	protected function get_current_uri($service_name, $query) -	{ -		if ($this->current_uri) -		{ -			$this->current_uri->setQuery($query); -			return $this->current_uri; -		} - -		$uri_factory = new \OAuth\Common\Http\Uri\UriFactory(); -		$super_globals = $this->request->get_super_global(\phpbb\request\request_interface::SERVER); -		if (!empty($super_globals['HTTP_X_FORWARDED_PROTO']) && $super_globals['HTTP_X_FORWARDED_PROTO'] === 'https') -		{ -			$super_globals['HTTPS'] = 'on'; -			$super_globals['SERVER_PORT'] = 443; -		} -		$current_uri = $uri_factory->createFromSuperGlobalArray($super_globals); -		$current_uri->setQuery($query); - -		$this->current_uri = $current_uri; -		return $current_uri; -	} - -	/** -	* Returns a new service object -	* -	* @param	string	$service_name			The name of the service -	* @param	\phpbb\auth\provider\oauth\token_storage $storage -	* @param	array	$service_credentials	{@see \phpbb\auth\provider\oauth\oauth::get_service_credentials} -	* @param	string	$query					The query string of the -	*											current_uri used in redirection -	* @param	array	$scopes					The scope of the request against -	*											the api. -	* @return	\OAuth\Common\Service\ServiceInterface -	* @throws	\Exception -	*/ -	protected function get_service($service_name, \phpbb\auth\provider\oauth\token_storage $storage, array $service_credentials, $query, array $scopes = array()) -	{ -		$current_uri = $this->get_current_uri($service_name, $query); - -		// Setup the credentials for the requests -		$credentials = new Credentials( -			$service_credentials['key'], -			$service_credentials['secret'], -			$current_uri->getAbsoluteUri() -		); - -		$service_factory = new \OAuth\ServiceFactory(); -		$service = $service_factory->createService($service_name, $credentials, $storage, $scopes); - -		if (!$service) -		{ -			throw new \Exception('AUTH_PROVIDER_OAUTH_ERROR_SERVICE_NOT_CREATED'); +			return $this->set_redirect($service);  		} - -		return $service;  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function get_login_data()  	{ -		$login_data = array( +		$login_data = [  			'TEMPLATE_FILE'		=> 'login_body_oauth.html',  			'BLOCK_VAR_NAME'	=> 'oauth', -			'BLOCK_VARS'		=> array(), -		); +			'BLOCK_VARS'		=> [], +		];  		foreach ($this->service_providers as $service_name => $service_provider)  		{  			// Only include data if the credentials are set  			$credentials = $service_provider->get_service_credentials(); +  			if ($credentials['key'] && $credentials['secret'])  			{ -				$actual_name = str_replace('auth.provider.oauth.service.', '', $service_name); -				$redirect_url = generate_board_url() . '/ucp.' . $this->php_ext . '?mode=login&login=external&oauth_service=' . $actual_name; -				$login_data['BLOCK_VARS'][$service_name] = array( +				$provider = $this->get_provider($service_name); +				$redirect_url = generate_board_url() . '/ucp.' . $this->php_ext . '?mode=login&login=external&oauth_service=' . $provider; + +				$login_data['BLOCK_VARS'][$service_name] = [  					'REDIRECT_URL'	=> redirect($redirect_url, true), -					'SERVICE_NAME'	=> $this->user->lang['AUTH_PROVIDER_OAUTH_SERVICE_' . strtoupper($actual_name)], -				); +					'SERVICE_NAME'	=> $this->get_provider_title($provider), +				];  			}  		} @@ -440,51 +362,55 @@ class oauth extends \phpbb\auth\provider\base  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function acp()  	{ -		$ret = array(); +		$ret = [];  		foreach ($this->service_providers as $service_name => $service_provider)  		{ -			$actual_name = str_replace('auth.provider.oauth.service.', '', $service_name); -			$ret[] = 'auth_oauth_' . $actual_name . '_key'; -			$ret[] = 'auth_oauth_' . $actual_name . '_secret'; +			$provider = $this->get_provider($service_name); + +			$provider = utf8_strtolower($provider); + +			$ret[] = 'auth_oauth_' . $provider . '_key'; +			$ret[] = 'auth_oauth_' . $provider . '_secret';  		}  		return $ret;  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function get_acp_template($new_config)  	{ -		$ret = array( +		$ret = [  			'BLOCK_VAR_NAME'	=> 'oauth_services', -			'BLOCK_VARS'		=> array(), +			'BLOCK_VARS'		=> [],  			'TEMPLATE_FILE'		=> 'auth_provider_oauth.html', -			'TEMPLATE_VARS'		=> array(), -		); +			'TEMPLATE_VARS'		=> [], +		];  		foreach ($this->service_providers as $service_name => $service_provider)  		{ -			$actual_name = str_replace('auth.provider.oauth.service.', '', $service_name); -			$ret['BLOCK_VARS'][$actual_name] = array( -				'ACTUAL_NAME'	=> $this->user->lang['AUTH_PROVIDER_OAUTH_SERVICE_' . strtoupper($actual_name)], -				'KEY'			=> $new_config['auth_oauth_' . $actual_name . '_key'], -				'NAME'			=> $actual_name, -				'SECRET'		=> $new_config['auth_oauth_' . $actual_name . '_secret'], -			); +			$provider = $this->get_provider($service_name); + +			$ret['BLOCK_VARS'][$provider] = [ +				'NAME'			=> $provider, +				'ACTUAL_NAME'	=> $this->get_provider_title($provider), +				'KEY'			=> $new_config['auth_oauth_' . utf8_strtolower($provider) . '_key'], +				'SECRET'		=> $new_config['auth_oauth_' . utf8_strtolower($provider) . '_secret'], +			];  		}  		return $ret;  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function login_link_has_necessary_data($login_link_data)  	{  		if (empty($login_link_data)) @@ -502,16 +428,13 @@ class oauth extends \phpbb\auth\provider\base  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function link_account(array $link_data)  	{  		// Check for a valid link method (auth_link or login_link)  		if (!array_key_exists('link_method', $link_data) || -			!in_array($link_data['link_method'], array( -				'auth_link', -				'login_link', -			))) +			!in_array($link_data['link_method'], ['auth_link', 'login_link']))  		{  			return 'LOGIN_LINK_MISSING_DATA';  		} @@ -527,7 +450,8 @@ class oauth extends \phpbb\auth\provider\base  			}  		} -		$service_name = 'auth.provider.oauth.service.' . strtolower($link_data['oauth_service']); +		$service_name = $this->get_service_name($link_data['oauth_service']); +  		if (!array_key_exists($service_name, $this->service_providers))  		{  			return 'LOGIN_ERROR_OAUTH_SERVICE_DOES_NOT_EXIST'; @@ -539,21 +463,109 @@ class oauth extends \phpbb\auth\provider\base  				return $this->link_account_auth_link($link_data, $service_name);  			case 'login_link':  				return $this->link_account_login_link($link_data, $service_name); +			default: +				return 'LOGIN_LINK_MISSING_DATA'; +		} +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function logout($data, $new_session) +	{ +		// Clear all tokens belonging to the user +		$storage = new token_storage($this->db, $this->user, $this->oauth_token_table, $this->oauth_state_table); +		$storage->clearAllTokens(); + +		return; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_auth_link_data($user_id = 0) +	{ +		$user_ids	= []; +		$block_vars	= []; + +		$sql = 'SELECT oauth_provider_id, provider + 			FROM ' . $this->oauth_account_table . ' +			WHERE user_id = ' . ($user_id > 0 ? (int) $user_id : (int) $this->user->data['user_id']); +		$result = $this->db->sql_query($sql); +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$user_ids[$row['provider']] = $row['oauth_provider_id']; +		} +		$this->db->sql_freeresult($result); + +		foreach ($this->service_providers as $service_name => $service_provider) +		{ +			// Only include data if the credentials are set +			$credentials = $service_provider->get_service_credentials(); + +			if ($credentials['key'] && $credentials['secret']) +			{ +				$provider = $this->get_provider($service_name); + +				$block_vars[$service_name] = [ +					'SERVICE_NAME'	=> $this->get_provider_title($provider), +					'UNIQUE_ID'		=> isset($user_ids[$provider]) ? $user_ids[$provider] : null, +					'HIDDEN_FIELDS'	=> [ +						'link'			=> !isset($user_ids[$provider]), +						'oauth_service' => $provider, +					], +				]; +			} +		} + +		return [ +			'BLOCK_VAR_NAME'	=> 'oauth', +			'BLOCK_VARS'		=> $block_vars, + +			'TEMPLATE_FILE'		=> 'ucp_auth_link_oauth.html', +		]; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function unlink_account(array $link_data) +	{ +		if (!array_key_exists('oauth_service', $link_data) || !$link_data['oauth_service']) +		{ +			return 'LOGIN_LINK_MISSING_DATA';  		} + +		// Remove user specified in $link_data if possible +		$user_id = isset($link_data['user_id']) ? $link_data['user_id'] : $this->user->data['user_id']; + +		// Remove the link +		$sql = 'DELETE FROM ' . $this->oauth_account_table . " +			WHERE provider = '" . $this->db->sql_escape($link_data['oauth_service']) . "' +				AND user_id = " . (int) $user_id; +		$this->db->sql_query($sql); + +		$service_name = $this->get_service_name($link_data['oauth_service']); + +		// Clear all tokens belonging to the user on this service +		$storage = new token_storage($this->db, $this->user, $this->oauth_token_table, $this->oauth_state_table); +		$storage->clearToken($service_name); + +		return false;  	}  	/** -	* Performs the account linking for login_link -	* -	* @param	array	$link_data		The same variable given to {@see \phpbb\auth\provider\provider_interface::link_account} -	* @param	string	$service_name	The name of the service being used in -	*									linking. -	* @return	string|null	Returns a language constant (string) if an error is -	*						encountered, or null on success. -	*/ +	 * Performs the account linking for login_link. +	 * +	 * @param array		$link_data		The same variable given to +	 * 									{@see \phpbb\auth\provider\provider_interface::link_account} +	 * @param string	$service_name	The name of the service being used in linking. +	 * @return string|false				Returns a language key (string) if an error is encountered, +	 * 									or false on success. +	 */  	protected function link_account_login_link(array $link_data, $service_name)  	{ -		$storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table, $this->auth_provider_oauth_state_table); +		$storage = new token_storage($this->db, $this->user, $this->oauth_token_table, $this->oauth_state_table);  		// Check for an access token, they should have one  		if (!$storage->has_access_token_by_session($service_name)) @@ -561,87 +573,109 @@ class oauth extends \phpbb\auth\provider\base  			return 'LOGIN_LINK_ERROR_OAUTH_NO_ACCESS_TOKEN';  		} -		// Prepare the query string -		$query = 'mode=login_link&login_link_oauth_service=' . strtolower($link_data['oauth_service']); -  		// Prepare for an authentication request -		$service_credentials = $this->service_providers[$service_name]->get_service_credentials(); -		$scopes = $this->service_providers[$service_name]->get_auth_scope(); -		$service = $this->get_service(strtolower($link_data['oauth_service']), $storage, $service_credentials, $query, $scopes); +		$query = 'mode=login_link&login_link_oauth_service=' . $link_data['oauth_service']; + +		try +		{ +			$service = $this->get_service($link_data['oauth_service'], $storage, $query); +		} +		catch (\Exception $e) +		{ +			return $e->getMessage(); +		} +  		$this->service_providers[$service_name]->set_external_service_provider($service); -		// The user has already authenticated successfully, request to authenticate again -		$unique_id = $this->service_providers[$service_name]->perform_token_auth(); +		try +		{ +			// The user has already authenticated successfully, request to authenticate again +			$unique_id = $this->service_providers[$service_name]->perform_token_auth(); +		} +		catch (exception $e) +		{ +			return $e->getMessage(); +		}  		// Insert into table, they will be able to log in after this -		$data = array( +		$data = [  			'user_id'			=> $link_data['user_id'], -			'provider'			=> strtolower($link_data['oauth_service']), +			'provider'			=> utf8_strtolower($link_data['oauth_service']),  			'oauth_provider_id'	=> $unique_id, -		); +		];  		$this->link_account_perform_link($data); +  		// Update token storage to store the user_id  		$storage->set_user_id($link_data['user_id']); + +		return false;  	}  	/** -	* Performs the account linking for auth_link -	* -	* @param	array	$link_data		The same variable given to {@see \phpbb\auth\provider\provider_interface::link_account} -	* @param	string	$service_name	The name of the service being used in -	*									linking. -	* @return	string|null	Returns a language constant (string) if an error is -	*						encountered, or null on success. -	*/ +	 * Performs the account linking for auth_link. +	 * +	 * @param array		$link_data		The same variable given to +	 * 									{@see \phpbb\auth\provider\provider_interface::link_account} +	 * @param string	$service_name	The name of the service being used in linking. +	 * @return string|false				Returns a language constant (string) if an error is encountered, +	 * 									or false on success. +	 */  	protected function link_account_auth_link(array $link_data, $service_name)  	{ -		$storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table, $this->auth_provider_oauth_state_table); -		$query = 'i=ucp_auth_link&mode=auth_link&link=1&oauth_service=' . strtolower($link_data['oauth_service']); -		$service_credentials = $this->service_providers[$service_name]->get_service_credentials(); -		$scopes = $this->service_providers[$service_name]->get_auth_scope(); -		$service = $this->get_service(strtolower($link_data['oauth_service']), $storage, $service_credentials, $query, $scopes); +		$storage = new token_storage($this->db, $this->user, $this->oauth_token_table, $this->oauth_state_table); +		$query = 'i=ucp_auth_link&mode=auth_link&link=1&oauth_service=' . $link_data['oauth_service']; -		if (($service::OAUTH_VERSION === 2 && $this->request->is_set('code', \phpbb\request\request_interface::GET)) -			|| ($service::OAUTH_VERSION === 1 && $this->request->is_set('oauth_token', \phpbb\request\request_interface::GET))) +		try +		{ +			/** @var OAuth1Service|OAuth2Service $service */ +			$service = $this->get_service($link_data['oauth_service'], $storage, $query); +		} +		catch (\Exception $e) +		{ +			return $e->getMessage(); +		} + +		if ($this->is_set_code($service))  		{  			$this->service_providers[$service_name]->set_external_service_provider($service); -			$unique_id = $this->service_providers[$service_name]->perform_auth_login(); + +			try +			{ +				$unique_id = $this->service_providers[$service_name]->perform_auth_login(); +			} +			catch (exception $e) +			{ +				return $e->getMessage(); +			}  			// Insert into table, they will be able to log in after this -			$data = array( +			$data = [  				'user_id'			=> $this->user->data['user_id'], -				'provider'			=> strtolower($link_data['oauth_service']), +				'provider'			=> utf8_strtolower($link_data['oauth_service']),  				'oauth_provider_id'	=> $unique_id, -			); +			];  			$this->link_account_perform_link($data); + +			return false;  		}  		else  		{ -			if ($service::OAUTH_VERSION === 1) -			{ -				$token = $service->requestRequestToken(); -				$url = $service->getAuthorizationUri(array('oauth_token' => $token->getRequestToken())); -			} -			else -			{ -				$url = $service->getAuthorizationUri(); -			} -			header('Location: ' . $url); +			return $this->set_redirect($service);  		}  	}  	/** -	* Performs the query that inserts an account link -	* -	* @param	array	$data	This array is passed to db->sql_build_array -	*/ +	 * Performs the query that inserts an account link +	 * +	 * @param	array	$data	This array is passed to db->sql_build_array +	 */  	protected function link_account_perform_link(array $data)  	{  		// Check if the external account is already associated with other user  		$sql = 'SELECT user_id -			FROM ' . $this->auth_provider_oauth_token_account_assoc . " +			FROM ' . $this->oauth_account_table . "  			WHERE provider = '" . $this->db->sql_escape($data['provider']) . "'  				AND oauth_provider_id = '" . $this->db->sql_escape($data['oauth_provider_id']) . "'";  		$result = $this->db->sql_query($sql); @@ -654,114 +688,172 @@ class oauth extends \phpbb\auth\provider\base  		}  		// Link account -		$sql = 'INSERT INTO ' . $this->auth_provider_oauth_token_account_assoc . ' -			' . $this->db->sql_build_array('INSERT', $data); +		$sql = 'INSERT INTO ' . $this->oauth_account_table . ' ' . $this->db->sql_build_array('INSERT', $data);  		$this->db->sql_query($sql);  		/**  		 * Event is triggered after user links account.  		 *  		 * @event core.auth_oauth_link_after -		 * @var    array    data    User row +		 * @var array	data	User row  		 * @since 3.1.11-RC1  		 */ -		$vars = array( +		$vars = [  			'data', -		); +		];  		extract($this->dispatcher->trigger_event('core.auth_oauth_link_after', compact($vars)));  	}  	/** -	* {@inheritdoc} -	*/ -	public function logout($data, $new_session) +	 * Returns a new service object. +	 * +	 * @param string			$provider		The name of the provider +	 * @param token_storage		$storage		Token storage object +	 * @param string			$query			The query string used for the redirect uri +	 * @return ServiceInterface +	 * @throws exception						When OAuth service was not created +	 */ +	protected function get_service($provider, token_storage $storage, $query)  	{ -		// Clear all tokens belonging to the user -		$storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table, $this->auth_provider_oauth_state_table); -		$storage->clearAllTokens(); +		$service_name = $this->get_service_name($provider); -		return; -	} +		/** @see \phpbb\auth\provider\oauth\service\service_interface::get_service_credentials */ +		$service_credentials = $this->service_providers[$service_name]->get_service_credentials(); -	/** -	* {@inheritdoc} -	*/ -	public function get_auth_link_data($user_id = 0) -	{ -		$block_vars = array(); +		/** @see \phpbb\auth\provider\oauth\service\service_interface::get_auth_scope */ +		$scopes = $this->service_providers[$service_name]->get_auth_scope(); -		// Get all external accounts tied to the current user -		$data = array( -			'user_id' => ($user_id <= 0) ? (int) $this->user->data['user_id'] : (int) $user_id, +		$callback = generate_board_url() . "/ucp.{$this->php_ext}?{$query}"; + +		// Setup the credentials for the requests +		$credentials = new Credentials( +			$service_credentials['key'], +			$service_credentials['secret'], +			$callback  		); -		$sql = 'SELECT oauth_provider_id, provider FROM ' . $this->auth_provider_oauth_token_account_assoc . ' -			WHERE ' . $this->db->sql_build_array('SELECT', $data); -		$result = $this->db->sql_query($sql); -		$rows = $this->db->sql_fetchrowset($result); -		$this->db->sql_freeresult($result); -		$oauth_user_ids = array(); +		$service_factory = new ServiceFactory; -		if ($rows !== false && count($rows)) +		// Allow providers to register a custom class or override the provider name +		if ($class = $this->service_providers[$service_name]->get_external_service_class())  		{ -			foreach ($rows as $row) +			if (class_exists($class)) +			{ +				try +				{ +					$service_factory->registerService($provider, $class); +				} +				catch (\OAuth\Common\Exception\Exception $e) +				{ +					throw new exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE'); +				} +			} +			else  			{ -				$oauth_user_ids[$row['provider']] = $row['oauth_provider_id']; +				$provider = $class;  			}  		} -		unset($rows); -		foreach ($this->service_providers as $service_name => $service_provider) +		$service = $service_factory->createService($provider, $credentials, $storage, $scopes); + +		if (!$service)  		{ -			// Only include data if the credentials are set -			$credentials = $service_provider->get_service_credentials(); -			if ($credentials['key'] && $credentials['secret']) -			{ -				$actual_name = str_replace('auth.provider.oauth.service.', '', $service_name); - -				$block_vars[$service_name] = array( -					'HIDDEN_FIELDS'	=> array( -						'link'			=> (!isset($oauth_user_ids[$actual_name])), -						'oauth_service' => $actual_name, -					), - -					'SERVICE_ID'	=> $actual_name, -					'SERVICE_NAME'	=> $this->user->lang['AUTH_PROVIDER_OAUTH_SERVICE_' . strtoupper($actual_name)], -					'UNIQUE_ID'		=> (isset($oauth_user_ids[$actual_name])) ? $oauth_user_ids[$actual_name] : null, -				); -			} +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_SERVICE_NOT_CREATED');  		} -		return array( -			'BLOCK_VAR_NAME'	=> 'oauth', -			'BLOCK_VARS'		=> $block_vars, +		return $service; +	} -			'TEMPLATE_FILE'	=> 'ucp_auth_link_oauth.html', -		); +	/** +	 * Returns the service name for an OAuth provider name. +	 * +	 * @param string	$provider		The OAuth provider name +	 * @return string					The service name +	 */ +	protected function get_service_name($provider) +	{ +		if (strpos($provider, 'auth.provider.oauth.service.') !== 0) +		{ +			$provider = 'auth.provider.oauth.service.' . utf8_strtolower($provider); +		} + +		return $provider;  	}  	/** -	* {@inheritdoc} -	*/ -	public function unlink_account(array $link_data) +	 * Returns the OAuth provider name from a service name. +	 * +	 * @param string	$service_name	The service name +	 * @return string					The OAuth provider name +	 */ +	protected function get_provider($service_name)  	{ -		if (!array_key_exists('oauth_service', $link_data) || !$link_data['oauth_service']) +		return str_replace('auth.provider.oauth.service.', '', $service_name); +	} + +	/** +	 * Returns the localized title for the OAuth provider. +	 * +	 * @param string	$provider		The OAuth provider name +	 * @return string					The OAuth provider title +	 */ +	protected function get_provider_title($provider) +	{ +		return $this->language->lang('AUTH_PROVIDER_OAUTH_SERVICE_' . utf8_strtoupper($provider)); +	} + +	/** +	 * Returns whether or not the authorization code is set. +	 * +	 * @param OAuth1Service|OAuth2Service	$service	The external OAuth service +	 * @return bool										Whether or not the authorization code is set in the URL +	 *                       							for the respective OAuth service's version +	 */ +	protected function is_set_code($service) +	{ +		switch ($service::OAUTH_VERSION)  		{ -			return 'LOGIN_LINK_MISSING_DATA'; +			case 1: +				return $this->request->is_set('oauth_token', request_interface::GET); + +			case 2: +				return $this->request->is_set('code', request_interface::GET); + +			default: +				return false;  		} +	} -		// Remove user specified in $link_data if possible -		$user_id = isset($link_data['user_id']) ? $link_data['user_id'] : $this->user->data['user_id']; +	/** +	 * Sets a redirect to the authorization uri. +	 * +	 * @param OAuth1Service|OAuth2Service $service		The external OAuth service +	 * @return array|false								Array if an error occurred, +	 *                            						false on success +	 */ +	protected function set_redirect($service) +	{ +		$parameters = []; -		// Remove the link -		$sql = 'DELETE FROM ' . $this->auth_provider_oauth_token_account_assoc . " -			WHERE provider = '" . $this->db->sql_escape($link_data['oauth_service']) . "' -				AND user_id = " . (int) $user_id; -		$this->db->sql_query($sql); +		if ($service::OAUTH_VERSION === 1) +		{ +			try +			{ +				$token		= $service->requestRequestToken(); +				$parameters	= ['oauth_token' => $token->getRequestToken()]; +			} +			catch (TokenResponseException $e) +			{ +				return [ +					'status'		=> LOGIN_ERROR_EXTERNAL_AUTH, +					'error_msg'		=> $e->getMessage(), +					'user_row'		=> ['user_id' => ANONYMOUS], +				]; +			} +		} -		// Clear all tokens belonging to the user on this service -		$service_name = 'auth.provider.oauth.service.' . strtolower($link_data['oauth_service']); -		$storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table, $this->auth_provider_oauth_state_table); -		$storage->clearToken($service_name); +		redirect($service->getAuthorizationUri($parameters), false, true); + +		return false;  	}  } diff --git a/phpBB/phpbb/auth/provider/oauth/service/base.php b/phpBB/phpbb/auth/provider/oauth/service/base.php index 6adf64aa30..5ab426a0aa 100644 --- a/phpBB/phpbb/auth/provider/oauth/service/base.php +++ b/phpBB/phpbb/auth/provider/oauth/service/base.php @@ -1,49 +1,57 @@  <?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. -* -*/ + * + * 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\auth\provider\oauth\service;  /** -* Base OAuth abstract class that all OAuth services should implement -*/ -abstract class base implements \phpbb\auth\provider\oauth\service\service_interface + * Base OAuth abstract class that all OAuth services should implement + */ +abstract class base implements service_interface  {  	/** -	* External OAuth service provider -	* -	* @var \OAuth\Common\Service\ServiceInterface -	*/ +	 * External OAuth service provider +	 * +	 * @var \OAuth\Common\Service\ServiceInterface +	 */  	protected $service_provider;  	/** -	* {@inheritdoc} -	*/ -	public function get_external_service_provider() +	 * {@inheritdoc} +	 */ +	public function get_auth_scope()  	{ -		return $this->service_provider; +		return [];  	}  	/** -	* {@inheritdoc} -	*/ -	public function get_auth_scope() +	 * {@inheritdoc} +	 */ +	public function get_external_service_class() +	{ +		return ''; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_external_service_provider()  	{ -		return array(); +		return $this->service_provider;  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function set_external_service_provider(\OAuth\Common\Service\ServiceInterface $service_provider)  	{  		$this->service_provider = $service_provider; diff --git a/phpBB/phpbb/auth/provider/oauth/service/bitly.php b/phpBB/phpbb/auth/provider/oauth/service/bitly.php index 25e731a02c..ca131b2019 100644 --- a/phpBB/phpbb/auth/provider/oauth/service/bitly.php +++ b/phpBB/phpbb/auth/provider/oauth/service/bitly.php @@ -1,94 +1,107 @@  <?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. -* -*/ + * + * 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\auth\provider\oauth\service;  /** -* Bitly OAuth service -*/ -class bitly extends \phpbb\auth\provider\oauth\service\base + * Bitly OAuth service + */ +class bitly extends base  { -	/** -	* phpBB config -	* -	* @var \phpbb\config\config -	*/ +	/** @var \phpbb\config\config */  	protected $config; -	/** -	* phpBB request -	* -	* @var \phpbb\request\request_interface -	*/ +	/** @var \phpbb\request\request_interface */  	protected $request;  	/** -	* Constructor -	* -	* @param	\phpbb\config\config				$config -	* @param	\phpbb\request\request_interface	$request -	*/ +	 * Constructor. +	 * +	 * @param \phpbb\config\config				$config		Config object +	 * @param \phpbb\request\request_interface	$request	Request object +	 */  	public function __construct(\phpbb\config\config $config, \phpbb\request\request_interface $request)  	{ -		$this->config = $config; -		$this->request = $request; +		$this->config	= $config; +		$this->request	= $request;  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function get_service_credentials()  	{ -		return array( +		return [  			'key'		=> $this->config['auth_oauth_bitly_key'],  			'secret'	=> $this->config['auth_oauth_bitly_secret'], -		); +		];  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function perform_auth_login()  	{  		if (!($this->service_provider instanceof \OAuth\OAuth2\Service\Bitly))  		{ -			throw new \phpbb\auth\provider\oauth\service\exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE'); +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE');  		} -		// This was a callback request from bitly, get the token -		$this->service_provider->requestAccessToken($this->request->variable('code', '')); +		try +		{ +			// This was a callback request, get the token +			$this->service_provider->requestAccessToken($this->request->variable('code', '')); +		} +		catch (\OAuth\Common\Http\Exception\TokenResponseException $e) +		{ +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_REQUEST'); +		} -		// Send a request with it -		$result = json_decode($this->service_provider->request('user/info'), true); +		try +		{ +			// Send a request with it +			$result = (array) json_decode($this->service_provider->request('user/info'), true); +		} +		catch (\OAuth\Common\Exception\Exception $e) +		{ +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_REQUEST'); +		}  		// Return the unique identifier returned from bitly  		return $result['data']['login'];  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function perform_token_auth()  	{  		if (!($this->service_provider instanceof \OAuth\OAuth2\Service\Bitly))  		{ -			throw new \phpbb\auth\provider\oauth\service\exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE'); +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE');  		} -		// Send a request with it -		$result = json_decode($this->service_provider->request('user/info'), true); +		try +		{ +			// Send a request with it +			$result = (array) json_decode($this->service_provider->request('user/info'), true); +		} +		catch (\OAuth\Common\Exception\Exception $e) +		{ +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_REQUEST'); +		} -		// Return the unique identifier returned from bitly +		// Return the unique identifier  		return $result['data']['login'];  	}  } diff --git a/phpBB/phpbb/auth/provider/oauth/service/facebook.php b/phpBB/phpbb/auth/provider/oauth/service/facebook.php index bb98835e07..f7dbe307eb 100644 --- a/phpBB/phpbb/auth/provider/oauth/service/facebook.php +++ b/phpBB/phpbb/auth/provider/oauth/service/facebook.php @@ -1,63 +1,55 @@  <?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. -* -*/ + * + * 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\auth\provider\oauth\service;  /** -* Facebook OAuth service -*/ + * Facebook OAuth service + */  class facebook extends base  { -	/** -	* phpBB config -	* -	* @var \phpbb\config\config -	*/ +	/** @var \phpbb\config\config */  	protected $config; -	/** -	* phpBB request -	* -	* @var \phpbb\request\request_interface -	*/ +	/** @var \phpbb\request\request_interface */  	protected $request;  	/** -	* Constructor -	* -	* @param	\phpbb\config\config				$config -	* @param	\phpbb\request\request_interface 	$request -	*/ +	 * Constructor. +	 * +	 * @param \phpbb\config\config				$config		Config object +	 * @param \phpbb\request\request_interface	$request	Request object +	 */  	public function __construct(\phpbb\config\config $config, \phpbb\request\request_interface $request)  	{ -		$this->config = $config; -		$this->request = $request; +		$this->config	= $config; +		$this->request	= $request;  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function get_service_credentials()  	{ -		return array( +		return [  			'key'		=> $this->config['auth_oauth_facebook_key'],  			'secret'	=> $this->config['auth_oauth_facebook_secret'], -		); +		];  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function perform_auth_login()  	{  		if (!($this->service_provider instanceof \OAuth\OAuth2\Service\Facebook)) @@ -65,19 +57,33 @@ class facebook extends base  			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE');  		} -		// This was a callback request, get the token -		$this->service_provider->requestAccessToken($this->request->variable('code', '')); +		try +		{ +			// This was a callback request, get the token +			$this->service_provider->requestAccessToken($this->request->variable('code', '')); +		} +		catch (\OAuth\Common\Http\Exception\TokenResponseException $e) +		{ +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_REQUEST'); +		} -		// Send a request with it -		$result = json_decode($this->service_provider->request('/me'), true); +		try +		{ +			// Send a request with it +			$result = (array) json_decode($this->service_provider->request('/me'), true); +		} +		catch (\OAuth\Common\Exception\Exception $e) +		{ +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_REQUEST'); +		}  		// Return the unique identifier  		return $result['id'];  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function perform_token_auth()  	{  		if (!($this->service_provider instanceof \OAuth\OAuth2\Service\Facebook)) @@ -85,8 +91,15 @@ class facebook extends base  			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE');  		} -		// Send a request with it -		$result = json_decode($this->service_provider->request('/me'), true); +		try +		{ +			// Send a request with it +			$result = (array) json_decode($this->service_provider->request('/me'), true); +		} +		catch (\OAuth\Common\Exception\Exception $e) +		{ +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_REQUEST'); +		}  		// Return the unique identifier  		return $result['id']; diff --git a/phpBB/phpbb/auth/provider/oauth/service/google.php b/phpBB/phpbb/auth/provider/oauth/service/google.php index cb9f83a94f..6e671ab13e 100644 --- a/phpBB/phpbb/auth/provider/oauth/service/google.php +++ b/phpBB/phpbb/auth/provider/oauth/service/google.php @@ -1,74 +1,66 @@  <?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. -* -*/ + * + * 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\auth\provider\oauth\service;  /** -* Google OAuth service -*/ + * Google OAuth service + */  class google extends base  { -	/** -	* phpBB config -	* -	* @var \phpbb\config\config -	*/ +	/** @var \phpbb\config\config */  	protected $config; -	/** -	* phpBB request -	* -	* @var \phpbb\request\request_interface -	*/ +	/** @var \phpbb\request\request_interface */  	protected $request;  	/** -	* Constructor -	* -	* @param	\phpbb\config\config				$config -	* @param	\phpbb\request\request_interface 	$request -	*/ +	 * Constructor. +	 * +	 * @param \phpbb\config\config				$config		Config object +	 * @param \phpbb\request\request_interface	$request	Request object +	 */  	public function __construct(\phpbb\config\config $config, \phpbb\request\request_interface $request)  	{ -		$this->config = $config; -		$this->request = $request; +		$this->config	= $config; +		$this->request	= $request;  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function get_auth_scope()  	{ -		return array( +		return [  			'userinfo_email',  			'userinfo_profile', -		); +		];  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function get_service_credentials()  	{ -		return array( +		return [  			'key'		=> $this->config['auth_oauth_google_key'],  			'secret'	=> $this->config['auth_oauth_google_secret'], -		); +		];  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function perform_auth_login()  	{  		if (!($this->service_provider instanceof \OAuth\OAuth2\Service\Google)) @@ -76,19 +68,33 @@ class google extends base  			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE');  		} -		// This was a callback request, get the token -		$this->service_provider->requestAccessToken($this->request->variable('code', '')); +		try +		{ +			// This was a callback request, get the token +			$this->service_provider->requestAccessToken($this->request->variable('code', '')); +		} +		catch (\OAuth\Common\Http\Exception\TokenResponseException $e) +		{ +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_REQUEST'); +		} -		// Send a request with it -		$result = json_decode($this->service_provider->request('https://www.googleapis.com/oauth2/v1/userinfo'), true); +		try +		{ +			// Send a request with it +			$result = (array) json_decode($this->service_provider->request('https://www.googleapis.com/oauth2/v1/userinfo'), true); +		} +		catch (\OAuth\Common\Exception\Exception $e) +		{ +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_REQUEST'); +		}  		// Return the unique identifier  		return $result['id'];  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function perform_token_auth()  	{  		if (!($this->service_provider instanceof \OAuth\OAuth2\Service\Google)) @@ -96,8 +102,15 @@ class google extends base  			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE');  		} -		// Send a request with it -		$result = json_decode($this->service_provider->request('https://www.googleapis.com/oauth2/v1/userinfo'), true); +		try +		{ +			// Send a request with it +			$result = (array) json_decode($this->service_provider->request('https://www.googleapis.com/oauth2/v1/userinfo'), true); +		} +		catch (\OAuth\Common\Exception\Exception $e) +		{ +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_REQUEST'); +		}  		// Return the unique identifier  		return $result['id']; diff --git a/phpBB/phpbb/auth/provider/oauth/service/service_interface.php b/phpBB/phpbb/auth/provider/oauth/service/service_interface.php index e84eb247b6..239e661989 100644 --- a/phpBB/phpbb/auth/provider/oauth/service/service_interface.php +++ b/phpBB/phpbb/auth/provider/oauth/service/service_interface.php @@ -1,73 +1,85 @@  <?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. -* -*/ + * + * 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\auth\provider\oauth\service;  /** -* OAuth service interface -*/ + * OAuth service interface + */  interface service_interface  {  	/** -	* Returns an array of the scopes necessary for auth -	* -	* @return	array	An array of the required scopes -	*/ +	 * Returns an array of the scopes necessary for auth +	 * +	 * @return array	An array of the required scopes +	 */  	public function get_auth_scope();  	/** -	* Returns the external library service provider once it has been set -	* -	* @param	\OAuth\Common\Service\ServiceInterface|null -	*/ -	public function get_external_service_provider(); - -	/** -	* Returns an array containing the service credentials belonging to requested -	* service. -	* -	* @return	array	An array containing the 'key' and the 'secret' of the -	*					service in the form: -	*						array( -	*							'key'		=> string -	*							'secret'	=> string -	*						) -	*/ +	 * Returns an array containing the service credentials belonging to requested +	 * service. +	 * +	 * @return array	An array containing the 'key' and the 'secret' of the +	 *					service in the form: +	 *						array( +	 *							'key'		=> string +	 *							'secret'	=> string +	 *						) +	 */  	public function get_service_credentials();  	/** -	* Returns the results of the authentication in json format -	* -	* @throws	\phpbb\auth\provider\oauth\service\exception -	* @return	string	The unique identifier returned by the service provider -	*					that is used to authenticate the user with phpBB. -	*/ +	 * Returns the results of the authentication in json format +	 * +	 * @throws \phpbb\auth\provider\oauth\service\exception +	 * @return string	The unique identifier returned by the service provider +	 *					that is used to authenticate the user with phpBB. +	 */  	public function perform_auth_login();  	/** -	* Returns the results of the authentication in json format -	* Use this function when the user already has an access token -	* -	* @throws	\phpbb\auth\provider\oauth\service\exception -	* @return	string	The unique identifier returned by the service provider -	*					that is used to authenticate the user with phpBB. -	*/ +	 * Returns the results of the authentication in json format +	 * Use this function when the user already has an access token +	 * +	 * @throws \phpbb\auth\provider\oauth\service\exception +	 * @return string	The unique identifier returned by the service provider +	 *					that is used to authenticate the user with phpBB. +	 */  	public function perform_token_auth();  	/** -	* Sets the external library service provider -	* -	* @param	\OAuth\Common\Service\ServiceInterface	$service_provider -	*/ +	 * Returns the class of external library service provider that has to be used. +	 * +	 * @return string	If the string is a class, it will register the provided string as a class, +	 *						which later will be generated as the OAuth external service provider. +	 * 					If the string is not a class, it will use this string, +	 * 						trying to generate a service for the version 2 and 1 respectively: +	 * 						\OAuth\OAuth2\Service\<string> +	 * 					If the string is empty, it will default to OAuth's standard service classes, +	 * 						trying to generate a service for the version 2 and 1 respectively: +	 * 						\OAuth\OAuth2\Service\Facebook +	 */ +	public function get_external_service_class(); + +	/** +	 * Returns the external library service provider once it has been set +	 */ +	public function get_external_service_provider(); + +	/** +	 * Sets the external library service provider +	 * +	 * @param \OAuth\Common\Service\ServiceInterface	$service_provider +	 */  	public function set_external_service_provider(\OAuth\Common\Service\ServiceInterface $service_provider);  } diff --git a/phpBB/phpbb/auth/provider/oauth/service/twitter.php b/phpBB/phpbb/auth/provider/oauth/service/twitter.php index 06beac51e2..35cbc9e4f7 100644 --- a/phpBB/phpbb/auth/provider/oauth/service/twitter.php +++ b/phpBB/phpbb/auth/provider/oauth/service/twitter.php @@ -1,102 +1,111 @@  <?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. -* -*/ + * + * 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\auth\provider\oauth\service;  /** -* Twitter OAuth service -*/ -class twitter extends \phpbb\auth\provider\oauth\service\base + * Twitter OAuth service + */ +class twitter extends base  { -	/** -	* phpBB config -	* -	* @var \phpbb\config\config -	*/ +	/** @var \phpbb\config\config */  	protected $config; -	/** -	* phpBB request -	* -	* @var \phpbb\request\request_interface -	*/ +	/** @var \phpbb\request\request_interface */  	protected $request;  	/** -	* Constructor -	* -	* @param	\phpbb\config\config				$config -	* @param	\phpbb\request\request_interface	$request -	*/ +	 * Constructor. +	 * +	 * @param \phpbb\config\config				$config		Config object +	 * @param \phpbb\request\request_interface	$request	Request object +	 */  	public function __construct(\phpbb\config\config $config, \phpbb\request\request_interface $request)  	{ -		$this->config = $config; -		$this->request = $request; +		$this->config	= $config; +		$this->request	= $request;  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function get_service_credentials()  	{ -		return array( +		return [  			'key'		=> $this->config['auth_oauth_twitter_key'],  			'secret'	=> $this->config['auth_oauth_twitter_secret'], -		); +		];  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function perform_auth_login()  	{  		if (!($this->service_provider instanceof \OAuth\OAuth1\Service\Twitter))  		{ -			throw new \phpbb\auth\provider\oauth\service\exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE'); +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE');  		}  		$storage = $this->service_provider->getStorage(); -		$token = $storage->retrieveAccessToken('Twitter'); -		$tokensecret = $token->getRequestTokenSecret(); -		// This was a callback request from twitter, get the token -		$this->service_provider->requestAccessToken( -			$this->request->variable('oauth_token', ''), -			$this->request->variable('oauth_verifier', ''), -			$tokensecret -		); +		try +		{ +			/** @var \OAuth\OAuth1\Token\TokenInterface $token */ +			$token = $storage->retrieveAccessToken('Twitter'); +		} +		catch (\OAuth\Common\Storage\Exception\TokenNotFoundException $e) +		{ +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_REQUEST'); +		} + +		$secret = $token->getRequestTokenSecret(); + +		try +		{ +			// This was a callback request, get the token +			$this->service_provider->requestAccessToken( +				$this->request->variable('oauth_token', ''), +				$this->request->variable('oauth_verifier', ''), +				$secret +			); +		} +		catch (\OAuth\Common\Http\Exception\TokenResponseException $e) +		{ +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_REQUEST'); +		}  		// Send a request with it -		$result = json_decode($this->service_provider->request('account/verify_credentials.json'), true); +		$result = (array) json_decode($this->service_provider->request('account/verify_credentials.json'), true); -		// Return the unique identifier returned from twitter +		// Return the unique identifier  		return $result['id'];  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function perform_token_auth()  	{  		if (!($this->service_provider instanceof \OAuth\OAuth1\Service\Twitter))  		{ -			throw new \phpbb\auth\provider\oauth\service\exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE'); +			throw new exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE');  		}  		// Send a request with it -		$result = json_decode($this->service_provider->request('account/verify_credentials.json'), true); +		$result = (array) json_decode($this->service_provider->request('account/verify_credentials.json'), true); -		// Return the unique identifier returned from twitter +		// Return the unique identifier  		return $result['id'];  	}  } diff --git a/phpBB/phpbb/auth/provider/oauth/token_storage.php b/phpBB/phpbb/auth/provider/oauth/token_storage.php index b0c2fd0d62..c0f585d7bb 100644 --- a/phpBB/phpbb/auth/provider/oauth/token_storage.php +++ b/phpBB/phpbb/auth/provider/oauth/token_storage.php @@ -1,15 +1,15 @@  <?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. -* -*/ + * + * 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\auth\provider\oauth; @@ -20,67 +20,48 @@ use OAuth\Common\Storage\Exception\TokenNotFoundException;  use OAuth\Common\Storage\Exception\AuthorizationStateNotFoundException;  /** -* OAuth storage wrapper for phpbb's cache -*/ + * OAuth storage wrapper for phpBB's cache + */  class token_storage implements TokenStorageInterface  { -	/** -	* Cache driver. -	* -	* @var \phpbb\db\driver\driver_interface -	*/ +	/** @var \phpbb\db\driver\driver_interface */  	protected $db; -	/** -	* phpBB user -	* -	* @var \phpbb\user -	*/ +	/** @var \phpbb\user */  	protected $user; -	/** -	* OAuth token table -	* -	* @var string -	*/ +	/** @var string OAuth table: token storage */  	protected $oauth_token_table; -	/** -	* OAuth state table -	* -	* @var string -	*/ +	/** @var string OAuth table: state */  	protected $oauth_state_table; -	/** -	* @var object|TokenInterface -	*/ +	/** @var TokenInterface OAuth token */  	protected $cachedToken; -	/** -	* @var string -	*/ +	/** @var string OAuth state */  	protected $cachedState;  	/** -	* Creates token storage for phpBB. -	* -	* @param	\phpbb\db\driver\driver_interface	$db -	* @param	\phpbb\user		$user -	* @param	string			$oauth_token_table -	* @param	string			$oauth_state_table -	*/ +	 * Constructor. +	 * +	 * @param \phpbb\db\driver\driver_interface	$db					Database object +	 * @param \phpbb\user						$user				User object +	 * @param string							$oauth_token_table	OAuth table: token storage +	 * @param string							$oauth_state_table	OAuth table: state +	 */  	public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $oauth_token_table, $oauth_state_table)  	{ -		$this->db = $db; -		$this->user = $user; +		$this->db	= $db; +		$this->user	= $user; +  		$this->oauth_token_table = $oauth_token_table;  		$this->oauth_state_table = $oauth_state_table;  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function retrieveAccessToken($service)  	{  		$service = $this->get_service_name_for_db($service); @@ -90,10 +71,10 @@ class token_storage implements TokenStorageInterface  			return $this->cachedToken;  		} -		$data = array( +		$data = [  			'user_id'	=> (int) $this->user->data['user_id'],  			'provider'	=> $service, -		); +		];  		if ((int) $this->user->data['user_id'] === ANONYMOUS)  		{ @@ -104,33 +85,38 @@ class token_storage implements TokenStorageInterface  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function storeAccessToken($service, TokenInterface $token)  	{  		$service = $this->get_service_name_for_db($service);  		$this->cachedToken = $token; -		$data = array( +		$data = [  			'oauth_token'	=> $this->json_encode_token($token), -		); +		];  		$sql = 'UPDATE ' . $this->oauth_token_table . ' -				SET ' . $this->db->sql_build_array('UPDATE', $data) . ' -				WHERE user_id = ' . (int) $this->user->data['user_id'] . ' -					' . ((int) $this->user->data['user_id'] === ANONYMOUS ? "AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'" : '') . " -					AND provider = '" . $this->db->sql_escape($service) . "'"; +			SET ' . $this->db->sql_build_array('UPDATE', $data) . ' +			WHERE user_id = ' . (int) $this->user->data['user_id'] . " +				AND provider = '" . $this->db->sql_escape($service) . "'"; + +		if ((int) $this->user->data['user_id'] === ANONYMOUS) +		{ +			$sql .= " AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'"; +		} +  		$this->db->sql_query($sql);  		if (!$this->db->sql_affectedrows())  		{ -			$data = array( +			$data = [  				'user_id'		=> (int) $this->user->data['user_id'],  				'provider'		=> $service,  				'oauth_token'	=> $this->json_encode_token($token),  				'session_id'	=> $this->user->data['session_id'], -			); +			];  			$sql = 'INSERT INTO ' . $this->oauth_token_table . $this->db->sql_build_array('INSERT', $data); @@ -141,8 +127,8 @@ class token_storage implements TokenStorageInterface  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function hasAccessToken($service)  	{  		$service = $this->get_service_name_for_db($service); @@ -152,22 +138,22 @@ class token_storage implements TokenStorageInterface  			return true;  		} -		$data = array( +		$data = [  			'user_id'	=> (int) $this->user->data['user_id'],  			'provider'	=> $service, -		); +		];  		if ((int) $this->user->data['user_id'] === ANONYMOUS)  		{  			$data['session_id']	= $this->user->data['session_id'];  		} -		return $this->_has_acess_token($data); +		return $this->has_access_token($data);  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function clearToken($service)  	{  		$service = $this->get_service_name_for_db($service); @@ -189,13 +175,13 @@ class token_storage implements TokenStorageInterface  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function clearAllTokens()  	{  		$this->cachedToken = null; -		$sql = 'DELETE FROM ' . $this->oauth_token_table . ' +		$sql = 'DELETE FROM ' . $this->oauth_token_table . '   			WHERE user_id = ' . (int) $this->user->data['user_id'];  		if ((int) $this->user->data['user_id'] === ANONYMOUS) @@ -209,31 +195,30 @@ class token_storage implements TokenStorageInterface  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function storeAuthorizationState($service, $state)  	{  		$service = $this->get_service_name_for_db($service);  		$this->cachedState = $state; -		$data = array( +		$data = [  			'user_id'		=> (int) $this->user->data['user_id'],  			'provider'		=> $service,  			'oauth_state'	=> $state,  			'session_id'	=> $this->user->data['session_id'], -		); +		]; -		$sql = 'INSERT INTO ' . $this->oauth_state_table . ' -			' . $this->db->sql_build_array('INSERT', $data); +		$sql = 'INSERT INTO ' . $this->oauth_state_table . ' ' . $this->db->sql_build_array('INSERT', $data);  		$this->db->sql_query($sql);  		return $this;  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function hasAuthorizationState($service)  	{  		$service = $this->get_service_name_for_db($service); @@ -243,10 +228,10 @@ class token_storage implements TokenStorageInterface  			return true;  		} -		$data = array( +		$data = [  			'user_id'	=> (int) $this->user->data['user_id'],  			'provider'	=> $service, -		); +		];  		if ((int) $this->user->data['user_id'] === ANONYMOUS)  		{ @@ -257,8 +242,8 @@ class token_storage implements TokenStorageInterface  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function retrieveAuthorizationState($service)  	{  		$service = $this->get_service_name_for_db($service); @@ -268,10 +253,10 @@ class token_storage implements TokenStorageInterface  			return $this->cachedState;  		} -		$data = array( +		$data = [  			'user_id'	=> (int) $this->user->data['user_id'],  			'provider'	=> $service, -		); +		];  		if ((int) $this->user->data['user_id'] === ANONYMOUS)  		{ @@ -282,8 +267,8 @@ class token_storage implements TokenStorageInterface  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function clearAuthorizationState($service)  	{  		$service = $this->get_service_name_for_db($service); @@ -305,8 +290,8 @@ class token_storage implements TokenStorageInterface  	}  	/** -	* {@inheritdoc} -	*/ +	 * {@inheritdoc} +	 */  	public function clearAllAuthorizationStates()  	{  		$this->cachedState = null; @@ -325,10 +310,11 @@ class token_storage implements TokenStorageInterface  	}  	/** -	* Updates the user_id field in the database assosciated with the token -	* -	* @param	int	$user_id -	*/ +	 * Updates the user_id field in the database associated with the token. +	 * +	 * @param int		$user_id	The user identifier +	 * @return void +	 */  	public function set_user_id($user_id)  	{  		if (!$this->cachedToken) @@ -336,21 +322,24 @@ class token_storage implements TokenStorageInterface  			return;  		} +		$data = [ +			'user_id' => (int) $user_id, +		]; +  		$sql = 'UPDATE ' . $this->oauth_token_table . ' -			SET ' . $this->db->sql_build_array('UPDATE', array( -					'user_id' => (int) $user_id -				)) . ' -				WHERE user_id = ' . (int) $this->user->data['user_id'] . " -					AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'"; +			SET ' . $this->db->sql_build_array('UPDATE', $data) . ' +			WHERE user_id = ' . (int) $this->user->data['user_id'] . " +				AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'";  		$this->db->sql_query($sql);  	}  	/** -	* Checks to see if an access token exists solely by the session_id of the user -	* -	* @param	string	$service	The name of the OAuth service -	* @return	bool	true if they have token, false if they don't -	*/ +	 * Checks to see if an access token exists solely by the session_id of the user. +	 * +	 * @param string	$service	The OAuth service name +	 * @return bool					true if the user's access token exists, +	 * 								false if the user's access token does not exist +	 */  	public function has_access_token_by_session($service)  	{  		$service = $this->get_service_name_for_db($service); @@ -360,20 +349,21 @@ class token_storage implements TokenStorageInterface  			return true;  		} -		$data = array( +		$data = [  			'session_id'	=> $this->user->data['session_id'],  			'provider'		=> $service, -		); +		]; -		return $this->_has_acess_token($data); +		return $this->has_access_token($data);  	}  	/** -	* Checks to see if a state exists solely by the session_id of the user -	* -	* @param	string	$service	The name of the OAuth service -	* @return	bool	true if they have state, false if they don't -	*/ +	 * Checks to see if a state exists solely by the session_id of the user. +	 * +	 * @param string	$service	The OAuth service name +	 * @return bool					true if the user's state exists, +	 * 								false if the user's state does not exist +	 */  	public function has_state_by_session($service)  	{  		$service = $this->get_service_name_for_db($service); @@ -383,25 +373,34 @@ class token_storage implements TokenStorageInterface  			return true;  		} -		$data = array( +		$data = [  			'session_id'	=> $this->user->data['session_id'],  			'provider'		=> $service, -		); +		];  		return (bool) $this->get_state_row($data);  	}  	/** -	* A helper function that performs the query for has access token functions -	* -	* @param	array	$data -	* @return	bool -	*/ -	protected function _has_acess_token($data) +	 * A helper function that performs the query for has access token functions. +	 * +	 * @param array		$data		The SQL WHERE data +	 * @return bool					true if the user's access token exists, +	 * 								false if the user's access token does not exist +	 */ +	protected function has_access_token($data)  	{  		return (bool) $this->get_access_token_row($data);  	} +	/** +	 * A helper function that performs the query for retrieving access token functions by session. +	 * Also checks if the token is a valid token. +	 * +	 * @param string	$service	The OAuth service provider name +	 * @return TokenInterface +	 * @throws TokenNotFoundException +	 */  	public function retrieve_access_token_by_session($service)  	{  		$service = $this->get_service_name_for_db($service); @@ -411,14 +410,21 @@ class token_storage implements TokenStorageInterface  			return $this->cachedToken;  		} -		$data = array( +		$data = [  			'session_id'	=> $this->user->data['session_id'], -			'provider'	=> $service, -		); +			'provider'		=> $service, +		];  		return $this->_retrieve_access_token($data);  	} +	/** +	 * A helper function that performs the query for retrieving state functions by session. +	 * +	 * @param string	$service	The OAuth service provider name +	 * @return string				The OAuth state +	 * @throws AuthorizationStateNotFoundException +	 */  	public function retrieve_state_by_session($service)  	{  		$service = $this->get_service_name_for_db($service); @@ -428,22 +434,22 @@ class token_storage implements TokenStorageInterface  			return $this->cachedState;  		} -		$data = array( +		$data = [  			'session_id'	=> $this->user->data['session_id'], -			'provider'	=> $service, -		); +			'provider'		=> $service, +		];  		return $this->_retrieve_state($data);  	}  	/** -	* A helper function that performs the query for retrieve access token functions -	* Also checks if the token is a valid token -	* -	* @param	array	$data -	* @return	mixed -	* @throws \OAuth\Common\Storage\Exception\TokenNotFoundException -	*/ +	 * A helper function that performs the query for retrieve access token functions. +	 * Also checks if the token is a valid token. +	 * +	 * @param array		$data		The SQL WHERE data +	 * @return TokenInterface +	 * @throws TokenNotFoundException +	 */  	protected function _retrieve_access_token($data)  	{  		$row = $this->get_access_token_row($data); @@ -459,19 +465,21 @@ class token_storage implements TokenStorageInterface  		if (!($token instanceof TokenInterface))  		{  			$this->clearToken($data['provider']); +  			throw new TokenNotFoundException('AUTH_PROVIDER_OAUTH_TOKEN_ERROR_INCORRECTLY_STORED');  		}  		$this->cachedToken = $token; +  		return $token;  	}  	/** -	 * A helper function that performs the query for retrieve state functions +	 * A helper function that performs the query for retrieve state functions.  	 * -	 * @param	array	$data -	 * @return	mixed -	 * @throws \OAuth\Common\Storage\Exception\AuthorizationStateNotFoundException +	 * @param array		$data		The SQL WHERE data +	 * @return string				The OAuth state +	 * @throws AuthorizationStateNotFoundException  	 */  	protected function _retrieve_state($data)  	{ @@ -483,18 +491,21 @@ class token_storage implements TokenStorageInterface  		}  		$this->cachedState = $row['oauth_state']; +  		return $this->cachedState;  	}  	/** -	* A helper function that performs the query for retrieving an access token -	* -	* @param	array	$data -	* @return	mixed -	*/ +	 * A helper function that performs the query for retrieving an access token. +	 * +	 * @param array		$data		The SQL WHERE data +	 * @return array|false			array with the OAuth token row, +	 *                       		false if the token does not exist +	 */  	protected function get_access_token_row($data)  	{ -		$sql = 'SELECT oauth_token FROM ' . $this->oauth_token_table . ' +		$sql = 'SELECT oauth_token  +			FROM ' . $this->oauth_token_table . '  			WHERE ' . $this->db->sql_build_array('SELECT', $data);  		$result = $this->db->sql_query($sql);  		$row = $this->db->sql_fetchrow($result); @@ -504,14 +515,16 @@ class token_storage implements TokenStorageInterface  	}  	/** -	 * A helper function that performs the query for retrieving a state +	 * A helper function that performs the query for retrieving a state.  	 * -	 * @param	array	$data -	 * @return	mixed +	 * @param array		$data		The SQL WHERE data +	 * @return array|false			array with the OAuth state row, +	 *                       		false if the state does not exist  	 */  	protected function get_state_row($data)  	{ -		$sql = 'SELECT oauth_state FROM ' . $this->oauth_state_table . ' +		$sql = 'SELECT oauth_state  +			FROM ' . $this->oauth_state_table . '  			WHERE ' . $this->db->sql_build_array('SELECT', $data);  		$result = $this->db->sql_query($sql);  		$row = $this->db->sql_fetchrow($result); @@ -520,16 +533,22 @@ class token_storage implements TokenStorageInterface  		return $row;  	} +	/** +	 * A helper function that JSON encodes a TokenInterface's data. +	 * +	 * @param TokenInterface	$token +	 * @return string					The json encoded TokenInterface's data +	 */  	public function json_encode_token(TokenInterface $token)  	{ -		$members = array( +		$members = [  			'accessToken'	=> $token->getAccessToken(),  			'endOfLife'		=> $token->getEndOfLife(),  			'extraParams'	=> $token->getExtraParams(),  			'refreshToken'	=> $token->getRefreshToken(),  			'token_class'	=> get_class($token), -		); +		];  		// Handle additional data needed for OAuth1 tokens  		if ($token instanceof StdOAuth1Token) @@ -542,6 +561,13 @@ class token_storage implements TokenStorageInterface  		return json_encode($members);  	} +	/** +	 * A helper function that JSON decodes a data string and creates a TokenInterface. +	 * +	 * @param string	$json			The json encoded TokenInterface's data +	 * @return TokenInterface +	 * @throws TokenNotFoundException +	 */  	public function json_decode_token($json)  	{  		$token_data = json_decode($json, true); @@ -557,7 +583,10 @@ class token_storage implements TokenStorageInterface  		$endOfLife		= $token_data['endOfLife'];  		$extra_params	= $token_data['extraParams']; -		// Create the token +		/** +		 * Create the token +		 * @var TokenInterface	$token +		 */  		$token = new $token_class($access_token, $refresh_token, TokenInterface::EOL_NEVER_EXPIRES, $extra_params);  		$token->setEndOfLife($endOfLife); @@ -573,20 +602,19 @@ class token_storage implements TokenStorageInterface  	}  	/** -	* Returns the name of the service as it must be stored in the database. -	* -	* @param	string	$service	The name of the OAuth service -	* @return	string	The name of the OAuth service as it needs to be stored -	*					in the database. -	*/ -	protected function get_service_name_for_db($service) +	 * Returns the service name as it must be stored in the database. +	 * +	 * @param string	$provider	The OAuth provider name +	 * @return string				The OAuth service name +	 */ +	protected function get_service_name_for_db($provider)  	{  		// Enforce the naming convention for oauth services -		if (strpos($service, 'auth.provider.oauth.service.') !== 0) +		if (strpos($provider, 'auth.provider.oauth.service.') !== 0)  		{ -			$service = 'auth.provider.oauth.service.' . strtolower($service); +			$provider = 'auth.provider.oauth.service.' . strtolower($provider);  		} -		return $service; +		return $provider;  	}  } diff --git a/phpBB/phpbb/auth/provider/provider_interface.php b/phpBB/phpbb/auth/provider/provider_interface.php index 463324ff46..21c73a33c5 100644 --- a/phpBB/phpbb/auth/provider/provider_interface.php +++ b/phpBB/phpbb/auth/provider/provider_interface.php @@ -53,7 +53,7 @@ interface provider_interface  	 * Autologin function  	 *  	 * @return 	array|null	containing the user row, empty if no auto login -	 * 						should take place, or null if not impletmented. +	 * 						should take place, or null if not implemented.  	 */  	public function autologin(); @@ -68,7 +68,7 @@ interface provider_interface  	/**  	 * This function updates the template with variables related to the acp -	 * options with whatever configuraton values are passed to it as an array. +	 * options with whatever configuration values are passed to it as an array.  	 * It then returns the name of the acp file related to this authentication  	 * provider.  	 * diff --git a/phpBB/phpbb/avatar/driver/upload.php b/phpBB/phpbb/avatar/driver/upload.php index a012bb15b6..a5b704b4ff 100644 --- a/phpBB/phpbb/avatar/driver/upload.php +++ b/phpBB/phpbb/avatar/driver/upload.php @@ -84,6 +84,7 @@ class upload extends \phpbb\avatar\driver\driver  		$template->assign_vars(array(  			'S_UPLOAD_AVATAR_URL' => ($this->config['allow_avatar_remote_upload']) ? true : false,  			'AVATAR_UPLOAD_SIZE' => $this->config['avatar_filesize'], +			'AVATAR_ALLOWED_EXTENSIONS' => implode(',', preg_replace('/^/', '.', $this->allowed_extensions)),  		));  		return true; diff --git a/phpBB/phpbb/cache/driver/apc.php b/phpBB/phpbb/cache/driver/apc.php deleted file mode 100644 index 521d5d41ea..0000000000 --- a/phpBB/phpbb/cache/driver/apc.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. -* -*/ - -namespace phpbb\cache\driver; - -/** -* ACM for APC -*/ -class apc extends \phpbb\cache\driver\memory -{ -	var $extension = 'apc'; - -	/** -	* {@inheritDoc} -	*/ -	function purge() -	{ -		apc_clear_cache('user'); - -		parent::purge(); -	} - -	/** -	* Fetch an item from the cache -	* -	* @access protected -	* @param string $var Cache key -	* @return mixed Cached data -	*/ -	function _read($var) -	{ -		return apc_fetch($this->key_prefix . $var); -	} - -	/** -	* Store data in the cache -	* -	* @access protected -	* @param string $var Cache key -	* @param mixed $data Data to store -	* @param int $ttl Time-to-live of cached data -	* @return bool True if the operation succeeded -	*/ -	function _write($var, $data, $ttl = 2592000) -	{ -		return apc_store($this->key_prefix . $var, $data, $ttl); -	} - -	/** -	* Remove an item from the cache -	* -	* @access protected -	* @param string $var Cache key -	* @return bool True if the operation succeeded -	*/ -	function _delete($var) -	{ -		return apc_delete($this->key_prefix . $var); -	} -} diff --git a/phpBB/phpbb/cache/driver/eaccelerator.php b/phpBB/phpbb/cache/driver/eaccelerator.php deleted file mode 100644 index 740855144f..0000000000 --- a/phpBB/phpbb/cache/driver/eaccelerator.php +++ /dev/null @@ -1,107 +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. -* -*/ - -namespace phpbb\cache\driver; - -/** -* ACM for eAccelerator -* @todo Missing locks from destroy() talk with David -*/ -class eaccelerator extends \phpbb\cache\driver\memory -{ -	var $extension = 'eaccelerator'; -	var $function = 'eaccelerator_get'; - -	var $serialize_header = '#phpbb-serialized#'; - -	/** -	* {@inheritDoc} -	*/ -	function purge() -	{ -		foreach (eaccelerator_list_keys() as $var) -		{ -			// @todo Check why the substr() -			// @todo Only unset vars matching $this->key_prefix -			eaccelerator_rm(substr($var['name'], 1)); -		} - -		parent::purge(); -	} - -	/** -	* {@inheritDoc} -	*/ -	function tidy() -	{ -		global $config; - -		eaccelerator_gc(); - -		$config->set('cache_last_gc', time(), false); -	} - -	/** -	* Fetch an item from the cache -	* -	* @access protected -	* @param string $var Cache key -	* @return mixed Cached data -	*/ -	function _read($var) -	{ -		$result = eaccelerator_get($this->key_prefix . $var); - -		if ($result === null) -		{ -			return false; -		} - -		// Handle serialized objects -		if (is_string($result) && strpos($result, $this->serialize_header . 'O:') === 0) -		{ -			$result = unserialize(substr($result, strlen($this->serialize_header))); -		} - -		return $result; -	} - -	/** -	* Store data in the cache -	* -	* @access protected -	* @param string $var Cache key -	* @param mixed $data Data to store -	* @param int $ttl Time-to-live of cached data -	* @return bool True if the operation succeeded -	*/ -	function _write($var, $data, $ttl = 2592000) -	{ -		// Serialize objects and make them easy to detect -		$data = (is_object($data)) ? $this->serialize_header . serialize($data) : $data; - -		return eaccelerator_put($this->key_prefix . $var, $data, $ttl); -	} - -	/** -	* Remove an item from the cache -	* -	* @access protected -	* @param string $var Cache key -	* @return bool True if the operation succeeded -	*/ -	function _delete($var) -	{ -		return eaccelerator_rm($this->key_prefix . $var); -	} -} diff --git a/phpBB/phpbb/cache/driver/memcache.php b/phpBB/phpbb/cache/driver/memcache.php deleted file mode 100644 index 57f138f574..0000000000 --- a/phpBB/phpbb/cache/driver/memcache.php +++ /dev/null @@ -1,122 +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. -* -*/ - -namespace phpbb\cache\driver; - -if (!defined('PHPBB_ACM_MEMCACHE_PORT')) -{ -	define('PHPBB_ACM_MEMCACHE_PORT', 11211); -} - -if (!defined('PHPBB_ACM_MEMCACHE_COMPRESS')) -{ -	define('PHPBB_ACM_MEMCACHE_COMPRESS', false); -} - -if (!defined('PHPBB_ACM_MEMCACHE_HOST')) -{ -	define('PHPBB_ACM_MEMCACHE_HOST', 'localhost'); -} - -if (!defined('PHPBB_ACM_MEMCACHE')) -{ -	//can define multiple servers with host1/port1,host2/port2 format -	define('PHPBB_ACM_MEMCACHE', PHPBB_ACM_MEMCACHE_HOST . '/' . PHPBB_ACM_MEMCACHE_PORT); -} - -/** -* ACM for Memcached -*/ -class memcache extends \phpbb\cache\driver\memory -{ -	var $extension = 'memcache'; - -	var $memcache; -	var $flags = 0; - -	function __construct() -	{ -		// Call the parent constructor -		parent::__construct(); - -		$this->memcache = new \Memcache; -		foreach (explode(',', PHPBB_ACM_MEMCACHE) as $u) -		{ -			preg_match('#(.*)/(\d+)#', $u, $parts); -			$this->memcache->addServer(trim($parts[1]), (int) trim($parts[2])); -		} -		$this->flags = (PHPBB_ACM_MEMCACHE_COMPRESS) ? MEMCACHE_COMPRESSED : 0; -	} - -	/** -	* {@inheritDoc} -	*/ -	function unload() -	{ -		parent::unload(); - -		$this->memcache->close(); -	} - -	/** -	* {@inheritDoc} -	*/ -	function purge() -	{ -		$this->memcache->flush(); - -		parent::purge(); -	} - -	/** -	* Fetch an item from the cache -	* -	* @access protected -	* @param string $var Cache key -	* @return mixed Cached data -	*/ -	function _read($var) -	{ -		return $this->memcache->get($this->key_prefix . $var); -	} - -	/** -	* Store data in the cache -	* -	* @access protected -	* @param string $var Cache key -	* @param mixed $data Data to store -	* @param int $ttl Time-to-live of cached data -	* @return bool True if the operation succeeded -	*/ -	function _write($var, $data, $ttl = 2592000) -	{ -		if (!$this->memcache->replace($this->key_prefix . $var, $data, $this->flags, $ttl)) -		{ -			return $this->memcache->set($this->key_prefix . $var, $data, $this->flags, $ttl); -		} -		return true; -	} - -	/** -	* Remove an item from the cache -	* -	* @access protected -	* @param string $var Cache key -	* @return bool True if the operation succeeded -	*/ -	function _delete($var) -	{ -		return $this->memcache->delete($this->key_prefix . $var); -	} -} diff --git a/phpBB/phpbb/cache/driver/memcached.php b/phpBB/phpbb/cache/driver/memcached.php index 7d66759ec2..fbb587a369 100644 --- a/phpBB/phpbb/cache/driver/memcached.php +++ b/phpBB/phpbb/cache/driver/memcached.php @@ -50,12 +50,16 @@ class memcached extends \phpbb\cache\driver\memory  	/**  	 * Memcached constructor +	 * +	 * @param string $memcached_servers Memcached servers string (optional)  	 */ -	public function __construct() +	public function __construct($memcached_servers = '')  	{  		// Call the parent constructor  		parent::__construct(); +		$memcached_servers = $memcached_servers ?: PHPBB_ACM_MEMCACHED; +  		$this->memcached = new \Memcached();  		$this->memcached->setOption(\Memcached::OPT_BINARY_PROTOCOL, true);  		// Memcached defaults to using compression, disable if we don't want @@ -65,10 +69,20 @@ class memcached extends \phpbb\cache\driver\memory  			$this->memcached->setOption(\Memcached::OPT_COMPRESSION, false);  		} -		foreach (explode(',', PHPBB_ACM_MEMCACHED) as $u) +		$server_list = []; +		foreach (explode(',', $memcached_servers) as $u) +		{ +			if (preg_match('#(.*)/(\d+)#', $u, $parts)) +			{ +				$server_list[] = [trim($parts[1]), (int) trim($parts[2])]; +			} +		} + +		$this->memcached->addServers($server_list); + +		if (empty($server_list) || empty($this->memcached->getStats()))  		{ -			preg_match('#(.*)/(\d+)#', $u, $parts); -			$this->memcached->addServer(trim($parts[1]), (int) trim($parts[2])); +			trigger_error('Could not connect to memcached server(s).');  		}  	} diff --git a/phpBB/phpbb/cache/driver/memory.php b/phpBB/phpbb/cache/driver/memory.php index eba9549877..956936bf6f 100644 --- a/phpBB/phpbb/cache/driver/memory.php +++ b/phpBB/phpbb/cache/driver/memory.php @@ -25,7 +25,7 @@ abstract class memory extends \phpbb\cache\driver\base  	*/  	function __construct()  	{ -		global $phpbb_root_path, $dbname, $table_prefix, $phpbb_container; +		global $dbname, $table_prefix, $phpbb_container;  		$this->cache_dir	= $phpbb_container->getParameter('core.cache_dir');  		$this->key_prefix	= substr(md5($dbname . $table_prefix), 0, 8) . '_'; diff --git a/phpBB/phpbb/cache/driver/xcache.php b/phpBB/phpbb/cache/driver/xcache.php deleted file mode 100644 index 0c845a6a8d..0000000000 --- a/phpBB/phpbb/cache/driver/xcache.php +++ /dev/null @@ -1,107 +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. -* -*/ - -namespace phpbb\cache\driver; - -/** -* ACM for XCache -* -* To use this module you need ini_get() enabled and the following INI settings configured as follows: -* - xcache.var_size > 0 -* - xcache.admin.enable_auth = off (or xcache.admin.user and xcache.admin.password set) -* -*/ -class xcache extends \phpbb\cache\driver\memory -{ -	var $extension = 'XCache'; - -	function __construct() -	{ -		parent::__construct(); - -		if (!function_exists('ini_get') || (int) ini_get('xcache.var_size') <= 0) -		{ -			trigger_error('Increase xcache.var_size setting above 0 or enable ini_get() to use this ACM module.', E_USER_ERROR); -		} -	} - -	/** -	* {@inheritDoc} -	*/ -	function purge() -	{ -		// Run before for XCache, if admin functions are disabled it will terminate execution -		parent::purge(); - -		// If the admin authentication is enabled but not set up, this will cause a nasty error. -		// Not much we can do about it though. -		$n = xcache_count(XC_TYPE_VAR); - -		for ($i = 0; $i < $n; $i++) -		{ -			xcache_clear_cache(XC_TYPE_VAR, $i); -		} -	} - -	/** -	* Fetch an item from the cache -	* -	* @access protected -	* @param string $var Cache key -	* @return mixed Cached data -	*/ -	function _read($var) -	{ -		$result = xcache_get($this->key_prefix . $var); - -		return ($result !== null) ? $result : false; -	} - -	/** -	* Store data in the cache -	* -	* @access protected -	* @param string $var Cache key -	* @param mixed $data Data to store -	* @param int $ttl Time-to-live of cached data -	* @return bool True if the operation succeeded -	*/ -	function _write($var, $data, $ttl = 2592000) -	{ -		return xcache_set($this->key_prefix . $var, $data, $ttl); -	} - -	/** -	* Remove an item from the cache -	* -	* @access protected -	* @param string $var Cache key -	* @return bool True if the operation succeeded -	*/ -	function _delete($var) -	{ -		return xcache_unset($this->key_prefix . $var); -	} - -	/** -	* Check if a cache var exists -	* -	* @access protected -	* @param string $var Cache key -	* @return bool True if it exists, otherwise false -	*/ -	function _isset($var) -	{ -		return xcache_isset($this->key_prefix . $var); -	} -} diff --git a/phpBB/phpbb/captcha/non_gd.php b/phpBB/phpbb/captcha/non_gd.php index 3818672f17..8105187ed9 100644 --- a/phpBB/phpbb/captcha/non_gd.php +++ b/phpBB/phpbb/captcha/non_gd.php @@ -78,7 +78,7 @@ class non_gd  				for ($j = 0; $j < $code_len; $j++)  				{ -					$image .= $this->randomise(substr($hold_chars[$code{$j}][$i - $offset_y - 1], 1), $char_widths[$j]); +					$image .= $this->randomise(substr($hold_chars[$code[$j]][$i - $offset_y - 1], 1), $char_widths[$j]);  				}  				for ($j = $offset_x + $img_width; $j < $this->width; $j++) @@ -117,7 +117,7 @@ class non_gd  		$end = strlen($scanline) - ceil($width/2);  		for ($i = (int) floor($width / 2); $i < $end; $i++)  		{ -			$pixel = ord($scanline{$i}); +			$pixel = ord($scanline[$i]);  			if ($pixel < 190)  			{ @@ -129,7 +129,7 @@ class non_gd  			}  			else  			{ -				$new_line .= $scanline{$i}; +				$new_line .= $scanline[$i];  			}  		} diff --git a/phpBB/phpbb/class_loader.php b/phpBB/phpbb/class_loader.php index cfdcc2af0b..a4b69311ca 100644 --- a/phpBB/phpbb/class_loader.php +++ b/phpBB/phpbb/class_loader.php @@ -64,7 +64,7 @@ class class_loader  	/**  	* Provide the class loader with a cache to store paths. If set to null, the -	* the class loader will resolve paths by checking for the existance of every +	* the class loader will resolve paths by checking for the existence of every  	* directory in the class name every time.  	*  	* @param \phpbb\cache\driver\driver_interface $cache An implementation of the phpBB cache interface. diff --git a/phpBB/phpbb/config/config.php b/phpBB/phpbb/config/config.php index aaad333006..c619cae2fd 100644 --- a/phpBB/phpbb/config/config.php +++ b/phpBB/phpbb/config/config.php @@ -148,6 +148,25 @@ class config implements \ArrayAccess, \IteratorAggregate, \Countable  	}  	/** +	* Checks configuration option's value only if the new_value matches the +	* current configuration value and the configuration value does exist.Called +	* only after set_atomic has been called. +	* +	* @param  string $key       The configuration option's name +	* @param  string $new_value New configuration value +	* @throws \phpbb\exception\http_exception when config value is set and not equal to new_value. +	* @return bool              True if the value was changed, false otherwise. +	*/ +	public function ensure_lock($key, $new_value) +	{ +		if (isset($this->config[$key]) && $this->config[$key] == $new_value) +		{ +			return true; +		} +		throw new \phpbb\exception\http_exception(500, 'Failure while aqcuiring locks.'); +	} + +	/**  	* Increments an integer configuration value.  	*  	* @param string $key       The configuration option's name diff --git a/phpBB/phpbb/config_php_file.php b/phpBB/phpbb/config_php_file.php index 7445e7df22..e3f7357720 100644 --- a/phpBB/phpbb/config_php_file.php +++ b/phpBB/phpbb/config_php_file.php @@ -155,6 +155,12 @@ class config_php_file  			return $dbms;  		} +		// Force use of mysqli when specifying mysql +		if (preg_match('/(phpbb\\\db\\\driver\\\)?mysql$/i', $dbms)) +		{ +			return 'phpbb\db\driver\mysqli'; +		} +  		throw new \RuntimeException("You have specified an invalid dbms driver: $dbms");  	}  } diff --git a/phpBB/phpbb/console/command/cron/run.php b/phpBB/phpbb/console/command/cron/run.php index dea6493007..511c6bc01b 100644 --- a/phpBB/phpbb/console/command/cron/run.php +++ b/phpBB/phpbb/console/command/cron/run.php @@ -73,7 +73,7 @@ class run extends \phpbb\console\command\command  	* @param InputInterface $input The input stream used to get the argument and verboe option.  	* @param OutputInterface $output The output stream, used for printing verbose-mode and error information.  	* -	* @return int 0 if all is ok, 1 if a lock error occured and 2 if no task matching the argument was found. +	* @return int 0 if all is ok, 1 if a lock error occurred and 2 if no task matching the argument was found.  	*/  	protected function execute(InputInterface $input, OutputInterface $output)  	{ @@ -145,9 +145,11 @@ class run extends \phpbb\console\command\command  	*		and returns with status 2.  	*  	* @see execute -	* @param string $task_name The name of the task that should be run. +	*  	* @param InputInterface $input The input stream used to get the argument and verbose option.  	* @param OutputInterface $output The output stream, used for printing verbose-mode and error information. +	* @param string $task_name The name of the task that should be run. +	*  	* @return int 0 if all is well, 2 if no task matches $task_name.  	*/  	protected function run_one(InputInterface $input, OutputInterface $output, $task_name) diff --git a/phpBB/phpbb/console/command/extension/enable.php b/phpBB/phpbb/console/command/extension/enable.php index a6f5b10e86..504b5546b3 100644 --- a/phpBB/phpbb/console/command/extension/enable.php +++ b/phpBB/phpbb/console/command/extension/enable.php @@ -46,9 +46,11 @@ class enable extends command  		$extension = $this->manager->get_extension($name); -		if (!$extension->is_enableable()) +		if (($enableable = $extension->is_enableable()) !== true)  		{ -			$io->error($this->user->lang('CLI_EXTENSION_NOT_ENABLEABLE', $name)); +			$message = !empty($enableable) ? $enableable : $this->user->lang('CLI_EXTENSION_NOT_ENABLEABLE', $name); +			$message = is_array($message) ? implode(PHP_EOL, $message) : $message; +			$io->error($message);  			return 1;  		} diff --git a/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php b/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php deleted file mode 100644 index 6f7096296d..0000000000 --- a/phpBB/phpbb/console/command/fixup/recalculate_email_hash.php +++ /dev/null @@ -1,76 +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. -* -*/ -namespace phpbb\console\command\fixup; - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -class recalculate_email_hash extends \phpbb\console\command\command -{ -	/** @var \phpbb\db\driver\driver_interface */ -	protected $db; - -	public function __construct(\phpbb\user $user, \phpbb\db\driver\driver_interface $db) -	{ -		$this->db = $db; - -		parent::__construct($user); -	} - -	protected function configure() -	{ -		$this -			->setName('fixup:recalculate-email-hash') -			->setDescription($this->user->lang('CLI_DESCRIPTION_RECALCULATE_EMAIL_HASH')) -		; -	} - -	protected function execute(InputInterface $input, OutputInterface $output) -	{ -		$io = new SymfonyStyle($input, $output); - -		$sql = 'SELECT user_id, user_email, user_email_hash -			FROM ' . USERS_TABLE . ' -			WHERE user_type <> ' . USER_IGNORE . " -				AND user_email <> ''"; -		$result = $this->db->sql_query($sql); - -		while ($row = $this->db->sql_fetchrow($result)) -		{ -			$user_email_hash = phpbb_email_hash($row['user_email']); -			if ($user_email_hash !== $row['user_email_hash']) -			{ -				$sql_ary = array( -					'user_email_hash'	=> $user_email_hash, -				); - -				$sql = 'UPDATE ' . USERS_TABLE . ' -					SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' -					WHERE user_id = ' . (int) $row['user_id']; -				$this->db->sql_query($sql); - -				if ($output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG) -				{ -					$io->table( -						array('user_id', 'user_email', 'user_email_hash'), -						array(array($row['user_id'], $row['user_email'], $user_email_hash)) -					); -				} -			} -		} -		$this->db->sql_freeresult($result); - -		$io->success($this->user->lang('CLI_FIXUP_RECALCULATE_EMAIL_HASH_SUCCESS')); -	} -} diff --git a/phpBB/phpbb/console/command/update/check.php b/phpBB/phpbb/console/command/update/check.php index 9ced651e8b..4cd7d2155c 100644 --- a/phpBB/phpbb/console/command/update/check.php +++ b/phpBB/phpbb/console/command/update/check.php @@ -77,7 +77,7 @@ class check extends \phpbb\console\command\command  	*  	* @param InputInterface $input Input stream, used to get the options.  	* @param OutputInterface $output Output stream, used to print messages. -	* @return int 0 if the board is up to date, 1 if it is not and 2 if an error occured. +	* @return int 0 if the board is up to date, 1 if it is not and 2 if an error occurred.  	* @throws \RuntimeException  	*/  	protected function execute(InputInterface $input, OutputInterface $output) @@ -223,6 +223,7 @@ class check extends \phpbb\console\command\command  	* Check if all the available extensions are up to date  	*  	* @param SymfonyStyle	$io			IO handler, for formatted and unified IO +	* @param string			$stability	Stability specifier string  	* @param bool			$recheck	Disallow the use of the cache  	* @return int  	*/ diff --git a/phpBB/phpbb/console/command/user/add.php b/phpBB/phpbb/console/command/user/add.php index c60a059251..303216a93d 100644 --- a/phpBB/phpbb/console/command/user/add.php +++ b/phpBB/phpbb/console/command/user/add.php @@ -239,7 +239,7 @@ class add extends command  				array('string', false, $this->config['min_name_chars'], $this->config['max_name_chars']),  				array('username', '')),  			'new_password' => array( -				array('string', false, $this->config['min_pass_chars'], $this->config['max_pass_chars']), +				array('string', false, $this->config['min_pass_chars'], 0),  				array('password')),  			'email'        => array(  				array('string', false, 6, 60), diff --git a/phpBB/phpbb/content_visibility.php b/phpBB/phpbb/content_visibility.php index f023e0742c..fbc56f3db2 100644 --- a/phpBB/phpbb/content_visibility.php +++ b/phpBB/phpbb/content_visibility.php @@ -144,7 +144,14 @@ class content_visibility  	*/  	public function is_visible($mode, $forum_id, $data)  	{ -		$is_visible = $this->auth->acl_get('m_approve', $forum_id) || $data[$mode . '_visibility'] == ITEM_APPROVED; +		$visibility = $data[$mode . '_visibility']; +		$poster_key = ($mode === 'topic') ? 'topic_poster' : 'poster_id'; +		$is_visible = ($visibility == ITEM_APPROVED) || +			($this->config['display_unapproved_posts'] && +				($this->user->data['user_id'] != ANONYMOUS) && +				($visibility == ITEM_UNAPPROVED || $visibility == ITEM_REAPPROVE) && +				($this->user->data['user_id'] == $data[$poster_key])) || +			 $this->auth->acl_get('m_approve', $forum_id);  		/**  		* Allow changing the result of calling is_visible @@ -216,9 +223,16 @@ class content_visibility  		}  		else  		{ -			$where_sql .= $table_alias . $mode . '_visibility = ' . ITEM_APPROVED; -		} +			$visibility_query = $table_alias . $mode . '_visibility = '; +			$where_sql .= '(' . $visibility_query . ITEM_APPROVED . ')'; +			if ($this->config['display_unapproved_posts'] && ($this->user->data['user_id'] != ANONYMOUS)) +			{ +				$poster_key = ($mode === 'topic') ? 'topic_poster' : 'poster_id'; +				$where_sql .= ' OR ((' . $visibility_query . ITEM_UNAPPROVED . ' OR ' . $visibility_query . ITEM_REAPPROVE .')'; +				$where_sql .= ' AND ' . $table_alias . $poster_key . ' = ' . ((int) $this->user->data['user_id']) . ')'; +			} +		}  		return '(' . $where_sql . ')';  	} @@ -684,7 +698,7 @@ class content_visibility  	* @param $time			int		Timestamp when the action is performed  	* @param $reason		string	Reason why the visibilty was changed.  	* @param $force_update_all	bool	Force to update all posts within the topic -	* @return array		Changed topic data, empty array if an error occured. +	* @return array		Changed topic data, empty array if an error occurred.  	*/  	public function set_topic_visibility($visibility, $topic_id, $forum_id, $user_id, $time, $reason, $force_update_all = false)  	{ diff --git a/phpBB/phpbb/controller/helper.php b/phpBB/phpbb/controller/helper.php index 664b4f4e0f..58a4a492f8 100644 --- a/phpBB/phpbb/controller/helper.php +++ b/phpBB/phpbb/controller/helper.php @@ -121,7 +121,7 @@ class helper  	* @param int $code The error code (e.g. 404, 500, 503, etc.)  	* @return Response A Response instance  	* -	* @deprecated 3.1.3 (To be removed: 3.3.0) Use exceptions instead. +	* @deprecated 3.1.3 (To be removed: 4.0.0) Use exceptions instead.  	*/  	public function error($message, $code = 500)  	{ diff --git a/phpBB/phpbb/cron/controller/cron.php b/phpBB/phpbb/cron/controller/cron.php new file mode 100644 index 0000000000..6f0e35e4cd --- /dev/null +++ b/phpBB/phpbb/cron/controller/cron.php @@ -0,0 +1,40 @@ +<?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\cron\controller; + +use Symfony\Component\HttpFoundation\Response; + +/** + * Controller for running cron jobs + */ +class cron +{ +	/** +	 * Handles CRON requests +	 * +	 * @param string $cron_type +	 * +	 * @return Response +	 */ +	public function handle($cron_type) +	{ +		$response = new Response(); +		$response->headers->set('Cache-Control', 'no-cache'); +		$response->headers->set('Content-type', 'image/gif'); +		$response->headers->set('Content-length', '43'); +		$response->setContent(base64_decode('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==')); + +		return $response; +	} +} diff --git a/phpBB/phpbb/cron/event/cron_runner_listener.php b/phpBB/phpbb/cron/event/cron_runner_listener.php new file mode 100644 index 0000000000..9e9ecf0d47 --- /dev/null +++ b/phpBB/phpbb/cron/event/cron_runner_listener.php @@ -0,0 +1,103 @@ +<?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\cron\event; + +use phpbb\cron\manager; +use phpbb\lock\db; +use phpbb\request\request_interface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\Event\PostResponseEvent; + +/** + * Event listener that executes cron tasks, after the response was served + */ +class cron_runner_listener implements EventSubscriberInterface +{ +	/** +	 * @var \phpbb\lock\db +	 */ +	private $cron_lock; + +	/** +	 * @var \phpbb\cron\manager +	 */ +	private $cron_manager; + +	/** +	 * @var \phpbb\request\request_interface +	 */ +	private $request; + +	/** +	 * Constructor +	 * +	 * @param db 				$lock +	 * @param manager			$manager +	 * @param request_interface	$request +	 */ +	public function __construct(db $lock, manager $manager, request_interface $request) +	{ +		$this->cron_lock	= $lock; +		$this->cron_manager	= $manager; +		$this->request		= $request; +	} + +	/** +	 * Runs the cron job after the response was sent +	 * +	 * @param PostResponseEvent	$event	The event +	 */ +	public function on_kernel_terminate(PostResponseEvent $event) +	{ +		$request = $event->getRequest(); +		$controller_name = $request->get('_route'); + +		if ($controller_name !== 'phpbb_cron_run') +		{ +			return; +		} + +		$cron_type = $request->get('cron_type'); + +		if ($this->cron_lock->acquire()) +		{ +			$task = $this->cron_manager->find_task($cron_type); +			if ($task) +			{ +				if ($task->is_parametrized()) +				{ +					$task->parse_parameters($this->request); +				} + +				if ($task->is_ready()) +				{ +					$task->run(); +				} + +				$this->cron_lock->release(); +			} +		} +	} + +	/** +	 * {@inheritdoc} +	 */ +	static public function getSubscribedEvents() +	{ +		return array( +			KernelEvents::TERMINATE		=> 'on_kernel_terminate', +		); +	} +} diff --git a/phpBB/phpbb/cron/manager.php b/phpBB/phpbb/cron/manager.php index 9bd30a0a5b..59ee693074 100644 --- a/phpBB/phpbb/cron/manager.php +++ b/phpBB/phpbb/cron/manager.php @@ -13,6 +13,9 @@  namespace phpbb\cron; +use phpbb\cron\task\wrapper; +use phpbb\routing\helper; +  /**  * Cron manager class.  * @@ -21,6 +24,11 @@ namespace phpbb\cron;  class manager  {  	/** +	 * @var helper +	 */ +	protected $routing_helper; + +	/**  	* Set of \phpbb\cron\task\wrapper objects.  	* Array holding all tasks that have been found.  	* @@ -28,18 +36,27 @@ class manager  	*/  	protected $tasks = array(); +	/** +	 * @var string +	 */  	protected $phpbb_root_path; + +	/** +	 * @var string +	 */  	protected $php_ext;  	/**  	* Constructor. Loads all available tasks.  	*  	* @param array|\Traversable $tasks Provides an iterable set of task names +	* @param helper $routing_helper Routing helper  	* @param string $phpbb_root_path Relative path to phpBB root  	* @param string $php_ext PHP file extension  	*/ -	public function __construct($tasks, $phpbb_root_path, $php_ext) +	public function __construct($tasks, helper $routing_helper, $phpbb_root_path, $php_ext)  	{ +		$this->routing_helper = $routing_helper;  		$this->phpbb_root_path = $phpbb_root_path;  		$this->php_ext = $php_ext; @@ -142,6 +159,6 @@ class manager  	*/  	public function wrap_task(\phpbb\cron\task\task $task)  	{ -		return new \phpbb\cron\task\wrapper($task, $this->phpbb_root_path, $this->php_ext); +		return new wrapper($task, $this->routing_helper, $this->phpbb_root_path, $this->php_ext);  	}  } diff --git a/phpBB/phpbb/cron/task/core/update_hashes.php b/phpBB/phpbb/cron/task/core/update_hashes.php index ba095abc8b..9e938f74dd 100644 --- a/phpBB/phpbb/cron/task/core/update_hashes.php +++ b/phpBB/phpbb/cron/task/core/update_hashes.php @@ -56,7 +56,7 @@ class update_hashes extends \phpbb\cron\task\base  		foreach ($defaults as $type)  		{ -			if ($hashing_algorithms[$type]->is_supported()) +			if ($hashing_algorithms[$type]->is_supported() && !$hashing_algorithms[$type] instanceof \phpbb\passwords\driver\base_native)  			{  				$this->default_type = $type;  				break; diff --git a/phpBB/phpbb/cron/task/wrapper.php b/phpBB/phpbb/cron/task/wrapper.php index 8a4a8b1f0c..4dc3a7fb95 100644 --- a/phpBB/phpbb/cron/task/wrapper.php +++ b/phpBB/phpbb/cron/task/wrapper.php @@ -13,14 +13,32 @@  namespace phpbb\cron\task; +use phpbb\routing\helper; +  /**  * Cron task wrapper class.  * Enhances cron tasks with convenience methods that work identically for all tasks.  */  class wrapper  { +	/** +	 * @var helper +	 */ +	protected $routing_helper; + +	/** +	 * @var task +	 */  	protected $task; + +	/** +	 * @var string +	 */  	protected $phpbb_root_path; + +	/** +	 * @var string +	 */  	protected $php_ext;  	/** @@ -28,13 +46,15 @@ class wrapper  	*  	* Wraps a task $task, which must implement cron_task interface.  	* -	* @param \phpbb\cron\task\task $task The cron task to wrap. -	* @param string $phpbb_root_path Relative path to phpBB root -	* @param string $php_ext PHP file extension +	* @param task	$task				The cron task to wrap. +	* @param helper	$routing_helper		Routing helper for route generation +	* @param string	$phpbb_root_path	Relative path to phpBB root +	* @param string	$php_ext			PHP file extension  	*/ -	public function __construct(\phpbb\cron\task\task $task, $phpbb_root_path, $php_ext) +	public function __construct(task $task, helper $routing_helper, $phpbb_root_path, $php_ext)  	{  		$this->task = $task; +		$this->routing_helper = $routing_helper;  		$this->phpbb_root_path = $phpbb_root_path;  		$this->php_ext = $php_ext;  	} @@ -49,7 +69,7 @@ class wrapper  	*/  	public function is_parametrized()  	{ -		return $this->task instanceof \phpbb\cron\task\parametrized; +		return $this->task instanceof parametrized;  	}  	/** @@ -76,22 +96,13 @@ class wrapper  	*/  	public function get_url()  	{ -		$name = $this->get_name(); +		$params['cron_type'] = $this->get_name();  		if ($this->is_parametrized())  		{ -			$params = $this->task->get_parameters(); -			$extra = ''; -			foreach ($params as $key => $value) -			{ -				$extra .= '&' . $key . '=' . urlencode($value); -			} +			$params = array_merge($params, $this->task->get_parameters());  		} -		else -		{ -			$extra = ''; -		} -		$url = append_sid($this->phpbb_root_path . 'cron.' . $this->php_ext, 'cron_type=' . $name . $extra); -		return $url; + +		return $this->routing_helper->route('phpbb_cron_run', $params);  	}  	/** diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index a36ce8c0d7..93f0a749e5 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -76,6 +76,16 @@ abstract class driver implements driver_interface  	const SUBQUERY_BUILD = 5;  	/** +	* @var bool +	*/ +	protected $debug_load_time = false; + +	/** +	* @var bool +	*/ +	protected $debug_sql_explain = false; + +	/**  	* Constructor  	*/  	function __construct() @@ -98,6 +108,22 @@ abstract class driver implements driver_interface  	/**  	* {@inheritdoc}  	*/ +	public function set_debug_load_time($value) +	{ +		$this->debug_load_time = $value; +	} + +	/** +	* {@inheritdoc} +	*/ +	public function set_debug_sql_explain($value) +	{ +		$this->debug_sql_explain = $value; +	} + +	/** +	* {@inheritdoc} +	*/  	public function get_sql_layer()  	{  		return $this->sql_layer; @@ -955,7 +981,7 @@ abstract class driver implements driver_interface  			// Show complete SQL error and path to administrators only  			// Additionally show complete error on installation or if extended debug mode is enabled  			// The DEBUG constant is for development only! -			if ((isset($auth) && $auth->acl_get('a_')) || defined('IN_INSTALL') || defined('DEBUG')) +			if ((isset($auth) && $auth->acl_get('a_')) || defined('IN_INSTALL') || $this->debug_sql_explain)  			{  				$message .= ($sql) ? '<br /><br />SQL<br /><br />' . htmlspecialchars($sql) : '';  			} diff --git a/phpBB/phpbb/db/driver/driver_interface.php b/phpBB/phpbb/db/driver/driver_interface.php index 8b487c5d42..05ff5ef066 100644 --- a/phpBB/phpbb/db/driver/driver_interface.php +++ b/phpBB/phpbb/db/driver/driver_interface.php @@ -16,6 +16,20 @@ namespace phpbb\db\driver;  interface driver_interface  {  	/** +	* Set value for load_time debug parameter +	* +	* @param bool $value +	*/ +	public function set_debug_load_time($value); + +	/** +	* Set value for sql_explain debug parameter +	* +	* @param bool $value +	*/ +	public function set_debug_sql_explain($value); + +	/**  	* Gets the name of the sql layer.  	*  	* @return string diff --git a/phpBB/phpbb/db/driver/factory.php b/phpBB/phpbb/db/driver/factory.php index fb3a826254..bb6e7a2682 100644 --- a/phpBB/phpbb/db/driver/factory.php +++ b/phpBB/phpbb/db/driver/factory.php @@ -68,6 +68,22 @@ class factory implements driver_interface  	/**  	* {@inheritdoc}  	*/ +	public function set_debug_load_time($value) +	{ +		$this->get_driver()->set_debug_load_time($value); +	} + +	/** +	* {@inheritdoc} +	*/ +	public function set_debug_sql_explain($value) +	{ +		$this->get_driver()->set_debug_sql_explain($value); +	} + +	/** +	* {@inheritdoc} +	*/  	public function get_sql_layer()  	{  		return $this->get_driver()->get_sql_layer(); diff --git a/phpBB/phpbb/db/driver/mssql_odbc.php b/phpBB/phpbb/db/driver/mssql_odbc.php index 9d9ad603e0..06cdce7a15 100644 --- a/phpBB/phpbb/db/driver/mssql_odbc.php +++ b/phpBB/phpbb/db/driver/mssql_odbc.php @@ -151,12 +151,11 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base  		{  			global $cache; -			// EXPLAIN only in extra debug mode -			if (defined('DEBUG')) +			if ($this->debug_sql_explain)  			{  				$this->sql_report('start', $query);  			} -			else if (defined('PHPBB_DISPLAY_LOAD_TIME')) +			else if ($this->debug_load_time)  			{  				$this->curtime = microtime(true);  			} @@ -172,11 +171,11 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base  					$this->sql_error($query);  				} -				if (defined('DEBUG')) +				if ($this->debug_sql_explain)  				{  					$this->sql_report('stop', $query);  				} -				else if (defined('PHPBB_DISPLAY_LOAD_TIME')) +				else if ($this->debug_load_time)  				{  					$this->sql_time += microtime(true) - $this->curtime;  				} @@ -196,7 +195,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base  					$this->open_queries[(int) $this->query_result] = $this->query_result;  				}  			} -			else if (defined('DEBUG')) +			else if ($this->debug_sql_explain)  			{  				$this->sql_report('fromcache', $query);  			} diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php index a4dcac5966..30ef9d9bc4 100644 --- a/phpBB/phpbb/db/driver/mssqlnative.php +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -123,12 +123,11 @@ class mssqlnative extends \phpbb\db\driver\mssql_base  		{  			global $cache; -			// EXPLAIN only in extra debug mode -			if (defined('DEBUG')) +			if ($this->debug_sql_explain)  			{  				$this->sql_report('start', $query);  			} -			else if (defined('PHPBB_DISPLAY_LOAD_TIME')) +			else if ($this->debug_load_time)  			{  				$this->curtime = microtime(true);  			} @@ -146,11 +145,11 @@ class mssqlnative extends \phpbb\db\driver\mssql_base  				// reset options for next query  				$this->query_options = array(); -				if (defined('DEBUG')) +				if ($this->debug_sql_explain)  				{  					$this->sql_report('stop', $query);  				} -				else if (defined('PHPBB_DISPLAY_LOAD_TIME')) +				else if ($this->debug_load_time)  				{  					$this->sql_time += microtime(true) - $this->curtime;  				} @@ -170,7 +169,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base  					$this->open_queries[(int) $this->query_result] = $this->query_result;  				}  			} -			else if (defined('DEBUG')) +			else if ($this->debug_sql_explain)  			{  				$this->sql_report('fromcache', $query);  			} diff --git a/phpBB/phpbb/db/driver/mysql.php b/phpBB/phpbb/db/driver/mysql.php deleted file mode 100644 index a94e88b331..0000000000 --- a/phpBB/phpbb/db/driver/mysql.php +++ /dev/null @@ -1,503 +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. -* -*/ - -namespace phpbb\db\driver; - -/** -* MySQL4 Database Abstraction Layer -* Compatible with: -* MySQL 3.23+ -* MySQL 4.0+ -* MySQL 4.1+ -* MySQL 5.0+ -*/ -class mysql extends \phpbb\db\driver\mysql_base -{ -	var $multi_insert = true; -	var $connect_error = ''; - -	/** -	* {@inheritDoc} -	*/ -	function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) -	{ -		$this->persistency = $persistency; -		$this->user = $sqluser; -		$this->server = $sqlserver . (($port) ? ':' . $port : ''); -		$this->dbname = $database; - -		$this->sql_layer = 'mysql4'; - -		if ($this->persistency) -		{ -			if (!function_exists('mysql_pconnect')) -			{ -				$this->connect_error = 'mysql_pconnect function does not exist, is mysql extension installed?'; -				return $this->sql_error(''); -			} -			$this->db_connect_id = @mysql_pconnect($this->server, $this->user, $sqlpassword); -		} -		else -		{ -			if (!function_exists('mysql_connect')) -			{ -				$this->connect_error = 'mysql_connect function does not exist, is mysql extension installed?'; -				return $this->sql_error(''); -			} -			$this->db_connect_id = @mysql_connect($this->server, $this->user, $sqlpassword, $new_link); -		} - -		if ($this->db_connect_id && $this->dbname != '') -		{ -			if (@mysql_select_db($this->dbname, $this->db_connect_id)) -			{ -				// Determine what version we are using and if it natively supports UNICODE -				if (version_compare($this->sql_server_info(true), '4.1.0', '>=')) -				{ -					@mysql_query("SET NAMES 'utf8'", $this->db_connect_id); - -					// enforce strict mode on databases that support it -					if (version_compare($this->sql_server_info(true), '5.0.2', '>=')) -					{ -						$result = @mysql_query('SELECT @@session.sql_mode AS sql_mode', $this->db_connect_id); -						if ($result) -						{ -							$row = mysql_fetch_assoc($result); -							mysql_free_result($result); -							$modes = array_map('trim', explode(',', $row['sql_mode'])); -						} -						else -						{ -							$modes = array(); -						} - -						// TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES -						if (!in_array('TRADITIONAL', $modes)) -						{ -							if (!in_array('STRICT_ALL_TABLES', $modes)) -							{ -								$modes[] = 'STRICT_ALL_TABLES'; -							} - -							if (!in_array('STRICT_TRANS_TABLES', $modes)) -							{ -								$modes[] = 'STRICT_TRANS_TABLES'; -							} -						} - -						$mode = implode(',', $modes); -						@mysql_query("SET SESSION sql_mode='{$mode}'", $this->db_connect_id); -					} -				} -				else if (version_compare($this->sql_server_info(true), '4.0.0', '<')) -				{ -					$this->sql_layer = 'mysql'; -				} - -				return $this->db_connect_id; -			} -		} - -		return $this->sql_error(''); -	} - -	/** -	* {@inheritDoc} -	*/ -	function sql_server_info($raw = false, $use_cache = true) -	{ -		global $cache; - -		if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('mysql_version')) === false) -		{ -			$result = @mysql_query('SELECT VERSION() AS version', $this->db_connect_id); -			if ($result) -			{ -				$row = mysql_fetch_assoc($result); -				mysql_free_result($result); - -				$this->sql_server_version = $row['version']; - -				if (!empty($cache) && $use_cache) -				{ -					$cache->put('mysql_version', $this->sql_server_version); -				} -			} -		} - -		return ($raw) ? $this->sql_server_version : 'MySQL ' . $this->sql_server_version; -	} - -	/** -	* SQL Transaction -	* @access private -	*/ -	function _sql_transaction($status = 'begin') -	{ -		switch ($status) -		{ -			case 'begin': -				return @mysql_query('BEGIN', $this->db_connect_id); -			break; - -			case 'commit': -				return @mysql_query('COMMIT', $this->db_connect_id); -			break; - -			case 'rollback': -				return @mysql_query('ROLLBACK', $this->db_connect_id); -			break; -		} - -		return true; -	} - -	/** -	* {@inheritDoc} -	*/ -	function sql_query($query = '', $cache_ttl = 0) -	{ -		if ($query != '') -		{ -			global $cache; - -			// EXPLAIN only in extra debug mode -			if (defined('DEBUG')) -			{ -				$this->sql_report('start', $query); -			} -			else if (defined('PHPBB_DISPLAY_LOAD_TIME')) -			{ -				$this->curtime = microtime(true); -			} - -			$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; -			$this->sql_add_num_queries($this->query_result); - -			if ($this->query_result === false) -			{ -				if (($this->query_result = @mysql_query($query, $this->db_connect_id)) === false) -				{ -					$this->sql_error($query); -				} - -				if (defined('DEBUG')) -				{ -					$this->sql_report('stop', $query); -				} -				else if (defined('PHPBB_DISPLAY_LOAD_TIME')) -				{ -					$this->sql_time += microtime(true) - $this->curtime; -				} - -				if (!$this->query_result) -				{ -					return false; -				} - -				if ($cache && $cache_ttl) -				{ -					$this->open_queries[(int) $this->query_result] = $this->query_result; -					$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); -				} -				else if (strpos($query, 'SELECT') === 0) -				{ -					$this->open_queries[(int) $this->query_result] = $this->query_result; -				} -			} -			else if (defined('DEBUG')) -			{ -				$this->sql_report('fromcache', $query); -			} -		} -		else -		{ -			return false; -		} - -		return $this->query_result; -	} - -	/** -	* {@inheritDoc} -	*/ -	function sql_affectedrows() -	{ -		if ($this->db_connect_id) -		{ -			// We always want the number of matched rows -			// instead of changed rows, when running an update. -			// So when mysql_info() returns the number of matched rows -			// we return that one instead of mysql_affected_rows() -			$mysql_info = @mysql_info($this->db_connect_id); -			if ($mysql_info !== false) -			{ -				$match = array(); -				preg_match('#^Rows matched: (\d)+  Changed: (\d)+  Warnings: (\d)+$#', $mysql_info, $match); -				if (isset($match[1])) -				{ -					return $match[1]; -				} -			} - -			return @mysql_affected_rows($this->db_connect_id); -		} -		return false; -	} - -	/** -	* {@inheritDoc} -	*/ -	function sql_fetchrow($query_id = false) -	{ -		global $cache; - -		if ($query_id === false) -		{ -			$query_id = $this->query_result; -		} - -		if ($cache && $cache->sql_exists($query_id)) -		{ -			return $cache->sql_fetchrow($query_id); -		} - -		return ($query_id) ? mysql_fetch_assoc($query_id) : false; -	} - -	/** -	* {@inheritDoc} -	*/ -	function sql_rowseek($rownum, &$query_id) -	{ -		global $cache; - -		if ($query_id === false) -		{ -			$query_id = $this->query_result; -		} - -		if ($cache && $cache->sql_exists($query_id)) -		{ -			return $cache->sql_rowseek($rownum, $query_id); -		} - -		return ($query_id !== false) ? @mysql_data_seek($query_id, $rownum) : false; -	} - -	/** -	* {@inheritDoc} -	*/ -	function sql_nextid() -	{ -		return ($this->db_connect_id) ? @mysql_insert_id($this->db_connect_id) : false; -	} - -	/** -	* {@inheritDoc} -	*/ -	function sql_freeresult($query_id = false) -	{ -		global $cache; - -		if ($query_id === false) -		{ -			$query_id = $this->query_result; -		} - -		if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) -		{ -			return $cache->sql_freeresult($query_id); -		} - -		if (isset($this->open_queries[(int) $query_id])) -		{ -			unset($this->open_queries[(int) $query_id]); -			return mysql_free_result($query_id); -		} - -		return false; -	} - -	/** -	* {@inheritDoc} -	*/ -	function sql_escape($msg) -	{ -		if (!$this->db_connect_id) -		{ -			return @mysql_real_escape_string($msg); -		} - -		return @mysql_real_escape_string($msg, $this->db_connect_id); -	} - -	/** -	* return sql error array -	* @access private -	*/ -	function _sql_error() -	{ -		if ($this->db_connect_id) -		{ -			$error = array( -				'message'	=> @mysql_error($this->db_connect_id), -				'code'		=> @mysql_errno($this->db_connect_id), -			); -		} -		else if (function_exists('mysql_error')) -		{ -			$error = array( -				'message'	=> @mysql_error(), -				'code'		=> @mysql_errno(), -			); -		} -		else -		{ -			$error = array( -				'message'	=> $this->connect_error, -				'code'		=> '', -			); -		} - -		return $error; -	} - -	/** -	* Close sql connection -	* @access private -	*/ -	function _sql_close() -	{ -		return @mysql_close($this->db_connect_id); -	} - -	/** -	* Build db-specific report -	* @access private -	*/ -	function _sql_report($mode, $query = '') -	{ -		static $test_prof; - -		// current detection method, might just switch to see the existance of INFORMATION_SCHEMA.PROFILING -		if ($test_prof === null) -		{ -			$test_prof = false; -			if (version_compare($this->sql_server_info(true), '5.0.37', '>=') && version_compare($this->sql_server_info(true), '5.1', '<')) -			{ -				$test_prof = true; -			} -		} - -		switch ($mode) -		{ -			case 'start': - -				$explain_query = $query; -				if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m)) -				{ -					$explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2]; -				} -				else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m)) -				{ -					$explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2]; -				} - -				if (preg_match('/^SELECT/', $explain_query)) -				{ -					$html_table = false; - -					// begin profiling -					if ($test_prof) -					{ -						@mysql_query('SET profiling = 1;', $this->db_connect_id); -					} - -					if ($result = @mysql_query("EXPLAIN $explain_query", $this->db_connect_id)) -					{ -						while ($row = mysql_fetch_assoc($result)) -						{ -							$html_table = $this->sql_report('add_select_row', $query, $html_table, $row); -						} -						mysql_free_result($result); -					} - -					if ($html_table) -					{ -						$this->html_hold .= '</table>'; -					} - -					if ($test_prof) -					{ -						$html_table = false; - -						// get the last profile -						if ($result = @mysql_query('SHOW PROFILE ALL;', $this->db_connect_id)) -						{ -							$this->html_hold .= '<br />'; -							while ($row = mysql_fetch_assoc($result)) -							{ -								// make <unknown> HTML safe -								if (!empty($row['Source_function'])) -								{ -									$row['Source_function'] = str_replace(array('<', '>'), array('<', '>'), $row['Source_function']); -								} - -								// remove unsupported features -								foreach ($row as $key => $val) -								{ -									if ($val === null) -									{ -										unset($row[$key]); -									} -								} -								$html_table = $this->sql_report('add_select_row', $query, $html_table, $row); -							} -							mysql_free_result($result); -						} - -						if ($html_table) -						{ -							$this->html_hold .= '</table>'; -						} - -						@mysql_query('SET profiling = 0;', $this->db_connect_id); -					} -				} - -			break; - -			case 'fromcache': -				$endtime = explode(' ', microtime()); -				$endtime = $endtime[0] + $endtime[1]; - -				$result = @mysql_query($query, $this->db_connect_id); -				if ($result) -				{ -					while ($void = mysql_fetch_assoc($result)) -					{ -						// Take the time spent on parsing rows into account -					} -					mysql_free_result($result); -				} - -				$splittime = explode(' ', microtime()); -				$splittime = $splittime[0] + $splittime[1]; - -				$this->sql_report('record_fromcache', $query, $endtime, $splittime); - -			break; -		} -	} -} diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index b429ad97aa..0c1c063262 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -176,12 +176,11 @@ class mysqli extends \phpbb\db\driver\mysql_base  		{  			global $cache; -			// EXPLAIN only in extra debug mode -			if (defined('DEBUG')) +			if ($this->debug_sql_explain)  			{  				$this->sql_report('start', $query);  			} -			else if (defined('PHPBB_DISPLAY_LOAD_TIME')) +			else if ($this->debug_load_time)  			{  				$this->curtime = microtime(true);  			} @@ -196,11 +195,11 @@ class mysqli extends \phpbb\db\driver\mysql_base  					$this->sql_error($query);  				} -				if (defined('DEBUG')) +				if ($this->debug_sql_explain)  				{  					$this->sql_report('stop', $query);  				} -				else if (defined('PHPBB_DISPLAY_LOAD_TIME')) +				else if ($this->debug_load_time)  				{  					$this->sql_time += microtime(true) - $this->curtime;  				} @@ -215,7 +214,7 @@ class mysqli extends \phpbb\db\driver\mysql_base  					$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);  				}  			} -			else if (defined('DEBUG')) +			else if ($this->debug_sql_explain)  			{  				$this->sql_report('fromcache', $query);  			} @@ -376,7 +375,7 @@ class mysqli extends \phpbb\db\driver\mysql_base  	{  		static $test_prof; -		// current detection method, might just switch to see the existance of INFORMATION_SCHEMA.PROFILING +		// current detection method, might just switch to see the existence of INFORMATION_SCHEMA.PROFILING  		if ($test_prof === null)  		{  			$test_prof = false; diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php index 5fd14709f8..f2a0bb557a 100644 --- a/phpBB/phpbb/db/driver/oracle.php +++ b/phpBB/phpbb/db/driver/oracle.php @@ -246,12 +246,11 @@ class oracle extends \phpbb\db\driver\driver  		{  			global $cache; -			// EXPLAIN only in extra debug mode -			if (defined('DEBUG')) +			if ($this->debug_sql_explain)  			{  				$this->sql_report('start', $query);  			} -			else if (defined('PHPBB_DISPLAY_LOAD_TIME')) +			else if ($this->debug_load_time)  			{  				$this->curtime = microtime(true);  			} @@ -428,11 +427,11 @@ class oracle extends \phpbb\db\driver\driver  					}  				} -				if (defined('DEBUG')) +				if ($this->debug_sql_explain)  				{  					$this->sql_report('stop', $query);  				} -				else if (defined('PHPBB_DISPLAY_LOAD_TIME')) +				else if ($this->debug_load_time)  				{  					$this->sql_time += microtime(true) - $this->curtime;  				} @@ -452,7 +451,7 @@ class oracle extends \phpbb\db\driver\driver  					$this->open_queries[(int) $this->query_result] = $this->query_result;  				}  			} -			else if (defined('DEBUG')) +			else if ($this->debug_sql_explain)  			{  				$this->sql_report('fromcache', $query);  			} diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php index 44476612c3..ed330bc540 100644 --- a/phpBB/phpbb/db/driver/postgres.php +++ b/phpBB/phpbb/db/driver/postgres.php @@ -173,12 +173,11 @@ class postgres extends \phpbb\db\driver\driver  		{  			global $cache; -			// EXPLAIN only in extra debug mode -			if (defined('DEBUG')) +			if ($this->debug_sql_explain)  			{  				$this->sql_report('start', $query);  			} -			else if (defined('PHPBB_DISPLAY_LOAD_TIME')) +			else if ($this->debug_load_time)  			{  				$this->curtime = microtime(true);  			} @@ -194,11 +193,11 @@ class postgres extends \phpbb\db\driver\driver  					$this->sql_error($query);  				} -				if (defined('DEBUG')) +				if ($this->debug_sql_explain)  				{  					$this->sql_report('stop', $query);  				} -				else if (defined('PHPBB_DISPLAY_LOAD_TIME')) +				else if ($this->debug_load_time)  				{  					$this->sql_time += microtime(true) - $this->curtime;  				} @@ -218,7 +217,7 @@ class postgres extends \phpbb\db\driver\driver  					$this->open_queries[(int) $this->query_result] = $this->query_result;  				}  			} -			else if (defined('DEBUG')) +			else if ($this->debug_sql_explain)  			{  				$this->sql_report('fromcache', $query);  			} diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php index 0508500c52..43906f1b58 100644 --- a/phpBB/phpbb/db/driver/sqlite3.php +++ b/phpBB/phpbb/db/driver/sqlite3.php @@ -118,12 +118,11 @@ class sqlite3 extends \phpbb\db\driver\driver  		{  			global $cache; -			// EXPLAIN only in extra debug mode -			if (defined('DEBUG')) +			if ($this->debug_sql_explain)  			{  				$this->sql_report('start', $query);  			} -			else if (defined('PHPBB_DISPLAY_LOAD_TIME')) +			else if ($this->debug_load_time)  			{  				$this->curtime = microtime(true);  			} @@ -156,11 +155,11 @@ class sqlite3 extends \phpbb\db\driver\driver  					}  				} -				if (defined('DEBUG')) +				if ($this->debug_sql_explain)  				{  					$this->sql_report('stop', $query);  				} -				else if (defined('PHPBB_DISPLAY_LOAD_TIME')) +				else if ($this->debug_load_time)  				{  					$this->sql_time += microtime(true) - $this->curtime;  				} @@ -175,7 +174,7 @@ class sqlite3 extends \phpbb\db\driver\driver  					$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);  				}  			} -			else if (defined('DEBUG')) +			else if ($this->debug_sql_explain)  			{  				$this->sql_report('fromcache', $query);  			} diff --git a/phpBB/phpbb/db/extractor/mysql_extractor.php b/phpBB/phpbb/db/extractor/mysql_extractor.php index 34e309c19e..f3cb0db457 100644 --- a/phpBB/phpbb/db/extractor/mysql_extractor.php +++ b/phpBB/phpbb/db/extractor/mysql_extractor.php @@ -79,14 +79,7 @@ class mysql_extractor extends base_extractor  			throw new extractor_not_initialized_exception();  		} -		if ($this->db->get_sql_layer() === 'mysqli') -		{ -			$this->write_data_mysqli($table_name); -		} -		else -		{ -			$this->write_data_mysql($table_name); -		} +		$this->write_data_mysqli($table_name);  	}  	/** @@ -180,101 +173,6 @@ class mysql_extractor extends base_extractor  	}  	/** -	* Extracts data from database table (for MySQL driver) -	* -	* @param	string	$table_name	name of the database table -	* @return null -	* @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor() -	*/ -	protected function write_data_mysql($table_name) -	{ -		if (!$this->is_initialized) -		{ -			throw new extractor_not_initialized_exception(); -		} - -		$sql = "SELECT * -			FROM $table_name"; -		$result = mysql_unbuffered_query($sql, $this->db->get_db_connect_id()); - -		if ($result != false) -		{ -			$fields_cnt = mysql_num_fields($result); - -			// Get field information -			$field = array(); -			for ($i = 0; $i < $fields_cnt; $i++) -			{ -				$field[] = mysql_fetch_field($result, $i); -			} -			$field_set = array(); - -			for ($j = 0; $j < $fields_cnt; $j++) -			{ -				$field_set[] = $field[$j]->name; -			} - -			$search			= array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"'); -			$replace		= array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"'); -			$fields			= implode(', ', $field_set); -			$sql_data		= 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES '; -			$first_set		= true; -			$query_len		= 0; -			$max_len		= get_usable_memory(); - -			while ($row = mysql_fetch_row($result)) -			{ -				$values = array(); -				if ($first_set) -				{ -					$query = $sql_data . '('; -				} -				else -				{ -					$query  .= ',('; -				} - -				for ($j = 0; $j < $fields_cnt; $j++) -				{ -					if (!isset($row[$j]) || is_null($row[$j])) -					{ -						$values[$j] = 'NULL'; -					} -					else if ($field[$j]->numeric && ($field[$j]->type !== 'timestamp')) -					{ -						$values[$j] = $row[$j]; -					} -					else -					{ -						$values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'"; -					} -				} -				$query .= implode(', ', $values) . ')'; - -				$query_len += strlen($query); -				if ($query_len > $max_len) -				{ -					$this->flush($query . ";\n\n"); -					$query = ''; -					$query_len = 0; -					$first_set = true; -				} -				else -				{ -					$first_set = false; -				} -			} -			mysql_free_result($result); - -			// check to make sure we have nothing left to flush -			if (!$first_set && $query) -			{ -				$this->flush($query . ";\n\n"); -			} -		} -	} - -	/**  	* Extracts database table structure (for MySQLi or MySQL 3.23.20+)  	*  	* @param	string	$table_name	name of the database table @@ -300,7 +198,7 @@ class mysql_extractor extends base_extractor  	}  	/** -	* Extracts database table structure (for MySQL verisons older than 3.23.20) +	* Extracts database table structure (for MySQL versions older than 3.23.20)  	*  	* @param	string	$table_name	name of the database table  	* @return null diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_4_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_4_rc1.php index 10343438b3..247ccc7a76 100644 --- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_4_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_4_rc1.php @@ -117,7 +117,7 @@ class release_3_0_4_rc1 extends \phpbb\db\migration\migration  			}  			else  			{ -				// equivelant to "none", which is the "Display in user control panel" option +				// equivalent to "none", which is the "Display in user control panel" option  				$sql_ary['field_show_profile'] = 1;  			} diff --git a/phpBB/phpbb/db/migration/data/v310/softdelete_p1.php b/phpBB/phpbb/db/migration/data/v310/softdelete_p1.php index b1e7486e24..877cdc2fa3 100644 --- a/phpBB/phpbb/db/migration/data/v310/softdelete_p1.php +++ b/phpBB/phpbb/db/migration/data/v310/softdelete_p1.php @@ -132,7 +132,7 @@ class softdelete_p1 extends \phpbb\db\migration\migration  		/*  		* Using sql_case here to avoid "BIGINT UNSIGNED value is out of range" errors.  		* As we update all topics in 2 queries, one broken topic would stop the conversion -		* for all topics and the surpressed error will cause the admin to not even notice it. +		* for all topics and the suppressed error will cause the admin to not even notice it.  		*/  		$sql = 'UPDATE ' . $this->table_prefix . 'topics  			SET topic_posts_approved = topic_replies + 1, diff --git a/phpBB/phpbb/db/migration/data/v330/add_display_unapproved_posts_config.php b/phpBB/phpbb/db/migration/data/v330/add_display_unapproved_posts_config.php new file mode 100644 index 0000000000..209aba3646 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/add_display_unapproved_posts_config.php @@ -0,0 +1,34 @@ +<?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\v330; + +class add_display_unapproved_posts_config extends \phpbb\db\migration\migration +{ +	public function effectively_installed() +	{ +		return $this->config->offsetExists('display_unapproved_posts'); +	} + +	public static function depends_on() +	{ +		return ['\phpbb\db\migration\data\v330\dev',]; +	} + +	public function update_data() +	{ +		return [ +			['config.add', ['display_unapproved_posts', 1]], +		]; +	} +} diff --git a/phpBB/phpbb/db/migration/data/v330/dev.php b/phpBB/phpbb/db/migration/data/v330/dev.php new file mode 100644 index 0000000000..209f9fc7ec --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/dev.php @@ -0,0 +1,36 @@ +<?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\v330; + +class dev extends \phpbb\db\migration\migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.3.0-dev', '>='); +	} + +	static public function depends_on() +	{ +		return array( +			'\phpbb\db\migration\data\v32x\v327', +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.3.0-dev')), +		); +	} +} diff --git a/phpBB/phpbb/db/migration/data/v330/forums_legend_limit.php b/phpBB/phpbb/db/migration/data/v330/forums_legend_limit.php new file mode 100644 index 0000000000..c5a4beef38 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/forums_legend_limit.php @@ -0,0 +1,49 @@ +<?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\v330; + +class forums_legend_limit extends \phpbb\db\migration\migration +{ +	public function effectively_installed() +	{ +		return $this->db_tools->sql_column_exists($this->table_prefix . 'forums', 'display_subforum_limit'); +	} + +	static public function depends_on() +	{ +		return ['\phpbb\db\migration\data\v330\v330b1']; +	} + +	public function update_schema() +	{ +		return [ +			'add_columns'		=> [ +				$this->table_prefix . 'forums'	=> [ +					'display_subforum_limit'	=> ['BOOL', 0, 'after' => 'display_subforum_list'], +				], +			], +		]; +	} + +	public function revert_schema() +	{ +		return [ +			'drop_columns'		=> [ +				$this->table_prefix . 'forums'		=> [ +					'display_subforum_limit', +				], +			], +		]; +	} +} diff --git a/phpBB/phpbb/db/migration/data/v330/jquery_update.php b/phpBB/phpbb/db/migration/data/v330/jquery_update.php new file mode 100644 index 0000000000..f1ac6cdd41 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/jquery_update.php @@ -0,0 +1,37 @@ +<?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\v330; + +class jquery_update extends \phpbb\db\migration\migration +{ +	public function effectively_installed() +	{ +		return $this->config['load_jquery_url'] === '//ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js'; +	} + +	static public function depends_on() +	{ +		return array( +			'\phpbb\db\migration\data\v330\dev', +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js')), +		); +	} + +} diff --git a/phpBB/phpbb/db/migration/data/v330/remove_attachment_flash.php b/phpBB/phpbb/db/migration/data/v330/remove_attachment_flash.php new file mode 100644 index 0000000000..c136960905 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/remove_attachment_flash.php @@ -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\v330; + +class remove_attachment_flash extends \phpbb\db\migration\migration +{ +	// Following constants were deprecated in 3.3 +	// and moved from constants.php to compatibility_globals.php, +	// thus define them as class constants +	const ATTACHMENT_CATEGORY_FLASH = 5; + +	protected $cat_id = array( +		self::ATTACHMENT_CATEGORY_FLASH, +	); + +	public static function depends_on() +	{ +		return ['\phpbb\db\migration\data\v330\dev',]; +	} + +	public function update_data() +	{ +		return array( +			array('custom', array(array($this, 'remove_flash_group'))), +		); +	} + +	public function remove_flash_group() +	{ +		// select group ids of outdated media +		$sql = 'SELECT group_id +			FROM ' . EXTENSION_GROUPS_TABLE . ' +			WHERE ' . $this->db->sql_in_set('cat_id', $this->cat_id); +		$result = $this->db->sql_query($sql); + +		$group_ids = array(); +		while ($group_id = (int) $this->db->sql_fetchfield('group_id')) +		{ +			$group_ids[] = $group_id; +		} +		$this->db->sql_freeresult($result); + +		// nothing to do, admin has removed all the outdated media extension groups +		if (empty($group_ids)) +		{ +			return true; +		} + +		// get the group id of downloadable files +		$sql = 'SELECT group_id +			FROM ' . EXTENSION_GROUPS_TABLE . " +			WHERE group_name = 'DOWNLOADABLE_FILES'"; +		$result = $this->db->sql_query($sql); +		$download_id = (int) $this->db->sql_fetchfield('group_id'); +		$this->db->sql_freeresult($result); + +		if (empty($download_id)) +		{ +			$sql = 'UPDATE ' . EXTENSIONS_TABLE . ' +				SET group_id = 0 +				WHERE ' . $this->db->sql_in_set('group_id', $group_ids); +		} +		else +		{ +			// move outdated media extensions to downloadable files +			$sql = 'UPDATE ' . EXTENSIONS_TABLE . " +				SET group_id = $download_id" . ' +				WHERE ' . $this->db->sql_in_set('group_id', $group_ids); +		} + +		$this->db->sql_query($sql); + +		// delete the now empty, outdated media extension groups +		$sql = 'DELETE FROM ' . EXTENSION_GROUPS_TABLE . ' +			WHERE ' . $this->db->sql_in_set('group_id', $group_ids); +		$this->db->sql_query($sql); +	} +} diff --git a/phpBB/phpbb/db/migration/data/v330/remove_email_hash.php b/phpBB/phpbb/db/migration/data/v330/remove_email_hash.php new file mode 100644 index 0000000000..8ac8f4ed72 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/remove_email_hash.php @@ -0,0 +1,62 @@ +<?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\v330; + +class remove_email_hash extends \phpbb\db\migration\migration +{ +	static public function depends_on() +	{ +		return ['\phpbb\db\migration\data\v30x\release_3_0_0']; +	} + +	public function update_schema() +	{ +		return [ +			'add_index' => [ +				$this->table_prefix . 'users' => [ +					'user_email' => ['user_email'], +				], +			], +			'drop_keys' => [ +				$this->table_prefix . 'users' => [ +					'user_email_hash', +				], +			], +			'drop_columns' => [ +				$this->table_prefix . 'users' => ['user_email_hash'], +			], +		]; +	} + +	public function revert_schema() +	{ +		return [ +			'add_columns' => [ +				$this->table_prefix . 'users' => [ +					'user_email_hash' => ['BINT', 0], +				], +			], +			'add_index' => [ +				$this->table_prefix . 'users' => [ +					'user_email_hash', +				], +			], +			'drop_keys' => [ +				$this->table_prefix . 'users' => [ +					'user_email' => ['user_email'], +				], +			], +		]; +	} +} diff --git a/phpBB/phpbb/db/migration/data/v330/remove_max_pass_chars.php b/phpBB/phpbb/db/migration/data/v330/remove_max_pass_chars.php new file mode 100644 index 0000000000..10e5ee385d --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/remove_max_pass_chars.php @@ -0,0 +1,43 @@ +<?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\v330; + +class remove_max_pass_chars extends \phpbb\db\migration\migration +{ +	public function effectively_installed() +	{ +		return !$this->config->offsetExists('max_pass_chars'); +	} + +	public static function depends_on() +	{ +		return [ +			'\phpbb\db\migration\data\v330\dev', +		]; +	} + +	public function update_data() +	{ +		return [ +			['config.remove', ['max_pass_chars']], +		]; +	} + +	public function revert_data() +	{ +		return [ +			['config.add', ['max_pass_chars', 100]], +		]; +	} +} diff --git a/phpBB/phpbb/db/migration/data/v330/reset_password.php b/phpBB/phpbb/db/migration/data/v330/reset_password.php new file mode 100644 index 0000000000..953d478ccc --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/reset_password.php @@ -0,0 +1,48 @@ +<?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\v330; + +class reset_password extends \phpbb\db\migration\migration +{ +	static public function depends_on() +	{ +		return [ +			'\phpbb\db\migration\data\v330\dev', +		]; +	} + +	public function update_schema() +	{ +		return [ +			'add_columns' => [ +				$this->table_prefix . 'users' => [ +					'reset_token'				=> ['VCHAR:64', '', 'after' => 'user_actkey'], +					'reset_token_expiration'	=> ['TIMESTAMP', 0, 'after' => 'reset_token'], +				], +			], +		]; +	} + +	public function revert_schema() +	{ +		return [ +			'drop_columns' => [ +				$this->table_prefix . 'users' => [ +					'reset_token', +					'reset_token_expiration', +				], +			], +		]; +	} +} diff --git a/phpBB/phpbb/db/migration/data/v330/v330.php b/phpBB/phpbb/db/migration/data/v330/v330.php new file mode 100644 index 0000000000..05baffbdbd --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/v330.php @@ -0,0 +1,37 @@ +<?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\v330; + +class v330 extends \phpbb\db\migration\migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.3.0', '>='); +	} + +	static public function depends_on() +	{ +		return array( +			'\phpbb\db\migration\data\v32x\v329', +			'\phpbb\db\migration\data\v330\v330rc1', +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.3.0')), +		); +	} +} diff --git a/phpBB/phpbb/db/migration/data/v330/v330b1.php b/phpBB/phpbb/db/migration/data/v330/v330b1.php new file mode 100644 index 0000000000..3df44504fc --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/v330b1.php @@ -0,0 +1,41 @@ +<?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\v330; + +class v330b1 extends \phpbb\db\migration\migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.3.0-b1', '>='); +	} + +	static public function depends_on() +	{ +		return array( +			'\phpbb\db\migration\data\v330\jquery_update', +			'\phpbb\db\migration\data\v330\reset_password', +			'\phpbb\db\migration\data\v330\remove_attachment_flash', +			'\phpbb\db\migration\data\v330\remove_max_pass_chars', +			'\phpbb\db\migration\data\v32x\v328', +			'\phpbb\db\migration\data\v330\dev', +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.3.0-b1')), +		); +	} +} diff --git a/phpBB/phpbb/db/migration/data/v330/v330b2.php b/phpBB/phpbb/db/migration/data/v330/v330b2.php new file mode 100644 index 0000000000..cb2198aad7 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/v330b2.php @@ -0,0 +1,39 @@ +<?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\v330; + +class v330b2 extends \phpbb\db\migration\migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.3.0-b2', '>='); +	} + +	static public function depends_on() +	{ +		return array( +			'\phpbb\db\migration\data\v330\add_display_unapproved_posts_config', +			'\phpbb\db\migration\data\v330\forums_legend_limit', +			'\phpbb\db\migration\data\v330\remove_email_hash', +			'\phpbb\db\migration\data\v330\v330b1', +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.3.0-b2')), +		); +	} +} diff --git a/phpBB/phpbb/db/migration/data/v330/v330rc1.php b/phpBB/phpbb/db/migration/data/v330/v330rc1.php new file mode 100644 index 0000000000..52193750cc --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/v330rc1.php @@ -0,0 +1,36 @@ +<?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\v330; + +class v330rc1 extends \phpbb\db\migration\migration +{ +	public function effectively_installed() +	{ +		return version_compare($this->config['version'], '3.3.0-RC1', '>='); +	} + +	static public function depends_on() +	{ +		return array( +			'\phpbb\db\migration\data\v330\v330b2', +		); +	} + +	public function update_data() +	{ +		return array( +			array('config.update', array('version', '3.3.0-RC1')), +		); +	} +} diff --git a/phpBB/phpbb/db/migration/tool/module.php b/phpBB/phpbb/db/migration/tool/module.php index e5133c8152..93c338437e 100644 --- a/phpBB/phpbb/db/migration/tool/module.php +++ b/phpBB/phpbb/db/migration/tool/module.php @@ -509,7 +509,7 @@ class module implements \phpbb\db\migration\tool\tool_interface  	* Get parent module id  	*  	* @param string|int $parent_id The parent module_id|module_langname -	* @param int|string|array $data The module_id, module_langname for existance checking or module data array for adding +	* @param int|string|array $data The module_id, module_langname for existence checking or module data array for adding  	* @param bool $throw_exception The flag indicating if exception should be thrown on error  	* @return mixed The int parent module_id, an array of int parent module_id values or false  	* @throws \phpbb\db\migration\exception diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php index 2b0c66fc58..3a1ee758cf 100644 --- a/phpBB/phpbb/db/migrator.php +++ b/phpBB/phpbb/db/migrator.php @@ -784,7 +784,7 @@ class migrator  				{  					return array(  						$parameters[0], -						array($last_result), +						isset($parameters[1]) ? array_merge($parameters[1], array($last_result)) : array($last_result),  					);  				}  			break; diff --git a/phpBB/phpbb/db/tools/mssql.php b/phpBB/phpbb/db/tools/mssql.php index cbedf9a5c4..29f816a869 100644 --- a/phpBB/phpbb/db/tools/mssql.php +++ b/phpBB/phpbb/db/tools/mssql.php @@ -194,7 +194,7 @@ class mssql extends tools  				$primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set'];  			} -			// create sequence DDL based off of the existance of auto incrementing columns +			// create sequence DDL based off of the existence of auto incrementing columns  			if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'])  			{  				$create_sequence = $column_name; diff --git a/phpBB/phpbb/db/tools/postgres.php b/phpBB/phpbb/db/tools/postgres.php index 077d6e06f9..276ac135be 100644 --- a/phpBB/phpbb/db/tools/postgres.php +++ b/phpBB/phpbb/db/tools/postgres.php @@ -141,7 +141,7 @@ class postgres extends tools  				$primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set'];  			} -			// create sequence DDL based off of the existance of auto incrementing columns +			// create sequence DDL based off of the existence of auto incrementing columns  			if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'])  			{  				$create_sequence = $column_name; diff --git a/phpBB/phpbb/db/tools/tools.php b/phpBB/phpbb/db/tools/tools.php index c3352a1f66..1250a8901d 100644 --- a/phpBB/phpbb/db/tools/tools.php +++ b/phpBB/phpbb/db/tools/tools.php @@ -74,37 +74,6 @@ class tools implements tools_interface  				'VARBINARY'	=> 'varbinary(255)',  			), -			'mysql_40'	=> array( -				'INT:'		=> 'int(%d)', -				'BINT'		=> 'bigint(20)', -				'ULINT'		=> 'INT(10) UNSIGNED', -				'UINT'		=> 'mediumint(8) UNSIGNED', -				'UINT:'		=> 'int(%d) UNSIGNED', -				'TINT:'		=> 'tinyint(%d)', -				'USINT'		=> 'smallint(4) UNSIGNED', -				'BOOL'		=> 'tinyint(1) UNSIGNED', -				'VCHAR'		=> 'varbinary(255)', -				'VCHAR:'	=> 'varbinary(%d)', -				'CHAR:'		=> 'binary(%d)', -				'XSTEXT'	=> 'blob', -				'XSTEXT_UNI'=> 'blob', -				'STEXT'		=> 'blob', -				'STEXT_UNI'	=> 'blob', -				'TEXT'		=> 'blob', -				'TEXT_UNI'	=> 'blob', -				'MTEXT'		=> 'mediumblob', -				'MTEXT_UNI'	=> 'mediumblob', -				'TIMESTAMP'	=> 'int(11) UNSIGNED', -				'DECIMAL'	=> 'decimal(5,2)', -				'DECIMAL:'	=> 'decimal(%d,2)', -				'PDECIMAL'	=> 'decimal(6,3)', -				'PDECIMAL:'	=> 'decimal(%d,3)', -				'VCHAR_UNI'	=> 'blob', -				'VCHAR_UNI:'=> array('varbinary(%d)', 'limit' => array('mult', 3, 255, 'blob')), -				'VCHAR_CI'	=> 'blob', -				'VARBINARY'	=> 'varbinary(255)', -			), -  			'oracle'	=> array(  				'INT:'		=> 'number(%d)',  				'BINT'		=> 'number(20)', @@ -197,21 +166,6 @@ class tools implements tools_interface  		// Determine mapping database type  		switch ($this->db->get_sql_layer())  		{ -			case 'mysql': -				$this->sql_layer = 'mysql_40'; -			break; - -			case 'mysql4': -				if (version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) -				{ -					$this->sql_layer = 'mysql_41'; -				} -				else -				{ -					$this->sql_layer = 'mysql_40'; -				} -			break; -  			case 'mysqli':  				$this->sql_layer = 'mysql_41';  			break; @@ -240,8 +194,6 @@ class tools implements tools_interface  	{  		switch ($this->db->get_sql_layer())  		{ -			case 'mysql': -			case 'mysql4':  			case 'mysqli':  				$sql = 'SHOW TABLES';  			break; @@ -335,7 +287,7 @@ class tools implements tools_interface  				$primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set'];  			} -			// create sequence DDL based off of the existance of auto incrementing columns +			// create sequence DDL based off of the existence of auto incrementing columns  			if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'])  			{  				$create_sequence = $column_name; @@ -359,7 +311,6 @@ class tools implements tools_interface  				switch ($this->sql_layer)  				{ -					case 'mysql_40':  					case 'mysql_41':  					case 'sqlite3':  						$table_sql .= ",\n\t PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')'; @@ -381,7 +332,6 @@ class tools implements tools_interface  				$statements[] = $table_sql;  			break; -			case 'mysql_40':  			case 'sqlite3':  				$table_sql .= "\n);";  				$statements[] = $table_sql; @@ -834,7 +784,6 @@ class tools implements tools_interface  		switch ($this->sql_layer)  		{ -			case 'mysql_40':  			case 'mysql_41':  				$sql = "SHOW COLUMNS FROM $table_name";  			break; @@ -911,7 +860,6 @@ class tools implements tools_interface  	{  		switch ($this->sql_layer)  		{ -			case 'mysql_40':  			case 'mysql_41':  				$sql = 'SHOW KEYS  					FROM ' . $table_name; @@ -936,7 +884,7 @@ class tools implements tools_interface  		$result = $this->db->sql_query($sql);  		while ($row = $this->db->sql_fetchrow($result))  		{ -			if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && !$row['Non_unique']) +			if ($this->sql_layer == 'mysql_41' && !$row['Non_unique'])  			{  				continue;  			} @@ -971,7 +919,6 @@ class tools implements tools_interface  	{  		switch ($this->sql_layer)  		{ -			case 'mysql_40':  			case 'mysql_41':  				$sql = 'SHOW KEYS  					FROM ' . $table_name; @@ -996,7 +943,7 @@ class tools implements tools_interface  		$result = $this->db->sql_query($sql);  		while ($row = $this->db->sql_fetchrow($result))  		{ -			if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && ($row['Non_unique'] || $row[$col] == 'PRIMARY')) +			if ($this->sql_layer == 'mysql_41' && ($row['Non_unique'] || $row[$col] == 'PRIMARY'))  			{  				continue;  			} @@ -1094,7 +1041,6 @@ class tools implements tools_interface  		switch ($this->sql_layer)  		{ -			case 'mysql_40':  			case 'mysql_41':  				$sql .= " {$column_type} "; @@ -1248,7 +1194,6 @@ class tools implements tools_interface  		switch ($this->sql_layer)  		{ -			case 'mysql_40':  			case 'mysql_41':  				$after = (!empty($column_data['after'])) ? ' AFTER ' . $column_data['after'] : '';  				$statements[] = 'ALTER TABLE `' . $table_name . '` ADD COLUMN `' . $column_name . '` ' . $column_data['column_type_sql'] . $after; @@ -1281,7 +1226,6 @@ class tools implements tools_interface  		switch ($this->sql_layer)  		{ -			case 'mysql_40':  			case 'mysql_41':  				$statements[] = 'ALTER TABLE `' . $table_name . '` DROP COLUMN `' . $column_name . '`';  			break; @@ -1360,7 +1304,6 @@ class tools implements tools_interface  		switch ($this->sql_layer)  		{ -			case 'mysql_40':  			case 'mysql_41':  				$index_name = $this->check_index_name_length($table_name, $index_name, false);  				$statements[] = 'DROP INDEX ' . $index_name . ' ON ' . $table_name; @@ -1422,7 +1365,6 @@ class tools implements tools_interface  		switch ($this->sql_layer)  		{ -			case 'mysql_40':  			case 'mysql_41':  				$statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';  			break; @@ -1500,7 +1442,6 @@ class tools implements tools_interface  				$statements[] = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';  			break; -			case 'mysql_40':  			case 'mysql_41':  				$index_name = $this->check_index_name_length($table_name, $index_name);  				$statements[] = 'ALTER TABLE ' . $table_name . ' ADD UNIQUE INDEX ' . $index_name . '(' . implode(', ', $column) . ')'; @@ -1517,11 +1458,7 @@ class tools implements tools_interface  	{  		$statements = array(); -		// remove index length unless MySQL4 -		if ('mysql_40' != $this->sql_layer) -		{ -			$column = preg_replace('#:.*$#', '', $column); -		} +		$column = preg_replace('#:.*$#', '', $column);  		switch ($this->sql_layer)  		{ @@ -1531,17 +1468,6 @@ class tools implements tools_interface  				$statements[] = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';  			break; -			case 'mysql_40': -				// add index size to definition as required by MySQL4 -				foreach ($column as $i => $col) -				{ -					if (false !== strpos($col, ':')) -					{ -						list($col, $index_size) = explode(':', $col); -						$column[$i] = "$col($index_size)"; -					} -				} -			// no break  			case 'mysql_41':  				$index_name = $this->check_index_name_length($table_name, $index_name);  				$statements[] = 'ALTER TABLE ' . $table_name . ' ADD INDEX ' . $index_name . ' (' . implode(', ', $column) . ')'; @@ -1609,7 +1535,6 @@ class tools implements tools_interface  		switch ($this->sql_layer)  		{ -			case 'mysql_40':  			case 'mysql_41':  				$sql = 'SHOW KEYS  					FROM ' . $table_name; @@ -1634,7 +1559,7 @@ class tools implements tools_interface  		$result = $this->db->sql_query($sql);  		while ($row = $this->db->sql_fetchrow($result))  		{ -			if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && !$row['Non_unique']) +			if ($this->sql_layer == 'mysql_41' && !$row['Non_unique'])  			{  				continue;  			} @@ -1677,7 +1602,6 @@ class tools implements tools_interface  		switch ($this->sql_layer)  		{ -			case 'mysql_40':  			case 'mysql_41':  				$statements[] = 'ALTER TABLE `' . $table_name . '` CHANGE `' . $column_name . '` `' . $column_name . '` ' . $column_data['column_type_sql'];  			break; @@ -1826,7 +1750,6 @@ class tools implements tools_interface  	{  		switch ($this->sql_layer)  		{ -			case 'mysql_40':  			case 'mysql_41':  			case 'sqlite3':  				// Not supported diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index 8c1ce8bde2..70ceb9b5e3 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -158,13 +158,18 @@ class container_builder  			}  			else  			{ -				$this->container_extensions = array(new extension\core($this->get_config_path())); +				$this->container_extensions = [ +					new extension\core($this->get_config_path()), +				];  				if ($this->use_extensions)  				{  					$this->load_extensions();  				} +				// Add tables extension after all extensions +				$this->container_extensions[] = new extension\tables(); +  				// Inject the config  				if ($this->config_php_file)  				{ @@ -481,7 +486,7 @@ class container_builder  			$cached_container_dump = $dumper->dump(array(  				'class'      => 'phpbb_cache_container', -				'base_class' => 'Symfony\\Component\\DependencyInjection\\ContainerBuilder', +				'base_class' => 'Symfony\\Component\\DependencyInjection\\Container',  			));  			$cache->write($cached_container_dump, $this->container->getResources()); diff --git a/phpBB/phpbb/di/extension/container_configuration.php b/phpBB/phpbb/di/extension/container_configuration.php index 4585d6509e..57e7ef6ca6 100644 --- a/phpBB/phpbb/di/extension/container_configuration.php +++ b/phpBB/phpbb/di/extension/container_configuration.php @@ -31,10 +31,15 @@ class container_configuration implements ConfigurationInterface  		$rootNode  			->children()  				->booleanNode('require_dev_dependencies')->defaultValue(false)->end() +				->booleanNode('allow_install_dir')->defaultValue(false)->end()  				->arrayNode('debug')  					->addDefaultsIfNotSet()  					->children()  						->booleanNode('exceptions')->defaultValue(false)->end() +						->booleanNode('load_time')->defaultValue(false)->end() +						->booleanNode('sql_explain')->defaultValue(false)->end() +						->booleanNode('memory')->defaultValue(false)->end() +						->booleanNode('show_errors')->defaultValue(false)->end()  					->end()  				->end()  				->arrayNode('twig') @@ -45,6 +50,12 @@ class container_configuration implements ConfigurationInterface  						->booleanNode('enable_debug_extension')->defaultValue(false)->end()  					->end()  				->end() +				->arrayNode('session') +					->addDefaultsIfNotSet() +					->children() +						->booleanNode('log_errors')->defaultValue(false)->end() +					->end() +				->end()  			->end()  		;  		return $treeBuilder; diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php index 67150f0103..0497c90e2a 100644 --- a/phpBB/phpbb/di/extension/core.php +++ b/phpBB/phpbb/di/extension/core.php @@ -71,6 +71,8 @@ class core extends Extension  			}  		} +		$container->setParameter('allow_install_dir', $config['allow_install_dir']); +  		// Set the Twig options if defined in the environment  		$definition = $container->getDefinition('template.twig.environment');  		$twig_environment_options = $definition->getArgument(static::TWIG_OPTIONS_POSITION); @@ -97,6 +99,12 @@ class core extends Extension  		{  			$container->setParameter('debug.' . $name, $value);  		} + +		// Set the log options +		foreach ($config['session'] as $name => $value) +		{ +			$container->setParameter('session.' . $name, $value); +		}  	}  	/** diff --git a/phpBB/phpbb/di/extension/tables.php b/phpBB/phpbb/di/extension/tables.php new file mode 100644 index 0000000000..40684b6038 --- /dev/null +++ b/phpBB/phpbb/di/extension/tables.php @@ -0,0 +1,59 @@ +<?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\di\extension; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; + +/** + * Container tables extension + */ +class tables extends Extension +{ +	/** +	 * {@inheritDoc} +	 */ +	public function load(array $configs, ContainerBuilder $container) +	{ +		// Tables is a reserved parameter and will be overwritten at all times +		$tables = []; + +		// Add access via 'tables' parameter to acquire array with all tables +		$parameterBag = $container->getParameterBag(); +		$parameters = $parameterBag->all(); +		foreach ($parameters as $parameter_name => $parameter_value) +		{ +			if (!preg_match('/tables\.(.+)/', $parameter_name, $matches)) +			{ +				continue; +			} + +			$tables[$matches[1]] = $parameter_value; +		} + +		$container->setParameter('tables', $tables); +	} + +	/** +	 * Returns the recommended alias to use in XML. +	 * +	 * This alias is also the mandatory prefix to use when using YAML. +	 * +	 * @return string The alias +	 */ +	public function getAlias() +	{ +		return 'tables'; +	} +} diff --git a/phpBB/phpbb/di/service_collection.php b/phpBB/phpbb/di/service_collection.php index 8e9175e204..6298670c42 100644 --- a/phpBB/phpbb/di/service_collection.php +++ b/phpBB/phpbb/di/service_collection.php @@ -49,21 +49,6 @@ class service_collection extends \ArrayObject  		return new service_collection_iterator($this);  	} -	// Because of a PHP issue we have to redefine offsetExists -	// (even with a call to the parent): -	// 		https://bugs.php.net/bug.php?id=66834 -	// 		https://bugs.php.net/bug.php?id=67067 -	// But it triggers a sniffer issue that we have to skip -	// @codingStandardsIgnoreStart -	/** -	* {@inheritdoc} -	*/ -	public function offsetExists($index) -	{ -		return parent::offsetExists($index); -	} -	// @codingStandardsIgnoreEnd -  	/**  	* {@inheritdoc}  	*/ @@ -76,11 +61,11 @@ class service_collection extends \ArrayObject  	* Add a service to the collection  	*  	* @param string $name The service name -	* @return null +	* @return void  	*/  	public function add($name)  	{ -		$this->offsetSet($name, null); +		$this->offsetSet($name, false);  	}  	/** @@ -103,4 +88,35 @@ class service_collection extends \ArrayObject  	{  		return $this->service_classes;  	} + +	/** +	 * Returns the service associated to a class +	 * +	 * @return mixed +	 * @throw \RuntimeException if the +	 */ +	public function get_by_class($class) +	{ +		$service_id = null; + +		foreach ($this->service_classes as $id => $service_class) +		{ +			if ($service_class === $class) +			{ +				if ($service_id !== null) +				{ +					throw new \RuntimeException('More than one service definitions found for class "'.$class.'" in collection.'); +				} + +				$service_id = $id; +			} +		} + +		if ($service_id === null) +		{ +			throw new \RuntimeException('No service found for class "'.$class.'" in collection.'); +		} + +		return $this->offsetGet($service_id); +	}  } diff --git a/phpBB/phpbb/extension/extension_interface.php b/phpBB/phpbb/extension/extension_interface.php index 6a6b6adb8f..46072d420c 100644 --- a/phpBB/phpbb/extension/extension_interface.php +++ b/phpBB/phpbb/extension/extension_interface.php @@ -22,7 +22,8 @@ interface extension_interface  	/**  	* Indicate whether or not the extension can be enabled.  	* -	* @return bool +	* @return bool|array	True if extension is enableable, array of reasons +	*						if not, false for generic reason.  	*/  	public function is_enableable(); diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php index 4b4109bd85..1ce8425fff 100644 --- a/phpBB/phpbb/extension/manager.php +++ b/phpBB/phpbb/extension/manager.php @@ -161,6 +161,47 @@ class manager  	}  	/** +	* Update the database entry for an extension +	* +	* @param string $name Extension name to update +	* @param array	$data Data to update in the database +	* @param string	$action Action to perform, by default 'update', may be also 'insert' or 'delete' +	*/ +	protected function update_state($name, $data, $action = 'update') +	{ +		switch ($action) +		{ +			case 'insert': +				$this->extensions[$name] = $data; +				$this->extensions[$name]['ext_path'] = $this->get_extension_path($name); +				ksort($this->extensions); +				$sql = 'INSERT INTO ' . $this->extension_table . ' ' . $this->db->sql_build_array('INSERT', $data); +				$this->db->sql_query($sql); +			break; + +			case 'update': +				$this->extensions[$name] = array_merge($this->extensions[$name], $data); +				$sql = 'UPDATE ' . $this->extension_table . ' +					SET ' . $this->db->sql_build_array('UPDATE', $data) . " +					WHERE ext_name = '" . $this->db->sql_escape($name) . "'"; +				$this->db->sql_query($sql); +			break; + +			case 'delete': +				unset($this->extensions[$name]); +				$sql = 'DELETE FROM ' . $this->extension_table . " +					WHERE ext_name = '" . $this->db->sql_escape($name) . "'"; +				$this->db->sql_query($sql); +			break; +		} + +		if ($this->cache) +		{ +			$this->cache->purge(); +		} +	} + +	/**  	* Runs a step of the extension enabling process.  	*  	* Allows the exentension to enable in a long running script that works @@ -197,35 +238,7 @@ class manager  			'ext_state'		=> serialize($state),  		); -		$this->extensions[$name] = $extension_data; -		$this->extensions[$name]['ext_path'] = $this->get_extension_path($extension_data['ext_name']); -		ksort($this->extensions); - -		$sql = 'SELECT COUNT(ext_name) as row_count -			FROM ' . $this->extension_table . " -			WHERE ext_name = '" . $this->db->sql_escape($name) . "'"; -		$result = $this->db->sql_query($sql); -		$count = $this->db->sql_fetchfield('row_count'); -		$this->db->sql_freeresult($result); - -		if ($count) -		{ -			$sql = 'UPDATE ' . $this->extension_table . ' -				SET ' . $this->db->sql_build_array('UPDATE', $extension_data) . " -				WHERE ext_name = '" . $this->db->sql_escape($name) . "'"; -			$this->db->sql_query($sql); -		} -		else -		{ -			$sql = 'INSERT INTO ' . $this->extension_table . ' -				' . $this->db->sql_build_array('INSERT', $extension_data); -			$this->db->sql_query($sql); -		} - -		if ($this->cache) -		{ -			$this->cache->purge(); -		} +		$this->update_state($name, $extension_data, $this->is_configured($name) ? 'update' : 'insert');  		if ($active)  		{ @@ -272,46 +285,15 @@ class manager  		$extension = $this->get_extension($name);  		$state = $extension->disable_step($old_state); - -		// continue until the state is false -		if ($state !== false) -		{ -			$extension_data = array( -				'ext_state'		=> serialize($state), -			); -			$this->extensions[$name]['ext_state'] = serialize($state); - -			$sql = 'UPDATE ' . $this->extension_table . ' -				SET ' . $this->db->sql_build_array('UPDATE', $extension_data) . " -				WHERE ext_name = '" . $this->db->sql_escape($name) . "'"; -			$this->db->sql_query($sql); - -			if ($this->cache) -			{ -				$this->cache->purge(); -			} - -			return true; -		} +		$active = ($state !== false);  		$extension_data = array( -			'ext_active'	=> false, -			'ext_state'		=> serialize(false), +			'ext_active'	=> $active, +			'ext_state'		=> serialize($state),  		); -		$this->extensions[$name]['ext_active'] = false; -		$this->extensions[$name]['ext_state'] = serialize(false); +		$this->update_state($name, $extension_data); -		$sql = 'UPDATE ' . $this->extension_table . ' -			SET ' . $this->db->sql_build_array('UPDATE', $extension_data) . " -			WHERE ext_name = '" . $this->db->sql_escape($name) . "'"; -		$this->db->sql_query($sql); - -		if ($this->cache) -		{ -			$this->cache->purge(); -		} - -		return false; +		return $active;  	}  	/** @@ -357,40 +339,16 @@ class manager  		$extension = $this->get_extension($name);  		$state = $extension->purge_step($old_state); +		$purged = ($state === false); -		// continue until the state is false -		if ($state !== false) -		{ -			$extension_data = array( -				'ext_state'		=> serialize($state), -			); -			$this->extensions[$name]['ext_state'] = serialize($state); - -			$sql = 'UPDATE ' . $this->extension_table . ' -				SET ' . $this->db->sql_build_array('UPDATE', $extension_data) . " -				WHERE ext_name = '" . $this->db->sql_escape($name) . "'"; -			$this->db->sql_query($sql); - -			if ($this->cache) -			{ -				$this->cache->purge(); -			} - -			return true; -		} - -		unset($this->extensions[$name]); - -		$sql = 'DELETE FROM ' . $this->extension_table . " -			WHERE ext_name = '" . $this->db->sql_escape($name) . "'"; -		$this->db->sql_query($sql); +		$extension_data = array( +			'ext_state'	=> serialize($state), +		); -		if ($this->cache) -		{ -			$this->cache->purge(); -		} +		$this->update_state($name, $extension_data, $purged ? 'delete' : 'update'); -		return false; +		// continue until the state is false +		return !$purged;  	}  	/** diff --git a/phpBB/phpbb/feed/controller/feed.php b/phpBB/phpbb/feed/controller/feed.php index c0d7bc72ec..7826d19042 100644 --- a/phpBB/phpbb/feed/controller/feed.php +++ b/phpBB/phpbb/feed/controller/feed.php @@ -308,14 +308,13 @@ class feed  			 * Event to modify the feed row  			 *  			 * @event core.feed_modify_feed_row -			 * @var	int		forum_id	Forum ID -			 * @var	string	mode		Feeds mode (forums|topics|topics_new|topics_active|news) +			 * @var	feed_interface feed Feed instance  			 * @var	array	row			Array with feed data -			 * @var	int		topic_id	Topic ID  			 *  			 * @since 3.1.10-RC1 +			 * @changed 3.3.0 Replace forum_id, mode, topic_id with feed instance  			 */ -			$vars = array('forum_id', 'mode', 'row', 'topic_id'); +			$vars = array('feed', 'row');  			extract($this->phpbb_dispatcher->trigger_event('core.feed_modify_feed_row', compact($vars)));  			// BBCode options to correctly disable urls, smilies, bbcode... diff --git a/phpBB/phpbb/feed/topics_active.php b/phpBB/phpbb/feed/topics_active.php index ea9ee97b9d..ee7fe177f5 100644 --- a/phpBB/phpbb/feed/topics_active.php +++ b/phpBB/phpbb/feed/topics_active.php @@ -17,7 +17,7 @@ namespace phpbb\feed;   * Active Topics feed   *   * This will give you the last {$this->num_items} topics - * with replies made withing the last {$this->sort_days} days + * with replies made within the last {$this->sort_days} days   * including the last post.   */  class topics_active extends topic_base diff --git a/phpBB/phpbb/files/filespec.php b/phpBB/phpbb/files/filespec.php index 6847bca4cb..1e6771a3a4 100644 --- a/phpBB/phpbb/files/filespec.php +++ b/phpBB/phpbb/files/filespec.php @@ -420,7 +420,7 @@ class filespec  			return false;  		} -		$upload_mode = ($this->php_ini->getBool('open_basedir') || $this->php_ini->getBool('safe_mode')) ? 'move' : 'copy'; +		$upload_mode = ($this->php_ini->getBool('open_basedir')) ? 'move' : 'copy';  		$upload_mode = ($this->local) ? 'local' : $upload_mode;  		$this->destination_file = $this->destination_path . '/' . utf8_basename($this->realname); diff --git a/phpBB/phpbb/filesystem.php b/phpBB/phpbb/filesystem.php index af56d78845..6ac9459331 100644 --- a/phpBB/phpbb/filesystem.php +++ b/phpBB/phpbb/filesystem.php @@ -14,7 +14,7 @@  namespace phpbb;  /** - * @deprecated	3.2.0-dev	(To be removed 3.3.0) use \phpbb\filesystem\filesystem instead + * @deprecated	3.2.0-dev	(To be removed 4.0.0) use \phpbb\filesystem\filesystem instead   */  class filesystem extends \phpbb\filesystem\filesystem  { diff --git a/phpBB/phpbb/filesystem/filesystem.php b/phpBB/phpbb/filesystem/filesystem.php index c5be284d8c..9acead0876 100644 --- a/phpBB/phpbb/filesystem/filesystem.php +++ b/phpBB/phpbb/filesystem/filesystem.php @@ -67,7 +67,7 @@ class filesystem implements filesystem_interface  			$error = trim($e->getMessage());  			$file = substr($error, strrpos($error, ' ')); -			throw new filesystem_exception('CANNOT_CHANGE_FILE_GROUP', $file, array(), $e); +			throw new filesystem_exception('FILESYSTEM_CANNOT_CHANGE_FILE_GROUP', $file, array(), $e);  		}  	} @@ -124,14 +124,14 @@ class filesystem implements filesystem_interface  			{  				if (true !== @chmod($file, $dir_perm))  				{ -					throw new filesystem_exception('CANNOT_CHANGE_FILE_PERMISSIONS', $file,  array()); +					throw new filesystem_exception('FILESYSTEM_CANNOT_CHANGE_FILE_PERMISSIONS', $file,  array());  				}  			}  			else if (is_file($file))  			{  				if (true !== @chmod($file, $file_perm))  				{ -					throw new filesystem_exception('CANNOT_CHANGE_FILE_PERMISSIONS', $file,  array()); +					throw new filesystem_exception('FILESYSTEM_CANNOT_CHANGE_FILE_PERMISSIONS', $file,  array());  				}  			}  		} @@ -153,7 +153,7 @@ class filesystem implements filesystem_interface  			$error = trim($e->getMessage());  			$file = substr($error, strrpos($error, ' ')); -			throw new filesystem_exception('CANNOT_CHANGE_FILE_GROUP', $file, array(), $e); +			throw new filesystem_exception('FILESYSTEM_CANNOT_CHANGE_FILE_GROUP', $file, array(), $e);  		}  	} @@ -195,7 +195,7 @@ class filesystem implements filesystem_interface  		}  		catch (\Symfony\Component\Filesystem\Exception\IOException $e)  		{ -			throw new filesystem_exception('CANNOT_COPY_FILES', '', array(), $e); +			throw new filesystem_exception('FILESYSTEM_CANNOT_COPY_FILES', '', array(), $e);  		}  	} @@ -210,7 +210,7 @@ class filesystem implements filesystem_interface  		}  		catch (\Symfony\Component\Filesystem\Exception\IOException $e)  		{ -			throw new filesystem_exception('CANNOT_DUMP_FILE', $filename, array(), $e); +			throw new filesystem_exception('FILESYSTEM_CANNOT_DUMP_FILE', $filename, array(), $e);  		}  	} @@ -322,7 +322,7 @@ class filesystem implements filesystem_interface  			$msg = $e->getMessage();  			$filename = substr($msg, strpos($msg, '"'), strrpos($msg, '"')); -			throw new filesystem_exception('CANNOT_MIRROR_DIRECTORY', $filename, array(), $e); +			throw new filesystem_exception('FILESYSTEM_CANNOT_MIRROR_DIRECTORY', $filename, array(), $e);  		}  	} @@ -340,7 +340,7 @@ class filesystem implements filesystem_interface  			$msg = $e->getMessage();  			$filename = substr($msg, strpos($msg, '"'), strrpos($msg, '"')); -			throw new filesystem_exception('CANNOT_CREATE_DIRECTORY', $filename, array(), $e); +			throw new filesystem_exception('FILESYSTEM_CANNOT_CREATE_DIRECTORY', $filename, array(), $e);  		}  	} @@ -525,7 +525,7 @@ class filesystem implements filesystem_interface  			$error = trim($e->getMessage());  			$file = substr($error, strrpos($error, ' ')); -			throw new filesystem_exception('CANNOT_DELETE_FILES', $file, array(), $e); +			throw new filesystem_exception('FILESYSTEM_CANNOT_DELETE_FILES', $file, array(), $e);  		}  	} @@ -543,7 +543,7 @@ class filesystem implements filesystem_interface  			$msg = $e->getMessage();  			$filename = substr($msg, strpos($msg, '"'), strrpos($msg, '"')); -			throw new filesystem_exception('CANNOT_RENAME_FILE', $filename, array(), $e); +			throw new filesystem_exception('FILESYSTEM_CANNOT_RENAME_FILE', $filename, array(), $e);  		}  	} @@ -558,7 +558,7 @@ class filesystem implements filesystem_interface  		}  		catch (\Symfony\Component\Filesystem\Exception\IOException $e)  		{ -			throw new filesystem_exception('CANNOT_CREATE_SYMLINK', $origin_dir, array(), $e); +			throw new filesystem_exception('FILESYSTEM_CANNOT_CREATE_SYMLINK', $origin_dir, array(), $e);  		}  	} @@ -578,7 +578,7 @@ class filesystem implements filesystem_interface  			$error = trim($e->getMessage());  			$file = substr($error, strrpos($error, ' ')); -			throw new filesystem_exception('CANNOT_TOUCH_FILES', $file, array(), $e); +			throw new filesystem_exception('FILESYSTEM_CANNOT_TOUCH_FILES', $file, array(), $e);  		}  	} diff --git a/phpBB/phpbb/filesystem/filesystem_interface.php b/phpBB/phpbb/filesystem/filesystem_interface.php index 1093be2499..39ae0c3954 100644 --- a/phpBB/phpbb/filesystem/filesystem_interface.php +++ b/phpBB/phpbb/filesystem/filesystem_interface.php @@ -204,7 +204,7 @@ interface filesystem_interface  	 * This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions.  	 * The function determines owner and group from common.php file and sets the same to the provided file.  	 * The function uses bit fields to build the permissions. -	 * The function sets the appropiate execute bit on directories. +	 * The function sets the appropriate execute bit on directories.  	 *  	 * Supported constants representing bit fields are:  	 * diff --git a/phpBB/phpbb/finder.php b/phpBB/phpbb/finder.php index 1f1d931880..0a2b67a034 100644 --- a/phpBB/phpbb/finder.php +++ b/phpBB/phpbb/finder.php @@ -80,7 +80,7 @@ class finder  	/**  	* Set the array of extensions  	* -	* @param array $extensions		A list of extensions that should be searched aswell +	* @param array $extensions		A list of extensions that should be searched as well  	* @param bool $replace_list		Should the list be emptied before adding the extensions  	* @return \phpbb\finder This object for chaining calls  	*/ @@ -237,7 +237,7 @@ class finder  	}  	/** -	* Removes occurances of /./ and makes sure path ends without trailing slash +	* Removes occurrences of /./ and makes sure path ends without trailing slash  	*  	* @param string $directory A directory pattern  	* @return string A cleaned up directory pattern diff --git a/phpBB/phpbb/help/controller/bbcode.php b/phpBB/phpbb/help/controller/bbcode.php index e16f99023d..560b0c02ce 100644 --- a/phpBB/phpbb/help/controller/bbcode.php +++ b/phpBB/phpbb/help/controller/bbcode.php @@ -25,6 +25,11 @@ class bbcode extends controller  	{  		$this->language->add_lang('help/bbcode'); +		$this->template->assign_block_vars('navlinks', array( +			'BREADCRUMB_NAME'	=> $this->language->lang('BBCODE_GUIDE'), +			'U_BREADCRUMB'		=> $this->helper->route('phpbb_help_bbcode_controller'), +		)); +  		$this->manager->add_block(  			'HELP_BBCODE_BLOCK_INTRO',  			false, diff --git a/phpBB/phpbb/help/controller/faq.php b/phpBB/phpbb/help/controller/faq.php index 5e45cfe667..0f63be5b56 100644 --- a/phpBB/phpbb/help/controller/faq.php +++ b/phpBB/phpbb/help/controller/faq.php @@ -25,6 +25,11 @@ class faq extends controller  	{  		$this->language->add_lang('help/faq'); +		$this->template->assign_block_vars('navlinks', array( +			'BREADCRUMB_NAME'	=> $this->language->lang('FAQ_EXPLAIN'), +			'U_BREADCRUMB'		=> $this->helper->route('phpbb_help_faq_controller'), +		)); +  		$this->manager->add_block(  			'HELP_FAQ_BLOCK_LOGIN',  			false, diff --git a/phpBB/phpbb/install/controller/helper.php b/phpBB/phpbb/install/controller/helper.php index ff7e691224..f61c7de41f 100644 --- a/phpBB/phpbb/install/controller/helper.php +++ b/phpBB/phpbb/install/controller/helper.php @@ -267,7 +267,7 @@ class helper  			'L_SKIP'				=> $this->language->lang('SKIP'),  			'PAGE_TITLE'			=> $this->language->lang($page_title),  			'T_IMAGE_PATH'			=> $this->path_helper->get_web_root_path() . $path . 'images', -			'T_JQUERY_LINK'			=> $this->path_helper->get_web_root_path() . $path . '../assets/javascript/jquery.min.js', +			'T_JQUERY_LINK'			=> $this->path_helper->get_web_root_path() . $path . '../assets/javascript/jquery-3.4.1.min.js',  			'T_TEMPLATE_PATH'		=> $this->path_helper->get_web_root_path() . $path . 'style',  			'T_ASSETS_PATH'			=> $this->path_helper->get_web_root_path() . $path . '../assets', diff --git a/phpBB/phpbb/install/helper/container_factory.php b/phpBB/phpbb/install/helper/container_factory.php index 9e372fecde..655760270a 100644 --- a/phpBB/phpbb/install/helper/container_factory.php +++ b/phpBB/phpbb/install/helper/container_factory.php @@ -181,7 +181,7 @@ class container_factory  			$this->request->disable_super_globals();  		} -		// Get compatibilty globals and constants +		// Get compatibility globals and constants  		$this->update_helper->include_file('includes/compatibility_globals.' . $this->php_ext);  		register_compatibility_globals(); diff --git a/phpBB/phpbb/install/helper/database.php b/phpBB/phpbb/install/helper/database.php index fa5a10c6fc..51fd18f874 100644 --- a/phpBB/phpbb/install/helper/database.php +++ b/phpBB/phpbb/install/helper/database.php @@ -45,15 +45,6 @@ class database  			'AVAILABLE'		=> true,  			'2.0.x'			=> true,  		), -		'mysql'		=> array( -			'LABEL'			=> 'MySQL', -			'SCHEMA'		=> 'mysql', -			'MODULE'		=> 'mysql', -			'DELIM'			=> ';', -			'DRIVER'		=> 'phpbb\db\driver\mysql', -			'AVAILABLE'		=> true, -			'2.0.x'			=> true, -		),  		'mssql_odbc'=>	array(  			'LABEL'			=> 'MS SQL Server [ ODBC ]',  			'SCHEMA'		=> 'mssql', @@ -256,7 +247,6 @@ class database  		$dbms_info = $this->get_available_dbms($dbms);  		switch ($dbms_info[$dbms]['SCHEMA'])  		{ -			case 'mysql':  			case 'mysql_41':  				$prefix_length = 36;  			break; @@ -382,14 +372,6 @@ class database  			// Check if database version is supported  			switch ($dbms)  			{ -				case 'mysqli': -					if (version_compare($db->sql_server_info(true), '4.1.3', '<')) -					{ -						$errors[] = array( -							'title' => 'INST_ERR_DB_NO_MYSQLI', -						); -					} -				break;  				case 'sqlite3':  					if (version_compare($db->sql_server_info(true), '3.6.15', '<'))  					{ diff --git a/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php b/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php index 440748901c..3df9a91936 100644 --- a/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php +++ b/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php @@ -31,7 +31,7 @@ interface iohandler_interface  	 * @param string	$name		Name of the input variable to obtain  	 * @param mixed		$default	A default value that is returned if the variable was not set.  	 * 								This function will always return a value of the same type as the default. -	 * @param bool		$multibyte	If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters +	 * @param bool		$multibyte	If $default is a string this parameter has to be true if the variable may contain any UTF-8 characters  	 *								Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks  	 *  	 * @return mixed	Value of the input variable diff --git a/phpBB/phpbb/install/installer_configuration.php b/phpBB/phpbb/install/installer_configuration.php index 805140338c..dfafc40b4b 100644 --- a/phpBB/phpbb/install/installer_configuration.php +++ b/phpBB/phpbb/install/installer_configuration.php @@ -48,9 +48,9 @@ class installer_configuration implements ConfigurationInterface  							->cannotBeEmpty()  							->end()  						->scalarNode('description') -						->defaultValue('My amazing new phpBB board') -						->cannotBeEmpty() -						->end() +							->defaultValue('My amazing new phpBB board') +							->cannotBeEmpty() +							->end()  					->end()  				->end()  				->arrayNode('database') @@ -128,12 +128,11 @@ class installer_configuration implements ConfigurationInterface  						->integerNode('server_port')  							->defaultValue(80)  							->min(1) -							->cannotBeEmpty()  							->end()  						->scalarNode('script_path')  							->defaultValue('/')  							->cannotBeEmpty() -							 ->end() +							->end()  					->end()  				->end()  				->arrayNode('extensions') diff --git a/phpBB/phpbb/install/module/install_database/task/add_config_settings.php b/phpBB/phpbb/install/module/install_database/task/add_config_settings.php index ba439609ff..91d7884aa4 100644 --- a/phpBB/phpbb/install/module/install_database/task/add_config_settings.php +++ b/phpBB/phpbb/install/module/install_database/task/add_config_settings.php @@ -245,7 +245,6 @@ class add_config_settings extends \phpbb\install\task_base  					user_lang = '" . $this->db->sql_escape($this->install_config->get('user_language', 'en')) . "',  					user_email='" . $this->db->sql_escape($this->install_config->get('board_email')) . "',  					user_dateformat='" . $this->db->sql_escape($this->language->lang('default_dateformat')) . "', -					user_email_hash = " . $this->db->sql_escape(phpbb_email_hash($this->install_config->get('board_email'))) . ",  					username_clean = '" . $this->db->sql_escape(utf8_clean_string($this->install_config->get('admin_name'))) . "'  				WHERE username = 'Admin'", diff --git a/phpBB/phpbb/install/module/install_database/task/create_schema.php b/phpBB/phpbb/install/module/install_database/task/create_schema.php index a5635d5dbe..983bb42122 100644 --- a/phpBB/phpbb/install/module/install_database/task/create_schema.php +++ b/phpBB/phpbb/install/module/install_database/task/create_schema.php @@ -129,14 +129,7 @@ class create_schema extends \phpbb\install\task_base  		if ($dbms === 'mysql')  		{ -			if (version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) -			{ -				$schema_name .= '_41'; -			} -			else -			{ -				$schema_name .= '_40'; -			} +			$schema_name .= '_41';  		}  		$db_schema_path = $this->phpbb_root_path . 'install/schemas/' . $schema_name . '_schema.sql'; diff --git a/phpBB/phpbb/install/module/install_database/task/set_up_database.php b/phpBB/phpbb/install/module/install_database/task/set_up_database.php index 49c8ea23ad..4da5ece228 100644 --- a/phpBB/phpbb/install/module/install_database/task/set_up_database.php +++ b/phpBB/phpbb/install/module/install_database/task/set_up_database.php @@ -102,14 +102,7 @@ class set_up_database extends \phpbb\install\task_base  		if ($dbms === 'mysql')  		{ -			if (version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) -			{ -				$schema_name .= '_41'; -			} -			else -			{ -				$schema_name .= '_40'; -			} +			$schema_name .= '_41';  		}  		$this->schema_file_path = $this->phpbb_root_path . 'install/schemas/' . $schema_name . '_schema.sql'; diff --git a/phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php b/phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php index 5bc425b929..900d5b94bc 100644 --- a/phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php +++ b/phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php @@ -165,7 +165,7 @@ class create_config_file extends \phpbb\install\task_base  	protected function get_config_data($debug = false, $debug_container = false, $environment = null)  	{  		$config_content = "<?php\n"; -		$config_content .= "// phpBB 3.2.x auto-generated configuration file\n// Do not change anything in this file!\n"; +		$config_content .= "// phpBB 3.3.x auto-generated configuration file\n// Do not change anything in this file!\n";  		$dbms = $this->install_config->get('dbms');  		$db_driver = $this->db_helper->get_available_dbms($dbms); @@ -191,7 +191,6 @@ class create_config_file extends \phpbb\install\task_base  		}  		$config_content .= "\n@define('PHPBB_INSTALLED', true);\n"; -		$config_content .= "// @define('PHPBB_DISPLAY_LOAD_TIME', true);\n";  		if ($environment)  		{ diff --git a/phpBB/phpbb/install/module/requirements/task/check_server_environment.php b/phpBB/phpbb/install/module/requirements/task/check_server_environment.php index 29f9777747..41aa82623b 100644 --- a/phpBB/phpbb/install/module/requirements/task/check_server_environment.php +++ b/phpBB/phpbb/install/module/requirements/task/check_server_environment.php @@ -96,9 +96,7 @@ class check_server_environment extends \phpbb\install\task_base  	 */  	protected function check_php_version()  	{ -		$php_version = PHP_VERSION; - -		if (version_compare($php_version, '5.4') < 0) +		if (version_compare(PHP_VERSION, '7.1.3', '<'))  		{  			$this->response_helper->add_error_message('PHP_VERSION_REQD', 'PHP_VERSION_REQD_EXPLAIN'); diff --git a/phpBB/phpbb/install/module_base.php b/phpBB/phpbb/install/module_base.php index 93c10bd656..4464a89716 100644 --- a/phpBB/phpbb/install/module_base.php +++ b/phpBB/phpbb/install/module_base.php @@ -131,7 +131,7 @@ abstract class module_base implements module_interface  					$name,  				)); -				$this->install_config->increment_current_task_progress($this->task_step_count[$name]); +				$this->install_config->increment_current_task_progress($this->task_step_count[$name] ?? false);  			}  			else  			{ diff --git a/phpBB/phpbb/language/language_file_loader.php b/phpBB/phpbb/language/language_file_loader.php index b6816afd16..2910dd3c4a 100644 --- a/phpBB/phpbb/language/language_file_loader.php +++ b/phpBB/phpbb/language/language_file_loader.php @@ -151,6 +151,7 @@ class language_file_loader  	 *  	 * @param string	$path		Path to language directory  	 * @param string	$filename	Filename to load language strings from +	 * @param array		$locales	Array containing language fallback options  	 *  	 * @return string	Relative path to language file  	 * diff --git a/phpBB/phpbb/lock/db.php b/phpBB/phpbb/lock/db.php index 85ba9a7aa3..eea919f8f7 100644 --- a/phpBB/phpbb/lock/db.php +++ b/phpBB/phpbb/lock/db.php @@ -110,6 +110,13 @@ class db  		// process we failed to acquire the lock.  		$this->locked = $this->config->set_atomic($this->config_name, $lock_value, $this->unique_id, false); +		if ($this->locked == true) +		{ +			if ($this->config->ensure_lock($this->config_name, $this->unique_id)) +			{ +				return true; +			} +		}  		return $this->locked;  	} diff --git a/phpBB/phpbb/lock/flock.php b/phpBB/phpbb/lock/flock.php index df88e1490a..af051afb56 100644 --- a/phpBB/phpbb/lock/flock.php +++ b/phpBB/phpbb/lock/flock.php @@ -101,7 +101,10 @@ class flock  		if ($this->lock_fp)  		{ -			@flock($this->lock_fp, LOCK_EX); +			if (!@flock($this->lock_fp, LOCK_EX)) +			{ +				throw new \phpbb\exception\http_exception(500, 'Failure while aqcuiring locks.'); +			}  		}  		return (bool) $this->lock_fp; diff --git a/phpBB/phpbb/mimetype/guesser.php b/phpBB/phpbb/mimetype/guesser.php index 8baa77089b..f8cbffe8f5 100644 --- a/phpBB/phpbb/mimetype/guesser.php +++ b/phpBB/phpbb/mimetype/guesser.php @@ -76,7 +76,7 @@ class guesser  	* should be used first and vice versa. usort() orders the array values  	* from low to high depending on what the comparison function returns  	* to it. Return value should be smaller than 0 if value a is smaller -	* than value b. This has been reversed in the comparision function in +	* than value b. This has been reversed in the comparison function in  	* order to sort the guessers from high to low.  	* Method has been set to public in order to allow proper testing.  	* diff --git a/phpBB/phpbb/notification/type/approve_post.php b/phpBB/phpbb/notification/type/approve_post.php index e4b111e4da..139b5fabb9 100644 --- a/phpBB/phpbb/notification/type/approve_post.php +++ b/phpBB/phpbb/notification/type/approve_post.php @@ -78,10 +78,7 @@ class approve_post extends \phpbb\notification\type\post  			'ignore_users'		=> array(),  		), $options); -		$users = array(); -		$users[$post['poster_id']] = $this->notification_manager->get_default_methods(); - -		return $this->get_authorised_recipients(array_keys($users), $post['forum_id'], array_merge($options, array( +		return $this->get_authorised_recipients(array($post['poster_id']), $post['forum_id'], array_merge($options, array(  			'item_type'		=> static::$notification_option['id'],  		)));  	} @@ -94,7 +91,7 @@ class approve_post extends \phpbb\notification\type\post  	*  	* @param array $post Post data from submit_post  	* @param array $notify_users Notify users list -	* 		Formated from find_users_for_notification() +	* 		Formatted from find_users_for_notification()  	* @return array Whatever you want to send to create_insert_array().  	*/  	public function pre_create_insert_array($post, $notify_users) diff --git a/phpBB/phpbb/notification/type/approve_topic.php b/phpBB/phpbb/notification/type/approve_topic.php index f8a3fdec6f..0c343646ee 100644 --- a/phpBB/phpbb/notification/type/approve_topic.php +++ b/phpBB/phpbb/notification/type/approve_topic.php @@ -78,10 +78,7 @@ class approve_topic extends \phpbb\notification\type\topic  			'ignore_users'		=> array(),  		), $options); -		$users = array(); -		$users[$post['poster_id']] = $this->notification_manager->get_default_methods(); - -		return $this->get_authorised_recipients(array_keys($users), $post['forum_id'], array_merge($options, array( +		return $this->get_authorised_recipients(array($post['poster_id']), $post['forum_id'], array_merge($options, array(  			'item_type'		=> static::$notification_option['id'],  		)));  	} @@ -94,7 +91,7 @@ class approve_topic extends \phpbb\notification\type\topic  	*  	* @param array $post Post data from submit_post  	* @param array $notify_users Notify users list -	* 		Formated from find_users_for_notification() +	* 		Formatted from find_users_for_notification()  	* @return array Whatever you want to send to create_insert_array().  	*/  	public function pre_create_insert_array($post, $notify_users) diff --git a/phpBB/phpbb/notification/type/base.php b/phpBB/phpbb/notification/type/base.php index 77ed7f2b09..e4600add11 100644 --- a/phpBB/phpbb/notification/type/base.php +++ b/phpBB/phpbb/notification/type/base.php @@ -336,7 +336,7 @@ abstract class base implements \phpbb\notification\type\type_interface  	}  	/** -	* Get the reference of the notifcation (fall back) +	* Get the reference of the notification (fall back)  	*  	* @return string  	*/ @@ -356,7 +356,7 @@ abstract class base implements \phpbb\notification\type\type_interface  	}  	/** -	* Get the reason for the notifcation (fall back) +	* Get the reason for the notification (fall back)  	*  	* @return string  	*/ diff --git a/phpBB/phpbb/notification/type/post.php b/phpBB/phpbb/notification/type/post.php index 254f4c07b3..f0e938d3ce 100644 --- a/phpBB/phpbb/notification/type/post.php +++ b/phpBB/phpbb/notification/type/post.php @@ -352,7 +352,7 @@ class post extends \phpbb\notification\type\base  	*  	* @param array $post Post data from submit_post  	* @param array $notify_users Notify users list -	* 		Formated from find_users_for_notification() +	* 		Formatted from find_users_for_notification()  	* @return array Whatever you want to send to create_insert_array().  	*/  	public function pre_create_insert_array($post, $notify_users) diff --git a/phpBB/phpbb/notification/type/topic.php b/phpBB/phpbb/notification/type/topic.php index 5c42afa8c8..2535cdaed6 100644 --- a/phpBB/phpbb/notification/type/topic.php +++ b/phpBB/phpbb/notification/type/topic.php @@ -256,7 +256,7 @@ class topic extends \phpbb\notification\type\base  	*  	* @param array $post Post data from submit_post  	* @param array $notify_users Notify users list -	* 		Formated from find_users_for_notification() +	* 		Formatted from find_users_for_notification()  	* @return array Whatever you want to send to create_insert_array().  	*/  	public function pre_create_insert_array($post, $notify_users) diff --git a/phpBB/phpbb/notification/type/type_interface.php b/phpBB/phpbb/notification/type/type_interface.php index f9f832bdda..ed77335ce5 100644 --- a/phpBB/phpbb/notification/type/type_interface.php +++ b/phpBB/phpbb/notification/type/type_interface.php @@ -170,7 +170,7 @@ interface type_interface  	*  	* @param array $type_data The type specific data  	* @param array $notify_users Notify users list -	* 		Formated from find_users_for_notification() +	* 		Formatted from find_users_for_notification()  	* @return array Whatever you want to send to create_insert_array().  	*/  	public function pre_create_insert_array($type_data, $notify_users); diff --git a/phpBB/phpbb/passwords/driver/argon2i.php b/phpBB/phpbb/passwords/driver/argon2i.php new file mode 100644 index 0000000000..03368f6361 --- /dev/null +++ b/phpBB/phpbb/passwords/driver/argon2i.php @@ -0,0 +1,78 @@ +<?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\passwords\driver; + +class argon2i extends base_native +{ +	/** @var int Maximum memory (in bytes) that may be used to compute the Argon2 hash */ +	protected $memory_cost; + +	/** @var int Number of threads to use for computing the Argon2 hash */ +	protected $threads; + +	/** @var int Maximum amount of time it may take to compute the Argon2 hash */ +	protected $time_cost; + +	/** +	* Constructor of passwords driver object +	* +	* @param \phpbb\config\config $config phpBB config +	* @param \phpbb\passwords\driver\helper $helper Password driver helper +	* @param int $memory_cost Maximum memory (optional) +	* @param int $threads Number of threads to use (optional) +	* @param int $time_cost Maximum amount of time (optional) +	*/ +	public function __construct(\phpbb\config\config $config, helper $helper, $memory_cost = 1024, $threads = 2, $time_cost = 2) +	{ +		parent::__construct($config, $helper); + +		/** +		 * For Sodium implementation of argon2 algorithm (since PHP 7.4), set special value of 1 for "threads" cost factor +		 * See https://wiki.php.net/rfc/sodium.argon.hash and PHPBB3-16266 +		 * Don't allow cost factors to be below default settings where possible +		 */ +		$this->memory_cost = max($memory_cost, defined('PASSWORD_ARGON2_DEFAULT_MEMORY_COST') ? PASSWORD_ARGON2_DEFAULT_MEMORY_COST : 1024); +		$this->time_cost   = max($time_cost, defined('PASSWORD_ARGON2_DEFAULT_TIME_COST') ? PASSWORD_ARGON2_DEFAULT_TIME_COST : 2); +		$this->threads     = (defined('PASSWORD_ARGON2_PROVIDER') && PASSWORD_ARGON2_PROVIDER == 'sodium') ? +									PASSWORD_ARGON2_DEFAULT_THREADS : max($threads, defined('PASSWORD_ARGON2_DEFAULT_THREADS') ? PASSWORD_ARGON2_DEFAULT_THREADS : 1); +	} + +	/** +	* {@inheritdoc} +	*/ +	public function get_algo_name() +	{ +		return 'PASSWORD_ARGON2I'; +	} + +	/** +	* {@inheritdoc} +	*/ +	public function get_options() +	{ +		return [ +			'memory_cost' => $this->memory_cost, +			'time_cost'   => $this->time_cost, +			'threads'     => $this->threads +		]; +	} + +	/** +	* {@inheritdoc} +	*/ +	public function get_prefix() +	{ +		return '$argon2i$'; +	} +} diff --git a/phpBB/phpbb/db/tools.php b/phpBB/phpbb/passwords/driver/argon2id.php index 4d1b91f7b4..9e4b08bbb9 100644 --- a/phpBB/phpbb/db/tools.php +++ b/phpBB/phpbb/passwords/driver/argon2id.php @@ -11,11 +11,23 @@  *  */ -namespace phpbb\db; +namespace phpbb\passwords\driver; -/** - * @deprecated	3.2.0-dev	(To be removed 3.3.0) use \phpbb\db\tools\tools instead - */ -class tools extends \phpbb\db\tools\tools +class argon2id extends argon2i  { +	/** +	* {@inheritdoc} +	*/ +	public function get_algo_name() +	{ +		return 'PASSWORD_ARGON2ID'; +	} + +	/** +	* {@inheritdoc} +	*/ +	public function get_prefix() +	{ +		return '$argon2id$'; +	}  } diff --git a/phpBB/phpbb/passwords/driver/base_native.php b/phpBB/phpbb/passwords/driver/base_native.php new file mode 100644 index 0000000000..87498327f9 --- /dev/null +++ b/phpBB/phpbb/passwords/driver/base_native.php @@ -0,0 +1,75 @@ +<?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\passwords\driver; + +abstract class base_native extends base +{ +	/** +	* Return the constant name for this driver's algorithm +	* +	* @link https://www.php.net/manual/en/password.constants.php +	* +	* @return string +	*/ +	abstract public function get_algo_name(); + +	/** +	* Return the options set for this driver instance +	* +	* @return array +	*/ +	abstract public function get_options(); + +	/** +	* {@inheritdoc} +	*/ +	public function check($password, $hash, $user_row = []) +	{ +		return password_verify($password, $hash); +	} + +	/** +	* Return the value for this driver's algorithm +	* +	* @return integer +	*/ +	public function get_algo_value() +	{ +		return constant($this->get_algo_name()); +	} + +	/** +	* {@inheritdoc} +	*/ +	public function hash($password) +	{ +		return password_hash($password, $this->get_algo_value(), $this->get_options()); +	} + +	/** +	* {@inheritdoc} +	*/ +	public function is_supported() +	{ +		return defined($this->get_algo_name()) && function_exists('password_hash') && function_exists('password_needs_rehash') && function_exists('password_verify'); +	} + +	/** +	* {@inheritdoc} +	*/ +	public function needs_rehash($hash) +	{ +		return password_needs_rehash($hash, $this->get_algo_value(), $this->get_options()); +	} +} diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index fad76a9fe5..54e6dce4be 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -250,7 +250,7 @@ class manager  	/**  	* Check supplied password against hash and set convert_flag if password -	* needs to be converted to different format (preferrably newer one) +	* needs to be converted to different format (preferably newer one)  	*  	* @param string $password Password that should be checked  	* @param string $hash Stored hash diff --git a/phpBB/phpbb/plupload/plupload.php b/phpBB/phpbb/plupload/plupload.php index 5a5b8a1874..80d7e914db 100644 --- a/phpBB/phpbb/plupload/plupload.php +++ b/phpBB/phpbb/plupload/plupload.php @@ -325,6 +325,8 @@ class plupload  	* by PHP and actually exists, if not, it generates an error  	*  	* @param string $form_name The name of the file in the form data +	* @param int $chunk Chunk number +	* @param string $file_path File path  	*  	* @return null  	*/ diff --git a/phpBB/phpbb/report/report_handler.php b/phpBB/phpbb/report/report_handler.php index 854318c559..97acc1763e 100644 --- a/phpBB/phpbb/report/report_handler.php +++ b/phpBB/phpbb/report/report_handler.php @@ -51,7 +51,7 @@ abstract class report_handler implements report_handler_interface  	protected $report_data;  	/** -	 * Construtor +	 * Constructor  	 *  	 * @param \phpbb\db\driver\driver_interface	$db  	 * @param \phpbb\event\dispatcher_interface	$dispatcher diff --git a/phpBB/phpbb/request/request.php b/phpBB/phpbb/request/request.php index a0267d1370..4d7bc9ea48 100644 --- a/phpBB/phpbb/request/request.php +++ b/phpBB/phpbb/request/request.php @@ -179,7 +179,7 @@ class request implements \phpbb\request\request_interface  	* 										then specifying array("var", 1) as the name will return "a".  	* @param	mixed			$default	A default value that is returned if the variable was not set.  	* 										This function will always return a value of the same type as the default. -	* @param	bool			$multibyte	If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters +	* @param	bool			$multibyte	If $default is a string this parameter has to be true if the variable may contain any UTF-8 characters  	*										Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks  	* @param	\phpbb\request\request_interface::POST|GET|REQUEST|COOKIE	$super_global  	* 										Specifies which super global should be used @@ -203,7 +203,7 @@ class request implements \phpbb\request\request_interface  	* 										then specifying array("var", 1) as the name will return "a".  	* @param	mixed			$default	A default value that is returned if the variable was not set.  	* 										This function will always return a value of the same type as the default. -	* @param	bool			$multibyte	If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters +	* @param	bool			$multibyte	If $default is a string this parameter has to be true if the variable may contain any UTF-8 characters  	*										Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks  	* @param	\phpbb\request\request_interface::POST|GET|REQUEST|COOKIE	$super_global  	* 										Specifies which super global should be used @@ -268,7 +268,7 @@ class request implements \phpbb\request\request_interface  	* whatever).  	*  	* @param	string|array	$var_name		See \phpbb\request\request_interface::variable -	* @param	mixed			$Default		See \phpbb\request\request_interface::variable +	* @param	mixed			$default		See \phpbb\request\request_interface::variable  	*  	* @return	mixed	The server variable value.  	*/ @@ -395,7 +395,7 @@ class request implements \phpbb\request\request_interface  	* 										then specifying array("var", 1) as the name will return "a".  	* @param	mixed			$default	A default value that is returned if the variable was not set.  	* 										This function will always return a value of the same type as the default. -	* @param	bool			$multibyte	If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters +	* @param	bool			$multibyte	If $default is a string this parameter has to be true if the variable may contain any UTF-8 characters  	*										Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks  	* @param	\phpbb\request\request_interface::POST|GET|REQUEST|COOKIE	$super_global  	* 										Specifies which super global should be used diff --git a/phpBB/phpbb/request/request_interface.php b/phpBB/phpbb/request/request_interface.php index 3bfa8bb424..a1fbf0ae45 100644 --- a/phpBB/phpbb/request/request_interface.php +++ b/phpBB/phpbb/request/request_interface.php @@ -54,7 +54,7 @@ interface request_interface  	* 										then specifying array("var", 1) as the name will return "a".  	* @param	mixed			$default	A default value that is returned if the variable was not set.  	* 										This function will always return a value of the same type as the default. -	* @param	bool			$multibyte	If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters +	* @param	bool			$multibyte	If $default is a string this parameter has to be true if the variable may contain any UTF-8 characters  	*										Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks  	* @param	\phpbb\request\request_interface::POST|GET|REQUEST|COOKIE	$super_global  	* 										Specifies which super global should be used @@ -104,7 +104,7 @@ interface request_interface  	*  	* @return	mixed	The header value.  	*/ -	public function header($var_name, $default = ''); +	public function header($header_name, $default = '');  	/**  	* Checks whether a certain variable was sent via POST. diff --git a/phpBB/phpbb/request/type_cast_helper.php b/phpBB/phpbb/request/type_cast_helper.php index 912494998d..39d5908fd3 100644 --- a/phpBB/phpbb/request/type_cast_helper.php +++ b/phpBB/phpbb/request/type_cast_helper.php @@ -106,7 +106,8 @@ class type_cast_helper implements \phpbb\request\type_cast_helper_interface  				return;  			} -			list($default_key, $default_value) = each($default); +			$default_key = key($default); +			$default_value = current($default);  			$key_type = gettype($default_key);  			$_var = $var; diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php index 1105d0892f..42ac6eaba2 100644 --- a/phpBB/phpbb/search/fulltext_mysql.php +++ b/phpBB/phpbb/search/fulltext_mysql.php @@ -83,7 +83,7 @@ class fulltext_mysql extends \phpbb\search\base  	 * @param string $phpEx PHP file extension  	 * @param \phpbb\auth\auth $auth Auth object  	 * @param \phpbb\config\config $config Config object -	 * @param \phpbb\db\driver\driver_interface Database object +	 * @param \phpbb\db\driver\driver_interface $db Database object  	 * @param \phpbb\user $user User object  	 * @param \phpbb\event\dispatcher_interface	$phpbb_dispatcher	Event dispatcher object  	 */ @@ -150,11 +150,11 @@ class fulltext_mysql extends \phpbb\search\base  	/**  	* Checks for correct MySQL version and stores min/max word length in the config  	* -	* @return string|bool Language key of the error/incompatiblity occurred +	* @return string|bool Language key of the error/incompatibility occurred  	*/  	public function init()  	{ -		if ($this->db->get_sql_layer() != 'mysql4' && $this->db->get_sql_layer() != 'mysqli') +		if ($this->db->get_sql_layer() != 'mysqli')  		{  			return $this->user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_DATABASE'];  		} @@ -1005,14 +1005,7 @@ class fulltext_mysql extends \phpbb\search\base  		if (!isset($this->stats['post_subject']))  		{  			$alter_entry = array(); -			if ($this->db->get_sql_layer() == 'mysqli' || version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) -			{ -				$alter_entry[] = 'MODIFY post_subject varchar(255) COLLATE utf8_unicode_ci DEFAULT \'\' NOT NULL'; -			} -			else -			{ -				$alter_entry[] = 'MODIFY post_subject text NOT NULL'; -			} +			$alter_entry[] = 'MODIFY post_subject varchar(255) COLLATE utf8_unicode_ci DEFAULT \'\' NOT NULL';  			$alter_entry[] = 'ADD FULLTEXT (post_subject)';  			$alter_list[] = $alter_entry;  		} @@ -1020,15 +1013,7 @@ class fulltext_mysql extends \phpbb\search\base  		if (!isset($this->stats['post_content']))  		{  			$alter_entry = array(); -			if ($this->db->get_sql_layer() == 'mysqli' || version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) -			{ -				$alter_entry[] = 'MODIFY post_text mediumtext COLLATE utf8_unicode_ci NOT NULL'; -			} -			else -			{ -				$alter_entry[] = 'MODIFY post_text mediumtext NOT NULL'; -			} - +			$alter_entry[] = 'MODIFY post_text mediumtext COLLATE utf8_unicode_ci NOT NULL';  			$alter_entry[] = 'ADD FULLTEXT post_content (post_text, post_subject)';  			$alter_list[] = $alter_entry;  		} diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php index c83de75eed..23460d3381 100644 --- a/phpBB/phpbb/search/fulltext_native.php +++ b/phpBB/phpbb/search/fulltext_native.php @@ -109,6 +109,12 @@ class fulltext_native extends \phpbb\search\base  	* Initialises the fulltext_native search backend with min/max word length  	*  	* @param	boolean|string	&$error	is passed by reference and should either be set to false on success or an error message on failure +	* @param	string	$phpbb_root_path	phpBB root path +	* @param	string	$phpEx	PHP file extension +	* @param	\phpbb\auth\auth	$auth	Auth object +	* @param	\phpbb\config\config	$config	Config object +	* @param	\phpbb\db\driver\driver_interface	$db	Database object +	* @param	\phpbb\user	$user	User object  	* @param	\phpbb\event\dispatcher_interface	$phpbb_dispatcher	Event dispatcher object  	*/  	public function __construct(&$error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher) @@ -351,7 +357,7 @@ class fulltext_native extends \phpbb\search\base  			$this->db->sql_freeresult($result);  		} -		// Handle +, - without preceeding whitespace character +		// Handle +, - without preceding whitespace character  		$match		= array('#(\S)\+#', '#(\S)-#');  		$replace	= array('$1 +', '$1 +'); @@ -782,6 +788,8 @@ class fulltext_native extends \phpbb\search\base  		$must_not_contain_ids = $this->must_not_contain_ids;  		$must_contain_ids = $this->must_contain_ids; +		$sql_sort_table = $sql_sort_join = $sql_match = $sql_match_where = $sql_sort = ''; +  		/**  		* Allow changing the query used for counting for posts using fulltext_native  		* @@ -889,7 +897,6 @@ class fulltext_native extends \phpbb\search\base  			switch ($this->db->get_sql_layer())  			{ -				case 'mysql4':  				case 'mysqli':  					// 3.x does not support SQL_CALC_FOUND_ROWS @@ -1184,7 +1191,6 @@ class fulltext_native extends \phpbb\search\base  		{  			switch ($this->db->get_sql_layer())  			{ -				case 'mysql4':  				case 'mysqli':  //					$select = 'SQL_CALC_FOUND_ROWS ' . $select;  					$is_mysql = true; diff --git a/phpBB/phpbb/search/fulltext_postgres.php b/phpBB/phpbb/search/fulltext_postgres.php index 2f387e791e..6241f21fcf 100644 --- a/phpBB/phpbb/search/fulltext_postgres.php +++ b/phpBB/phpbb/search/fulltext_postgres.php @@ -173,7 +173,7 @@ class fulltext_postgres extends \phpbb\search\base  	/**  	* Checks for correct PostgreSQL version and stores min/max word length in the config  	* -	* @return string|bool Language key of the error/incompatiblity occurred +	* @return string|bool Language key of the error/incompatibility occurred  	*/  	public function init()  	{ diff --git a/phpBB/phpbb/search/fulltext_sphinx.php b/phpBB/phpbb/search/fulltext_sphinx.php index 227fbd3fd6..d2e12fd7c0 100644 --- a/phpBB/phpbb/search/fulltext_sphinx.php +++ b/phpBB/phpbb/search/fulltext_sphinx.php @@ -18,7 +18,7 @@ define('SPHINX_CONNECT_RETRIES', 3);  define('SPHINX_CONNECT_WAIT_TIME', 300);  /** -* Fulltext search based on the sphinx search deamon +* Fulltext search based on the sphinx search daemon  */  class fulltext_sphinx  { @@ -210,11 +210,11 @@ class fulltext_sphinx  	/**  	* Checks permissions and paths, if everything is correct it generates the config file  	* -	* @return string|bool Language key of the error/incompatiblity encountered, or false if successful +	* @return string|bool Language key of the error/incompatibility encountered, or false if successful  	*/  	public function init()  	{ -		if ($this->db->get_sql_layer() != 'mysql' && $this->db->get_sql_layer() != 'mysql4' && $this->db->get_sql_layer() != 'mysqli' && $this->db->get_sql_layer() != 'postgres') +		if ($this->db->get_sql_layer() != 'mysqli' && $this->db->get_sql_layer() != 'postgres')  		{  			return $this->user->lang['FULLTEXT_SPHINX_WRONG_DATABASE'];  		} @@ -233,7 +233,7 @@ class fulltext_sphinx  	protected function config_generate()  	{  		// Check if Database is supported by Sphinx -		if ($this->db->get_sql_layer() =='mysql' || $this->db->get_sql_layer() == 'mysql4' || $this->db->get_sql_layer() == 'mysqli') +		if ($this->db->get_sql_layer() == 'mysqli')  		{  			$this->dbtype = 'mysql';  		} diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index cc5a1b8f8f..6851bc8188 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -250,8 +250,7 @@ class session  			$ips = explode(' ', $this->forwarded_for);  			foreach ($ips as $ip)  			{ -				// check IPv4 first, the IPv6 is hopefully only going to be used very seldomly -				if (!empty($ip) && !preg_match(get_preg_expression('ipv4'), $ip) && !preg_match(get_preg_expression('ipv6'), $ip)) +				if (!filter_var($ip, FILTER_VALIDATE_IP))  				{  					// contains invalid data, don't use the forwarded for header  					$this->forwarded_for = ''; @@ -311,49 +310,17 @@ class session  		foreach ($ips as $ip)  		{ -			if (function_exists('phpbb_ip_normalise')) -			{ -				// Normalise IP address -				$ip = phpbb_ip_normalise($ip); - -				if (empty($ip)) -				{ -					// IP address is invalid. -					break; -				} - -				// IP address is valid. -				$this->ip = $ip; - -				// Skip legacy code. -				continue; -			} - -			if (preg_match(get_preg_expression('ipv4'), $ip)) -			{ -				$this->ip = $ip; -			} -			else if (preg_match(get_preg_expression('ipv6'), $ip)) -			{ -				// Quick check for IPv4-mapped address in IPv6 -				if (stripos($ip, '::ffff:') === 0) -				{ -					$ipv4 = substr($ip, 7); +			// Normalise IP address +			$ip = phpbb_ip_normalise($ip); -					if (preg_match(get_preg_expression('ipv4'), $ipv4)) -					{ -						$ip = $ipv4; -					} -				} - -				$this->ip = $ip; -			} -			else +			if ($ip === false)  			{ -				// We want to use the last valid address in the chain -				// Leave foreach loop when address is invalid +				// IP address is invalid.  				break;  			} + +			// IP address is valid. +			$this->ip = $ip;  		}  		$this->load = false; @@ -478,8 +445,8 @@ class session  				}  				else  				{ -					// Added logging temporarly to help debug bugs... -					if (defined('DEBUG') && $this->data['user_id'] != ANONYMOUS) +					// Added logging temporarily to help debug bugs... +					if ($phpbb_container->getParameter('session.log_errors') && $this->data['user_id'] != ANONYMOUS)  					{  						if ($referer_valid)  						{ @@ -987,72 +954,96 @@ class session  	{  		global $db, $config, $phpbb_container, $phpbb_dispatcher; -		$batch_size = 10; -  		if (!$this->time_now)  		{  			$this->time_now = time();  		} -		// Firstly, delete guest sessions -		$sql = 'DELETE FROM ' . SESSIONS_TABLE . ' -			WHERE session_user_id = ' . ANONYMOUS . ' -				AND session_time < ' . (int) ($this->time_now - $config['session_length']); -		$db->sql_query($sql); +		/** +		 * Get expired sessions for registered users, only most recent for each user +		 * Inner SELECT gets most recent expired sessions for unique session_user_id +		 * Outer SELECT gets data for them +		 */ +		$sql_select = 'SELECT s1.session_page, s1.session_user_id, s1.session_time AS recent_time +			FROM ' . SESSIONS_TABLE . ' AS s1 +			INNER JOIN ( +				SELECT session_user_id, MAX(session_time) AS recent_time +				FROM ' . SESSIONS_TABLE . ' +				WHERE session_time < ' . ($this->time_now - (int) $config['session_length']) . ' +					AND session_user_id <> ' . ANONYMOUS . ' +				GROUP BY session_user_id +			) AS s2 +			ON s1.session_user_id = s2.session_user_id +				AND s1.session_time = s2.recent_time'; + +		switch ($db->get_sql_layer()) +		{ +			case 'sqlite3': +				if (phpbb_version_compare($db->sql_server_info(true), '3.8.3', '>=')) +				{ +					// For SQLite versions 3.8.3+ which support Common Table Expressions (CTE) +					$sql = "WITH s3 (session_page, session_user_id, session_time) AS ($sql_select) +						UPDATE " . USERS_TABLE . ' +						SET (user_lastpage, user_lastvisit) = (SELECT session_page, session_time FROM s3 WHERE session_user_id = user_id) +						WHERE EXISTS (SELECT session_user_id FROM s3 WHERE session_user_id = user_id)'; +					$db->sql_query($sql); -		// Get expired sessions, only most recent for each user -		$sql = 'SELECT session_user_id, session_page, MAX(session_time) AS recent_time -			FROM ' . SESSIONS_TABLE . ' -			WHERE session_time < ' . ($this->time_now - $config['session_length']) . ' -			GROUP BY session_user_id, session_page'; -		$result = $db->sql_query_limit($sql, $batch_size); +					break; +				} -		$del_user_id = array(); -		$del_sessions = 0; +			// No break, for SQLite versions prior to 3.8.3 and Oracle +			case 'oracle': +				$result = $db->sql_query($sql_select); +				while ($row = $db->sql_fetchrow($result)) +				{ +					$sql = 'UPDATE ' . USERS_TABLE . ' +						SET user_lastvisit = ' . (int) $row['recent_time'] . ", user_lastpage = '" . $db->sql_escape($row['session_page']) . "' +						WHERE user_id = " . (int) $row['session_user_id']; +					$db->sql_query($sql); +				} +				$db->sql_freeresult($result); +			break; -		while ($row = $db->sql_fetchrow($result)) -		{ -			$sql = 'UPDATE ' . USERS_TABLE . ' -				SET user_lastvisit = ' . (int) $row['recent_time'] . ", user_lastpage = '" . $db->sql_escape($row['session_page']) . "' -				WHERE user_id = " . (int) $row['session_user_id']; -			$db->sql_query($sql); +			case 'mysqli': +				$sql = 'UPDATE ' . USERS_TABLE . " u, +					($sql_select) s3 +					SET u.user_lastvisit = s3.recent_time, u.user_lastpage = s3.session_page +					WHERE u.user_id = s3.session_user_id"; +				$db->sql_query($sql); +			break; -			$del_user_id[] = (int) $row['session_user_id']; -			$del_sessions++; +			default: +				$sql = 'UPDATE ' . USERS_TABLE . " +					SET user_lastvisit = s3.recent_time, user_lastpage = s3.session_page +					FROM ($sql_select) s3 +					WHERE user_id = s3.session_user_id"; +				$db->sql_query($sql); +			break;  		} -		$db->sql_freeresult($result); -		if (count($del_user_id)) +		// Delete all expired sessions +		$sql = 'DELETE FROM ' . SESSIONS_TABLE . ' +			WHERE session_time < ' . ($this->time_now - (int) $config['session_length']); +		$db->sql_query($sql); + +		// Update gc timer +		$config->set('session_last_gc', $this->time_now, false); + +		if ($config['max_autologin_time'])  		{ -			// Delete expired sessions -			$sql = 'DELETE FROM ' . SESSIONS_TABLE . ' -				WHERE ' . $db->sql_in_set('session_user_id', $del_user_id) . ' -					AND session_time < ' . ($this->time_now - $config['session_length']); +			$sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' +				WHERE last_login < ' . (time() - (86400 * (int) $config['max_autologin_time']));  			$db->sql_query($sql);  		} -		if ($del_sessions < $batch_size) -		{ -			// Less than 10 users, update gc timer ... else we want gc -			// called again to delete other sessions -			$config->set('session_last_gc', $this->time_now, false); - -			if ($config['max_autologin_time']) -			{ -				$sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' -					WHERE last_login < ' . (time() - (86400 * (int) $config['max_autologin_time'])); -				$db->sql_query($sql); -			} - -			// only called from CRON; should be a safe workaround until the infrastructure gets going -			/* @var $captcha_factory \phpbb\captcha\factory */ -			$captcha_factory = $phpbb_container->get('captcha.factory'); -			$captcha_factory->garbage_collect($config['captcha_plugin']); +		// only called from CRON; should be a safe workaround until the infrastructure gets going +		/* @var \phpbb\captcha\factory $captcha_factory */ +		$captcha_factory = $phpbb_container->get('captcha.factory'); +		$captcha_factory->garbage_collect($config['captcha_plugin']); -			$sql = 'DELETE FROM ' . LOGIN_ATTEMPT_TABLE . ' -				WHERE attempt_time < ' . (time() - (int) $config['ip_login_limit_time']); -			$db->sql_query($sql); -		} +		$sql = 'DELETE FROM ' . LOGIN_ATTEMPT_TABLE . ' +			WHERE attempt_time < ' . (time() - (int) $config['ip_login_limit_time']); +		$db->sql_query($sql);  		/**  		* Event to trigger extension on session_gc @@ -1362,7 +1353,7 @@ class session  	* Only IPv4 (rbldns does not support AAAA records/IPv6 lookups)  	*  	* @author satmd (from the php manual) -	* @param string 		$mode	register/post - spamcop for example is ommitted for posting +	* @param string 		$mode	register/post - spamcop for example is omitted for posting  	* @param string|false	$ip		the IPv4 address to check  	*  	* @return false if ip is not blacklisted, else an array([checked server], [lookup]) @@ -1400,7 +1391,7 @@ class session  			foreach ($dnsbl_check as $dnsbl => $lookup)  			{ -				if (phpbb_checkdnsrr($reverse_ip . '.' . $dnsbl . '.', 'A') === true) +				if (checkdnsrr($reverse_ip . '.' . $dnsbl . '.', 'A') === true)  				{  					$info = array($dnsbl, $lookup . $ip);  				} @@ -1421,7 +1412,7 @@ class session  	/**  	* Check if URI is blacklisted -	* This should be called only where absolutly necessary, for example on the submitted website field +	* This should be called only where absolutely necessary, for example on the submitted website field  	* This function is not in use at the moment and is only included for testing purposes, it may not work at all!  	* This means it is untested at the moment and therefore commented out  	* @@ -1444,7 +1435,7 @@ class session  		{  			// One problem here... the return parameter for the "windows" method is different from what  			// we expect... this may render this check useless... -			if (phpbb_checkdnsrr($uri . '.multi.uribl.com.', 'A') === true) +			if (checkdnsrr($uri . '.multi.uribl.com.', 'A') === true)  			{  				return true;  			} diff --git a/phpBB/phpbb/template/asset.php b/phpBB/phpbb/template/asset.php index cb00f16549..d6b46234f0 100644 --- a/phpBB/phpbb/template/asset.php +++ b/phpBB/phpbb/template/asset.php @@ -45,13 +45,6 @@ class asset  	*/  	public function set_url($url)  	{ -		if (version_compare(PHP_VERSION, '5.4.7') < 0 && substr($url, 0, 2) === '//') -		{ -			// Workaround for PHP 5.4.6 and older bug #62844 - add fake scheme and then remove it -			$this->components = parse_url('http:' . $url); -			$this->components['scheme'] = ''; -			return; -		}  		$this->components = parse_url($url);  	} diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 202e29ce00..f059c327c1 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -87,7 +87,7 @@ class context  	}  	/** -	* Retreive a single scalar value from a single key. +	* Retrieve a single scalar value from a single key.  	*  	* @param string $varname Variable name  	* @return mixed Variable value, or null if not set @@ -149,7 +149,7 @@ class context  			{  				// If the key name is lowercase and the data is an array,  				// it could be a template loop. So we set the S_NUM_ROWS there -				// aswell. +				// as well.  				if ($sub_block_name === strtolower($sub_block_name) && is_array($sub_block))  				{  					$this->set_num_rows($sub_block); diff --git a/phpBB/phpbb/template/template.php b/phpBB/phpbb/template/template.php index df83d5bc43..6634c28d02 100644 --- a/phpBB/phpbb/template/template.php +++ b/phpBB/phpbb/template/template.php @@ -136,7 +136,7 @@ interface template  	public function retrieve_vars(array $vararray);  	/** -	* Retreive a single scalar value from a single key. +	* Retrieve a single scalar value from a single key.  	*  	* @param string $varname Variable name  	* @return mixed Variable value, or null if not set diff --git a/phpBB/phpbb/template/twig/extension.php b/phpBB/phpbb/template/twig/extension.php index f6f8e03ca2..1131a7f3aa 100644 --- a/phpBB/phpbb/template/twig/extension.php +++ b/phpBB/phpbb/template/twig/extension.php @@ -18,6 +18,9 @@ class extension extends \Twig_Extension  	/** @var \phpbb\template\context */  	protected $context; +	/** @var \phpbb\template\twig\environment */ +	protected $environment; +  	/** @var \phpbb\language\language */  	protected $language; @@ -25,12 +28,13 @@ class extension extends \Twig_Extension  	* Constructor  	*  	* @param \phpbb\template\context $context +	* @param \phpbb\template\twig\environment $environment  	* @param \phpbb\language\language $language -	* @return \phpbb\template\twig\extension  	*/ -	public function __construct(\phpbb\template\context $context, $language) +	public function __construct(\phpbb\template\context $context, \phpbb\template\twig\environment $environment, $language)  	{  		$this->context = $context; +		$this->environment = $environment;  		$this->language = $language;  	} @@ -56,9 +60,9 @@ class extension extends \Twig_Extension  			new \phpbb\template\twig\tokenparser\includeparser,  			new \phpbb\template\twig\tokenparser\includejs,  			new \phpbb\template\twig\tokenparser\includecss, -			new \phpbb\template\twig\tokenparser\event, -			new \phpbb\template\twig\tokenparser\includephp, -			new \phpbb\template\twig\tokenparser\php, +			new \phpbb\template\twig\tokenparser\event($this->environment), +			new \phpbb\template\twig\tokenparser\includephp($this->environment), +			new \phpbb\template\twig\tokenparser\php($this->environment),  		);  	} @@ -85,6 +89,8 @@ class extension extends \Twig_Extension  	{  		return array(  			new \Twig_SimpleFunction('lang', array($this, 'lang')), +			new \Twig_SimpleFunction('lang_defined', array($this, 'lang_defined')), +			new \Twig_SimpleFunction('get_class', 'get_class'),  		);  	} @@ -136,7 +142,7 @@ class extension extends \Twig_Extension  	*  	* @return mixed The sliced variable  	*/ -	function loop_subset(\Twig_Environment $env, $item, $start, $end = null, $preserveKeys = false) +	public function loop_subset(\Twig_Environment $env, $item, $start, $end = null, $preserveKeys = false)  	{  		// We do almost the same thing as Twig's slice (array_slice), except when $end is positive  		if ($end >= 1) @@ -165,7 +171,7 @@ class extension extends \Twig_Extension  	*  	* @return string  	*/ -	function lang() +	public function lang()  	{  		$args = func_get_args();  		$key = $args[0]; @@ -182,4 +188,14 @@ class extension extends \Twig_Extension  		return call_user_func_array(array($this->language, 'lang'), $args);  	} + +	/** +	 * Check if a language variable exists +	 * +	 * @return bool +	 */ +	public function lang_defined($key) +	{ +		return call_user_func_array([$this->language, 'is_set'], [$key]); +	}  } diff --git a/phpBB/phpbb/template/twig/extension/avatar.php b/phpBB/phpbb/template/twig/extension/avatar.php new file mode 100644 index 0000000000..7a17fd4b42 --- /dev/null +++ b/phpBB/phpbb/template/twig/extension/avatar.php @@ -0,0 +1,80 @@ +<?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\template\twig\extension; + +class avatar extends \Twig_Extension +{ +	/** +	 * Get the name of this extension +	 * +	 * @return string +	 */ +	public function getName() +	{ +		return 'avatar'; +	} + +	/** +	 * Returns a list of global functions to add to the existing list. +	 * +	 * @return array An array of global functions +	 */ +	public function getFunctions() +	{ +		return array( +			new \Twig_SimpleFunction('avatar', array($this, 'get_avatar')), +		); +	} + +	/** +	 * Get avatar for placing into templates. +	 * +	 * How to use in a template: +	 * - {{ avatar('mode', row, alt, ignore_config, lazy) }} +	 * +	 * The mode and row (group_row or user_row) are required. +	 * The other fields (alt|ignore_config|lazy) are optional. +	 * +	 * @uses \phpbb_get_group_avatar() +	 * @uses \phpbb_get_user_avatar() +	 * +	 * @return string	The avatar HTML for the specified mode +	 */ +	public function get_avatar() +	{ +		$args = func_get_args(); + +		$mode = (string) $args[0]; +		$row = (array) $args[1]; +		$alt = isset($args[2]) ? (string) $args[2] : false; +		$ignore_config = isset($args[3]) ? (bool) $args[3] : false; +		$lazy = isset($args[4]) ? (bool) $args[4] : false; + +		// To prevent having to redefine alt attribute ('USER_AVATAR'|'GROUP_AVATAR'), we check if an alternative has been provided +		switch ($mode) +		{ +			case 'group': +				return $alt ? phpbb_get_group_avatar($row, $alt, $ignore_config, $lazy) : phpbb_get_group_avatar($row); +			break; + +			case 'user': +				return $alt ? phpbb_get_user_avatar($row, $alt, $ignore_config, $lazy) : phpbb_get_user_avatar($row); +			break; + +			default: +				return ''; +			break; +		} +	} +} diff --git a/phpBB/phpbb/template/twig/extension/config.php b/phpBB/phpbb/template/twig/extension/config.php new file mode 100644 index 0000000000..cbf6e505c5 --- /dev/null +++ b/phpBB/phpbb/template/twig/extension/config.php @@ -0,0 +1,64 @@ +<?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\template\twig\extension; + +class config extends \Twig_Extension +{ +	/** @var \phpbb\config\config */ +	protected $config; + +	/** +	 * Constructor. +	 * +	 * @param \phpbb\config\config	$config		Configuration object +	 */ +	public function __construct(\phpbb\config\config $config) +	{ +		$this->config = $config; +	} + +	/** +	 * Get the name of this extension +	 * +	 * @return string +	 */ +	public function getName() +	{ +		return 'config'; +	} + +	/** +	 * Returns a list of global functions to add to the existing list. +	 * +	 * @return array An array of global functions +	 */ +	public function getFunctions() +	{ +		return array( +			new \Twig_SimpleFunction('config', array($this, 'get_config')), +		); +	} + +	/** +	 * Retrieves a configuration value for use in templates. +	 * +	 * @return string	The configuration value +	 */ +	public function get_config() +	{ +		$args = func_get_args(); + +		return $this->config->offsetGet($args[0]); +	} +} diff --git a/phpBB/phpbb/template/twig/extension/username.php b/phpBB/phpbb/template/twig/extension/username.php new file mode 100644 index 0000000000..ef149693a0 --- /dev/null +++ b/phpBB/phpbb/template/twig/extension/username.php @@ -0,0 +1,84 @@ +<?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\template\twig\extension; + +class username extends \Twig_Extension +{ +	/** +	 * Get the name of this extension +	 * +	 * @return string +	 */ +	public function getName() +	{ +		return 'username'; +	} + +	/** +	 * Returns a list of global functions to add to the existing list. +	 * +	 * @return array An array of global functions +	 */ +	public function getFunctions() +	{ +		return array( +			new \Twig_SimpleFunction('username', array($this, 'get_username')), +		); +	} + +	/** +	 * Get username details for placing into templates. +	 * +	 * How to use in a template: +	 * - {{ username('mode', user_id, username, user_colour, guest_username, custom_profile_url) }} +	 * - {{ username('mode', user_row, guest_username, custom_profile_url) }} +	 * It's possible to provide the user identifier, name and colour separately, +	 * or provide the entire user row at once as an array. +	 * +	 * The mode, user_id and username are required (separately or through a user row). +	 * The other fields (user_colour|guest_username|custom_profile_url) are optional. +	 * +	 * @uses \get_username_string() +	 * +	 * @return string		A string based on what is wanted depending on $mode +	 */ +	public function get_username() +	{ +		$args = func_get_args(); + +		$mode = $args[0]; +		$user = $args[1]; + +		// If the entire user row is provided +		if (is_array($user)) +		{ +			$user_id = isset($user['user_id']) ? $user['user_id'] : ''; +			$username = isset($user['username']) ? $user['username'] : ''; +			$user_colour = isset($user['user_colour']) ? $user['user_colour'] : ''; +			$guest_username = isset($args[2]) ? $args[2] : false; +			$custom_profile_url = isset($args[3]) ? $args[3] : false; +		} +		else +		{ +			// Options are provided separately +			$user_id = $user; +			$username = $args[2]; +			$user_colour = isset($args[3]) ? $args[3] : ''; +			$guest_username = isset($args[4]) ? $args[4] : false; +			$custom_profile_url = isset($args[5]) ? $args[5] : false; +		} + +		return get_username_string($mode, $user_id, $username, $user_colour, $guest_username, $custom_profile_url); +	} +} diff --git a/phpBB/phpbb/template/twig/lexer.php b/phpBB/phpbb/template/twig/lexer.php index d0bcfa615e..6615a46067 100644 --- a/phpBB/phpbb/template/twig/lexer.php +++ b/phpBB/phpbb/template/twig/lexer.php @@ -15,20 +15,10 @@ namespace phpbb\template\twig;  class lexer extends \Twig_Lexer  { -	public function set_environment(\Twig_Environment $env) +	public function tokenize(\Twig_Source $source)  	{ -		$this->env = $env; -	} - -	public function tokenize($code, $filename = null) -	{ -		// Handle \Twig_Source format input -		if ($code instanceof \Twig_Source) -		{ -			$source = $code; -			$code = $source->getCode(); -			$filename = $source->getName(); -		} +		$code = $source->getCode(); +		$filename = $source->getName();  		// Our phpBB tags  		// Commented out tokens are handled separately from the main replace diff --git a/phpBB/phpbb/template/twig/loader.php b/phpBB/phpbb/template/twig/loader.php index c13e3ee298..0f193dbe59 100644 --- a/phpBB/phpbb/template/twig/loader.php +++ b/phpBB/phpbb/template/twig/loader.php @@ -35,7 +35,7 @@ class loader extends \Twig_Loader_Filesystem  	{  		$this->filesystem = $filesystem; -		parent::__construct($paths, $this->filesystem->realpath(dirname(__FILE__))); +		parent::__construct($paths, __DIR__);  	}  	/** @@ -116,7 +116,7 @@ class loader extends \Twig_Loader_Filesystem  	* Override for Twig_Loader_Filesystem::findTemplate to add support  	*	for loading from safe directories.  	*/ -	protected function findTemplate($name) +	protected function findTemplate($name, $throw = true)  	{  		$name = (string) $name; @@ -132,12 +132,12 @@ class loader extends \Twig_Loader_Filesystem  		// First, find the template name. The override above of validateName  		//	causes the validateName process to be skipped for this call -		$file = parent::findTemplate($name); +		$file = parent::findTemplate($name, $throw);  		try  		{  			// Try validating the name (which may throw an exception) -			parent::validateName($name); +			$this->validateName($name);  		}  		catch (\Twig_Error_Loader $e)  		{ diff --git a/phpBB/phpbb/template/twig/node/definenode.php b/phpBB/phpbb/template/twig/node/definenode.php index ddbd151d20..1c51596916 100644 --- a/phpBB/phpbb/template/twig/node/definenode.php +++ b/phpBB/phpbb/template/twig/node/definenode.php @@ -16,7 +16,7 @@ namespace phpbb\template\twig\node;  class definenode extends \Twig_Node  { -	public function __construct($capture, \Twig_NodeInterface $name, \Twig_NodeInterface $value, $lineno, $tag = null) +	public function __construct($capture, \Twig_Node $name, \Twig_Node $value, $lineno, $tag = null)  	{  		parent::__construct(array('name' => $name, 'value' => $value), array('capture' => $capture, 'safe' => false), $lineno, $tag);  	} diff --git a/phpBB/phpbb/template/twig/node/includeasset.php b/phpBB/phpbb/template/twig/node/includeasset.php index 12034b7820..69bfd58803 100644 --- a/phpBB/phpbb/template/twig/node/includeasset.php +++ b/phpBB/phpbb/template/twig/node/includeasset.php @@ -15,15 +15,11 @@ namespace phpbb\template\twig\node;  abstract class includeasset extends \Twig_Node  { -	/** @var \Twig_Environment */ -	protected $environment; - -	public function __construct(\Twig_Node_Expression $expr, \phpbb\template\twig\environment $environment, $lineno, $tag = null) +	public function __construct(\Twig_Node_Expression $expr, $lineno, $tag = null)  	{ -		$this->environment = $environment; -  		parent::__construct(array('expr' => $expr), array(), $lineno, $tag);  	} +  	/**  	* Compiles the node to PHP.  	* @@ -33,20 +29,18 @@ abstract class includeasset extends \Twig_Node  	{  		$compiler->addDebugInfo($this); -		$config = $this->environment->get_phpbb_config(); -  		$compiler  			->write("\$asset_file = ")  			->subcompile($this->getNode('expr'))  			->raw(";\n") -			->write("\$asset = new \phpbb\\template\\asset(\$asset_file, \$this->getEnvironment()->get_path_helper(), \$this->getEnvironment()->get_filesystem());\n") +			->write("\$asset = new \phpbb\\template\\asset(\$asset_file, \$this->env->get_path_helper(), \$this->env->get_filesystem());\n")  			->write("if (substr(\$asset_file, 0, 2) !== './' && \$asset->is_relative()) {\n")  			->indent()  				->write("\$asset_path = \$asset->get_path();") -				->write("\$local_file = \$this->getEnvironment()->get_phpbb_root_path() . \$asset_path;\n") +				->write("\$local_file = \$this->env->get_phpbb_root_path() . \$asset_path;\n")  				->write("if (!file_exists(\$local_file)) {\n")  				->indent() -					->write("\$local_file = \$this->getEnvironment()->findTemplate(\$asset_path);\n") +					->write("\$local_file = \$this->env->findTemplate(\$asset_path);\n")  					->write("\$asset->set_path(\$local_file, true);\n")  				->outdent()  				->write("}\n") @@ -55,10 +49,10 @@ abstract class includeasset extends \Twig_Node  			->write("\n")  			->write("if (\$asset->is_relative()) {\n")  			->indent() -			->write("\$asset->add_assets_version('{$config['assets_version']}');\n") +			->write("\$asset->add_assets_version(\$this->env->get_phpbb_config()['assets_version']);\n")  			->outdent()  			->write("}\n") -			->write("\$this->getEnvironment()->get_assets_bag()->add_{$this->get_setters_name()}(\$asset);") +			->write("\$this->env->get_assets_bag()->add_{$this->get_setters_name()}(\$asset);")  		;  	} diff --git a/phpBB/phpbb/template/twig/node/includephp.php b/phpBB/phpbb/template/twig/node/includephp.php index 76182c2f84..0cf95abe99 100644 --- a/phpBB/phpbb/template/twig/node/includephp.php +++ b/phpBB/phpbb/template/twig/node/includephp.php @@ -63,15 +63,15 @@ class includephp extends \Twig_Node  				// Absolute path specified  				->write("require(\$location);\n")  			->outdent() -			->write("} else if (file_exists(\$this->getEnvironment()->get_phpbb_root_path() . \$location)) {\n") +			->write("} else if (file_exists(\$this->env->get_phpbb_root_path() . \$location)) {\n")  			->indent()  				// PHP file relative to phpbb_root_path -				->write("require(\$this->getEnvironment()->get_phpbb_root_path() . \$location);\n") +				->write("require(\$this->env->get_phpbb_root_path() . \$location);\n")  			->outdent()  			->write("} else {\n")  			->indent()  				// Local path (behaves like INCLUDE) -				->write("require(\$this->getEnvironment()->getLoader()->getCacheKey(\$location));\n") +				->write("require(\$this->env->getLoader()->getCacheKey(\$location));\n")  			->outdent()  			->write("}\n")  		; diff --git a/phpBB/phpbb/template/twig/tokenparser/defineparser.php b/phpBB/phpbb/template/twig/tokenparser/defineparser.php index b755836ccd..6285091e94 100644 --- a/phpBB/phpbb/template/twig/tokenparser/defineparser.php +++ b/phpBB/phpbb/template/twig/tokenparser/defineparser.php @@ -21,7 +21,7 @@ class defineparser extends \Twig_TokenParser  	*  	* @param \Twig_Token $token A Twig_Token instance  	* -	* @return \Twig_NodeInterface A Twig_NodeInterface instance +	* @return \Twig_Node A Twig_Node instance  	* @throws \Twig_Error_Syntax  	* @throws \phpbb\template\twig\node\definenode  	*/ @@ -41,7 +41,7 @@ class defineparser extends \Twig_TokenParser  			{  				// This would happen if someone improperly formed their DEFINE syntax  				// e.g. <!-- DEFINE $VAR = foo --> -				throw new \Twig_Error_Syntax('Invalid DEFINE', $token->getLine(), $this->parser->getFilename()); +				throw new \Twig_Error_Syntax('Invalid DEFINE', $token->getLine(), $this->parser->getStream()->getSourceContext()->getPath());  			}  			$stream->expect(\Twig_Token::BLOCK_END_TYPE); diff --git a/phpBB/phpbb/template/twig/tokenparser/event.php b/phpBB/phpbb/template/twig/tokenparser/event.php index f73ef4ae25..92ecff4a74 100644 --- a/phpBB/phpbb/template/twig/tokenparser/event.php +++ b/phpBB/phpbb/template/twig/tokenparser/event.php @@ -15,12 +15,25 @@ namespace phpbb\template\twig\tokenparser;  class event extends \Twig_TokenParser  { +	/** @var \phpbb\template\twig\environment */ +	protected $environment; + +	/** +	* Constructor +	* +	* @param \phpbb\template\twig\environment $environment +	*/ +	public function __construct(\phpbb\template\twig\environment $environment) +	{ +		$this->environment = $environment; +	} +  	/**  	* Parses a token and returns a node.  	*  	* @param \Twig_Token $token A Twig_Token instance  	* -	* @return \Twig_NodeInterface A Twig_NodeInterface instance +	* @return \Twig_Node A Twig_Node instance  	*/  	public function parse(\Twig_Token $token)  	{ @@ -29,7 +42,7 @@ class event extends \Twig_TokenParser  		$stream = $this->parser->getStream();  		$stream->expect(\Twig_Token::BLOCK_END_TYPE); -		return new \phpbb\template\twig\node\event($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); +		return new \phpbb\template\twig\node\event($expr, $this->environment, $token->getLine(), $this->getTag());  	}  	/** diff --git a/phpBB/phpbb/template/twig/tokenparser/includecss.php b/phpBB/phpbb/template/twig/tokenparser/includecss.php index 1f30811754..f7e55a46fb 100644 --- a/phpBB/phpbb/template/twig/tokenparser/includecss.php +++ b/phpBB/phpbb/template/twig/tokenparser/includecss.php @@ -20,7 +20,7 @@ class includecss extends \Twig_TokenParser  	*  	* @param \Twig_Token $token A Twig_Token instance  	* -	* @return \Twig_NodeInterface A Twig_NodeInterface instance +	* @return \Twig_Node A Twig_Node instance  	*/  	public function parse(\Twig_Token $token)  	{ @@ -29,7 +29,7 @@ class includecss extends \Twig_TokenParser  		$stream = $this->parser->getStream();  		$stream->expect(\Twig_Token::BLOCK_END_TYPE); -		return new \phpbb\template\twig\node\includecss($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); +		return new \phpbb\template\twig\node\includecss($expr, $token->getLine(), $this->getTag());  	}  	/** diff --git a/phpBB/phpbb/template/twig/tokenparser/includejs.php b/phpBB/phpbb/template/twig/tokenparser/includejs.php index 4b67d2c468..598ea0a70d 100644 --- a/phpBB/phpbb/template/twig/tokenparser/includejs.php +++ b/phpBB/phpbb/template/twig/tokenparser/includejs.php @@ -20,7 +20,7 @@ class includejs extends \Twig_TokenParser  	*  	* @param \Twig_Token $token A Twig_Token instance  	* -	* @return \Twig_NodeInterface A Twig_NodeInterface instance +	* @return \Twig_Node A Twig_Node instance  	*/  	public function parse(\Twig_Token $token)  	{ @@ -29,7 +29,7 @@ class includejs extends \Twig_TokenParser  		$stream = $this->parser->getStream();  		$stream->expect(\Twig_Token::BLOCK_END_TYPE); -		return new \phpbb\template\twig\node\includejs($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); +		return new \phpbb\template\twig\node\includejs($expr, $token->getLine(), $this->getTag());  	}  	/** diff --git a/phpBB/phpbb/template/twig/tokenparser/includeparser.php b/phpBB/phpbb/template/twig/tokenparser/includeparser.php index aa7236aaa6..2fba4ac4c4 100644 --- a/phpBB/phpbb/template/twig/tokenparser/includeparser.php +++ b/phpBB/phpbb/template/twig/tokenparser/includeparser.php @@ -21,7 +21,7 @@ class includeparser extends \Twig_TokenParser_Include  	*  	* @param \Twig_Token $token A Twig_Token instance  	* -	* @return \Twig_NodeInterface A Twig_NodeInterface instance +	* @return \Twig_Node A Twig_Node instance  	*/  	public function parse(\Twig_Token $token)  	{ diff --git a/phpBB/phpbb/template/twig/tokenparser/includephp.php b/phpBB/phpbb/template/twig/tokenparser/includephp.php index 3992636f8c..2fdf396452 100644 --- a/phpBB/phpbb/template/twig/tokenparser/includephp.php +++ b/phpBB/phpbb/template/twig/tokenparser/includephp.php @@ -16,12 +16,25 @@ namespace phpbb\template\twig\tokenparser;  class includephp extends \Twig_TokenParser  { +	/** @var \phpbb\template\twig\environment */ +	protected $environment; + +	/** +	* Constructor +	* +	* @param \phpbb\template\twig\environment $environment +	*/ +	public function __construct(\phpbb\template\twig\environment $environment) +	{ +		$this->environment = $environment; +	} +  	/**  	* Parses a token and returns a node.  	*  	* @param \Twig_Token $token A Twig_Token instance  	* -	* @return \Twig_NodeInterface A Twig_NodeInterface instance +	* @return \Twig_Node A Twig_Node instance  	*/  	public function parse(\Twig_Token $token)  	{ @@ -40,7 +53,7 @@ class includephp extends \Twig_TokenParser  		$stream->expect(\Twig_Token::BLOCK_END_TYPE); -		return new \phpbb\template\twig\node\includephp($expr, $this->parser->getEnvironment(), $token->getLine(), $ignoreMissing, $this->getTag()); +		return new \phpbb\template\twig\node\includephp($expr, $this->environment, $token->getLine(), $ignoreMissing, $this->getTag());  	}  	/** diff --git a/phpBB/phpbb/template/twig/tokenparser/php.php b/phpBB/phpbb/template/twig/tokenparser/php.php index f11ce35896..3007912b47 100644 --- a/phpBB/phpbb/template/twig/tokenparser/php.php +++ b/phpBB/phpbb/template/twig/tokenparser/php.php @@ -15,12 +15,25 @@ namespace phpbb\template\twig\tokenparser;  class php extends \Twig_TokenParser  { +	/** @var \phpbb\template\twig\environment */ +	protected $environment; + +	/** +	* Constructor +	* +	* @param \phpbb\template\twig\environment $environment +	*/ +	public function __construct(\phpbb\template\twig\environment $environment) +	{ +		$this->environment = $environment; +	} +  	/**  	* Parses a token and returns a node.  	*  	* @param \Twig_Token $token A Twig_Token instance  	* -	* @return \Twig_NodeInterface A Twig_NodeInterface instance +	* @return \Twig_Node A Twig_Node instance  	*/  	public function parse(\Twig_Token $token)  	{ @@ -32,7 +45,7 @@ class php extends \Twig_TokenParser  		$stream->expect(\Twig_Token::BLOCK_END_TYPE); -		return new \phpbb\template\twig\node\php($body, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); +		return new \phpbb\template\twig\node\php($body, $this->environment, $token->getLine(), $this->getTag());  	}  	public function decideEnd(\Twig_Token $token) diff --git a/phpBB/phpbb/textformatter/acp_utils_interface.php b/phpBB/phpbb/textformatter/acp_utils_interface.php new file mode 100644 index 0000000000..cdee56f19d --- /dev/null +++ b/phpBB/phpbb/textformatter/acp_utils_interface.php @@ -0,0 +1,54 @@ +<?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\textformatter; + +interface acp_utils_interface +{ +	/** +	* There is an issue with the definition +	*/ +	const BBCODE_STATUS_INVALID_DEFINITION = 'invalid_definition'; + +	/** +	* There is an issue with the template +	*/ +	const BBCODE_STATUS_INVALID_TEMPLATE = 'invalid_template'; + +	/** +	* The BBCode is valid and can be safely used by anyone +	*/ +	const BBCODE_STATUS_SAFE = 'safe'; + +	/** +	* The BBCode is valid but may be unsafe to use +	*/ +	const BBCODE_STATUS_UNSAFE = 'unsafe'; + +	/** +	* Analyse given BBCode definition for issues and safeness +	* +	* Required elements in the return array: +	*  - status: see BBCODE_STATUS_* constants +	* +	* Optional elements in the return array: +	*  - name:       Name of the BBCode based on the definition. Required if status is "safe". +	*  - error_text: Textual description of the issue in plain text or as a L_* string. +	*  - error_html: Visual description of the issue in HTML. +	* +	* @param  string $definition BBCode definition, e.g. [b]{TEXT}[/b] +	* @param  string $template   BBCode template, e.g. <b>{TEXT}</b> +	* @return array +	*/ +	public function analyse_bbcode(string $definition, string $template): array; +} diff --git a/phpBB/phpbb/textformatter/s9e/acp_utils.php b/phpBB/phpbb/textformatter/s9e/acp_utils.php new file mode 100644 index 0000000000..c4a668020e --- /dev/null +++ b/phpBB/phpbb/textformatter/s9e/acp_utils.php @@ -0,0 +1,67 @@ +<?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\textformatter\s9e; + +use phpbb\textformatter\acp_utils_interface; +use s9e\TextFormatter\Configurator\Exceptions\UnsafeTemplateException; + +class acp_utils implements acp_utils_interface +{ +	/** +	* @var factory $factory +	*/ +	protected $factory; + +	/** +	* @param factory $factory +	*/ +	public function __construct(factory $factory) +	{ +		$this->factory = $factory; +	} + +	/** +	* {@inheritdoc} +	*/ +	public function analyse_bbcode(string $definition, string $template): array +	{ +		$configurator = $this->factory->get_configurator(); +		$return       = ['status' => self::BBCODE_STATUS_SAFE]; + +		// Capture and normalize the BBCode name manually because there's no easy way to retrieve +		// it in TextFormatter <= 2.x +		if (preg_match('(\\[([-\\w]++))', $definition, $m)) +		{ +			$return['name'] = strtoupper($m[1]); +		} + +		try +		{ +			$configurator->BBCodes->addCustom($definition, $template); +		} +		catch (UnsafeTemplateException $e) +		{ +			$return['status']     = self::BBCODE_STATUS_UNSAFE; +			$return['error_text'] = $e->getMessage(); +			$return['error_html'] = $e->highlightNode('<span class="highlight">'); +		} +		catch (\Exception $e) +		{ +			$return['status']     = (preg_match('(xml|xpath|xsl)i', $e->getMessage())) ? self::BBCODE_STATUS_INVALID_TEMPLATE : self::BBCODE_STATUS_INVALID_DEFINITION; +			$return['error_text'] = $e->getMessage(); +		} + +		return $return; +	} +} diff --git a/phpBB/phpbb/textformatter/s9e/bbcode_merger.php b/phpBB/phpbb/textformatter/s9e/bbcode_merger.php index 264eb93782..d1bedb0b72 100644 --- a/phpBB/phpbb/textformatter/s9e/bbcode_merger.php +++ b/phpBB/phpbb/textformatter/s9e/bbcode_merger.php @@ -14,7 +14,7 @@  namespace phpbb\textformatter\s9e;  use phpbb\textformatter\s9e\factory; -use s9e\TextFormatter\Configurator\Helpers\TemplateHelper; +use s9e\TextFormatter\Configurator\Helpers\TemplateLoader;  use s9e\TextFormatter\Configurator\Items\UnsafeTemplate;  class bbcode_merger @@ -91,9 +91,9 @@ class bbcode_merger  	*/  	protected function indent_template($template)  	{ -		$dom = TemplateHelper::loadTemplate($template); +		$dom = TemplateLoader::load($template);  		$dom->formatOutput = true; -		$template = TemplateHelper::saveTemplate($dom); +		$template = TemplateLoader::save($dom);  		// Remove the first level of indentation if the template starts with whitespace  		if (preg_match('(^\\n +)', $template, $m)) diff --git a/phpBB/phpbb/ucp/controller/reset_password.php b/phpBB/phpbb/ucp/controller/reset_password.php new file mode 100644 index 0000000000..5c27c4f414 --- /dev/null +++ b/phpBB/phpbb/ucp/controller/reset_password.php @@ -0,0 +1,443 @@ +<?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\ucp\controller; + +use phpbb\auth\auth; +use phpbb\config\config; +use phpbb\controller\helper; +use phpbb\db\driver\driver_interface; +use phpbb\event\dispatcher; +use phpbb\exception\http_exception; +use phpbb\language\language; +use phpbb\log\log_interface; +use phpbb\passwords\manager; +use phpbb\request\request_interface; +use phpbb\template\template; +use phpbb\user; +use Symfony\Component\HttpFoundation\Response; + +/** +* Handling forgotten passwords via reset password functionality +*/ +class reset_password +{ +	/** @var config */ +	protected $config; + +	/** @var driver_interface */ +	protected $db; + +	/** @var dispatcher */ +	protected $dispatcher; + +	/** @var helper */ +	protected $helper; + +	/** @var language */ +	protected $language; + +	/** @var log_interface */ +	protected $log; + +	/** @var manager */ +	protected $passwords_manager; + +	/** @var request_interface */ +	protected $request; + +	/** @var template */ +	protected $template; + +	/** @var user */ +	protected $user; + +	/** @var array phpBB DB table names */ +	protected $users_table; + +	/** @var string phpBB root path */ +	protected $root_path; + +	/** @var string PHP extension */ +	protected $php_ext; + +	/** +	 * Reset password controller constructor. +	 * +	 * @param config $config +	 * @param driver_interface $db +	 * @param dispatcher $dispatcher +	 * @param helper $helper +	 * @param language $language +	 * @param log_interface $log +	 * @param manager $passwords_manager +	 * @param request_interface $request +	 * @param template $template +	 * @param user $user +	 * @param string $users_table +	 * @param string $root_path +	 * @param string $php_ext +	 */ +	public function __construct(config $config, driver_interface $db, dispatcher $dispatcher, helper $helper, +								language $language, log_interface $log, manager $passwords_manager, +								request_interface $request, template $template, user $user, string $users_table, +								string $root_path, string $php_ext) +	{ +		$this->config = $config; +		$this->db = $db; +		$this->dispatcher = $dispatcher; +		$this->helper = $helper; +		$this->language = $language; +		$this->log = $log; +		$this->passwords_manager = $passwords_manager; +		$this->request = $request; +		$this->template = $template; +		$this->user = $user; +		$this->users_table = $users_table; +		$this->root_path = $root_path; +		$this->php_ext = $php_ext; +	} + +	/** +	 * Init controller +	 */ +	protected function init_controller() +	{ +		$this->language->add_lang('ucp'); + +		if (!$this->config['allow_password_reset']) +		{ +			throw new http_exception(Response::HTTP_OK, 'UCP_PASSWORD_RESET_DISABLED', [ +				'<a href="mailto:' . htmlspecialchars($this->config['board_contact']) . '">', +				'</a>' +			]); +		} +	} + +	/** +	 * Remove reset token for specified user +	 * +	 * @param int $user_id User ID +	 */ +	protected function remove_reset_token(int $user_id) +	{ +		$sql_ary = [ +			'reset_token'				=> '', +			'reset_token_expiration'	=> 0, +		]; + +		$sql = 'UPDATE ' . $this->users_table . ' +					SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' +					WHERE user_id = ' . $user_id; +		$this->db->sql_query($sql); +	} + +	/** +	 * Handle password reset request +	 * +	 * @return Response +	 */ +	public function request() +	{ +		$this->init_controller(); + +		$submit		= $this->request->is_set_post('submit'); +		$username	= $this->request->variable('username', '', true); +		$email		= strtolower($this->request->variable('email', '')); + +		add_form_key('ucp_reset_password'); + +		if ($submit) +		{ +			if (!check_form_key('ucp_reset_password')) +			{ +				throw new http_exception(Response::HTTP_UNAUTHORIZED, 'FORM_INVALID'); +			} + +			if (empty($email)) +			{ +				return $this->helper->message('NO_EMAIL_USER'); +			} + +			$sql_array = [ +				'SELECT'	=> 'user_id, username, user_permissions, user_email, user_jabber, user_notify_type, user_type,' +								. ' user_lang, user_inactive_reason, reset_token, reset_token_expiration', +				'FROM'		=> [$this->users_table => 'u'], +				'WHERE'		=> "user_email = '" . $this->db->sql_escape($email) . "'" . +					(!empty($username) ? " AND username_clean = '" . $this->db->sql_escape(utf8_clean_string($username)) . "'" : ''), +			]; + +			/** +			 * Change SQL query for fetching user data +			 * +			 * @event core.ucp_remind_modify_select_sql +			 * @var	string	email		User's email from the form +			 * @var	string	username	User's username from the form +			 * @var	array	sql_array	Fully assembled SQL query with keys SELECT, FROM, WHERE +			 * @since 3.1.11-RC1 +			 * @changed 3.3.0-b1 Moved to reset password controller +			 */ +			$vars = [ +				'email', +				'username', +				'sql_array', +			]; +			extract($this->dispatcher->trigger_event('core.ucp_remind_modify_select_sql', compact($vars))); + +			$sql = $this->db->sql_build_query('SELECT', $sql_array); +			$result = $this->db->sql_query_limit($sql, 2); // don't waste resources on more rows than we need +			$rowset = $this->db->sql_fetchrowset($result); +			$this->db->sql_freeresult($result); + +			if (count($rowset) > 1) +			{ +				$this->template->assign_vars([ +					'USERNAME_REQUIRED'	=> true, +					'EMAIL'				=> $email, +				]); +			} +			else +			{ +				$message = $this->language->lang('PASSWORD_RESET_LINK_SENT') . '<br /><br />' . $this->language->lang('RETURN_INDEX', '<a href="' . append_sid("{$this->root_path}index.{$this->php_ext}") . '">', '</a>'); + +				if (empty($rowset)) +				{ +					return $this->helper->message($message); +				} + +				$user_row = $rowset[0]; + +				if ($user_row['user_type'] == USER_IGNORE || $user_row['user_type'] == USER_INACTIVE) +				{ +					return $this->helper->message($message); +				} + +				// Do not create multiple valid reset tokens +				if (!empty($user_row['reset_token']) && (int) $user_row['reset_token_expiration'] >= time()) +				{ +					return $this->helper->message($message); +				} + +				// Check users permissions +				$auth = new auth(); +				$auth->acl($user_row); + +				if (!$auth->acl_get('u_chgpasswd')) +				{ +					return $this->helper->message($message); +				} + +				// Generate reset token +				$reset_token = strtolower(gen_rand_string(32)); + +				$sql_ary = [ +					'reset_token'				=> $reset_token, +					'reset_token_expiration'	=> strtotime('+1 day'), +				]; + +				$sql = 'UPDATE ' . $this->users_table . ' +					SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' +					WHERE user_id = ' . $user_row['user_id']; +				$this->db->sql_query($sql); + +				if (!class_exists('messenger')) +				{ +					include($this->root_path . 'includes/functions_messenger.' . $this->php_ext); +				} + +				/** @var \messenger $messenger */ +				$messenger = new \messenger(false); + +				$messenger->template('user_forgot_password', $user_row['user_lang']); + +				$messenger->set_addresses($user_row); + +				$messenger->anti_abuse_headers($this->config, $this->user); + +				$messenger->assign_vars([ +						'USERNAME'			=> htmlspecialchars_decode($user_row['username']), +						'U_RESET_PASSWORD'	=> generate_board_url(true) . $this->helper->route('phpbb_ucp_reset_password_controller', [ +							'u'		=> $user_row['user_id'], +							'token'	=> $reset_token, +						], false) +				]); + +				$messenger->send($user_row['user_notify_type']); + +				return $this->helper->message($message); +			} +		} + +		$this->template->assign_vars([ +			'USERNAME'					=> $username, +			'EMAIL'						=> $email, +			'U_RESET_PASSWORD_ACTION'	=> $this->helper->route('phpbb_ucp_forgot_password_controller'), +		]); + +		return $this->helper->render('ucp_reset_password.html', $this->language->lang('RESET_PASSWORD')); +	} + +	/** +	 * Handle controller requests +	 * +	 * @return Response +	 */ +	public function reset() +	{ +		$this->init_controller(); + +		$submit			= $this->request->is_set_post('submit'); +		$reset_token	= $this->request->variable('token', ''); +		$user_id		= $this->request->variable('u', 0); + +		if (empty($reset_token)) +		{ +			return $this->helper->message('NO_RESET_TOKEN'); +		} + +		if (!$user_id) +		{ +			return $this->helper->message('NO_USER'); +		} + +		add_form_key('ucp_reset_password'); + +		$sql_array = [ +			'SELECT'	=> 'user_id, username, user_permissions, user_email, user_jabber, user_notify_type, user_type,' +				. ' user_lang, user_inactive_reason, reset_token, reset_token_expiration', +			'FROM'		=> [$this->users_table => 'u'], +			'WHERE'		=> 'user_id = ' . $user_id, +		]; + +		/** +		 * Change SQL query for fetching user data +		 * +		 * @event core.ucp_reset_password_modify_select_sql +		 * @var	int	user_id		User ID from the form +		 * @var	string	reset_token Reset token +		 * @var	array	sql_array	Fully assembled SQL query with keys SELECT, FROM, WHERE +		 * @since 3.3.0-b1 +		 */ +		$vars = [ +			'user_id', +			'reset_token', +			'sql_array', +		]; +		extract($this->dispatcher->trigger_event('core.ucp_reset_password_modify_select_sql', compact($vars))); + +		$sql = $this->db->sql_build_query('SELECT', $sql_array); +		$result = $this->db->sql_query_limit($sql, 1); +		$user_row = $this->db->sql_fetchrow($result); +		$this->db->sql_freeresult($result); + +		$message = $this->language->lang('RESET_TOKEN_EXPIRED_OR_INVALID') . '<br /><br />' . $this->language->lang('RETURN_INDEX', '<a href="' . append_sid("{$this->root_path}index.{$this->php_ext}") . '">', '</a>'); + +		if (empty($user_row)) +		{ +			return $this->helper->message($message); +		} + +		if (!hash_equals($reset_token, $user_row['reset_token'])) +		{ +			return $this->helper->message($message); +		} + +		if ($user_row['reset_token_expiration'] < time()) +		{ +			$this->remove_reset_token($user_id); + +			return $this->helper->message($message); +		} + +		$errors = []; + +		if ($submit) +		{ +			if (!check_form_key('ucp_reset_password')) +			{ +				return $this->helper->message('FORM_INVALID'); +			} + +			if ($user_row['user_type'] == USER_IGNORE || $user_row['user_type'] == USER_INACTIVE) +			{ +				return $this->helper->message($message); +			} + +			// Check users permissions +			$auth = new auth(); +			$auth->acl($user_row); + +			if (!$auth->acl_get('u_chgpasswd')) +			{ +				return $this->helper->message($message); +			} + +			if (!function_exists('validate_data')) +			{ +				include($this->root_path . 'includes/functions_user.' . $this->php_ext); +			} + +			$data = [ +				'new_password'		=> $this->request->untrimmed_variable('new_password', '', true), +				'password_confirm'	=> $this->request->untrimmed_variable('new_password_confirm', '', true), +			]; +			$check_data = [ +				'new_password'		=> [ +					['string', false, $this->config['min_pass_chars'], 0], +					['password'], +				], +				'password_confirm'	=> ['string', true, $this->config['min_pass_chars'], 0], +			]; +			$errors = array_merge($errors, validate_data($data, $check_data)); +			if (strcmp($data['new_password'], $data['password_confirm']) !== 0) +			{ +				$errors[] = $data['password_confirm'] ? 'NEW_PASSWORD_ERROR' : 'NEW_PASSWORD_CONFIRM_EMPTY'; +			} +			if (empty($errors)) +			{ +				$sql_ary = [ +					'user_password'				=> $this->passwords_manager->hash($data['new_password']), +					'user_login_attempts'		=> 0, +					'reset_token'				=> '', +					'reset_token_expiration'	=> 0, +				]; +				$sql = 'UPDATE ' . $this->users_table . ' +							SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' +							WHERE user_id = ' . (int) $user_row['user_id']; +				$this->db->sql_query($sql); +				$this->log->add('user', $user_row['user_id'], $this->user->ip, 'LOG_USER_NEW_PASSWORD', false, [ +					'reportee_id' => $user_row['user_id'], +					$user_row['username'] +				]); +				meta_refresh(3, append_sid("{$this->root_path}index.{$this->php_ext}")); +				return $this->helper->message($this->language->lang('PASSWORD_RESET')); +			} +		} + +		if (!empty($errors)) +		{ +			$this->template->assign_block_vars_array('PASSWORD_RESET_ERRORS', array_map([$this->language, 'lang'], $errors)); +		} + +		$this->template->assign_vars([ +			'S_IS_PASSWORD_RESET'		=> true, +			'U_RESET_PASSWORD_ACTION'	=> $this->helper->route('phpbb_ucp_reset_password_controller'), +			'S_HIDDEN_FIELDS'			=> build_hidden_fields([ +				'u'		=> $user_id, +				'token'	=> $reset_token, +			]), +		]); + +		return $this->helper->render('ucp_reset_password.html', $this->language->lang('RESET_PASSWORD')); +	} +} diff --git a/phpBB/phpbb/user.php b/phpBB/phpbb/user.php index 9817e40edb..21d156e060 100644 --- a/phpBB/phpbb/user.php +++ b/phpBB/phpbb/user.php @@ -110,7 +110,7 @@ class user extends \phpbb\session  	function setup($lang_set = false, $style_id = false)  	{  		global $db, $request, $template, $config, $auth, $phpEx, $phpbb_root_path, $cache; -		global $phpbb_dispatcher; +		global $phpbb_dispatcher, $phpbb_container;  		$this->language->set_default_language($config['default_lang']); @@ -361,8 +361,8 @@ class user extends \phpbb\session  		}  		// Disable board if the install/ directory is still present -		// For the brave development army we do not care about this, else we need to comment out this everytime we develop locally -		if (!defined('DEBUG') && !defined('ADMIN_START') && !defined('IN_INSTALL') && !defined('IN_LOGIN') && file_exists($phpbb_root_path . 'install') && !is_file($phpbb_root_path . 'install')) +		// For the brave development army we do not care about this, else we need to comment out this every time we develop locally +		if (!$phpbb_container->getParameter('allow_install_dir') && !defined('ADMIN_START') && !defined('IN_INSTALL') && !defined('IN_LOGIN') && file_exists($phpbb_root_path . 'install') && !is_file($phpbb_root_path . 'install'))  		{  			// Adjust the message slightly according to the permissions  			if ($auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_')) @@ -480,7 +480,7 @@ class user extends \phpbb\session  	* @return int|bool     The plural-case we need to use for the number plural-rule combination, false if $force_rule  	* 					   was invalid.  	* -	* @deprecated: 3.2.0-dev (To be removed: 3.3.0) +	* @deprecated: 3.2.0-dev (To be removed: 4.0.0)  	*/  	function get_plural_form($number, $force_rule = false)  	{ @@ -491,8 +491,8 @@ class user extends \phpbb\session  	* Add Language Items - use_db and use_help are assigned where needed (only use them to force inclusion)  	*  	* @param mixed $lang_set specifies the language entries to include -	* @param bool $use_db internal variable for recursion, do not use	@deprecated 3.2.0-dev (To be removed: 3.3.0) -	* @param bool $use_help internal variable for recursion, do not use	@deprecated 3.2.0-dev (To be removed: 3.3.0) +	* @param bool $use_db internal variable for recursion, do not use	@deprecated 3.2.0-dev (To be removed: 4.0.0) +	* @param bool $use_help internal variable for recursion, do not use	@deprecated 3.2.0-dev (To be removed: 4.0.0)  	* @param string $ext_name The extension to load language from, or empty for core files  	*  	* Examples: @@ -507,7 +507,7 @@ class user extends \phpbb\session  	* Note: $use_db and $use_help should be removed. The old function was kept for BC purposes,  	* 		so the BC logic is handled here.  	* -	* @deprecated: 3.2.0-dev (To be removed: 3.3.0) +	* @deprecated: 3.2.0-dev (To be removed: 4.0.0)  	*/  	function add_lang($lang_set, $use_db = false, $use_help = false, $ext_name = '')  	{ @@ -548,7 +548,7 @@ class user extends \phpbb\session  	/**  	 * BC function for loading language files  	 * -	 * @deprecated 3.2.0-dev (To be removed: 3.3.0) +	 * @deprecated 3.2.0-dev (To be removed: 4.0.0)  	 */  	private function set_lang($lang_set, $use_help, $ext_name)  	{ @@ -584,7 +584,7 @@ class user extends \phpbb\session  	*  	* Note: $use_db and $use_help should be removed. Kept for BC purposes.  	* -	* @deprecated: 3.2.0-dev (To be removed: 3.3.0) +	* @deprecated: 3.2.0-dev (To be removed: 4.0.0)  	*/  	function add_lang_ext($ext_name, $lang_set, $use_db = false, $use_help = false)  	{ @@ -786,7 +786,7 @@ class user extends \phpbb\session  	}  	/** -	* Funtion to make the user leave the NEWLY_REGISTERED system group. +	* Function to make the user leave the NEWLY_REGISTERED system group.  	* @access public  	*/  	function leave_newly_registered() diff --git a/phpBB/phpbb/user_loader.php b/phpBB/phpbb/user_loader.php index 9297450f3e..3dacf07ff5 100644 --- a/phpBB/phpbb/user_loader.php +++ b/phpBB/phpbb/user_loader.php @@ -123,7 +123,7 @@ class user_loader  	/**  	* Get a user row from our users cache  	* -	* @param int $user_id User ID of the user you want to retreive +	* @param int $user_id User ID of the user you want to retrieve  	* @param bool $query Should we query the database if this user has not yet been loaded?  	* 						Typically this should be left as false and you should make sure  	* 						you load users ahead of time with load_users() @@ -150,7 +150,7 @@ class user_loader  	/**  	* Get username  	* -	* @param int $user_id User ID of the user you want to retreive the username for +	* @param int $user_id User ID of the user you want to retrieve the username for  	* @param string $mode The mode to load (same as get_username_string). One of the following:  	* 			profile (for getting an url to the profile)  	* 			username (for obtaining the username) @@ -204,7 +204,7 @@ class user_loader  	/**  	* Get rank  	* -	* @param int $user_id User ID of the user you want to retreive the rank for +	* @param int $user_id User ID of the user you want to retrieve the rank for  	* @param bool $query Should we query the database if this user has not yet been loaded?  	* 						Typically this should be left as false and you should make sure  	* 						you load users ahead of time with load_users() | 
