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