Products.CMFPlone/midsummersprint_fix_transforms: sync safe_html settings with tinymce

Gil Forcada <jenkins-z4DKO/[email protected]>
Newsgroups gmane.comp.web.zope.plone.cvs
Message-ID <[email protected]>
Repository: Products.CMFPlone
Branch: refs/heads/midsummersprint_fix_transforms
Date: 2017-07-13T22:58:33+02:00
Author: MrTango (MrTango) <md-r4/[email protected]>
Commit: https://github.com/plone/Products.CMFPlone/commit/8f7505b822e5f61be1108087700ebbe0d174f2b5

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 bf634613c..a3e76609d 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.