[Checkins] SVN: z3c.dav/trunk/src/z3c/dav/ Integrate the if header validator into the WebDAV publication utility.

Michael Kerrin michael.kerrin at openapp.ie
Thu May 31 15:45:00 EDT 2007


Log message for revision 76059:
  Integrate the if header validator into the WebDAV publication utility.
  
  Alos update the locking implementation to use the information generated by
  this validator.
  

Changed:
  U   z3c.dav/trunk/src/z3c/dav/locking.py
  U   z3c.dav/trunk/src/z3c/dav/locking.txt
  U   z3c.dav/trunk/src/z3c/dav/publisher.py

-=-
Modified: z3c.dav/trunk/src/z3c/dav/locking.py
===================================================================
--- z3c.dav/trunk/src/z3c/dav/locking.py	2007-05-31 19:24:39 UTC (rev 76058)
+++ z3c.dav/trunk/src/z3c/dav/locking.py	2007-05-31 19:44:59 UTC (rev 76059)
@@ -49,33 +49,11 @@
 import z3c.dav.properties
 from z3c.dav.coreproperties import IActiveLock, IDAVSupportedlock
 import z3c.dav.utils
+import ifvalidator
 
 MAXTIMEOUT = (2L ** 32) - 1
 DEFAULTTIMEOUT = 12 * 60L
 
-def getIfHeader(request):
-    """
-    Parse the `If` HTTP header in this request and return a list of lock tokens
-    and entity tags.
-
-    XXX - This implementation is overly simplicitic.
-
-      >>> from zope.publisher.browser import TestRequest
-
-      >>> getIfHeader(TestRequest()) is None
-      True
-      >>> getIfHeader(TestRequest(environ = {'IF': 'xxx'})) is None
-      True
-      >>> getIfHeader(TestRequest(environ = {'IF': '<xxx>'}))
-      'xxx'
-
-    """
-    headervalue = request.get("IF", "")
-    if headervalue and headervalue[0] == "<" and headervalue[-1] == ">":
-        return headervalue[1:-1]
-    return None
-
-
 @component.adapter(interface.Interface, z3c.dav.interfaces.IWebDAVRequest)
 @interface.implementer(z3c.dav.interfaces.IWebDAVMethod)
 def LOCK(context, request):
@@ -295,12 +273,7 @@
             raise z3c.dav.interfaces.PreconditionFailed(
                 self.context, message = u"Context is not locked.")
 
-        locktoken = component.getMultiAdapter((self.context, self.request),
-                                              IActiveLock).locktoken[0]
-        request_uri = self.request.getHeader("IF", "")
-        if not request_uri or \
-               request_uri[0] != "<" or request_uri[-1] != ">" or \
-               request_uri[1:-1] != locktoken:
+        if not ifvalidator.matchesIfHeader(self.context, self.request):
             raise z3c.dav.interfaces.PreconditionFailed(
                 self.context, message = u"Lock-Token doesn't match request uri")
 

Modified: z3c.dav/trunk/src/z3c/dav/locking.txt
===================================================================
--- z3c.dav/trunk/src/z3c/dav/locking.txt	2007-05-31 19:24:39 UTC (rev 76058)
+++ z3c.dav/trunk/src/z3c/dav/locking.txt	2007-05-31 19:44:59 UTC (rev 76059)
@@ -19,12 +19,16 @@
 =====
 
   >>> import UserDict
+  >>> import UserDict
   >>> from cStringIO import StringIO
   >>> import zope.interface
   >>> from zope.interface.verify import verifyObject
   >>> import zope.component
+  >>> import zope.annotation.interfaces
+  >>> import zope.publisher.interfaces.http
   >>> import zope.app.container.interfaces
   >>> import z3c.dav.interfaces
+  >>> from zope.traversing.interfaces import IPhysicallyLocatable
 
 Define a test request object and a content type against which to run the
 tests.
@@ -43,10 +47,25 @@
 
   >>> class Resource(object):
   ...    zope.interface.implements(IResource)
+  ...    _path = '/test'
   ...    _lockinfo = None
 
+  >>> class ResourcePhysicallyLocatable(object):
+  ...    zope.interface.implements(IPhysicallyLocatable)
+  ...    def __init__(self, context):
+  ...        self.context = context
+  ...    def getPath(self):
+  ...        return self.context._path
+
   >>> gsm = zope.component.getGlobalSiteManager()
 
+  >>> gsm.registerAdapter(ResourcePhysicallyLocatable, (IResource,))
+
+The `IF` validator annotes the request object.
+
+  >>> from z3c.dav import ifvalidator
+  >>> validator = ifvalidator.IFValidator()
+
 LOCK Method
 ===========
 
@@ -383,6 +402,11 @@
   ...    def lockdiscovery(self):
   ...        return [Activelock(self.context, self.request)]
 
+  >>> gsm.registerAdapter(ifvalidator.StateTokens,
+  ...    (IResource,
+  ...     zope.publisher.interfaces.http.IHTTPRequest,
+  ...     zope.interface.Interface))
+
 We need the following setup in-order for the LOCK method to render the
 `{DAV:}lockdiscovery` widget.
 
