2 Copyright (C) 2004-2005 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #import <Foundation/NSArray.h>
23 #import <Foundation/NSString.h>
24 #import <NGObjWeb/NSException+HTTP.h>
25 #import <NGObjWeb/SoObject+SoDAV.h>
26 #import <NGObjWeb/WOContext.h>
27 #import <NGObjWeb/WORequest.h>
28 #import <NGExtensions/NSObject+Logs.h>
29 #import <EOControl/EOQualifier.h>
30 #import <EOControl/EOSortOrdering.h>
31 #import <GDLContentStore/GCSFolder.h>
33 #import "SOGoContactGCSEntry.h"
34 #import "SOGoContactGCSFolder.h"
36 #define folderListingFields [NSArray arrayWithObjects: @"c_name", @"c_cn", \
37 @"c_givenname", @"c_screenname", \
38 @"c_o", @"c_mail", @"c_telephonenumber", \
41 @implementation SOGoContactGCSFolder
43 + (id <SOGoContactFolder>) contactFolderWithName: (NSString *) aName
44 andDisplayName: (NSString *) aDisplayName
45 inContainer: (SOGoObject *) aContainer
47 SOGoContactGCSFolder *folder;
49 folder = [[self alloc] initWithName: aName
50 andDisplayName: aDisplayName
51 inContainer: aContainer];
59 [displayName release];
63 - (id <SOGoContactFolder>) initWithName: (NSString *) newName
64 andDisplayName: (NSString *) newDisplayName
65 inContainer: (SOGoObject *) newContainer
67 if ((self = [self initWithName: newName
68 inContainer: newContainer]))
69 ASSIGN (displayName, newDisplayName);
74 - (BOOL) folderIsMandatory
76 return [nameInContainer isEqualToString: @"personal"];
79 - (NSString *) displayName
86 - (id <SOGoContactObject>) lookupContactWithId: (NSString *) recordId
88 SOGoContactGCSEntry *contact;
90 if ([recordId length] > 0)
91 contact = [SOGoContactGCSEntry objectWithName: recordId
99 - (id) lookupName: (NSString *) _key
100 inContext: (WOContext *) _ctx
101 acquire: (BOOL) _flag
107 /* first check attributes directly bound to the application */
108 obj = [super lookupName:_key inContext:_ctx acquire:NO];
111 if ([[[_ctx request] method] isEqualToString: @"PUT"])
113 if ([_key isEqualToString: @"PUT"])
116 obj = [SOGoContactGCSEntry objectWithName: _key
120 obj = [self lookupContactWithId: _key];
122 // if (!(obj || isPut))
123 // obj = [NSException exceptionWithHTTPStatus:404 /* Not Found */];
126 // if ([[self ocsFolder] versionOfContentWithName:_key])
128 // return [self contactWithName:_key inContext:_ctx];
131 /* return 404 to stop acquisition */
136 - (EOQualifier *) _qualifierForFilter: (NSString *) filter
139 EOQualifier *qualifier;
141 if (filter && [filter length] > 0)
143 qs = [NSString stringWithFormat:
144 @"(c_sn isCaseInsensitiveLike: '%@%%') OR "
145 @"(c_givenname isCaseInsensitiveLike: '%@%%') OR "
146 @"(c_mail isCaseInsensitiveLike: '%@%%') OR "
147 @"(c_telephonenumber isCaseInsensitiveLike: '%%%@%%')",
148 filter, filter, filter, filter];
149 qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
157 - (NSArray *) _flattenedRecords: (NSArray *) records
159 NSMutableArray *newRecords;
160 NSEnumerator *oldRecords;
161 NSDictionary *oldRecord;
162 NSMutableDictionary *newRecord;
165 newRecords = [NSMutableArray arrayWithCapacity: [records count]];
167 oldRecords = [records objectEnumerator];
168 oldRecord = [oldRecords nextObject];
171 newRecord = [NSMutableDictionary new];
172 [newRecord autorelease];
174 [newRecord setObject: [oldRecord objectForKey: @"c_name"]
176 [newRecord setObject: [oldRecord objectForKey: @"c_name"]
179 data = [oldRecord objectForKey: @"c_cn"];
182 [newRecord setObject: data
183 forKey: @"displayName"];
185 data = [oldRecord objectForKey: @"c_mail"];
188 [newRecord setObject: data forKey: @"mail"];
190 data = [oldRecord objectForKey: @"c_screenname"];
193 [newRecord setObject: data forKey: @"screenName"];
195 data = [oldRecord objectForKey: @"c_o"];
198 [newRecord setObject: data forKey: @"org"];
200 data = [oldRecord objectForKey: @"c_telephonenumber"];
203 [newRecord setObject: data forKey: @"phone"];
205 [newRecords addObject: newRecord];
206 oldRecord = [oldRecords nextObject];
212 - (NSArray *) lookupContactsWithFilter: (NSString *) filter
213 sortBy: (NSString *) sortKey
214 ordering: (NSComparisonResult) sortOrdering
216 NSArray *fields, *dbRecords, *records;
217 EOQualifier *qualifier;
218 EOSortOrdering *ordering;
220 // NSLog (@"fetching records matching '%@', sorted by '%@' in order %d",
221 // filter, sortKey, sortOrdering);
223 fields = folderListingFields;
224 qualifier = [self _qualifierForFilter: filter];
225 dbRecords = [[self ocsFolder] fetchFields: fields
226 matchingQualifier: qualifier];
227 if ([dbRecords count] > 0)
229 records = [self _flattenedRecords: dbRecords];
231 = [EOSortOrdering sortOrderingWithKey: sortKey
232 selector: ((sortOrdering == NSOrderedDescending)
233 ? EOCompareCaseInsensitiveDescending
234 : EOCompareCaseInsensitiveAscending)];
236 = [records sortedArrayUsingKeyOrderArray:
237 [NSArray arrayWithObject: ordering]];
242 // [self errorWithFormat:@"(%s): fetch failed!", __PRETTY_FUNCTION__];
244 //[self debugWithFormat:@"fetched %i records.", [records count]];
248 - (NSArray *) davNamespaces
250 return [NSArray arrayWithObject: @"urn:ietf:params:xml:ns:carddav"];
253 - (NSArray *) davComplianceClassesInContext: (id)_ctx
255 NSMutableArray *classes;
256 NSArray *primaryClasses;
258 classes = [NSMutableArray new];
259 [classes autorelease];
261 primaryClasses = [super davComplianceClassesInContext: _ctx];
263 [classes addObjectsFromArray: primaryClasses];
264 [classes addObject: @"access-control"];
265 [classes addObject: @"addressbook-access"];
270 - (NSString *) groupDavResourceType
272 return @"vcard-collection";
275 - (NSException *) delete
277 return (([nameInContainer isEqualToString: @"personal"])
278 ? [NSException exceptionWithHTTPStatus: 403
279 reason: @"the 'personal' folder cannot be deleted"]
285 // - (id) GETAction: (id)_ctx
287 // // TODO: I guess this should really be done by SOPE (redirect to
288 // // default method)
292 // uri = [[_ctx request] uri];
293 // if (![uri hasSuffix:@"/"]) uri = [uri stringByAppendingString:@"/"];
294 // uri = [uri stringByAppendingString:@"view"];
296 // r = [_ctx response];
297 // [r setStatus:302 /* moved */];
298 // [r setHeader:uri forKey:@"location"];
304 - (NSString *) folderType
309 - (NSString *) outlookFolderClass
311 return @"IPF.Contact";
314 @end /* SOGoContactGCSFolder */