Log message for revision 74067: Issue #452: Make HTML scrubbing pluggable using a utility.
Changed: U CMF/branches/2.1/CHANGES.txt U CMF/branches/2.1/CMFDefault/interfaces/_content.py U CMF/branches/2.1/CMFDefault/tests/test_utils.py U CMF/branches/2.1/CMFDefault/utils.py -=- Modified: CMF/branches/2.1/CHANGES.txt =================================================================== --- CMF/branches/2.1/CHANGES.txt 2007-04-09 21:53:05 UTC (rev 74066) +++ CMF/branches/2.1/CHANGES.txt 2007-04-09 22:05:03 UTC (rev 74067) @@ -2,6 +2,11 @@ Bug Fixes + - Use a utility, registered for + 'Products.CMFDefault.interfaces.IHTMLScrubber', to perform scrubbing + of HTML; fall back to the old, hard-wired behavior. + (http://www.zope.org/Collectors/CMF/452) + - Remove antique usage of marker attributes in favor of interfaces, leaving BBB behind for places potentially affecting third-party code. (http://www.zope.org/Collectors/CMF/440) Modified: CMF/branches/2.1/CMFDefault/interfaces/_content.py =================================================================== --- CMF/branches/2.1/CMFDefault/interfaces/_content.py 2007-04-09 21:53:05 UTC (rev 74066) +++ CMF/branches/2.1/CMFDefault/interfaces/_content.py 2007-04-09 22:05:03 UTC (rev 74067) @@ -18,6 +18,12 @@ from zope.interface import Interface from zope.interface import Attribute +class IHTMLScrubber(Interface): + """ Utility inteface for scrubbing user-supplied HTML. + """ + def scrub(html): + """ Return 'scrubbed' HTML. + """ class IDocument(Interface): Modified: CMF/branches/2.1/CMFDefault/tests/test_utils.py =================================================================== --- CMF/branches/2.1/CMFDefault/tests/test_utils.py 2007-04-09 21:53:05 UTC (rev 74066) +++ CMF/branches/2.1/CMFDefault/tests/test_utils.py 2007-04-09 22:05:03 UTC (rev 74067) @@ -122,7 +122,7 @@ self.assertNotEqual( preloaded[ 'Author' ], headers[ 'Author' ] ) self.assertEqual( preloaded[ 'text_format' ], headers[ 'text_format' ] ) - def test_scrubHTML(self): + def test_scrubHTML_no_adapter_falls_back(self): from Products.CMFDefault.utils import scrubHTML self.assertEqual( scrubHTML('<a href="foo.html">bar</a>'), @@ -144,6 +144,46 @@ self.assertEqual( scrubHTML('<meta name="title" content="" /><meta>'), '<meta name="title" content="" /><meta />' ) + def test_scrubHTML_with_adapter(self): + from zope.interface import implements + from zope.component.testing import setUp + from zope.component.testing import tearDown + from zope.app.testing import ztapi + from Products.CMFDefault.interfaces import IHTMLScrubber + from Products.CMFDefault.utils import scrubHTML + + class _Scrubber: + implements(IHTMLScrubber) + def scrub(self, html): + return html.upper() + + + setUp() + try: + ztapi.provideUtility(IHTMLScrubber, _Scrubber()) + self.assertEqual( scrubHTML('<a href="foo.html">bar</a>'), + '<A HREF="FOO.HTML">BAR</A>' ) + self.assertEqual( scrubHTML('<b>bar</b>'), + '<B>BAR</B>' ) + self.assertEqual( scrubHTML('<base href="" /><base>'), + '<BASE HREF="" /><BASE>' ) + self.assertEqual( scrubHTML('<blockquote>bar</blockquote>'), + '<BLOCKQUOTE>BAR</BLOCKQUOTE>' ) + self.assertEqual( scrubHTML('<body bgcolor="#ffffff">bar</body>'), + '<BODY BGCOLOR="#FFFFFF">BAR</BODY>' ) + self.assertEqual( scrubHTML('<br /><br>'), + '<BR /><BR>' ) + self.assertEqual( scrubHTML('<hr /><hr>'), + '<HR /><HR>' ) + self.assertEqual( scrubHTML('<img src="foo.png" /><img>'), + '<IMG SRC="FOO.PNG" /><IMG>' ) + self.assertEqual( scrubHTML( + '<meta name="title" content="" /><meta>'), + '<META NAME="TITLE" CONTENT="" /><META>' ) + + finally: + tearDown() + def test_bodyfinder(self): from Products.CMFDefault.utils import bodyfinder Modified: CMF/branches/2.1/CMFDefault/utils.py =================================================================== --- CMF/branches/2.1/CMFDefault/utils.py 2007-04-09 21:53:05 UTC (rev 74066) +++ CMF/branches/2.1/CMFDefault/utils.py 2007-04-09 22:05:03 UTC (rev 74067) @@ -31,13 +31,15 @@ from zope import i18n from zope.component import getUtility +from zope.component import queryUtility from zope.i18n.interfaces import IUserPreferredCharsets from zope.i18nmessageid import MessageFactory from Products.CMFCore.interfaces import IPropertiesTool -from exceptions import EmailAddressInvalid -from exceptions import IllegalHTML +from Products.CMFDefault.interfaces import IHTMLScrubber +from Products.CMFDefault.exceptions import EmailAddressInvalid +from Products.CMFDefault.exceptions import IllegalHTML security = ModuleSecurityInfo( 'Products.CMFDefault.utils' ) @@ -294,10 +296,12 @@ from htmlentitydefs import entitydefs # replace entitydefs from sgmllib - def __init__( self ): + def __init__( self, valid_tags=None, nasty_tags=None ): SGMLParser.__init__( self ) self.result = "" + self.valid_tags = valid_tags or VALID_TAGS + self.nasty_tags = nasty_tags or NASTY_TAGS def handle_data( self, data ): @@ -321,7 +325,7 @@ def unknown_starttag(self, tag, attrs): """ Delete all tags except for legal ones. """ - if VALID_TAGS.has_key(tag): + if self.valid_tags.has_key(tag): self.result = self.result + '<' + tag @@ -340,12 +344,12 @@ self.result = '%s %s="%s"' % (self.result, k, v) endTag = '</%s>' % tag - if VALID_TAGS.get(tag): + if self.valid_tags.get(tag): self.result = self.result + '>' else: self.result = self.result + ' />' - elif NASTY_TAGS.get(tag): + elif self.nasty_tags.get(tag): msg = _(u"Dynamic tag '${tag}' not allowed.", mapping={'tag': tag}) raise IllegalHTML(msg) @@ -355,7 +359,7 @@ def unknown_endtag(self, tag): - if VALID_TAGS.get(tag): + if self.valid_tags.get(tag): self.result = "%s</%s>" % (self.result, tag) remTag = '</%s>' % tag @@ -365,7 +369,14 @@ def scrubHTML( html ): """ Strip illegal HTML tags from string text. + + o Prefer a utility, if registered. """ + scrubber = queryUtility(IHTMLScrubber) + + if scrubber is not None: + return scrubber.scrub(html) + parser = StrippingParser() parser.feed( html ) parser.close() _______________________________________________ CMF-checkins mailing list [email protected] http://mail.zope.org/mailman/listinfo/cmf-checkins
