diff options
Diffstat (limited to 'phpBB/includes')
31 files changed, 584 insertions, 185 deletions
diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index 5b1db5c31b..94e3660de8 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -27,6 +27,9 @@ class acp_attachments  	/** @var \phpbb\config\config */  	protected $config; +	/** @var \phpbb\language\language */ +	protected $language; +  	/** @var ContainerBuilder */  	protected $phpbb_container; @@ -54,6 +57,7 @@ class acp_attachments  		$this->id = $id;  		$this->db = $db;  		$this->config = $config; +		$this->language = $phpbb_container->get('language');  		$this->template = $template;  		$this->user = $user;  		$this->phpbb_container = $phpbb_container; @@ -128,7 +132,7 @@ class acp_attachments  				$s_assigned_groups = array();  				while ($row = $db->sql_fetchrow($result))  				{ -					$row['group_name'] = (isset($user->lang['EXT_GROUP_' . $row['group_name']])) ? $user->lang['EXT_GROUP_' . $row['group_name']] : $row['group_name']; +					$row['group_name'] = $this->language->is_set('EXT_GROUP_' . utf8_strtoupper($row['group_name'])) ? $this->language->lang('EXT_GROUP_' . utf8_strtoupper($row['group_name'])) : $row['group_name'];  					$s_assigned_groups[$row['cat_id']][] = $row['group_name'];  				}  				$db->sql_freeresult($result); @@ -573,7 +577,7 @@ class acp_attachments  							$group_id = $db->sql_nextid();  						} -						$group_name = (isset($user->lang['EXT_GROUP_' . $group_name])) ? $user->lang['EXT_GROUP_' . $group_name] : $group_name; +						$group_name = $this->language->is_set('EXT_GROUP_' . utf8_strtoupper($group_name)) ? $this->language->lang('EXT_GROUP_' . utf8_strtoupper($group_name)) : $group_name;  						$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXTGROUP_' . strtoupper($action), false, array($group_name));  					} @@ -875,7 +879,7 @@ class acp_attachments  						'U_EDIT'		=> $this->u_action . "&action=edit&g={$row['group_id']}",  						'U_DELETE'		=> $this->u_action . "&action=delete&g={$row['group_id']}", -						'GROUP_NAME'	=> (isset($user->lang['EXT_GROUP_' . $row['group_name']])) ? $user->lang['EXT_GROUP_' . $row['group_name']] : $row['group_name'], +						'GROUP_NAME'	=> $this->language->is_set('EXT_GROUP_' . utf8_strtoupper($row['group_name'])) ? $this->language->lang('EXT_GROUP_' . utf8_strtoupper($row['group_name'])) : $row['group_name'],  						'CATEGORY'		=> $cat_lang[$row['cat_id']],  						)  					); @@ -1244,15 +1248,11 @@ class acp_attachments  						'ATTACHMENT_POSTER'	=> get_username_string('full', (int) $row['poster_id'], (string) $row['username'], (string) $row['user_colour'], (string) $row['username']),  						'FILESIZE'			=> get_formatted_filesize((int) $row['filesize']),  						'FILETIME'			=> $user->format_date((int) $row['filetime']), -						'REAL_FILENAME'		=> (!$row['in_message']) ? utf8_basename((string) $row['real_filename']) : '', -						'PHYSICAL_FILENAME'	=> utf8_basename((string) $row['physical_filename']), -						'EXT_GROUP_NAME'	=> (!empty($extensions[$row['extension']]['group_name'])) ? $user->lang['EXT_GROUP_' . $extensions[$row['extension']]['group_name']] : '', +						'REAL_FILENAME'		=> utf8_basename((string) $row['real_filename']), +						'EXT_GROUP_NAME'	=> $this->language->is_set('EXT_GROUP_' . utf8_strtoupper($extensions[$row['extension']]['group_name'])) ?  $this->language->lang('EXT_GROUP_' . utf8_strtoupper($extensions[$row['extension']]['group_name'])) : $extensions[$row['extension']]['group_name'],  						'COMMENT'			=> $comment,  						'TOPIC_TITLE'		=> (!$row['in_message']) ? (string) $row['topic_title'] : '',  						'ATTACH_ID'			=> (int) $row['attach_id'], -						'POST_ID'			=> (int) $row['post_msg_id'], -						'TOPIC_ID'			=> (int) $row['topic_id'], -						'POST_IDS'			=> (!empty($post_ids[$row['attach_id']])) ? (int) $post_ids[$row['attach_id']] : '',  						'L_DOWNLOAD_COUNT'	=> $user->lang($l_downloaded_viewed, (int) $row['download_count']), @@ -1434,7 +1434,7 @@ class acp_attachments  		$group_name = array();  		while ($row = $db->sql_fetchrow($result))  		{ -			$row['group_name'] = (isset($user->lang['EXT_GROUP_' . $row['group_name']])) ? $user->lang['EXT_GROUP_' . $row['group_name']] : $row['group_name']; +			$row['group_name'] = $this->language->is_set('EXT_GROUP_' . utf8_strtoupper($row['group_name'])) ? $this->language->lang('EXT_GROUP_' . utf8_strtoupper($row['group_name'])) : $row['group_name'];  			$group_name[] = $row;  		}  		$db->sql_freeresult($result); diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index 1f7374a07f..bd8df6a63b 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -33,7 +33,6 @@ class acp_bbcodes  		// Set up general vars  		$action	= $request->variable('action', '');  		$bbcode_id = $request->variable('bbcode', 0); -		$submit = $request->is_set_post('submit');  		$this->tpl_name = 'acp_bbcodes';  		$this->page_title = 'ACP_BBCODES'; @@ -41,11 +40,6 @@ class acp_bbcodes  		add_form_key($form_key); -		if ($submit && !check_form_key($form_key)) -		{ -			trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); -		} -  		// Set up mode-specific vars  		switch ($action)  		{ @@ -179,6 +173,12 @@ class acp_bbcodes  				extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_modify_create', compact($vars)));  				$warn_text = preg_match('%<[^>]*\{text[\d]*\}[^>]*>%i', $bbcode_tpl); + +				if (!$warn_text && !check_form_key($form_key)) +				{ +					trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); +				} +  				if (!$warn_text || confirm_box(true))  				{  					$data = $this->build_regexp($bbcode_match, $bbcode_tpl); @@ -211,11 +211,6 @@ class acp_bbcodes  						$test = $data['bbcode_tag'];  					} -					if (!preg_match('%\\[' . $test . '[^]]*].*?\\[/' . $test . ']%s', $bbcode_match)) -					{ -						trigger_error($user->lang['BBCODE_OPEN_ENDED_TAG'] . adm_back_link($this->u_action), E_USER_WARNING); -					} -  					if (strlen($data['bbcode_tag']) > 16)  					{  						trigger_error($user->lang['BBCODE_TAG_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index f89f5535eb..0730b4e285 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -30,10 +30,13 @@ class acp_board  	function main($id, $mode)  	{ -		global $user, $template, $request; +		global $user, $template, $request, $language;  		global $config, $phpbb_root_path, $phpEx;  		global $cache, $phpbb_container, $phpbb_dispatcher, $phpbb_log; +		/** @var \phpbb\language\language $language Language object */ +		$language = $phpbb_container->get('language'); +  		$user->add_lang('acp/board');  		$submit = (isset($_POST['submit']) || isset($_POST['allow_quick_reply_enable'])) ? true : false; @@ -56,7 +59,7 @@ class acp_board  						'legend1'				=> 'ACP_BOARD_SETTINGS',  						'sitename'				=> array('lang' => 'SITE_NAME',				'validate' => 'string',	'type' => 'text:40:255', 'explain' => false),  						'site_desc'				=> array('lang' => 'SITE_DESC',				'validate' => 'string',	'type' => 'text:40:255', 'explain' => false), -						'site_home_url'			=> array('lang' => 'SITE_HOME_URL',			'validate' => 'string',	'type' => 'url:40:255', 'explain' => true), +						'site_home_url'			=> array('lang' => 'SITE_HOME_URL',			'validate' => 'url',	'type' => 'url:40:255', 'explain' => true),  						'site_home_text'		=> array('lang' => 'SITE_HOME_TEXT',		'validate' => 'string',	'type' => 'text:40:255', 'explain' => true),  						'board_index_text'		=> array('lang' => 'BOARD_INDEX_TEXT',		'validate' => 'string',	'type' => 'text:40:255', 'explain' => true),  						'board_disable'			=> array('lang' => 'DISABLE_BOARD',			'validate' => 'bool',	'type' => 'custom', 'method' => 'board_disable', 'explain' => true), @@ -122,6 +125,7 @@ class acp_board  				$avatar_vars = array();  				foreach ($avatar_drivers as $current_driver)  				{ +					/** @var \phpbb\avatar\driver\driver_interface $driver */  					$driver = $phpbb_avatar_manager->get_driver($current_driver, false);  					/* @@ -446,6 +450,7 @@ class acp_board  						'email_enable'			=> array('lang' => 'ENABLE_EMAIL',			'validate' => 'bool',	'type' => 'radio:enabled_disabled', 'explain' => true),  						'board_email_form'		=> array('lang' => 'BOARD_EMAIL_FORM',		'validate' => 'bool',	'type' => 'radio:enabled_disabled', 'explain' => true),  						'email_package_size'	=> array('lang' => 'EMAIL_PACKAGE_SIZE',	'validate' => 'int:0',	'type' => 'number:0:99999', 'explain' => true), +						'email_max_chunk_size'	=> array('lang' => 'EMAIL_MAX_CHUNK_SIZE',	'validate' => 'int:1:99999',	'type' => 'number:1:99999', 'explain' => true),  						'board_contact'			=> array('lang' => 'CONTACT_EMAIL',			'validate' => 'email',	'type' => 'email:25:100', 'explain' => true),  						'board_contact_name'	=> array('lang' => 'CONTACT_EMAIL_NAME',	'validate' => 'string',	'type' => 'text:25:50', 'explain' => true),  						'board_email'			=> array('lang' => 'ADMIN_EMAIL',			'validate' => 'email',	'type' => 'email:25:100', 'explain' => true), @@ -730,7 +735,7 @@ class acp_board  			$template->assign_block_vars('options', array(  				'KEY'			=> $config_key,  				'TITLE'			=> (isset($user->lang[$vars['lang']])) ? $user->lang[$vars['lang']] : $vars['lang'], -				'S_EXPLAIN'		=> $vars['explain'], +				'S_EXPLAIN'		=> $vars['explain'] && !empty($l_explain),  				'TITLE_EXPLAIN'	=> $l_explain,  				'CONTENT'		=> $content,  				) diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index 05f2b98524..677fce7217 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -58,7 +58,6 @@ class acp_database  						$type	= $request->variable('type', '');  						$table	= array_intersect($this->db_tools->sql_list_tables(), $request->variable('table', array('')));  						$format	= $request->variable('method', ''); -						$where	= $request->variable('where', '');  						if (!count($table))  						{ @@ -70,12 +69,9 @@ class acp_database  							trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);  						} -						$store = $structure = $schema_data = false; - -						if ($where == 'store') -						{ -							$store = true; -						} +						$store = true; +						$structure = false; +						$schema_data = false;  						if ($type == 'full' || $type == 'structure')  						{ @@ -216,7 +212,7 @@ class acp_database  						}  						else if (confirm_box(true))  						{ -							switch ($backup_info['extensions']) +							switch ($backup_info['extension'])  							{  								case 'sql':  									$fp = fopen($backup_info['file_name'], 'rb'); diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index be5a7a2f26..22c775b7c3 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -986,6 +986,23 @@ class acp_forums  			$errors[] = $user->lang['FORUM_NAME_EMPTY'];  		} +		/** +		 * Replace Emojis and other 4bit UTF-8 chars not allowed by MySql to UCR / NCR. +		 * Using their Numeric Character Reference's Hexadecimal notation. +		 */ +		$forum_data_ary['forum_name'] = utf8_encode_ucr($forum_data_ary['forum_name']); + +		/** +		 * This should never happen again. +		 * Leaving the fallback here just in case there will be the need of it. +		 */ +		if (preg_match_all('/[\x{10000}-\x{10FFFF}]/u', $forum_data_ary['forum_name'], $matches)) +		{ +			$character_list = implode('<br>', $matches[0]); + +			$errors[] = $user->lang('FORUM_NAME_EMOJI', $character_list); +		} +  		if (utf8_strlen($forum_data_ary['forum_desc']) > 4000)  		{  			$errors[] = $user->lang['FORUM_DESC_TOO_LONG']; @@ -1416,8 +1433,8 @@ class acp_forums  		* This event may be triggered, when a forum is deleted  		*  		* @event core.acp_manage_forums_move_children -		* @var	int		from_id		If of the current parent forum -		* @var	int		to_id		If of the new parent forum +		* @var	int		from_id		Id of the current parent forum +		* @var	int		to_id		Id of the new parent forum  		* @var	array	errors		Array of errors, should be strings and not  		*							language key.  		* @since 3.1.0-a1 @@ -1522,8 +1539,8 @@ class acp_forums  		* Event when we move content from one forum to another  		*  		* @event core.acp_manage_forums_move_content -		* @var	int		from_id		If of the current parent forum -		* @var	int		to_id		If of the new parent forum +		* @var	int		from_id		Id of the current parent forum +		* @var	int		to_id		Id of the new parent forum  		* @var	bool	sync		Shall we sync the "to"-forum's data  		* @var	array	errors		Array of errors, should be strings and not  		*							language key. If this array is not empty, @@ -1569,6 +1586,19 @@ class acp_forums  			$db->sql_query($sql);  		} +		/** +		 * Event when content has been moved from one forum to another +		 * +		 * @event core.acp_manage_forums_move_content_after +		 * @var	int		from_id		Id of the current parent forum +		 * @var	int		to_id		Id of the new parent forum +		 * @var	bool	sync		Shall we sync the "to"-forum's data +		 * +		 * @since 3.2.9-RC1 +		 */ +		$vars = array('from_id', 'to_id', 'sync'); +		extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_move_content_after', compact($vars))); +  		if ($sync)  		{  			// Delete ghost topics that link back to the same forum then resync counters diff --git a/phpBB/includes/acp/acp_prune.php b/phpBB/includes/acp/acp_prune.php index 3eee4f7922..c5f7789de8 100644 --- a/phpBB/includes/acp/acp_prune.php +++ b/phpBB/includes/acp/acp_prune.php @@ -537,6 +537,7 @@ class acp_prune  					AND ug.user_id <> ' . ANONYMOUS . '  					AND u.user_type <> ' . USER_FOUNDER . '  					AND ug.user_pending = 0 +					AND ug.group_leader = 0  					AND u.user_id = ug.user_id  					' . (!empty($user_ids) ? ' AND ' . $db->sql_in_set('ug.user_id', $user_ids) : '');  			$result = $db->sql_query($sql); diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index 1bf5a3c6a8..87c8d88f52 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -259,6 +259,19 @@ class acp_styles  		// Get list of styles to uninstall  		$ids = $this->request_vars('id', 0, true); +		// Don't remove prosilver, you can still deactivate it. +		$sql = 'SELECT style_id +			FROM ' . STYLES_TABLE . " +			WHERE style_name = '" . $this->db->sql_escape('prosilver') . "'"; +		$result = $this->db->sql_query($sql); +		$prosilver_id = (int) $this->db->sql_fetchfield('style_id'); +		$this->db->sql_freeresult($result); + +		if ($prosilver_id && in_array($prosilver_id, $ids)) +		{ +			trigger_error($this->user->lang('UNINSTALL_PROSILVER') . adm_back_link($this->u_action), E_USER_WARNING); +		} +  		// Check if confirmation box was submitted  		if (confirm_box(true))  		{ @@ -998,11 +1011,14 @@ class acp_styles  				'L_ACTION'	=> $this->user->lang['EXPORT']  			); */ -			// Uninstall -			$actions[] = array( -				'U_ACTION'	=> $this->u_action . '&action=uninstall&hash=' . generate_link_hash('uninstall') . '&id=' . $style['style_id'], -				'L_ACTION'	=> $this->user->lang['STYLE_UNINSTALL'] -			); +			if ($style['style_name'] !== 'prosilver') +			{ +				// Uninstall +				$actions[] = array( +					'U_ACTION'	=> $this->u_action . '&action=uninstall&hash=' . generate_link_hash('uninstall') . '&id=' . $style['style_id'], +					'L_ACTION'	=> $this->user->lang['STYLE_UNINSTALL'] +				); +			}  			// Preview  			$actions[] = array( @@ -1123,7 +1139,14 @@ class acp_styles  	*/  	protected function read_style_cfg($dir)  	{ +		// This should never happen, we give them a red warning because of its relevance. +		if (!file_exists($this->styles_path . $dir . '/style.cfg')) +		{ +			trigger_error($this->user->lang('NO_STYLE_CFG', $dir), E_USER_WARNING); +		} +  		static $required = array('name', 'phpbb_version', 'copyright'); +  		$cfg = parse_cfg_file($this->styles_path . $dir . '/style.cfg');  		// Check if it is a valid file diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php index 9124a59ef2..fa3afa6ce3 100644 --- a/phpBB/includes/acp/acp_update.php +++ b/phpBB/includes/acp/acp_update.php @@ -59,17 +59,19 @@ class acp_update  		$update_link = $phpbb_root_path . 'install/app.' . $phpEx; -		$template->assign_vars(array( -			'S_UP_TO_DATE'			=> empty($updates_available), -			'U_ACTION'				=> $this->u_action, -			'U_VERSIONCHECK_FORCE'	=> append_sid($this->u_action . '&versioncheck_force=1'), +		$template_ary = [ +			'S_UP_TO_DATE'				=> empty($updates_available), +			'U_ACTION'					=> $this->u_action, +			'U_VERSIONCHECK_FORCE'		=> append_sid($this->u_action . '&versioncheck_force=1'), -			'CURRENT_VERSION'		=> $config['version'], +			'CURRENT_VERSION'			=> $config['version'], -			'UPDATE_INSTRUCTIONS'	=> sprintf($user->lang['UPDATE_INSTRUCTIONS'], $update_link), +			'UPDATE_INSTRUCTIONS'		=> $user->lang('UPDATE_INSTRUCTIONS', $update_link),  			'S_VERSION_UPGRADEABLE'		=> !empty($upgrades_available),  			'UPGRADE_INSTRUCTIONS'		=> !empty($upgrades_available) ? $user->lang('UPGRADE_INSTRUCTIONS', $upgrades_available['current'], $upgrades_available['announcement']) : false, -		)); +		]; + +		$template->assign_vars($template_ary);  		// Incomplete update?  		if (phpbb_version_compare($config['version'], PHPBB_VERSION, '<')) diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 2d1eaadfae..fd4b5e8c24 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -855,7 +855,7 @@ class acp_users  						$check_ary += array(  							'username'			=> array(  								array('string', false, $config['min_name_chars'], $config['max_name_chars']), -								array('username', $user_row['username']) +								array('username', $user_row['username'], true)  							),  						);  					} diff --git a/phpBB/includes/compatibility_globals.php b/phpBB/includes/compatibility_globals.php index 0f403896a7..ad394e3782 100644 --- a/phpBB/includes/compatibility_globals.php +++ b/phpBB/includes/compatibility_globals.php @@ -29,7 +29,7 @@ function register_compatibility_globals()  {  	global $phpbb_container; -	global $cache, $phpbb_dispatcher, $request, $user, $auth, $db, $config, $phpbb_log; +	global $cache, $phpbb_dispatcher, $request, $user, $auth, $db, $config, $language, $phpbb_log;  	global $symfony_request, $phpbb_filesystem, $phpbb_path_helper, $phpbb_extension_manager, $template;  	// set up caching @@ -48,6 +48,9 @@ function register_compatibility_globals()  	/* @var $user \phpbb\user */  	$user = $phpbb_container->get('user'); +	/* @var \phpbb\language\language $language */ +	$language = $phpbb_container->get('language'); +  	/* @var $auth \phpbb\auth\auth */  	$auth = $phpbb_container->get('auth'); diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index d80f348ac5..a2e7d92f7d 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -28,7 +28,7 @@ if (!defined('IN_PHPBB'))  */  // phpBB Version -@define('PHPBB_VERSION', '3.2.6-dev'); +@define('PHPBB_VERSION', '3.2.9-dev');  // QA-related  // define('PHPBB_QA', 1); diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index e2ea7ad232..c9f589c174 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -1843,27 +1843,6 @@ function redirect($url, $return = false, $disable_cd_check = false)  		garbage_collection();  	} -	// Redirect via an HTML form for PITA webservers -	if (@preg_match('#WebSTAR|Xitami#', getenv('SERVER_SOFTWARE'))) -	{ -		header('Refresh: 0; URL=' . $url); - -		echo '<!DOCTYPE html>'; -		echo '<html dir="' . $user->lang['DIRECTION'] . '" lang="' . $user->lang['USER_LANG'] . '">'; -		echo '<head>'; -		echo '<meta charset="utf-8">'; -		echo '<meta http-equiv="X-UA-Compatible" content="IE=edge">'; -		echo '<meta http-equiv="refresh" content="0; url=' . str_replace('&', '&', $url) . '" />'; -		echo '<title>' . $user->lang['REDIRECT'] . '</title>'; -		echo '</head>'; -		echo '<body>'; -		echo '<div style="text-align: center;">' . sprintf($user->lang['URL_REDIRECT'], '<a href="' . str_replace('&', '&', $url) . '">', '</a>') . '</div>'; -		echo '</body>'; -		echo '</html>'; - -		exit; -	} -  	// Behave as per HTTP/1.1 spec for others  	header('Location: ' . $url);  	exit; @@ -2143,25 +2122,29 @@ function check_form_key($form_name, $timespan = false)  /**  * Build Confirm box  * @param boolean $check True for checking if confirmed (without any additional parameters) and false for displaying the confirm box -* @param string $title Title/Message used for confirm box. +* @param string|array $title Title/Message used for confirm box.  *		message text is _CONFIRM appended to title.  *		If title cannot be found in user->lang a default one is displayed  *		If title_CONFIRM cannot be found in user->lang the text given is used. +*       If title is an array, the first array value is used as explained per above, +*       all other array values are sent as parameters to the language function.  * @param string $hidden Hidden variables  * @param string $html_body Template used for confirm box  * @param string $u_action Custom form action +* +* @return bool True if confirmation was successful, false if not  */  function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_body.html', $u_action = '')  {  	global $user, $template, $db, $request; -	global $config, $phpbb_path_helper; +	global $config, $language, $phpbb_path_helper, $phpbb_dispatcher;  	if (isset($_POST['cancel']))  	{  		return false;  	} -	$confirm = ($user->lang['YES'] === $request->variable('confirm', '', true, \phpbb\request\request_interface::POST)); +	$confirm = ($language->lang('YES') === $request->variable('confirm', '', true, \phpbb\request\request_interface::POST));  	if ($check && $confirm)  	{ @@ -2195,13 +2178,27 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo  	// generate activation key  	$confirm_key = gen_rand_string(10); +	// generate language strings +	if (is_array($title)) +	{ +		$key = array_shift($title); +		$count = array_shift($title); +		$confirm_title =  $language->is_set($key) ? $language->lang($key, $count, $title) : $language->lang('CONFIRM'); +		$confirm_text = $language->is_set($key . '_CONFIRM') ? $language->lang($key . '_CONFIRM', $count, $title) : $key; +	} +	else +	{ +		$confirm_title = $language->is_set($title) ? $language->lang($title) : $language->lang('CONFIRM'); +		$confirm_text = $language->is_set($title . '_CONFIRM') ? $language->lang($title . '_CONFIRM') : $title; +	} +  	if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])  	{ -		adm_page_header((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]); +		adm_page_header($confirm_title);  	}  	else  	{ -		page_header((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]); +		page_header($confirm_title);  	}  	$template->set_filenames(array( @@ -2221,10 +2218,10 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo  	$u_action .= ((strpos($u_action, '?') === false) ? '?' : '&') . 'confirm_key=' . $confirm_key;  	$template->assign_vars(array( -		'MESSAGE_TITLE'		=> (!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang($title, 1), -		'MESSAGE_TEXT'		=> (!isset($user->lang[$title . '_CONFIRM'])) ? $title : $user->lang[$title . '_CONFIRM'], +		'MESSAGE_TITLE'		=> $confirm_title, +		'MESSAGE_TEXT'		=> $confirm_text, -		'YES_VALUE'			=> $user->lang['YES'], +		'YES_VALUE'			=> $language->lang('YES'),  		'S_CONFIRM_ACTION'	=> $u_action,  		'S_HIDDEN_FIELDS'	=> $hidden . $s_hidden_fields,  		'S_AJAX_REQUEST'	=> $request->is_ajax(), @@ -2237,16 +2234,36 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo  	if ($request->is_ajax())  	{  		$u_action .= '&confirm_uid=' . $user->data['user_id'] . '&sess=' . $user->session_id . '&sid=' . $user->session_id; -		$json_response = new \phpbb\json_response; -		$json_response->send(array( +		$data = array(  			'MESSAGE_BODY'		=> $template->assign_display('body'), -			'MESSAGE_TITLE'		=> (!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title], -			'MESSAGE_TEXT'		=> (!isset($user->lang[$title . '_CONFIRM'])) ? $title : $user->lang[$title . '_CONFIRM'], +			'MESSAGE_TITLE'		=> $confirm_title, +			'MESSAGE_TEXT'		=> $confirm_text, -			'YES_VALUE'			=> $user->lang['YES'], +			'YES_VALUE'			=> $language->lang('YES'),  			'S_CONFIRM_ACTION'	=> str_replace('&', '&', $u_action), //inefficient, rewrite whole function  			'S_HIDDEN_FIELDS'	=> $hidden . $s_hidden_fields -		)); +		); + +		/** +		 * This event allows an extension to modify the ajax output of confirm box. +		 * +		 * @event core.confirm_box_ajax_before +		 * @var string	u_action		Action of the form +		 * @var array	data			Data to be sent +		 * @var string	hidden			Hidden fields generated by caller +		 * @var string	s_hidden_fields	Hidden fields generated by this function +		 * @since 3.2.8-RC1 +		 */ +		$vars = array( +			'u_action', +			'data', +			'hidden', +			's_hidden_fields', +		); +		extract($phpbb_dispatcher->trigger_event('core.confirm_box_ajax_before', compact($vars))); + +		$json_response = new \phpbb\json_response; +		$json_response->send($data);  	}  	if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin']) @@ -2257,6 +2274,8 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo  	{  		page_footer();  	} + +	exit; // unreachable, page_footer() above will call exit()  }  /** @@ -2268,6 +2287,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa  	global $request, $phpbb_container, $phpbb_dispatcher, $phpbb_log;  	$err = ''; +	$form_name = 'login';  	// Make sure user->setup() has been called  	if (!$user->is_setup()) @@ -2343,8 +2363,19 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa  			trigger_error('NO_AUTH_ADMIN_USER_DIFFER');  		} -		// If authentication is successful we redirect user to previous page -		$result = $auth->login($username, $password, $autologin, $viewonline, $admin); +		// Check form key +		if ($password && !defined('IN_CHECK_BAN') && !check_form_key($form_name)) +		{ +			$result = array( +				'status' => false, +				'error_msg' => 'FORM_INVALID', +			); +		} +		else +		{ +			// If authentication is successful we redirect user to previous page +			$result = $auth->login($username, $password, $autologin, $viewonline, $admin); +		}  		// If admin authentication and login, we will log if it was a success or not...  		// We also break the operation on the first non-success login - it could be argued that the user already knows @@ -4094,9 +4125,9 @@ function phpbb_get_user_avatar($user_row, $alt = 'USER_AVATAR', $ignore_config =  *  * @return string Avatar html  */ -function phpbb_get_group_avatar($user_row, $alt = 'GROUP_AVATAR', $ignore_config = false, $lazy = false) +function phpbb_get_group_avatar($group_row, $alt = 'GROUP_AVATAR', $ignore_config = false, $lazy = false)  { -	$row = \phpbb\avatar\manager::clean_row($user_row, 'group'); +	$row = \phpbb\avatar\manager::clean_row($group_row, 'group');  	return phpbb_get_avatar($row, $alt, $ignore_config, $lazy);  } @@ -4401,6 +4432,23 @@ function page_header($page_title = '', $display_online_list = false, $item_id =  	$controller_helper = $phpbb_container->get('controller.helper');  	$notification_mark_hash = generate_link_hash('mark_all_notifications_read'); +	$s_login_redirect = build_hidden_fields(array('redirect' => $phpbb_path_helper->remove_web_root_path(build_url()))); + +	// Add form token for login box, in case page is presenting a login form. +	add_form_key('login', '_LOGIN'); + +	/** +	 * Workaround for missing template variable in pre phpBB 3.2.6 styles. +	 * @deprecated 3.2.7 (To be removed: 3.3.0-a1) +	 */ +	$form_token_login = $template->retrieve_var('S_FORM_TOKEN_LOGIN'); +	if (!empty($form_token_login)) +	{ +		$s_login_redirect .= $form_token_login; +		// Remove S_FORM_TOKEN_LOGIN as it's already appended to S_LOGIN_REDIRECT +		$template->assign_var('S_FORM_TOKEN_LOGIN', ''); +	} +  	// The following assigns all _common_ variables that may be used at any point in a template.  	$template->assign_vars(array(  		'SITENAME'						=> $config['sitename'], @@ -4490,7 +4538,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id =  		'S_TOPIC_ID'			=> $topic_id,  		'S_LOGIN_ACTION'		=> ((!defined('ADMIN_START')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') : append_sid("{$phpbb_admin_path}index.$phpEx", false, true, $user->session_id)), -		'S_LOGIN_REDIRECT'		=> build_hidden_fields(array('redirect' => $phpbb_path_helper->remove_web_root_path(build_url()))), +		'S_LOGIN_REDIRECT'		=> $s_login_redirect,  		'S_ENABLE_FEEDS'			=> ($config['feed_enable']) ? true : false,  		'S_ENABLE_FEEDS_OVERALL'	=> ($config['feed_overall']) ? true : false, @@ -4541,12 +4589,13 @@ function page_header($page_title = '', $display_online_list = false, $item_id =  	if ($send_headers)  	{ -		// An array of http headers that phpbb will set. The following event may override these. +		// An array of http headers that phpBB will set. The following event may override these.  		$http_headers += array(  			// application/xhtml+xml not used because of IE  			'Content-type' => 'text/html; charset=UTF-8',  			'Cache-Control' => 'private, no-cache="set-cookie"',  			'Expires' => gmdate('D, d M Y H:i:s', time()) . ' GMT', +			'Referrer-Policy' => 'strict-origin-when-cross-origin',  		);  		if (!empty($user->data['is_bot']))  		{ diff --git a/phpBB/includes/functions_acp.php b/phpBB/includes/functions_acp.php index 9b7491305c..a2014a7d5b 100644 --- a/phpBB/includes/functions_acp.php +++ b/phpBB/includes/functions_acp.php @@ -112,12 +112,13 @@ function adm_page_header($page_title)  		'CONTAINER_EXCEPTION'	=> $phpbb_container->hasParameter('container_exception') ? $phpbb_container->getParameter('container_exception') : false,  	)); -	// An array of http headers that phpbb will set. The following event may override these. +	// An array of http headers that phpBB will set. The following event may override these.  	$http_headers = array(  		// application/xhtml+xml not used because of IE  		'Content-type' => 'text/html; charset=UTF-8',  		'Cache-Control' => 'private, no-cache="set-cookie"',  		'Expires' => gmdate('D, d M Y H:i:s', time()) . ' GMT', +		'Referrer-Policy' => 'strict-origin-when-cross-origin',  	);  	/** @@ -419,7 +420,7 @@ function build_cfg_template($tpl_type, $key, &$new_ary, $config_key, $vars)  */  function validate_config_vars($config_vars, &$cfg_array, &$error)  { -	global $phpbb_root_path, $user, $phpbb_dispatcher, $phpbb_filesystem; +	global $phpbb_root_path, $user, $phpbb_dispatcher, $phpbb_filesystem, $language;  	$type	= 0;  	$min	= 1; @@ -442,6 +443,16 @@ function validate_config_vars($config_vars, &$cfg_array, &$error)  		// Validate a bit. ;) (0 = type, 1 = min, 2= max)  		switch ($validator[$type])  		{ +			case 'url': +				$cfg_array[$config_name] = trim($cfg_array[$config_name]); + +				if (!empty($cfg_array[$config_name]) && !preg_match('#^' . get_preg_expression('url') . '$#iu', $cfg_array[$config_name])) +				{ +					$error[] = $language->lang('URL_INVALID', $language->lang($config_definition['lang'])); +				} + +			// no break here +  			case 'string':  				$length = utf8_strlen($cfg_array[$config_name]); diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index c19d48b0be..cc82fdbda3 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -543,6 +543,20 @@ function move_topics($topic_ids, $forum_id, $auto_sync = true)  		$topic_ids = array($topic_ids);  	} +	/** +	 * Perform additional actions before topics move +	 * +	 * @event core.move_topics_before +	 * @var	array	topic_ids	Array of the moved topic ids +	 * @var	string	forum_id	The forum id from where the topics are moved +	 * @since 3.2.9-RC1 +	 */ +	$vars = array( +		'topic_ids', +		'forum_id', +	); +	extract($phpbb_dispatcher->trigger_event('core.move_topics_before', compact($vars))); +  	$sql = 'DELETE FROM ' . TOPICS_TABLE . '  		WHERE ' . $db->sql_in_set('topic_moved_id', $topic_ids) . '  			AND forum_id = ' . $forum_id; @@ -593,6 +607,22 @@ function move_topics($topic_ids, $forum_id, $auto_sync = true)  	}  	unset($table_ary); +	/** +	 * Perform additional actions after topics move +	 * +	 * @event core.move_topics_after +	 * @var	array	topic_ids	Array of the moved topic ids +	 * @var	string	forum_id	The forum id from where the topics were moved +	 * @var	array	forum_ids	Array of the forums where the topics were moved (includes also forum_id) +	 * @since 3.2.9-RC1 +	 */ +	$vars = array( +		'topic_ids', +		'forum_id', +		'forum_ids', +	); +	extract($phpbb_dispatcher->trigger_event('core.move_topics_after', compact($vars))); +  	if ($auto_sync)  	{  		sync('forum', 'forum_id', $forum_ids, true, true); diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index a15a03f966..2542be5e02 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -1482,6 +1482,8 @@ function truncate_string($string, $max_length = 60, $max_store_length = 255, $al  * Get username details for placing into templates.  * This function caches all modes on first call, except for no_profile and anonymous user - determined by $user_id.  * +* @html Username spans and links +*  * @param string $mode Can be profile (for getting an url to the profile), username (for obtaining the username), colour (for obtaining the user colour), full (for obtaining a html string representing a coloured link to the users profile) or no_profile (the same as full but forcing no profile link)  * @param int $user_id The users id  * @param string $username The users name @@ -1501,6 +1503,7 @@ function get_username_string($mode, $user_id, $username, $username_colour = '',  	{  		global $phpbb_root_path, $phpEx; +		/** @html Username spans and links for usage in the template */  		$_profile_cache['base_url'] = append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u={USER_ID}');  		$_profile_cache['tpl_noprofile'] = '<span class="username">{USERNAME}</span>';  		$_profile_cache['tpl_noprofile_colour'] = '<span style="color: {USERNAME_COLOUR};" class="username-coloured">{USERNAME}</span>'; diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 792467019f..e4adce14fc 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -70,7 +70,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod  				$data = array(  					'NO_UNREAD_POSTS'	=> $user->lang['NO_UNREAD_POSTS'],  					'UNREAD_POSTS'		=> $user->lang['UNREAD_POSTS'], -					'U_MARK_FORUMS'		=> ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}index.$phpEx", 'hash=' . generate_link_hash('global') . '&mark=forums&mark_time=' . time()) : '', +					'U_MARK_FORUMS'		=> ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}index.$phpEx", 'hash=' . generate_link_hash('global') . '&mark=forums&mark_time=' . time(), false) : '',  					'MESSAGE_TITLE'		=> $user->lang['INFORMATION'],  					'MESSAGE_TEXT'		=> $user->lang['FORUMS_MARKED']  				); @@ -355,7 +355,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod  				$data = array(  					'NO_UNREAD_POSTS'	=> $user->lang['NO_UNREAD_POSTS'],  					'UNREAD_POSTS'		=> $user->lang['UNREAD_POSTS'], -					'U_MARK_FORUMS'		=> ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'hash=' . generate_link_hash('global') . '&f=' . $root_data['forum_id'] . '&mark=forums&mark_time=' . time()) : '', +					'U_MARK_FORUMS'		=> ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'hash=' . generate_link_hash('global') . '&f=' . $root_data['forum_id'] . '&mark=forums&mark_time=' . time(), false) : '',  					'MESSAGE_TITLE'		=> $user->lang['INFORMATION'],  					'MESSAGE_TEXT'		=> $user->lang['FORUMS_MARKED']  				); @@ -539,7 +539,8 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod  		{  			if ($row['forum_password_last_post'] === '' && $auth->acl_gets('f_read', 'f_list_topics', $row['forum_id_last_post']))  			{ -				$last_post_subject = censor_text($row['forum_last_post_subject']); +				$last_post_subject = utf8_decode_ncr(censor_text($row['forum_last_post_subject'])); +  				$last_post_subject_truncated = truncate_string($last_post_subject, 30, 255, false, $user->lang['ELLIPSIS']);  			}  			else @@ -547,11 +548,12 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod  				$last_post_subject = $last_post_subject_truncated = '';  			}  			$last_post_time = $user->format_date($row['forum_last_post_time']); +			$last_post_time_rfc3339 = gmdate(DATE_RFC3339, $row['forum_last_post_time']);  			$last_post_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id_last_post'] . '&p=' . $row['forum_last_post_id']) . '#p' . $row['forum_last_post_id'];  		}  		else  		{ -			$last_post_subject = $last_post_time = $last_post_url = $last_post_subject_truncated = ''; +			$last_post_subject = $last_post_time = $last_post_time_rfc3339 = $last_post_url = $last_post_subject_truncated = '';  		}  		// Output moderator listing ... if applicable @@ -622,6 +624,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod  			'LAST_POST_SUBJECT'		=> $last_post_subject,  			'LAST_POST_SUBJECT_TRUNCATED'	=> $last_post_subject_truncated,  			'LAST_POST_TIME'		=> $last_post_time, +			'LAST_POST_TIME_RFC3339'=> $last_post_time_rfc3339,  			'LAST_POSTER'			=> get_username_string('username', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']),  			'LAST_POSTER_COLOUR'	=> get_username_string('colour', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']),  			'LAST_POSTER_FULL'		=> get_username_string('full', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), @@ -1117,7 +1120,6 @@ function display_custom_bbcodes()  			'BBCODE_TAG'		=> $row['bbcode_tag'],  			'BBCODE_TAG_CLEAN'	=> str_replace('=', '-', $row['bbcode_tag']),  			'BBCODE_HELPLINE'	=> $row['bbcode_helpline'], -			'A_BBCODE_HELPLINE'	=> str_replace(array('&', '"', "'", '<', '>'), array('&', '"', "\'", '<', '>'), $row['bbcode_helpline']),  		);  		/** diff --git a/phpBB/includes/functions_download.php b/phpBB/includes/functions_download.php index 7be12baa13..1f409be58c 100644 --- a/phpBB/includes/functions_download.php +++ b/phpBB/includes/functions_download.php @@ -196,7 +196,7 @@ function send_file_to_browser($attachment, $upload_dir, $category)  	}  	// Now the tricky part... let's dance -	header('Cache-Control: public'); +	header('Cache-Control: private');  	// Send out the Headers. Do not set Content-Disposition to inline please, it is a security measure for users using the Internet Explorer.  	header('Content-Type: ' . $attachment['mimetype']); @@ -451,7 +451,7 @@ function set_modified_headers($stamp, $browser)  		{  			send_status_line(304, 'Not Modified');  			// seems that we need those too ... browsers -			header('Cache-Control: public'); +			header('Cache-Control: private');  			header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');  			return true;  		} diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 4f0d40031d..ec297b536a 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -181,10 +181,9 @@ class messenger  	/**  	* Adds X-AntiAbuse headers  	* -	* @param array $config		Configuration array -	* @param user $user			A user object -	* -	* @return null +	* @param \phpbb\config\config	$config		Config object +	* @param \phpbb\user			$user		User object +	* @return void  	*/  	function anti_abuse_headers($config, $user)  	{ @@ -1582,6 +1581,14 @@ class smtp_class  	*/  	protected function starttls()  	{ +		global $config; + +		// allow SMTPS (what was used by phpBB 3.0) if hostname is prefixed with tls:// or ssl:// +		if (strpos($config['smtp_host'], 'tls://') === 0 || strpos($config['smtp_host'], 'ssl://') === 0) +		{ +			return true; +		} +  		if (!function_exists('stream_socket_enable_crypto'))  		{  			return false; @@ -1604,7 +1611,9 @@ class smtp_class  		if (socket_set_blocking($this->socket, 1))  		{ -			$result = stream_socket_enable_crypto($this->socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); +			// https://secure.php.net/manual/en/function.stream-socket-enable-crypto.php#119122 +			$crypto = (phpbb_version_compare(PHP_VERSION, '5.6.7', '<')) ? STREAM_CRYPTO_METHOD_TLS_CLIENT : STREAM_CRYPTO_METHOD_SSLv23_CLIENT; +			$result = stream_socket_enable_crypto($this->socket, true, $crypto);  			socket_set_blocking($this->socket, (int) $stream_meta['blocked']);  		} @@ -1884,14 +1893,21 @@ function mail_encode($str, $eol = "\r\n")  }  /** -* Wrapper for sending out emails with the PHP's mail function -*/ + * Wrapper for sending out emails with the PHP's mail function + */  function phpbb_mail($to, $subject, $msg, $headers, $eol, &$err_msg)  {  	global $config, $phpbb_root_path, $phpEx; -	// We use the EOL character for the OS here because the PHP mail function does not correctly transform line endings. On Windows SMTP is used (SMTP is \r\n), on UNIX a command is used... -	// Reference: http://bugs.php.net/bug.php?id=15841 +	// Convert Numeric Character References to UTF-8 chars (ie. Emojis) +	$subject = utf8_decode_ncr($subject); +	$msg = utf8_decode_ncr($msg); + +	/** +	 * We use the EOL character for the OS here because the PHP mail function does not correctly transform line endings. +	 * On Windows SMTP is used (SMTP is \r\n), on UNIX a command is used... +	 * Reference: http://bugs.php.net/bug.php?id=15841 +	 */  	$headers = implode($eol, $headers);  	if (!class_exists('\phpbb\error_collector')) @@ -1902,10 +1918,14 @@ function phpbb_mail($to, $subject, $msg, $headers, $eol, &$err_msg)  	$collector = new \phpbb\error_collector;  	$collector->install(); -	// On some PHP Versions mail() *may* fail if there are newlines within the subject. -	// Newlines are used as a delimiter for lines in mail_encode() according to RFC 2045 section 6.8. -	// Because PHP can't decide what is wanted we revert back to the non-RFC-compliant way of separating by one space (Use '' as parameter to mail_encode() results in SPACE used) +	/** +	 * On some PHP Versions mail() *may* fail if there are newlines within the subject. +	 * Newlines are used as a delimiter for lines in mail_encode() according to RFC 2045 section 6.8. +	 * Because PHP can't decide what is wanted we revert back to the non-RFC-compliant way of separating by one space +	 * (Use '' as parameter to mail_encode() results in SPACE used) +	 */  	$additional_parameters = $config['email_force_sender'] ? '-f' . $config['board_email'] : ''; +  	$result = mail($to, mail_encode($subject, ''), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $headers, $additional_parameters);  	$collector->uninstall(); diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 3640f543d9..1956f65666 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -52,9 +52,29 @@ function generate_smilies($mode, $forum_id)  		page_header($user->lang['SMILIES']); -		$sql = 'SELECT COUNT(smiley_id) AS item_count -			FROM ' . SMILIES_TABLE . ' -			GROUP BY smiley_url'; +		$sql_ary = [ +			'SELECT'	=> 'COUNT(s.smiley_id) AS item_count', +			'FROM'		=> [ +				SMILIES_TABLE => 's', +			], +			'GROUP_BY'	=> 's.smiley_url', +		]; + +		/** +		* Modify SQL query that fetches the total number of smilies in window mode +		* +		* @event core.generate_smilies_count_sql_before +		* @var int		forum_id	Forum where smilies are generated +		* @var array	sql_ary		Array with the SQL query +		* @since 3.2.9-RC1 +		*/ +		$vars = [ +			'forum_id', +			'sql_ary', +		]; +		extract($phpbb_dispatcher->trigger_event('core.generate_smilies_count_sql_before', compact($vars))); + +		$sql = $db->sql_build_query('SELECT', $sql_ary);  		$result = $db->sql_query($sql, 3600);  		$smiley_count = 0; @@ -114,6 +134,22 @@ function generate_smilies($mode, $forum_id)  	}  	$db->sql_freeresult($result); +	/** +	* Modify smilies before they are assigned to the template +	* +	* @event core.generate_smilies_modify_rowset +	* @var string	mode		Smiley mode, either window or inline +	* @var int		forum_id	Forum where smilies are generated +	* @var array	smilies		Smiley rows fetched from the database +	* @since 3.2.9-RC1 +	*/ +	$vars = [ +		'mode', +		'forum_id', +		'smilies', +	]; +	extract($phpbb_dispatcher->trigger_event('core.generate_smilies_modify_rowset', compact($vars))); +  	if (count($smilies))  	{  		$root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_path_helper->get_web_root_path(); @@ -978,6 +1014,30 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id  			AND u.user_id = p.poster_id',  	); +	/** +	* Event to modify the SQL query for topic reviews +	* +	* @event core.topic_review_modify_sql_ary +	* @var	int		topic_id			The topic ID that is being reviewed +	* @var	int		forum_id			The topic's forum ID +	* @var	string	mode				The topic review mode +	* @var	int		cur_post_id			Post offset ID +	* @var	bool	show_quote_button	Flag indicating if the quote button should be displayed +	* @var	array	post_list			Array with the post IDs +	* @var	array	sql_ary				Array with the SQL query +	* @since 3.2.8-RC1 +	*/ +	$vars = array( +		'topic_id', +		'forum_id', +		'mode', +		'cur_post_id', +		'show_quote_button', +		'post_list', +		'sql_ary', +	); +	extract($phpbb_dispatcher->trigger_event('core.topic_review_modify_sql_ary', compact($vars))); +  	$sql = $db->sql_build_query('SELECT', $sql_ary);  	$result = $db->sql_query($sql); @@ -1284,6 +1344,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $  				delete_topics('topic_id', array($topic_id), false);  				$phpbb_content_visibility->remove_topic_from_statistic($data, $sql_data); +				$config->increment('num_posts', -1, false);  				$update_sql = update_post_information('forum', $forum_id, true);  				if (count($update_sql)) @@ -2054,6 +2115,11 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data  				continue;  			} +			if (preg_match('/[\x{10000}-\x{10FFFF}]/u', $attach_row['attach_comment'])) +			{ +				trigger_error('ATTACH_COMMENT_NO_EMOJIS'); +			} +  			if (!$attach_row['is_orphan'])  			{  				// update entry in db if attachment already stored in db and filespace diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 444bf2c7e0..f07512d623 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -490,7 +490,7 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false)  				'bcc'				=> explode(':', $row['bcc_address']),  				'friend'			=> (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['friend'] : 0,  				'foe'				=> (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['foe'] : 0, -				'user_in_group'		=> array($user->data['group_id']), +				'user_in_group'		=> $user->data['group_id'],  				'author_in_group'	=> array())  			); @@ -1966,7 +1966,7 @@ function submit_pm($mode, $subject, &$data_ary, $put_in_outbox = true)  */  function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode = false)  { -	global $db, $user, $template, $phpbb_root_path, $phpEx, $auth; +	global $db, $user, $template, $phpbb_root_path, $phpEx, $auth, $phpbb_dispatcher;  	// Select all receipts and the author from the pm we currently view, to only display their pm-history  	$sql = 'SELECT author_id, user_id @@ -1985,9 +1985,7 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode  	$recipients = array_unique($recipients);  	// Get History Messages (could be newer) -	$sql = 'SELECT t.*, p.*, u.* -		FROM ' . PRIVMSGS_TABLE . ' p, ' . PRIVMSGS_TO_TABLE . ' t, ' . USERS_TABLE . ' u -		WHERE t.msg_id = p.msg_id +	$sql_where = 't.msg_id = p.msg_id  			AND p.author_id = u.user_id  			AND t.folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ')  			AND ' . $db->sql_in_set('t.author_id', $recipients, false, true) . " @@ -1998,13 +1996,37 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode  	if (!$message_row['root_level'])  	{ -		$sql .= " AND (p.root_level = $msg_id OR (p.root_level = 0 AND p.msg_id = $msg_id))"; +		$sql_where .= " AND (p.root_level = $msg_id OR (p.root_level = 0 AND p.msg_id = $msg_id))";  	}  	else  	{ -		$sql .= " AND (p.root_level = " . $message_row['root_level'] . ' OR p.msg_id = ' . $message_row['root_level'] . ')'; +		$sql_where .= " AND (p.root_level = " . $message_row['root_level'] . ' OR p.msg_id = ' . $message_row['root_level'] . ')';  	} -	$sql .= ' ORDER BY p.message_time DESC'; + +	$sql_ary = array( +		'SELECT'	=> 't.*, p.*, u.*', +		'FROM'		=> array( +			PRIVMSGS_TABLE		=> 'p', +			PRIVMSGS_TO_TABLE	=> 't', +			USERS_TABLE			=> 'u' +		), +		'LEFT_JOIN'	=> array(), +		'WHERE'		=> $sql_where, +		'ORDER_BY'	=> 'p.message_time DESC', +	); + +	/** +	* Event to modify the SQL query before the message history in private message is queried +	* +	* @event core.message_history_modify_sql_ary +	* @var	array	sql_ary		The SQL array to get the data of the message history in private message +	* @since 3.2.8-RC1 +	*/ +	$vars = array('sql_ary'); +	extract($phpbb_dispatcher->trigger_event('core.message_history_modify_sql_ary', compact($vars))); + +	$sql = $db->sql_build_query('SELECT', $sql_ary); +	unset($sql_ary);  	$result = $db->sql_query($sql);  	$row = $db->sql_fetchrow($result); @@ -2087,7 +2109,7 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode  			$previous_history_pm = $prev_id;  		} -		$template->assign_block_vars('history_row', array( +		$template_vars = array(  			'MESSAGE_AUTHOR_QUOTE'		=> (($decoded_message) ? addslashes(get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username'])) : ''),  			'MESSAGE_AUTHOR_FULL'		=> get_username_string('full', $author_id, $row['username'], $row['user_colour'], $row['username']),  			'MESSAGE_AUTHOR_COLOUR'		=> get_username_string('colour', $author_id, $row['username'], $row['user_colour'], $row['username']), @@ -2109,8 +2131,25 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode  			'USER_ID'			=> $row['user_id'],  			'U_VIEW_MESSAGE'	=> "$url&f=$folder_id&p=" . $row['msg_id'],  			'U_QUOTE'			=> (!$in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=quote&f=" . $folder_id . "&p=" . $row['msg_id'] : '', -			'U_POST_REPLY_PM'	=> ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $row['msg_id'] : '') +			'U_POST_REPLY_PM'	=> ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $row['msg_id'] : '' +		); + +		/** +		* Modify the template vars for displaying the message history in private message +		* +		* @event core.message_history_modify_template_vars +		* @var array	template_vars		Array containing the query +		* @var array	row					Array containing the action user row +		* @since 3.2.8-RC1 +		*/ +		$vars = array( +			'template_vars', +			'row',  		); +		extract($phpbb_dispatcher->trigger_event('core.message_history_modify_template_vars', compact($vars))); + +		$template->assign_block_vars('history_row', $template_vars); +  		unset($rowset[$i]);  		$prev_id = $id;  	} diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index d86470adf9..e0b6a9d0c6 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -1732,7 +1732,7 @@ function phpbb_validate_timezone($timezone)   * @return mixed							Either false if validation succeeded or a string which will be   *											used as the error message (with the variable name appended)   */ -function validate_username($username, $allowed_username = false) +function validate_username($username, $allowed_username = false, $allow_all_names = false)  {  	global $config, $db, $user, $cache; @@ -1815,13 +1815,16 @@ function validate_username($username, $allowed_username = false)  		return 'USERNAME_TAKEN';  	} -	$bad_usernames = $cache->obtain_disallowed_usernames(); - -	foreach ($bad_usernames as $bad_username) +	if (!$allow_all_names)  	{ -		if (preg_match('#^' . $bad_username . '$#', $clean_username)) +		$bad_usernames = $cache->obtain_disallowed_usernames(); + +		foreach ($bad_usernames as $bad_username)  		{ -			return 'USERNAME_DISALLOWED'; +			if (preg_match('#^' . $bad_username . '$#', $clean_username)) +			{ +				return 'USERNAME_DISALLOWED'; +			}  		}  	} @@ -1942,9 +1945,10 @@ function validate_user_email($email, $allowed_email = false)  		return $validate_email;  	} -	if (($ban_reason = $user->check_ban(false, false, $email, true)) !== false) +	$ban = $user->check_ban(false, false, $email, true); +	if (!empty($ban))  	{ -		return ($ban_reason === true) ? 'EMAIL_BANNED' : $ban_reason; +		return !empty($ban['ban_give_reason']) ? $ban['ban_give_reason'] : 'EMAIL_BANNED';  	}  	if (!$config['allow_emailreuse']) diff --git a/phpBB/includes/mcp/mcp_ban.php b/phpBB/includes/mcp/mcp_ban.php index 8797f06db8..6f748f5433 100644 --- a/phpBB/includes/mcp/mcp_ban.php +++ b/phpBB/includes/mcp/mcp_ban.php @@ -269,7 +269,7 @@ class mcp_ban  		}  		else if ($post_id)  		{ -			$post_info = phpbb_get_post_data($post_id, 'm_ban'); +			$post_info = phpbb_get_post_data(array($post_id), 'm_ban');  			if (count($post_info) && !empty($post_info[$post_id]))  			{ diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index 065e9bba12..744eaebd7d 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -41,6 +41,22 @@ class mcp_main  		$quickmod = ($mode == 'quickmod') ? true : false; +		/** +		* Event to perform additional actions before an MCP action is executed. +		* +		* @event core.mcp_main_before +		* @var	string	action				The action that is about to be performed +		* @var	string	mode				The mode in which the MCP is accessed, e.g. front, forum_view, topic_view, post_details, quickmod +		* @var	boolean	quickmod			Whether or not the action is performed via QuickMod +		* @since 3.2.8-RC1 +		*/ +		$vars = [ +			'action', +			'mode', +			'quickmod', +		]; +		extract($phpbb_dispatcher->trigger_event('core.mcp_main_before', compact($vars))); +  		switch ($action)  		{  			case 'lock': @@ -378,7 +394,7 @@ function lock_unlock($action, $ids)  */  function change_topic_type($action, $topic_ids)  { -	global $user, $db, $request, $phpbb_log; +	global $user, $db, $request, $phpbb_log, $phpbb_dispatcher;  	switch ($action)  	{ @@ -974,10 +990,11 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = ''  			'DELETE_TOPIC_PERMANENTLY_EXPLAIN'	=> $user->lang('DELETE_TOPIC_PERMANENTLY', count($topic_ids)),  		)); -		$l_confirm = (count($topic_ids) == 1) ? 'DELETE_TOPIC' : 'DELETE_TOPICS'; +		$count = count($topic_ids); +		$l_confirm = $count === 1 ? 'DELETE_TOPIC' : 'DELETE_TOPICS';  		if ($only_softdeleted)  		{ -			$l_confirm .= '_PERMANENTLY'; +			$l_confirm = array($l_confirm . '_PERMANENTLY', $count);  			$s_hidden_fields['delete_permanent'] = '1';  		}  		else if ($only_shadow || !$auth->acl_get('m_softdelete', $forum_id)) @@ -1228,10 +1245,11 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '',  			'DELETE_POST_PERMANENTLY_EXPLAIN'	=> $user->lang('DELETE_POST_PERMANENTLY', count($post_ids)),  		)); -		$l_confirm = (count($post_ids) == 1) ? 'DELETE_POST' : 'DELETE_POSTS'; +		$count = count($post_ids); +		$l_confirm = $count === 1 ? 'DELETE_POST' : 'DELETE_POSTS';  		if ($only_softdeleted)  		{ -			$l_confirm .= '_PERMANENTLY'; +			$l_confirm = array($l_confirm . '_PERMANENTLY', $count);  			$s_hidden_fields['delete_permanent'] = '1';  		}  		else if (!$auth->acl_get('m_softdelete', $forum_id)) diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index 68a65aafdd..83ad56f3e4 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -142,14 +142,36 @@ function mcp_topic_view($id, $mode, $action)  	}  	$start = $pagination->validate_start($start, $posts_per_page, $total); -	$sql = 'SELECT u.username, u.username_clean, u.user_colour, p.* -		FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u -		WHERE ' . (($action == 'reports') ? 'p.post_reported = 1 AND ' : '') . ' +	$sql_where = (($action == 'reports') ? 'p.post_reported = 1 AND ' : '') . '  			p.topic_id = ' . $topic_id . '  			AND ' .	$phpbb_content_visibility->get_visibility_sql('post', $topic_info['forum_id'], 'p.') . '  			AND p.poster_id = u.user_id ' . -			$limit_time_sql . ' -		ORDER BY ' . $sort_order_sql; +			$limit_time_sql; + +	$sql_ary = array( +		'SELECT'	=> 'u.username, u.username_clean, u.user_colour, p.*', +		'FROM'		=> array( +			POSTS_TABLE		=> 'p', +			USERS_TABLE		=> 'u' +		), +		'LEFT_JOIN'	=> array(), +		'WHERE'		=> $sql_where, +		'ORDER_BY'	=> $sort_order_sql, +	); + +	/** +	* Event to modify the SQL query before the MCP topic review posts is queried +	* +	* @event core.mcp_topic_modify_sql_ary +	* @var	array	sql_ary		The SQL array to get the data of the MCP topic review posts +	* @since 3.2.8-RC1 +	*/ +	$vars = array('sql_ary'); +	extract($phpbb_dispatcher->trigger_event('core.mcp_topic_modify_sql_ary', compact($vars))); + +	$sql = $db->sql_build_query('SELECT', $sql_ary); +	unset($sql_ary); +  	$result = $db->sql_query_limit($sql, $posts_per_page, $start);  	$rowset = $post_id_list = array(); diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 0b79cca864..e1c28223dc 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -1525,6 +1525,35 @@ class parse_message extends bbcode_firstpass  	}  	/** +	 * Check attachment form token depending on submit type +	 * +	 * @param \phpbb\language\language $language Language +	 * @param \phpbb\request\request_interface $request Request +	 * @param string $form_name Form name for checking form key +	 * +	 * @return bool True if form token is not needed or valid, false if needed and invalid +	 */ +	function check_attachment_form_token(\phpbb\language\language $language, \phpbb\request\request_interface $request, $form_name) +	{ +		$add_file = $request->is_set_post('add_file'); +		$delete_file = $request->is_set_post('delete_file'); + +		if (($add_file || $delete_file) && !check_form_key($form_name)) +		{ +			$this->warn_msg[] = $language->lang('FORM_INVALID'); + +			if ($request->is_ajax() && $this->plupload) +			{ +				$this->plupload->emit_error(-400, 'FORM_INVALID'); +			} + +			return false; +		} + +		return true; +	} + +	/**  	* Parse Attachments  	*/  	function parse_attachments($form_name, $mode, $forum_id, $submit, $preview, $refresh, $is_message = false) diff --git a/phpBB/includes/ucp/ucp_attachments.php b/phpBB/includes/ucp/ucp_attachments.php index c1b623cd71..7808fed325 100644 --- a/phpBB/includes/ucp/ucp_attachments.php +++ b/phpBB/includes/ucp/ucp_attachments.php @@ -29,7 +29,7 @@ class ucp_attachments  	function main($id, $mode)  	{ -		global $template, $user, $db, $config, $phpEx, $phpbb_root_path, $phpbb_container, $request; +		global $template, $user, $db, $config, $phpEx, $phpbb_root_path, $phpbb_container, $request, $auth;  		$start		= $request->variable('start', 0);  		$sort_key	= $request->variable('sk', 'a'); @@ -41,16 +41,27 @@ class ucp_attachments  		if ($delete && count($delete_ids))  		{  			// Validate $delete_ids... -			$sql = 'SELECT attach_id -				FROM ' . ATTACHMENTS_TABLE . ' -				WHERE poster_id = ' . $user->data['user_id'] . ' -					AND is_orphan = 0 -					AND ' . $db->sql_in_set('attach_id', $delete_ids); +			$sql = 'SELECT a.attach_id, p.post_edit_locked, t.topic_status, f.forum_id, f.forum_status +				FROM ' . ATTACHMENTS_TABLE . ' a +				LEFT JOIN ' . POSTS_TABLE . ' p +					ON (a.post_msg_id = p.post_id AND a.in_message = 0) +				LEFT JOIN ' . TOPICS_TABLE . ' t +					ON (t.topic_id = p.topic_id AND a.in_message = 0) +				LEFT JOIN ' . FORUMS_TABLE . ' f +					ON (f.forum_id = t.forum_id AND a.in_message = 0) +				WHERE a.poster_id = ' . $user->data['user_id'] . ' +					AND a.is_orphan = 0 +					AND ' . $db->sql_in_set('a.attach_id', $delete_ids);  			$result = $db->sql_query($sql);  			$delete_ids = array();  			while ($row = $db->sql_fetchrow($result))  			{ +				if (!$auth->acl_get('m_edit', $row['forum_id']) && ($row['forum_status'] == ITEM_LOCKED || $row['topic_status'] == ITEM_LOCKED || $row['post_edit_locked'])) +				{ +					continue; +				} +  				$delete_ids[] = $row['attach_id'];  			}  			$db->sql_freeresult($result); @@ -124,10 +135,12 @@ class ucp_attachments  		$pagination = $phpbb_container->get('pagination');  		$start = $pagination->validate_start($start, $config['topics_per_page'], $num_attachments); -		$sql = 'SELECT a.*, t.topic_title, p.message_subject as message_title +		$sql = 'SELECT a.*, t.topic_title, pr.message_subject as message_title, p.post_edit_locked, t.topic_status, f.forum_id, f.forum_status  			FROM ' . ATTACHMENTS_TABLE . ' a +				LEFT JOIN ' . POSTS_TABLE . ' p ON (a.post_msg_id = p.post_id AND a.in_message = 0)  				LEFT JOIN ' . TOPICS_TABLE . ' t ON (a.topic_id = t.topic_id AND a.in_message = 0) -				LEFT JOIN ' . PRIVMSGS_TABLE . ' p ON (a.post_msg_id = p.msg_id AND a.in_message = 1) +				LEFT JOIN ' . FORUMS_TABLE . ' f ON (f.forum_id = t.forum_id AND a.in_message = 0) +				LEFT JOIN ' . PRIVMSGS_TABLE . ' pr ON (a.post_msg_id = pr.msg_id AND a.in_message = 1)  			WHERE a.poster_id = ' . $user->data['user_id'] . "  				AND a.is_orphan = 0  			ORDER BY $order_by"; @@ -164,6 +177,7 @@ class ucp_attachments  					'TOPIC_ID'			=> $row['topic_id'],  					'S_IN_MESSAGE'		=> $row['in_message'], +					'S_LOCKED'			=> !$row['in_message'] && !$auth->acl_get('m_edit', $row['forum_id']) && ($row['forum_status'] == ITEM_LOCKED || $row['topic_status'] == ITEM_LOCKED || $row['post_edit_locked']),  					'U_VIEW_ATTACHMENT'	=> append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $row['attach_id']),  					'U_VIEW_TOPIC'		=> $view_topic) diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index 543db4f889..87a8c91fd2 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -26,7 +26,7 @@ if (!defined('IN_PHPBB'))  function compose_pm($id, $mode, $action, $user_folders = array())  {  	global $template, $db, $auth, $user, $cache; -	global $phpbb_root_path, $phpEx, $config; +	global $phpbb_root_path, $phpEx, $config, $language;  	global $request, $phpbb_dispatcher, $phpbb_container;  	// Damn php and globals - i know, this is horrible @@ -799,7 +799,10 @@ function compose_pm($id, $mode, $action, $user_folders = array())  		extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_modify_parse_before', compact($vars)));  		// Parse Attachments - before checksum is calculated -		$message_parser->parse_attachments('fileupload', $action, 0, $submit, $preview, $refresh, true); +		if ($message_parser->check_attachment_form_token($language, $request, 'ucp_pm_compose')) +		{ +			$message_parser->parse_attachments('fileupload', $action, 0, $submit, $preview, $refresh, true); +		}  		if (count($message_parser->warn_msg) && !($remove_u || $remove_g || $add_to || $add_bcc))  		{ @@ -996,7 +999,10 @@ function compose_pm($id, $mode, $action, $user_folders = array())  		{  			$quote_attributes['post_id'] = $post['msg_id'];  		} - +		if ($action === 'quote') +		{ +			$quote_attributes['msg_id'] = $post['msg_id']; +		}  		/** @var \phpbb\language\language $language */  		$language = $phpbb_container->get('language');  		/** @var \phpbb\textformatter\utils_interface $text_formatter_utils */ @@ -1007,6 +1013,16 @@ function compose_pm($id, $mode, $action, $user_folders = array())  	if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !$preview && !$refresh)  	{  		$message_subject = ((!preg_match('/^Re:/', $message_subject)) ? 'Re: ' : '') . censor_text($message_subject); + +		/** +		* This event allows you to modify the PM subject of the PM being quoted +		* +		* @event core.pm_modify_message_subject +		* @var	string		message_subject		String with the PM subject already censored. +		* @since 3.2.8-RC1 +		*/ +		$vars = array('message_subject'); +		extract($phpbb_dispatcher->trigger_event('core.pm_modify_message_subject', compact($vars)));  	}  	if ($action == 'forward' && !$preview && !$refresh && !$submit) diff --git a/phpBB/includes/ucp/ucp_pm_viewfolder.php b/phpBB/includes/ucp/ucp_pm_viewfolder.php index a0b535d683..09e7bf4d7c 100644 --- a/phpBB/includes/ucp/ucp_pm_viewfolder.php +++ b/phpBB/includes/ucp/ucp_pm_viewfolder.php @@ -138,9 +138,9 @@ function view_folder($id, $mode, $folder_id, $folder)  				$row_indicator = '';  				foreach ($color_rows as $var)  				{ -					if (($var != 'friend' && $var != 'foe' && $row['pm_' . $var]) +					if (($var !== 'friend' && $var !== 'foe' && $row[($var === 'message_reported') ? $var : "pm_{$var}"])  						|| -						(($var == 'friend' || $var == 'foe') && isset(${$var}[$row['author_id']]) && ${$var}[$row['author_id']])) +						(($var === 'friend' || $var === 'foe') && isset(${$var}[$row['author_id']]) && ${$var}[$row['author_id']]))  					{  						$row_indicator = $var;  						break; diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index 9a1284083f..36ab3d0463 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -133,7 +133,6 @@ class ucp_profile  							'user_email'		=> ($auth->acl_get('u_chgemail')) ? $data['email'] : $user->data['user_email'],  							'user_email_hash'	=> ($auth->acl_get('u_chgemail')) ? phpbb_email_hash($data['email']) : $user->data['user_email_hash'],  							'user_password'		=> ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? $passwords_manager->hash($data['new_password']) : $user->data['user_password'], -							'user_passchg'		=> ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? time() : 0,  						);  						if ($auth->acl_get('u_chgname') && $config['allow_namechange'] && $data['username'] != $user->data['username']) @@ -147,6 +146,8 @@ class ucp_profile  						if ($auth->acl_get('u_chgpasswd') && $data['new_password'] && !$passwords_manager->check($data['new_password'], $user->data['user_password']))  						{ +							$sql_ary['user_passchg'] = time(); +  							$user->reset_login_keys();  							$phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_NEW_PASSWORD', false, array(  								'reportee_id' => $user->data['user_id'], diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 0e673cb692..03ac63b12b 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -39,12 +39,23 @@ class ucp_register  			trigger_error('UCP_REGISTER_DISABLE');  		} -		$coppa			= $request->is_set('coppa') ? (int) $request->variable('coppa', false) : false; +		$coppa			= $request->is_set('coppa_yes') ? 1 : ($request->is_set('coppa_no') ? 0 : false); +		$coppa			= $request->is_set('coppa') ? $request->variable('coppa', 0) : $coppa;  		$agreed			= $request->variable('agreed', false);  		$submit			= $request->is_set_post('submit');  		$change_lang	= $request->variable('change_lang', '');  		$user_lang		= $request->variable('lang', $user->lang_name); +		if ($agreed && !check_form_key('ucp_register')) +		{ +			$agreed = false; +		} + +		if ($coppa !== false && !check_form_key('ucp_register')) +		{ +			$coppa = false; +		} +  		/**  		* Add UCP register data before they are assigned to the template or submitted  		* @@ -67,14 +78,7 @@ class ucp_register  		);  		extract($phpbb_dispatcher->trigger_event('core.ucp_register_requests_after', compact($vars))); -		if ($agreed) -		{ -			add_form_key('ucp_register'); -		} -		else -		{ -			add_form_key('ucp_register_terms'); -		} +		add_form_key('ucp_register');  		if ($change_lang || $user_lang != $config['default_lang'])  		{ @@ -168,11 +172,8 @@ class ucp_register  				$template_vars = array(  					'S_LANG_OPTIONS'	=> (count($lang_row) > 1) ? language_select($user_lang) : '', -					'L_COPPA_NO'		=> sprintf($user->lang['UCP_COPPA_BEFORE'], $coppa_birthday), -					'L_COPPA_YES'		=> sprintf($user->lang['UCP_COPPA_ON_AFTER'], $coppa_birthday), - -					'U_COPPA_NO'		=> append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register&coppa=0'), -					'U_COPPA_YES'		=> append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register&coppa=1'), +					'L_COPPA_NO'		=> $user->lang('UCP_COPPA_BEFORE', $coppa_birthday), +					'L_COPPA_YES'		=> $user->lang('UCP_COPPA_ON_AFTER', $coppa_birthday),  					'S_SHOW_COPPA'		=> true,  					'S_HIDDEN_FIELDS'	=> build_hidden_fields($s_hidden_fields), diff --git a/phpBB/includes/utf/utf_tools.php b/phpBB/includes/utf/utf_tools.php index 89de454427..bb155aeae5 100644 --- a/phpBB/includes/utf/utf_tools.php +++ b/phpBB/includes/utf/utf_tools.php @@ -418,24 +418,43 @@ function utf8_recode($string, $encoding)  }  /** -* Replace all UTF-8 chars that are not in ASCII with their NCR -* -* @param	string	$text		UTF-8 string in NFC -* @return	string				ASCII string using NCRs for non-ASCII chars -*/ + * Replace some special UTF-8 chars that are not in ASCII with their UCR. + * using their Numeric Character Reference's Hexadecimal notation. + * + * Doesn't interfere with Japanese or Cyrillic etc. + * Unicode character visualization will depend on the character support + * of your web browser and the fonts installed on your system. + * + * @see https://en.wikibooks.org/wiki/Unicode/Character_reference/1F000-1FFFF + * + * @param	string	$text		UTF-8 string in NFC + * @return	string				ASCII string using NCR for non-ASCII chars + */ +function utf8_encode_ucr($text) +{ +	return preg_replace_callback('/[\\xF0-\\xF4].../', 'utf8_encode_ncr_callback', $text); +} + +/** + * Replace all UTF-8 chars that are not in ASCII with their NCR + * using their Numeric Character Reference's Hexadecimal notation. + * + * @param	string	$text		UTF-8 string in NFC + * @return	string				ASCII string using NCRs for non-ASCII chars + */  function utf8_encode_ncr($text)  {  	return preg_replace_callback('#[\\xC2-\\xF4][\\x80-\\xBF]{1,3}#', 'utf8_encode_ncr_callback', $text);  }  /** -* Callback used in encode_ncr() -* -* Takes a UTF-8 char and replaces it with its NCR. Attention, $m is an array -* -* @param	array	$m			0-based numerically indexed array passed by preg_replace_callback() -* @return	string				A HTML NCR if the character is valid, or the original string otherwise -*/ + * Callback used in utf8_encode_ncr() and utf8_encode_ucr() + * + * Takes a UTF-8 char and replaces it with its NCR. Attention, $m is an array + * + * @param	array	$m			0-based numerically indexed array passed by preg_replace_callback() + * @return	string				A HTML NCR if the character is valid, or the original string otherwise + */  function utf8_encode_ncr_callback($m)  {  	return '&#' . utf8_ord($m[0]) . ';';  | 
