Commit 149a696b authored by Hanno Schlichting's avatar Hanno Schlichting

Moved ``TaintedString`` into the new AccessControl.tainted module.

parent be86c7e0
...@@ -11,6 +11,8 @@ Trunk (unreleased) ...@@ -11,6 +11,8 @@ Trunk (unreleased)
Restructuring Restructuring
+++++++++++++ +++++++++++++
- Moved ``TaintedString`` into the new AccessControl.tainted module.
- Moved the ``zExceptions`` package into its own distribution. - Moved the ``zExceptions`` package into its own distribution.
- Completely refactored ``ZPublisher.WSGIResponse`` in order to provide - Completely refactored ``ZPublisher.WSGIResponse`` in order to provide
......
##############################################################################
#
# Copyright (c) 2002 Zope Foundation and Contributors.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
""" TaintedString implementation.
TaintedStrings hold potentially dangerous untrusted data; anything that could
possibly hold HTML is considered dangerous. DTML code will use the quoted
value of this string, and raised exceptions in Zope will use the repr()
conversion.
"""
from cgi import escape
class TaintedString:
def __init__(self, value):
self._value = value
def __str__(self):
return self._value
def __repr__(self):
return repr(self.quoted())
def __cmp__(self, o):
return cmp(self._value, o)
def __hash__(self):
return hash(self._value)
def __len__(self):
return len(self._value)
def __getitem__(self, index):
v = self._value[index]
if '<' in v:
v = self.__class__(v)
return v
def __getslice__(self, i, j):
i = max(i, 0)
j = max(j, 0)
v = self._value[i:j]
if '<' in v:
v = self.__class__(v)
return v
def __add__(self, o):
return self.__class__(self._value + o)
def __radd__(self, o):
return self.__class__(o + self._value)
def __mul__(self, o):
return self.__class__(self._value * o)
def __rmul__(self, o):
return self.__class__(o * self._value)
def __mod__(self, o):
return self.__class__(self._value % o)
def __int__(self):
return int(self._value)
def __float__(self):
return float(self._value)
def __long__(self):
return long(self._value)
def __getstate__(self):
# If an object tries to store a TaintedString, it obviously wasn't
# aware that it was playing with untrusted data. Complain acordingly.
raise SystemError("A TaintedString cannot be pickled. Code that "
"caused this TaintedString to be stored should be more careful "
"with untrusted data from the REQUEST.")
def __getattr__(self, a):
# for string methods support other than those defined below
return getattr(self._value, a)
# Python 2.2 only.
def decode(self, *args):
return self.__class__(self._value.decode(*args))
def encode(self, *args):
return self.__class__(self._value.encode(*args))
def expandtabs(self, *args):
return self.__class__(self._value.expandtabs(*args))
def replace(self, *args):
v = self._value.replace(*args)
if '<' in v:
v = self.__class__(v)
return v
def split(self, *args):
r = self._value.split(*args)
return map(lambda v, c=self.__class__: '<' in v and c(v) or v, r)
def splitlines(self, *args):
r = self._value.splitlines(*args)
return map(lambda v, c=self.__class__: '<' in v and c(v) or v, r)
def translate(self, *args):
v = self._value.translate(*args)
if '<' in v:
v = self.__class__(v)
return v
def quoted(self):
return escape(self._value, 1)
# As called by cDocumentTemplate
__untaint__ = quoted
def createSimpleWrapper(func):
return lambda s, f=func: s.__class__(getattr(s._value, f)())
def createOneArgWrapper(func):
return lambda s, a, f=func: s.__class__(getattr(s._value, f)(a))
def createOneOptArgWrapper(func):
return lambda s, a=None, f=func: s.__class__(getattr(s._value, f)(a))
simpleWrappedMethods = ["capitalize", "lower", "swapcase", "title", "upper"]
oneArgWrappedMethods = ["center", "join", "ljust", "rjust"]
oneOptArgWrappedMethods = ["lstrip", "rstrip", "strip"]
for f in simpleWrappedMethods:
setattr(TaintedString, f, createSimpleWrapper(f))
for f in oneArgWrappedMethods:
setattr(TaintedString, f, createOneArgWrapper(f))
for f in oneOptArgWrappedMethods:
setattr(TaintedString, f, createOneOptArgWrapper(f))
...@@ -11,8 +11,6 @@ ...@@ -11,8 +11,6 @@
# #
############################################################################## ##############################################################################
""" TaintedString tests. """ TaintedString tests.
$Id$
""" """
import unittest import unittest
...@@ -25,7 +23,7 @@ class TestTaintedString(unittest.TestCase): ...@@ -25,7 +23,7 @@ class TestTaintedString(unittest.TestCase):
self.tainted = self._getClass()(self.unquoted) self.tainted = self._getClass()(self.unquoted)
def _getClass(self): def _getClass(self):
from Shared.TaintedString import TaintedString from AccessControl.tainted import TaintedString
return TaintedString return TaintedString
def testStr(self): def testStr(self):
...@@ -159,6 +157,3 @@ def test_suite(): ...@@ -159,6 +157,3 @@ def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestTaintedString)) suite.addTest(unittest.makeSuite(TestTaintedString))
return suite return suite
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
...@@ -31,7 +31,7 @@ from RestrictedPython.Guards import safe_builtins ...@@ -31,7 +31,7 @@ from RestrictedPython.Guards import safe_builtins
from RestrictedPython.Utilities import utility_builtins from RestrictedPython.Utilities import utility_builtins
from RestrictedPython.Eval import RestrictionCapableEval from RestrictedPython.Eval import RestrictionCapableEval
from Shared.TaintedString import TaintedString from AccessControl.tainted import TaintedString
test = utility_builtins['test'] # for backwards compatibility, dont remove! test = utility_builtins['test'] # for backwards compatibility, dont remove!
......
...@@ -160,7 +160,7 @@ from DocumentTemplate.html_quote import html_quote ...@@ -160,7 +160,7 @@ from DocumentTemplate.html_quote import html_quote
from DocumentTemplate.DT_Util import parse_params, name_param, str, ustr from DocumentTemplate.DT_Util import parse_params, name_param, str, ustr
from Acquisition import aq_base from Acquisition import aq_base
from Shared.TaintedString import TaintedString from AccessControl.tainted import TaintedString
from zope.structuredtext.html import HTML from zope.structuredtext.html import HTML
from zope.structuredtext.document import DocumentWithImages from zope.structuredtext.document import DocumentWithImages
from App.config import getConfiguration from App.config import getConfiguration
......
...@@ -51,7 +51,7 @@ class TestNewlineToBr(doctest.DocTestCase): ...@@ -51,7 +51,7 @@ class TestNewlineToBr(doctest.DocTestCase):
... <li>line one</li> ... <li>line one</li>
... <li>line two</li> ... <li>line two</li>
... ''' ... '''
>>> from Shared.TaintedString import TaintedString >>> from AccessControl.tainted import TaintedString
>>> tainted = TaintedString(text) >>> tainted = TaintedString(text)
>>> print DT_Var.newline_to_br(tainted) >>> print DT_Var.newline_to_br(tainted)
<br /> <br />
......
...@@ -29,12 +29,12 @@ from AccessControl.Permissions import view as View ...@@ -29,12 +29,12 @@ from AccessControl.Permissions import view as View
from AccessControl.Permissions import ftp_access from AccessControl.Permissions import ftp_access
from AccessControl.DTML import RestrictedDTML from AccessControl.DTML import RestrictedDTML
from AccessControl.requestmethod import requestmethod from AccessControl.requestmethod import requestmethod
from AccessControl.tainted import TaintedString
from OFS.Cache import Cacheable from OFS.Cache import Cacheable
from OFS.History import Historical from OFS.History import Historical
from OFS.History import html_diff from OFS.History import html_diff
from OFS.SimpleItem import Item_w__name__ from OFS.SimpleItem import Item_w__name__
from OFS.ZDOM import ElementWithTitle from OFS.ZDOM import ElementWithTitle
from Shared.TaintedString import TaintedString
from webdav.Lockable import ResourceLockedError from webdav.Lockable import ResourceLockedError
from zExceptions import Forbidden from zExceptions import Forbidden
from zExceptions.TracebackSupplement import PathTracebackSupplement from zExceptions.TracebackSupplement import PathTracebackSupplement
......
...@@ -44,7 +44,7 @@ class TestItem(unittest.TestCase): ...@@ -44,7 +44,7 @@ class TestItem(unittest.TestCase):
self.failUnless('full details: testing' in value.message) self.failUnless('full details: testing' in value.message)
def test_raise_StandardErrorMessage_TaintedString_errorValue(self): def test_raise_StandardErrorMessage_TaintedString_errorValue(self):
from Shared.TaintedString import TaintedString from AccessControl.tainted import TaintedString
class REQUEST(object): class REQUEST(object):
class RESPONSE(object): class RESPONSE(object):
handle_errors = True handle_errors = True
......
...@@ -15,7 +15,7 @@ class DTMLMethodTests(unittest.TestCase): ...@@ -15,7 +15,7 @@ class DTMLMethodTests(unittest.TestCase):
verifyClass(IWriteLock, self._getTargetClass()) verifyClass(IWriteLock, self._getTargetClass())
def test_edit_taintedstring(self): def test_edit_taintedstring(self):
from Shared.TaintedString import TaintedString from AccessControl.tainted import TaintedString
doc = self._makeOne() doc = self._makeOne()
self.assertEquals(doc.read(), '') self.assertEquals(doc.read(), '')
data = TaintedString('hello<br/>') data = TaintedString('hello<br/>')
......
############################################################################## from zope.deferredimport import deprecated
# deprecated('Shared.TaintedString will be removed in Zope 2.14. Please '
# Copyright (c) 2002 Zope Foundation and Contributors. 'import from AccessControl.tainted instead.',
# TaintedString = 'AccessControl.tainted:TaintedString',
# This software is subject to the provisions of the Zope Public License, createSimpleWrapper = 'AccessControl.tainted:createSimpleWrapper',
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. createOneArgWrapper = 'AccessControl.tainted:createOneArgWrapper',
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED createOneOptArgWrapper = 'AccessControl.tainted:createOneOptArgWrapper',
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED )
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
""" TaintedString implementation.
TaintedStrings hold potentially dangerous untrusted data; anything that could
possibly hold HTML is considered dangerous. DTML code will use the quoted
value of this string, and raised exceptions in Zope will use the repr()
conversion.
$Id$
"""
from cgi import escape
class TaintedString:
def __init__(self, value):
self._value = value
def __str__(self):
return self._value
def __repr__(self):
return repr(self.quoted())
def __cmp__(self, o):
return cmp(self._value, o)
def __hash__(self):
return hash(self._value)
def __len__(self):
return len(self._value)
def __getitem__(self, index):
v = self._value[index]
if '<' in v:
v = self.__class__(v)
return v
def __getslice__(self, i, j):
i = max(i, 0)
j = max(j, 0)
v = self._value[i:j]
if '<' in v:
v = self.__class__(v)
return v
def __add__(self, o):
return self.__class__(self._value + o)
def __radd__(self, o):
return self.__class__(o + self._value)
def __mul__(self, o):
return self.__class__(self._value * o)
def __rmul__(self, o):
return self.__class__(o * self._value)
def __mod__(self, o):
return self.__class__(self._value % o)
def __int__(self):
return int(self._value)
def __float__(self):
return float(self._value)
def __long__(self):
return long(self._value)
def __getstate__(self):
# If an object tries to store a TaintedString, it obviously wasn't aware
# that it was playing with untrusted data. Complain acordingly.
raise SystemError("A TaintedString cannot be pickled. Code that "
"caused this TaintedString to be stored should be more careful "
"with untrusted data from the REQUEST.")
def __getattr__(self, a):
# for string methods support other than those defined below
return getattr(self._value, a)
# Python 2.2 only.
def decode(self, *args):
return self.__class__(self._value.decode(*args))
def encode(self, *args):
return self.__class__(self._value.encode(*args))
def expandtabs(self, *args):
return self.__class__(self._value.expandtabs(*args))
def replace(self, *args):
v = self._value.replace(*args)
if '<' in v:
v = self.__class__(v)
return v
def split(self, *args):
r = self._value.split(*args)
return map(lambda v, c=self.__class__: '<' in v and c(v) or v, r)
def splitlines(self, *args):
r = self._value.splitlines(*args)
return map(lambda v, c=self.__class__: '<' in v and c(v) or v, r)
def translate(self, *args):
v = self._value.translate(*args)
if '<' in v:
v = self.__class__(v)
return v
def quoted(self):
return escape(self._value, 1)
# As called by cDocumentTemplate
__untaint__ = quoted
def createSimpleWrapper(func):
return lambda s, f=func: s.__class__(getattr(s._value, f)())
def createOneArgWrapper(func):
return lambda s, a, f=func: s.__class__(getattr(s._value, f)(a))
def createOneOptArgWrapper(func):
return lambda s, a=None, f=func: s.__class__(getattr(s._value, f)(a))
simpleWrappedMethods = \
"capitalize lower swapcase title upper".split()
oneArgWrappedMethods = "center join ljust rjust".split()
oneOptArgWrappedMethods = "lstrip rstrip strip".split()
for f in simpleWrappedMethods:
setattr(TaintedString, f, createSimpleWrapper(f))
for f in oneArgWrappedMethods:
setattr(TaintedString, f, createOneArgWrapper(f))
for f in oneOptArgWrappedMethods:
setattr(TaintedString, f, createOneOptArgWrapper(f))
...@@ -38,7 +38,7 @@ from zope.interface import implements ...@@ -38,7 +38,7 @@ from zope.interface import implements
from zope.publisher.base import DebugFlags from zope.publisher.base import DebugFlags
from zope.publisher.interfaces.browser import IBrowserRequest from zope.publisher.interfaces.browser import IBrowserRequest
from Shared.TaintedString import TaintedString from AccessControl.tainted import TaintedString
from ZPublisher.BaseRequest import BaseRequest from ZPublisher.BaseRequest import BaseRequest
from ZPublisher.BaseRequest import quote from ZPublisher.BaseRequest import quote
from ZPublisher.Converters import get_converter from ZPublisher.Converters import get_converter
......
...@@ -11,12 +11,10 @@ ...@@ -11,12 +11,10 @@
# #
############################################################################## ##############################################################################
"""TaintedString legacy module. """TaintedString legacy module.
$Id$
""" """
from zope.deferredimport import deprecated from zope.deferredimport import deprecated
deprecated('ZPublisher.TaintedString will be removed in Zope 2.14. Please ' deprecated('ZPublisher.TaintedString will be removed in Zope 2.14. Please '
'import from Shared.TaintedString instead.', 'import from AccessControl.tainted instead.',
TaintedString = 'Shared.TaintedString:TaintedString', TaintedString = 'AccessControl.tainted:TaintedString',
) )
...@@ -71,7 +71,7 @@ class HTTPRequestTests(unittest.TestCase): ...@@ -71,7 +71,7 @@ class HTTPRequestTests(unittest.TestCase):
# Also raises an Assertion if a string which *should* have been # Also raises an Assertion if a string which *should* have been
# tainted is found, or when a tainted string is not deemed dangerous. # tainted is found, or when a tainted string is not deemed dangerous.
from ZPublisher.HTTPRequest import record from ZPublisher.HTTPRequest import record
from Shared.TaintedString import TaintedString from AccessControl.tainted import TaintedString
retval = 0 retval = 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment