]> err.no Git - sope/commitdiff
minor fixes in WebDAV layer
authorhelge <helge@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Wed, 1 Jun 2005 13:53:51 +0000 (13:53 +0000)
committerhelge <helge@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Wed, 1 Jun 2005 13:53:51 +0000 (13:53 +0000)
added documentation

git-svn-id: http://svn.opengroupware.org/SOPE/trunk@816 e4a50df8-12e2-0310-a44c-efbce7f8a7e3

sope-appserver/NGObjWeb/ChangeLog
sope-appserver/NGObjWeb/Version
sope-appserver/NGObjWeb/WebDAV/DAVFetchSpec.txt
sope-appserver/NGObjWeb/WebDAV/README
sope-appserver/NGObjWeb/WebDAV/SoObjectWebDAVDispatcher.m

index 383c14859dd6e211921d7782bd194d540a5e0c2d..ab1e3cdf4d60749876b72d7d93247dfb8aa2931b 100644 (file)
@@ -1,3 +1,12 @@
+2005-06-01  Helge Hess  <helge.hess@skyrix.com>
+
+       * v4.5.162
+
+       * WebDAV/SoObjectWebDAVDispatcher.m: minor code cleanups, added support
+         for PROPFIND without content (treated as <allprop/>)
+
+       * WebDAV/README: added content to the README
+
 2005-05-30  Helge Hess  <helge.hess@skyrix.com>
 
        * SoObjects/SoProductClassInfo.m: allow plain string values for slots
index 82d5051ff61f8353328cb116194ee5af004341c5..ddf7386be661498c36be6f25fd3079c92408a1f4 100644 (file)
@@ -1,6 +1,6 @@
 # version file
 
-SUBMINOR_VERSION:=161
+SUBMINOR_VERSION:=162
 
 # v4.5.122 requires libNGExtensions v4.5.153
 # v4.5.91  requires libNGExtensions v4.5.134
index 09826f62ee2b3e480db0b40967166c3762c01a78..8c4510e418e5701e50573422fae28e57bf697010 100644 (file)
@@ -1,4 +1,5 @@
-# $Id$
+DAVFetchSpec
+============
 
 Required Context
 
index 789b62c7940afa8e5d13cde6f9de69f8b80db9d3..c3a121f111645626bc973922b9a4e1bbfd7aff72 100644 (file)
-# $Id$
-
 NGObjWeb WebDAV Implementation for SoObjects
 ============================================
 
-PROPFIND, TODO:
-"A client may choose not to submit a request body.  An empty PROPFIND request 
- body MUST be treated as a request for the names and values of all properties."
-- means, an empty request is to be treated as allprop?
+This subproject contains a WebDAV implementation for SOPE which is based on top
+of the SoObjectRequestHandler.
+
+The central point where processing starts once the request is received by the
+handler, is the
+
+  SoObjectWebDAVDispatcher
+
+class. This class knows about the various WebDAV HTTP methods and takes
+appropriate actions by calling specified methods on either the SoObject which
+is targetted by the URL or on one of the maintenance objects. Eg WebDAV 
+locking and notification is handled by the
+
+  SoDAVLockManager
+  SoSubscriptionManager
+
+classes, so the targetted object itself doesn't need to concern itself about
+that.
+
+Once a WebDAV action has been performed, the
+
+  SoWebDAVRenderer
+
+class is used to turn the result value of the HTTP method in a suitable WebDAV
+XML representation. To support non basic XML properties there is also a helper
+class
+
+  SoWebDAVValue
+
+
+PROPFIND/SEARCH Queries
+=======================
+
+The payload of both, WebDAV PROPFIND and SEARCH methods are represented as a
+regular EOControl EOFetchSpecification. The fetchspec is annotated with various
+hints to add additional WebDAV information. This includes the required depth
+of the query as well as the properties being requested.
+
+In case a SEARCH query is decoded, a regular EOQualifier/EOSortOrdering is
+used for representing that query.
+
+To perform a query, the layer will call:
+
+  - (id)performWebDAVQuery:(EOFetchSpecification *)_fetchSpecification
+    inContext:(WOContext *)_context;
+
+on the target object.
+
+Note that there are default implementations for queries based on KVC
+(see below)
+
+
+A special feature is that an object can make the WebDAV layer "remap" the 
+public WebDAV property names to internal names, for example KVC keys. To do so
+the object needs to implement
+
+  - (NSDictionary *)davAttributeMapInContext:(WOContext *)_context;
+
+For example this can be used to map the "davDisplayName" to the "title" of a
+given object.
+
+
+Default Query Implementation
+============================
+
+The default implementation is done in the NSObject(SoDAVQuery) category which
+requires an NSObject conforming to the "So" model of doing things. A query is
+initiated by
+
+  - (id)performWebDAVQuery:(EOFetchSpecification *)_fetchSpecification
+    inContext:(WOContext *)_context;
+
+The method then splits the operation based on the depth into one of those
+methods for 'self'(0) or 'deep'(infinity) queries:
+
+  - (id)davQueryOnSelf:(EOFetchSpecification *)_fs inContext:(WOContext *)_ctx;
+  - (id)performWebDAVDeepQuery:((EOFetchSpecification *)_fs 
+    inContext:(WOContext *)_ctx;
+
+For 'flat'(1) queries it uses a datasource to fetch the content and the
+-davQueryOnSelf:inContext: method to retrieve info on the object itself
+(required by WebDAV, but buggy in some implementations, eg WebFolders). The
+datasource is determined by
+
+  - (EODataSource *)contentDataSourceInContext:(WOContext *)_context;
+
+Per default this returns the SoObjectDataSource which performs KVC / EOControl
+based filtering and sorting.
+
+Besides those standard queries, the default implementations also deals with
+bulk queries as generated by either BPROPFIND or by the _range_ URI hack for
+ZideLook. Those will call
+
+  - (id)performWebDAVBulkQuery:(EOFetchSpecification *)_fetchSpec
+    inContext:(WOContext *)_context;
+
+Its discouraged to use bulk queries, since they are non-standard.
+
+
+Special Features
+================
+
+The dispatcher supports various Exchange WebDAV enhancements, eg bulk queries
+like BPROPFIND.
+
+Further it supports so called "ZideStore range" queries which are treated
+similiar to BPROPFIND and catches URLs starting with _range.
+
+
+TODO
+====
+
+REPORT
+- find a good way to represent arbitary reports
+
+extended ops: ACL, CHECKOUT etc
+
+
+Notes
+=====
 
 DASL:
   ---snip---
index f18c1e2a527436c8c51d2e57114db4ae6e42e9b4..cd9f1d054f89657d17033e5deda690758782b270 100644 (file)
@@ -217,7 +217,7 @@ static NSTimeZone                *gmt      = nil;
             : SoPerm_ChangeImagesAndFiles
           onObject:self->object
           inContext:_ctx];
-  if (e) return e;
+  if (e != nil) return e;
   
   if ((e = [self->object validateName:@"PUT" inContext:_ctx]))
     return e;
@@ -302,7 +302,7 @@ static NSTimeZone                *gmt      = nil;
   e  = [sm validatePermission:SoPerm_AddFolders 
           onObject:self->object
           inContext:_ctx];
