/* SOGoContactSourceFolder.m - this file is part of SOGo * * Copyright (C) 2006-2009 Inverse inc. * * Author: Wolfgang Sourdeau * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import "SOGoContactLDIFEntry.h" #import "SOGoContactSourceFolder.h" @class WOContext; @implementation SOGoContactSourceFolder #warning this should be unified within SOGoFolder - (void) appendObject: (NSDictionary *) object withBaseURL: (NSString *) baseURL toREPORTResponse: (WOResponse *) r { SOGoContactLDIFEntry *component; NSString *name, *etagLine, *contactString; name = [object objectForKey: @"c_name"]; if ([name length]) { component = [self lookupName: name inContext: context acquire: NO]; if ([component isKindOfClass: [NSException class]]) { [self logWithFormat: @"Object with name '%@' not found. You likely have a LDAP configuration issue.", name]; return; } [r appendContentString: @" \r\n"]; [r appendContentString: @" "]; [r appendContentString: baseURL]; if (![baseURL hasSuffix: @"/"]) [r appendContentString: @"/"]; [r appendContentString: name]; [r appendContentString: @"\r\n"]; [r appendContentString: @" \r\n"]; [r appendContentString: @" \r\n"]; etagLine = [NSString stringWithFormat: @" %@\r\n", [component davEntityTag]]; [r appendContentString: etagLine]; [r appendContentString: @" \r\n"]; [r appendContentString: @" HTTP/1.1 200 OK\r\n"]; [r appendContentString: @" \r\n"]; [r appendContentString: @" "]; contactString = [[component contentAsString] stringByEscapingXMLString]; [r appendContentString: contactString]; [r appendContentString: @"\r\n"]; [r appendContentString: @" \r\n"]; } } + (id) folderWithName: (NSString *) aName andDisplayName: (NSString *) aDisplayName inContainer: (id) aContainer { id folder; folder = [[self alloc] initWithName: aName andDisplayName: aDisplayName inContainer: aContainer]; [folder autorelease]; return folder; } - (id) init { if ((self = [super init])) { entries = nil; source = nil; } return self; } - (id) initWithName: (NSString *) newName andDisplayName: (NSString *) newDisplayName inContainer: (id) newContainer { if ((self = [self initWithName: newName inContainer: newContainer])) { if (![newDisplayName length]) newDisplayName = newName; ASSIGN (displayName, newDisplayName); } return self; } - (void) dealloc { [entries release]; [source release]; [super dealloc]; } - (void) setSource: (id) newSource { ASSIGN (source, newSource); } - (NSString *) groupDavResourceType { return @"vcard-collection"; } - (NSArray *) davResourceType { NSMutableArray *resourceType; NSArray *cardDavCollection; cardDavCollection = [NSArray arrayWithObjects: @"addressbook", @"urn:ietf:params:xml:ns:carddav", nil]; resourceType = [NSMutableArray arrayWithArray: [super davResourceType]]; [resourceType addObject: cardDavCollection]; return resourceType; } - (id) lookupName: (NSString *) objectName inContext: (WOContext *) lookupContext acquire: (BOOL) acquire { NSDictionary *ldifEntry; id obj; /* first check attributes directly bound to the application */ obj = [super lookupName: objectName inContext: lookupContext acquire: NO]; if (!obj) { ldifEntry = [source lookupContactEntry: objectName]; if (ldifEntry) obj = [SOGoContactLDIFEntry contactEntryWithName: objectName withLDIFEntry: ldifEntry inContainer: self]; else obj = [NSException exceptionWithHTTPStatus: 404]; } return obj; } - (NSArray *) toOneRelationshipKeys { return [source 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: @"c_cn"]; data = [oldRecord objectForKey: @"mail"]; if (!data) data = @""; [newRecord setObject: data forKey: @"c_mail"]; data = [oldRecord objectForKey: @"nsaimid"]; if (![data length]) data = [oldRecord objectForKey: @"nscpaimscreenname"]; if (![data length]) data = @""; [newRecord setObject: data forKey: @"c_screenname"]; data = [oldRecord objectForKey: @"o"]; if (!data) data = @""; [newRecord setObject: data forKey: @"c_o"]; 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: @"c_telephonenumber"]; // Custom attribute for group-lookups. See LDAPSource.m where // it's set. data = [oldRecord objectForKey: @"isGroup"]; if (data) [newRecord setObject: data forKey: @"isGroup"]; data = [oldRecord objectForKey: @"c_info"]; if ([data length] > 0) [newRecord setObject: data forKey: @"contactInfo"]; [newRecords addObject: newRecord]; oldRecord = [oldRecords nextObject]; } return newRecords; } - (NSArray *) lookupContactsWithFilter: (NSString *) filter sortBy: (NSString *) sortKey ordering: (NSComparisonResult) sortOrdering { NSArray *records, *result; EOSortOrdering *ordering; result = nil; if (filter && [filter length] > 0) { records = [self _flattenedRecords: [source fetchContactsMatching: filter]]; ordering = [EOSortOrdering sortOrderingWithKey: sortKey selector: ((sortOrdering == NSOrderedDescending) ? EOCompareCaseInsensitiveDescending : EOCompareCaseInsensitiveAscending)]; result = [records sortedArrayUsingKeyOrderArray: [NSArray arrayWithObject: ordering]]; } return result; } - (NSString *) davDisplayName { return displayName; } - (BOOL) isFolderish { return YES; } /* folder type */ - (NSString *) folderType { return @"Contact"; } - (NSString *) outlookFolderClass { return @"IPF.Contact"; } /* 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"; } - (NSArray *) subscriptionRoles { return [NSArray arrayWithObject: SoRole_Authenticated]; } /* TODO: this might change one day when we support LDAP acls */ - (NSArray *) aclsForUser: (NSString *) uid { return nil; } @end