]> err.no Git - sope/blobdiff - sope-appserver/NGObjWeb/WebDAV/SoObjectWebDAVDispatcher.m
reverted gstep-base workaround (fixed in gstep-base svn trunk), bumped framework...
[sope] / sope-appserver / NGObjWeb / WebDAV / SoObjectWebDAVDispatcher.m
index cd9f1d054f89657d17033e5deda690758782b270..82f813d35ab3e41d64698622ef18e2c7cef78fa4 100644 (file)
@@ -30,6 +30,7 @@
 #include "SoDAVLockManager.h"
 #include "EOFetchSpecification+SoDAV.h"
 #include "WOContext+SoObjects.h"
+#include "NSException+HTTP.h"
 #include <NGObjWeb/WOApplication.h>
 #include <NGObjWeb/WORequest.h>
 #include <NGObjWeb/WOResponse.h>
@@ -105,55 +106,12 @@ static NSTimeZone                *gmt      = nil;
                      userInfo:ui];
 }
 
-- (NSArray *)allowedMethods {
-  static NSArray *defMethods = nil;
-  NSMutableArray *allow;
-
-  if (defMethods == nil) {
-    defMethods = [[[NSUserDefaults standardUserDefaults] 
-                                   arrayForKey:@"SoWebDAVDefaultAllowMethods"] 
-                                   copy];
-  }
-  
-  allow = [NSMutableArray arrayWithCapacity:16];
-  if (defMethods) [allow addObjectsFromArray:defMethods];
-  
-  if ([self->object 
-           respondsToSelector:@selector(performWebDAVQuery:inContext:)]) {
-    [allow addObject:@"PROPFIND"];
-    [allow addObject:@"SEARCH"];
-  }
-  if ([self->object respondsToSelector:
-            @selector(davSetProperties:removePropertiesNamed:)])
-    [allow addObject:@"PROPPATCH"];
-  
-  return allow;
-}
-
 - (NSString *)baseURLForContext:(WOContext *)_ctx {
-  /*
-    Note: Evolution doesn't correctly transfer the "Host:" header, it
-    misses the port argument :-(
-  */
-  NSString  *baseURL;
-  WORequest *rq;
-  NSString  *hostport;
-  id tmp;
+  extern NSString *SoObjectRootURLInContext(WOContext *_ctx, id logobj, BOOL withAppPart);
+  NSString *rootURL;
   
-  rq = [_ctx request];
-  
-  if ((tmp = [rq headerForKey:@"x-webobjects-server-name"])) {
-    hostport = tmp;
-    if ((tmp = [rq headerForKey:@"x-webobjects-server-port"]))
-      hostport = [NSString stringWithFormat:@"%@:%@", hostport, tmp];
-  }
-  else if ((tmp = [rq headerForKey:@"host"]))
-    hostport = tmp;
-  else
-    hostport = [[NSHost currentHost] name];
-  
-  baseURL = [NSString stringWithFormat:@"http://%@%@", hostport, [rq uri]];
-  return baseURL;
+  rootURL = SoObjectRootURLInContext(_ctx, self, NO);
+  return [rootURL stringByAppendingString:[[_ctx request] uri]];
 }
 
 - (id)primaryCallWebDAVMethod:(NSString *)_name inContext:(WOContext *)_ctx {
@@ -175,16 +133,43 @@ static NSTimeZone                *gmt      = nil;
 
 /* core HTTP methods */
 
-- (id)doGET:(WOContext *)_ctx {
+- (id)_callObjectMethod:(NSString *)_method inContext:(WOContext *)_ctx {
+  /* returns 'nil' if the object had no such method */
   NSException *e;
   id methodObject;
+  id result;
+  
+  methodObject =
+    [self->object lookupName:_method inContext:_ctx acquire:NO];
+  if (![methodObject isNotNull])
+    return nil;
+  if ([methodObject isKindOfClass:[NSException class]]) {
+    if ([(NSException *)methodObject httpStatus] == 404 /* Not Found */) {
+      /* not found */
+      return nil;
+    }
+    return methodObject; /* the exception */
+  }
+  if ((e = [self->object validateName:_method inContext:_ctx]) != nil)
+    return e;
   
+  if ([methodObject respondsToSelector:
+                     @selector(takeValuesFromRequest:inContext:)])
+    [methodObject takeValuesFromRequest:[_ctx request] inContext:_ctx];
   
-  if ((methodObject = 
-       [self->object lookupName:@"GET" inContext:_ctx acquire:NO]) == nil)
+  result = [methodObject callOnObject:self->object inContext:_ctx];
+  return (result != nil) ? result : [NSNull null];
+}
+
+- (id)doGET:(WOContext *)_ctx {
+  NSException *e;
+  id methodObject;
+  
+  methodObject = [self->object lookupName:@"GET" inContext:_ctx acquire:NO];
+  if (methodObject == nil)
     methodObject = [self->object lookupDefaultMethod];
   else {
-    if ((e = [self->object validateName:@"GET" inContext:_ctx]))
+    if ((e = [self->object validateName:@"GET" inContext:_ctx]) != nil)
       return e;
   }
   
@@ -226,6 +211,7 @@ static NSTimeZone                *gmt      = nil;
   
   if ([pathInfo length] > 0) {
     /* check whether all the parent collections are available */
+    // TODO: we might also want to check for a 'create' permission
     if ([pathInfo rangeOfString:@"/"].length > 0) {
       return [self httpException:409 /* Conflict */
                   reason:
@@ -269,7 +255,35 @@ static NSTimeZone                *gmt      = nil;
 }
 
 - (id)doOPTIONS:(WOContext *)_ctx {
-  return [self allowedMethods];
+  WOResponse *response;
+  NSArray    *tmp;
+  id         result;
+  
+  /* this checks whether the object provides a specific OPTIONS method */
+  if ((result = [self _callObjectMethod:@"OPTIONS" inContext:_ctx]) != nil)
+    return result;
+  
+  response = [_ctx response];
+  [response setStatus:200 /* OK */];
+  
+  if ((tmp = [self->object davAllowedMethodsInContext:_ctx]) != nil) 
+    [response setHeader:[tmp componentsJoinedByString:@", "] forKey:@"allow"];
+  
+  if ([[[_ctx request] clientCapabilities] isWebFolder]) {
+    /*
+       As described over here:
+         http://teyc.editthispage.com/2005/06/02
+       
+       This page also says that: "MS-Auth-Via header is not required to work
+       with Web Folders".
+    */
+    [response setHeader:[tmp componentsJoinedByString:@", "] forKey:@"public"];
+  }
+  
+  if ((tmp = [self->object davComplianceClassesInContext:_ctx]) != nil) 
+    [response setHeader:[tmp componentsJoinedByString:@", "] forKey:@"dav"];
+  
+  return response;
 }
 
 - (id)doHEAD:(WOContext *)_ctx {
@@ -1471,10 +1485,40 @@ static NSTimeZone                *gmt      = nil;
 /* DAV reports */
 
 - (id)doREPORT:(WOContext *)_ctx {
+  WORequest *rq;
+  id domDocument;
+  
+  rq = [_ctx request];
+  
+  /* ensure XML */
+
+  if (![[rq headerForKey:@"content-type"] hasPrefix:@"text/xml"]) {
+    return [self httpException:400 /* invalid request */
+                reason:@"XML entity expected for WebDAV REPORT."];
+  }
+
+  /* retrieve XML */
+
+  if ((domDocument = [rq contentAsDOMDocument]) == nil) {
+    return [self httpException:400 /* invalid request */
+                reason:@"Could not parse XML of WebDAV REPORT."];
+  }
+  
+  /* process DOM */
+
+  [self logWithFormat:@"TODO: process REPORT: %@", domDocument];
+  
   return [self httpException:405 /* method not allowed */
               reason:@"WebDAV reports not yet implemented."];
 }
 
+/* CalDAV */
+
+- (id)doMKCALENDAR:(WOContext *)_ctx {
+  return [self httpException:405 /* method not allowed */
+              reason:@"CalDAV calendar creation not yet implemented."];
+}
+
 /* DAV access control lists */
 
 - (id)doACL:(WOContext *)_ctx {