From 4c24835d126fc712f7c1726914431522b5849a22 Mon Sep 17 00:00:00 2001 From: helge Date: Wed, 1 Jun 2005 13:53:51 +0000 Subject: [PATCH] minor fixes in WebDAV layer added documentation git-svn-id: http://svn.opengroupware.org/SOPE/trunk@816 e4a50df8-12e2-0310-a44c-efbce7f8a7e3 --- sope-appserver/NGObjWeb/ChangeLog | 9 ++ sope-appserver/NGObjWeb/Version | 2 +- .../NGObjWeb/WebDAV/DAVFetchSpec.txt | 3 +- sope-appserver/NGObjWeb/WebDAV/README | 126 +++++++++++++++++- .../WebDAV/SoObjectWebDAVDispatcher.m | 59 +++++--- 5 files changed, 172 insertions(+), 27 deletions(-) diff --git a/sope-appserver/NGObjWeb/ChangeLog b/sope-appserver/NGObjWeb/ChangeLog index 383c1485..ab1e3cdf 100644 --- a/sope-appserver/NGObjWeb/ChangeLog +++ b/sope-appserver/NGObjWeb/ChangeLog @@ -1,3 +1,12 @@ +2005-06-01 Helge Hess + + * v4.5.162 + + * WebDAV/SoObjectWebDAVDispatcher.m: minor code cleanups, added support + for PROPFIND without content (treated as ) + + * WebDAV/README: added content to the README + 2005-05-30 Helge Hess * SoObjects/SoProductClassInfo.m: allow plain string values for slots diff --git a/sope-appserver/NGObjWeb/Version b/sope-appserver/NGObjWeb/Version index 82d5051f..ddf7386b 100644 --- a/sope-appserver/NGObjWeb/Version +++ b/sope-appserver/NGObjWeb/Version @@ -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 diff --git a/sope-appserver/NGObjWeb/WebDAV/DAVFetchSpec.txt b/sope-appserver/NGObjWeb/WebDAV/DAVFetchSpec.txt index 09826f62..8c4510e4 100644 --- a/sope-appserver/NGObjWeb/WebDAV/DAVFetchSpec.txt +++ b/sope-appserver/NGObjWeb/WebDAV/DAVFetchSpec.txt @@ -1,4 +1,5 @@ -# $Id$ +DAVFetchSpec +============ Required Context diff --git a/sope-appserver/NGObjWeb/WebDAV/README b/sope-appserver/NGObjWeb/WebDAV/README index 789b62c7..c3a121f1 100644 --- a/sope-appserver/NGObjWeb/WebDAV/README +++ b/sope-appserver/NGObjWeb/WebDAV/README @@ -1,12 +1,126 @@ -# $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--- diff --git a/sope-appserver/NGObjWeb/WebDAV/SoObjectWebDAVDispatcher.m b/sope-appserver/NGObjWeb/WebDAV/SoObjectWebDAVDispatcher.m index f18c1e2a..cd9f1d05 100644 --- a/sope-appserver/NGObjWeb/WebDAV/SoObjectWebDAVDispatcher.m +++ b/sope-appserver/NGObjWeb/WebDAV/SoObjectWebDAVDispatcher.m @@ -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 */ -- 2.39.5