diff options
Diffstat (limited to 'phpBB/phpbb')
103 files changed, 1744 insertions, 605 deletions
| 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/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/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/console/command/cron/run.php b/phpBB/phpbb/console/command/cron/run.php index dea6493007..df8bcf44f9 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)  	{ diff --git a/phpBB/phpbb/console/command/extension/enable.php b/phpBB/phpbb/console/command/extension/enable.php index a6f5b10e86..f007009aa0 100644 --- a/phpBB/phpbb/console/command/extension/enable.php +++ b/phpBB/phpbb/console/command/extension/enable.php @@ -69,7 +69,10 @@ class enable extends command  		}  		else  		{ -			$io->error($this->user->lang('CLI_EXTENSION_ENABLE_FAILURE', $name)); +			$enableable = $this->manager->get_extension($name)->is_enableable(); +			$message = !empty($enableable) ? $enableable : $this->user->lang('CLI_EXTENSION_ENABLE_FAILURE'); +			$message = is_array($message) ? implode(PHP_EOL, $message) : $message; +			$io->error($message, $name);  			return 1;  		}  	} diff --git a/phpBB/phpbb/console/command/update/check.php b/phpBB/phpbb/console/command/update/check.php index 9ced651e8b..85c6cf7379 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) 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..704ec6badb 100644 --- a/phpBB/phpbb/content_visibility.php +++ b/phpBB/phpbb/content_visibility.php @@ -684,7 +684,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/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 index a94e88b331..8ce70444c2 100644 --- a/phpBB/phpbb/db/driver/mysql.php +++ b/phpBB/phpbb/db/driver/mysql.php @@ -171,12 +171,11 @@ class mysql 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);  			} @@ -191,11 +190,11 @@ class mysql 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 mysql extends \phpbb\db\driver\mysql_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);  			} @@ -390,7 +389,7 @@ class mysql 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/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..534e8b7653 100644 --- a/phpBB/phpbb/db/extractor/mysql_extractor.php +++ b/phpBB/phpbb/db/extractor/mysql_extractor.php @@ -300,7 +300,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/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/remove_attachment_flash.php b/phpBB/phpbb/db/migration/data/v330/remove_attachment_flash.php new file mode 100644 index 0000000000..11dc43483b --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/remove_attachment_flash.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\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 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_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/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..d128df96c4 100644 --- a/phpBB/phpbb/db/tools/tools.php +++ b/phpBB/phpbb/db/tools/tools.php @@ -335,7 +335,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; 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..8c1c172e36 100644 --- a/phpBB/phpbb/di/service_collection.php +++ b/phpBB/phpbb/di/service_collection.php @@ -103,4 +103,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/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/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/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_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..4607ce9ec2 100644 --- a/phpBB/phpbb/install/module/requirements/task/check_server_environment.php +++ b/phpBB/phpbb/install/module/requirements/task/check_server_environment.php @@ -98,7 +98,7 @@ class check_server_environment extends \phpbb\install\task_base  	{  		$php_version = PHP_VERSION; -		if (version_compare($php_version, '5.4') < 0) +		if (version_compare($php_version, '7.1') < 0)  		{  			$this->response_helper->add_error_message('PHP_VERSION_REQD', 'PHP_VERSION_REQD_EXPLAIN'); 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..49d7d6393e --- /dev/null +++ b/phpBB/phpbb/passwords/driver/argon2i.php @@ -0,0 +1,73 @@ +<?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); + +		// Don't allow cost factors to be below default settings +		$this->memory_cost = max($memory_cost, 1024); +		$this->threads     = max($threads,     2); +		$this->time_cost   = max($time_cost,   2); +	} + +	/** +	* {@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/passwords/driver/argon2id.php b/phpBB/phpbb/passwords/driver/argon2id.php new file mode 100644 index 0000000000..9e4b08bbb9 --- /dev/null +++ b/phpBB/phpbb/passwords/driver/argon2id.php @@ -0,0 +1,33 @@ +<?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 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/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..5c30f9b062 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 @@ -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..54dd8cef15 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 diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php index 1105d0892f..4d3e13663d 100644 --- a/phpBB/phpbb/search/fulltext_mysql.php +++ b/phpBB/phpbb/search/fulltext_mysql.php @@ -150,7 +150,7 @@ 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()  	{ diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php index c83de75eed..ecebbd37cd 100644 --- a/phpBB/phpbb/search/fulltext_native.php +++ b/phpBB/phpbb/search/fulltext_native.php @@ -351,7 +351,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 +'); 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 2c2eb84dc7..d8331d3815 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,7 +210,7 @@ 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()  	{ diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index 31f32af7c4..38e40ba29e 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -250,7 +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 +				// check IPv4 first, the IPv6 is hopefully only going to be used very seldom  				if (!empty($ip) && !preg_match(get_preg_expression('ipv4'), $ip) && !preg_match(get_preg_expression('ipv6'), $ip))  				{  					// contains invalid data, don't use the forwarded for header @@ -478,8 +478,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)  						{ @@ -1336,7 +1336,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]) @@ -1395,7 +1395,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  	* 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/s9e/bbcode_merger.php b/phpBB/phpbb/textformatter/s9e/bbcode_merger.php index a05ca3c2b8..af644192d8 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..7bd1b20cb3 --- /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_hash = '" . $this->db->sql_escape(phpbb_email_hash($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() | 
