From 4cfb2b0ccd91becfa7816660b70e419ae9019452 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Thu, 19 Mar 2009 19:07:39 +0000 Subject: [PATCH] Monotone-Parent: b11b40d1a73231b76eb4bb1ce04046646f40d52f Monotone-Revision: 2c52bc9062d09379395dae99d6c685de6c8157c9 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2009-03-19T19:07:39 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 8 +++ SoObjects/SOGo/SOGoUserFolder.m | 103 ++++++++++++++++++++++++++++---- 2 files changed, 101 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index e0cf2a9e1..c7e6b491a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2009-03-19 Wolfgang Sourdeau + * SoObjects/SOGo/SOGoUserFolder.m ([SOGoUserFolder + -foldersOfType:folderTypeforUID:uid]): now also returns the owner + of the folders in the folder dictionary. + ([SOGoUserFolder -davCollectionQuery:queryContext]): works again + for multiple users if the DAV:owner property is specified in the + query. The response is formatted in a way that is compatible with + both the 0.8x and 0.9x SOGo extensions. + * SoObjects/SOGo/SOGoUser.m ([SOGoUser -homeFolderInContext:context]): no longer put the home folder in cache, since it uses an context that is freed and invalidated diff --git a/SoObjects/SOGo/SOGoUserFolder.m b/SoObjects/SOGo/SOGoUserFolder.m index 4f4600ea6..115d18baa 100644 --- a/SoObjects/SOGo/SOGoUserFolder.m +++ b/SoObjects/SOGo/SOGoUserFolder.m @@ -166,6 +166,7 @@ static NSString *LDAPContactInfoAttribute = nil; [currentDictionary setObject: [currentFolder displayName] forKey: @"displayName"]; [currentDictionary setObject: folderName forKey: @"name"]; + [currentDictionary setObject: folderOwner forKey: @"owner"]; [currentDictionary setObject: [currentFolder folderType] forKey: @"type"]; [folders addObject: currentDictionary]; @@ -244,15 +245,17 @@ static NSString *LDAPContactInfoAttribute = nil; NSDictionary *currentFolder; NSString *baseHREF, *data; NSEnumerator *foldersEnum; + SOGoUser *ownerUser; - baseHREF = [[self davURL] absoluteString]; + baseHREF = [[container davURL] absoluteString]; if ([baseHREF hasSuffix: @"/"]) baseHREF = [baseHREF substringToIndex: [baseHREF length] - 1]; foldersEnum = [folders objectEnumerator]; while ((currentFolder = [foldersEnum nextObject])) { [r appendContentString: @""]; - data = [NSString stringWithFormat: @"%@%@/", baseHREF, + data = [NSString stringWithFormat: @"%@/%@%@/", baseHREF, + [currentFolder objectForKey: @"owner"], [currentFolder objectForKey: @"name"]]; [r appendContentString: data]; [r appendContentString: @""]; @@ -260,7 +263,89 @@ static NSString *LDAPContactInfoAttribute = nil; [r appendContentString: @""]; data = [currentFolder objectForKey: @"displayName"]; [r appendContentString: [data stringByEscapingXMLString]]; - [r appendContentString: @""]; + [r appendContentString: @""]; + + /* Remove this once extensions 0.8x are no longer used */ + data = [NSString stringWithFormat: @"%@/%@", baseHREF, + [currentFolder objectForKey: @"owner"]]; + [r appendContentString: data]; + + [r appendContentString: @""]; + + ownerUser = [SOGoUser userWithLogin: [currentFolder objectForKey: @"owner"] + roles: nil]; + data = [ownerUser cn]; + [r appendContentString: [data stringByEscapingXMLString]]; + [r appendContentString: @""]; + + [r appendContentString: @""]; + data = [currentFolder objectForKey: @"displayName"]; + [r appendContentString: [data stringByEscapingXMLString]]; + [r appendContentString: @""]; + /* end of temporary compatibility hack */ + + [r appendContentString: @""]; + } +} + +/* This method takes a user principal and converts it to a potential username. + The old form using "dav/users/XXX" is also supported. */ +- (NSString *) _userFromDAVuser: (NSString *) davOwnerMatch +{ + NSRange match; + NSString *user; + + match = [davOwnerMatch rangeOfString: @"/SOGo/dav/users/"]; + if (match.location == NSNotFound) + match = [davOwnerMatch rangeOfString: @"/SOGo/dav/"]; + if (match.location != NSNotFound) + { + user = [davOwnerMatch substringFromIndex: NSMaxRange (match)]; + match = [user rangeOfString: @"/"]; + if (match.location != NSNotFound) + user = [user substringToIndex: match.location]; + } + else + user = nil; + + return user; +} + +- (NSArray *) _searchDavOwners: (NSString *) davOwnerMatch +{ + NSArray *users, *owners; + NSString *ownerMatch; + LDAPUserManager *um; + + owners = [NSMutableArray array]; + if (davOwnerMatch) + { + ownerMatch = [self _userFromDAVuser: davOwnerMatch]; + um = [LDAPUserManager sharedUserManager]; + users = [[um fetchUsersMatching: ownerMatch] + sortedArrayUsingSelector: @selector (caseInsensitiveDisplayNameCompare:)]; + owners = [users objectsForKey: @"c_uid" notFoundMarker: nil]; + } + else + owners = [NSArray arrayWithObject: [self ownerInContext: nil]]; + + return owners; +} + +- (void) _appendFoldersOfType: (NSString *) folderType + ofOwnersMatching: (NSString *) ownerMatch + toResponse: (WOResponse *) r +{ + NSString *currentOwner; + NSEnumerator *owners; + NSArray *folders; + + owners = [[self _searchDavOwners: ownerMatch] objectEnumerator]; + while ((currentOwner = [owners nextObject])) + { + folders = [self foldersOfType: folderType + forUID: currentOwner]; + [self _appendFolders: folders toResponse: r]; } } @@ -269,7 +354,6 @@ static NSString *LDAPContactInfoAttribute = nil; WOResponse *r; NSDictionary *filter; id document; - NSArray *folders; r = [context response]; [r setStatus: 207]; @@ -283,9 +367,9 @@ static NSString *LDAPContactInfoAttribute = nil; document = [[context request] contentAsDOMDocument]; filter = [self _parseCollectionFilters: document]; - folders = [self foldersOfType: [filter objectForKey: @"resource-type"] - forUID: [self ownerInContext: nil]]; - [self _appendFolders: folders toResponse: r]; + [self _appendFoldersOfType: [filter objectForKey: @"resource-type"] + ofOwnersMatching: [filter objectForKey: @"owner"] + toResponse: r]; [r appendContentString:@""]; @@ -308,9 +392,8 @@ static NSString *LDAPContactInfoAttribute = nil; // We sort our array - this is pretty useful for the // SOGo Integrator extension, among other things. - users = [[[[um fetchUsersMatching: user] objectEnumerator] allObjects] - sortedArrayUsingSelector: @selector(caseInsensitiveDisplayNameCompare:)]; - + users = [[um fetchUsersMatching: user] + sortedArrayUsingSelector: @selector (caseInsensitiveDisplayNameCompare:)]; for (i = 0; i < [users count]; i++) { currentUser = [users objectAtIndex: i];