/* NSObject+CardDAV.m - this file is part of SOGo * * Copyright (C) 2007-2015 Inverse inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #import #import #import #import #import #import #import #import #import #import #import #import "SOGoContactFolder.h" #import "SOGoContactGCSEntry.h" @implementation SOGoFolder (CardDAV) - (void) _appendObject: (NSDictionary *) object withBaseURL: (NSString *) baseURL toREPORTResponse: (WOResponse *) r { id component; NSString *name, *etagLine, *contactString; name = [object objectForKey: @"c_name"]; if ([name length]) { component = [self lookupName: name inContext: context acquire: NO]; if ([component isKindOfClass: [NSException class]]) { [self logWithFormat: @"Object with name '%@' not found. You likely have a LDAP configuration issue.", name]; return; } #warning we provide both "address-data" and "addressbook-data" for compatibility reasons, we should actually check which one has been queried [r appendContentString: @"" @""]; [r appendContentString: baseURL]; if (![baseURL hasSuffix: @"/"]) [r appendContentString: @"/"]; [r appendContentString: name]; [r appendContentString: @"" @"" @""]; etagLine = [NSString stringWithFormat: @"%@", [component davEntityTag]]; [r appendContentString: etagLine]; [r appendContentString: @""]; contactString = [[component contentAsString] safeStringByEscapingXMLString]; [r appendContentString: contactString]; [r appendContentString: @"" @""]; [r appendContentString: contactString]; [r appendContentString: @"" @"" @"HTTP/1.1 200 OK" @"" @""]; } } - (void) _appendComponentsMatchingFilters: (NSArray *) filters toResponse: (WOResponse *) response context: (id) localContext { unsigned int count,i , max; NSAutoreleasePool *pool; NSDictionary *currentFilter, *contact; NSEnumerator *contacts; NSString *baseURL, *domain; baseURL = [self baseURLInContext: localContext]; domain = [[localContext activeUser] domain]; max = [filters count]; for (count = 0; count < max; count++) { currentFilter = [filters objectAtIndex: count]; contacts = [[(id)self lookupContactsWithFilter: [[currentFilter allValues] lastObject] onCriteria: nil sortBy: @"c_givenname" ordering: NSOrderedDescending inDomain: domain] objectEnumerator]; pool = [[NSAutoreleasePool alloc] init]; i = 0; while ((contact = [contacts nextObject])) { [self _appendObject: contact withBaseURL: baseURL toREPORTResponse: response]; if (i % 10 == 0) { RELEASE(pool); pool = [[NSAutoreleasePool alloc] init]; } i++; } RELEASE(pool); } } - (BOOL) _isValidFilter: (NSString *) theString { NSString *newString; newString = [theString lowercaseString]; return ([newString isEqualToString: @"sn"] || [newString isEqualToString: @"givenname"] || [newString isEqualToString: @"email"] || [newString isEqualToString: @"mail"] || [newString isEqualToString: @"telephonenumber"]); } - (NSDictionary *) _parseContactFilter: (id ) filterElement { NSMutableDictionary *filterData; id parentNode; id ranges; filterData = nil; parentNode = [filterElement parentNode]; if ([[(id)parentNode tagName] isEqualToString: @"filter"] && [self _isValidFilter: [filterElement attribute: @"name"]]) { ranges = [filterElement getElementsByTagName: @"text-match"]; if ([(NSArray *) ranges count] && [(NSArray *) [[ranges objectAtIndex: 0] childNodes] count]) { filterData = [NSMutableDictionary dictionary]; [filterData setObject: [(NGDOMNode *)[ranges objectAtIndex: 0] textValue] forKey: [filterElement attribute: @"name"]]; } } return filterData; } - (NSArray *) _parseContactFilters: (id ) parentNode { NSEnumerator *children; id node; NSMutableArray *filters; NSDictionary *filter; filters = [NSMutableArray array]; children = [(NSArray *)[parentNode getElementsByTagName: @"prop-filter"] objectEnumerator]; while ((node = [children nextObject])) { filter = [self _parseContactFilter: node]; if (filter) [filters addObject: filter]; } // If no filters are provided, we return everything. if (![filters count]) { [filters addObject: [NSDictionary dictionaryWithObject: @"." forKey: @"email"]]; [filters addObject: [NSDictionary dictionaryWithObject: @"%" forKey: @"name"]]; } return filters; } /** foo */ - (id) davAddressbookQuery: (id) queryContext { WOResponse *r; NSArray *filters; id document; r = [queryContext response]; [r prepareDAVResponse]; [r appendContentString: @""]; document = [[queryContext request] contentAsDOMDocument]; filters = [self _parseContactFilters: [document documentElement]]; [self _appendComponentsMatchingFilters: filters toResponse: r context: queryContext]; [r appendContentString: @""]; return r; } @end