-  if (e) return e;
+  if (e != nil) return e;
 
   /* check whether all the parent collections are available */
   if ([pathInfo rangeOfString:@"/"].length > 0) {
@@ -402,7 +402,7 @@ static NSTimeZone                *gmt      = nil;
   e  = [sm validatePermission:SoPerm_AccessContentsInformation 
           onObject:self->object
           inContext:_ctx];
-  if (e) return e;
+  if (e != nil) return e;
   
   /* perform search */
   
@@ -418,15 +418,29 @@ static NSTimeZone                *gmt      = nil;
   
   if ([depth length] == 0) depth = @"infinity";
   
-  [self lockParser:davsax];
-  {
-    [xmlParser parseFromSource:[rq content]];
-    propNames = [[davsax propFindQueriedNames] copy];
-    findAll   = [davsax  propFindAllProperties];
-    findNames = [davsax  propFindPropertyNames];
+  if ([[rq content] length] > 0) {
+    [self lockParser:davsax];
+    {
+      [xmlParser parseFromSource:[rq content]];
+      propNames = [[davsax propFindQueriedNames] copy];
+      findAll   = [davsax  propFindAllProperties];
+      findNames = [davsax  propFindPropertyNames];
+    }
+    [self unlockParser:davsax];
+    propNames = [propNames autorelease];
+  }
+  else {
+    /*
+      8.1 PROPFIND
+      "A client may choose not to submit a request body.  An empty PROPFIND 
+       request body MUST be treated as a request for the names and values of
+       all properties."
+      TODO: means, an empty request is to be treated as allprop?
+    */
+    propNames = nil;
+    findAll   = YES;
+    findNames = NO;
   }
-  [self unlockParser:davsax];
-  propNames = [propNames autorelease];
   
   /* check query all properties */
   
@@ -473,7 +487,7 @@ static NSTimeZone                *gmt      = nil;
     
     hints = [self hintsWithScope:[self scopeForDepth:depth inContext:_ctx]
                  propNames:propNames findAll:findAll namesOnly:findNames];
-    if (rtargets) /* range-query keys */
+    if (rtargets != nil) /* range-query keys */
       [hints setObject:rtargets forKey:@"bulkTargetKeys"];
     
     fs = [EOFetchSpecification alloc];
@@ -548,7 +562,7 @@ static NSTimeZone                *gmt      = nil;
             : SoPerm_ChangeImagesAndFiles
           onObject:self->object
           inContext:_ctx];
-  if (e) return e;
+  if (e != nil) return e;
   
   /* check for conflicts */
 
@@ -676,7 +690,7 @@ static NSTimeZone                *gmt      = nil;
             davSetProperties:setProps
             removePropertiesNamed:delProps
             inContext:_ctx];
-    if (e) return e;
+    if (e != nil) return e;
   }
   else {
     /* create an object */
@@ -711,7 +725,7 @@ static NSTimeZone                *gmt      = nil;
   e  = [sm validatePermission:SoPerm_WebDAVLockItems
           onObject:self->object
           inContext:_ctx];
-  if (e) return e;
+  if (e != nil) return e;
   
   /* check lock manager */
   
@@ -763,7 +777,7 @@ static NSTimeZone                *gmt      = nil;
   e  = [sm validatePermission:SoPerm_WebDAVUnlockItems
           onObject:self->object
           inContext:_ctx];
-  if (e) return e;
+  if (e != nil) return e;
   
   /* check lock manager */
   
@@ -975,7 +989,7 @@ static NSTimeZone                *gmt      = nil;
   e  = [sm validatePermission:SoPerm_AccessContentsInformation 
           onObject:self->object
           inContext:_ctx];
-  if (e) return e;
+  if (e != nil) return e;
 
   /* perform search */
   
@@ -1271,7 +1285,7 @@ static NSTimeZone                *gmt      = nil;
   e  = [sm validatePermission:SoPerm_AccessContentsInformation 
           onObject:self->object
           inContext:_ctx];
-  if (e) return e;
+  if (e != nil) return e;
 
   /* perform search */
   
@@ -1454,6 +1468,13 @@ static NSTimeZone                *gmt      = nil;
               reason:@"WebDAV operation not yet implemented."];
 }
 
+/* DAV reports */
+
+- (id)doREPORT:(WOContext *)_ctx {
+  return [self httpException:405 /* method not allowed */
+              reason:@"WebDAV reports not yet implemented."];
+}
+
 /* DAV access control lists */
 
 - (id)doACL:(WOContext *)_ctx {
@@ -1520,7 +1541,7 @@ static NSTimeZone                *gmt      = nil;
   e  = [sm validatePermission:SoPerm_WebDAVAccess
           onObject:self->object
           inContext:_ctx];
-  if (e) return e;
+  if (e != nil) return e;
   
   /* perform search */