[Zope-Checkins] SVN: Zope/branches/philikon-zope2.11-with-standard-docutils/lib/python/ Alternate approach to forbidding file inclusion in reStructuredText that's used from Zope:

Philipp von Weitershausen philikon at philikon.de
Wed Jun 6 11:54:34 EDT 2007


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">&lt;string&gt;</tt>, line 1)</p>
+<p>&quot;include&quot; directive disabled.</p>'''
+
+docutils_raw_warning = '''\
+<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">&lt;string&gt;</tt>, line 1)</p>
+<p>&quot;raw&quot; 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("&quot;raw&quot; 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">&lt;string&gt;</tt>, line 2)</p>
+<p>&quot;include&quot; directive disabled.</p>'''
+
+docutils_raw_warning = '''\
+<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">&lt;string&gt;</tt>, line 1)</p>
+<p>&quot;raw&quot; 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("&quot;raw&quot; 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)



More information about the Zope-Checkins mailing list