2 Copyright (C) 2004-2005 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 #import <NGObjWeb/SoObject.h>
23 #import <GDLAccess/EOAdaptorChannel.h>
24 #import <GDLContentStore/GCSFolderManager.h>
25 #import <GDLContentStore/GCSFolder.h>
26 #import <GDLContentStore/GCSFolderType.h>
28 #import "SOGoPermissions.h"
29 #import "SOGoFolder.h"
34 static NSString *defaultUserID = @"<default>";
36 @implementation SOGoFolder
40 return [super version] + 0 /* v0 */;
45 NSAssert2([super version] == 0,
46 @"invalid superclass (%@) version %i !",
47 NSStringFromClass([self superclass]), [super version]);
50 + (NSString *) globallyUniqueObjectId
53 4C08AE1A-A808-11D8-AC5A-000393BBAFF6
54 SOGo-Web-28273-18283-288182
55 printf( "%x", *(int *) &f);
58 static int sequence = 0;
59 static float rndm = 0;
63 { /* break if we fork ;-) */
68 f = [[NSDate date] timeIntervalSince1970];
69 return [NSString stringWithFormat:@"%0X-%0X-%0X-%0X",
70 pid, *(int *)&f, sequence++, random];
75 if ((self = [super init]))
79 aclCache = [NSMutableDictionary new];
100 - (void) setOCSPath: (NSString *) _path
102 if ([ocsPath isEqualToString:_path])
106 [self warnWithFormat:@"GCS path is already set! '%@'", _path];
108 ASSIGNCOPY(ocsPath, _path);
111 - (NSString *) ocsPath
116 - (GCSFolderManager *) folderManager
118 static GCSFolderManager *folderManager = nil;
122 folderManager = [GCSFolderManager defaultFolderManager];
123 [folderManager setFolderNamePrefix: @"SOGo_"];
126 return folderManager;
129 - (GCSFolder *) ocsFolderForPath: (NSString *) _path
131 return [[self folderManager] folderAtPath:_path];
134 - (GCSFolder *) ocsFolder
139 ocsFolder = [[self ocsFolderForPath:[self ocsPath]] retain];
141 if ([ocsFolder isNotNull])
149 - (NSString *) folderType
158 result = [[self folderManager] createFolderOfType: [self folderType]
161 return (result == nil);
164 - (NSException *) delete
166 return [[self folderManager] deleteFolderAtPath: ocsPath];
169 - (NSArray *)fetchContentObjectNames {
170 NSArray *fields, *records;
172 fields = [NSArray arrayWithObject:@"c_name"];
173 records = [[self ocsFolder] fetchFields:fields matchingQualifier:nil];
174 if (![records isNotNull]) {
175 [self errorWithFormat:@"(%s): fetch failed!", __PRETTY_FUNCTION__];
178 if ([records isKindOfClass:[NSException class]])
180 return [records valueForKey:@"c_name"];
183 - (BOOL) nameExistsInFolder: (NSString *) objectName
185 NSArray *fields, *records;
186 EOQualifier *qualifier;
189 = [EOQualifier qualifierWithQualifierFormat:
190 [NSString stringWithFormat: @"c_name='%@'", objectName]];
192 fields = [NSArray arrayWithObject: @"c_name"];
193 records = [[self ocsFolder] fetchFields: fields
194 matchingQualifier: qualifier];
196 && ![records isKindOfClass:[NSException class]]
197 && [records count] > 0);
200 - (NSDictionary *)fetchContentStringsAndNamesOfAllObjects {
203 files = [[self ocsFolder] fetchContentsOfAllFiles];
204 if (![files isNotNull]) {
205 [self errorWithFormat:@"(%s): fetch failed!", __PRETTY_FUNCTION__];
208 if ([files isKindOfClass:[NSException class]])
215 - (NSString *)defaultFilenameExtension {
217 Override to add an extension to a filename
219 Note: be careful with that, needs to be consistent with object lookup!
224 - (NSArray *) davResourceType
226 NSArray *rType, *groupDavCollection;
228 if ([self respondsToSelector: @selector (groupDavResourceType)])
230 groupDavCollection = [NSArray arrayWithObjects: [self groupDavResourceType],
231 @"http://groupdav.org/", @"G", nil];
232 rType = [NSArray arrayWithObjects: @"collection", groupDavCollection, nil];
235 rType = [NSArray arrayWithObject: @"collection"];
240 - (NSString *) davContentType
242 return @"httpd/unix-directory";
245 - (NSArray *) toOneRelationshipKeys {
246 /* toOneRelationshipKeys are the 'files' contained in a folder */
249 NSString *name, *ext;
253 names = [self fetchContentObjectNames];
254 count = [names count];
255 ext = [self defaultFilenameExtension];
256 if (count && [ext length] > 0)
258 ma = [NSMutableArray arrayWithCapacity: count];
259 for (i = 0; i < count; i++)
261 name = [names objectAtIndex: i];
262 r = [name rangeOfString: @"."];
264 name = [[name stringByAppendingString:@"."] stringByAppendingString: ext];
274 /* acls as a container */
276 - (NSArray *) aclUsersForObjectAtPath: (NSArray *) objectPathArray;
278 EOQualifier *qualifier;
282 qs = [NSString stringWithFormat: @"c_object = '/%@'",
283 [objectPathArray componentsJoinedByString: @"/"]];
284 qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
285 records = [[self ocsFolder] fetchAclMatchingQualifier: qualifier];
287 return [records valueForKey: @"c_uid"];
290 - (NSArray *) _fetchAclsForUser: (NSString *) uid
291 forObjectAtPath: (NSString *) objectPath
293 EOQualifier *qualifier;
295 NSMutableArray *acls;
298 qs = [NSString stringWithFormat: @"(c_object = '/%@') AND (c_uid = '%@')",
300 qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
301 records = [[self ocsFolder] fetchAclMatchingQualifier: qualifier];
303 acls = [NSMutableArray array];
304 if ([records count] > 0)
306 [acls addObject: SOGoRole_AuthorizedSubscriber];
307 [acls addObjectsFromArray: [records valueForKey: @"c_role"]];
313 - (void) _cacheRoles: (NSArray *) roles
314 forUser: (NSString *) uid
315 forObjectAtPath: (NSString *) objectPath
317 NSMutableDictionary *aclsForObject;
319 aclsForObject = [aclCache objectForKey: objectPath];
322 aclsForObject = [NSMutableDictionary dictionary];
323 [aclCache setObject: aclsForObject
327 [aclsForObject setObject: roles forKey: uid];
329 [aclsForObject removeObjectForKey: uid];
332 - (NSArray *) aclsForUser: (NSString *) uid
333 forObjectAtPath: (NSArray *) objectPathArray
336 NSString *objectPath;
337 NSDictionary *aclsForObject;
339 objectPath = [objectPathArray componentsJoinedByString: @"/"];
340 aclsForObject = [aclCache objectForKey: objectPath];
342 acls = [aclsForObject objectForKey: uid];
347 acls = [self _fetchAclsForUser: uid forObjectAtPath: objectPath];
348 [self _cacheRoles: acls forUser: uid forObjectAtPath: objectPath];
351 if (!([acls count] || [uid isEqualToString: defaultUserID]))
352 acls = [self aclsForUser: defaultUserID
353 forObjectAtPath: objectPathArray];
358 - (void) removeAclsForUsers: (NSArray *) users
359 forObjectAtPath: (NSArray *) objectPathArray
361 EOQualifier *qualifier;
362 NSString *uids, *qs, *objectPath;
363 NSMutableDictionary *aclsForObject;
365 if ([users count] > 0)
367 objectPath = [objectPathArray componentsJoinedByString: @"/"];
368 aclsForObject = [aclCache objectForKey: objectPath];
370 [aclsForObject removeObjectsForKeys: users];
371 uids = [users componentsJoinedByString: @"') OR (c_uid = '"];
373 stringWithFormat: @"(c_object = '/%@') AND ((c_uid = '%@'))",
375 qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
376 [[self ocsFolder] deleteAclMatchingQualifier: qualifier];
380 - (void) _commitRoles: (NSArray *) roles
381 forUID: (NSString *) uid
382 forObject: (NSString *) objectPath
384 EOAdaptorChannel *channel;
386 NSEnumerator *userRoles;
387 NSString *SQL, *currentRole;
389 folder = [self ocsFolder];
390 channel = [folder acquireAclChannel];
391 userRoles = [roles objectEnumerator];
392 currentRole = [userRoles nextObject];
395 SQL = [NSString stringWithFormat: @"INSERT INTO %@"
396 @" (c_object, c_uid, c_role)"
397 @" VALUES ('/%@', '%@', '%@')",
398 [folder aclTableName],
399 objectPath, uid, currentRole];
400 [channel evaluateExpressionX: SQL];
401 currentRole = [userRoles nextObject];
404 [folder releaseChannel: channel];
407 - (void) setRoles: (NSArray *) roles
408 forUser: (NSString *) uid
409 forObjectAtPath: (NSArray *) objectPathArray
411 NSString *objectPath;
412 NSMutableArray *newRoles;
414 [self removeAclsForUsers: [NSArray arrayWithObject: uid]
415 forObjectAtPath: objectPathArray];
417 newRoles = [NSMutableArray arrayWithArray: roles];
418 [newRoles removeObject: SOGoRole_AuthorizedSubscriber];
419 [newRoles removeObject: SOGoRole_None];
420 objectPath = [objectPathArray componentsJoinedByString: @"/"];
421 [self _cacheRoles: newRoles forUser: uid
422 forObjectAtPath: objectPath];
423 if (![newRoles count])
424 [newRoles addObject: SOGoRole_None];
426 [self _commitRoles: newRoles forUID: uid forObject: objectPath];
430 - (NSArray *) aclUsers
432 return [self aclUsersForObjectAtPath: [self pathArrayToSoObject]];
435 - (NSArray *) aclsForUser: (NSString *) uid
437 NSMutableArray *acls;
438 NSArray *ownAcls, *containerAcls;
440 acls = [NSMutableArray array];
441 ownAcls = [self aclsForUser: uid
442 forObjectAtPath: [self pathArrayToSoObject]];
443 [acls addObjectsFromArray: ownAcls];
444 if ([container respondsToSelector: @selector (aclsForUser:)])
446 containerAcls = [container aclsForUser: uid];
447 if ([containerAcls count] > 0)
449 if ([containerAcls containsObject: SOGoRole_ObjectReader])
450 [acls addObject: SOGoRole_ObjectViewer];
451 #warning this should be checked
452 if ([containerAcls containsObject: SOGoRole_ObjectEraser])
453 [acls addObject: SOGoRole_ObjectEraser];
460 - (void) setRoles: (NSArray *) roles
461 forUser: (NSString *) uid
463 return [self setRoles: roles
465 forObjectAtPath: [self pathArrayToSoObject]];
468 - (void) removeAclsForUsers: (NSArray *) users
470 return [self removeAclsForUsers: users
471 forObjectAtPath: [self pathArrayToSoObject]];
474 - (NSString *) defaultUserID
476 return defaultUserID;
479 - (NSString *) httpURLForAdvisoryToUser: (NSString *) uid
481 return [[self soURL] absoluteString];
484 - (NSString *) resourceURLForAdvisoryToUser: (NSString *) uid
486 return [[self davURL] absoluteString];
491 - (BOOL) davIsCollection
493 return [self isFolderish];
498 - (NSString *)outlookFolderClass {
504 - (void)appendAttributesToDescription:(NSMutableString *)_ms {
505 [super appendAttributesToDescription:_ms];
507 [_ms appendFormat:@" ocs=%@", [self ocsPath]];
510 - (NSString *)loggingPrefix {
511 return [NSString stringWithFormat:@"<0x%08X[%@]:%@>",
512 self, NSStringFromClass([self class]),
513 [self nameInContainer]];
516 @end /* SOGoFolder */