diff options
| -rw-r--r-- | phpBB/includes/acp/acp_board.php | 7 | ||||
| -rw-r--r-- | phpBB/language/en/acp/board.php | 2 | ||||
| -rw-r--r-- | phpBB/phpbb/extension/metadata_manager.php | 5 | ||||
| -rw-r--r-- | phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php | 2 | ||||
| -rw-r--r-- | phpBB/phpbb/textformatter/data_access.php | 50 | ||||
| -rw-r--r-- | phpBB/phpbb/textformatter/s9e/factory.php | 3 | ||||
| -rw-r--r-- | phpBB/styles/prosilver/template/search_results.html | 2 | ||||
| -rw-r--r-- | phpBB/styles/prosilver/template/ucp_pm_viewmessage.html | 4 | ||||
| -rw-r--r-- | phpBB/styles/prosilver/theme/icons.css | 4 | ||||
| -rw-r--r-- | tests/functional/acp_bbcodes_test.php | 46 | ||||
| -rw-r--r-- | tests/functional/acp_smilies_test.php | 43 | ||||
| -rw-r--r-- | tests/functional/posting_test.php | 41 | 
12 files changed, 189 insertions, 20 deletions
diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 826d0007b7..1f9c15dbd0 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -196,6 +196,7 @@ class acp_board  						'allow_post_flash'		=> array('lang' => 'ALLOW_POST_FLASH',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'allow_smilies'			=> array('lang' => 'ALLOW_SMILIES',			'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false),  						'allow_post_links'		=> array('lang' => 'ALLOW_POST_LINKS',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), +						'allowed_schemes_links'	=> array('lang' => 'ALLOWED_SCHEMES_LINKS',	'validate' => 'string',	'type' => 'text:0:255', 'explain' => true),  						'allow_nocensors'		=> array('lang' => 'ALLOW_NO_CENSORS',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'allow_bookmarks'		=> array('lang' => 'ALLOW_BOOKMARKS',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'enable_post_confirm'	=> array('lang' => 'VISUAL_CONFIRM_POST',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), @@ -552,6 +553,12 @@ class acp_board  			}  		} +		// Invalidate the text_formatter cache when posting options are changed +		if ($mode == 'post' && $submit) +		{ +			$phpbb_container->get('text_formatter.cache')->invalidate(); +		} +  		// Store news and exclude ids  		if ($mode == 'feed' && $submit)  		{ diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index 08290c9617..6a5a4158e3 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -161,6 +161,8 @@ $lang = array_merge($lang, array(  	'ACP_POST_SETTINGS_EXPLAIN'			=> 'Here you can set all default settings for posting.',  	'ALLOW_POST_LINKS'					=> 'Allow links in posts/private messages',  	'ALLOW_POST_LINKS_EXPLAIN'			=> 'If disallowed the <code>[URL]</code> BBCode tag and automatic/magic URLs are disabled.', +	'ALLOWED_SCHEMES_LINKS'				=> 'Allowed schemes in links', +	'ALLOWED_SCHEMES_LINKS_EXPLAIN'		=> 'Users can only post schemeless URLs or one of the comma-separated list of allowed schemes.',  	'ALLOW_POST_FLASH'					=> 'Allow use of <code>[FLASH]</code> BBCode tag in posts',  	'ALLOW_POST_FLASH_EXPLAIN'			=> 'If disallowed the <code>[FLASH]</code> BBCode tag is disabled in posts. Otherwise the permission system controls which users can use the <code>[FLASH]</code> BBCode tag.', diff --git a/phpBB/phpbb/extension/metadata_manager.php b/phpBB/phpbb/extension/metadata_manager.php index 2b8b1bbd6a..348b3c2cdf 100644 --- a/phpBB/phpbb/extension/metadata_manager.php +++ b/phpBB/phpbb/extension/metadata_manager.php @@ -214,7 +214,10 @@ class metadata_manager  			case 'all':  				$this->validate('display'); -				$this->validate_enable(); +				if (!$this->validate_enable()) +				{ +					throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array($name)); +				}  			break;  			case 'display': diff --git a/phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php b/phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php index 258a035768..5cdc331cbc 100644 --- a/phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php +++ b/phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php @@ -47,7 +47,7 @@ class ftp_file_updater implements file_updater_interface  	 * @param string		$phpbb_root_path  	 * @param string		$php_ext  	 */ -	public function __constructor(update_helper $update_helper, $phpbb_root_path, $php_ext) +	public function __construct(update_helper $update_helper, $phpbb_root_path, $php_ext)  	{  		$this->transfer			= null;  		$this->update_helper	= $update_helper; diff --git a/phpBB/phpbb/textformatter/data_access.php b/phpBB/phpbb/textformatter/data_access.php index 2103bf8e60..0d37e62c87 100644 --- a/phpBB/phpbb/textformatter/data_access.php +++ b/phpBB/phpbb/textformatter/data_access.php @@ -81,11 +81,8 @@ class data_access  	public function get_bbcodes()  	{  		$sql = 'SELECT bbcode_match, bbcode_tpl FROM ' . $this->bbcodes_table; -		$result = $this->db->sql_query($sql); -		$rows = $this->db->sql_fetchrowset($result); -		$this->db->sql_freeresult($result); -		return $rows; +		return $this->fetch_decoded_rowset($sql, ['bbcode_match']);  	}  	/** @@ -101,11 +98,8 @@ class data_access  		$sql = 'SELECT code, emotion, smiley_url, smiley_width, smiley_height  			FROM ' . $this->smilies_table . '  			ORDER BY display_on_posting DESC'; -		$result = $this->db->sql_query($sql); -		$rows = $this->db->sql_fetchrowset($result); -		$this->db->sql_freeresult($result); -		return $rows; +		return $this->fetch_decoded_rowset($sql, ['code', 'emotion', 'smiley_url']);  	}  	/** @@ -116,11 +110,8 @@ class data_access  	protected function get_styles()  	{  		$sql = 'SELECT style_id, style_path, style_parent_id, bbcode_bitfield FROM ' . $this->styles_table; -		$result = $this->db->sql_query($sql); -		$rows = $this->db->sql_fetchrowset($result); -		$this->db->sql_freeresult($result); -		return $rows; +		return $this->fetch_decoded_rowset($sql);  	}  	/** @@ -219,10 +210,43 @@ class data_access  	public function get_censored_words()  	{  		$sql = 'SELECT word, replacement FROM ' . $this->words_table; + +		return $this->fetch_decoded_rowset($sql, ['word', 'replacement']); +	} + +	/** +	* Decode HTML special chars in given rowset +	* +	* @param  array $rows    Original rowset +	* @param  array $columns List of columns to decode +	* @return array          Decoded rowset +	*/ +	protected function decode_rowset(array $rows, array $columns) +	{ +		foreach ($rows as &$row) +		{ +			foreach ($columns as $column) +			{ +				$row[$column] = htmlspecialchars_decode($row[$column]); +			} +		} + +		return $rows; +	} + +	/** +	* Fetch all rows for given query and decode plain text columns +	* +	* @param  string $sql     SELECT query +	* @param  array  $columns List of columns to decode +	* @return array +	*/ +	protected function fetch_decoded_rowset($sql, array $columns = []) +	{  		$result = $this->db->sql_query($sql);  		$rows = $this->db->sql_fetchrowset($result);  		$this->db->sql_freeresult($result); -		return $rows; +		return $this->decode_rowset($rows, $columns);  	}  } diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 55149b8e63..5cbf2712f7 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -333,8 +333,7 @@ class factory implements \phpbb\textformatter\cache_interface  			$configurator->plugins->load('Censor', array('tagName' => 'censor:tag'));  			foreach ($censor as $row)  			{ -				// NOTE: words are stored as HTML, we need to decode them to plain text -				$configurator->Censor->add(htmlspecialchars_decode($row['word']),  htmlspecialchars_decode($row['replacement'])); +				$configurator->Censor->add($row['word'], $row['replacement']);  			}  		} diff --git a/phpBB/styles/prosilver/template/search_results.html b/phpBB/styles/prosilver/template/search_results.html index f7114567e5..ff4f3389c6 100644 --- a/phpBB/styles/prosilver/template/search_results.html +++ b/phpBB/styles/prosilver/template/search_results.html @@ -78,7 +78,7 @@  			<!-- EVENT search_results_topic_before -->  			<li class="row<!-- IF searchresults.S_ROW_COUNT is even --> bg1<!-- ELSE --> bg2<!-- ENDIF -->">  				<dl class="row-item {searchresults.TOPIC_IMG_STYLE}"> -					<dt<!-- IF searchresults.TOPIC_ICON_IMG and S_TOPIC_ICONS --> style="background-image: url({T_ICONS_PATH}{searchresults.TOPIC_ICON_IMG}); background-repeat: no-repeat;"<!-- ENDIF --> title="{searchresults.TOPIC_FOLDER_IMG_ALT}"> +					<dt<!-- IF searchresults.TOPIC_ICON_IMG --> style="background-image: url({T_ICONS_PATH}{searchresults.TOPIC_ICON_IMG}); background-repeat: no-repeat;"<!-- ENDIF --> title="{searchresults.TOPIC_FOLDER_IMG_ALT}">  						<!-- IF searchresults.S_UNREAD_TOPIC and not S_IS_BOT --><a href="{searchresults.U_NEWEST_POST}" class="row-item-link"></a><!-- ENDIF -->  						<div class="list-inner">  							<!-- EVENT topiclist_row_prepend --> diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html b/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html index e2a086060c..4295867c05 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html +++ b/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html @@ -15,7 +15,7 @@  		<!-- ENDIF -->  		<!-- IF U_VIEW_NEXT_HISTORY -->  			<a href="{U_VIEW_NEXT_HISTORY}" class="right-box arrow-{S_CONTENT_FLOW_END}"> -				<i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_VIEW_NEXT_HISTORY}</span> +				<i class="icon fa-angle-{S_CONTENT_FLOW_END} fa-fw icon-black" aria-hidden="true"></i><span>{L_VIEW_NEXT_HISTORY}</span>  			</a>  		<!-- ENDIF -->  	</fieldset> @@ -179,7 +179,7 @@  	<!-- ENDIF -->  	<!-- IF U_NEXT_PM -->  		<a href="{U_NEXT_PM}" class="right-box arrow-{S_CONTENT_FLOW_END}"> -			<i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_VIEW_NEXT_PM}</span> +			<i class="icon fa-angle-{S_CONTENT_FLOW_END} fa-fw icon-black" aria-hidden="true"></i><span>{L_VIEW_NEXT_PM}</span>  		</a>  	<!-- ENDIF -->  	<!-- IF not S_UNREAD and not S_SPECIAL_FOLDER --><label for="dest_folder"><!-- IF S_VIEW_MESSAGE -->{L_MOVE_TO_FOLDER}{L_COLON} <!-- ELSE -->{L_MOVE_MARKED_TO_FOLDER}<!-- ENDIF --> <select name="dest_folder" id="dest_folder">{S_TO_FOLDER_OPTIONS}</select></label> <input class="button2" type="submit" name="move_pm" value="{L_GO}" /><!-- ENDIF --> diff --git a/phpBB/styles/prosilver/theme/icons.css b/phpBB/styles/prosilver/theme/icons.css index 9fb7244f4b..411fecaf3b 100644 --- a/phpBB/styles/prosilver/theme/icons.css +++ b/phpBB/styles/prosilver/theme/icons.css @@ -54,6 +54,10 @@  	font-size: 16px;  } +.arrow-left .icon { +	float: left; +} +  .arrow-left:hover .icon {  	margin-left: -5px;  	margin-right: 5px; diff --git a/tests/functional/acp_bbcodes_test.php b/tests/functional/acp_bbcodes_test.php new file mode 100644 index 0000000000..58681dfa07 --- /dev/null +++ b/tests/functional/acp_bbcodes_test.php @@ -0,0 +1,46 @@ +<?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. + * + */ + +/** + * @group functional + */ +class phpbb_functional_acp_bbcodes_test extends phpbb_functional_test_case +{ +	public function test_htmlspecialchars() +	{ +		$this->login(); +		$this->admin_login(); + +		// Create the BBCode +		$crawler = self::request('GET', 'adm/index.php?i=acp_bbcodes&sid=' . $this->sid . '&mode=bbcodes&action=add'); +		$form = $crawler->selectButton('Submit')->form(array( +			'bbcode_match' => '[mod="{TEXT1}"]{TEXT2}[/mod]', +			'bbcode_tpl'   => '<div>{TEXT1}</div><div>{TEXT2}</div>' +		)); +		self::submit($form); + +		// Test it in the "new topic" preview +		$crawler = self::request('GET', 'posting.php?mode=post&f=2&sid=' . $this->sid); +		$form = $crawler->selectButton('Preview')->form(array( +			'subject' => 'subject', +			'message' => '[mod=a]b[/mod][mod="c"]d[/mod]' +		)); +		$crawler = self::submit($form); + +		$html = $crawler->filter('#preview')->html(); +		$this->assertContains('<div>a</div>', $html); +		$this->assertContains('<div>b</div>', $html); +		$this->assertContains('<div>c</div>', $html); +		$this->assertContains('<div>d</div>', $html); +	} +} diff --git a/tests/functional/acp_smilies_test.php b/tests/functional/acp_smilies_test.php new file mode 100644 index 0000000000..ebe8717fa7 --- /dev/null +++ b/tests/functional/acp_smilies_test.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. + * + */ + +/** + * @group functional + */ +class phpbb_functional_acp_smilies_test extends phpbb_functional_test_case +{ +	public function test_htmlspecialchars() +	{ +		$this->login(); +		$this->admin_login(); + +		// Create the BBCode +		$crawler = self::request('GET', 'adm/index.php?i=acp_icons&sid=' . $this->sid . '&mode=smilies&action=edit&id=1'); +		$form = $crawler->selectButton('Submit')->form(array( +			'code[icon_e_biggrin.gif]'    => '>:D', +			'emotion[icon_e_biggrin.gif]' => '>:D' +		)); +		self::submit($form); + +		// Test it in the "new topic" preview +		$crawler = self::request('GET', 'posting.php?mode=post&f=2&sid=' . $this->sid); +		$form = $crawler->selectButton('Preview')->form(array( +			'subject' => 'subject', +			'message' => '>:D' +		)); +		$crawler = self::submit($form); + +		$html = $crawler->filter('#preview')->html(); +		$this->assertRegexp('(<img [^>]+ alt=">:D" title=">:D"[^>]*>)', $html); +	} +} diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index 83acefd2f3..8e6328d1d3 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -264,4 +264,45 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case  		// Test that the preview contains the correct link  		$this->assertEquals($url, $crawler->filter('#preview a')->attr('href'));  	} + +	public function test_allowed_schemes_links() +	{ +		$text = 'http://example.org/ tcp://localhost:22/ServiceName'; + +		$this->login(); +		$this->admin_login(); + +		// Post with default settings +		$crawler = self::request('GET', 'posting.php?mode=post&f=2'); +		$form = $crawler->selectButton('Preview')->form(array( +			'subject' => 'Test subject', +			'message' => $text, +		)); +		$crawler = self::submit($form); +		$this->assertContains( +			'<a href="http://example.org/" class="postlink">http://example.org/</a> tcp://localhost:22/ServiceName', +			$crawler->filter('#preview .content')->html() +		); + +		// Update allowed schemes +		$crawler = self::request('GET', 'adm/index.php?sid=' . $this->sid . '&i=acp_board&mode=post'); +		$form = $crawler->selectButton('Submit')->form(); +		$values = $form->getValues(); +		$values['config[allowed_schemes_links]'] = 'https,tcp'; +		$form->setValues($values); +		$crawler = self::submit($form); +		$this->assertEquals(1, $crawler->filter('.successbox')->count()); + +		// Post with new settings +		$crawler = self::request('GET', 'posting.php?mode=post&f=2'); +		$form = $crawler->selectButton('Preview')->form(array( +			'subject' => 'Test subject', +			'message' => $text, +		)); +		$crawler = self::submit($form); +		$this->assertContains( +			'http://example.org/ <a href="tcp://localhost:22/ServiceName" class="postlink">tcp://localhost:22/ServiceName</a>', +			$crawler->filter('#preview .content')->html() +		); +	}  }  | 
