PHP Fatal error: Cannot set directive after finalization

SteveX
SteveX
@ultrajam
10 years ago
2,584 posts
Very happy to see the change to add html5 elements to htmlpurifier in the latest core update - Thanks! :)

However, I have a problem with existing pages containing an editor field not loading and throwing a fatal error:
Quote:
[28-Jul-2015 19:01:29 Europe/Dublin] PHP Fatal error: Cannot set directive after finalization invoked on line 329 in file /home/academicskills/public_html/modules/ujEditorTemplates-release-0.6.2/include.php in /home/academicskills/public_html/modules/jrCore-release-5.2.37/contrib/htmlpurifier/HTMLPurifier.standalone.php on line 2607 [x 5]
The code on line 329 adds my bootstrap specific elements and reads:
$_data->set('HTML.AllowedElements', $_elem);

This has been working well up until today's update, do you know if this is something I need to fix within my module or is it something similar to where this error occurred back in December?
https://www.jamroom.net/the-jamroom-network/forum/jamroom-developers/18891/adding-attributes-to-htmlpurifier-in-a-listener


--
¯\_(ツ)_/¯ Education, learning resources, TEL, AR/VR/MR, CC licensed content, panoramas, interactive narrative, sectional modules (like jrDocs), lunch at Uni of Bristol. Get in touch if you share my current interests or can suggest better :)

updated by @ultrajam: 09/03/15 02:28:24AM
brian
@brian
10 years ago
10,149 posts
Yeah getting the HTML5 support in was a real pain - make sure in your module you are not calling autoFinalize() anywhere.

Let me know if that helps.


--
Brian Johnson
Founder and Lead Developer - Jamroom
https://www.jamroom.net
SteveX
SteveX
@ultrajam
10 years ago
2,584 posts
Thanks Brian.

No use of autoFinalize anywhere. The listener is just this (abbreviated):

function ujEditorTemplates_html_purifier_listener($_data, $_user, $_conf, $_args, $event)
{ $_elem = $_data->get('HTML.AllowedElements'); // Set additional Bootstrap elements $_elem['abbr'] = 1; $_elem['blockquote'] = 1; $_elem['cite'] = 1; // ...plus a load more of these... $_elem = implode(',', array_keys($_elem)); $_data->set('HTML.AllowedElements', $_elem); $_attr = $_data->get('HTML.AllowedAttributes'); // Set additional Bootstrap attributes $_attr['abbr.title'] = 1; $_attr['cite.title'] = 1; $_attr['blockquote.class'] = 1; // ...plus a load more of these... $_attr = implode(',', array_keys($_attr)); $_data->set('HTML.AllowedAttributes', $_attr); return $_data; }



--
¯\_(ツ)_/¯ Education, learning resources, TEL, AR/VR/MR, CC licensed content, panoramas, interactive narrative, sectional modules (like jrDocs), lunch at Uni of Bristol. Get in touch if you share my current interests or can suggest better :)

updated by @ultrajam: 07/28/15 12:34:42PM
brian
@brian
10 years ago
10,149 posts
Without the actual module I don't know. However I don't think you need this anymore, as those tags are now supported in the core.


--
Brian Johnson
Founder and Lead Developer - Jamroom
https://www.jamroom.net
SteveX
SteveX
@ultrajam
10 years ago
2,584 posts
The listener's the only part related to htmlpurifier - the rest is just templates, css and js with a button for using the templates in tinymce.

Why does htmlpurifier run on editor fields on their way out of the database? Shouldn't it clean the html once on save rather than each time a page with editor content is displayed?

We are supporting the full set of bootstrap classes, javascript (data-*) and aria attributes in TinyMCE. If it's in the bootstrap docs it needs to work in TinyMCE, and the accessibility features are essential.

I'm done for the night, so I'll roll back to the previous version of the core for tomorrow day and try this out again tomorrow evening.


--
¯\_(ツ)_/¯ Education, learning resources, TEL, AR/VR/MR, CC licensed content, panoramas, interactive narrative, sectional modules (like jrDocs), lunch at Uni of Bristol. Get in touch if you share my current interests or can suggest better :)
brian
@brian
10 years ago
10,149 posts
SteveX:
Why does htmlpurifier run on editor fields on their way out of the database? Shouldn't it clean the html once on save rather than each time a page with editor content is displayed?

No - because any changes to your rules would require to recreate the input.

