]> err.no Git - sope/blob - sope-appserver/NGObjWeb/WebDAV/SoObject+SoDAV.m
added some comments
[sope] / sope-appserver / NGObjWeb / WebDAV / SoObject+SoDAV.m
1 /*
2   Copyright (C) 2002-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE 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   SOPE 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 SOPE; 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   // TODO: check for set in SoClass slots
49   static NSArray *defNames = nil;
50   if (defNames == nil) {
51     defNames = [[[NSUserDefaults standardUserDefaults] 
52                                  arrayForKey:@"SoDefaultWebDAVPropertyNames"]
53                                  copy];
54   }
55 #if 0 /* TODO: check whether this would be better ... */
56   keys = [[self soClassDescription] attributeKeys];
57   [self debugWithFormat:@"using keys from description: %@", keys];
58 #endif
59   return defNames;
60 }
61
62 /* attributes */
63
64 - (BOOL)davIsCollection {
65   id v;
66   
67   if ([self respondsToSelector:@selector(isCollection)])
68     return [self isCollection];
69   if ([(v = [self valueForKey:@"NSFileType"]) isNotNull]) {
70     if ([v isEqualToString:NSFileTypeDirectory])
71       return YES;
72     else
73       return NO;
74   }
75   if ([[self toManyRelationshipKeys] count] > 0)
76     return YES;
77   if ([[self toOneRelationshipKeys] count] > 0)
78     return YES;
79   return NO;
80 }
81
82 - (BOOL)davIsFolder {
83   return [self davIsCollection];
84 }
85
86 - (BOOL)davHasSubFolders {
87   NSEnumerator *e;
88   NSString *childName;
89   id       ctx;
90   
91   if (![self davIsCollection]) return NO;
92   ctx = [[WOApplication application] context];
93   
94   e = [self davChildKeysInContext:ctx];
95   while ((childName = [e nextObject])) {
96     if ([[self lookupName:childName inContext:ctx acquire:NO] davIsFolder])
97       return YES;
98   }
99   return NO;
100 }
101
102 - (BOOL)davDenySubFolders {
103   return [self davIsCollection] ? NO : YES;
104 }
105
106 - (unsigned int)davChildCount {
107   NSEnumerator *e;
108   unsigned int i;
109   
110   if (![self davIsCollection]) return 0;
111   e = [self davChildKeysInContext:[[WOApplication application] context]];
112   for (i = 0; [e nextObject]; i++)
113     ;
114   return i;
115 }
116 - (unsigned int)davObjectCount {
117   NSEnumerator *e;
118   unsigned int i;
119   NSString     *childName;
120   WOContext    *ctx;
121   
122   if (![self davIsCollection]) return 0;
123   
124   ctx = [[WOApplication application] context];
125   i = 0;
126   e = [self davChildKeysInContext:ctx];
127   while ((childName = [e nextObject])) {
128     if (![[self lookupName:childName inContext:ctx acquire:NO] davIsCollection])
129       i++;
130   }
131   return i;
132 }
133 - (unsigned int)davVisibleCount {
134   return [self davObjectCount];
135 }
136
137 - (BOOL)davIsHidden {
138   return NO;
139 }
140
141 - (id)davUid {
142   if ([self respondsToSelector:@selector(globalID)])
143     return [self globalID];
144   return [self davURL];
145 }
146 - (id)davEntityTag {
147   return [self davUid];
148 }
149
150 - (BOOL)davIsStructuredDocument {
151   return NO;
152 }
153
154 - (id)davURL {
155   id url;
156   
157   if ([self respondsToSelector:@selector(baseURLInContext:)]) {
158     url = [self baseURLInContext:[[WOApplication application] context]];
159   }
160   else if ([self respondsToSelector:@selector(baseURL)]) {
161     [self logWithFormat:@"object does not respond to baseURLInContext:?"];
162     url = [self baseURL];
163   }
164   else {
165     [self warnWithFormat:@"unable to calculate davURL for this object !"];
166     url = nil;
167   }
168   if (url == nil)
169     [self warnWithFormat:@"got no davURL for this object !"];
170   
171   return url;
172 }
173
174 - (NSDate *)davLastModified {
175   id v;
176   if ((v = [self valueForKey:NSFileModificationDate])) return v;
177   return [NSDate date];
178 }
179
180 - (NSDate *)davCreationDate {
181   id v;
182   if ((v = [self valueForKey:@"NSFileCreationDate"]))  return v;
183   if ((v = [self valueForKey:NSFileModificationDate])) return v;
184   return nil;
185 }
186
187 - (NSString *)davContentType {
188   if ([self davIsFolder]) {
189     //return @"x-directory/webdav"; /* this is taken from Nautilus */
190     return @"httpd/unix-directory"; /* this is returned by Apache */
191   }
192   
193   return @"application/octet-stream";
194 }
195
196 - (id)davContentLength {
197   id v;
198   if ((v = [self valueForKey:NSFileSize])) return v;
199   if ([self respondsToSelector:@selector(contentLength)])
200     return [NSNumber numberWithUnsignedInt:[self contentLength]];
201   return 0;
202 }
203 - (NSString *)davDisplayName {
204   id v = nil;
205   
206   if ([self respondsToSelector:@selector(displayName)])
207     return [self displayName];
208 #if COCOA_Foundation_LIBRARY
209   NS_DURING /* handle query for unbound key is easily triggered ... */
210     if ((v = [self valueForKey:@"NSFileSubject"])) ;
211     else if ((v = [self valueForKey:@"NSFileName"])) ;
212     else if ((v = [self valueForKey:@"NSFilePath"])) ;
213   NS_HANDLER
214     v = nil;
215   NS_ENDHANDLER;
216 #else
217   if ((v = [self valueForKey:@"NSFileSubject"])) return v;
218   if ((v = [self valueForKey:@"NSFileName"])) return v;
219   if ((v = [self valueForKey:@"NSFilePath"])) return [v lastPathComponent];
220 #endif
221   if ([self respondsToSelector:@selector(path)])
222     return [[self path] lastPathComponent];
223   return nil;
224 }
225
226 - (NSString *)davResourceType {
227   if ([self davIsCollection])
228     return @"collection";
229   return nil;
230 }
231
232 - (NSString *)davContentClass {
233   /* this doesn't return something really useful, override if necessary ! */
234   return ([self davIsFolder])
235     ? @"urn:content-classes:folder"
236     : @"urn:content-classes:item";
237 }
238
239 - (BOOL)davIsExecutable {
240   return NO;
241 }
242
243 /* lock manager */
244
245 - (SoDAVLockManager *)davLockManagerInContext:(id)_ctx {
246   return [SoDAVLockManager sharedLockManager];
247 }
248
249 @end /* NSObject(SoObjectSoDAV) */
250
251 @interface WOCoreApplication(Resources)
252 + (NSString *)findNGObjWebResource:(NSString *)_name ofType:(NSString *)_ext;
253 @end
254
255 @implementation NSObject(SoObjectDAVMaps)
256
257 + (id)defaultWebDAVAttributeMap {
258   static NSDictionary *defMap = nil;
259   if (defMap == nil) {
260     NSString *path;
261     
262     path = [WOApplication findNGObjWebResource:@"DAVPropMap" ofType:@"plist"];
263     if (path != nil)
264       defMap = [[NSDictionary alloc] initWithContentsOfFile:path];
265   }
266   return defMap;
267 }
268
269 - (id)davAttributeMapInContext:(id)_ctx {
270   /* default is: do map some DAV properties, pass through anything else */
271   return [[self class] defaultWebDAVAttributeMap];
272 }
273
274 @end /* NSObject(SoObjectDAVMaps) */
275
276 #include <NGObjWeb/WOApplication.h>
277 #include <NGObjWeb/WORequestHandler.h>
278
279 @implementation WOCoreApplication(WebDAV)
280
281 - (BOOL)davIsCollection {
282   return YES;
283 }
284 - (BOOL)davHasSubFolders {
285   return YES;
286 }
287 - (id)davUid {
288   return [self davURL];
289 }
290 - (id)davURL {
291   return [self baseURL];
292 }
293 - (NSDate *)davLastModified {
294   return [NSDate date];
295 }
296 - (NSDate *)davCreationDate {
297   return nil;
298 }
299 - (NSString *)davContentType {
300   return @"text/html";
301 }
302 - (id)davContentLength {
303   return 0;
304 }
305 - (NSString *)davDisplayName {
306   return @"ROOT";
307 }
308
309 @end /* WOCoreApplication(WebDAV) */
310
311 @implementation WOApplication(WebDAV)
312
313 - (NSString *)davDisplayName {
314   return [self name];
315 }
316
317 @end /* WOApplication(WebDAV) */
318
319 @implementation WORequestHandler(WebDAV)
320
321 - (BOOL)davIsCollection {
322   return YES;
323 }
324 - (BOOL)davHasSubFolders {
325   return YES;
326 }
327
328 - (id)davUid {
329   return [self davURL];
330 }
331
332 - (NSDate *)davLastModified {
333   return [NSDate date];
334 }
335 - (NSDate *)davCreationDate {
336   return nil;
337 }
338
339 - (NSString *)davContentType {
340   return @"text/html";
341 }
342
343 - (id)davContentLength {
344   return 0;
345 }
346
347 @end /* WORequestHandler(WebDAV) */
348
349 #include "SoControlPanel.h"
350
351 @implementation SoControlPanel(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 - (id)davContentLength {
372   return 0;
373 }
374
375 @end /* SoControlPanel(WebDAV) */
376
377 @implementation NSObject(DavOperations)
378
379 - (NSException *)davSetProperties:(NSDictionary *)_setProps
380   removePropertiesNamed:(NSArray *)_delProps
381   inContext:(id)_ctx
382 {
383   return [NSException exceptionWithHTTPStatus:405 /* not allowed */
384                       reason:@"this object cannot edit object properties "
385                       @"via WebDAV"];
386 }
387
388 - (id)davCreateObject:(NSString *)_name
389   properties:(NSDictionary *)_props
390   inContext:(id)_ctx
391 {
392   return [NSException exceptionWithHTTPStatus:405 /* not allowed */
393                       reason:@"this object cannot create child objects "
394                       @"via WebDAV"];
395 }
396
397 - (NSException *)davCreateCollection:(NSString *)_name inContext:(id)_ctx {
398   return [NSException exceptionWithHTTPStatus:405 /* not allowed */
399                       reason:@"this object cannot create subcollections "
400                       @"via WebDAV"];
401 }
402
403 - (NSException *)davMoveToTargetObject:(id)_target newName:(NSString *)_name
404   inContext:(id)_ctx
405 {
406   return [NSException exceptionWithHTTPStatus:405 /* not allowed */
407                       reason:@"this object cannot be moved via WebDAV"];
408 }
409
410 - (NSException *)davCopyToTargetObject:(id)_target newName:(NSString *)_name
411   inContext:(id)_ctx
412 {
413   return [NSException exceptionWithHTTPStatus:405 /* not allowed */
414                       reason:@"this object cannot be copied via WebDAV"];
415 }
416
417 @end /* NSObject(DavOperations) */