Log message for revision 76433: Alternate approach to forbidding file inclusion in reStructuredText that's used from Zope: * ship with a standard docutils package * don't monkey patch docutils functions, rather change the default setting for file_inclusion_enabled in the docutils parser. This changes the behaviour, however. Instead of failing with a NotImplementedError, users will now see the rendered document with a warning message. I think this is much more sensible, anyway.
Changed: _U Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/ U Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/DocumentTemplate/tests/testDTML.py U Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/Products/ZReST/ZReST.py U Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/Products/ZReST/tests/test_ZReST.py U Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/reStructuredText/__init__.py U Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/reStructuredText/tests/testReST.py -=- Property changes on: Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python ___________________________________________________________________ Name: svn:externals - ZConfig svn://svn.zope.org/repos/main/ZConfig/tags/ZConfig-2.3.1 BTrees -r 68677 svn://svn.zope.org/repos/main/ZODB/branches/3.7/src/BTrees persistent -r 68677 svn://svn.zope.org/repos/main/ZODB/branches/3.7/src/persistent ThreadedAsync -r 68677 svn://svn.zope.org/repos/main/ZODB/branches/3.7/src/ThreadedAsync transaction -r 68677 svn://svn.zope.org/repos/main/ZODB/branches/3.7/src/transaction ZEO -r 68677 svn://svn.zope.org/repos/main/ZODB/branches/3.7/src/ZEO ZODB -r 68677 svn://svn.zope.org/repos/main/ZODB/branches/3.7/src/ZODB ZopeUndo -r 68677 svn://svn.zope.org/repos/main/ZODB/branches/3.7/src/ZopeUndo zdaemon -r 40792 svn://svn.zope.org/repos/main/zdaemon/trunk/src/zdaemon pytz -r 69031 svn://svn.zope.org/repos/main/Zope3/branches/3.3/src/pytz zodbcode -r 69031 svn://svn.zope.org/repos/main/Zope3/branches/3.3/src/zodbcode mechanize -r 69031 svn://svn.zope.org/repos/main/Zope3/branches/3.3/src/mechanize docutils svn://svn.zope.org/repos/main/docutils/tags/0.4.0-zope ClientForm svn://svn.zope.org/repos/main/Zope3/trunk/src/ClientForm RestrictedPython svn://svn.zope.org/repos/main/RestrictedPython/tags/3.4.0/src/RestrictedPython + ZConfig svn://svn.zope.org/repos/main/ZConfig/tags/ZConfig-2.3.1 BTrees -r 68677 svn://svn.zope.org/repos/main/ZODB/branches/3.7/src/BTrees persistent -r 68677 svn://svn.zope.org/repos/main/ZODB/branches/3.7/src/persistent ThreadedAsync -r 68677 svn://svn.zope.org/repos/main/ZODB/branches/3.7/src/ThreadedAsync transaction -r 68677 svn://svn.zope.org/repos/main/ZODB/branches/3.7/src/transaction ZEO -r 68677 svn://svn.zope.org/repos/main/ZODB/branches/3.7/src/ZEO ZODB -r 68677 svn://svn.zope.org/repos/main/ZODB/branches/3.7/src/ZODB ZopeUndo -r 68677 svn://svn.zope.org/repos/main/ZODB/branches/3.7/src/ZopeUndo zdaemon -r 40792 svn://svn.zope.org/repos/main/zdaemon/trunk/src/zdaemon pytz -r 69031 svn://svn.zope.org/repos/main/Zope3/branches/3.3/src/pytz zodbcode -r 69031 svn://svn.zope.org/repos/main/Zope3/branches/3.3/src/zodbcode mechanize -r 69031 svn://svn.zope.org/repos/main/Zope3/branches/3.3/src/mechanize docutils svn://svn.zope.org/repos/main/docutils/tags/0.4.0 ClientForm svn://svn.zope.org/repos/main/Zope3/trunk/src/ClientForm RestrictedPython svn://svn.zope.org/repos/main/RestrictedPython/tags/3.4.0/src/RestrictedPython Modified: Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/DocumentTemplate/tests/testDTML.py =================================================================== --- Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/DocumentTemplate/tests/testDTML.py 2007-06-06 15:48:08 UTC (rev 76432) +++ Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/DocumentTemplate/tests/testDTML.py 2007-06-06 15:54:34 UTC (rev 76433) @@ -16,7 +16,7 @@ __rcs_id__='$Id$' __version__='$Revision: 1.15 $'[11:-2] -import sys, os +import sys, os, cgi import unittest if __name__=='__main__': @@ -43,6 +43,14 @@ def d(**kw): return kw +docutils_include_warning = '''\ +<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils"><string></tt>, line 1)</p> +<p>"include" directive disabled.</p>''' + +docutils_raw_warning = '''\ +<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils"><string></tt>, line 1)</p> +<p>"raw" directive disabled.</p>''' + class PukeError(Exception): """Exception raised in test code.""" @@ -340,38 +348,51 @@ source = '.. include:: /etc/passwd' html = self.doc_class('<dtml-var name="foo" fmt="restructured-text">') html._vars['foo'] = source - self.assertRaises(NotImplementedError, html) + result = html() + # The include: directive hasn't been rendered, it remains + # verbatimly in the rendered output. Instead a warning + # message is presented: + self.assert_(source in result) + self.assert_(docutils_include_warning in result) + def test_fmt_reST_raw_directive_disabled(self): - EXPECTED = '<h1>HELLO WORLD</h1>' - source = '.. raw:: html\n\n %s\n' % EXPECTED html = self.doc_class('<dtml-var name="foo" fmt="restructured-text">') html._vars['foo'] = source + result = html() - result = html() # don't raise, but don't work either - self.failIf(EXPECTED in result) + # The raw: directive hasn't been rendered, it remains + # verbatimly in the rendered output. Instead a warning + # message is presented: + self.assert_(EXPECTED not in result) + self.assert_(cgi.escape(EXPECTED) in result) + self.assert_(docutils_raw_warning in result) - self.failUnless(""raw" directive disabled" in result) - from cgi import escape - self.failUnless(escape(EXPECTED) in result) - def test_fmt_reST_raw_directive_file_option_raises(self): - source = '.. raw:: html\n :file: inclusion.txt' html = self.doc_class('<dtml-var name="foo" fmt="restructured-text">') html._vars['foo'] = source + result = html() - self.assertRaises(NotImplementedError, html, source) + # The raw: directive hasn't been rendered, it remains + # verbatimly in the rendered output. Instead a warning + # message is presented: + self.assert_(source in result) + self.assert_(docutils_raw_warning in result) def test_fmt_reST_raw_directive_url_option_raises(self): - source = '.. raw:: html\n :url: http://www.zope.org' html = self.doc_class('<dtml-var name="foo" fmt="restructured-text">') html._vars['foo'] = source + result = html() - self.assertRaises(NotImplementedError, html, source) + # The raw: directive hasn't been rendered, it remains + # verbatimly in the rendered output. Instead a warning + # message is presented: + self.assert_(source in result) + self.assert_(docutils_raw_warning in result) def testPropogatedError(self): Modified: Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/Products/ZReST/ZReST.py =================================================================== --- Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/Products/ZReST/ZReST.py 2007-06-06 15:48:08 UTC (rev 76432) +++ Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/Products/ZReST/ZReST.py 2007-06-06 15:54:34 UTC (rev 76433) @@ -193,16 +193,16 @@ ''' Render the source to HTML ''' if self._v_formatted is None: - + warnings = self._v_warnings = Warnings() settings = { 'halt_level': 6, - 'report_level' : self.report_level, + 'report_level' : int(self.report_level), 'input_encoding': self.input_encoding, 'output_encoding': self.output_encoding, 'initial_header_level' : 1, 'stylesheet' : self.stylesheet, 'stylesheet_path' : None, - 'pub.settings.warning_stream' : Warnings(), + 'warning_stream' : warnings, 'raw_enabled' : 0, 'file_insertion_enabled' : 0, } Modified: Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/Products/ZReST/tests/test_ZReST.py =================================================================== --- Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/Products/ZReST/tests/test_ZReST.py 2007-06-06 15:48:08 UTC (rev 76432) +++ Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/Products/ZReST/tests/test_ZReST.py 2007-06-06 15:54:34 UTC (rev 76433) @@ -5,6 +5,7 @@ $Id$ """ import unittest +import cgi import tempfile txt = """Hello World @@ -26,6 +27,9 @@ daemon:x:2:2:Daemon:/sbin:/bin/bash """ +docutils_include_warning = '(WARNING/2) "include" directive disabled.' +docutils_raw_warning = '(WARNING/2) "raw" directive disabled.' + class TestZReST(unittest.TestCase): def _getTargetClass(self): @@ -78,32 +82,51 @@ def test_include_directive_raises(self): resty = self._makeOne() resty.source = 'hello world\n .. include:: /etc/passwd' - self.assertRaises(NotImplementedError, resty.render) + result = resty.render() + warnings = ''.join(resty._v_warnings.messages) + # The include: directive hasn't been rendered, it remains + # verbatimly in the rendered output. Instead a warning + # message is presented: + self.assert_(docutils_include_warning in warnings) + def test_raw_directive_disabled(self): - + resty = self._makeOne() EXPECTED = '<h1>HELLO WORLD</h1>' - - resty = self._makeOne() resty.source = '.. raw:: html\n\n %s\n' % EXPECTED - result = resty.render() # don't raise, but don't work either - self.failIf(EXPECTED in result) + result = resty.render() + warnings = ''.join(resty._v_warnings.messages) + # The raw: directive hasn't been rendered, it remains + # verbatimly in the rendered output. Instead a warning + # message is presented: + self.assert_(EXPECTED not in result) + self.assert_(cgi.escape(EXPECTED) in result) + self.assert_(docutils_raw_warning in warnings) + def test_raw_directive_file_directive_raises(self): - resty = self._makeOne() resty.source = '.. raw:: html\n :file: inclusion.txt' - self.assertRaises(NotImplementedError, resty.render) + result = resty.render() + warnings = ''.join(resty._v_warnings.messages) + # The raw: directive hasn't been rendered, it remains + # verbatimly in the rendered output. Instead a warning + # message is presented: + self.assert_(docutils_raw_warning in warnings) + def test_raw_directive_url_directive_raises(self): - resty = self._makeOne() resty.source = '.. raw:: html\n :url: http://www.zope.org/' - self.assertRaises(NotImplementedError, resty.render) + result = resty.render() + warnings = ''.join(resty._v_warnings.messages) + # The raw: directive hasn't been rendered, it remains + # verbatimly in the rendered output. Instead a warning + # message is presented: + self.assert_(docutils_raw_warning in warnings) def test_csv_table_file_option_raise(self): - resty = self._makeOne() csv_file = self._csvfile() resty.source = '.. csv-table:: \n :file: %s' % csv_file Modified: Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/reStructuredText/__init__.py =================================================================== --- Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/reStructuredText/__init__.py 2007-06-06 15:48:08 UTC (rev 76432) +++ Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/reStructuredText/__init__.py 2007-06-06 15:54:34 UTC (rev 76433) @@ -28,6 +28,15 @@ can download docutils at http://docutils.sourceforge.net/#download. """ % {'version' : docutils.__version__, 'path' : docutils.__path__[0] } +# Disable inclusion of files for security reasons. We do this by +# changing the default value of the ``file_insertion_enabled`` +# parameter to False. +import docutils.parsers.rst +for title, options, conf in docutils.parsers.rst.Parser.settings_spec[2]: + if options == ['--file-insertion-enabled']: + conf['default'] = 0 + break + import sys, os, locale from App.config import getConfiguration from docutils.core import publish_parts Modified: Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/reStructuredText/tests/testReST.py =================================================================== --- Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/reStructuredText/tests/testReST.py 2007-06-06 15:48:08 UTC (rev 76432) +++ Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/reStructuredText/tests/testReST.py 2007-06-06 15:54:34 UTC (rev 76433) @@ -1,6 +1,7 @@ # -*- coding: iso-8859-15 -*- import unittest +import cgi from reStructuredText import HTML @@ -20,6 +21,15 @@ """ +docutils_include_warning = '''\ +<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils"><string></tt>, line 2)</p> +<p>"include" directive disabled.</p>''' + +docutils_raw_warning = '''\ +<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils"><string></tt>, line 1)</p> +<p>"raw" directive disabled.</p>''' + + class TestReST(unittest.TestCase): def testRoman(self): @@ -84,39 +94,49 @@ def test_include_directive_raises(self): source = 'hello world\n .. include:: /etc/passwd' - self.assertRaises(NotImplementedError, HTML, source) + result = HTML(source) + # The include: directive hasn't been rendered, it remains + # verbatimly in the rendered output. Instead a warning + # message is presented: + self.assert_(docutils_include_warning in result) + def test_raw_directive_disabled(self): - EXPECTED = '<h1>HELLO WORLD</h1>' - source = '.. raw:: html\n\n %s\n' % EXPECTED result = HTML(source) # don't raise, but don't work either - self.failIf(EXPECTED in result) - self.failUnless(""raw" directive disabled" in result) - from cgi import escape - self.failUnless(escape(EXPECTED) in result) + # The raw: directive hasn't been rendered, it remains + # verbatimly in the rendered output. Instead a warning + # message is presented: + self.assert_(EXPECTED not in result) + self.assert_(cgi.escape(EXPECTED) in result) + self.assert_(docutils_raw_warning in result) def test_raw_directive_file_option_raises(self): - source = '.. raw:: html\n :file: inclusion.txt' - self.assertRaises(NotImplementedError, HTML, source) + result = HTML(source) + # The raw: directive hasn't been rendered, it remains + # verbatimly in the rendered output. Instead a warning + # message is presented: + self.assert_(docutils_raw_warning in result) + def test_raw_directive_url_option_raises(self): - source = '.. raw:: html\n :url: http://www.zope.org' - self.assertRaises(NotImplementedError, HTML, source) + result = HTML(source) + # The raw: directive hasn't been rendered, it remains + # verbatimly in the rendered output. Instead a warning + # message is presented: + self.assert_(docutils_raw_warning in result) def test_csv_table_file_option_raise(self): - source = '.. csv-table:: \n :file: inclusion.txt' result = HTML(source) self.failUnless('File and URL access deactivated' in result) def test_csv_table_url_option_raise(self): - source = '.. csv-table:: \n :url: http://www.evil.org' result = HTML(source) self.failUnless('File and URL access deactivated' in result) _______________________________________________ Zope-Checkins maillist - Zope-Checkins@zope.org http://mail.zope.org/mailman/listinfo/zope-checkins