From 5a93bb6effae8921e767501a66f76ffbc2fd05bc Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 12 Sep 2021 00:05:22 -0400 Subject: [PATCH 1/2] Prevent expandTags to be performed on existing links in Module\Api\Mastodon\Statuses - We never need to expand tags inside of an already existing BBCode url tag --- src/Module/Api/Mastodon/Statuses.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Module/Api/Mastodon/Statuses.php b/src/Module/Api/Mastodon/Statuses.php index 6ae076733..ed5abf199 100644 --- a/src/Module/Api/Mastodon/Statuses.php +++ b/src/Module/Api/Mastodon/Statuses.php @@ -63,7 +63,10 @@ class Statuses extends BaseApi // The imput is defined as text. So we can use Markdown for some enhancements $body = Markdown::toBBCode($request['status']); - $body = BBCode::expandTags($body); + // Avoids potential double expansion of existing links + $body = BBCode::performWithEscapedTags($body, ['url'], function ($body) { + return BBCode::expandTags($body); + }); $item = []; $item['uid'] = $uid; From 8e99b7f77516ecaab2680f314177005f2dc5a658 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 12 Sep 2021 00:06:14 -0400 Subject: [PATCH 2/2] Refine BBCode::expandTags regular expression - Now requires the tag to be preceded by either a non-word character or a start of a line - Added corresponding tests --- src/Content/Text/BBCode.php | 5 +++-- tests/src/Content/Text/BBCodeTest.php | 28 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 5a2b966dd..4d495a72b 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -2289,14 +2289,14 @@ class BBCode } /** - * Expand tags to URLs + * Expand tags to URLs, checks the tag is at the start of a line or preceded by a non-word character * * @param string $body * @return string body with expanded tags */ public static function expandTags(string $body) { - return preg_replace_callback("/([!#@])([^\^ \x0D\x0A,;:?\']*[^\^ \x0D\x0A,;:?!\'.])/", + return preg_replace_callback("/(?<=\W|^)([!#@])([^\^ \x0D\x0A,;:?'\"]*[^\^ \x0D\x0A,;:?!'\".])/", function ($match) { switch ($match[1]) { case '!': @@ -2309,6 +2309,7 @@ class BBCode } break; case '#': + default: return $match[1] . '[url=' . 'https://' . DI::baseUrl() . '/search?tag=' . $match[2] . ']' . $match[2] . '[/url]'; } }, $body); diff --git a/tests/src/Content/Text/BBCodeTest.php b/tests/src/Content/Text/BBCodeTest.php index 2fcf5a5fa..e2c4d9288 100644 --- a/tests/src/Content/Text/BBCodeTest.php +++ b/tests/src/Content/Text/BBCodeTest.php @@ -75,6 +75,7 @@ class BBCodeTest extends MockedTest ->andReturn($baseUrlMock); $baseUrlMock->shouldReceive('getHostname')->withNoArgs()->andReturn('friendica.local'); $baseUrlMock->shouldReceive('getUrlPath')->withNoArgs()->andReturn(''); + $baseUrlMock->shouldReceive('__toString')->withNoArgs()->andReturn('friendica.local'); $config = \HTMLPurifier_HTML5Config::createDefault(); $config->set('HTML.Doctype', 'HTML5'); @@ -339,4 +340,31 @@ class BBCodeTest extends MockedTest self::assertEquals($expected, $actual); } + + public function dataExpandTags() + { + return [ + 'bug-10692-non-word' => [ + '[url=https://github.com/friendica/friendica/blob/2021.09-rc/src/Util/Logger/StreamLogger.php#L160]https://github.com/friendica/friendica/blob/2021.09-rc/src/Util/Logger/StreamLogger.php#L160[/url]', + '[url=https://github.com/friendica/friendica/blob/2021.09-rc/src/Util/Logger/StreamLogger.php#L160]https://github.com/friendica/friendica/blob/2021.09-rc/src/Util/Logger/StreamLogger.php#L160[/url]', + ], + 'bug-10692-start-line' => [ + '#[url=https://friendica.local/search?tag=L160]L160[/url]', + '#L160', + ] + ]; + } + + /** + * @dataProvider dataExpandTags + * + * @param string $expected Expected BBCode output + * @param string $text Input text + */ + public function testExpandTags(string $expected, string $text) + { + $actual = BBCode::expandTags($text); + + self::assertEquals($expected, $actual); + } }