2 Copyright (C) 2002-2004 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #include "SoObject+SoDAV.h"
24 #include "NSException+HTTP.h"
25 #include "SoDAVLockManager.h"
26 #include <NGObjWeb/WOApplication.h>
29 /* informal interface for methods tried by the DAV key implementation */
31 @interface NSObject(SoResourceObject)
34 - (NSString *)displayName;
37 - (unsigned int)contentLength;
38 - (EOGlobalID *)globalID;
41 - (id)baseURLInContext:(id)_ctx;
45 @implementation NSObject(SoObjectSoDAVImp)
47 - (NSArray *)defaultWebDAVPropertyNamesInContext:(id)_ctx {
48 static NSArray *defNames = nil;
49 if (defNames == nil) {
50 defNames = [[[NSUserDefaults standardUserDefaults]
51 arrayForKey:@"SoDefaultWebDAVPropertyNames"]
54 #if 0 /* TODO: check whether this would be better ... */
55 keys = [[self soClassDescription] attributeKeys];
56 [self debugWithFormat:@"using keys from description: %@", keys];
63 - (BOOL)davIsCollection {
65 if ([self respondsToSelector:@selector(isCollection)])
66 return [self isCollection];
67 if ((v = [self valueForKey:@"NSFileType"])) {
68 if ([v isEqualToString:NSFileTypeDirectory])
73 return [[self toOneRelationshipKeys] count] > 0 ? YES : NO;
77 return [self davIsCollection];
80 - (BOOL)davHasSubFolders {
85 if (![self davIsCollection]) return NO;
86 ctx = [[WOApplication application] context];
88 e = [self davChildKeysInContext:ctx];
89 while ((childName = [e nextObject])) {
90 if ([[self lookupName:childName inContext:ctx acquire:NO] davIsFolder])
96 - (BOOL)davDenySubFolders {
97 return [self davIsCollection] ? NO : YES;
100 - (unsigned int)davChildCount {
104 if (![self davIsCollection]) return 0;
105 e = [self davChildKeysInContext:[[WOApplication application] context]];
106 for (i = 0; [e nextObject]; i++)
110 - (unsigned int)davObjectCount {
116 if (![self davIsCollection]) return 0;
118 ctx = [[WOApplication application] context];
120 e = [self davChildKeysInContext:ctx];
121 while ((childName = [e nextObject])) {
122 if (![[self lookupName:childName inContext:ctx acquire:NO] davIsCollection])
127 - (unsigned int)davVisibleCount {
128 return [self davObjectCount];
131 - (BOOL)davIsHidden {
136 if ([self respondsToSelector:@selector(globalID)])
137 return [self globalID];
138 return [self davURL];
141 return [self davUid];
144 - (BOOL)davIsStructuredDocument {
151 if ([self respondsToSelector:@selector(baseURLInContext:)]) {
152 url = [self baseURLInContext:[[WOApplication application] context]];
154 else if ([self respondsToSelector:@selector(baseURL)]) {
155 [self logWithFormat:@"object does not respond to baseURLInContext:?"];
156 url = [self baseURL];
160 @"WARNING: unable to calculate davURL for this object !"];
164 [self logWithFormat:@"WARNING: got no davURL for this object !"];
169 - (NSDate *)davLastModified {
171 if ((v = [self valueForKey:NSFileModificationDate])) return v;
172 return [NSDate date];
175 - (NSDate *)davCreationDate {
177 if ((v = [self valueForKey:@"NSFileCreationDate"])) return v;
178 if ((v = [self valueForKey:NSFileModificationDate])) return v;
182 - (NSString *)davContentType {
183 if ([self davIsFolder]) {
184 //return @"x-directory/webdav"; /* this is taken from Nautilus */
185 return @"httpd/unix-directory"; /* this is returned by Apache */
188 return @"application/octet-stream";
191 - (id)davContentLength {
193 if ((v = [self valueForKey:NSFileSize])) return v;
194 if ([self respondsToSelector:@selector(contentLength)])
195 return [NSNumber numberWithUnsignedInt:[self contentLength]];
198 - (NSString *)davDisplayName {
201 if ([self respondsToSelector:@selector(displayName)])
202 return [self displayName];
203 #if COCOA_Foundation_LIBRARY
204 NS_DURING /* handle query for unbound key is easily triggered ... */
205 if ((v = [self valueForKey:@"NSFileSubject"])) ;
206 else if ((v = [self valueForKey:@"NSFileName"])) ;
207 else if ((v = [self valueForKey:@"NSFilePath"])) ;
212 if ((v = [self valueForKey:@"NSFileSubject"])) return v;
213 if ((v = [self valueForKey:@"NSFileName"])) return v;
214 if ((v = [self valueForKey:@"NSFilePath"])) return [v lastPathComponent];
216 if ([self respondsToSelector:@selector(path)])
217 return [[self path] lastPathComponent];
221 - (NSString *)davResourceType {
222 if ([self davIsCollection])
223 return @"collection";
227 - (NSString *)davContentClass {
228 /* this doesn't return something really useful, override if necessary ! */
229 return ([self davIsFolder])
230 ? @"urn:content-classes:folder"
231 : @"urn:content-classes:item";
234 - (BOOL)davIsExecutable {
240 - (SoDAVLockManager *)davLockManagerInContext:(id)_ctx {
241 return [SoDAVLockManager sharedLockManager];
244 @end /* NSObject(SoObjectSoDAV) */
246 @implementation NSObject(SoObjectDAVMaps)
248 + (NSString *)lookupDefMapPlist {
250 #if !COMPILE_AS_FRAMEWORK
251 NSFileManager *fm = [NSFileManager defaultManager];
255 #if COMPILE_AS_FRAMEWORK
259 bundle = [NSBundle bundleForClass:self];
260 apath = [bundle pathForResource:@"DAVPropMap" ofType:@"plist"];
263 env = [[NSProcessInfo processInfo] environment];
264 relPath = @"Libraries";
265 relPath = [relPath stringByAppendingPathComponent:@"Resources"];
266 relPath = [relPath stringByAppendingPathComponent:@"NGObjWeb"];
267 relPath = [relPath stringByAppendingPathComponent:@"DAVPropMap.plist"];
269 apath = [env objectForKey:@"GNUSTEP_USER_ROOT"];
270 apath = [apath stringByAppendingPathComponent:relPath];
271 if (![fm fileExistsAtPath:apath]) {
272 apath = [env objectForKey:@"GNUSTEP_LOCAL_ROOT"];
273 apath = [apath stringByAppendingPathComponent:relPath];
275 if (![fm fileExistsAtPath:apath]) {
276 apath = [env objectForKey:@"GNUSTEP_SYSTEM_ROOT"];
277 apath = [apath stringByAppendingPathComponent:relPath];
279 if (![fm fileExistsAtPath:apath]) {
282 if (![fm fileExistsAtPath:apath]) {
283 NSLog(@"ERROR: cannot find DAVPropMap.plist resource "
284 @"of NGObjWeb library !");
290 + (id)defaultWebDAVAttributeMap {
291 static NSDictionary *defMap = nil;
295 if ((path = [self lookupDefMapPlist]))
296 defMap = [[NSDictionary alloc] initWithContentsOfFile:path];
301 - (id)davAttributeMapInContext:(id)_ctx {
302 /* default is: do map some DAV properties, pass through anything else */
303 return [[self class] defaultWebDAVAttributeMap];
306 @end /* NSObject(SoObjectDAVMaps) */
308 #include <NGObjWeb/WOApplication.h>
309 #include <NGObjWeb/WORequestHandler.h>
311 @implementation WOCoreApplication(WebDAV)
313 - (BOOL)davIsCollection {
316 - (BOOL)davHasSubFolders {
320 return [self davURL];
323 return [self baseURL];
325 - (NSDate *)davLastModified {
326 return [NSDate date];
328 - (NSDate *)davCreationDate {
331 - (NSString *)davContentType {
334 - (id)davContentLength {
337 - (NSString *)davDisplayName {
341 @end /* WOCoreApplication(WebDAV) */
343 @implementation WOApplication(WebDAV)
345 - (NSString *)davDisplayName {
349 @end /* WOApplication(WebDAV) */
351 @implementation WORequestHandler(WebDAV)
353 - (BOOL)davIsCollection {
356 - (BOOL)davHasSubFolders {
361 return [self davURL];
364 - (NSDate *)davLastModified {
365 return [NSDate date];
367 - (NSDate *)davCreationDate {
371 - (NSString *)davContentType {
375 - (id)davContentLength {
379 @end /* WORequestHandler(WebDAV) */
381 #include "SoControlPanel.h"
383 @implementation SoControlPanel(WebDAV)
385 - (BOOL)davIsCollection {
388 - (BOOL)davHasSubFolders {
393 return [self davURL];
396 - (NSDate *)davLastModified {
397 return [NSDate date];
399 - (NSDate *)davCreationDate {
403 - (id)davContentLength {
407 @end /* SoControlPanel(WebDAV) */
409 @implementation NSObject(DavOperations)
411 - (NSException *)davSetProperties:(NSDictionary *)_setProps
412 removePropertiesNamed:(NSArray *)_delProps
415 return [NSException exceptionWithHTTPStatus:405 /* not allowed */
416 reason:@"this object cannot edit object properties "
420 - (id)davCreateObject:(NSString *)_name
421 properties:(NSDictionary *)_props
424 return [NSException exceptionWithHTTPStatus:405 /* not allowed */
425 reason:@"this object cannot create child objects "
429 - (NSException *)davCreateCollection:(NSString *)_name inContext:(id)_ctx {
430 return [NSException exceptionWithHTTPStatus:405 /* not allowed */
431 reason:@"this object cannot create subcollections "
435 - (NSException *)davMoveToTargetObject:(id)_target newName:(NSString *)_name
438 return [NSException exceptionWithHTTPStatus:405 /* not allowed */
439 reason:@"this object cannot be moved via WebDAV"];
442 - (NSException *)davCopyToTargetObject:(id)_target newName:(NSString *)_name
445 return [NSException exceptionWithHTTPStatus:405 /* not allowed */
446 reason:@"this object cannot be copied via WebDAV"];
449 @end /* NSObject(DavOperations) */