[Checkins] SVN: Zope/trunk/ DAV: litmus' cond_put_unlocked test (#22) exposed a bug in

Chris McDonough chrism at plope.com
Sun Jun 17 11:58:27 EDT 2007


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



More information about the Checkins mailing list