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 *defaultUser = @"<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 *) aclsForObjectAtPath: (NSArray *) objectPathArray;
273 EOQualifier *qualifier;
276 qs = [NSString stringWithFormat: @"c_object = '/%@'",
277 [objectPathArray componentsJoinedByString: @"/"]];
278 qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
280 return [[self ocsFolder] fetchAclMatchingQualifier: qualifier];
283 - (NSArray *) _fetchAclsForUser: (NSString *) uid
284 forObjectAtPath: (NSString *) objectPath
286 EOQualifier *qualifier;
288 NSMutableArray *acls;
291 qs = [NSString stringWithFormat: @"(c_object = '/%@') AND (c_uid = '%@')",
293 qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
294 records = [[self ocsFolder] fetchAclMatchingQualifier: qualifier];
296 acls = [NSMutableArray array];
297 if ([records count] > 0)
299 [acls addObject: SOGoRole_AuthorizedSubscriber];
300 [acls addObjectsFromArray: [records valueForKey: @"c_role"]];
306 - (void) _cacheRoles: (NSArray *) roles
307 forUser: (NSString *) uid
308 forObjectAtPath: (NSString *) objectPath
310 NSMutableDictionary *aclsForObject;
312 aclsForObject = [aclCache objectForKey: objectPath];
315 aclsForObject = [NSMutableDictionary dictionary];
316 [aclCache setObject: aclsForObject
320 [aclsForObject setObject: roles forKey: uid];
322 [aclsForObject removeObjectForKey: uid];
325 - (NSArray *) aclsForUser: (NSString *) uid
326 forObjectAtPath: (NSArray *) objectPathArray
329 NSString *objectPath;
330 NSDictionary *aclsForObject;
332 objectPath = [objectPathArray componentsJoinedByString: @"/"];
333 aclsForObject = [aclCache objectForKey: objectPath];
335 acls = [aclsForObject objectForKey: uid];
340 acls = [self _fetchAclsForUser: uid forObjectAtPath: objectPath];
341 [self _cacheRoles: acls forUser: uid forObjectAtPath: objectPath];
344 if (!([acls count] || [uid isEqualToString: defaultUser]))
345 acls = [self aclsForUser: defaultUser forObjectAtPath: objectPathArray];
350 - (void) removeAclsForUsers: (NSArray *) users
351 forObjectAtPath: (NSArray *) objectPathArray
353 EOQualifier *qualifier;
354 NSString *uids, *qs, *objectPath;
355 NSMutableDictionary *aclsForObject;
357 if ([users count] > 0)
359 objectPath = [objectPathArray componentsJoinedByString: @"/"];
360 aclsForObject = [aclCache objectForKey: objectPath];
362 [aclsForObject removeObjectsForKeys: users];
363 uids = [users componentsJoinedByString: @"') OR (c_uid = '"];
365 stringWithFormat: @"(c_object = '/%@') AND ((c_uid = '%@'))",
367 qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
368 [[self ocsFolder] deleteAclMatchingQualifier: qualifier];
372 - (void) setRoles: (NSArray *) roles
373 forUser: (NSString *) uid
374 forObjectAtPath: (NSArray *) objectPathArray
376 EOAdaptorChannel *channel;
378 NSEnumerator *userRoles;
379 NSString *SQL, *currentRole, *objectPath;
381 [self removeAclsForUsers: [NSArray arrayWithObject: uid]
382 forObjectAtPath: objectPathArray];
383 objectPath = [objectPathArray componentsJoinedByString: @"/"];
384 [self _cacheRoles: roles forUser: uid forObjectAtPath: objectPath];
386 folder = [self ocsFolder];
387 channel = [folder acquireAclChannel];
388 userRoles = [roles objectEnumerator];
389 currentRole = [userRoles nextObject];
392 if (![currentRole isEqualToString: SOGoRole_AuthorizedSubscriber])
394 SQL = [NSString stringWithFormat: @"INSERT INTO %@"
395 @" (c_object, c_uid, c_role)"
396 @" VALUES ('/%@', '%@', '%@')",
397 [folder aclTableName],
398 objectPath, uid, currentRole];
399 [channel evaluateExpressionX: SQL];
401 currentRole = [userRoles nextObject];
404 [folder releaseChannel: channel];
408 - (NSArray *) defaultAclRoles
410 #warning this should be changed to something useful
416 return [self aclsForObjectAtPath: [self pathArrayToSoObject]];
419 - (NSArray *) aclsForUser: (NSString *) uid
421 return [self aclsForUser: uid
422 forObjectAtPath: [self pathArrayToSoObject]];
425 - (void) setRoles: (NSArray *) roles
426 forUser: (NSString *) uid
428 return [self setRoles: roles
430 forObjectAtPath: [self pathArrayToSoObject]];
433 - (void) removeAclsForUsers: (NSArray *) users
435 return [self removeAclsForUsers: users
436 forObjectAtPath: [self pathArrayToSoObject]];
441 - (BOOL) davIsCollection
443 return [self isFolderish];
448 - (NSString *)outlookFolderClass {
454 - (void)appendAttributesToDescription:(NSMutableString *)_ms {
455 [super appendAttributesToDescription:_ms];
457 [_ms appendFormat:@" ocs=%@", [self ocsPath]];
460 - (NSString *)loggingPrefix {
461 return [NSString stringWithFormat:@"<0x%08X[%@]:%@>",
462 self, NSStringFromClass([self class]),
463 [self nameInContainer]];
466 @end /* SOGoFolder */