2019-03-23 18:44:52 +01:00
< ? php
2020-02-09 15:45:36 +01:00
/**
2021-03-29 08:40:20 +02:00
* @ copyright Copyright ( C ) 2010 - 2021 , the Friendica project
2020-02-09 15:45:36 +01:00
*
* @ license GNU AGPL version 3 or any later version
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation , either version 3 of the
* License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < https :// www . gnu . org / licenses />.
*
*/
2019-03-23 18:44:52 +01:00
namespace Friendica\Test\src\Content\Text ;
2019-08-15 17:23:00 +02:00
use Friendica\App\BaseURL ;
2019-03-23 18:44:52 +01:00
use Friendica\Content\Text\BBCode ;
2020-01-18 20:59:39 +01:00
use Friendica\Core\L10n ;
2020-10-18 20:31:57 +02:00
use Friendica\Network\HTTPException\InternalServerErrorException ;
2019-03-23 18:44:52 +01:00
use Friendica\Test\MockedTest ;
use Friendica\Test\Util\AppMockTrait ;
use Friendica\Test\Util\VFSTrait ;
2020-10-18 20:31:57 +02:00
use Mockery ;
2019-03-23 18:44:52 +01:00
class BBCodeTest extends MockedTest
{
use VFSTrait ;
use AppMockTrait ;
2021-04-01 23:04:30 +02:00
protected function setUp () : void
2019-03-23 18:44:52 +01:00
{
parent :: setUp ();
$this -> setUpVfsDir ();
$this -> mockApp ( $this -> root );
$this -> configMock -> shouldReceive ( 'get' )
-> with ( 'system' , 'remove_multiplicated_lines' )
-> andReturn ( false );
$this -> configMock -> shouldReceive ( 'get' )
-> with ( 'system' , 'no_oembed' )
-> andReturn ( false );
$this -> configMock -> shouldReceive ( 'get' )
-> with ( 'system' , 'allowed_link_protocols' )
-> andReturn ( null );
$this -> configMock -> shouldReceive ( 'get' )
-> with ( 'system' , 'url' )
-> andReturn ( 'friendica.local' );
2019-06-20 22:14:05 +02:00
$this -> configMock -> shouldReceive ( 'get' )
-> with ( 'system' , 'no_smilies' )
-> andReturn ( false );
2020-05-17 19:28:40 +02:00
$this -> configMock -> shouldReceive ( 'get' )
-> with ( 'system' , 'big_emojis' )
-> andReturn ( false );
2021-03-14 19:06:27 +01:00
$this -> configMock -> shouldReceive ( 'get' )
-> with ( 'system' , 'allowed_oembed' )
-> andReturn ( '' );
2019-07-09 21:44:02 +02:00
2020-10-18 20:31:57 +02:00
$l10nMock = Mockery :: mock ( L10n :: class );
2019-07-09 21:44:02 +02:00
$l10nMock -> shouldReceive ( 't' ) -> withAnyArgs () -> andReturnUsing ( function ( $args ) { return $args ; });
2019-07-26 15:54:14 +02:00
$this -> dice -> shouldReceive ( 'create' )
2020-01-18 13:48:29 +01:00
-> with ( L10n :: class )
2019-07-26 15:54:14 +02:00
-> andReturn ( $l10nMock );
2019-08-04 19:02:16 +02:00
2020-10-18 20:31:57 +02:00
$baseUrlMock = Mockery :: mock ( BaseURL :: class );
2019-08-04 19:02:16 +02:00
$baseUrlMock -> shouldReceive ( 'get' ) -> withAnyArgs () -> andReturn ( 'friendica.local' );
$this -> dice -> shouldReceive ( 'create' )
2020-01-18 13:48:29 +01:00
-> with ( BaseURL :: class )
2019-08-04 19:02:16 +02:00
-> andReturn ( $baseUrlMock );
2021-03-14 19:06:27 +01:00
$baseUrlMock -> shouldReceive ( 'getHostname' ) -> withNoArgs () -> andReturn ( 'friendica.local' );
$baseUrlMock -> shouldReceive ( 'getUrlPath' ) -> withNoArgs () -> andReturn ( '' );
2021-09-12 06:06:14 +02:00
$baseUrlMock -> shouldReceive ( '__toString' ) -> withNoArgs () -> andReturn ( 'friendica.local' );
2020-12-04 13:27:13 +01:00
$config = \HTMLPurifier_HTML5Config :: createDefault ();
$config -> set ( 'HTML.Doctype' , 'HTML5' );
$config -> set ( 'Attr.AllowedRel' , [
'noreferrer' => true ,
'noopener' => true ,
]);
$config -> set ( 'Attr.AllowedFrameTargets' , [
'_blank' => true ,
]);
$this -> HTMLPurifier = new \HTMLPurifier ( $config );
2019-03-23 18:44:52 +01:00
}
public function dataLinks ()
{
return [
/** @see https://github.com/friendica/friendica/issues/2487 */
'bug-2487-1' => [
'data' => 'https://de.wikipedia.org/wiki/Juha_Sipilä' ,
'assertHTML' => true ,
],
'bug-2487-2' => [
'data' => 'https://de.wikipedia.org/wiki/Dnepr_(Motorradmarke)' ,
'assertHTML' => true ,
],
'bug-2487-3' => [
'data' => 'https://friendica.wäckerlin.ch/friendica' ,
'assertHTML' => true ,
],
'bug-2487-4' => [
'data' => 'https://mastodon.social/@morevnaproject' ,
'assertHTML' => true ,
],
/** @see https://github.com/friendica/friendica/issues/5795 */
'bug-5795' => [
'data' => 'https://social.nasqueron.org/@liw/100798039015010628' ,
'assertHTML' => true ,
],
/** @see https://github.com/friendica/friendica/issues/6095 */
'bug-6095' => [
'data' => 'https://en.wikipedia.org/wiki/Solid_(web_decentralization_project)' ,
'assertHTML' => true ,
],
'no-protocol' => [
'data' => 'example.com/path' ,
'assertHTML' => false
],
'wrong-protocol' => [
'data' => 'ftp://example.com' ,
'assertHTML' => false
],
'wrong-domain-without-path' => [
'data' => 'http://example' ,
'assertHTML' => false
],
'wrong-domain-with-path' => [
'data' => 'http://example/path' ,
'assertHTML' => false
],
'bug-6857-domain-start' => [
'data' => " http:// \n example.com " ,
'assertHTML' => false
],
'bug-6857-domain-end' => [
'data' => " http://example \n .com " ,
'assertHTML' => false
],
'bug-6857-tld' => [
'data' => " http://example. \n com " ,
'assertHTML' => false
],
'bug-6857-end' => [
'data' => " http://example.com \n test " ,
'assertHTML' => false
],
'bug-6901' => [
'data' => " http://example.com<ul> " ,
'assertHTML' => false
],
2019-05-19 20:57:28 +02:00
'bug-7150' => [
'data' => html_entity_decode ( 'http://example.com ' , ENT_QUOTES , 'UTF-8' ),
'assertHTML' => false
],
2019-06-16 04:26:29 +02:00
'bug-7271-query-string-brackets' => [
'data' => 'https://example.com/search?q=square+brackets+[url]' ,
'assertHTML' => true
],
'bug-7271-path-brackets' => [
'data' => 'http://example.com/path/to/file[3].html' ,
'assertHTML' => true
],
2019-03-23 18:44:52 +01:00
];
}
/**
* Test convert different links inside a text
2020-10-18 20:31:57 +02:00
*
2019-03-23 18:44:52 +01:00
* @ dataProvider dataLinks
*
2020-10-18 20:31:57 +02:00
* @ param string $data The data to text
* @ param bool $assertHTML True , if the link is a HTML link ( < a href ...>...</ a > )
*
* @ throws InternalServerErrorException
2019-03-23 18:44:52 +01:00
*/
2020-10-18 20:31:57 +02:00
public function testAutoLinking ( string $data , bool $assertHTML )
2019-03-23 18:44:52 +01:00
{
$output = BBCode :: convert ( $data );
2020-12-04 13:27:13 +01:00
$assert = $this -> HTMLPurifier -> purify ( '<a href="' . $data . '" target="_blank" rel="noopener noreferrer">' . $data . '</a>' );
2019-03-23 18:44:52 +01:00
if ( $assertHTML ) {
2020-10-17 14:19:57 +02:00
self :: assertEquals ( $assert , $output );
2019-03-23 18:44:52 +01:00
} else {
2020-10-17 14:19:57 +02:00
self :: assertNotEquals ( $assert , $output );
2019-03-23 18:44:52 +01:00
}
}
2019-06-16 04:24:51 +02:00
public function dataBBCodes ()
{
return [
'bug-7271-condensed-space' => [
2020-12-04 13:27:13 +01:00
'expectedHtml' => '<ul class="listdecimal" style="list-style-type:decimal;"><li> <a href="http://example.com/" target="_blank" rel="noopener noreferrer">http://example.com/</a></li></ul>' ,
2019-06-16 04:24:51 +02:00
'text' => '[ol][*] http://example.com/[/ol]' ,
],
'bug-7271-condensed-nospace' => [
2020-12-04 13:27:13 +01:00
'expectedHtml' => '<ul class="listdecimal" style="list-style-type:decimal;"><li><a href="http://example.com/" target="_blank" rel="noopener noreferrer">http://example.com/</a></li></ul>' ,
2019-06-16 04:24:51 +02:00
'text' => '[ol][*]http://example.com/[/ol]' ,
],
'bug-7271-indented-space' => [
2020-12-04 13:27:13 +01:00
'expectedHtml' => '<ul class="listbullet" style="list-style-type:circle;"><li> <a href="http://example.com/" target="_blank" rel="noopener noreferrer">http://example.com/</a></li></ul>' ,
2019-06-16 04:24:51 +02:00
'text' => ' [ ul ]
[ * ] http :// example . com /
[ / ul ] ' ,
],
'bug-7271-indented-nospace' => [
2020-12-04 13:27:13 +01:00
'expectedHtml' => '<ul class="listbullet" style="list-style-type:circle;"><li><a href="http://example.com/" target="_blank" rel="noopener noreferrer">http://example.com/</a></li></ul>' ,
2019-06-16 04:24:51 +02:00
'text' => ' [ ul ]
[ * ] http :// example . com /
[ / ul ] ' ,
],
2019-09-05 22:37:16 +02:00
'bug-2199-named-size' => [
2020-12-04 13:27:13 +01:00
'expectedHtml' => '<span style="font-size:xx-large;line-height:normal;">Test text</span>' ,
2019-09-05 22:37:16 +02:00
'text' => '[size=xx-large]Test text[/size]' ,
],
'bug-2199-numeric-size' => [
2020-12-04 13:27:13 +01:00
'expectedHtml' => '<span style="font-size:24px;line-height:normal;">Test text</span>' ,
2019-09-05 22:37:16 +02:00
'text' => '[size=24]Test text[/size]' ,
],
'bug-2199-diaspora-no-named-size' => [
'expectedHtml' => 'Test text' ,
'text' => '[size=xx-large]Test text[/size]' ,
2019-09-26 02:25:42 +02:00
'try_oembed' => false ,
2019-09-05 22:37:16 +02:00
// Triggers the diaspora compatible output
2021-09-28 05:36:48 +02:00
'simpleHtml' => BBCode :: DIASPORA ,
2019-09-05 22:37:16 +02:00
],
'bug-2199-diaspora-no-numeric-size' => [
'expectedHtml' => 'Test text' ,
'text' => '[size=24]Test text[/size]' ,
2019-09-26 02:25:42 +02:00
'try_oembed' => false ,
2019-09-05 22:37:16 +02:00
// Triggers the diaspora compatible output
2021-09-28 05:36:48 +02:00
'simpleHtml' => BBCode :: DIASPORA ,
2019-09-05 22:37:16 +02:00
],
2019-09-26 02:25:42 +02:00
'bug-7665-audio-tag' => [
2020-12-04 13:27:13 +01:00
'expectedHtml' => '<audio src="http://www.cendrones.fr/colloque2017/jonathanbocquet.mp3" controls><a href="http://www.cendrones.fr/colloque2017/jonathanbocquet.mp3">http://www.cendrones.fr/colloque2017/jonathanbocquet.mp3</a></audio>' ,
2019-09-26 02:25:42 +02:00
'text' => '[audio]http://www.cendrones.fr/colloque2017/jonathanbocquet.mp3[/audio]' ,
'try_oembed' => true ,
],
2019-12-21 05:20:41 +01:00
'bug-7808-code-lt' => [
'expectedHtml' => '<code><</code>' ,
'text' => '[code]<[/code]' ,
],
'bug-7808-code-gt' => [
'expectedHtml' => '<code>></code>' ,
'text' => '[code]>[/code]' ,
],
'bug-7808-code-amp' => [
'expectedHtml' => '<code>&</code>' ,
'text' => '[code]&[/code]' ,
2020-06-23 13:52:38 +02:00
],
'task-8800-pre-spaces-notag' => [
'expectedHtml' => '[test] Space' ,
'text' => '[test] Space' ,
],
2020-06-23 13:53:18 +02:00
'task-8800-pre-spaces' => [
2020-12-04 13:27:13 +01:00
'expectedHtml' => ' Spaces' ,
2020-06-23 13:53:18 +02:00
'text' => '[pre] Spaces[/pre]' ,
],
2020-12-04 13:27:13 +01:00
'bug-9611-purify-xss-nobb' => [
'expectedHTML' => '<span>dare to move your mouse here</span>' ,
'text' => '[nobb]<span onmouseover="alert(0)">dare to move your mouse here</span>[/nobb]'
],
'bug-9611-purify-xss-noparse' => [
'expectedHTML' => '<span>dare to move your mouse here</span>' ,
'text' => '[noparse]<span onmouseover="alert(0)">dare to move your mouse here</span>[/noparse]'
],
'bug-9611-purify-xss-attributes' => [
'expectedHTML' => '<span>dare to move your mouse here</span>' ,
'text' => '[color="onmouseover=alert(0) style="]dare to move your mouse here[/color]'
],
'bug-9611-purify-attributes-correct' => [
'expectedHTML' => '<span style="color:#FFFFFF;">dare to move your mouse here</span>' ,
'text' => '[color=FFFFFF]dare to move your mouse here[/color]'
],
2020-12-18 17:11:48 +01:00
'bug-9639-span-classes' => [
'expectedHTML' => '<span class="arbitrary classes">Test</span>' ,
'text' => '[class=arbitrary classes]Test[/class]' ,
],
2021-09-28 05:36:48 +02:00
'bug-10772-duplicated-links' => [
'expectedHTML' => 'Jetzt wird mir klar, warum Kapitalisten jedes Mal durchdrehen wenn Marx und das Kapital ins Gespräch kommt. Soziopathen.<br>Karl Marx - Die ursprüngliche Akkumulation<br><a href="https://wohlstandfueralle.podigee.io/107-urspruengliche-akkumulation" target="_blank" rel="noopener noreferrer">https://wohlstandfueralle.podigee.io/107-urspruengliche-akkumulation</a><br>#Podcast #Kapitalismus' ,
'text' => " Jetzt wird mir klar, warum Kapitalisten jedes Mal durchdrehen wenn Marx und das Kapital ins Gespräch kommt. Soziopathen.
2021-09-28 06:27:24 +02:00
Karl Marx - Die ursprüngliche Akkumulation
[ url = https :// wohlstandfueralle . podigee . io / 107 - urspruengliche - akkumulation ] https :// wohlstandfueralle . podigee . io / 107 - urspruengliche - akkumulation [ / url ]
#[url=https://horche.demkontinuum.de/search?tag=Podcast]Podcast[/url] #[url=https://horche.demkontinuum.de/search?tag=Kapitalismus]Kapitalismus[/url]
[ attachment type = 'link' url = 'https://wohlstandfueralle.podigee.io/107-urspruengliche-akkumulation' title = 'Ep. 107: Karl Marx #8 - Die ursprüngliche Akkumulation' publisher_name = 'Wohlstand für Alle' preview = 'https://images.podigee-cdn.net/0x,s6LXshYO7uhG23H431B30t4hxj1bQuzlTsUlze0F_-H8=/https://cdn.podigee.com/uploads/u8126/bd5fe4f4-38b7-4f3f-b269-6a0080144635.jpg' ] Wie der Kapitalismus funktioniert und inwieweit Menschen darin ausgebeutet werden , haben wir bereits besprochen . Immer wieder verweisen wir auch darauf , dass der Kapitalismus nicht immer schon existierte , sondern historisiert werden muss . [ / attachment ] " ,
2021-09-28 05:36:48 +02:00
'try_oembed' => false ,
'simpleHtml' => BBCode :: TWITTER ,
],
2019-06-16 04:24:51 +02:00
];
}
/**
* Test convert bbcodes to HTML
2019-09-26 02:25:42 +02:00
*
2019-06-16 04:24:51 +02:00
* @ dataProvider dataBBCodes
*
* @ param string $expectedHtml Expected HTML output
* @ param string $text BBCode text
2019-09-26 02:25:42 +02:00
* @ param bool $try_oembed Whether to convert multimedia BBCode tag
2019-06-16 04:24:51 +02:00
* @ param int $simpleHtml BBCode :: convert method $simple_html parameter value , optional .
* @ param bool $forPlaintext BBCode :: convert method $for_plaintext parameter value , optional .
2020-10-18 20:31:57 +02:00
*
* @ throws InternalServerErrorException
2019-06-16 04:24:51 +02:00
*/
2020-10-18 20:31:57 +02:00
public function testConvert ( string $expectedHtml , string $text , $try_oembed = false , int $simpleHtml = 0 , bool $forPlaintext = false )
2019-06-16 04:24:51 +02:00
{
2019-09-26 02:25:42 +02:00
$actual = BBCode :: convert ( $text , $try_oembed , $simpleHtml , $forPlaintext );
2019-06-16 04:24:51 +02:00
2020-10-17 14:19:57 +02:00
self :: assertEquals ( $expectedHtml , $actual );
2019-06-16 04:24:51 +02:00
}
2019-12-21 05:20:41 +01:00
public function dataBBCodesToMarkdown ()
{
return [
'bug-7808-gt' => [
'expected' => '>`>`' ,
'text' => '>[code]>[/code]' ,
],
'bug-7808-lt' => [
'expected' => '<`<`' ,
'text' => '<[code]<[/code]' ,
],
'bug-7808-amp' => [
'expected' => '&`&`' ,
'text' => '&[code]&[/code]' ,
],
];
}
/**
* Test convert bbcodes to Markdown
*
* @ dataProvider dataBBCodesToMarkdown
*
2020-10-18 20:31:57 +02:00
* @ param string $expected Expected Markdown output
* @ param string $text BBCode text
2019-12-21 05:20:41 +01:00
* @ param bool $for_diaspora
2020-10-18 20:31:57 +02:00
*
* @ throws InternalServerErrorException
2019-12-21 05:20:41 +01:00
*/
2020-10-18 20:31:57 +02:00
public function testToMarkdown ( string $expected , string $text , $for_diaspora = false )
2019-12-21 05:20:41 +01:00
{
$actual = BBCode :: toMarkdown ( $text , $for_diaspora );
2020-10-17 14:19:57 +02:00
self :: assertEquals ( $expected , $actual );
2019-12-21 05:20:41 +01:00
}
2021-09-12 06:06:14 +02:00
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 );
}
2019-03-23 18:44:52 +01:00
}