]> err.no Git - scalable-opengroupware.org/blob - SoObjects/SOGo/LDAPSource.m
9b9390662984ed49edb8cdc5e27d698fd3673668
[scalable-opengroupware.org] / SoObjects / SOGo / LDAPSource.m
1 /* LDAPSource.m - this file is part of SOGo
2  *
3  * Copyright (C) 2007 Inverse groupe conseil
4  *
5  * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
6  *
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)
10  * any later version.
11  *
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.
16  *
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.
21  */
22
23 #import <Foundation/NSArray.h>
24 #import <Foundation/NSDictionary.h>
25 #import <Foundation/NSString.h>
26
27 #import <EOControl/EOControl.h>
28 #import <NGLdap/NGLdapConnection.h>
29 #import <NGLdap/NGLdapAttribute.h>
30 #import <NGLdap/NGLdapEntry.h>
31
32 #import "LDAPSource.h"
33
34 static NSArray *commonSearchFields;
35
36 @implementation LDAPSource
37
38 + (void) initialize
39 {
40   if (!commonSearchFields)
41     {
42       commonSearchFields = [NSArray arrayWithObjects:
43                                       @"title",
44                                     @"company",
45                                     @"o",
46                                     @"displayName",
47                                     @"modifytimestamp",
48                                     @"mozillaHomeState",
49                                     @"mozillaHomeUrl",
50                                     @"homeurl",
51                                     @"st",
52                                     @"region",
53                                     @"mozillaCustom2",
54                                     @"custom2",
55                                     @"mozillaHomeCountryName",
56                                     @"description",
57                                     @"notes",
58                                     @"department",
59                                     @"departmentnumber",
60                                     @"ou",
61                                     @"orgunit",
62                                     @"mobile",
63                                     @"cellphone",
64                                     @"carphone",
65                                     @"mozillaCustom1",
66                                     @"custom1",
67                                     @"mozillaNickname",
68                                     @"xmozillanickname",
69                                     @"mozillaWorkUrl",
70                                     @"workurl",
71                                     @"fax",
72                                     @"facsimileTelephoneNumber",
73                                     @"telephoneNumber",
74                                     @"mozillaHomeStreet",
75                                     @"mozillaSecondEmail",
76                                     @"xmozillasecondemail",
77                                     @"mozillaCustom4",
78                                     @"custom4",
79                                     @"nsAIMid",
80                                     @"nscpaimscreenname",
81                                     @"street",
82                                     @"streetAddress",
83                                     @"postOfficeBox",
84                                     @"homePhone",
85                                     @"cn",
86                                     @"commonname",
87                                     @"givenName",
88                                     @"mozillaHomePostalCode",
89                                     @"mozillaHomeLocalityName",
90                                     @"mozillaWorkStreet2",
91                                     @"mozillaUseHtmlMail",
92                                     @"xmozillausehtmlmail",
93                                     @"mozillaHomeStreet2",
94                                     @"postalCode",
95                                     @"zip",
96                                     @"c",
97                                     @"countryname",
98                                     @"pager",
99                                     @"pagerphone",
100                                     @"mail",
101                                     @"sn",
102                                     @"surname",
103                                     @"mozillaCustom3",
104                                     @"custom3",
105                                     @"l",
106                                     @"locality",
107                                     @"birthyear",
108                                     @"serialNumber",
109                                     @"calFBURL",
110                                     nil];
111       [commonSearchFields retain];
112     }
113 }
114
115 + (id) sourceFromUDSource: (NSDictionary *) udSource
116 {
117   id newSource;
118
119   newSource = [[self alloc] initFromUDSource: udSource];
120   [newSource autorelease];
121
122   return newSource;
123 }
124
125 - (id) init
126 {
127   if ((self = [super init]))
128     {
129       bindDN = nil;
130       hostname = nil;
131       port = 389;
132       password = nil;
133
134       baseDN = nil;
135       IDField = @"cn"; /* the first part of a user DN */
136       CNField = @"cn";
137       UIDField = @"uid";
138
139       ldapConnection = nil;
140       searchAttributes = nil;
141     }
142
143   return self;
144 }
145
146 - (void) dealloc
147 {
148   [bindDN release];
149   [hostname release];
150   [password release];
151   [baseDN release];
152   [IDField release];
153   [CNField release];
154   [UIDField release];
155   [ldapConnection release];
156   [super dealloc];
157 }
158
159 - (id) initFromUDSource: (NSDictionary *) udSource
160 {
161   self = [self init];
162
163   [self setBindDN: [udSource objectForKey: @"bindDN"]
164         hostname: [udSource objectForKey: @"hostname"]
165         port: [udSource objectForKey: @"port"]
166         andPassword: [udSource objectForKey: @"bindPassword"]];
167   [self setBaseDN: [udSource objectForKey: @"baseDN"]
168         IDField: [udSource objectForKey: @"IDFieldName"]
169         CNField: [udSource objectForKey: @"CNFieldName"]
170         andUIDField:  [udSource objectForKey: @"UIDFieldName"]];
171
172   return self;
173 }
174
175 - (void) setBindDN: (NSString *) newBindDN
176           hostname: (NSString *) newBindHostname
177               port: (NSString *) newBindPort
178        andPassword: (NSString *) newBindPassword
179 {
180   ASSIGN (bindDN, newBindDN);
181   ASSIGN (hostname, newBindHostname);
182   if (newBindPort)
183     port = [newBindPort intValue];
184   ASSIGN (password, newBindPassword);
185 }
186
187 - (void) setBaseDN: (NSString *) newBaseDN
188            IDField: (NSString *) newIDField
189            CNField: (NSString *) newCNField
190        andUIDField: (NSString *) newUIDField
191 {
192   ASSIGN (baseDN, newBaseDN);
193   if (newIDField)
194     ASSIGN (IDField, newIDField);
195   if (CNField)
196     ASSIGN (CNField, newCNField);
197   if (UIDField)
198     ASSIGN (UIDField, newUIDField);
199 }
200
201 - (void) _initLDAPConnection
202 {
203   ldapConnection = [[NGLdapConnection alloc] initWithHostName: hostname
204                                              port: port];
205   [ldapConnection bindWithMethod: @"simple"
206                   binddn: bindDN
207                   credentials: password];
208 }
209
210 /* user management */
211 - (BOOL) checkLogin: (NSString *) loginToCheck
212         andPassword: (NSString *) passwordToCheck
213 {
214   BOOL didBind;
215   NSString *userDN;
216   NGLdapConnection *bindConnection;
217
218   bindConnection = [[NGLdapConnection alloc] initWithHostName: hostname
219                                              port: port];
220   userDN = [NSString stringWithFormat: @"%@=%@,%@",
221                      IDField, loginToCheck, baseDN];
222   NS_DURING
223     didBind = [bindConnection bindWithMethod: @"simple" binddn: userDN
224                               credentials: passwordToCheck];
225   NS_HANDLER
226     didBind = NO;
227   NS_ENDHANDLER
228
229   [bindConnection release];
230
231   return didBind;
232 }
233
234 /* contact management */
235 - (EOQualifier *) _qualifierForFilter: (NSString *) filter
236 {
237   NSString *qs;
238   EOQualifier *qualifier;
239
240   if (filter && [filter length] > 0)
241     {
242       if ([filter isEqualToString: @"."])
243         qs = @"(cn='*')";
244       else
245         qs = [NSString stringWithFormat:
246                          @"(cn='%@*')"
247                        @"OR (sn='%@*')"
248                        @"OR (displayName='%@*')"
249                        @"OR (mail='%@*')"
250                        @"OR (telephoneNumber='*%@*')",
251                        filter, filter, filter, filter, filter];
252       qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
253     }
254   else
255     qualifier = nil;
256
257   return qualifier;
258 }
259
260 - (EOQualifier *) _qualifierForUIDFilter: (NSString *) uid
261 {
262   NSString *qs;
263
264   qs = [NSString stringWithFormat: (@"(%@='%@') OR (mail='%@')"
265                                     @" OR (mozillaSecondEmail='%@')"
266                                     @" OR (xmozillasecondemail='%@')"),
267                  UIDField, uid, uid, uid, uid];
268
269   return [EOQualifier qualifierWithQualifierFormat: qs];
270 }
271
272 - (NSArray *) _searchAttributes
273 {
274   if (!searchAttributes)
275     {
276       searchAttributes = [NSMutableArray new];
277       if (CNField)
278         [searchAttributes addObject: CNField];
279       if (UIDField)
280         [searchAttributes addObject: UIDField];
281       [searchAttributes addObjectsFromArray: commonSearchFields];
282     }
283
284   return searchAttributes;
285 }
286
287 - (NSArray *) allEntryIDs
288 {
289   NSMutableArray *ids;
290   NSEnumerator *entries;
291   NGLdapEntry *currentEntry;
292   NSString *value;
293
294   ids = [NSMutableArray array];
295
296   if (!ldapConnection)
297     [self _initLDAPConnection];
298   entries = [ldapConnection deepSearchAtBaseDN: baseDN
299                             qualifier: nil
300                             attributes: [NSArray arrayWithObject: IDField]];
301   if (entries)
302     {
303       currentEntry = [entries nextObject];
304       while (currentEntry)
305         {
306           value = [[currentEntry attributeWithName: IDField]
307                     stringValueAtIndex: 0];
308           if ([value length] > 0)
309             [ids addObject: value];
310           currentEntry = [entries nextObject];
311         }
312     }
313
314   return ids;
315 }
316
317 - (NSDictionary *) _convertLDAPEntryToContact: (NGLdapEntry *) ldapEntry
318 {
319   NSMutableDictionary *contactEntry;
320   NSEnumerator *attributes;
321   NSString *currentAttribute, *value;
322
323   contactEntry = [NSMutableDictionary dictionary];
324   attributes = [[self _searchAttributes] objectEnumerator];
325   currentAttribute = [attributes nextObject];
326   while (currentAttribute)
327     {
328       value = [[ldapEntry attributeWithName: currentAttribute]
329                 stringValueAtIndex: 0];
330       if (value)
331         [contactEntry setObject: value forKey: currentAttribute];
332       currentAttribute = [attributes nextObject];
333     }
334   value = [[ldapEntry attributeWithName: IDField] stringValueAtIndex: 0];
335   if (!value)
336     value = @"";
337   [contactEntry setObject: value forKey: @"c_name"];
338   value = [[ldapEntry attributeWithName: UIDField] stringValueAtIndex: 0];
339   if (!value)
340     value = @"";
341   [contactEntry setObject: value forKey: @"c_uid"];
342   value = [[ldapEntry attributeWithName: CNField] stringValueAtIndex: 0];
343   if (!value)
344     value = @"";
345   [contactEntry setObject: value forKey: @"c_cn"];
346
347   return contactEntry;
348 }
349
350 - (NSArray *) fetchContactsMatching: (NSString *) match
351 {
352   NSMutableArray *contacts;
353   NGLdapEntry *currentEntry;
354   NSEnumerator *entries;
355
356   contacts = [NSMutableArray array];
357
358   if (!ldapConnection)
359     [self _initLDAPConnection];
360   entries = [ldapConnection deepSearchAtBaseDN: baseDN
361                             qualifier: [self _qualifierForFilter: match]
362                             attributes: [self _searchAttributes]];
363   if (entries)
364     {
365       currentEntry = [entries nextObject];
366       while (currentEntry)
367         {
368           [contacts addObject:
369                       [self _convertLDAPEntryToContact: currentEntry]];
370           currentEntry = [entries nextObject];
371         }
372     }
373
374   return contacts;
375 }
376
377 - (NSDictionary *) lookupContactEntry: (NSString *) entryID;
378 {
379   NSDictionary *contactEntry;
380   NGLdapEntry *ldapEntry;
381
382   if (!ldapConnection)
383     [self _initLDAPConnection];
384   ldapEntry
385     = [ldapConnection entryAtDN: [NSString stringWithFormat: @"%@=%@,%@",
386                                            IDField, entryID, baseDN]
387                       attributes: [self _searchAttributes]];
388   if (ldapEntry)
389     contactEntry = [self _convertLDAPEntryToContact: ldapEntry];
390   else
391     contactEntry = nil;
392
393   return contactEntry;
394 }
395
396 - (NSDictionary *) lookupContactEntryWithUIDorEmail: (NSString *) uid;
397 {
398   NSDictionary *contactEntry;
399   NGLdapEntry *ldapEntry;
400   NSEnumerator *entries;
401   EOQualifier *qualifier;
402
403   if (!ldapConnection)
404     [self _initLDAPConnection];
405   qualifier = [self _qualifierForUIDFilter: uid];
406   entries = [ldapConnection deepSearchAtBaseDN: baseDN
407                              qualifier: qualifier
408                             attributes: [self _searchAttributes]];
409   ldapEntry = [entries nextObject];
410   if (ldapEntry)
411     contactEntry = [self _convertLDAPEntryToContact: ldapEntry];
412   else
413     contactEntry = nil;
414
415   return contactEntry;
416 }
417
418 @end