Products.CMFPlone/robodoc: sync safe_html settings with tinymce
Peter Holzer <jenkins-z4DKO/[email protected]> Fri, 28 Jul 2017 05:39:02 -0700 (PDT)
| Newsgroups | gmane.comp.web.zope.plone.cvs |
|---|---|
| Message-ID | <[email protected]> |
Repository: Products.CMFPlone Branch: refs/heads/robodoc Date: 2017-07-28T12:36:55+02:00 Author: MrTango (MrTango) <md-r4/[email protected]> Commit: https://github.com/plone/Products.CMFPlone/commit/946f3b3cee049646d3cf1eb0f176e9cb3c743a54 sync safe_html settings with tinymce Files changed: M Products/CMFPlone/controlpanel/browser/filter.py M Products/CMFPlone/interfaces/controlpanel.py M Products/CMFPlone/patterns/settings.py M Products/CMFPlone/patterns/tinymce.py M Products/CMFPlone/tests/robot/test_controlpanel_filter.robot M setup.py diff --git a/Products/CMFPlone/controlpanel/browser/filter.py b/Products/CMFPlone/controlpanel/browser/filter.py index e9aebedb7..8c822d855 100644 --- a/Products/CMFPlone/controlpanel/browser/filter.py +++ b/Products/CMFPlone/controlpanel/browser/filter.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- +from plone.app.registry.browser import controlpanel from plone.z3cform import layout from Products.CMFPlone import PloneMessageFactory as _ # NOQA from Products.CMFPlone.interfaces import IFilterSchema from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile -from plone.app.registry.browser import controlpanel from Products.statusmessages.interfaces import IStatusMessage from z3c.form import button diff --git a/Products/CMFPlone/interfaces/controlpanel.py b/Products/CMFPlone/interfaces/controlpanel.py index fb28d4cc0..a8d7d4a83 100644 --- a/Products/CMFPlone/interfaces/controlpanel.py +++ b/Products/CMFPlone/interfaces/controlpanel.py @@ -365,90 +365,90 @@ class IFilterSchema(Interface): title=_(u'Valid tags'), description=_(u'A list of valid tags which will be not filtered out.'), default=[ - 'a', - 'abbr', - 'acronym', - 'address', - 'article', - 'aside', - 'audio', - 'b', - 'bdo', - 'big', - 'blockquote', - 'body', - 'br', - 'canvas', - 'caption', - 'cite', - 'code', - 'col', - 'colgroup', - 'command', - 'datalist', - 'dd', - 'del', - 'details', - 'dfn', - 'dialog', - 'div', - 'dl', - 'dt', - 'em', - 'figure', - 'footer', - 'h1', - 'h2', - 'h3', - 'h4', - 'h5', - 'h6', - 'head', - 'header', - 'hgroup', - 'html', - 'i', - 'iframe', - 'img', - 'ins', - 'kbd', - 'keygen', - 'li', - 'map', - 'mark', - 'meter', - 'nav', - 'ol', - 'output', - 'p', - 'pre', - 'progress', - 'q', - 'rp', - 'rt', - 'ruby', - 'samp', - 'section', - 'small', - 'source', - 'span', - 'strong', - 'sub', - 'sup', - 'table', - 'tbody', - 'td', - 'tfoot', - 'th', - 'thead', - 'time', - 'title', - 'tr', - 'tt', - 'u', - 'ul', - 'var', - 'video', + u'a', + u'abbr', + u'acronym', + u'address', + u'article', + u'aside', + u'audio', + u'b', + u'bdo', + u'big', + u'blockquote', + u'body', + u'br', + u'canvas', + u'caption', + u'cite', + u'code', + u'col', + u'colgroup', + u'command', + u'datalist', + u'dd', + u'del', + u'details', + u'dfn', + u'dialog', + u'div', + u'dl', + u'dt', + u'em', + u'figure', + u'footer', + u'h1', + u'h2', + u'h3', + u'h4', + u'h5', + u'h6', + u'head', + u'header', + u'hgroup', + u'html', + u'i', + u'iframe', + u'img', + u'ins', + u'kbd', + u'keygen', + u'li', + u'map', + u'mark', + u'meter', + u'nav', + u'ol', + u'output', + u'p', + u'pre', + u'progress', + u'q', + u'rp', + u'rt', + u'ruby', + u'samp', + u'section', + u'small', + u'source', + u'span', + u'strong', + u'sub', + u'sup', + u'table', + u'tbody', + u'td', + u'tfoot', + u'th', + u'thead', + u'time', + u'title', + u'tr', + u'tt', + u'u', + u'ul', + u'var', + u'video', ], value_type=schema.TextLine(), missing_value=[], diff --git a/Products/CMFPlone/patterns/settings.py b/Products/CMFPlone/patterns/settings.py index c568c07fc..5f3ae140f 100644 --- a/Products/CMFPlone/patterns/settings.py +++ b/Products/CMFPlone/patterns/settings.py @@ -3,7 +3,6 @@ from Acquisition import aq_parent from borg.localrole.interfaces import IFactoryTempFolder from plone.app.content.browser.interfaces import IFolderContentsView -from plone.app.layout.navigation.root import getNavigationRootObject from plone.app.widgets.utils import get_relateditems_options from plone.app.z3cform.utils import call_callables from plone.registry.interfaces import IRegistry @@ -81,7 +80,9 @@ def image_scales(self): 'plone.app.vocabularies.ImagesScales' ) vocabulary = factory(self.context) - ret = [{'title': translate(it.title), 'value': it.value} for it in vocabulary] + ret = [{ + 'title': translate(it.title), 'value': it.value} + for it in vocabulary] ret = sorted(ret, key=lambda it: it['title']) return json.dumps(ret) diff --git a/Products/CMFPlone/patterns/tinymce.py b/Products/CMFPlone/patterns/tinymce.py index 5e9e5dc14..b66f499c6 100644 --- a/Products/CMFPlone/patterns/tinymce.py +++ b/Products/CMFPlone/patterns/tinymce.py @@ -1,8 +1,10 @@ # -*- coding: utf-8 -*- +from lxml import html from plone.app.layout.navigation.root import getNavigationRootObject from plone.app.theming.utils import theming_policy from plone.registry.interfaces import IRegistry from Products.CMFCore.utils import getToolByName +from Products.CMFPlone.interfaces import IFilterSchema from Products.CMFPlone.interfaces import ITinyMCESchema from Products.CMFPlone.utils import get_portal from zope.component import getUtility @@ -20,6 +22,11 @@ def __init__(self, context, request): prefix="plone", check=False ) + self.filter_settings = getUtility(IRegistry).forInterface( + IFilterSchema, + prefix="plone", + check=False + ) self.nav_root = getNavigationRootObject( self.context, get_portal(), @@ -197,6 +204,19 @@ def get_tiny_config(self): except ValueError: pass + # add safe_html settings, which are useed in backend for filtering: + if not self.filter_settings.disable_filtering: + valid_tags = self.filter_settings.valid_tags + custom_attributes = self.filter_settings.custom_attributes + safe_attributes = [attr.decode() for attr in html.defs.safe_attrs] + valid_attributes = safe_attributes + custom_attributes + # valid_elements : 'a[href|target=_blank],strong/b,div[align],br' + tiny_valid_elements = [] + for tag in valid_tags: + tag_str = "%s[%s]" % (tag, "|".join(valid_attributes)) + tiny_valid_elements.append(tag_str) + tiny_config['valid_elements'] = ",".join(tiny_valid_elements) + if settings.other_settings: try: tiny_config.update(json.loads(settings.other_settings)) diff --git a/Products/CMFPlone/tests/robot/test_controlpanel_filter.robot b/Products/CMFPlone/tests/robot/test_controlpanel_filter.robot index e55d39b56..b8698c6e1 100644 --- a/Products/CMFPlone/tests/robot/test_controlpanel_filter.robot +++ b/Products/CMFPlone/tests/robot/test_controlpanel_filter.robot @@ -14,6 +14,7 @@ Resource plone/app/robotframework/keywords.robot Resource plone/app/robotframework/saucelabs.robot Library Remote ${PLONE_URL}/RobotRemote +Library Collections Resource keywords.robot @@ -32,26 +33,20 @@ Scenario: Configure Filter Control Panel to filter out nasty tags Scenario: Configure Filter Control Panel to strip out tags Given a logged-in site administrator and the filter control panel - When I add 'h1' to the stripped tags list + When I remove 'h1' from the valid tags list Then the 'h1' tag is stripped when a document is saved Scenario: Configure Filter Control Panel to allow custom tags Given a logged-in site administrator and the filter control panel - When I add 'marquee' to the custom tags list - Then the 'marquee' tag is preserved when a document is saved + When I add 'foobar' to the valid tags list + Then the 'foobar' tag is preserved when a document is saved -Scenario: Configure Filter Control Panel to strip out attributes +Scenario: Configure Filter Control Panel to allow custom attributes Given a logged-in site administrator and the filter control panel - When I add 'data-stripme' to the stripped attributes list - Then the 'data-stripme' attribute is stripped when a document is saved - -Scenario: Configure Filter Control Panel to allow style attributes - Given a logged-in site administrator - and the filter control panel - When I add 'display' to the allowed style attributes - Then the 'display' style attribute is preserved when a document is saved + When I add 'foo-foo' to the custom attributes list + Then the 'foo-foo' attribute is preserved when a document is saved Scenario: Filter Control Panel displays information regarding caching when saved Given a logged-in site administrator @@ -82,23 +77,18 @@ I add '${tag}' to the nasty tags list Click Button Save Wait until page contains Changes saved -I add '${tag}' to the stripped tags list - Input Text name=form.widgets.stripped_tags ${tag} - Click Button Save - Wait until page contains Changes saved - -I add '${tag}' to the custom tags list - Input Text name=form.widgets.custom_tags ${tag} +I remove '${tag}' from the valid tags list + Remove line from textarea form.widgets.valid_tags ${tag} Click Button Save Wait until page contains Changes saved -I add '${tag}' to the stripped attributes list - Input Text name=form.widgets.stripped_attributes ${tag} +I add '${tag}' to the valid tags list + Input Text name=form.widgets.valid_tags ${tag} Click Button Save Wait until page contains Changes saved -I add '${tag}' to the allowed style attributes - Input text name=form.widgets.style_whitelist ${tag} +I add '${tag}' to the custom attributes list + Input Text name=form.widgets.custom_attributes ${tag} Click Button Save Wait until page contains Changes saved @@ -128,50 +118,23 @@ the 'h1' tag is stripped when a document is saved Page should contain heading XPath Should Match X Times //div[@id='content-core']//h1 0 message=h1 should have been stripped out -the 'marquee' tag is preserved when a document is saved +the '${tag}' tag is preserved when a document is saved ${doc1_uid}= Create content id=doc1 title=Document 1 type=Document Go To ${PLONE_URL}/doc1/edit patterns are loaded - Input RichText <marquee>lorem ipsum</marquee> + Input RichText <${tag}>lorem ipsum</${tag}> Click Button Save Wait until page contains Changes saved - XPath Should Match X Times //div[@id='content-core']//marquee 1 message=the marquee tag should have been preserved + XPath Should Match X Times //div[@id='content-core']//${tag} 1 message=the ${tag} tag should have been preserved -the 'data-stripme' attribute is stripped when a document is saved +the '${attribute}' attribute is preserved when a document is saved ${doc1_uid}= Create content id=doc1 title=Document 1 type=Document Go To ${PLONE_URL}/doc1/edit patterns are loaded - Input RichText <h4 data-stripme="foo">lorem ipsum</h4> + Input RichText <span ${attribute}="foo">lorem ipsum</span> Click Button Save Wait until page contains Changes saved - Page should contain lorem ipsum - - XPath Should Match X Times //*[@id='content-core']//h4 1 message=h4 tag should be present - XPath Should Match X Times //*[@id='content-core']//h4[@data-stripme='foo'] 0 message=data-stripme attribute should have been filtered out - -the 'foobar' class is filtered out when a document is saved - ${doc1_uid}= Create content id=doc1 title=Document 1 type=Document - Go To ${PLONE_URL}/doc1/edit - patterns are loaded - Input RichText <h4 class="foobar">lorem ipsum</h4> - Click Button Save - Wait until page contains Changes saved - Page should contain lorem ipsum - - XPath Should Match X Times //*[@id='content-core']//h4 1 message=h4 tag should be present - XPath Should Match X Times //*[@id='content-core']//h4[@class='foobar'] 0 message=class foobar should have been filtered out - -the 'display' style attribute is preserved when a document is saved - ${doc1_uid}= Create content id=doc1 title=Document 1 type=Document - Go To ${PLONE_URL}/doc1/edit - patterns are loaded - Input RichText <h4 style="display: block">lorem ipsum</h4> - Click Button Save - Wait until page contains Changes saved - Page should contain lorem ipsum - - XPath Should Match X Times //*[@id='content-core']//h4 1 message=h4 tag should be present - XPath Should Match X Times //*[@id='content-core']//h4[@style] 1 message=style attribute with display:block should be present + XPath Should Match X Times //span[@${attribute}] 1 message=the ${attribute} tag should have been preserved success message should contain information regarding caching Element Should Contain css=.portalMessage.warning HTML generation is heavily cached across Plone. You may have to edit existing content or restart your server to see the changes. diff --git a/setup.py b/setup.py index 2764017a2..1819071b8 100644 --- a/setup.py +++ b/setup.py @@ -37,6 +37,7 @@ 'lxml', 'mock', 'plone.app.robotframework>0.9.16', + 'robotframework-debuglibrary', 'plone.app.testing', 'zope.globalrequest', 'zope.testing', ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot