Commit 96c3005c authored by Tres Seaver's avatar Tres Seaver

Synch with 2.10 branch.

parent 37462b85
......@@ -18,6 +18,14 @@ Zope Changes
Bugs Fixed
- reStructuredText/ZReST: setting raw_enabled to 0 for security
reasons
- Collector #2113: 'zopectl test' masked Ctrl-C.
- OFS Image: Image and File updated to use isinstance(data, str)
and raises TypeError upon encountering unicode objects.
- OFS Application: Updated deprecation warnings.
Support for '__ac_permissions__' and 'meta_types' will be removed in
Zope 2.11, 'methods' support might remain longer.
......
......@@ -43,7 +43,6 @@ from zExceptions import Redirect
from cgi import escape
import transaction
StringType=type('')
manage_addFileForm=DTMLFile('dtml/imageAdd', globals(),Kind='File',kind='file')
def manage_addFile(self,id,file='',title='',precondition='', content_type='',
REQUEST=None):
......@@ -231,7 +230,7 @@ class File(Persistent, Implicit, PropertyManager,
RESPONSE.setStatus(206) # Partial content
data = self.data
if type(data) is StringType:
if isinstance(data, str):
RESPONSE.write(data[start:end])
return True
......@@ -302,7 +301,7 @@ class File(Persistent, Implicit, PropertyManager,
'Content-Range: bytes %d-%d/%d\r\n\r\n' % (
start, end - 1, self.size))
if type(data) is StringType:
if isinstance(data, str):
RESPONSE.write(data[start:end])
else:
......@@ -401,7 +400,7 @@ class File(Persistent, Implicit, PropertyManager,
self.ZCacheable_set(None)
data=self.data
if type(data) is type(''):
if isinstance(data, str):
RESPONSE.setBase(None)
return data
......@@ -428,6 +427,10 @@ class File(Persistent, Implicit, PropertyManager,
security.declarePrivate('update_data')
def update_data(self, data, content_type=None, size=None):
if isinstance(data, unicode):
raise TypeError('Data can only be str or file-like. '
'Unicode objects are expressly forbidden.')
if content_type is not None: self.content_type=content_type
if size is None: size=len(data)
self.size=size
......@@ -481,7 +484,7 @@ class File(Persistent, Implicit, PropertyManager,
if headers and headers.has_key('content-type'):
content_type=headers['content-type']
else:
if type(body) is not type(''): body=body.data
if not isinstance(body, str): body=body.data
content_type, enc=guess_content_type(
getattr(file, 'filename',id), body, content_type)
return content_type
......@@ -490,7 +493,7 @@ class File(Persistent, Implicit, PropertyManager,
n=1 << 16
if type(file) is StringType:
if isinstance(file, str):
size=len(file)
if size < n: return file, size
# Big string: cut it into smaller chunks
......@@ -617,7 +620,7 @@ class File(Persistent, Implicit, PropertyManager,
return result
data = self.data
if type(data) is type(''):
if isinstance(data, str):
RESPONSE.setBase(None)
return data
......@@ -777,6 +780,10 @@ class Image(File):
security.declarePrivate('update_data')
def update_data(self, data, content_type=None, size=None):
if isinstance(data, unicode):
raise TypeError('Data can only be str or file-like. '
'Unicode objects are expressly forbidden.')
if size is None: size=len(data)
self.size=size
......
......@@ -237,11 +237,11 @@ class Traversable:
if not validated:
raise Unauthorized, name
else:
if hasattr(aq_base(obj), name):
if getattr(aq_base(obj), name, marker) is not marker:
if restricted:
next = guarded_getattr(obj, name, marker)
next = guarded_getattr(obj, name)
else:
next = _getattr(obj, name, marker)
next = _getattr(obj, name)
else:
try:
next=obj[name]
......@@ -249,6 +249,9 @@ class Traversable:
# Raise NotFound for easier debugging
# instead of AttributeError: __getitem__
raise NotFound, name
if restricted and not securityManager.validate(
obj, obj, _none, next):
raise Unauthorized, name
except (AttributeError, NotFound, KeyError), e:
# Try to look for a view
......@@ -270,13 +273,10 @@ class Traversable:
next = _getattr(obj, name, marker)
except AttributeError:
raise e
if next is marker:
# Nothing found re-raise error
raise e
if restricted and not securityManager.validate(
obj, obj, _none, next):
raise Unauthorized, name
if next is marker:
# Nothing found re-raise error
raise e
obj = next
return obj
......
......@@ -252,7 +252,12 @@ class FileTests(unittest.TestCase):
verifyClass(HTTPRangeInterface, File)
verifyClass(WriteLockInterface, File)
def testUnicode(self):
val = u'some unicode string here'
self.assertRaises(TypeError, self.file.manage_edit,
'foobar', 'text/plain', filedata=val)
class ImageTests(FileTests):
data = open(filedata, 'rb').read()
content_type = 'image/gif'
......@@ -285,7 +290,6 @@ class ImageTests(FileTests):
verifyClass(WriteLockInterface, Image)
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(FileTests),
......
......@@ -68,6 +68,24 @@ class CruelSecurityPolicy:
return 0
class ProtectedMethodSecurityPolicy:
"""Check security strictly on bound methods.
"""
def validate(self, accessed, container, name, value, *args):
if getattr(aq_base(value), 'im_self', None) is None:
return 1
# Bound method
if name is None:
raise Unauthorized
klass = value.im_self.__class__
roles = getattr(klass, name+'__roles__', object())
if roles is None: # ACCESS_PUBLIC
return 1
raise Unauthorized(name)
class UnitTestUser( Acquisition.Implicit ):
"""
Stubbed out manager for unit testing purposes.
......@@ -103,6 +121,22 @@ class BoboTraversable(SimpleItem):
bb_status = 'screechy'
class Restricted(SimpleItem):
"""Instance we'll check with ProtectedMethodSecurityPolicy
"""
getId__roles__ = None # ACCESS_PUBLIC
def getId(self):
return self.id
private__roles__ = () # ACCESS_PRIVATE
def private(self):
return 'private!'
# not protected
def ohno(self):
return 'ohno!'
class BoboTraversableWithAcquisition(SimpleItem):
"""
A BoboTraversable class which may use acquisition to find objects.
......@@ -210,6 +244,17 @@ class TestTraverse( unittest.TestCase ):
self.failUnlessRaises(
KeyError, self.folder1.unrestrictedTraverse, '/folder1/file2/' )
def testTraverseMethodRestricted(self):
self.root.my = Restricted('my')
my = self.root.my
my.id = 'my'
noSecurityManager()
SecurityManager.setSecurityPolicy(ProtectedMethodSecurityPolicy())
r = my.restrictedTraverse('getId')
self.assertEquals(r(), 'my')
self.assertRaises(Unauthorized, my.restrictedTraverse, 'private')
self.assertRaises(Unauthorized, my.restrictedTraverse, 'ohno')
def testBoboTraverseToWrappedSubObj(self):
# Verify it's possible to use __bobo_traverse__ with the
# Zope security policy.
......
......@@ -204,6 +204,7 @@ class ZReST(Item, PropertyManager, Historical, Implicit, Persistent):
'stylesheet_path' : None,
'pub.settings.warning_stream' : Warnings(),
'file_insertion_enabled' : 0,
'raw_enabled' : 0,
}
self._v_formatted = docutils.core.publish_string(
......
......@@ -258,14 +258,20 @@ class ZopeCmd(ZDCmd):
pid = os.fork()
if pid == 0: # child
os.execv(self.options.python, args)
else:
os.waitpid(pid, 0)
# Parent process running (execv replaces process in child
while True:
try:
os.waitpid(pid, 0)
except (OSError, KeyboardInterrupt):
continue
else:
break
def help_test(self):
print "test [args]+ -- run unit / functional tests."
print " See $ZOPE_HOME/bin/test.py --help for syntax."
def main(args=None):
# This is exactly like zdctl.main(), but uses ZopeCtlOptions and
# ZopeCmd instead of ZDCtlOptions and ZDCmd, so the default values
......
......@@ -73,6 +73,7 @@ def render(src,
settings['stylesheet'] = stylesheet
settings['stylesheet_path'] = None
settings['file_insertion_enabled'] = 0
settings['raw_enabled'] = 0
if language_code:
settings['language_code'] = language_code
settings['language_code'] = language_code
......
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