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