]> err.no Git - scalable-opengroupware.org/blob - SoObjects/Contacts/SOGoContactLDAPFolder.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1257 d1b88da0-ebda-0310...
[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/NSDictionary.h>
25 #import <Foundation/NSString.h>
26
27 #import <NGObjWeb/NSException+HTTP.h>
28 #import <NGObjWeb/WOApplication.h>
29 #import <NGObjWeb/WOContext.h>
30 #import <NGObjWeb/WOContext+SoObjects.h>
31 #import <NGObjWeb/WOResponse.h>
32 #import <NGObjWeb/SoObject.h>
33 #import <NGObjWeb/SoUser.h>
34 #import <EOControl/EOSortOrdering.h>
35 #import <SaxObjC/XMLNamespaces.h>
36
37 #import <SoObjects/SOGo/LDAPSource.h>
38 #import <SoObjects/SOGo/NSString+Utilities.h>
39 #import "SOGoContactLDIFEntry.h"
40 #import "SOGoContactLDAPFolder.h"
41 #import <NGExtensions/NSString+misc.h>
42 #import <NGObjWeb/WORequest.h>
43 #import <NGObjWeb/SoSelectorInvocation.h>
44
45 @class WOContext;
46
47 @implementation SOGoContactLDAPFolder
48
49 #warning this should be unified within SOGoFolder
50 - (void) appendObject: (NSDictionary *) object
51           withBaseURL: (NSString *) baseURL
52      toREPORTResponse: (WOResponse *) r
53 {
54   SOGoContactLDIFEntry *component;
55   NSString *name, *etagLine, *contactString;
56
57   name = [object objectForKey: @"c_name"];
58   component = [self lookupName: name inContext: context acquire: NO];
59
60   [r appendContentString: @"  <D:response>\r\n"];
61   [r appendContentString: @"    <D:href>"];
62   [r appendContentString: baseURL];
63   if (![baseURL hasSuffix: @"/"])
64     [r appendContentString: @"/"];
65   [r appendContentString: name];
66   [r appendContentString: @"</D:href>\r\n"];
67
68   [r appendContentString: @"    <D:propstat>\r\n"];
69   [r appendContentString: @"      <D:prop>\r\n"];
70   etagLine = [NSString stringWithFormat: @"        <D:getetag>%@</D:getetag>\r\n",
71                        [component davEntityTag]];
72   [r appendContentString: etagLine];
73   [r appendContentString: @"      </D:prop>\r\n"];
74   [r appendContentString: @"      <D:status>HTTP/1.1 200 OK</D:status>\r\n"];
75   [r appendContentString: @"    </D:propstat>\r\n"];
76   [r appendContentString: @"    <C:addressbook-data>"];
77   contactString = [[component contentAsString] stringByEscapingXMLString];
78   [r appendContentString: contactString];
79   [r appendContentString: @"</C:addressbook-data>\r\n"];
80   [r appendContentString: @"  </D:response>\r\n"];
81 }
82
83 + (id) folderWithName: (NSString *) aName
84        andDisplayName: (NSString *) aDisplayName
85           inContainer: (id) aContainer
86 {
87   id folder;
88
89   folder = [[self alloc] initWithName: aName
90                          andDisplayName: aDisplayName
91                          inContainer: aContainer];
92   [folder autorelease];
93
94   return folder;
95 }
96
97 - (id) init
98 {
99   if ((self = [super init]))
100     {
101       displayName = nil;
102       entries = nil;
103       ldapSource = nil;
104     }
105
106   return self;
107 }
108
109 - (id) initWithName: (NSString *) newName
110      andDisplayName: (NSString *) newDisplayName
111         inContainer: (id) newContainer
112 {
113   if ((self = [self initWithName: newName
114                     inContainer: newContainer]))
115     {
116       ASSIGN (displayName, newDisplayName);
117     }
118
119   return self;
120 }
121
122 - (void) dealloc
123 {
124   [displayName release];
125   [entries release];
126   [ldapSource release];
127   [super dealloc];
128 }
129
130 - (void) setLDAPSource: (LDAPSource *) newLDAPSource
131 {
132   ASSIGN (ldapSource, newLDAPSource);
133 }
134
135 - (NSString *) displayName
136 {
137   return displayName;
138 }
139
140 - (NSArray *) davNamespaces
141 {
142   return [NSArray arrayWithObject: @"urn:ietf:params:xml:ns:carddav"];
143 }
144
145 - (id) lookupName: (NSString *) objectName
146         inContext: (WOContext *) lookupContext
147           acquire: (BOOL) acquire
148 {
149   id obj;
150   NSDictionary *ldifEntry;
151
152   //NSLog (@"looking up name '%@'...", objectName);
153
154   /* first check attributes directly bound to the application */
155   obj = [super lookupName: objectName inContext: lookupContext acquire: NO];
156
157   if (!obj)
158     {
159       ldifEntry = [ldapSource lookupContactEntry: objectName];
160       obj = ((ldifEntry)
161              ? [SOGoContactLDIFEntry contactEntryWithName: objectName
162                                      withLDIFEntry: ldifEntry
163                                      inContainer: self]
164              : [NSException exceptionWithHTTPStatus: 404]);
165     }
166
167   return obj;
168 }
169
170 - (NSArray *) toOneRelationshipKeys
171 {
172   return [ldapSource allEntryIDs];
173 }
174
175 - (NSArray *) _flattenedRecords: (NSArray *) records
176 {
177   NSMutableArray *newRecords;
178   NSEnumerator *oldRecords;
179   NSDictionary *oldRecord;
180   NSMutableDictionary *newRecord;
181   NSString *data;
182   
183   newRecords = [[NSMutableArray alloc] initWithCapacity: [records count]];
184   [newRecords autorelease];
185
186   oldRecords = [records objectEnumerator];
187   oldRecord = [oldRecords nextObject];
188   while (oldRecord)
189     {
190       newRecord = [NSMutableDictionary new];
191       [newRecord autorelease];
192
193       [newRecord setObject: [oldRecord objectForKey: @"c_uid"]
194                  forKey: @"c_uid"];
195       [newRecord setObject: [oldRecord objectForKey: @"c_name"]
196                  forKey: @"c_name"];
197
198       data = [oldRecord objectForKey: @"displayName"];
199       if (!data)
200         data = [oldRecord objectForKey: @"c_cn"];
201       if (!data)
202         data = @"";
203       [newRecord setObject: data forKey: @"displayName"];
204
205       data = [oldRecord objectForKey: @"mail"];
206       if (!data)
207         data = @"";
208       [newRecord setObject: data forKey: @"mail"];
209
210       data = [oldRecord objectForKey: @"nsAIMid"];
211       if (![data length])
212         data = [oldRecord objectForKey: @"nscpaimscreenname"];
213       if (![data length])
214         data = @"";
215       [newRecord setObject: data forKey: @"screenName"];
216
217       data = [oldRecord objectForKey: @"o"];
218       if (!data)
219         data = @"";
220       [newRecord setObject: data forKey: @"org"];
221
222       data = [oldRecord objectForKey: @"telephoneNumber"];
223       if (![data length])
224         data = [oldRecord objectForKey: @"cellphone"];
225       if (![data length])
226         data = [oldRecord objectForKey: @"homePhone"];
227       if (![data length])
228         data = @"";
229       [newRecord setObject: data forKey: @"phone"];
230
231       [newRecords addObject: newRecord];
232       oldRecord = [oldRecords nextObject];
233     }
234
235   return newRecords;
236 }
237
238 - (NSArray *) lookupContactsWithFilter: (NSString *) filter
239                                 sortBy: (NSString *) sortKey
240                               ordering: (NSComparisonResult) sortOrdering
241 {
242   NSArray *records, *result;
243   EOSortOrdering *ordering;
244
245   result = nil;
246
247   if (filter && [filter length] > 0)
248     {
249       records = [self _flattenedRecords:
250                         [ldapSource fetchContactsMatching: filter]];
251       ordering
252         = [EOSortOrdering sortOrderingWithKey: sortKey
253                           selector: ((sortOrdering == NSOrderedDescending)
254                                      ? EOCompareCaseInsensitiveDescending
255                                      : EOCompareCaseInsensitiveAscending)];
256       result
257         = [records sortedArrayUsingKeyOrderArray:
258                      [NSArray arrayWithObject: ordering]];
259     }
260
261   return result;
262 }
263
264 - (NSArray *) davResourceType
265 {
266   NSArray *rType, *groupDavCollection;
267
268   groupDavCollection = [NSArray arrayWithObjects: @"vcard-collection",
269                                 XMLNS_GROUPDAV, nil];
270   rType = [NSArray arrayWithObjects: @"collection", groupDavCollection, nil];
271
272   return rType;
273 }
274
275 - (NSString *) davContentType
276 {
277   return @"httpd/unix-directory";
278 }
279
280 - (BOOL) davIsCollection
281 {
282   return YES;
283 }
284
285 - (NSString *) davDisplayName
286 {
287   return displayName;
288 }
289
290 - (BOOL) isFolderish
291 {
292   return YES;
293 }
294
295 /* sorting */
296 - (NSComparisonResult) compare: (id) otherFolder
297 {
298   NSComparisonResult comparison;
299
300   if ([NSStringFromClass([otherFolder class])
301                         isEqualToString: @"SOGoContactGCSFolder"])
302     comparison = NSOrderedDescending;
303   else
304     comparison
305       = [[self displayName]
306           localizedCaseInsensitiveCompare: [otherFolder displayName]];
307
308   return comparison;
309 }
310
311 /* acls */
312 - (NSString *) ownerInContext: (WOContext *) noContext
313 {
314   return @"nobody";
315 }
316
317 /* TODO: this might change one day when we support LDAP acls */
318 - (NSArray *) aclsForUser: (NSString *) uid
319 {
320   return nil;
321 }
322
323 @end