02111-1307, USA.
*/
-#import <unistd.h>
-#import <stdlib.h>
-
#import <Foundation/NSArray.h>
+#import <Foundation/NSDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
+#import <Foundation/NSKeyValueCoding.h>
#import <Foundation/NSURL.h>
+#import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/SoObject.h>
+#import <NGObjWeb/SoObject+SoDAV.h>
+#import <NGObjWeb/SoSelectorInvocation.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGExtensions/NSNull+misc.h>
#import <NGExtensions/NSObject+Logs.h>
#import <EOControl/EOQualifier.h>
#import <GDLAccess/EOAdaptorChannel.h>
+#import <GDLContentStore/GCSChannelManager.h>
#import <GDLContentStore/GCSFolderManager.h>
#import <GDLContentStore/GCSFolder.h>
#import <GDLContentStore/GCSFolderType.h>
+#import <GDLContentStore/NSURL+GCS.h>
#import <SaxObjC/XMLNamespaces.h>
+#import "NSArray+Utilities.h"
+#import "NSString+Utilities.h"
+
#import "SOGoPermissions.h"
#import "SOGoUser.h"
NSStringFromClass([self superclass]), [super version]);
}
-+ (NSString *) globallyUniqueObjectId
++ (id) folderWithSubscriptionReference: (NSString *) reference
+ inContainer: (id) aContainer
{
- /*
- 4C08AE1A-A808-11D8-AC5A-000393BBAFF6
- SOGo-Web-28273-18283-288182
- printf( "%x", *(int *) &f);
- */
- static int pid = 0;
- static int sequence = 0;
- static float rndm = 0;
- float f;
-
- if (pid == 0)
- { /* break if we fork ;-) */
- pid = getpid();
- rndm = random();
- }
- sequence++;
- f = [[NSDate date] timeIntervalSince1970];
- return [NSString stringWithFormat:@"%0X-%0X-%0X-%0X",
- pid, *(int *)&f, sequence++, random];
+ id newFolder;
+ NSArray *elements, *pathElements;
+ NSString *ocsPath, *objectPath, *owner, *ocsName, *folderName;
+
+ elements = [reference componentsSeparatedByString: @":"];
+ owner = [elements objectAtIndex: 0];
+ objectPath = [elements objectAtIndex: 1];
+ pathElements = [objectPath componentsSeparatedByString: @"/"];
+ if ([pathElements count] > 1)
+ ocsName = [pathElements objectAtIndex: 1];
+ else
+ ocsName = @"personal";
+
+ ocsPath = [NSString stringWithFormat: @"/Users/%@/%@/%@",
+ owner, [pathElements objectAtIndex: 0], ocsName];
+ folderName = [NSString stringWithFormat: @"%@_%@", owner, ocsName];
+ newFolder = [[self alloc] initWithName: folderName
+ inContainer: aContainer];
+ [newFolder setOCSPath: ocsPath];
+ [newFolder setOwner: owner];
+
+ return newFolder;
}
- (id) init
{
if ((self = [super init]))
{
+ displayName = nil;
ocsPath = nil;
ocsFolder = nil;
aclCache = [NSMutableDictionary new];
[ocsFolder release];
[ocsPath release];
[aclCache release];
+ [displayName release];
[super dealloc];
}
- (void) setOCSPath: (NSString *) _path
{
- if ([ocsPath isEqualToString:_path])
- return;
-
- if (ocsPath)
- [self warnWithFormat:@"GCS path is already set! '%@'", _path];
-
- ASSIGNCOPY(ocsPath, _path);
+ if (![ocsPath isEqualToString:_path])
+ {
+ if (ocsPath)
+ [self warnWithFormat: @"GCS path is already set! '%@'", _path];
+ ASSIGN (ocsPath, _path);
+ }
}
- (NSString *) ocsPath
static GCSFolderManager *folderManager = nil;
if (!folderManager)
- {
- folderManager = [GCSFolderManager defaultFolderManager];
- [folderManager setFolderNamePrefix: @"SOGo"];
- }
+ folderManager = [GCSFolderManager defaultFolderManager];
return folderManager;
}
- (BOOL) folderIsMandatory
{
- [self subclassResponsibility: _cmd];
+ return [nameInContainer isEqualToString: @"personal"];
+}
+
+- (void) _setDisplayNameFromRow: (NSDictionary *) row
+{
+ NSString *currentLogin, *ownerLogin;
+ NSDictionary *ownerIdentity;
+
+ displayName
+ = [NSMutableString stringWithString: [row objectForKey: @"c_foldername"]];
+ currentLogin = [[context activeUser] login];
+ ownerLogin = [self ownerInContext: context];
+ if (![currentLogin isEqualToString: ownerLogin])
+ {
+ ownerIdentity = [[SOGoUser userWithLogin: ownerLogin roles: nil]
+ primaryIdentity];
+ [displayName appendFormat: @" (%@ <%@>)",
+ [ownerIdentity objectForKey: @"fullName"],
+ [ownerIdentity objectForKey: @"email"]];
+ }
+}
+
+- (void) _fetchDisplayName
+{
+ GCSChannelManager *cm;
+ EOAdaptorChannel *fc;
+ NSURL *folderLocation;
+ NSString *sql;
+ NSArray *attrs;
+ NSDictionary *row;
+
+ cm = [GCSChannelManager defaultChannelManager];
+ folderLocation
+ = [[GCSFolderManager defaultFolderManager] folderInfoLocation];
+ fc = [cm acquireOpenChannelForURL: folderLocation];
+ if (fc)
+ {
+ sql
+ = [NSString stringWithFormat: (@"SELECT c_foldername FROM %@"
+ @" WHERE c_path = '%@'"),
+ [folderLocation gcsTableName], ocsPath];
+ [fc evaluateExpressionX: sql];
+ attrs = [fc describeResults: NO];
+ row = [fc fetchAttributes: attrs withZone: NULL];
+ if (row)
+ [self _setDisplayNameFromRow: row];
+ [fc cancelFetch];
+ [cm releaseChannel: fc];
+ }
+}
+
+- (void) setDisplayName: (NSString *) newDisplayName
+{
+ ASSIGN (displayName, newDisplayName);
+}
+
+- (NSString *) displayName
+{
+ if (!displayName)
+ [self _fetchDisplayName];
+
+ return displayName;
+}
- return NO;
+- (NSString *) davDisplayName
+{
+ return [self displayName];
}
- (GCSFolder *) ocsFolder
{
NSException *result;
+// [self dieHard];
result = [[self folderManager] createFolderOfType: [self folderType]
+ withName: displayName
atPath: ocsPath];
return (result == nil);
- (NSException *) delete
{
- return [[self folderManager] deleteFolderAtPath: ocsPath];
+ NSException *error;
+
+ if ([nameInContainer isEqualToString: @"personal"])
+ error = [NSException exceptionWithHTTPStatus: 403
+ reason: @"folder 'personal' cannot be deleted"];
+ else
+ error = [[self folderManager] deleteFolderAtPath: ocsPath];
+
+ return error;
+}
+
+- (void) renameTo: (NSString *) newName
+{
+ GCSChannelManager *cm;
+ EOAdaptorChannel *fc;
+ NSURL *folderLocation;
+ NSString *sql;
+
+ [displayName release];
+ displayName = nil;
+
+ cm = [GCSChannelManager defaultChannelManager];
+ folderLocation
+ = [[GCSFolderManager defaultFolderManager] folderInfoLocation];
+ fc = [cm acquireOpenChannelForURL: folderLocation];
+ if (fc)
+ {
+ sql
+ = [NSString stringWithFormat: (@"UPDATE %@ SET c_foldername = '%@'"
+ @" WHERE c_path = '%@'"),
+ [folderLocation gcsTableName], newName, ocsPath];
+ [fc evaluateExpressionX: sql];
+ [cm releaseChannel: fc];
+// sql = [sql stringByAppendingFormat:@" WHERE %@ = '%@'",
+// uidColumnName, [self uid]];
+ }
}
- (NSArray *) fetchContentObjectNames
}
if ([records isKindOfClass: [NSException class]])
return records;
- return [records valueForKey: @"c_name"];
+ return [records objectsForKey: @"c_name"];
}
- (BOOL) nameExistsInFolder: (NSString *) objectName
if ([self respondsToSelector: @selector (groupDavResourceType)])
{
- groupDavCollection = [NSArray arrayWithObjects: [self groupDavResourceType],
- XMLNS_GROUPDAV, nil];
- rType = [NSArray arrayWithObjects: @"collection", groupDavCollection, nil];
+ groupDavCollection
+ = [NSArray arrayWithObjects: [self groupDavResourceType],
+ XMLNS_GROUPDAV, nil];
+ rType = [NSArray arrayWithObjects: @"collection", groupDavCollection,
+ nil];
}
else
rType = [NSArray arrayWithObject: @"collection"];
name = [names objectAtIndex: i];
r = [name rangeOfString: @"."];
if (r.length == 0)
- name = [[name stringByAppendingString:@"."] stringByAppendingString: ext];
- [ma addObject:name];
+ name = [NSMutableString stringWithFormat: @"%@.%@", name, ext];
+ [ma addObject: name];
}
names = ma;
/* acls */
- (NSArray *) aclUsers
{
- return [self aclUsersForObjectAtPath: [self pathArrayToSoObject]];
+ return [self aclUsersForObjectAtPath: [self pathArrayToSOGoObject]];
}
- (NSArray *) aclsForUser: (NSString *) uid
acls = [NSMutableArray array];
ownAcls = [self aclsForUser: uid
- forObjectAtPath: [self pathArrayToSoObject]];
+ forObjectAtPath: [self pathArrayToSOGoObject]];
[acls addObjectsFromArray: ownAcls];
if ([container respondsToSelector: @selector (aclsForUser:)])
{
{
return [self setRoles: roles
forUser: uid
- forObjectAtPath: [self pathArrayToSoObject]];
+ forObjectAtPath: [self pathArrayToSOGoObject]];
}
- (void) removeAclsForUsers: (NSArray *) users
{
return [self removeAclsForUsers: users
- forObjectAtPath: [self pathArrayToSoObject]];
+ forObjectAtPath: [self pathArrayToSOGoObject]];
}
- (NSString *) defaultUserID
return [[self davURL] absoluteString];
}
+- (id) lookupName: (NSString *) lookupName
+ inContext: (id) localContext
+ acquire: (BOOL) acquire
+{
+ id obj;
+ NSArray *davNamespaces;
+ NSDictionary *davInvocation;
+ NSString *objcMethod;
+
+ obj = [super lookupName: lookupName inContext: localContext
+ acquire: acquire];
+ if (!obj)
+ {
+ davNamespaces = [self davNamespaces];
+ if ([davNamespaces count] > 0)
+ {
+ davInvocation = [lookupName asDavInvocation];
+ if (davInvocation
+ && [davNamespaces
+ containsObject: [davInvocation objectForKey: @"ns"]])
+ {
+ objcMethod = [[davInvocation objectForKey: @"method"]
+ davMethodToObjC];
+ obj = [[SoSelectorInvocation alloc]
+ initWithSelectorNamed:
+ [NSString stringWithFormat: @"%@:", objcMethod]
+ addContextParameter: YES];
+ [obj autorelease];
+ }
+ }
+ }
+
+ return obj;
+}
+
/* WebDAV */
+- (NSArray *) davNamespaces
+{
+ return nil;
+}
+
- (BOOL) davIsCollection
{
return [self isFolderish];
/* folder type */
-- (NSString *)outlookFolderClass {
+- (NSString *) outlookFolderClass
+{
+ [self subclassResponsibility: _cmd];
+
return nil;
}
/* description */
-- (void)appendAttributesToDescription:(NSMutableString *)_ms {
+- (void) appendAttributesToDescription: (NSMutableString *) _ms
+{
[super appendAttributesToDescription:_ms];
[_ms appendFormat:@" ocs=%@", [self ocsPath]];
}
-- (NSString *)loggingPrefix {
+- (NSString *) loggingPrefix
+{
return [NSString stringWithFormat:@"<0x%08X[%@]:%@>",
self, NSStringFromClass([self class]),
[self nameInContainer]];