1 /* NSObject+CardDAV.m - this file is part of SOGo
3 * Copyright (C) 2007 Inverse groupe conseil
5 * Author: Ludovic Marcotte <ludovic@inverse.ca>
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)
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.
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.
23 #import <Foundation/NSArray.h>
25 #import <NGObjWeb/WOContext.h>
26 #import <NGObjWeb/WORequest.h>
27 #import <NGObjWeb/WOResponse.h>
28 #import <NGExtensions/NSString+misc.h>
29 #import <DOM/DOMProtocols.h>
30 #import <SaxObjC/SaxObjC.h>
31 #import <SaxObjC/XMLNamespaces.h>
33 #import "SOGoContactFolder.h"
34 #import "SOGoContactGCSEntry.h"
36 @implementation SOGoFolder (CardDAV)
38 - (void) _appendComponentsMatchingFilters: (NSArray *) filters
39 toResponse: (WOResponse *) response
40 context: (id) localContext
42 unsigned int count, max;
43 NSDictionary *currentFilter, *contact;
44 NSEnumerator *contacts;
46 SOGoObject <SOGoContactFolder> *o;
48 o = (id<SOGoContactFolder>)self;
49 baseURL = [o baseURLInContext: localContext];
51 max = [filters count];
52 for (count = 0; count < max; count++)
54 currentFilter = [filters objectAtIndex: count];
55 contacts = [[o lookupContactsWithFilter: [[currentFilter allValues] lastObject]
56 sortBy: @"c_givenname"
57 ordering: NSOrderedDescending]
60 while ((contact = [contacts nextObject]))
62 [o appendObject: contact
64 toREPORTResponse: response];
69 - (BOOL) _isValidFilter: (NSString *) theString
71 if ([theString caseInsensitiveCompare: @"sn"] == NSOrderedSame)
74 if ([theString caseInsensitiveCompare: @"givenname"] == NSOrderedSame)
77 if ([theString caseInsensitiveCompare: @"mail"] == NSOrderedSame)
80 if ([theString caseInsensitiveCompare: @"telephonenumber"] == NSOrderedSame)
86 - (NSDictionary *) _parseContactFilter: (id <DOMElement>) filterElement
88 NSMutableDictionary *filterData;
89 id <DOMNode> parentNode;
90 id <DOMNodeList> ranges;
92 parentNode = [filterElement parentNode];
94 if ([[parentNode tagName] isEqualToString: @"filter"] &&
95 [self _isValidFilter: [filterElement attribute: @"name"]])
97 ranges = [filterElement getElementsByTagName: @"text-match"];
99 if ([(NSArray *)ranges count] && [(NSArray *)[[ranges objectAtIndex: 0] childNodes] count])
101 filterData = [NSMutableDictionary new];
102 [filterData autorelease];
103 [filterData setObject: [[(NSArray *)[[ranges objectAtIndex: 0] childNodes] lastObject] data]
104 forKey: [filterElement attribute: @"name"]];
113 - (NSArray *) _parseContactFilters: (id <DOMElement>) parentNode
115 NSEnumerator *children;
117 NSMutableArray *filters;
118 NSDictionary *filter;
120 filters = [[NSMutableArray new] autorelease];
122 children = [[parentNode getElementsByTagName: @"prop-filter"]
125 node = [children nextObject];
129 filter = [self _parseContactFilter: node];
131 [filters addObject: filter];
132 node = [children nextObject];
138 - (id) davAddressbookQuery: (id) queryContext
142 id <DOMDocument> document;
144 r = [queryContext response];
146 [r setContentEncoding: NSUTF8StringEncoding];
147 [r setHeader: @"text/xml; charset=\"utf-8\"" forKey: @"content-type"];
148 [r setHeader: @"no-cache" forKey: @"pragma"];
149 [r setHeader: @"no-cache" forKey: @"cache-control"];
150 [r appendContentString:@"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"];
151 [r appendContentString: @"<D:multistatus xmlns:D=\"DAV:\""
152 @" xmlns:C=\"urn:ietf:params:xml:ns:carddav\">\r\n"];
154 document = [[queryContext request] contentAsDOMDocument];
155 filters = [self _parseContactFilters: [document documentElement]];
157 [self _appendComponentsMatchingFilters: filters
159 context: queryContext];
160 [r appendContentString:@"</D:multistatus>\r\n"];