#import <Foundation/NSString.h>
#import <NGObjWeb/NSException+HTTP.h>
-#import <NGObjWeb/SoObject.h>
#import <NGObjWeb/WOApplication.h>
#import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WOContext+SoObjects.h>
+#import <NGObjWeb/WOResponse.h>
+#import <NGObjWeb/SoObject.h>
#import <NGObjWeb/SoUser.h>
#import <EOControl/EOSortOrdering.h>
+#import <SaxObjC/XMLNamespaces.h>
#import <SoObjects/SOGo/LDAPSource.h>
+#import <SoObjects/SOGo/NSString+Utilities.h>
#import "SOGoContactLDIFEntry.h"
#import "SOGoContactLDAPFolder.h"
-
-#define folderListingFields [NSArray arrayWithObjects: @"c_name", @"cn", \
- @"displayName", \
- @"streetAddress", \
- @"o", \
- @"sn", @"givenname", @"l", \
- @"mail", @"telephonenumber", \
- @"mailNickname", \
- @"sAMAccountName", \
- @"uid", \
- nil]
+#import <NGExtensions/NSString+misc.h>
+#import <NGObjWeb/WORequest.h>
+#import <NGObjWeb/SoSelectorInvocation.h>
@class WOContext;
@implementation SOGoContactLDAPFolder
-+ (id <SOGoContactFolder>) contactFolderWithName: (NSString *) aName
- andDisplayName: (NSString *) aDisplayName
- inContainer: (SOGoObject *) aContainer
+#warning this should be unified within SOGoFolder
+- (void) appendObject: (NSDictionary *) object
+ withBaseURL: (NSString *) baseURL
+ toREPORTResponse: (WOResponse *) r
{
- SOGoContactLDAPFolder *folder;
+ SOGoContactLDIFEntry *component;
+ NSString *name, *etagLine, *contactString;
+
+ name = [object objectForKey: @"c_name"];
+ component = [self lookupName: name inContext: context acquire: NO];
+
+ [r appendContentString: @" <D:response>\r\n"];
+ [r appendContentString: @" <D:href>"];
+ [r appendContentString: baseURL];
+ if (![baseURL hasSuffix: @"/"])
+ [r appendContentString: @"/"];
+ [r appendContentString: name];
+ [r appendContentString: @"</D:href>\r\n"];
+
+ [r appendContentString: @" <D:propstat>\r\n"];
+ [r appendContentString: @" <D:prop>\r\n"];
+ etagLine = [NSString stringWithFormat: @" <D:getetag>%@</D:getetag>\r\n",
+ [component davEntityTag]];
+ [r appendContentString: etagLine];
+ [r appendContentString: @" </D:prop>\r\n"];
+ [r appendContentString: @" <D:status>HTTP/1.1 200 OK</D:status>\r\n"];
+ [r appendContentString: @" </D:propstat>\r\n"];
+ [r appendContentString: @" <C:addressbook-data>"];
+ contactString = [[component contentAsString] stringByEscapingXMLString];
+ [r appendContentString: contactString];
+ [r appendContentString: @"</C:addressbook-data>\r\n"];
+ [r appendContentString: @" </D:response>\r\n"];
+}
+
++ (id) folderWithName: (NSString *) aName
+ andDisplayName: (NSString *) aDisplayName
+ inContainer: (id) aContainer
+{
+ id folder;
folder = [[self alloc] initWithName: aName
andDisplayName: aDisplayName
{
if ((self = [super init]))
{
- name = nil;
displayName = nil;
- container = nil;
entries = nil;
ldapSource = nil;
}
return self;
}
-- (id <SOGoContactFolder>) initWithName: (NSString *) newName
- andDisplayName: (NSString *) newDisplayName
- inContainer: (SOGoObject *) newContainer
+- (id) initWithName: (NSString *) newName
+ andDisplayName: (NSString *) newDisplayName
+ inContainer: (id) newContainer
{
- self = [self init];
-
- ASSIGN (name, newName);
- ASSIGN (displayName, newDisplayName);
- ASSIGN (container, newContainer);
+ if ((self = [self initWithName: newName
+ inContainer: newContainer]))
+ {
+ ASSIGN (displayName, newDisplayName);
+ }
return self;
}
- (void) dealloc
{
- [name release];
[displayName release];
- [container release];
[entries release];
[ldapSource release];
[super dealloc];
return displayName;
}
-- (NSString *) nameInContainer
+- (NSArray *) davNamespaces
{
- return name;
+ return [NSArray arrayWithObject: @"urn:ietf:params:xml:ns:carddav"];
}
- (id) lookupName: (NSString *) objectName
id obj;
NSDictionary *ldifEntry;
-// NSLog (@"looking up name '%@'...", name);
+ //NSLog (@"looking up name '%@'...", objectName);
/* first check attributes directly bound to the application */
obj = [super lookupName: objectName inContext: lookupContext acquire: NO];
+
if (!obj)
{
ldifEntry = [ldapSource lookupContactEntry: objectName];
obj = ((ldifEntry)
- ? [SOGoContactLDIFEntry contactEntryWithName: name
+ ? [SOGoContactLDIFEntry contactEntryWithName: objectName
withLDIFEntry: ldifEntry
inContainer: self]
: [NSException exceptionWithHTTPStatus: 404]);
return [ldapSource allEntryIDs];
}
+- (NSArray *) _flattenedRecords: (NSArray *) records
+{
+ NSMutableArray *newRecords;
+ NSEnumerator *oldRecords;
+ NSDictionary *oldRecord;
+ NSMutableDictionary *newRecord;
+ NSString *data;
+
+ newRecords = [[NSMutableArray alloc] initWithCapacity: [records count]];
+ [newRecords autorelease];
+
+ oldRecords = [records objectEnumerator];
+ oldRecord = [oldRecords nextObject];
+ while (oldRecord)
+ {
+ newRecord = [NSMutableDictionary new];
+ [newRecord autorelease];
+
+ [newRecord setObject: [oldRecord objectForKey: @"c_uid"]
+ forKey: @"c_uid"];
+ [newRecord setObject: [oldRecord objectForKey: @"c_name"]
+ forKey: @"c_name"];
+
+ data = [oldRecord objectForKey: @"displayName"];
+ if (!data)
+ data = [oldRecord objectForKey: @"c_cn"];
+ if (!data)
+ data = @"";
+ [newRecord setObject: data forKey: @"displayName"];
+
+ data = [oldRecord objectForKey: @"mail"];
+ if (!data)
+ data = @"";
+ [newRecord setObject: data forKey: @"mail"];
+
+ data = [oldRecord objectForKey: @"nsAIMid"];
+ if (![data length])
+ data = [oldRecord objectForKey: @"nscpaimscreenname"];
+ if (![data length])
+ data = @"";
+ [newRecord setObject: data forKey: @"screenName"];
+
+ data = [oldRecord objectForKey: @"o"];
+ if (!data)
+ data = @"";
+ [newRecord setObject: data forKey: @"org"];
+
+ data = [oldRecord objectForKey: @"telephoneNumber"];
+ if (![data length])
+ data = [oldRecord objectForKey: @"cellphone"];
+ if (![data length])
+ data = [oldRecord objectForKey: @"homePhone"];
+ if (![data length])
+ data = @"";
+ [newRecord setObject: data forKey: @"phone"];
+
+ [newRecords addObject: newRecord];
+ oldRecord = [oldRecords nextObject];
+ }
+
+ return newRecords;
+}
+
- (NSArray *) lookupContactsWithFilter: (NSString *) filter
sortBy: (NSString *) sortKey
ordering: (NSComparisonResult) sortOrdering
if (filter && [filter length] > 0)
{
- records = [ldapSource fetchContactsMatching: filter];
+ records = [self _flattenedRecords:
+ [ldapSource fetchContactsMatching: filter]];
ordering
= [EOSortOrdering sortOrderingWithKey: sortKey
selector: ((sortOrdering == NSOrderedDescending)
[NSArray arrayWithObject: ordering]];
}
- //[self debugWithFormat:@"fetched %i records.", [records count]];
return result;
}
-- (NSString *) groupDavResourceType
+- (NSArray *) davResourceType
+{
+ NSArray *rType, *groupDavCollection;
+
+ groupDavCollection = [NSArray arrayWithObjects: @"vcard-collection",
+ XMLNS_GROUPDAV, nil];
+ rType = [NSArray arrayWithObjects: @"collection", groupDavCollection, nil];
+
+ return rType;
+}
+
+- (NSString *) davContentType
{
- return @"vcard-collection";
+ return @"httpd/unix-directory";
+}
+
+- (BOOL) davIsCollection
+{
+ return YES;
+}
+
+- (NSString *) davDisplayName
+{
+ return displayName;
+}
+
+- (BOOL) isFolderish
+{
+ return YES;
+}
+
+/* sorting */
+- (NSComparisonResult) compare: (id) otherFolder
+{
+ NSComparisonResult comparison;
+
+ if ([NSStringFromClass([otherFolder class])
+ isEqualToString: @"SOGoContactGCSFolder"])
+ comparison = NSOrderedDescending;
+ else
+ comparison
+ = [[self displayName]
+ localizedCaseInsensitiveCompare: [otherFolder displayName]];
+
+ return comparison;
}
/* acls */
+- (NSString *) ownerInContext: (WOContext *) noContext
+{
+ return @"nobody";
+}
+
/* TODO: this might change one day when we support LDAP acls */
- (NSArray *) aclsForUser: (NSString *) uid
{