diff --git a/ChangeLog b/ChangeLog index 4c5820ced..492e770c2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2006-08-09 Wolfgang Sourdeau + * SoObjects/Contacts/SOGoContactLDAPFolder.[hm]: new class that + returns entries an LDAP server. Conforms to the new + SOGOContactFolder protocol. + * SoObjects/Contacts/SOGoContactLDAPEntry.[hm]: new class that returns a vCard based on contact entries from an LDAP server. Conforms to the new SOGOContactObject protocol. diff --git a/SoObjects/Contacts/SOGoContactLDAPFolder.h b/SoObjects/Contacts/SOGoContactLDAPFolder.h new file mode 100644 index 000000000..ff29ea1af --- /dev/null +++ b/SoObjects/Contacts/SOGoContactLDAPFolder.h @@ -0,0 +1,56 @@ +/* SOGoContactLDAPFolder.h - this file is part of SOGo + * + * Copyright (C) 2006 Inverse groupe conseil + * + * 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. + */ + +#ifndef SOGOCONTACTLDAPFOLDER_H +#define SOGOCONTACTLDAPFOLDER_H + +#import +#import "SOGoContactFolder.h" + +@class NSString, NSArray; +@class NGLdapConnection; + +@interface SOGoContactLDAPFolder : SOGoObject +{ + NGLdapConnection *connection; + NSString *contactIdentifier; + NSString *rootDN; + NSString *displayName; + NSMutableDictionary *entries; +} + +- (NGLdapConnection *) LDAPconnection; + +- (void) setDisplayName: (NSString *) aDisplayName; +- (NSString *) displayName; + +- (void) LDAPSetHostname: (NSString *) aHostname + setPort: (int) aPort + setBindDN: (NSString *) aBindDN + setBindPW: (NSString *) aBindPW + setContactIdentifier: (NSString *) aCI + setRootDN: (NSString *) aRootDN; + +@end + + +#endif /* SOGOCONTACTLDAPFOLDER_H */ diff --git a/SoObjects/Contacts/SOGoContactLDAPFolder.m b/SoObjects/Contacts/SOGoContactLDAPFolder.m new file mode 100644 index 000000000..cf2e0169e --- /dev/null +++ b/SoObjects/Contacts/SOGoContactLDAPFolder.m @@ -0,0 +1,375 @@ +/* SOGoContactLDAPFolder.m - this file is part of SOGo + * + * Copyright (C) 2006 Inverse groupe conseil + * + * 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 "common.h" + +#import "NGLdapEntry+Contact.h" + +#import "SOGoContactLDAPEntry.h" +#import "SOGoContactLDAPFolder.h" + +@class WOContext; + +@implementation SOGoContactLDAPFolder + ++ (id ) contactFolderWithName: (NSString *) aName + andDisplayName: (NSString *) aDisplayName + inContainer: (SOGoObject *) aContainer +{ + SOGoContactLDAPFolder *folder; + + folder = [[self alloc] initWithName: aName + andDisplayName: aDisplayName + inContainer: aContainer]; + [folder autorelease]; + + return folder; +} + +- (id) init +{ + if ((self = [super init])) + { + connection = nil; + contactIdentifier = nil; + rootDN = nil; + entries = nil; + } + + return self; +} + +- (id ) initWithName: (NSString *) aName + andDisplayName: (NSString *) aDisplayName + inContainer: (SOGoObject *) aContainer +{ + if ((self = [self initWithName: aName + inContainer: aContainer])) + [self setDisplayName: aDisplayName]; + + return self; +} + +- (void) dealloc +{ + if (connection) + { + if ([connection isBound]) + [connection unbind]; + [connection release]; + } + if (contactIdentifier) + [contactIdentifier release]; + if (rootDN) + [rootDN release]; + if (entries) + [entries release]; + [super dealloc]; +} + +- (void) setDisplayName: (NSString *) aDisplayName +{ + if (displayName) + [displayName release]; + displayName = aDisplayName; + if (displayName) + [displayName retain]; +} + +- (NSString *) displayName +{ + return displayName; +} + +- (void) LDAPSetHostname: (NSString *) aHostname + setPort: (int) aPort + setBindDN: (NSString *) aBindDN + setBindPW: (NSString *) aBindPW + setContactIdentifier: (NSString *) aCI + setRootDN: (NSString *) aRootDN; +{ + connection = [[NGLdapConnection alloc] initWithHostName: aHostname + port: aPort]; + [connection bindWithMethod: nil + binddn: aBindDN + credentials: aBindPW]; + + if (rootDN) + [rootDN release]; + rootDN = [aRootDN copy]; + if (contactIdentifier) + [contactIdentifier release]; + contactIdentifier = [aCI copy]; +} + +- (NGLdapConnection *) LDAPconnection +{ + return connection; +} + +- (NGLdapAttribute *) _attrWithName: (NSString *) aName +{ + return [[[NGLdapAttribute alloc] initWithAttributeName: aName] autorelease]; +} + +- (NSArray *) _searchAttributes +{ + return [NSArray arrayWithObjects: + @"title", + @"company", + @"o", + @"modifytimestamp", + @"mozillaHomeState", + @"mozillaHomeUrl", + @"homeurl", + @"st", + @"region", + @"mozillaCustom2", + @"custom2", + @"mozillaHomeCountryName", + @"description", + @"notes", + @"department", + @"departmentnumber", + @"ou", + @"orgunit", + @"mobile", + @"cellphone", + @"carphone", + @"mozillaCustom1", + @"custom1", + @"mozillaNickname", + @"xmozillanickname", + @"mozillaWorkUrl", + @"workurl", + @"fax", + @"facsimileTelephoneNumber", + @"telephoneNumber", + @"mozillaHomeStreet", + @"mozillaSecondEmail", + @"xmozillasecondemail", + @"mozillaCustom4", + @"custom4", + @"nsAIMid", + @"nscpaimscreenname", + @"street", + @"streetaddress", + @"postOfficeBox", + @"homePhone", + @"cn", + contactIdentifier, + @"commonname", + @"givenName", + @"mozillaHomePostalCode", + @"mozillaHomeLocalityName", + @"mozillaWorkStreet2", + @"mozillaUseHtmlMail", + @"xmozillausehtmlmail", + @"mozillaHomeStreet2", + @"postalCode", + @"zip", + @"c", + @"countryname", + @"pager", + @"pagerphone", + @"mail", + @"sn", + @"surname", + @"mozillaCustom3", + @"custom3", + @"l", + @"locality", + @"birthyear", + @"serialNumber", + nil]; +} + +- (void) _loadEntries: (NSString *) entryId +{ + NSEnumerator *contacts; + NGLdapEntry *entry; + NSString *key; + + if (!entries) + entries = [NSMutableDictionary new]; + + if (entryId) + { + if (![entries objectForKey: entryId]) + { + entry + = [connection entryAtDN: + [NSString stringWithFormat: @"%@=%@,%@", + contactIdentifier, entryId, rootDN] + attributes: [self _searchAttributes]]; + if (entry) + [entries setObject: entry forKey: entryId]; + } + } + else + { + contacts = [connection deepSearchAtBaseDN: rootDN + qualifier: nil + attributes: [self _searchAttributes]]; + if (contacts) + { + entry = [contacts nextObject]; + while (entry) + { + key = [[entry attributeWithName: contactIdentifier] + stringValueAtIndex: 0]; + if (key && ![entries objectForKey: key]) + [entries setObject: entry forKey: key]; + entry = [contacts nextObject]; + } + } + } +} + +- (id) lookupName: (NSString *) name + inContext: (WOContext *) context + acquire: (BOOL) acquire +{ + id obj; + NGLdapEntry *entry; + + NSLog (@"looking up name '%@'...", name); + + /* first check attributes directly bound to the application */ + obj = [super lookupName: name inContext: context acquire: NO]; + if (!obj) + { + [self _loadEntries: name]; + entry = [entries objectForKey: name]; + obj = ((entry) + ? [SOGoContactLDAPEntry contactEntryWithName: name + withLDAPEntry: entry + inContainer: self] + : [NSException exceptionWithHTTPStatus: 404]); + } + + return obj; +} + +- (NSArray *) toOneRelationshipKeys +{ + [self _loadEntries: nil]; + + return [entries allKeys]; +} + +- (id ) lookupContactWithId: (NSString *) recordId +{ + NGLdapEntry *entry; + + [self _loadEntries: recordId]; + + entry = [entries objectForKey: recordId]; + return ((entry) + ? [SOGoContactLDAPEntry contactEntryWithName: recordId + withLDAPEntry: entry + inContainer: self] + : nil); +} + +- (EOQualifier *) _qualifierForFilter: (NSString *) filter +{ + NSString *qs; + EOQualifier *qualifier; + + if (filter && [filter length] > 0) + { + qs = [NSString stringWithFormat: + @"(cn='*%@*')" + @"OR (mail='*%@*')" + @"OR (telephoneNumber='*%@*')", + filter, filter, filter]; + qualifier = [EOQualifier qualifierWithQualifierFormat: qs]; + } + else + qualifier = nil; + + return qualifier; +} + +- (NSArray *) lookupContactsWithFilter: (NSString *) filter + sortBy: (NSString *) sortKey + ordering: (NSComparisonResult) sortOrdering +{ + NSMutableArray *records; + NSArray *result; + NGLdapEntry *entry; + NSEnumerator *contacts; + EOSortOrdering *ordering; + + result = nil; + + if (filter && [filter length] > 0) + { + NSLog (@"%@: fetching records matching '*%@*', sorted by '%@'" + @" in order %d", + self, filter, sortKey, sortOrdering); + + records = [NSMutableArray new]; + [records autorelease]; + + contacts = [connection deepSearchAtBaseDN: rootDN + qualifier: [self _qualifierForFilter: filter] + attributes: folderListingFields]; + entry = [contacts nextObject]; + while (entry) + { + [records addObject: [entry asDictionaryWithAttributeNames: nil + andCName: @"cn"]]; + entry = [contacts nextObject]; + } + + ordering + = [EOSortOrdering sortOrderingWithKey: sortKey + selector: ((sortOrdering == NSOrderedDescending) + ? EOCompareCaseInsensitiveDescending + : EOCompareCaseInsensitiveAscending)]; + result + = [records sortedArrayUsingKeyOrderArray: + [NSArray arrayWithObject: ordering]]; + } + + //[self debugWithFormat:@"fetched %i records.", [records count]]; + return result; +} + +@end