Page MenuHomePhabricator

Bug1310.patch

Authored By
bzimport
Nov 21 2014, 8:11 PM
Size
5 KB
Referenced Files
None
Subscribers
None

Bug1310.patch

Index: tests/phpunit/includes/parser/NestingTest.php
===================================================================
--- tests/phpunit/includes/parser/NestingTest.php (revision 0)
+++ tests/phpunit/includes/parser/NestingTest.php (revision 0)
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * @group Parser
+ */
+class NestingTest extends MediaWikiTestCase {
+
+ function provideCases() {
+ return array(
+ array( "<foo>123</foo>", "foo", "123", array() ),
+ array( "<foo>foo</foo>", "foo", "foo", array() ),
+ array( "A<foo>foo</Foo>B", "foo", "foo", array() ),
+ array( "A<foo a=1 b='foo'>123<foo>456</foo>789</foo>B", "foo", "123<foo>456</foo>789", array( "a" => "1", "b" => "foo" ) ),
+ array( "<foo<foo", "foo", null, null ),
+
+ array(
+ "<ref name=\"citation:1\">" .
+ "<ref name=\"Other2001\"/>" .
+ "<ref name=\"YetAnother2004\"/>" .
+ "</ref>",
+ "ref", "<ref name=\"Other2001\"/><ref name=\"YetAnother2004\"/>", array( "name" => "citation:1" )
+ ),
+
+ array( "<ref name='x' foo ><ref/></ref >", "ref", "<ref/>", array( "name" => "x", "foo" => "foo" ) )
+
+
+ );
+ }
+
+ function provideNotWorkingCases() {
+ return array(
+ array( "<foo a='<foo>'>123</foo>", "foo", null, null ),
+ array( "<foo foo='123'>123<!--</foo>-->456</foo>", "foo", "123456", array( "foo" => "123" ) ),
+ );
+ }
+
+ var $mInnerText;
+ var $mParams;
+
+ /**
+ * @dataProvider provideCases
+ */
+ function testCases( $wikiText, $tag, $expectedInnerText, $expectedParams ) {
+ global $wgParserConf;
+ $parser = new Parser( $wgParserConf );
+
+ $parser->setHook( $tag, array( $this, 'tagCallback' ) );
+ $parserOutput = $parser->parse( $wikiText, Title::newFromText( 'Test' ), new ParserOptions );
+
+ $this->assertEquals( $expectedInnerText, $this->mInnerText );
+ $this->assertEquals( $expectedParams, $this->mParams );
+
+ $parser->mPreprocessor = null; # Break the Parser <-> Preprocessor cycle
+ }
+
+ function tagCallback( $innerText, $params, $parser ) {
+ $this->mInnerText = $innerText;
+ $this->mParams = $params;
+
+ return "dummy";
+ }
+}
Index: includes/parser/Preprocessor_DOM.php
===================================================================
--- includes/parser/Preprocessor_DOM.php (revision 110110)
+++ includes/parser/Preprocessor_DOM.php (working copy)
@@ -413,18 +413,51 @@
$close = '';
} else {
$attrEnd = $tagEndPos;
- // Find closing tag
- if ( preg_match( "/<\/" . preg_quote( $name, '/' ) . "\s*>/i",
- $text, $matches, PREG_OFFSET_CAPTURE, $tagEndPos + 1 ) )
- {
- $inner = substr( $text, $tagEndPos + 1, $matches[0][1] - $tagEndPos - 1 );
- $i = $matches[0][1] + strlen( $matches[0][0] );
- $close = '<close>' . htmlspecialchars( $matches[0][0] ) . '</close>';
- } else {
- // No end tag -- let it run out to the end of the text.
+
+ // we know that one start tag was already found
+ $numOfStartTags = 1;
+ $numOfEndTags = 0;
+ $offset = $tagEndPos;
+ $pattern = "/<" . preg_quote( $name, '/' ) . "[^>]*>" . "|" . "<\/" . preg_quote( $name, '/' ) . "\s*>/i";
+
+ while( $numOfStartTags != $numOfEndTags ) {
+ // match start tag or end tag
+ if( preg_match( $pattern, $text, $matches, PREG_OFFSET_CAPTURE, $offset + 1 ) === 0 ) {
+ // nothing found
+ break;
+ }
+
+ // what is it, start or end tag?
+ if( substr( $matches[ 0 ][ 0 ], 0, 2 ) === "</" ) {
+ $numOfEndTags++;
+ } else {
+ $numOfStartTags++;
+ }
+
+ $previousMatches = $matches;
+ $offset = $matches[ 0 ][ 1 ];
+ }
+
+ if( $numOfEndTags === 0 ) {
+ // no end tag, swallow everything
$inner = substr( $text, $tagEndPos + 1 );
$i = strlen( $text );
$close = '';
+
+ } else {
+
+ if( $numOfStartTags === $numOfEndTags ) {
+ // match made in heaven, all start tags have end tags
+ $inner = substr( $text, $tagEndPos + 1, $offset - ( $tagEndPos + 1 ) );
+ $i = $offset + strlen( $matches[0][0] );
+ $close = '<close>' . htmlspecialchars( $matches[0][0] ) . '</close>';
+
+ } else {
+ // not balanced, at least one start tag is orphan
+ $inner = substr( $text, $tagEndPos + 1, $offset - ( $tagEndPos + 1 ) );
+ $i = $offset + strlen( $previousMatches[0][0] );
+ $close = '<close>' . htmlspecialchars( $previousMatches[0][0] ) . '</close>';
+ }
}
}
// <includeonly> and <noinclude> just become <ignore> tags

File Metadata

Mime Type
text/x-diff
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1407
Default Alt Text
Bug1310.patch (5 KB)

Event Timeline