]> err.no Git - scalable-opengroupware.org/blob - SoObjects/Contacts/SOGoContactLDAPFolder.m
b15ed3033a7282628cc7cfbb3a024c5f17e8a118
[scalable-opengroupware.org] / SoObjects / Contacts / SOGoContactLDAPFolder.m
1 /* SOGoContactLDAPFolder.m - this file is part of SOGo
2  *
3  * Copyright (C) 2006 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/NSString.h>
25
26 #import <Foundation/NSDictionary.h>
27 #import <Foundation/NSString.h>
28
29 #import <NGObjWeb/WOApplication.h>
30 #import <NGObjWeb/WOContext.h>
31 #import <NGObjWeb/WOContext+SoObjects.h>
32 #import <NGObjWeb/SoUser.h>
33
34 #import <NGLdap/NGLdapAttribute.h>
35 #import <NGLdap/NGLdapConnection.h>
36 #import <NGLdap/NGLdapEntry.h>
37
38 #import "common.h"
39
40 #import "NGLdapEntry+Contact.h"
41
42 #import "SOGoContactLDAPEntry.h"
43 #import "SOGoContactLDAPFolder.h"
44
45 #define folderListingFields [NSArray arrayWithObjects: @"c_name", @"cn", \
46                                      @"displayName",                     \
47                                      @"streetAddress",                   \
48                                      @"o", \
49                                      @"sn", @"givenname", @"l",          \
50                                      @"mail", @"telephonenumber",        \
51                                      @"mailNickname",                    \
52                                      @"sAMAccountName",                  \
53                                      @"uid",                  \
54                                      nil]
55
56 @class WOContext;
57
58 @implementation SOGoContactLDAPFolder
59
60 + (id <SOGoContactFolder>) contactFolderWithName: (NSString *) aName
61                                   andDisplayName: (NSString *) aDisplayName
62                                      inContainer: (SOGoObject *) aContainer
63 {
64   SOGoContactLDAPFolder *folder;
65
66   folder = [[self alloc] initWithName: aName
67                          andDisplayName: aDisplayName
68                          inContainer: aContainer];
69   [folder autorelease];
70
71   return folder;
72 }
73
74 - (id) init
75 {
76   if ((self = [super init]))
77     {
78       connection = nil;
79       contactIdentifier = nil;
80       userIdentifier = nil;
81       rootDN = nil;
82       entries = nil;
83     }
84
85   return self;
86 }
87
88 - (id <SOGoContactFolder>) initWithName: (NSString *) aName
89                          andDisplayName: (NSString *) aDisplayName
90                             inContainer: (SOGoObject *) aContainer
91 {
92   if ((self = [self initWithName: aName
93                     inContainer: aContainer]))
94     [self setDisplayName: aDisplayName];
95   
96   return self;
97 }
98
99 - (void) dealloc
100 {
101   [connection release];
102   [contactIdentifier release];
103   [userIdentifier release];
104   [rootDN release];
105   [entries release];
106   [super dealloc];
107 }
108
109 - (void) setDisplayName: (NSString *) aDisplayName
110 {
111   if (displayName)
112     [displayName release];
113   displayName = aDisplayName;
114   if (displayName)
115     [displayName retain];
116 }
117
118 - (NSString *) displayName
119 {
120   return displayName;
121 }
122
123 - (void) LDAPSetHostname: (NSString *) aHostname
124                  setPort: (int) aPort
125                setBindDN: (NSString *) aBindDN
126                setBindPW: (NSString *) aBindPW
127     setContactIdentifier: (NSString *) aCI
128        setUserIdentifier: (NSString *) aUI
129                setRootDN: (NSString *) aRootDN;
130 {
131   connection = [[NGLdapConnection alloc] initWithHostName: aHostname
132                                          port: aPort];
133   [connection bindWithMethod: nil
134               binddn: aBindDN
135               credentials: aBindPW];
136
137   if (rootDN)
138     [rootDN release];
139   rootDN = [aRootDN copy];
140   if (contactIdentifier)
141     [contactIdentifier release];
142   contactIdentifier = [aCI copy];
143   if (userIdentifier)
144     [userIdentifier release];
145   userIdentifier = [aUI copy];
146 }
147
148 - (NGLdapConnection *) LDAPconnection
149 {
150   return connection;
151 }
152
153 - (NGLdapAttribute *) _attrWithName: (NSString *) aName
154 {
155   return [[[NGLdapAttribute alloc] initWithAttributeName: aName] autorelease];
156 }
157
158 - (NSArray *) _searchAttributes
159 {
160   return [NSArray arrayWithObjects:
161                     contactIdentifier,
162                   userIdentifier,
163                   @"title",
164                   @"company",
165                   @"o",
166                   @"displayName",
167                   @"modifytimestamp",
168                   @"mozillaHomeState",
169                   @"mozillaHomeUrl",
170                   @"homeurl",
171                   @"st",
172                   @"region",
173                   @"mozillaCustom2",
174                   @"custom2",
175                   @"mozillaHomeCountryName",
176                   @"description",
177                   @"notes",
178                   @"department",
179                   @"departmentnumber",
180                   @"ou",
181                   @"orgunit",
182                   @"mobile",
183                   @"cellphone",
184                   @"carphone",
185                   @"mozillaCustom1",
186                   @"custom1",
187                   @"mozillaNickname",
188                   @"xmozillanickname",
189                   @"mozillaWorkUrl",
190                   @"workurl",
191                   @"fax",
192                   @"facsimileTelephoneNumber",
193                   @"telephoneNumber",
194                   @"mozillaHomeStreet",
195                   @"mozillaSecondEmail",
196                   @"xmozillasecondemail",
197                   @"mozillaCustom4",
198                   @"custom4",
199                   @"nsAIMid",
200                   @"nscpaimscreenname",
201                   @"street",
202                   @"streetAddress",
203                   @"postOfficeBox",
204                   @"homePhone",
205                   @"cn",
206                   @"commonname",
207                   @"givenName",
208                   @"mozillaHomePostalCode",
209                   @"mozillaHomeLocalityName",
210                   @"mozillaWorkStreet2",
211                   @"mozillaUseHtmlMail",
212                   @"xmozillausehtmlmail",
213                   @"mozillaHomeStreet2",
214                   @"postalCode",
215                   @"zip",
216                   @"c",
217                   @"countryname",
218                   @"pager",
219                   @"pagerphone",
220                   @"mail",
221                   @"sn",
222                   @"surname",
223                   @"mozillaCustom3",
224                   @"custom3",
225                   @"l",
226                   @"locality",
227                   @"birthyear",
228                   @"serialNumber",
229                   @"calFBURL",
230                   nil];
231 }
232
233 - (void) _loadEntries: (NSString *) entryId
234 {
235   NSEnumerator *contacts;
236   NGLdapEntry *entry;
237   NSString *key;
238
239   if (!entries)
240     entries = [NSMutableDictionary new];
241
242   if (entryId)
243     {
244       if (![entries objectForKey: entryId])
245         {
246           entry
247             = [connection entryAtDN:
248                             [NSString stringWithFormat: @"%@=%@,%@",
249                                       contactIdentifier, entryId, rootDN]
250                           attributes: [self _searchAttributes]];
251           if (entry)
252             [entries setObject: entry forKey: entryId];
253         }
254     }
255   else
256     {
257       contacts = [connection deepSearchAtBaseDN: rootDN
258                              qualifier: nil
259                              attributes: [self _searchAttributes]];
260       if (contacts)
261         {
262           entry = [contacts nextObject];
263           while (entry)
264             {
265               key = [[entry attributeWithName: contactIdentifier]
266                       stringValueAtIndex: 0];
267               if (key && ![entries objectForKey: key])
268                 [entries setObject: entry forKey: key];
269               entry = [contacts nextObject];
270             }
271         }
272     }
273 }
274
275 - (id) lookupName: (NSString *) name
276         inContext: (WOContext *) lookupContext
277           acquire: (BOOL) acquire
278 {
279   id obj;
280   NGLdapEntry *entry;
281
282 //   NSLog (@"looking up name '%@'...", name);
283
284   /* first check attributes directly bound to the application */
285   obj = [super lookupName: name inContext: lookupContext acquire: NO];
286   if (!obj)
287     {
288       [self _loadEntries: name];
289       entry = [entries objectForKey: name];
290       obj = ((entry)
291              ? [SOGoContactLDAPEntry contactEntryWithName: name
292                                      withLDAPEntry: entry
293                                      inContainer: self]
294              : [NSException exceptionWithHTTPStatus: 404]);
295     }
296
297   return obj;
298 }
299
300 - (NSArray *) toOneRelationshipKeys
301 {
302   [self _loadEntries: nil];
303
304   return [entries allKeys];
305 }
306
307 - (id <SOGoContactObject>) lookupContactWithId: (NSString *) recordId
308 {
309   NGLdapEntry *entry;
310
311   [self _loadEntries: recordId];
312
313   entry = [entries objectForKey: recordId];
314   return ((entry)
315           ? [SOGoContactLDAPEntry contactEntryWithName: recordId
316                                   withLDAPEntry: entry
317                                   inContainer: self]
318           : nil);
319 }
320
321 - (EOQualifier *) _qualifierForFilter: (NSString *) filter
322 {
323   NSString *qs;
324   EOQualifier *qualifier;
325
326   if (filter && [filter length] > 0)
327     {
328       if ([filter isEqualToString: @"."])
329         qs = @"(cn='*')";
330       else
331         qs = [NSString stringWithFormat:
332                          @"(cn='%@*')"
333                        @"OR (sn='%@*')"
334                        @"OR (displayName='%@*')"
335                        @"OR (mail='%@*')"
336                        @"OR (telephoneNumber='*%@*')",
337                        filter, filter, filter, filter, filter];
338       qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
339     }
340   else
341     qualifier = nil;
342
343   return qualifier;
344 }
345
346 - (NSArray *) lookupContactsWithFilter: (NSString *) filter
347                                 sortBy: (NSString *) sortKey
348                               ordering: (NSComparisonResult) sortOrdering
349 {
350   NSMutableArray *records;
351   NSArray *result;
352   NGLdapEntry *entry;
353   NSEnumerator *contacts;
354   EOSortOrdering *ordering;
355
356   result = nil;
357
358   if (filter && [filter length] > 0)
359     {
360       NSLog (@"%@: fetching records matching '%@', sorted by '%@'"
361              @" in order %d",
362              self, filter, sortKey, sortOrdering);
363
364       records = [NSMutableArray new];
365       [records autorelease];
366
367       contacts = [connection deepSearchAtBaseDN: rootDN
368                              qualifier: [self _qualifierForFilter: filter]
369                              attributes: folderListingFields];
370       entry = [contacts nextObject];
371       while (entry)
372         {
373           [records addObject: [entry asDictionaryWithAttributeNames: nil
374                                      withUID: userIdentifier
375                                      andCName: contactIdentifier]];
376           entry = [contacts nextObject];
377         }
378
379       ordering
380         = [EOSortOrdering sortOrderingWithKey: sortKey
381                           selector: ((sortOrdering == NSOrderedDescending)
382                                      ? EOCompareCaseInsensitiveDescending
383                                      : EOCompareCaseInsensitiveAscending)];
384       result
385         = [records sortedArrayUsingKeyOrderArray:
386                      [NSArray arrayWithObject: ordering]];
387     }
388
389   //[self debugWithFormat:@"fetched %i records.", [records count]];
390   return result;
391 }
392
393 - (NSString *) groupDavResourceType
394 {
395   return @"vcard-collection";
396 }
397
398 /* acls */
399 /* TODO: this might change one day when we support LDAP acls */
400 - (NSArray *) aclsForUser: (NSString *) uid
401 {
402   return nil;
403 }
404
405 @end