Problem/Motivation
When adding a <script> or <style> elements to a filtered text field Html::escapeCdataElement() gets called by a number of filters via Html::normalize() or Html::serialize() which encloses the contents of the elements in a CDATA, but this is causing some issues.
Basically I have found 3 issues.
1. The opening and closing comments are being wrapped in a HTML comment which is not applicable to a script or a style element. See #3162421: Upgrade HTML::escapeCdataElement to correctly comment CDATA for a fix.
2. Since Html::escapeCdataElement() is called from multiple filters, (i.e. the HTML corrector and the Alignment filters) the CDATA's are not being nested correctly. Infact http://wikipedia.org/wiki/CDATA#Nesting and when it is being called 7 times you get a real mess.
<style type="text/css">
/*<![CDATA[*/
/*<![CDATA[*/
/*<![CDATA[*/
/*<![CDATA[*/
/*<![CDATA[*/
/*<![CDATA[*/
/*<![CDATA[*/
.content { max-width: 100%; }
/*<!]]]]]]]]]]]]]]><![CDATA[><![CDATA[><![CDATA[><![CDATA[><![CDATA[><![CDATA[>*/
/*<!]]]]]]]]]]]]><![CDATA[><![CDATA[><![CDATA[><![CDATA[><![CDATA[>*/
/*<!]]]]]]]]]]><![CDATA[><![CDATA[><![CDATA[><![CDATA[>*/
/*<!]]]]]]]]><![CDATA[><![CDATA[><![CDATA[>*/
/*<!]]]]]]><![CDATA[><![CDATA[>*/
/*<!]]]]><![CDATA[>*/
/*<!]]>*/
</style>
3. Lastly I do not think that we should be nesting CDATA. It is not needed,
Steps to reproduce
In a text filtered field add the following
<style>.content { max-width: 100%; }</style>
If you are using a text format which uses multiple filters like HTML filter, HTML Corrector filter, Align filter, it will result in the multiple nesting.
Proposed resolution
Add a check in the escapeCdataElement() if data contains CDATA and wrap that way.
Previous proposal
I am not sure we need the nesting behaviour, But how we check for it I am not 100% sure. I.e. Should be just search for CDATA or search for "\n{$comment_start}
Html::escapeCdataElement() is only called from Html::serialize() (In core) for script and style elements so really the nesting functionality could be removed.
API changes
If we correct the nesting behaviour to produce correct nesting we may want to add a flag to turn on and off the nesting just in case someone is relying on this feature.
| Comment | File | Size | Author |
|---|---|---|---|
| #25 | 3259255-25.patch | 5.73 KB | smustgrave |
| #25 | interdiff-23-25.txt | 988 bytes | smustgrave |
| #10 | 3259255-10.patch | 5.23 KB | gordon |
| #9 | interdiff-3259255-8-9.txt | 708 bytes | gordon |
| #9 | 3259255-9.patch | 5.24 KB | gordon |
Comments
Comment #2
gordon commentedHere is a first try.
I have included #3162421: Upgrade HTML::escapeCdataElement to correctly comment CDATA in this patch as it is such a small change in a larger issue.
I have decided that nesting should never be done and removed it altogether. However the way I have added this it would be easy to add it back in and resolve how it should nest correctly.
I have made the check so that it will only check for the presents of "CDATA" to determine if it should not be wrapped. This means that if the user wants to handle the handling of the CDATA wrapping themselves they can do it and it will not be done. Also if they do not want the CDATA wrapping they can just add a commented out CDATA and it will not changing anything.
Comment #3
gordon commentedSmall cleanup on the formatting of the CDATA.
Comment #4
gordon commentedMissed removing a trailing >
Comment #5
gordon commentedMake sure the output is identical to the examples in https://en.wikipedia.org/wiki/CDATA#Use_of_CDATA_in_program_output
Comment #6
cilefen commentedLet’s send this to the test bots. This will need a new unit test or alterations to an existing one, if any exists.
Comment #7
cilefen commentedSetting to needs work for test coverage.
Comment #8
gordon commentedI have fixed up the tests. Lets see if I got them all.
Comment #9
gordon commentedCorrect a couple of tests.
Comment #10
gordon commentedFix up another test issues.
Comment #11
gordon commentedFound another issue. Try again.
Comment #12
gordon commentedThis must be it.
Comment #13
gordon commentedThe tests are passing now. Basically it was just changing expected results to be the new format.
Comment #14
gordon commentedUpdate customer.
Comment #16
smustgrave commentedStill applies and passes 9.5 tests.
Test cases were also added
Comment #17
quietone commentedNice to see a working patch with tests.
The IS suggests adding a flag and I see no discussion here on that point. If this is changing behavior I expect we do need to consider not breaking things.
This still needs a code review and a fail patch. Setting back to NR.
Comment #18
smustgrave commentedHere's a tests only patch and reupload of #12
This issue came up today so thought I would move it forward.
As far as a flag change I'm not sure if that's needed anymore (could be mistaken) the current solution does not make use of any flag.
So maybe we drop that API change proposal?
Comment #19
smustgrave commentedNot sure what happened with the file upload
Comment #22
catchCan this be !str_contains() now?
The issue summary could use an update, I'm also wondering whether the current test coverage covers the nesting case that's in the issue summary.
Comment #23
smustgrave commentedComment #24
larowlanThe existing test method
\Drupal\Tests\filter\Kernel\FilterKernelTest::testHtmlCorrectorFilteris testing\Drupal\Component\Utility\Html::normalizebut none of the existing or new cases call Html::normalize twice per the originally reported issue.So I think we should add an extra test case that does that.
I think we should also open a follow up to move that test coverage out of the filter module, into the Utility component, it doesn't use any filter features.
Comment #25
smustgrave commentedOpened [#3352404
Added another assertion that calls normalize() twice.
Comment #26
borisson_This looks great, great test coverage!
Comment #28
catchCommitted 16a4426 and pushed to 10.1.x. Thanks!