2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
6 SOPE 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 SOPE 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 SOPE; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #include "NGLdapSearchResultEnumerator.h"
23 #include "NGLdapConnection+Private.h"
24 #include "NGLdapAttribute.h"
25 #include "NGLdapEntry.h"
30 @implementation NGLdapSearchResultEnumerator
32 - (id)initWithConnection:(NGLdapConnection *)_con messageID:(int)_mid {
33 self->connection = [_con retain];
34 self->handle = [_con ldapHandle];
36 self->startTime = [[NSDate date] timeIntervalSince1970];
41 [self->connection release];
51 - (NSTimeInterval)duration {
52 return [[NSDate date] timeIntervalSince1970] - self->startTime;
65 res = ldap_abandon(self->handle, self->msgid);
68 [self->connection release]; self->connection = nil;
72 - (NSArray *)_attributesFromResult:(LDAPMessage *)result {
73 NSMutableArray *attributes;
77 attributes = [[NSMutableArray alloc] initWithCapacity:32];
79 for (attr = ldap_first_attribute(self->handle, result, &ber);
81 free(attr), attr = ldap_next_attribute(self->handle, result, ber)) {
83 NGLdapAttribute *attribute;
84 struct berval **values;
88 if (!(key = [[NSString alloc] initWithCString:attr]))
89 /* missing attribute name */
94 if ((values = ldap_get_values_len(self->handle, result, attr)) == NULL) {
95 ovalues = [[NSArray alloc] init];
97 else if ((valueCount = ldap_count_values_len(values)) == 1) {
100 value = [[NSData alloc] initWithBytes:values[0]->bv_val
101 length:values[0]->bv_len];
103 ovalues = [[NSArray alloc] initWithObjects:&value count:1];
111 a = [[NSMutableArray alloc] initWithCapacity:valueCount];
113 for (j = 0; values[j]; j++) {
116 data = [[NSData alloc] initWithBytes:values[j]->bv_val
117 length:values[j]->bv_len];
126 ldap_value_free_len(values);
130 /* create attribute */
133 [[NGLdapAttribute alloc] initWithAttributeName:key values:ovalues];
135 [key release]; key = nil;
136 [ovalues release]; ovalues = nil;
138 [attributes addObject:attribute];
159 if (self->handle == NULL)
166 if (self->timeout > 0) {
167 to.tv_sec = self->timeout;
168 to.tv_sec = (long)(self->timeout * 1000.0) - (to.tv_sec * 1000);
172 res = ldap_result(self->handle, self->msgid, 0, top, &msg);
176 #if defined(LDAP_RES_SEARCH_REFERENCE)
177 case LDAP_RES_SEARCH_REFERENCE: {
182 rres = ldap_parse_reference(self->handle, msg, &rptr, &ctrl,
183 0 /* don't free msg */);
184 if (rres == LDAP_SUCCESS) {
188 NSLog(@"%s: couldn't parse result reference ..", __PRETTY_FUNCTION__);
191 NSLog(@"WARNING: doesn't support result references yet ..");
193 if (rptr) ldap_value_free(rptr);
194 if (ctrl) ldap_controls_free(ctrl);
200 case LDAP_RES_SEARCH_ENTRY: {
203 if ((resultCount = ldap_count_entries(self->handle, msg)) == -1) {
207 err = ldap_result2error(self->handle, msg, 1 /* free msg */);
209 [[self->connection _exceptionForErrorCode:err
210 operation:@"count-fetch"
215 else if (resultCount == 1) {
221 if ((result = ldap_first_entry(self->handle, msg)) == NULL) {
222 /* could not get entry */
225 err = ldap_result2error(self->handle, msg, 1 /* free msg */);
227 [[self->connection _exceptionForErrorCode:resultCount
235 /* get distinguished name */
237 if ((tmp = ldap_get_dn(self->handle, result))) {
239 dn = [[[NSString alloc] initWithUTF8String:tmp] autorelease];
242 fprintf(stderr, "Got exception %s while NSUTF8StringEncoding, "
243 "use defaultCStringEncoding",
244 [[localException description] cString]);
250 dn = [[[NSString alloc] initWithCString:tmp] autorelease];
254 /* get all attributes */
256 attributes = [self _attributesFromResult:result];
259 // TODO: ldap_msgfree(result); // do not release result-msg ???
263 record = [[NGLdapEntry alloc] initWithDN:dn attributes:attributes];
265 [attributes release]; attributes = nil;
267 else if (resultCount == 0) {
268 /* no more results */
274 case LDAP_RES_SEARCH_RESULT:
276 [self->connection release]; self->connection = nil;
280 NSLog(@"unexpected msg-code: %X", res);
290 return [record autorelease];
295 - (NSString *)description {
298 s = [NSMutableString stringWithCapacity:100];
299 [s appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
301 [s appendFormat:@" msgid=%i", [self messageID]];
302 [s appendFormat:@" duration=%.2fs", [self duration]];
303 [s appendFormat:@" index=%i", [self index]];
305 [s appendString:@">"];
310 @end /* LDAPResultEnumerator */