]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/search.c
Fix unportable code. Thanks, Hallvard.
[openldap] / servers / slapd / back-ldap / search.c
1 /* search.c - ldap backend search function */
2
3 /*
4  * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
5  * 
6  * Permission is granted to anyone to use this software for any purpose
7  * on any computer system, and to alter it and redistribute it, subject
8  * to the following restrictions:
9  * 
10  * 1. The author is not responsible for the consequences of use of this
11  *    software, no matter how awful, even if they arise from flaws in it.
12  * 
13  * 2. The origin of this software must not be misrepresented, either by
14  *    explicit claim or by omission.  Since few users ever read sources,
15  *    credits should appear in the documentation.
16  * 
17  * 3. Altered versions must be plainly marked as such, and must not be
18  *    misrepresented as being the original software.  Since few users
19  *    ever read sources, credits should appear in the documentation.
20  * 
21  * 4. This notice may not be removed or altered.
22  */
23
24 #include "portable.h"
25
26 #include <stdio.h>
27
28 #include <ac/socket.h>
29 #include <ac/string.h>
30 #include <ac/time.h>
31
32 #include "slap.h"
33 #include "back-ldap.h"
34
35 int
36 ldap_back_search(
37     Backend     *be,
38     Connection  *conn,
39     Operation   *op,
40     char        *base,
41     int         scope,
42     int         deref,
43     int         size,
44     int         time,
45     Filter      *filter,
46     char        *filterstr,
47     char        **attrs,
48     int         attrsonly
49 )
50 {
51         struct ldapinfo *li = (struct ldapinfo *) be->be_private;
52         struct ldapconn *lc;
53         struct timeval  tv;
54         LDAPMessage             *res, *e;
55         int                     i, rc, msgid, sres = LDAP_SUCCESS; 
56         char *match = NULL, *err = NULL;
57
58         lc = ldap_back_getconn(li, conn, op);
59         if (!lc)
60                 return( -1 );
61
62         if (deref != -1)
63                 ldap_set_option( lc->ld, LDAP_OPT_DEREF, (void *)&deref);
64         if (time != -1)
65                 ldap_set_option( lc->ld, LDAP_OPT_TIMELIMIT, (void *)&time);
66         if (size != -1)
67                 ldap_set_option( lc->ld, LDAP_OPT_SIZELIMIT, (void *)&size);
68         if (!lc->bound) {
69                 ldap_back_dobind(lc, op);
70                 if (!lc->bound)
71                         return( -1 );
72         }
73
74         if ((msgid = ldap_search(lc->ld, base, scope, filterstr, attrs,
75                 attrsonly)) == -1)
76 fail:           return( ldap_back_op_result(lc, op) );
77
78         /* We pull apart the ber result, stuff it into a slapd entry, and
79          * let send_search_entry stuff it back into ber format. Slow & ugly,
80          * but this is necessary for version matching, and for ACL processing.
81          */
82         
83         for (i=0, rc=0; rc != -1;
84                 rc = ldap_result(lc->ld, LDAP_RES_ANY, 0, &tv, &res)) {
85                 int ab;
86
87                 /* check for abandon */
88                 ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
89                 ab = op->o_abandon;
90                 ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
91
92                 if (ab) {
93                         ldap_abandon(lc->ld, msgid);
94                 } else if (rc == 0) {
95                         tv.tv_sec = 0;
96                         tv.tv_usec = 100000;
97                         ldap_pvt_thread_yield();
98                         continue;
99                 } else if (rc == LDAP_RES_SEARCH_ENTRY) {
100                         e = ldap_first_entry(lc->ld,res);
101                         ldap_send_entry(be, op, lc, e, attrs, attrsonly);
102                         i++;
103                 } else {
104                         sres = ldap_result2error(lc->ld, res, 1);
105                         ldap_get_option(lc->ld, LDAP_OPT_ERROR_STRING, &err);
106                         ldap_get_option(lc->ld, LDAP_OPT_MATCHED_DN, &match);
107                         rc = 0;
108                 }
109                 ldap_msgfree(res);
110                 if (ab)
111                         return (0);
112                 else if (rc == 0)
113                         break;
114         }
115
116         if (rc == -1)
117                 goto fail;
118
119         send_search_result( conn, op, sres,
120                 match, err, NULL, NULL, i );
121         if (match)
122                 free(match);
123         if (err)
124                 free(err);
125         return( 0 );
126 }
127
128 ldap_send_entry(
129         Backend *be,
130         Operation *op,
131         struct ldapconn *lc,
132         LDAPMessage *e,
133         char **attrs,
134         int attrsonly
135 )
136 {
137         char *a;
138         Entry ent;
139         BerElement *ber = NULL;
140         Attribute *attr, **attrp;
141         struct berval *dummy = NULL;
142
143         ent.e_dn = ldap_get_dn(lc->ld, e);
144         ent.e_ndn = ch_strdup( ent.e_dn);
145         (void) dn_normalize_case( ent.e_ndn );
146         ent.e_id = 0;
147         ent.e_attrs = 0;
148         ent.e_private = 0;
149         attrp = &ent.e_attrs;
150
151         for (a = ldap_first_attribute(lc->ld, e, &ber); a;
152                 a = ldap_next_attribute(lc->ld, e, ber)) {
153                 attr = (Attribute *)ch_malloc( sizeof(Attribute) );
154                 attr->a_next = 0;
155                 attr->a_type = ch_strdup(a);
156                 attr->a_syntax = attr_syntax(a);
157                 attr->a_vals = ldap_get_values_len(lc->ld, e, a);
158                 if (!attr->a_vals)
159                         attr->a_vals = &dummy;
160                 *attrp = attr;
161                 attrp = &attr->a_next;
162         }
163         send_search_entry( be, lc->conn, op, &ent, attrs, attrsonly, NULL );
164         for (;ent.e_attrs;) {
165                 attr=ent.e_attrs;
166                 ent.e_attrs = attr->a_next;
167                 free(attr->a_type);
168                 if (attr->a_vals != &dummy)
169                         ber_bvecfree(attr->a_vals);
170                 free(attr);
171         }
172         if (ber)
173                 ber_free(ber,0);
174 }