@@ -519,6 +543,14 @@
 case the `handleLock` method is not called but the `handleLockRefresh` is
 called.
 
+  >>> class ReqAnnotation(UserDict.IterableUserDict):
+  ...    zope.interface.implements(zope.annotation.interfaces.IAnnotations)
+  ...    def __init__(self, request):
+  ...        self.data = request._environ.setdefault('annoations', {})
+
+  >>> gsm.registerAdapter(ReqAnnotation,
+  ...    (zope.publisher.interfaces.http.IHTTPRequest,))
+
   >>> LOCK(resource, TestWebDAVRequest()).handleLockRefresh()
   Traceback (most recent call last):
   ...
@@ -534,6 +566,19 @@
 
   >>> LOCK(resource, TestWebDAVRequest(
   ...    environ = {'IF': '<urn:resourcelocktoken>'})).handleLockRefresh()
+  Traceback (most recent call last):
+  ...
+  PreconditionFailed: Lock-Token doesn't match request uri
+
+We need to call the if validators valid method which will annotate the
+request object after parsing the if header, with the results of the
+conditional.
+
+  >>> request = TestWebDAVRequest(
+  ...    environ = {'IF': '(<urn:resourcelocktoken>)'})
+  >>> validator.valid(resource, request, None)
+  True
+  >>> LOCK(resource, request).handleLockRefresh()
   Refreshed lock token.
   >>> resource._lockinfo['duration']
   datetime.timedelta(0, 720)
@@ -544,9 +589,12 @@
   >>> resource._lockinfo['depth']
   'infinity'
 
-  >>> LOCK(resource, TestWebDAVRequest(
-  ...    environ = {'IF': '<urn:resourcelocktoken>',
-  ...               'TIMEOUT': 'Second-1440'})).handleLockRefresh()
+  >>> request = TestWebDAVRequest(
+  ...    environ = {'IF': '(<urn:resourcelocktoken>)',
+  ...               'TIMEOUT': 'Second-1440'})
+  >>> validator.valid(resource, request, None)
+  True
+  >>> LOCK(resource, request).handleLockRefresh()
   Refreshed lock token.
   >>> resource._lockinfo['duration']
   datetime.timedelta(0, 1440)
@@ -562,7 +610,9 @@
 gets refreshed and the `{DAV:}lockdiscovery` property is rendered and
 returned.
 
-  >>> request = TestWebDAVRequest(environ = {'IF': '<urn:resourcelocktoken>'})
+  >>> request = TestWebDAVRequest(environ = {'IF': '(<urn:resourcelocktoken>)'})
+  >>> validator.valid(resource, request, None)
+  True
   >>> respbody = LOCK(resource, request).LOCK()
   Refreshed lock token.
 
@@ -606,8 +656,10 @@
 
 Similar if we specify a timeout header.
 
-  >>> request = TestWebDAVRequest(environ = {'IF': '<urn:resourcelocktoken>',
+  >>> request = TestWebDAVRequest(environ = {'IF': '(<urn:resourcelocktoken>)',
   ...                                  'TIMEOUT': 'Second-1440'})
+  >>> validator.valid(resource, request, None)
+  True
   >>> respbody = LOCK(resource, request).LOCK()
   Refreshed lock token.
   >>> resource._lockinfo['duration']
@@ -736,11 +788,20 @@
 Cleanup
 -------
 
+  >>> gsm.unregisterAdapter(ResourcePhysicallyLocatable, (IResource,))
+  True
+
   >>> gsm.unregisterAdapter(Supportedlock)
   True
   >>> gsm.unregisterAdapter(Activelock)
   True
 
+  >>> gsm.unregisterAdapter(ifvalidator.StateTokens,
+  ...    (IResource,
+  ...     zope.publisher.interfaces.http.IHTTPRequest,
+  ...     zope.interface.Interface))
+  True
+
   >>> gsm.unregisterAdapter(z3c.dav.widgets.ListDAVWidget,
   ...                       (zope.schema.interfaces.IList,
   ...                        z3c.dav.interfaces.IWebDAVRequest))
@@ -767,3 +828,6 @@
   True
   >>> gsm.unregisterAdapter(Lockdiscovery)
   True
+  >>> gsm.unregisterAdapter(ReqAnnotation,
+  ...    (zope.publisher.interfaces.http.IHTTPRequest,))
+  True

Modified: z3c.dav/trunk/src/z3c/dav/publisher.py
===================================================================
--- z3c.dav/trunk/src/z3c/dav/publisher.py	2007-05-31 19:24:39 UTC (rev 76058)
+++ z3c.dav/trunk/src/z3c/dav/publisher.py	2007-05-31 19:44:59 UTC (rev 76059)
@@ -22,6 +22,7 @@
 from zope.app.publication.interfaces import IRequestPublicationFactory
 
 import z3c.etree
+import z3c.conditionalviews
 import interfaces
 
 
@@ -29,7 +30,7 @@
     implements(interfaces.IWebDAVResponse)
 
 
-class WebDAVRequest(HTTPRequest):
+class WebDAVRequest(z3c.conditionalviews.ConditionalHTTPRequest):
     implements(interfaces.IWebDAVRequest)
 
     __slot__ = (



More information about the Checkins mailing list