1 /* LDAPSource.m - this file is part of SOGo
3 * Copyright (C) 2007 Inverse groupe conseil
5 * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
7 * This file is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
12 * This file is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 #import <Foundation/NSArray.h>
24 #import <Foundation/NSDictionary.h>
25 #import <Foundation/NSString.h>
27 #import <EOControl/EOControl.h>
28 #import <NGLdap/NGLdapConnection.h>
29 #import <NGLdap/NGLdapAttribute.h>
30 #import <NGLdap/NGLdapEntry.h>
32 #import "LDAPSource.h"
34 static NSArray *commonSearchFields;
38 @implementation LDAPSource
44 if (!commonSearchFields)
46 ud = [NSUserDefaults standardUserDefaults];
47 sizeLimit = [ud integerForKey: @"SOGoLDAPQueryLimit"];
48 timeLimit = [ud integerForKey: @"SOGoLDAPQueryTimeout"];
50 commonSearchFields = [NSArray arrayWithObjects:
63 @"mozillaHomeCountryName",
80 @"facsimileTelephoneNumber",
83 @"mozillaSecondEmail",
84 @"xmozillasecondemail",
96 @"mozillaHomePostalCode",
97 @"mozillaHomeLocalityName",
98 @"mozillaWorkStreet2",
99 @"mozillaUseHtmlMail",
100 @"xmozillausehtmlmail",
101 @"mozillaHomeStreet2",
119 [commonSearchFields retain];
123 + (id) sourceFromUDSource: (NSDictionary *) udSource
127 newSource = [[self alloc] initFromUDSource: udSource];
128 [newSource autorelease];
135 if ((self = [super init]))
143 IDField = @"cn"; /* the first part of a user DN */
148 ldapConnection = nil;
149 searchAttributes = nil;
164 [bindFields release];
165 [ldapConnection release];
169 - (id) initFromUDSource: (NSDictionary *) udSource
173 [self setBindDN: [udSource objectForKey: @"bindDN"]
174 hostname: [udSource objectForKey: @"hostname"]
175 port: [udSource objectForKey: @"port"]
176 andPassword: [udSource objectForKey: @"bindPassword"]];
177 [self setBaseDN: [udSource objectForKey: @"baseDN"]
178 IDField: [udSource objectForKey: @"IDFieldName"]
179 CNField: [udSource objectForKey: @"CNFieldName"]
180 UIDField: [udSource objectForKey: @"UIDFieldName"]
181 andBindFields: [udSource objectForKey: @"bindFields"]];
186 - (void) setBindDN: (NSString *) newBindDN
187 hostname: (NSString *) newBindHostname
188 port: (NSString *) newBindPort
189 andPassword: (NSString *) newBindPassword
191 ASSIGN (bindDN, newBindDN);
192 ASSIGN (hostname, newBindHostname);
194 port = [newBindPort intValue];
195 ASSIGN (password, newBindPassword);
198 - (void) setBaseDN: (NSString *) newBaseDN
199 IDField: (NSString *) newIDField
200 CNField: (NSString *) newCNField
201 UIDField: (NSString *) newUIDField
202 andBindFields: (NSString *) newBindFields
204 ASSIGN (baseDN, newBaseDN);
206 ASSIGN (IDField, newIDField);
208 ASSIGN (CNField, newCNField);
210 ASSIGN (UIDField, newUIDField);
212 ASSIGN (bindFields, newBindFields);
215 - (void) _initLDAPConnection
217 ldapConnection = [[NGLdapConnection alloc] initWithHostName: hostname
219 [ldapConnection bindWithMethod: @"simple"
221 credentials: password];
223 [ldapConnection setQuerySizeLimit: sizeLimit];
225 [ldapConnection setQueryTimeLimit: timeLimit];
228 /* user management */
229 - (EOQualifier *) _qualifierForBindFilter: (NSString *) uid
232 NSEnumerator *fields;
233 NSString *currentField;
235 qs = [NSMutableString string];
236 fields = [[bindFields componentsSeparatedByString: @","] objectEnumerator];
237 currentField = [fields nextObject];
240 [qs appendFormat: @"OR (%@='%@')", currentField, uid];
241 currentField = [fields nextObject];
243 [qs deleteCharactersInRange: NSMakeRange (0, 3)];
245 return [EOQualifier qualifierWithQualifierFormat: qs];
248 - (NSString *) _fetchUserDNForLogin: (NSString *) loginToCheck
251 NSEnumerator *entries;
252 NGLdapEntry *userEntry;
254 [self _initLDAPConnection];
255 entries = [ldapConnection deepSearchAtBaseDN: baseDN
256 qualifier: [self _qualifierForBindFilter: loginToCheck]
257 attributes: [NSArray arrayWithObject: @"dn"]];
258 userEntry = [entries nextObject];
260 userDN = [userEntry dn];
263 [ldapConnection release];
268 - (BOOL) checkLogin: (NSString *) loginToCheck
269 andPassword: (NSString *) passwordToCheck
273 NGLdapConnection *bindConnection;
275 if ([loginToCheck length] > 0)
277 bindConnection = [[NGLdapConnection alloc] initWithHostName: hostname
280 [ldapConnection setQueryTimeLimit: timeLimit];
282 userDN = [self _fetchUserDNForLogin: loginToCheck];
284 userDN = [NSString stringWithFormat: @"%@=%@,%@",
285 IDField, loginToCheck, baseDN];
289 didBind = [bindConnection bindWithMethod: @"simple"
291 credentials: passwordToCheck];
296 [bindConnection release];
304 /* contact management */
305 - (EOQualifier *) _qualifierForFilter: (NSString *) filter
308 EOQualifier *qualifier;
310 if ([filter length] > 0)
312 if ([filter isEqualToString: @"."])
315 qs = [NSString stringWithFormat:
318 @"OR (displayName='%@*')"
320 @"OR (telephoneNumber='*%@*')",
321 filter, filter, filter, filter, filter];
322 qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
330 - (EOQualifier *) _qualifierForUIDFilter: (NSString *) uid
334 qs = [NSString stringWithFormat: (@"(%@='%@') OR (mail='%@')"
335 @" OR (mozillaSecondEmail='%@')"
336 @" OR (xmozillasecondemail='%@')"),
337 UIDField, uid, uid, uid, uid];
339 return [EOQualifier qualifierWithQualifierFormat: qs];
342 - (NSArray *) _searchAttributes
344 if (!searchAttributes)
346 searchAttributes = [NSMutableArray new];
348 [searchAttributes addObject: CNField];
350 [searchAttributes addObject: UIDField];
351 [searchAttributes addObjectsFromArray: commonSearchFields];
354 return searchAttributes;
357 - (NSArray *) allEntryIDs
360 NSEnumerator *entries;
361 NGLdapEntry *currentEntry;
364 ids = [NSMutableArray array];
366 [self _initLDAPConnection];
367 entries = [ldapConnection deepSearchAtBaseDN: baseDN
369 attributes: [NSArray arrayWithObject: IDField]];
372 currentEntry = [entries nextObject];
375 value = [[currentEntry attributeWithName: IDField]
376 stringValueAtIndex: 0];
377 if ([value length] > 0)
378 [ids addObject: value];
379 currentEntry = [entries nextObject];
382 [ldapConnection release];
387 - (NSDictionary *) _convertLDAPEntryToContact: (NGLdapEntry *) ldapEntry
389 NSMutableDictionary *contactEntry;
390 NSEnumerator *attributes;
391 NSString *currentAttribute, *value;
393 contactEntry = [NSMutableDictionary dictionary];
394 attributes = [[self _searchAttributes] objectEnumerator];
395 currentAttribute = [attributes nextObject];
396 while (currentAttribute)
398 value = [[ldapEntry attributeWithName: currentAttribute]
399 stringValueAtIndex: 0];
401 [contactEntry setObject: value forKey: currentAttribute];
402 currentAttribute = [attributes nextObject];
404 value = [[ldapEntry attributeWithName: IDField] stringValueAtIndex: 0];
407 [contactEntry setObject: value forKey: @"c_name"];
408 value = [[ldapEntry attributeWithName: UIDField] stringValueAtIndex: 0];
411 [contactEntry setObject: value forKey: @"c_uid"];
412 value = [[ldapEntry attributeWithName: CNField] stringValueAtIndex: 0];
415 [contactEntry setObject: value forKey: @"c_cn"];
420 - (NSArray *) fetchContactsMatching: (NSString *) match
422 NSMutableArray *contacts;
423 NGLdapEntry *currentEntry;
424 NSEnumerator *entries;
426 contacts = [NSMutableArray array];
428 if ([match length] > 0)
430 [self _initLDAPConnection];
431 entries = [ldapConnection deepSearchAtBaseDN: baseDN
432 qualifier: [self _qualifierForFilter: match]
433 attributes: [self _searchAttributes]];
436 currentEntry = [entries nextObject];
440 [self _convertLDAPEntryToContact: currentEntry]];
441 currentEntry = [entries nextObject];
444 [ldapConnection release];
450 - (NSDictionary *) lookupContactEntry: (NSString *) entryID;
452 NSDictionary *contactEntry;
453 NGLdapEntry *ldapEntry;
457 if ([entryID length] > 0)
459 [self _initLDAPConnection];
461 = [ldapConnection entryAtDN: [NSString stringWithFormat: @"%@=%@,%@",
462 IDField, entryID, baseDN]
463 attributes: [self _searchAttributes]];
465 contactEntry = [self _convertLDAPEntryToContact: ldapEntry];
466 [ldapConnection release];
472 - (NSDictionary *) lookupContactEntryWithUIDorEmail: (NSString *) uid;
474 NSDictionary *contactEntry;
475 NGLdapEntry *ldapEntry;
476 NSEnumerator *entries;
477 EOQualifier *qualifier;
481 if ([uid length] > 0)
483 [self _initLDAPConnection];
484 qualifier = [self _qualifierForUIDFilter: uid];
485 entries = [ldapConnection deepSearchAtBaseDN: baseDN
487 attributes: [self _searchAttributes]];
488 ldapEntry = [entries nextObject];
490 contactEntry = [self _convertLDAPEntryToContact: ldapEntry];
491 [ldapConnection release];