Skip to content

Commit fc28f80

Browse files
authored
Fix EZP-26096: Custom tags' text line parameters not saved correctly (#1249)
1 parent 3929217 commit fc28f80

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

extension/ezoe/tests/ezoexmltext_regression.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,36 @@
99

1010
class eZOEXMLTextRegression extends ezpDatabaseTestCase
1111
{
12+
/**
13+
* Test for EZP-26096
14+
* @link https://jira.ez.no/browse/EZP-26096
15+
* @dataProvider providerParsingGreaterThanAttribute
16+
*/
17+
public function testParsingGreaterThanAttribute( $html, $expectedXml )
18+
{
19+
$parser = new eZOEInputParser();
20+
$dom = $parser->process( $html );
21+
22+
self::assertInstanceOf( 'DomDocument', $dom );
23+
self::assertEquals( $expectedXml, trim( $dom->saveXML() ) );
24+
}
25+
26+
public function providerParsingGreaterThanAttribute()
27+
{
28+
return array(
29+
array(
30+
'<div type="custom" class="ezoeItemCustomTag factbox" customattributes="title|This > is > a > fact > attribute_separationalign|right"><p>This is a fact</p></div>',
31+
'<?xml version="1.0" encoding="utf-8"?>
32+
<section xmlns:image="http://ez.no/namespaces/ezpublish3/image/" xmlns:xhtml="http://ez.no/namespaces/ezpublish3/xhtml/" xmlns:custom="http://ez.no/namespaces/ezpublish3/custom/"><paragraph xmlns:tmp="http://ez.no/namespaces/ezpublish3/temporary/"><custom name="factbox" custom:title="This &gt; is &gt; a &gt; fact &gt; "><paragraph>This is a fact</paragraph></custom></paragraph></section>',
33+
),
34+
array(
35+
'<div type="custom" class="ezoeItemCustomTag factbox" customattributes="title|<a href=&quot;#test&quot;>Test</a>attribute_separationalign|right"><p>This is a fact</p></div>',
36+
'<?xml version="1.0" encoding="utf-8"?>
37+
<section xmlns:image="http://ez.no/namespaces/ezpublish3/image/" xmlns:xhtml="http://ez.no/namespaces/ezpublish3/xhtml/" xmlns:custom="http://ez.no/namespaces/ezpublish3/custom/"><paragraph xmlns:tmp="http://ez.no/namespaces/ezpublish3/temporary/"><custom name="factbox" custom:title="&lt;a href=&amp;quot;#test&amp;quot;&gt;Test&lt;/a&gt;"><paragraph>This is a fact</paragraph></custom></paragraph></section>',
38+
)
39+
);
40+
}
41+
1242
/**
1343
* Test for issue #16605: Online Editor adds a lot of Non Breaking spaces (nbsp)
1444
*

kernel/classes/datatypes/ezxmltext/ezxmlinputparser.php

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ function parseTag( &$data, &$pos, &$parent )
413413
// Regular tag: get tag's name and attributes.
414414
else
415415
{
416-
$tagEndPos = strpos( $data, '>', $tagBeginPos );
416+
$tagEndPos = $this->findEndOpeningTagPosition( $data, $tagBeginPos );
417417
if ( $tagEndPos === false )
418418
{
419419
$pos = $tagBeginPos + 1;
@@ -583,6 +583,59 @@ function parseTag( &$data, &$pos, &$parent )
583583
Helper functions for pass 1
584584
*/
585585

586+
/**
587+
* Finds the postion of the > character which marks the end of the opening
588+
* tag that starts at $tagBeginPos in $data.
589+
* It's not as easy as it seems, because some '>' can also appear in attributes.
590+
* So we need to iterate over the next '>' characters to find the correct one.
591+
* See https://jira.ez.no/browse/EZP-26096
592+
*
593+
* @param string $data
594+
* @param integer $tagBeginPos
595+
* @param integer $offset used for recursive call when a > is found in an attribute.
596+
* @return integer|false
597+
*/
598+
private function findEndOpeningTagPosition( $data, $tagBeginPos, $offset = 0 )
599+
{
600+
$endPos = strpos( $data, '>', $tagBeginPos + $offset );
601+
if ( $endPos === false )
602+
{
603+
return false;
604+
}
605+
$tagCode = substr( $data, $tagBeginPos, $endPos - $tagBeginPos );
606+
if ( strpos( $tagCode, '=' ) === false )
607+
{
608+
// this tag has no attribute, so the next '>' is the right one.
609+
return $endPos;
610+
}
611+
if ( $this->isValidXmlTag( $tagCode ) )
612+
{
613+
return $endPos;
614+
}
615+
return $this->findEndOpeningTagPosition( $data, $tagBeginPos, $endPos + 1 );
616+
}
617+
618+
/**
619+
* Checks whether $code can be considered as a valid XML excerpt. If not,
620+
* it's probably because we found a '>' in the middle of an attribute.
621+
*
622+
* @param string $code
623+
* @return boolean
624+
*/
625+
private function isValidXmlTag( $code )
626+
{
627+
if ( $code[strlen( $code ) - 1] !== '/' )
628+
{
629+
$code .= '/';
630+
}
631+
$code .= '>';
632+
$code = '<' . str_replace( '<', '&lt;', substr( $code, 1 ) );
633+
$errorHanding = libxml_use_internal_errors( true );
634+
$simpleXml = simplexml_load_string( $code );
635+
libxml_use_internal_errors( $errorHanding );
636+
return ( $simpleXml !== false );
637+
}
638+
586639
function parseAttributes( $attributeString )
587640
{
588641
$attributes = array();

0 commit comments

Comments
 (0)