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;
277 if ([loginToCheck length] > 0)
279 bindConnection = [[NGLdapConnection alloc] initWithHostName: hostname
282 [ldapConnection setQueryTimeLimit: timeLimit];
284 userDN = [self _fetchUserDNForLogin: loginToCheck];
286 userDN = [NSString stringWithFormat: @"%@=%@,%@",
287 IDField, loginToCheck, baseDN];
291 didBind = [bindConnection bindWithMethod: @"simple"
293 credentials: passwordToCheck];
297 [bindConnection release];
303 /* contact management */
304 - (EOQualifier *) _qualifierForFilter: (NSString *) filter
307 EOQualifier *qualifier;
309 if ([filter length] > 0)
311 if ([filter isEqualToString: @"."])
314 qs = [NSString stringWithFormat:
317 @"OR (displayName='%@*')"
319 @"OR (telephoneNumber='*%@*')",
320 filter, filter, filter, filter, filter];
321 qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
329 - (EOQualifier *) _qualifierForUIDFilter: (NSString *) uid
333 qs = [NSString stringWithFormat: (@"(%@='%@') OR (mail='%@')"
334 @" OR (mozillaSecondEmail='%@')"
335 @" OR (xmozillasecondemail='%@')"),
336 UIDField, uid, uid, uid, uid];
338 return [EOQualifier qualifierWithQualifierFormat: qs];
341 - (NSArray *) _searchAttributes
343 if (!searchAttributes)
345 searchAttributes = [NSMutableArray new];
347 [searchAttributes addObject: CNField];
349 [searchAttributes addObject: UIDField];
350 [searchAttributes addObjectsFromArray: commonSearchFields];
353 return searchAttributes;
356 - (NSArray *) allEntryIDs
359 NSEnumerator *entries;
360 NGLdapEntry *currentEntry;
363 ids = [NSMutableArray array];
365 [self _initLDAPConnection];
366 entries = [ldapConnection deepSearchAtBaseDN: baseDN
368 attributes: [NSArray arrayWithObject: IDField]];
371 currentEntry = [entries nextObject];
374 value = [[currentEntry attributeWithName: IDField]
375 stringValueAtIndex: 0];
376 if ([value length] > 0)
377 [ids addObject: value];
378 currentEntry = [entries nextObject];
381 [ldapConnection release];
386 - (NSDictionary *) _convertLDAPEntryToContact: (NGLdapEntry *) ldapEntry
388 NSMutableDictionary *contactEntry;
389 NSEnumerator *attributes;
390 NSString *currentAttribute, *value;
392 contactEntry = [NSMutableDictionary dictionary];
393 attributes = [[self _searchAttributes] objectEnumerator];
394 currentAttribute = [attributes nextObject];
395 while (currentAttribute)
397 value = [[ldapEntry attributeWithName: currentAttribute]
398 stringValueAtIndex: 0];
400 [contactEntry setObject: value forKey: currentAttribute];
401 currentAttribute = [attributes nextObject];
403 value = [[ldapEntry attributeWithName: IDField] stringValueAtIndex: 0];
406 [contactEntry setObject: value forKey: @"c_name"];
407 value = [[ldapEntry attributeWithName: UIDField] stringValueAtIndex: 0];
410 [contactEntry setObject: value forKey: @"c_uid"];
411 value = [[ldapEntry attributeWithName: CNField] stringValueAtIndex: 0];
414 [contactEntry setObject: value forKey: @"c_cn"];
419 - (NSArray *) fetchContactsMatching: (NSString *) match
421 NSMutableArray *contacts;
422 NGLdapEntry *currentEntry;
423 NSEnumerator *entries;
425 contacts = [NSMutableArray array];
427 if ([match length] > 0)
429 [self _initLDAPConnection];
430 entries = [ldapConnection deepSearchAtBaseDN: baseDN
431 qualifier: [self _qualifierForFilter: match]
432 attributes: [self _searchAttributes]];
435 currentEntry = [entries nextObject];
439 [self _convertLDAPEntryToContact: currentEntry]];
440 currentEntry = [entries nextObject];
443 [ldapConnection release];
449 - (NSDictionary *) lookupContactEntry: (NSString *) entryID;
451 NSDictionary *contactEntry;
452 NGLdapEntry *ldapEntry;
456 if ([entryID length] > 0)
458 [self _initLDAPConnection];
460 = [ldapConnection entryAtDN: [NSString stringWithFormat: @"%@=%@,%@",
461 IDField, entryID, baseDN]
462 attributes: [self _searchAttributes]];
464 contactEntry = [self _convertLDAPEntryToContact: ldapEntry];
465 [ldapConnection release];
471 - (NSDictionary *) lookupContactEntryWithUIDorEmail: (NSString *) uid;
473 NSDictionary *contactEntry;
474 NGLdapEntry *ldapEntry;
475 NSEnumerator *entries;
476 EOQualifier *qualifier;
480 if ([uid length] > 0)
482 [self _initLDAPConnection];
483 qualifier = [self _qualifierForUIDFilter: uid];
484 entries = [ldapConnection deepSearchAtBaseDN: baseDN
486 attributes: [self _searchAttributes]];
487 ldapEntry = [entries nextObject];
489 contactEntry = [self _convertLDAPEntryToContact: ldapEntry];
490 [ldapConnection release];