MyBB Community Forums

Full Version: Wiki plugin internal link tag parsing bug
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I've installed the wiki plugin by Matthias M. (http://mods.mybb.com/view/wiki).

The tags for internal links to other wiki pages ([wiki ]...[/wiki ]) generate the expected link if they appear on a line by themselves, but get ignored (the opening and closing tags and their contents appear as raw text when the wiki page is viewed) when any text appears before or after the tags on the same line.

I've looked over the plugin source files, but can't identify where the [wiki ] tags are being parsed.

Has anyone else found a way to fix this problem?
inc/plugins/wiki.php::wiki_parse_wiki_tag()

try changing '#\[wiki\](.+)\[/wiki\]#' to '#\[wiki\](.+?)\[/wiki\]#', that's the only obvious error I see

it would only affect having more than one [Wiki: ] (Broken link, head over to docs.mybb.com instead) tag in a line though. Any other text should be fine.
(2013-04-02, 07:01 PM)frostschutz Wrote: [ -> ]inc/plugins/wiki.php::wiki_parse_wiki_tag()

try changing '#\[wiki\](.+)\[/wiki\]#' to '#\[wiki\](.+?)\[/wiki\]#', that's the only obvious error I see

it would only affect having more than one [Wiki: ] (Broken link, head over to docs.mybb.com instead) tag in a line though. Any other text should be fine.

Thank you. That's exactly the spot where the code needed fixing.

However, the problem was different from what I thought, and the solution is different from what you propose.

The problem was not that [wiki ] tags weren't being parsed if they shared a line with any other text. The problem was that [wiki ] tags weren't being parsed if there were multiple [wiki ] tags on the same line. It's because by default regular expressions are "greedy", that is they will take the longest possible string when a pattern matches multiple possible strings. If a line contains multiple [wiki ] tags, the regular expression #\[wiki\](.+)\[/wiki\]# will match the the opening tag of the first set, the closing tag of the last set, and considers everything in between, including other [wiki ] tags and any other text appearing between the first and last [wiki ] tags to be the name of the target wiki page.

The fix is to turn off the regular expression's default greediness by adding the modifier 'U' to the expression: #\[wiki\](.+)\[/wiki\]#U

This ungreedy version of the regular expression will match the shortest possible string when the pattern matches multiple possible strings, therefore preventing the match from spanning multiple [wiki ] tags and guaranteeing that the text between the matched opening and closing tags will be just the target wiki page name.

My modified version of inc/plugins/wiki.php::wiki_parse_wiki_tag():
function wiki_parse_wiki_tag(&$message)
{
	return preg_replace_callback('#\[wiki\](.+)\[/wiki\]#U', 'wiki_build_tag', $message);
}
And how is that different from using .+? (the ? making the + non-greedy)
Oops, it's not.Blush

Question-mark-after-quantifier-for-nongreedy is a new regexp trick for me. I know I'm going to confuse it with the zero-or-one-occurences quantifier question mark.Huh

To clarify, frostschutz's regular expression (#\[wiki\](.+?)\[/wiki\]#) should work as well as mine (#\[wiki\](.+)\[/wiki\]#U).