Quote:
We are supporting the full set of bootstrap classes, javascript (data-*) and aria attributes in TinyMCE. If it's in the bootstrap docs it needs to work in TinyMCE, and the accessibility features are essential.

I'm done for the night, so I'll roll back to the previous version of the core for tomorrow day and try this out again tomorrow evening.

Sorry Steve - unfortunately HTML Purifier is not friendly to work with in ANY way - after this last round of battling it to get HTML 5 support I'm about ready to throw it out and either build my own replacement or look for something else.


--
Brian Johnson
Founder and Lead Developer - Jamroom
https://www.jamroom.net
SteveX
SteveX
@ultrajam
10 years ago
2,584 posts
There is a typo on line 1478 of util.php
Quote: emned.allowfullscreen
emned should be embed


--
¯\_(ツ)_/¯ Education, learning resources, TEL, AR/VR/MR, CC licensed content, panoramas, interactive narrative, sectional modules (like jrDocs), lunch at Uni of Bristol. Get in touch if you share my current interests or can suggest better :)

updated by @ultrajam: 07/29/15 05:46:57AM
SteveX
SteveX
@ultrajam
10 years ago
2,584 posts
This doesn't seem to be a problem with my module, but with adding to the whitelist (I tried disabling my modules and adding an attribute to the htmlpurifier whitelist in the jrFramer listener - got the same error).

I think I have a fix:

In order to add or set the whitelist (AllowedElements or AllowedAttributes) autoFinalize needs to be set to false before the html_purifier trigger event runs on line 1564 of /modules/jrCore/lib/util.php.
$pc->autoFinalize = false;
It actually did this until 5.2.37


--
¯\_(ツ)_/¯ Education, learning resources, TEL, AR/VR/MR, CC licensed content, panoramas, interactive narrative, sectional modules (like jrDocs), lunch at Uni of Bristol. Get in touch if you share my current interests or can suggest better :)
SteveX
SteveX
@ultrajam
10 years ago
2,584 posts
It is really strange though, I can set blockquote.class in my listener, but not blockquote.data-content.

To get blockquote.data-content to work I need to add it in my listener, and also in jrCore_strip_html alongside where you have added code to allow for data-lightbox. It doesn't seem to work if it is added in one place or the other, it needs to be in both.


--
¯\_(ツ)_/¯ Education, learning resources, TEL, AR/VR/MR, CC licensed content, panoramas, interactive narrative, sectional modules (like jrDocs), lunch at Uni of Bristol. Get in touch if you share my current interests or can suggest better :)

