]> err.no Git - scalable-opengroupware.org/blob - UI/Contacts/UIxContactFoldersView.m
45e98dd1f201672d131907ac1a9f81a97f61cb94
[scalable-opengroupware.org] / UI / Contacts / UIxContactFoldersView.m
1 /* UIxContactFoldersView.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/NSString.h>
24
25 #import <NGObjWeb/NSException+HTTP.h>
26 #import <NGObjWeb/SoObject.h>
27 #import <NGObjWeb/WOResponse.h>
28 #import <NGObjWeb/WOContext.h>
29
30 #import <GDLContentStore/GCSFolder.h>
31 #import <GDLContentStore/GCSFolderManager.h>
32
33 #import <SoObjects/SOGo/SOGoUser.h>
34 #import <SoObjects/SOGo/NSString+Utilities.h>
35 #import <SoObjects/Contacts/SOGoContactFolders.h>
36 #import <SoObjects/Contacts/SOGoContactFolder.h>
37 #import <SoObjects/Contacts/SOGoContactGCSFolder.h>
38 #import <SoObjects/Contacts/SOGoContactLDAPFolder.h>
39
40 #import "common.h"
41
42 #import "UIxContactFoldersView.h"
43
44 @implementation UIxContactFoldersView
45
46 - (id) _selectActionForApplication: (NSString *) actionName
47 {
48   SOGoContactFolders *folders;
49   NSString *url, *action;
50   WORequest *request;
51
52   folders = [self clientObject];
53   action = [NSString stringWithFormat: @"../%@/%@",
54                      [folders defaultSourceName],
55                      actionName];
56
57   request = [[self context] request];
58
59   url = [[request uri] composeURLWithAction: action
60                        parameters: [self queryParameters]
61                        andHash: NO];
62
63   return [self redirectToLocation: url];
64 }
65
66 - (id) defaultAction
67 {
68   return [self _selectActionForApplication: @"view"];
69 }
70
71 - (id) newAction
72 {
73   return [self _selectActionForApplication: @"new"];
74 }
75
76 - (id <WOActionResults>) newAbAction
77 {
78   id <WOActionResults> response;
79   NSString *name;
80
81   name = [self queryParameterForKey: @"name"];
82   if ([name length] > 0)
83     response = [[self clientObject] newFolderWithName: name];
84   else
85     response = [NSException exceptionWithHTTPStatus: 400
86                             reason: @"The name is missing"];
87   
88   return response;
89 }
90
91 - (id) selectForMailerAction
92 {
93   return [self _selectActionForApplication: @"mailer-contacts"];
94 }
95
96 - (NSArray *) _searchResults: (NSString *) contact
97              ldapFoldersOnly: (BOOL) ldapFoldersOnly
98 {
99   NSMutableArray *results;
100   SOGoContactFolders *topFolder;
101   NSEnumerator *sogoContactFolders;
102   id <SOGoContactFolder> currentFolder;
103
104   results = [NSMutableArray new];
105   [results autorelease];
106
107   topFolder = [self clientObject];
108   sogoContactFolders = [[topFolder contactFolders] objectEnumerator];
109   currentFolder = [sogoContactFolders nextObject];
110   while (currentFolder)
111     {
112       if (!ldapFoldersOnly
113           || [currentFolder isKindOfClass: [SOGoContactLDAPFolder class]])
114         [results addObjectsFromArray: [currentFolder
115                                         lookupContactsWithFilter: contact
116                                         sortBy: @"cn"
117                                         ordering: NSOrderedAscending]];
118       currentFolder = [sogoContactFolders nextObject];
119     }
120   [topFolder release];
121
122   return results;
123 }
124
125 - (NSString *) _emailForResult: (NSDictionary *) result
126 {
127   NSMutableString *email;
128   NSString *name, *mail;
129
130   email = [NSMutableString string];
131   name = [result objectForKey: @"displayName"];
132   if (![name length])
133     name = [result objectForKey: @"cn"];
134   mail = [result objectForKey: @"mail"];
135   if ([name length])
136     [email appendFormat: @"%@ <%@>", name, mail];
137   else
138     [email appendString: mail];
139
140   return email;
141 }
142
143 - (NSDictionary *) _nextResultWithUid: (NSEnumerator *) results
144 {
145   NSDictionary *result, *possibleResult;
146
147   result = nil;
148   possibleResult = [results nextObject];
149   while (possibleResult && !result)
150     if ([[possibleResult objectForKey: @"c_uid"] length])
151       result = possibleResult;
152     else
153       possibleResult = [results nextObject];
154
155   return result;
156 }
157
158 - (WOResponse *) _responseForResults: (NSArray *) results
159 {
160   WOResponse *response;
161   NSString *email, *responseString, *uid;
162   NSDictionary *result;
163
164   response = [context response];
165
166   if ([results count])
167     {
168       result = [self _nextResultWithUid: [results objectEnumerator]];
169       if (!result)
170         result = [results objectAtIndex: 0];
171       email = [self _emailForResult: result];
172       uid = [result objectForKey: @"c_uid"];
173       if ([uid length] == 0)
174         uid = @"";
175       responseString = [NSString stringWithFormat: @"%@:%@",
176                                  uid, email];
177       [response setStatus: 200];
178       [response setHeader: @"text/plain; charset=iso-8859-1"
179                 forKey: @"Content-Type"];
180       [response appendContentString: responseString];
181     }
182   else
183     [response setStatus: 404];
184
185   return response;
186 }
187
188 - (id <WOActionResults>) contactSearchAction
189 {
190   NSString *contact;
191   id <WOActionResults> result;
192   BOOL ldapFoldersOnly;
193
194   contact = [self queryParameterForKey: @"search"];
195   ldapFoldersOnly = [[self queryParameterForKey: @"ldap-only"] boolValue];
196   if ([contact length] > 0)
197     result
198       = [self _responseForResults: [self _searchResults: contact
199                                          ldapFoldersOnly: ldapFoldersOnly]];
200   else
201     result = [NSException exceptionWithHTTPStatus: 400
202                           reason: @"missing 'search' parameter"];
203   
204   return result;
205 }
206
207 - (NSArray *) _gcsFoldersFromFolder: (SOGoContactFolders *) contactFolders
208 {
209   NSMutableArray *gcsFolders;
210   NSEnumerator *contactSubfolders;
211   SOGoContactGCSFolder *currentContactFolder;
212   NSString *folderName, *displayName;
213   NSMutableDictionary *currentDictionary;
214
215   gcsFolders = [NSMutableArray new];
216   [gcsFolders autorelease];
217
218   contactSubfolders = [[contactFolders contactFolders] objectEnumerator];
219   currentContactFolder = [contactSubfolders nextObject];
220   while (currentContactFolder)
221     {
222       if ([currentContactFolder
223             isKindOfClass: [SOGoContactGCSFolder class]])
224         {
225           folderName = [NSString stringWithFormat: @"/Contacts/%@",
226                                  [currentContactFolder nameInContainer]];
227           currentDictionary = [NSMutableDictionary new];
228           [currentDictionary autorelease];
229           displayName = [[currentContactFolder ocsFolder] folderName];
230           [currentDictionary setObject: displayName forKey: @"displayName"];
231           [currentDictionary setObject: folderName forKey: @"name"];
232           [currentDictionary setObject: @"contact" forKey: @"type"];
233           [gcsFolders addObject: currentDictionary];
234         }
235       currentContactFolder = [contactSubfolders nextObject];
236     }
237
238   return gcsFolders;
239 }
240
241 - (NSArray *) _foldersForUID: (NSString *) uid
242                       ofType: (NSString *) folderType
243 {
244   NSObject *topFolder, *userFolder;
245   SOGoContactFolders *contactFolders;
246   NSMutableArray *folders;
247   NSMutableDictionary *currentDictionary;
248
249   folders = [NSMutableArray new];
250   [folders autorelease];
251
252   topFolder = [[[self clientObject] container] container];
253   userFolder = [topFolder lookupName: uid inContext: context acquire: NO];
254
255   /* FIXME: should be moved in the SOGo* classes. Maybe by having a SOGoFolderManager. */
256 #warning this might need adjustments whenever we permit multiple calendar folders per-user
257   if ([folderType length] == 0 || [folderType isEqualToString: @"calendar"])
258     {
259       currentDictionary = [NSMutableDictionary new];
260       [currentDictionary autorelease];
261       [currentDictionary setObject: [self labelForKey: @"Calendar"]
262                          forKey: @"displayName"];
263       [currentDictionary setObject: @"/Calendar" forKey: @"name"];
264       [currentDictionary setObject: @"calendar" forKey: @"type"];
265       [folders addObject: currentDictionary];
266     }
267   if ([folderType length] == 0 || [folderType isEqualToString: @"contact"])
268     {
269       contactFolders = [userFolder lookupName: @"Contacts"
270                                    inContext: context acquire: NO];
271       [folders
272         addObjectsFromArray: [self _gcsFoldersFromFolder: contactFolders]];
273     }
274
275   return folders;
276 }
277
278 - (NSString *) _foldersStringForFolders: (NSEnumerator *) folders
279 {
280   NSMutableString *foldersString;
281   NSDictionary *currentFolder;
282
283   foldersString = [NSMutableString new];
284   [foldersString autorelease];
285
286   currentFolder = [folders nextObject];
287   while (currentFolder)
288     {
289       [foldersString appendFormat: @";%@:%@:%@",
290                      [currentFolder objectForKey: @"displayName"],
291                      [currentFolder objectForKey: @"name"],
292                      [currentFolder objectForKey: @"type"]];
293       currentFolder = [folders nextObject];
294     }
295
296   return foldersString;
297 }
298
299 - (WOResponse *) _foldersResponseForResults: (NSArray *) results
300                                    withType: (NSString *) folderType
301 {
302   WOResponse *response;
303   NSString *uid, *foldersString;
304   NSMutableString *responseString;
305   NSDictionary *result;
306   NSEnumerator *resultsEnum;
307   NSArray *folders;
308
309   response = [context response];
310
311   if ([results count])
312     {
313       [response setStatus: 200];
314       [response setHeader: @"text/plain; charset=iso-8859-1"
315                 forKey: @"Content-Type"];
316
317       responseString = [NSMutableString new];
318       resultsEnum = [results objectEnumerator];
319       result = [resultsEnum nextObject];
320       while (result)
321         {
322           uid = [result objectForKey: @"c_uid"];
323           folders = [self _foldersForUID: uid ofType: folderType];
324           foldersString
325             = [self _foldersStringForFolders: [folders objectEnumerator]];
326           [responseString appendFormat: @"%@:%@%@\n",
327                           uid, [self _emailForResult: result], foldersString];
328           result = [resultsEnum nextObject];
329         }
330       [response appendContentString: responseString];
331       [responseString release];
332     }
333   else
334     [response setStatus: 404];
335
336   return response;
337 }
338
339 - (id <WOActionResults>) foldersSearchAction
340 {
341   NSString *contact, *folderType;
342   id <WOActionResults> result;
343   BOOL ldapOnly;
344
345   contact = [self queryParameterForKey: @"search"];
346   if ([contact length] > 0)
347     {
348       ldapOnly = [[self queryParameterForKey: @"ldap-only"] boolValue];
349       folderType = [self queryParameterForKey: @"type"];
350       result = [self _foldersResponseForResults:
351                        [self _searchResults: contact
352                              ldapFoldersOnly: ldapOnly]
353                      withType: folderType];
354     }
355   else
356     result = [NSException exceptionWithHTTPStatus: 400
357                           reason: @"missing 'search' parameter"];
358
359   return result;
360 }
361
362 - (SOGoContactGCSFolder *) contactFolderForUID: (NSString *) uid
363 {
364   SOGoFolder *upperContainer;
365   SOGoUserFolder *userFolder;
366   SOGoContactFolders *contactFolders;
367   SOGoContactGCSFolder *contactFolder;
368   SoSecurityManager *securityManager;
369
370   upperContainer = [[[self clientObject] container] container];
371   userFolder = [SOGoUserFolder objectWithName: uid
372                                inContainer: upperContainer];
373   contactFolders = [SOGoContactFolders objectWithName: @"Contacts"
374                                        inContainer: userFolder];
375   contactFolder = [SOGoContactGCSFolder objectWithName: @"personal"
376                                         inContainer: contactFolders];
377   [contactFolder
378     setOCSPath: [NSString stringWithFormat: @"/Users/%@/Contacts/personal", uid]];
379   [contactFolder setOwner: uid];
380
381   securityManager = [SoSecurityManager sharedSecurityManager];
382
383   return (([securityManager validatePermission: SoPerm_AccessContentsInformation
384                             onObject: contactFolder
385                             inContext: context] == nil)
386           ? contactFolder : nil);
387 }
388
389 @end