Log message for revision 76732: DAV: litmus' cond_put_unlocked test (#22) exposed a bug in webdav.Resource.dav__simpleifhandler. If the resource is not locked, and a DAV request contains an If header, no token can possibly match and we must return a 412 Precondition Failed instead of 204 No Content.
Changed: U Zope/trunk/doc/CHANGES.txt U Zope/trunk/lib/python/webdav/Lockable.py U Zope/trunk/lib/python/webdav/Resource.py U Zope/trunk/lib/python/webdav/tests/testLockItem.py A Zope/trunk/lib/python/webdav/tests/testLockable.py U Zope/trunk/lib/python/webdav/tests/testResource.py -=- Modified: Zope/trunk/doc/CHANGES.txt =================================================================== --- Zope/trunk/doc/CHANGES.txt 2007-06-17 15:01:29 UTC (rev 76731) +++ Zope/trunk/doc/CHANGES.txt 2007-06-17 15:58:27 UTC (rev 76732) @@ -97,6 +97,12 @@ Bugs Fixed + - DAV: litmus' cond_put_unlocked test (#22) exposed a bug in + webdav.Resource.dav__simpleifhandler. If the resource is not + locked, and a DAV request contains an If header, no token can + possibly match and we must return a 412 Precondition Failed + instead of 204 No Content. + - DAV: litmus' cond_put_corrupt_token test (#18) exposed a bug in webdav.Resource.dav__simpleifhandler. If the resource is locked at all, and a DAV request contains an If header, and Modified: Zope/trunk/lib/python/webdav/Lockable.py =================================================================== --- Zope/trunk/lib/python/webdav/Lockable.py 2007-06-17 15:01:29 UTC (rev 76731) +++ Zope/trunk/lib/python/webdav/Lockable.py 2007-06-17 15:58:27 UTC (rev 76732) @@ -152,5 +152,9 @@ def wl_isLocked(ob): """ Returns true if the object is locked, returns 0 if the object is not locked or does not implement the WriteLockInterface """ + return wl_isLockable(ob) and ob.wl_isLocked() + +def wl_isLockable(ob): return (IWriteLock.providedBy(ob) or - WriteLockInterface.isImplementedBy(ob)) and ob.wl_isLocked() + WriteLockInterface.isImplementedBy(ob)) + Modified: Zope/trunk/lib/python/webdav/Resource.py =================================================================== --- Zope/trunk/lib/python/webdav/Resource.py 2007-06-17 15:01:29 UTC (rev 76731) +++ Zope/trunk/lib/python/webdav/Resource.py 2007-06-17 15:58:27 UTC (rev 76732) @@ -113,12 +113,27 @@ def dav__simpleifhandler(self, request, response, method='PUT', col=0, url=None, refresh=0): ifhdr = request.get_header('If', None) - if Lockable.wl_isLocked(self) and (not ifhdr): - raise Locked, "Resource is locked." - if not ifhdr: return None - if not Lockable.wl_isLocked(self): return None + lockable = Lockable.wl_isLockable(self) + if not lockable: + # degenerate case, we shouldnt have even called this method. + return None + locked = self.wl_isLocked() + + if locked and (not ifhdr): + raise Locked('Resource is locked.') + + if not ifhdr: + return None + + if (not locked): + # we have an if header but the resource isn't locked, we + # can shortcut checking the tags in the if header; no token + # can possibly match + raise PreconditionFailed( + 'Resource not locked but If header specified') + # Since we're a simple if handler, and since some clients don't # pass in the port information in the resource part of an If # header, we're only going to worry about if the paths compare Modified: Zope/trunk/lib/python/webdav/tests/testLockItem.py =================================================================== --- Zope/trunk/lib/python/webdav/tests/testLockItem.py 2007-06-17 15:01:29 UTC (rev 76731) +++ Zope/trunk/lib/python/webdav/tests/testLockItem.py 2007-06-17 15:58:27 UTC (rev 76732) @@ -17,7 +17,6 @@ verifyClass(ILockItem, LockItem) - def test_suite(): return unittest.TestSuite(( unittest.makeSuite(TestLockItem), Added: Zope/trunk/lib/python/webdav/tests/testLockable.py =================================================================== --- Zope/trunk/lib/python/webdav/tests/testLockable.py (rev 0) +++ Zope/trunk/lib/python/webdav/tests/testLockable.py 2007-06-17 15:58:27 UTC (rev 76732) @@ -0,0 +1,39 @@ +import unittest + +class TestUtilFunctions(unittest.TestCase): + def test_wl_isLocked(self): + from webdav.Lockable import wl_isLocked + unlockable = UnlockableResource() + self.failIf(wl_isLocked(unlockable)) + lockable_unlocked = LockableResource(locked=False) + self.failIf(wl_isLocked(lockable_unlocked)) + lockable_locked = LockableResource(locked=True) + self.failUnless(wl_isLocked(lockable_locked)) + + def test_wl_isLockable(self): + from webdav.Lockable import wl_isLockable + unlockable = UnlockableResource() + self.failIf(wl_isLockable(unlockable)) + lockable = LockableResource(locked=False) + self.failUnless(wl_isLockable(lockable)) + +from webdav.interfaces import IWriteLock +from zope.interface import implements + +class LockableResource: + implements(IWriteLock) + def __init__(self, locked): + self.locked = locked + def wl_isLocked(self): + return self.locked + +class UnlockableResource: + pass + +def test_suite(): + return unittest.TestSuite(( + unittest.makeSuite(TestUtilFunctions), + )) + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite') Property changes on: Zope/trunk/lib/python/webdav/tests/testLockable.py ___________________________________________________________________ Name: svn:eol-style + native Modified: Zope/trunk/lib/python/webdav/tests/testResource.py =================================================================== --- Zope/trunk/lib/python/webdav/tests/testResource.py 2007-06-17 15:01:29 UTC (rev 76731) +++ Zope/trunk/lib/python/webdav/tests/testResource.py 2007-06-17 15:58:27 UTC (rev 76732) @@ -56,6 +56,26 @@ from webdav.common import Locked self.assertRaises(Locked, inst.MOVE, request, response) + def test_dav__simpleifhandler_fail_cond_put_unlocked(self): + """ + DAV: litmus' cond_put_unlocked test (#22) exposed a bug in + webdav.Resource.dav__simpleifhandler. If the resource is not + locked, and a DAV request contains an If header, no token can + possibly match and we must return a 412 Precondition Failed + instead of 204 No Content. + """ + ifhdr = 'If: (<locktoken:foo>)' + request = DummyRequest({'URL':'http://example.com/foo/PUT'}, + {'If':ifhdr}) + response = DummyResponse() + inst = self._makeOne() + from zope.interface import directlyProvides + from webdav.interfaces import IWriteLock + directlyProvides(inst, IWriteLock) + from webdav.common import PreconditionFailed + self.assertRaises(PreconditionFailed, inst.dav__simpleifhandler, + request, response) + def test_dav__simpleifhandler_cond_put_corrupt_token(self): """ DAV: litmus' cond_put_corrupt_token test (#18) exposed a bug _______________________________________________ Zope-Checkins maillist - Zope-Checkins@zope.org http://mail.zope.org/mailman/listinfo/zope-checkins