diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 872509884c..dc7608b37e 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "d5368b75d221b5573b30307cb2f25f3b", + "hash": "c14bcbf5a6c4fd121492568aa3654c07", "packages": [ { "name": "lusitanian/oauth", @@ -220,12 +220,12 @@ "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "31fe627a4a82d41098a2db8036287c0693c79f13" + "reference": "29c5959f4425934a53b6fdb42760d719b95a6e82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/31fe627a4a82d41098a2db8036287c0693c79f13", - "reference": "31fe627a4a82d41098a2db8036287c0693c79f13", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/29c5959f4425934a53b6fdb42760d719b95a6e82", + "reference": "29c5959f4425934a53b6fdb42760d719b95a6e82", "shasum": "" }, "require": { @@ -270,7 +270,7 @@ "parser", "shortcodes" ], - "time": "2015-04-25 20:58:33" + "time": "2015-05-18 04:48:32" }, { "name": "symfony/config", @@ -612,6 +612,56 @@ "homepage": "http://symfony.com", "time": "2015-04-10 08:56:33" }, + { + "name": "symfony/finder", + "version": "2.8.x-dev", + "target-dir": "Symfony/Component/Finder", + "source": { + "type": "git", + "url": "https://github.com/symfony/Finder.git", + "reference": "ad159e0da47e9ffe719bafdc004159ad6e395567" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Finder/zipball/ad159e0da47e9ffe719bafdc004159ad6e395567", + "reference": "ad159e0da47e9ffe719bafdc004159ad6e395567", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7|~3.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Finder\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Finder Component", + "homepage": "http://symfony.com", + "time": "2015-04-10 08:56:33" + }, { "name": "symfony/http-foundation", "version": "2.8.x-dev", @@ -2571,56 +2621,6 @@ "homepage": "http://symfony.com", "time": "2015-04-10 08:56:33" }, - { - "name": "symfony/finder", - "version": "2.8.x-dev", - "target-dir": "Symfony/Component/Finder", - "source": { - "type": "git", - "url": "https://github.com/symfony/Finder.git", - "reference": "ad159e0da47e9ffe719bafdc004159ad6e395567" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/ad159e0da47e9ffe719bafdc004159ad6e395567", - "reference": "ad159e0da47e9ffe719bafdc004159ad6e395567", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Finder\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Symfony Finder Component", - "homepage": "http://symfony.com", - "time": "2015-04-10 08:56:33" - }, { "name": "symfony/process", "version": "2.8.x-dev", @@ -2681,6 +2681,7 @@ "symfony/dependency-injection": 20, "symfony/event-dispatcher": 20, "symfony/filesystem": 20, + "symfony/finder": 20, "symfony/http-kernel": 20, "symfony/routing": 20, "symfony/security-core": 20, @@ -2691,7 +2692,6 @@ "symfony/css-selector": 20, "symfony/debug": 20, "symfony/dom-crawler": 20, - "symfony/finder": 20, "symfony/http-foundation": 20, "symfony/process": 20 }, diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 9fe598d7fb..f018d735a7 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -1250,6 +1250,16 @@ class parse_message extends bbcode_firstpass return (!$update_this_message) ? $return_message : $this->warn_msg; } + // Remove quotes that are nested too deep + if ($config['max_quote_depth'] > 0) + { + $this->message = $phpbb_container->get('text_formatter.utils')->remove_bbcode( + $this->message, + 'quote', + $config['max_quote_depth'] + ); + } + // Check for errors $errors = $parser->get_errors(); if ($errors) diff --git a/phpBB/posting.php b/phpBB/posting.php index 2d01922c80..a4fb4d7a8d 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -1578,11 +1578,22 @@ if (!sizeof($error) && $preview) } } +// Remove quotes that would become nested too deep before decoding the text +$generate_quote = ($mode == 'quote' && !$submit && !$preview && !$refresh); +if ($generate_quote && $config['max_quote_depth'] > 0 && preg_match('#^<[rt][ >]#', $message_parser->message)) +{ + $message_parser->message = $phpbb_container->get('text_formatter.utils')->remove_bbcode( + $message_parser->message, + 'quote', + $config['max_quote_depth'] - 1 + ); +} + // Decode text for message display $post_data['bbcode_uid'] = ($mode == 'quote' && !$preview && !$refresh && !sizeof($error)) ? $post_data['bbcode_uid'] : $message_parser->bbcode_uid; $message_parser->decode_message($post_data['bbcode_uid']); -if ($mode == 'quote' && !$submit && !$preview && !$refresh) +if ($generate_quote) { if ($config['allow_bbcode']) { diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index 7acf375c5d..5c083aef37 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -71,4 +71,85 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case $crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}"); $this->assertContains('😀', $crawler->text()); } + + /** + * @testdox max_quote_depth is applied to the text populating the posting form + */ + public function test_quote_depth_form() + { + $text = '0[quote]1[quote]2[/quote]1[/quote]0'; + $expected = array( + 0 => '[quote="admin"]0[quote]1[quote]2[/quote]1[/quote]0[/quote]', + 1 => '[quote="admin"]00[/quote]', + 2 => '[quote="admin"]0[quote]11[/quote]0[/quote]', + 3 => '[quote="admin"]0[quote]1[quote]2[/quote]1[/quote]0[/quote]', + ); + + $this->login(); + $topic = $this->create_topic(2, 'Test Topic 1', 'Test topic'); + $post = $this->create_post(2, $topic['topic_id'], 'Re: Test Topic 1', $text); + $quote_url = "posting.php?mode=quote&f=2&t={$post['topic_id']}&p={$post['post_id']}&sid={$this->sid}"; + + $this->admin_login(); + foreach ($expected as $quote_depth => $expected_text) + { + $this->set_quote_depth($quote_depth); + $crawler = self::request('GET', $quote_url); + $this->assertContains($expected_text, $crawler->filter('textarea#message')->text()); + } + } + + /** + * @testdox max_quote_depth is applied to the submitted text + */ + public function test_quote_depth_submit() + { + $text = 'depth:0[quote]depth:1[quote]depth:2[quote]depth:3[/quote][/quote][/quote]'; + $contains = array( + 0 => array('depth:0', 'depth:1', 'depth:2', 'depth:3'), + 1 => array('depth:0', 'depth:1'), + 2 => array('depth:0', 'depth:1', 'depth:2'), + 3 => array('depth:0', 'depth:1', 'depth:2', 'depth:3'), + ); + $not_contains = array( + 0 => array(), + 1 => array('depth:2', 'depth:3'), + 2 => array('depth:3'), + 3 => array(), + ); + + $this->login(); + $this->admin_login(); + $topic = $this->create_topic(2, 'Test Topic 1', 'Test topic'); + + for ($quote_depth = 0; $quote_depth <= 2; ++$quote_depth) + { + $this->set_quote_depth($quote_depth); + + $post = $this->create_post(2, $topic['topic_id'], 'Re: Test Topic 1', $text); + $url = "viewtopic.php?p={$post['post_id']}&sid={$this->sid}"; + + $crawler = self::request('GET', $url); + $text_content = $crawler->filter('#p' . $post['post_id'])->text(); + foreach ($contains[$quote_depth] as $contains_text) + { + $this->assertContains($contains_text, $text_content); + } + foreach ($not_contains[$quote_depth] as $not_contains_text) + { + $this->assertNotContains($not_contains_text, $text_content); + } + } + } + + protected function set_quote_depth($depth) + { + $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[max_quote_depth]'] = $depth; + $form->setValues($values); + $crawler = self::submit($form); + $this->assertEquals(1, $crawler->filter('.successbox')->count()); + } }