Skip to content

Commit

Permalink
MDL-68738 wiki: Prevent URLs inside links from turning into another link
Browse files Browse the repository at this point in the history
There was a problem with wiki pages in the HTML markup syntax. If they
contain a link and the link text has a URL in it, that URL was converted
into another link. But it was not correctly nested and it caused
additional troubles with filters (particularly the multimedia filter if
the URL was a video such as on youtube).

The solution here is similar to what we do in filters. We protect the
whole explicit link so that its content is not further parsed. That
prevents the inner URL to be converted into another link and the
explicit link has the full control.
  • Loading branch information
mudrd8mz authored and stronk7 committed May 21, 2020
1 parent 0aadca7 commit e67a606
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 0 deletions.
9 changes: 9 additions & 0 deletions mod/wiki/parser/markups/html.php
Expand Up @@ -46,6 +46,15 @@ protected function before_parsing() {
parent::before_parsing();

$this->minheaderlevel = $this->find_min_header_level($this->string);

// Protect all explicit links from further wiki parsing. The link text may contain another URL which would get
// converted into another link via {@see nwiki_parser::$tagrules} 'url' element.
if (preg_match_all('/<a\s[^>]+?>(.*?)<\/a>/is', $this->string, $matches)) {
foreach (array_unique($matches[0]) as $match) {
$this->string = str_replace($match, $this->protect($match), $this->string);
}
}

$this->rules($this->string);
}

Expand Down
86 changes: 86 additions & 0 deletions mod/wiki/tests/wikiparser_test.php
Expand Up @@ -39,6 +39,92 @@

class mod_wiki_wikiparser_test extends basic_testcase {

/**
* URL inside the clickable text of some link should not be turned into a new link via the url_tag_rule.
*
* @dataProvider urls_inside_link_text_provider
* @param string $markup Markup of the Wiki page the text is part of.
* @param string $input The input text.
* @param string $output The expected output HTML as a result of the parsed input text.
*/
public function test_urls_inside_link_text(string $markup, string $input, string $output) {

$parsingresult = wiki_parser_proxy::parse($input, $markup, [
'link_callback' => '/mod/wiki/locallib.php:wiki_parser_link',
'link_callback_args' => ['swid' => 1],
]);

$this->assertContains($output, $parsingresult['parsed_text']);
}

/**
* Provides data sets for {@see self::test_urls_inside_link_text()}.
*
* @return array
*/
public function urls_inside_link_text_provider() {
return [
'creole implicit link' => [
'markup' => 'creole',
'input' => 'Visit https://site.url for more information.',
'output' => 'Visit <a href="https://site.url">https://site.url</a> for more information.',
],
'creole explicit link' => [
'markup' => 'creole',
'input' => 'Visit [[https://site.url]] for more information.',
'output' => 'Visit <a href="https://site.url">https://site.url</a> for more information.',
],
'creole explicit link with text' => [
'markup' => 'creole',
'input' => 'Visit [[https://site.url|http://www.site.url]] for more information.',
'output' => 'Visit <a href="https://site.url">http://www.site.url</a> for more information.',
],
'nwiki implicit link' => [
'markup' => 'nwiki',
'input' => 'Visit https://site.url for more information.',
'output' => 'Visit <a href="https://site.url">https://site.url</a> for more information.',
],
'nwiki explicit link' => [
'markup' => 'nwiki',
'input' => 'Visit [https://site.url] for more information.',
'output' => 'Visit <a href="https://site.url">https://site.url</a> for more information.',
],
'nwiki explicit link with space separated text' => [
'markup' => 'nwiki',
'input' => 'Visit [https://site.url http://www.site.url] for more information.',
'output' => 'Visit <a href="https://site.url">http://www.site.url</a> for more information.',
],
'nwiki explicit link with pipe separated text' => [
'markup' => 'nwiki',
'input' => 'Visit [https://site.url|http://www.site.url] for more information.',
'output' => 'Visit <a href="https://site.url">http://www.site.url</a> for more information.',
],
'html implicit link' => [
'markup' => 'html',
'input' => 'Visit https://site.url for more information.',
'output' => 'Visit <a href="https://site.url">https://site.url</a> for more information.',
],
'html explicit link with text' => [
'markup' => 'html',
'input' => 'Visit <a href="https://site.url">http://www.site.url</a> for more information.',
'output' => 'Visit <a href="https://site.url">http://www.site.url</a> for more information.',
],
'html wiki link to non-existing page' => [
'markup' => 'html',
'input' => 'Visit [[Another page]] for more information.',
'output' => 'Visit <a class="wiki_newentry" ' .
'href="https://www.example.com/moodle/mod/wiki/create.php?swid=1&amp;title=Another+page&amp;action=new">' .
'Another page</a> for more information.',
],
'html wiki link inside an explicit link' => [
// The explicit href URL takes precedence here, the [[...]] is not turned into a wiki link.
'markup' => 'html',
'input' => 'Visit <a href="https://site.url">[[Another page]]</a> for more information.',
'output' => 'Visit <a href="https://site.url">[[Another page]]</a> for more information.',
],
];
}

function testCreoleMarkup() {
$this->assertTestFiles('creole');
}
Expand Down

0 comments on commit e67a606

Please sign in to comment.