]> err.no Git - sope/blob - sope-appserver/NGObjWeb/WebDAV/SoObject+SoDAV.m
fixed header
[sope] / sope-appserver / NGObjWeb / WebDAV / SoObject+SoDAV.m
1 /*
2   Copyright (C) 2002-2004 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
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
9   later version.
10
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.
15
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
19   02111-1307, USA.
20 */
21
22 #include "SoObject+SoDAV.h"
23 #include "SoObject.h"
24 #include "NSException+HTTP.h"
25 #include "SoDAVLockManager.h"
26 #include <NGObjWeb/WOApplication.h>
27 #include "common.h"
28
29 /* informal interface for methods tried by the DAV key implementation */
30
31 @interface NSObject(SoResourceObject)
32
33 - (BOOL)isCollection;
34 - (NSString *)displayName;
35 - (NSString *)path;
36
37 - (unsigned int)contentLength;
38 - (EOGlobalID *)globalID;
39
40 - (id)baseURL;
41 - (id)baseURLInContext:(id)_ctx;
42
43 @end
44
45 @implementation NSObject(SoObjectSoDAVImp)
46
47 - (NSArray *)defaultWebDAVPropertyNamesInContext:(id)_ctx {
48   static NSArray *defNames = nil;
49   if (defNames == nil) {
50     defNames = [[[NSUserDefaults standardUserDefaults] 
51                                  arrayForKey:@"SoDefaultWebDAVPropertyNames"]
52                                  copy];
53   }
54 #if 0 /* TODO: check whether this would be better ... */
55   keys = [[self soClassDescription] attributeKeys];
56   [self debugWithFormat:@"using keys from description: %@", keys];
57 #endif
58   return defNames;
59 }
60
61 /* attributes */
62
63 - (BOOL)davIsCollection {
64   id v;
65   if ([self respondsToSelector:@selector(isCollection)])
66     return [self isCollection];
67   if ((v = [self valueForKey:@"NSFileType"])) {
68     if ([v isEqualToString:NSFileTypeDirectory])
69       return YES;
70     else
71       return NO;
72   }
73   return [[self toOneRelationshipKeys] count] > 0 ? YES : NO;
74 }
75
76 - (BOOL)davIsFolder {
77   return [self davIsCollection];
78 }
79
80 - (BOOL)davHasSubFolders {
81   NSEnumerator *e;
82   NSString *childName;
83   id       ctx;
84   
85   if (![self davIsCollection]) return NO;
86   ctx = [[WOApplication application] context];
87   
88   e = [self davChildKeysInContext:ctx];
89   while ((childName = [e nextObject])) {
90     if ([[self lookupName:childName inContext:ctx acquire:NO] davIsFolder])
91       return YES;
92   }
93   return NO;
94 }
95
96 - (BOOL)davDenySubFolders {
97   return [self davIsCollection] ? NO : YES;
98 }
99
100 - (unsigned int)davChildCount {
101   NSEnumerator *e;
102   unsigned int i;
103   
104   if (![self davIsCollection]) return 0;
105   e = [self davChildKeysInContext:[[WOApplication application] context]];
106   for (i = 0; [e nextObject]; i++)
107     ;
108   return i;
109 }
110 - (unsigned int)davObjectCount {
111   NSEnumerator *e;
112   unsigned int i;
113   NSString     *childName;
114   WOContext    *ctx;
115   
116   if (![self davIsCollection]) return 0;
117   
118   ctx = [[WOApplication application] context];
119   i = 0;
120   e = [self davChildKeysInContext:ctx];
121   while ((childName = [e nextObject])) {
122     if (![[self lookupName:childName inContext:ctx acquire:NO] davIsCollection])
123       i++;
124   }
125   return i;
126 }
127 - (unsigned int)davVisibleCount {
128   return [self davObjectCount];
129 }
130
131 - (BOOL)davIsHidden {
132   return NO;
133 }
134
135 - (id)davUid {
136   if ([self respondsToSelector:@selector(globalID)])
137     return [self globalID];
138   return [self davURL];
139 }
140 - (id)davEntityTag {
141   return [self davUid];
142 }
143
144 - (BOOL)davIsStructuredDocument {
145   return NO;
146 }
147
148 - (id)davURL {
149   id url;
150   
151   if ([self respondsToSelector:@selector(baseURLInContext:)]) {
152     url = [self baseURLInContext:[[WOApplication application] context]];
153   }
154   else if ([self respondsToSelector:@selector(baseURL)]) {
155     [self logWithFormat:@"object does not respond to baseURLInContext:?"];
156     url = [self baseURL];
157   }
158   else {
159     [self logWithFormat:
160             @"WARNING: unable to calculate davURL for this object !"];
161     url = nil;
162   }
163   if (url == nil)
164     [self logWithFormat:@"WARNING: got no davURL for this object !"];
165   
166   return url;
167 }
168
169 - (NSDate *)davLastModified {
170   id v;
171   if ((v = [self valueForKey:NSFileModificationDate])) return v;
172   return [NSDate date];
173 }
174
175 - (NSDate *)davCreationDate {
176   id v;
177   if ((v = [self valueForKey:@"NSFileCreationDate"]))  return v;
178   if ((v = [self valueForKey:NSFileModificationDate])) return v;
179   return nil;
180 }
181
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 */
186   }
187   
188   return @"application/octet-stream";
189 }
190
191 - (id)davContentLength {
192   id v;
193   if ((v = [self valueForKey:NSFileSize])) return v;
194   if ([self respondsToSelector:@selector(contentLength)])
195     return [NSNumber numberWithUnsignedInt:[self contentLength]];
196   return 0;
197 }
198 - (NSString *)davDisplayName {
199   id v = nil;
200   
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"])) ;
208   NS_HANDLER
209     v = nil;
210   NS_ENDHANDLER;
211 #else
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];
215 #endif
216   if ([self respondsToSelector:@selector(path)])
217     return [[self path] lastPathComponent];
218   return nil;
219 }
220
221 - (NSString *)davResourceType {
222   if ([self davIsCollection])
223     return @"collection";
224   return nil;
225 }
226
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";
232 }
233
234 - (BOOL)davIsExecutable {
235   return NO;
236 }
237
238 /* lock manager */
239
240 - (SoDAVLockManager *)davLockManagerInContext:(id)_ctx {
241   return [SoDAVLockManager sharedLockManager];
242 }
243
244 @end /* NSObject(SoObjectSoDAV) */
245
246 @implementation NSObject(SoObjectDAVMaps)
247
248 + (NSString *)lookupDefMapPlist {
249   NSString *apath;
250 #if !COMPILE_AS_FRAMEWORK
251     NSFileManager *fm = [NSFileManager defaultManager];
252     NSDictionary  *env;
253     NSString      *relPath;
254 #endif
255 #if COMPILE_AS_FRAMEWORK
256     {
257       NSBundle *bundle;
258       
259       bundle = [NSBundle bundleForClass:self];
260       apath  = [bundle pathForResource:@"DAVPropMap" ofType:@"plist"];
261     }
262 #else
263     env  = [[NSProcessInfo processInfo] environment];
264     relPath = @"Libraries";
265     relPath = [relPath stringByAppendingPathComponent:@"Resources"];
266     relPath = [relPath stringByAppendingPathComponent:@"NGObjWeb"];
267     relPath = [relPath stringByAppendingPathComponent:@"DAVPropMap.plist"];
268     
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];
274     }
275     if (![fm fileExistsAtPath:apath]) {
276       apath = [env objectForKey:@"GNUSTEP_SYSTEM_ROOT"];
277       apath = [apath stringByAppendingPathComponent:relPath];
278     }
279     if (![fm fileExistsAtPath:apath]) {
280       apath = relPath;
281     }
282     if (![fm fileExistsAtPath:apath]) {
283       NSLog(@"ERROR: cannot find DAVPropMap.plist resource "
284             @"of NGObjWeb library !");
285     }
286 #endif
287   return apath;
288 }
289
290 + (id)defaultWebDAVAttributeMap {
291   static NSDictionary *defMap = nil;
292   if (defMap == nil) {
293     NSString *path;
294     
295     if ((path = [self lookupDefMapPlist]))
296       defMap = [[NSDictionary alloc] initWithContentsOfFile:path];
297   }
298   return defMap;
299 }
300
301 - (id)davAttributeMapInContext:(id)_ctx {
302   /* default is: do map some DAV properties, pass through anything else */
303   return [[self class] defaultWebDAVAttributeMap];
304 }
305
306 @end /* NSObject(SoObjectDAVMaps) */
307
308 #include <NGObjWeb/WOApplication.h>
309 #include <NGObjWeb/WORequestHandler.h>
310
311 @implementation WOCoreApplication(WebDAV)
312
313 - (BOOL)davIsCollection {
314   return YES;
315 }
316 - (BOOL)davHasSubFolders {
317   return YES;
318 }
319 - (id)davUid {
320   return [self davURL];
321 }
322 - (id)davURL {
323   return [self baseURL];
324 }
325 - (NSDate *)davLastModified {
326   return [NSDate date];
327 }
328 - (NSDate *)davCreationDate {
329   return nil;
330 }
331 - (NSString *)davContentType {
332   return @"text/html";
333 }
334 - (id)davContentLength {
335   return 0;
336 }
337 - (NSString *)davDisplayName {
338   return @"ROOT";
339 }
340
341 @end /* WOCoreApplication(WebDAV) */
342
343 @implementation WOApplication(WebDAV)
344
345 - (NSString *)davDisplayName {
346   return [self name];
347 }
348
349 @end /* WOApplication(WebDAV) */
350
351 @implementation WORequestHandler(WebDAV)
352
353 - (BOOL)davIsCollection {
354   return YES;
355 }
356 - (BOOL)davHasSubFolders {
357   return YES;
358 }
359
360 - (id)davUid {
361   return [self davURL];
362 }
363
364 - (NSDate *)davLastModified {
365   return [NSDate date];
366 }
367 - (NSDate *)davCreationDate {
368   return nil;
369 }
370
371 - (NSString *)davContentType {
372   return @"text/html";
373 }
374
375 - (id)davContentLength {
376   return 0;
377 }
378
379 @end /* WORequestHandler(WebDAV) */
380
381 #include "SoControlPanel.h"
382
383 @implementation SoControlPanel(WebDAV)
384
385 - (BOOL)davIsCollection {
386   return YES;
387 }
388 - (BOOL)davHasSubFolders {
389   return YES;
390 }
391
392 - (id)davUid {
393   return [self davURL];
394 }
395
396 - (NSDate *)davLastModified {
397   return [NSDate date];
398 }
399 - (NSDate *)davCreationDate {
400   return nil;
401 }
402
403 - (id)davContentLength {
404   return 0;
405 }
406
407 @end /* SoControlPanel(WebDAV) */
408
409 @implementation NSObject(DavOperations)
410
411 - (NSException *)davSetProperties:(NSDictionary *)_setProps
412   removePropertiesNamed:(NSArray *)_delProps
413   inContext:(id)_ctx
414 {
415   return [NSException exceptionWithHTTPStatus:405 /* not allowed */
416                       reason:@"this object cannot edit object properties "
417                       @"via WebDAV"];
418 }
419
420 - (id)davCreateObject:(NSString *)_name
421   properties:(NSDictionary *)_props
422   inContext:(id)_ctx
423 {
424   return [NSException exceptionWithHTTPStatus:405 /* not allowed */
425                       reason:@"this object cannot create child objects "
426                       @"via WebDAV"];
427 }
428
429 - (NSException *)davCreateCollection:(NSString *)_name inContext:(id)_ctx {
430   return [NSException exceptionWithHTTPStatus:405 /* not allowed */
431                       reason:@"this object cannot create subcollections "
432                       @"via WebDAV"];
433 }
434
435 - (NSException *)davMoveToTargetObject:(id)_target newName:(NSString *)_name
436   inContext:(id)_ctx
437 {
438   return [NSException exceptionWithHTTPStatus:405 /* not allowed */
439                       reason:@"this object cannot be moved via WebDAV"];
440 }
441
442 - (NSException *)davCopyToTargetObject:(id)_target newName:(NSString *)_name
443   inContext:(id)_ctx
444 {
445   return [NSException exceptionWithHTTPStatus:405 /* not allowed */
446                       reason:@"this object cannot be copied via WebDAV"];
447 }
448
449 @end /* NSObject(DavOperations) */