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 - (NSArray *) toOneRelationshipKeys {
241 /* toOneRelationshipKeys are the 'files' contained in a folder */
244 NSString *name, *ext;
248 names = [self fetchContentObjectNames];
249 count = [names count];
250 ext = [self defaultFilenameExtension];
251 if (count && [ext length] > 0)
253 ma = [NSMutableArray arrayWithCapacity: count];
254 for (i = 0; i < count; i++)
256 name = [names objectAtIndex: i];
257 r = [name rangeOfString: @"."];
259 name = [[name stringByAppendingString:@"."] stringByAppendingString: ext];
269 /* acls as a container */
271 - (NSArray *) aclUsersForObjectAtPath: (NSArray *) objectPathArray;
273 EOQualifier *qualifier;
277 qs = [NSString stringWithFormat: @"c_object = '/%@'",
278 [objectPathArray componentsJoinedByString: @"/"]];
279 qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
280 records = [[self ocsFolder] fetchAclMatchingQualifier: qualifier];
282 return [records valueForKey: @"c_uid"];
285 - (NSArray *) _fetchAclsForUser: (NSString *) uid
286 forObjectAtPath: (NSString *) objectPath
288 EOQualifier *qualifier;
290 NSMutableArray *acls;
293 qs = [NSString stringWithFormat: @"(c_object = '/%@') AND (c_uid = '%@')",
295 qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
296 records = [[self ocsFolder] fetchAclMatchingQualifier: qualifier];
298 acls = [NSMutableArray array];
299 if ([records count] > 0)
301 [acls addObject: SOGoRole_AuthorizedSubscriber];
302 [acls addObjectsFromArray: [records valueForKey: @"c_role"]];
308 - (void) _cacheRoles: (NSArray *) roles
309 forUser: (NSString *) uid
310 forObjectAtPath: (NSString *) objectPath
312 NSMutableDictionary *aclsForObject;
314 aclsForObject = [aclCache objectForKey: objectPath];
317 aclsForObject = [NSMutableDictionary dictionary];
318 [aclCache setObject: aclsForObject
322 [aclsForObject setObject: roles forKey: uid];
324 [aclsForObject removeObjectForKey: uid];
327 - (NSArray *) aclsForUser: (NSString *) uid
328 forObjectAtPath: (NSArray *) objectPathArray
331 NSString *objectPath;
332 NSDictionary *aclsForObject;
334 objectPath = [objectPathArray componentsJoinedByString: @"/"];
335 aclsForObject = [aclCache objectForKey: objectPath];
337 acls = [aclsForObject objectForKey: uid];
342 acls = [self _fetchAclsForUser: uid forObjectAtPath: objectPath];
343 [self _cacheRoles: acls forUser: uid forObjectAtPath: objectPath];
346 if (!([acls count] || [uid isEqualToString: defaultUserID]))
347 acls = [self aclsForUser: defaultUserID
348 forObjectAtPath: objectPathArray];
353 - (void) removeAclsForUsers: (NSArray *) users
354 forObjectAtPath: (NSArray *) objectPathArray
356 EOQualifier *qualifier;
357 NSString *uids, *qs, *objectPath;
358 NSMutableDictionary *aclsForObject;
360 if ([users count] > 0)
362 objectPath = [objectPathArray componentsJoinedByString: @"/"];
363 aclsForObject = [aclCache objectForKey: objectPath];
365 [aclsForObject removeObjectsForKeys: users];
366 uids = [users componentsJoinedByString: @"') OR (c_uid = '"];
368 stringWithFormat: @"(c_object = '/%@') AND ((c_uid = '%@'))",
370 qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
371 [[self ocsFolder] deleteAclMatchingQualifier: qualifier];
375 - (void) _commitRoles: (NSArray *) roles
376 forUID: (NSString *) uid
377 forObject: (NSString *) objectPath
379 EOAdaptorChannel *channel;
381 NSEnumerator *userRoles;
382 NSString *SQL, *currentRole;
384 folder = [self ocsFolder];
385 channel = [folder acquireAclChannel];
386 userRoles = [roles objectEnumerator];
387 currentRole = [userRoles nextObject];
390 SQL = [NSString stringWithFormat: @"INSERT INTO %@"
391 @" (c_object, c_uid, c_role)"
392 @" VALUES ('/%@', '%@', '%@')",
393 [folder aclTableName],
394 objectPath, uid, currentRole];
395 [channel evaluateExpressionX: SQL];
396 currentRole = [userRoles nextObject];
399 [folder releaseChannel: channel];
402 - (void) setRoles: (NSArray *) roles
403 forUser: (NSString *) uid
404 forObjectAtPath: (NSArray *) objectPathArray
406 NSString *objectPath;
407 NSMutableArray *newRoles;
409 [self removeAclsForUsers: [NSArray arrayWithObject: uid]
410 forObjectAtPath: objectPathArray];
412 newRoles = [NSMutableArray arrayWithArray: roles];
413 [newRoles removeObject: SOGoRole_AuthorizedSubscriber];
414 [newRoles removeObject: SOGoRole_None];
415 objectPath = [objectPathArray componentsJoinedByString: @"/"];
416 [self _cacheRoles: newRoles forUser: uid
417 forObjectAtPath: objectPath];
418 if (![newRoles count])
419 [newRoles addObject: SOGoRole_None];
421 [self _commitRoles: newRoles forUID: uid forObject: objectPath];
425 - (NSArray *) aclUsers
427 return [self aclUsersForObjectAtPath: [self pathArrayToSoObject]];
430 - (NSArray *) aclsForUser: (NSString *) uid
432 return [self aclsForUser: uid
433 forObjectAtPath: [self pathArrayToSoObject]];
436 - (void) setRoles: (NSArray *) roles
437 forUser: (NSString *) uid
439 return [self setRoles: roles
441 forObjectAtPath: [self pathArrayToSoObject]];
444 - (void) removeAclsForUsers: (NSArray *) users
446 return [self removeAclsForUsers: users
447 forObjectAtPath: [self pathArrayToSoObject]];
450 - (NSString *) defaultUserID
452 return defaultUserID;
455 - (BOOL) hasSupportForDefaultRoles
462 - (BOOL) davIsCollection
464 return [self isFolderish];
469 - (NSString *)outlookFolderClass {
475 - (void)appendAttributesToDescription:(NSMutableString *)_ms {
476 [super appendAttributesToDescription:_ms];
478 [_ms appendFormat:@" ocs=%@", [self ocsPath]];
481 - (NSString *)loggingPrefix {
482 return [NSString stringWithFormat:@"<0x%08X[%@]:%@>",
483 self, NSStringFromClass([self class]),
484 [self nameInContainer]];
487 @end /* SOGoFolder */