]> git.sur5r.net Git - openldap/blob - libraries/libldap/vlvctrl.c
Merge remote-tracking branch 'origin/mdb.master'
[openldap] / libraries / libldap / vlvctrl.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2012 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 /* Portions Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
16  *
17  * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
18  * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
19  * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
20  * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
21  * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
22  * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
23  * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
24  * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
25  *---
26  * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License
27  * can be found in the file "build/LICENSE-2.0.1" in this distribution
28  * of OpenLDAP Software.
29  */
30
31 #include "portable.h"
32
33 #include <stdio.h>
34 #include <ac/stdlib.h>
35 #include <ac/string.h>
36 #include <ac/time.h>
37
38 #include "ldap-int.h"
39
40 #define LDAP_VLVBYINDEX_IDENTIFIER     0xa0L
41 #define LDAP_VLVBYVALUE_IDENTIFIER     0x81L
42 #define LDAP_VLVCONTEXT_IDENTIFIER     0x04L
43
44
45 /*---
46    ldap_create_vlv_control
47    
48    Create and encode the Virtual List View control.
49
50    ld        (IN)  An LDAP session handle.
51    
52    vlvinfop  (IN)  The address of an LDAPVLVInfo structure whose contents 
53                                    are used to construct the value of the control
54                                    that is created.
55    
56    value     (OUT) A struct berval that contains the value to be assigned to the ldctl_value member
57                                    of an LDAPControl structure that contains the 
58                                    VirtualListViewRequest control.
59                                    The bv_val member of the berval structure
60                                    SHOULD be freed when it is no longer in use by
61                                    calling ldap_memfree().
62                                           
63    
64    Ber encoding
65    
66    VirtualListViewRequest ::= SEQUENCE {
67                 beforeCount  INTEGER (0 .. maxInt),
68                 afterCount   INTEGER (0 .. maxInt),
69                 CHOICE {
70                                 byoffset [0] SEQUENCE, {
71                                 offset        INTEGER (0 .. maxInt),
72                                 contentCount  INTEGER (0 .. maxInt) }
73                                 [1] greaterThanOrEqual assertionValue }
74                 contextID     OCTET STRING OPTIONAL }
75           
76    
77    Note:  The first time the VLV control is created, the ldvlv_context
78                   field of the LDAPVLVInfo structure should be set to NULL.
79                   The context obtained from calling ldap_parse_vlv_control()
80                   should be used as the context in the next ldap_create_vlv_control
81                   call.
82
83  ---*/
84
85 int
86 ldap_create_vlv_control_value(
87         LDAP *ld,
88         LDAPVLVInfo *vlvinfop,
89         struct berval *value )
90 {
91         ber_tag_t tag;
92         BerElement *ber;
93
94         if ( ld == NULL || vlvinfop == NULL || value == NULL ) {
95                 if ( ld )
96                         ld->ld_errno = LDAP_PARAM_ERROR;
97                 return LDAP_PARAM_ERROR;
98         }
99
100         assert( LDAP_VALID( ld ) );
101
102         value->bv_val = NULL;
103         value->bv_len = 0;
104         ld->ld_errno = LDAP_SUCCESS;
105
106         ber = ldap_alloc_ber_with_options( ld );
107         if ( ber == NULL ) {
108                 ld->ld_errno = LDAP_NO_MEMORY;
109                 return ld->ld_errno;
110         }
111
112         tag = ber_printf( ber, "{ii" /*}*/,
113                 vlvinfop->ldvlv_before_count,
114                 vlvinfop->ldvlv_after_count );
115         if ( tag == LBER_ERROR ) {
116                 goto error_return;
117         }
118
119         if ( vlvinfop->ldvlv_attrvalue == NULL ) {
120                 tag = ber_printf( ber, "t{iiN}",
121                         LDAP_VLVBYINDEX_IDENTIFIER,
122                         vlvinfop->ldvlv_offset,
123                         vlvinfop->ldvlv_count );
124                 if ( tag == LBER_ERROR ) {
125                         goto error_return;
126                 }
127
128         } else {
129                 tag = ber_printf( ber, "tO",
130                         LDAP_VLVBYVALUE_IDENTIFIER,
131                         vlvinfop->ldvlv_attrvalue );
132                 if ( tag == LBER_ERROR ) {
133                         goto error_return;
134                 }
135         }
136
137         if ( vlvinfop->ldvlv_context ) {
138                 tag = ber_printf( ber, "tO",
139                         LDAP_VLVCONTEXT_IDENTIFIER,
140                         vlvinfop->ldvlv_context );
141                 if ( tag == LBER_ERROR ) {
142                         goto error_return;
143                 }
144         }
145
146         tag = ber_printf( ber, /*{*/ "N}" ); 
147         if ( tag == LBER_ERROR ) {
148                 goto error_return;
149         }
150
151         if ( ber_flatten2( ber, value, 1 ) == -1 ) {
152                 ld->ld_errno = LDAP_NO_MEMORY;
153         }
154
155         if ( 0 ) {
156 error_return:;
157                 ld->ld_errno = LDAP_ENCODING_ERROR;
158         }
159
160         if ( ber != NULL ) {
161                 ber_free( ber, 1 );
162         }
163
164         return ld->ld_errno;
165 }
166
167 /*---
168    ldap_create_vlv_control
169    
170    Create and encode the Virtual List View control.
171
172    ld        (IN)  An LDAP session handle.
173    
174    vlvinfop  (IN)  The address of an LDAPVLVInfo structure whose contents 
175                                    are used to construct the value of the control
176                                    that is created.
177    
178    ctrlp     (OUT) A result parameter that will be assigned the address
179                                    of an LDAPControl structure that contains the 
180                                    VirtualListViewRequest control created by this function.
181                                    The memory occupied by the LDAPControl structure
182                                    SHOULD be freed when it is no longer in use by
183                                    calling ldap_control_free().
184                                           
185    
186    Ber encoding
187    
188    VirtualListViewRequest ::= SEQUENCE {
189                 beforeCount  INTEGER (0 .. maxInt),
190                 afterCount   INTEGER (0 .. maxInt),
191                 CHOICE {
192                                 byoffset [0] SEQUENCE, {
193                                 offset        INTEGER (0 .. maxInt),
194                                 contentCount  INTEGER (0 .. maxInt) }
195                                 [1] greaterThanOrEqual assertionValue }
196                 contextID     OCTET STRING OPTIONAL }
197           
198    
199    Note:  The first time the VLV control is created, the ldvlv_context
200                   field of the LDAPVLVInfo structure should be set to NULL.
201                   The context obtained from calling ldap_parse_vlv_control()
202                   should be used as the context in the next ldap_create_vlv_control
203                   call.
204
205  ---*/
206
207 int
208 ldap_create_vlv_control(
209         LDAP *ld,
210         LDAPVLVInfo *vlvinfop,
211         LDAPControl **ctrlp )
212 {
213         struct berval   value;
214
215         if ( ctrlp == NULL ) {
216                 ld->ld_errno = LDAP_PARAM_ERROR;
217                 return ld->ld_errno;
218         }
219
220         ld->ld_errno = ldap_create_vlv_control_value( ld, vlvinfop, &value );
221         if ( ld->ld_errno == LDAP_SUCCESS ) {
222
223                 ld->ld_errno = ldap_control_create( LDAP_CONTROL_VLVREQUEST,
224                         1, &value, 0, ctrlp );
225                 if ( ld->ld_errno != LDAP_SUCCESS ) {
226                         LDAP_FREE( value.bv_val );
227                 }
228         }
229
230         return ld->ld_errno;
231 }
232
233
234 /*---
235    ldap_parse_vlvresponse_control
236    
237    Decode the Virtual List View control return information.
238
239    ld           (IN)   An LDAP session handle.
240    
241    ctrl         (IN)   The address of the LDAPControl structure.
242    
243    target_posp  (OUT)  This result parameter is filled in with the list
244                                            index of the target entry.  If this parameter is
245                                            NULL, the target position is not returned.
246    
247    list_countp  (OUT)  This result parameter is filled in with the server's
248                                            estimate of the size of the list.  If this parameter
249                                            is NULL, the size is not returned.
250    
251    contextp     (OUT)  This result parameter is filled in with the address
252                                            of a struct berval that contains the server-
253                                            generated context identifier if one was returned by
254                                            the server.  If the server did not return a context
255                                            identifier, this parameter will be set to NULL, even
256                                            if an error occured.
257                                            The returned context SHOULD be used in the next call
258                                            to create a VLV sort control.  The struct berval
259                                            returned SHOULD be disposed of by calling ber_bvfree()
260                                            when it is no longer needed.  If NULL is passed for
261                                            contextp, the context identifier is not returned.
262    
263    errcodep     (OUT)  This result parameter is filled in with the VLV
264                                            result code.  If this parameter is NULL, the result
265                                            code is not returned.  
266    
267    
268    Ber encoding
269    
270    VirtualListViewResponse ::= SEQUENCE {
271                 targetPosition    INTEGER (0 .. maxInt),
272                 contentCount     INTEGER (0 .. maxInt),
273                 virtualListViewResult ENUMERATED {
274                 success (0),
275                 operatonsError (1),
276                 unwillingToPerform (53),
277                 insufficientAccessRights (50),
278                 busy (51),
279                 timeLimitExceeded (3),
280                 adminLimitExceeded (11),
281                 sortControlMissing (60),
282                 offsetRangeError (61),
283                 other (80) },
284                 contextID     OCTET STRING OPTIONAL }
285    
286 ---*/
287
288 int
289 ldap_parse_vlvresponse_control(
290         LDAP *ld,
291         LDAPControl *ctrl,
292         ber_int_t *target_posp,
293         ber_int_t *list_countp,
294         struct berval  **contextp,
295         ber_int_t *errcodep )
296 {
297         BerElement  *ber;
298         ber_int_t pos, count, err;
299         ber_tag_t tag, berTag;
300         ber_len_t berLen;
301
302         assert( ld != NULL );
303         assert( LDAP_VALID( ld ) );
304
305         if (contextp) {
306                 *contextp = NULL;        /* Make sure we return a NULL if error occurs. */
307         }
308
309         if (ctrl == NULL) {
310                 ld->ld_errno = LDAP_PARAM_ERROR;
311                 return(ld->ld_errno);
312         }
313
314         if (strcmp(LDAP_CONTROL_VLVRESPONSE, ctrl->ldctl_oid) != 0) {
315                 /* Not VLV Response control */
316                 ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
317                 return(ld->ld_errno);
318         }
319
320         /* Create a BerElement from the berval returned in the control. */
321         ber = ber_init(&ctrl->ldctl_value);
322
323         if (ber == NULL) {
324                 ld->ld_errno = LDAP_NO_MEMORY;
325                 return(ld->ld_errno);
326         }
327
328         /* Extract the data returned in the control. */
329         tag = ber_scanf(ber, "{iie" /*}*/, &pos, &count, &err);
330
331         if( tag == LBER_ERROR) {
332                 ber_free(ber, 1);
333                 ld->ld_errno = LDAP_DECODING_ERROR;
334                 return(ld->ld_errno);
335         }
336
337
338         /* Since the context is the last item encoded, if caller doesn't want
339            it returned, don't decode it. */
340         if (contextp) {
341                 if (LDAP_VLVCONTEXT_IDENTIFIER == ber_peek_tag(ber, &berLen)) {
342                         tag = ber_scanf(ber, "tO", &berTag, contextp);
343
344                         if( tag == LBER_ERROR) {
345                                 ber_free(ber, 1);
346                                 ld->ld_errno = LDAP_DECODING_ERROR;
347                                 return(ld->ld_errno);
348                         }
349                 }
350         }
351
352         ber_free(ber, 1);
353
354         /* Return data to the caller for items that were requested. */
355         if (target_posp) *target_posp = pos;
356         if (list_countp) *list_countp = count;
357         if (errcodep) *errcodep = err;
358
359         ld->ld_errno = LDAP_SUCCESS;
360         return(ld->ld_errno);
361 }