]> git.sur5r.net Git - openldap/blob - libraries/libldap/vlvctrl.c
Changes from HEAD for beta
[openldap] / libraries / libldap / vlvctrl.c
1 /*
2  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5 /* Adapted for inclusion into OpenLDAP by Kurt D. Zeilenga */
6 /*---
7  * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
8  *
9  * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
10  * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
11  * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
12  * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
13  * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
14  * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
15  * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
16  * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
17  *---*/
18 /* Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License
19  * can be found in the file "build/LICENSE-2.0.1" in this distribution
20  * of OpenLDAP Software.
21  */
22 /*
23  * Portions Copyright (C) The Internet Society (1997)
24  * ASN.1 fragments are from RFC 2251; see RFC for full legal notices.
25  */
26
27 #include "portable.h"
28
29 #include <stdio.h>
30 #include <ac/stdlib.h>
31 #include <ac/string.h>
32 #include <ac/time.h>
33
34 #include "ldap-int.h"
35
36 #define LDAP_VLVBYINDEX_IDENTIFIER     0xa0L
37 #define LDAP_VLVBYVALUE_IDENTIFIER     0x81L
38 #define LDAP_VLVCONTEXT_IDENTIFIER     0x04L
39
40
41 /*---
42    ldap_create_vlv_control
43    
44    Create and encode the Virtual List View control.
45
46    ld        (IN)  An LDAP session handle, as obtained from a call to
47                                    ldap_init().
48    
49    vlvinfop  (IN)  The address of an LDAPVLVInfo structure whose contents 
50                                    are used to construct the value of the control
51                                    that is created.
52    
53    ctrlp     (OUT) A result parameter that will be assigned the address
54                                    of an LDAPControl structure that contains the 
55                                    VirtualListViewRequest control created by this function.
56                                    The memory occupied by the LDAPControl structure
57                                    SHOULD be freed when it is no longer in use by
58                                    calling ldap_control_free().
59                                           
60    
61    Ber encoding
62    
63    VirtualListViewRequest ::= SEQUENCE {
64                 beforeCount  INTEGER (0 .. maxInt),
65                 afterCount   INTEGER (0 .. maxInt),
66                 CHOICE {
67                                 byoffset [0] SEQUENCE, {
68                                 offset        INTEGER (0 .. maxInt),
69                                 contentCount  INTEGER (0 .. maxInt) }
70                                 [1] greaterThanOrEqual assertionValue }
71                 contextID     OCTET STRING OPTIONAL }
72           
73    
74    Note:  The first time the VLV control is created, the ldvlv_context
75                   field of the LDAPVLVInfo structure should be set to NULL.
76                   The context obtained from calling ldap_parse_vlv_control()
77                   should be used as the context in the next ldap_create_vlv_control
78                   call.
79
80  ---*/
81
82 int
83 ldap_create_vlv_control( LDAP *ld,
84                                                  LDAPVLVInfo *vlvinfop,
85                                                  LDAPControl **ctrlp )
86 {
87         ber_tag_t tag;
88         BerElement *ber;
89
90         assert( ld != NULL );
91         assert( LDAP_VALID( ld ) );
92         assert( vlvinfop != NULL );
93         assert( ctrlp != NULL );
94
95         if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
96                 ld->ld_errno = LDAP_NO_MEMORY;
97                 return(LDAP_NO_MEMORY);
98         }
99
100         tag = ber_printf(ber, "{ii" /*}*/,
101                 vlvinfop->ldvlv_before_count,
102                 vlvinfop->ldvlv_after_count);
103         if( tag == LBER_ERROR ) goto exit;
104
105         if (vlvinfop->ldvlv_attrvalue == NULL) {
106                 tag = ber_printf(ber, "t{iiN}",
107                         LDAP_VLVBYINDEX_IDENTIFIER,
108                         vlvinfop->ldvlv_offset,
109                         vlvinfop->ldvlv_count);
110                 if( tag == LBER_ERROR ) goto exit;
111
112         } else {
113                 tag = ber_printf(ber, "tO",
114                         LDAP_VLVBYVALUE_IDENTIFIER,
115                         vlvinfop->ldvlv_attrvalue);
116                 if( tag == LBER_ERROR ) goto exit;
117         }
118
119         if (vlvinfop->ldvlv_context) {
120                 tag = ber_printf(ber, "tO",
121                         LDAP_VLVCONTEXT_IDENTIFIER,
122                         vlvinfop->ldvlv_context);
123                 if( tag == LBER_ERROR ) goto exit;
124         }
125
126         tag = ber_printf(ber, /*{*/ "N}"); 
127         if( tag == LBER_ERROR ) goto exit;
128
129         ld->ld_errno = ldap_create_control(     LDAP_CONTROL_VLVREQUEST,
130                 ber, 1, ctrlp);
131
132         ber_free(ber, 1);
133         return(ld->ld_errno);
134
135 exit:
136         ber_free(ber, 1);
137         ld->ld_errno = LDAP_ENCODING_ERROR;
138         return(ld->ld_errno);
139 }
140
141
142 /*---
143    ldap_parse_vlv_control
144    
145    Decode the Virtual List View control return information.
146
147    ld           (IN)   An LDAP session handle.
148    
149    ctrls        (IN)   The address of a NULL-terminated array of 
150                                            LDAPControl structures, typically obtained 
151                                            by a call to ldap_parse_result().
152    
153    target_posp  (OUT)  This result parameter is filled in with the list
154                                            index of the target entry.  If this parameter is
155                                            NULL, the target position is not returned.
156    
157    list_countp  (OUT)  This result parameter is filled in with the server's
158                                            estimate of the size of the list.  If this parameter
159                                            is NULL, the size is not returned.
160    
161    contextp     (OUT)  This result parameter is filled in with the address
162                                            of a struct berval that contains the server-
163                                            generated context identifier if one was returned by
164                                            the server.  If the server did not return a context
165                                            identifier, this parameter will be set to NULL, even
166                                            if an error occured.
167                                            The returned context SHOULD be used in the next call
168                                            to create a VLV sort control.  The struct berval
169                                            returned SHOULD be disposed of by calling ber_bvfree()
170                                            when it is no longer needed.  If NULL is passed for
171                                            contextp, the context identifier is not returned.
172    
173    errcodep     (OUT)  This result parameter is filled in with the VLV
174                                            result code.  If this parameter is NULL, the result
175                                            code is not returned.  
176    
177    
178    Ber encoding
179    
180    VirtualListViewResponse ::= SEQUENCE {
181                 targetPosition    INTEGER (0 .. maxInt),
182                 contentCount     INTEGER (0 .. maxInt),
183                 virtualListViewResult ENUMERATED {
184                 success (0),
185                 operatonsError (1),
186                 unwillingToPerform (53),
187                 insufficientAccessRights (50),
188                 busy (51),
189                 timeLimitExceeded (3),
190                 adminLimitExceeded (11),
191                 sortControlMissing (60),
192                 offsetRangeError (61),
193                 other (80) },
194                 contextID     OCTET STRING OPTIONAL }
195    
196 ---*/
197
198 int
199 ldap_parse_vlv_control(
200         LDAP           *ld,
201         LDAPControl    **ctrls,
202         unsigned long  *target_posp,
203         unsigned long  *list_countp,
204         struct berval  **contextp,
205         int            *errcodep )
206 {
207         BerElement  *ber;
208         LDAPControl *pControl;
209         int i;
210         unsigned long pos, count, err;
211         ber_tag_t tag, berTag;
212         ber_len_t berLen;
213
214         assert( ld != NULL );
215         assert( LDAP_VALID( ld ) );
216
217         if (contextp) {
218                 *contextp = NULL;        /* Make sure we return a NULL if error occurs. */
219         }
220
221         if (ctrls == NULL) {
222                 ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
223                 return(ld->ld_errno);
224         }
225
226         /* Search the list of control responses for a VLV control. */
227         for (i=0; ctrls[i]; i++) {
228                 pControl = ctrls[i];
229                 if (!strcmp(LDAP_CONTROL_VLVRESPONSE, pControl->ldctl_oid))
230                         goto foundVLVControl;
231         }
232
233         /* No sort control was found. */
234         ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
235         return(ld->ld_errno);
236
237 foundVLVControl:
238         /* Create a BerElement from the berval returned in the control. */
239         ber = ber_init(&pControl->ldctl_value);
240
241         if (ber == NULL) {
242                 ld->ld_errno = LDAP_NO_MEMORY;
243                 return(ld->ld_errno);
244         }
245
246         /* Extract the data returned in the control. */
247         tag = ber_scanf(ber, "{iie" /*}*/, &pos, &count, &err);
248
249         if( tag == LBER_ERROR) {
250                 ber_free(ber, 1);
251                 ld->ld_errno = LDAP_DECODING_ERROR;
252                 return(ld->ld_errno);
253         }
254
255
256         /* Since the context is the last item encoded, if caller doesn't want
257            it returned, don't decode it. */
258         if (contextp) {
259                 if (LDAP_VLVCONTEXT_IDENTIFIER == ber_peek_tag(ber, &berLen)) {
260                         tag = ber_scanf(ber, "tO", &berTag, contextp);
261
262                         if( tag == LBER_ERROR) {
263                                 ber_free(ber, 1);
264                                 ld->ld_errno = LDAP_DECODING_ERROR;
265                                 return(ld->ld_errno);
266                         }
267                 }
268         }
269
270         ber_free(ber, 1);
271
272         /* Return data to the caller for items that were requested. */
273         if (target_posp) {
274                 *target_posp = pos;
275         }
276         if (list_countp) {
277                 *list_countp = count;
278         }
279         if (errcodep) {
280                 *errcodep = err;
281         }
282
283         ld->ld_errno = LDAP_SUCCESS;
284         return(ld->ld_errno);
285 }