updated by @ultrajam: 07/29/15 09:41:15AM
michael
@michael
10 years ago
7,791 posts
Whats the setup to see this happening?
* ujEditorTemplates active and allowed via quota
* add something with a blockquote element with a data-content param (got the code for what you're using)
* add that to a blog post?

Want to setup on my local dev so I have a debugger.
---
Thanks for embed in util, fixed.
SteveX
SteveX
@ultrajam
10 years ago
2,584 posts
Thanks Michael.

Try adding elements and attributes to the whitelist using jrFramer - so set that active and allowed.

Replace jrFramer_html_purifier_listener with this:
function jrFramer_html_purifier_listener($_data,$_user,$_conf,$_args,$event)
{ if (isset($_conf['jrFramer_active']) && $_conf['jrFramer_active'] == 'on') { $_data->set('HTML.SafeIframe', true); $_data->set('URI.SafeIframeRegexp', '%(.*)%'); // ADDITIONAL TESTING CODE $_elem = $_data->get('HTML.AllowedElements'); // Set additional elements $_elem['abbr'] = 1; $_elem['blockquote'] = 1; $_elem['cite'] = 1; $_elem = implode(',', array_keys($_elem)); $_data->set('HTML.AllowedElements', $_elem); $_attr = $_data->get('HTML.AllowedAttributes'); // Set additional attributes $_attr['abbr.title'] = 1; $_attr['cite.title'] = 1; $_attr['blockquote.class'] = 1; // this needs to be present in the function in util.php as well $_attr['blockquote.data-content'] = 1; $_attr = implode(',', array_keys($_attr)); $_data->set('HTML.AllowedAttributes', $_attr); } return $_data; }

You will get the fatal error when visiting a page with an editor field in it.

To fix that error add this at line 1564 of util.php:
$pc->autoFinalize = false;

Then add blockquote and cite to your quota config Allowed HTML Tags if necessary.

Clear caches after each change to attributes or elements.

Then add this to an editor field and save:
<blockquote class="blockquote-reverse" data-content="test-content-12">
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>
  <footer>Someone famous in <cite title="Source Title">Source Title</cite></footer>
</blockquote>

data-content="test-content-12" will be stripped out on save. Which isn't what I expected to happen.

You can test that the listener is adding the attributes in by commenting out $_attr['blockquote.class'] = 1; then clearing caches, then saving the editor field again - the blockquote class will be stripped out. Remove the comment, clear caches, resave the editor field and the class will be saved.

So that is working fine with class, but not with data-content.

To get data-content to save it needs to be added in the listener, and ALSO in the jrCOre_strip_html function in util.php

Find this line:
$def->addAttribute('a', 'data-lightbox', 'Text');
and add this line after it:
$def->addAttribute('blockquote', 'data-content', 'Text');

Empty caches, save the editor field and the data-content attribute will be saved.
Comment out either the line whitelisting data-content in the jrCore_strip_html function OR jrFramer_html_purifier_listener (empty caches etc) and data-content will be stripped out. It needs to be allowed in both places.

This means that (once the fatal error has been fixed) with the current listener you cannot add to the attributes whitelist. Class, title etc can be whitelisted for an element, but not data elements, aria attributes, etc. They need to be allowed in BOTH places ('HTML.AllowedElements' and the HTML Definition), and adding via listener only adds in HTML.AllowedElements.


--
¯\_(ツ)_/¯ Education, learning resources, TEL, AR/VR/MR, CC licensed content, panoramas, interactive narrative, sectional modules (like jrDocs), lunch at Uni of Bristol. Get in touch if you share my current interests or can suggest better :)

updated by @ultrajam: 07/30/15 04:21:23AM
michael
@michael
10 years ago
7,791 posts
Sorry I didn't get to this today steve, I'll try to tomorrow.

--edit--
Thanks for the really great write up on how to get setup. :)
updated by @michael: 07/31/15 02:51:21AM
michael
@michael
10 years ago
7,791 posts
Without changing anything, if I have:
span,strong,em,a,b,u,i,p,div,br,img,h1,h2,h3,h4,pre,
hr,ul,ol,li,table,tbody,th,tr,td,figure,figcaption,
figure.class,figcaption.class,iframe,blockquote,footer,
cite,cite.class,cite.title,blockquote.class,blockquote.data-content
as the "Allowed HTML Tags" then the only thing that gets stripped out is that:
data-content=

looking for how to get to keep that now.
updated by @michael: 07/31/15 10:20:44PM
michael
@michael
10 years ago
7,791 posts
This looks related:
http://htmlpurifier.org/phorum/read.php?3,7261
Quote: .....they're not supported because they're not part of the HTML4 spec, so HTML Purifier doesn't know about them. If you're sure they're safe from an XSS perspective, you can teach HTML Purifier about them using http://htmlpurifier.org/docs/enduser-customize.html .....

and leads us to here:
http://htmlpurifier.org/docs/enduser-customize.html

Trying to figure out how to add custom definition of 'data-content' now.
SteveX
SteveX
@ultrajam
10 years ago
2,584 posts
Thanks Michael, try this:

This will work with Allowed HTML Tags (blockquote,blockquote.class,blockquote.data-content,cite,cite.title,footer)

In util.php jrCore_strip_html around line 1571 add this additional code after the line $def->addAttribute('a', 'data-lightbox', 'Text');:
// ------- additional code -------                    
// comment out unset($_att); on line 1559 in order for this to work
foreach ($_att as $attr) {
    if (!strpos($attr, ',')) { // ignore jamrooms lists of element.attributes defined above
        list($element,$attribute) = explode('.', $attr);
        $def->addAttribute($element, $attribute, 'Text'); // add to HTML Definition
    }
}
unset($_att);
// ------- end additional code -------  

NOTE: Comment out unset($_att); on line 1559 - we need that array in order for this to work.

Obviously that doesnt take into account anything added by the trigger listeners, but it works perfectly with the elements and attributes added to the quota Allowed HTML Tags (as far as I have tested).


--
¯\_(ツ)_/¯ Education, learning resources, TEL, AR/VR/MR, CC licensed content, panoramas, interactive narrative, sectional modules (like jrDocs), lunch at Uni of Bristol. Get in touch if you share my current interests or can suggest better :)

updated by @ultrajam: 08/02/15 08:52:17AM

Tags