]> git.sur5r.net Git - openldap/blob - libraries/libldap/vlvctrl.c
Sync with HEAD for OL 2.4.5
[openldap] / libraries / libldap / vlvctrl.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2007 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
105         ber = ldap_alloc_ber_with_options( ld );
106         if ( ber == NULL ) {
107                 ld->ld_errno = LDAP_NO_MEMORY;
108                 return ld->ld_errno;
109         }
110
111         tag = ber_printf( ber, "{ii" /*}*/,
112                 vlvinfop->ldvlv_before_count,
113                 vlvinfop->ldvlv_after_count );
114         if ( tag == LBER_ERROR ) {
115                 goto error_return;
116         }
117
118         if ( vlvinfop->ldvlv_attrvalue == NULL ) {
119                 tag = ber_printf( ber, "t{iiN}",
120                         LDAP_VLVBYINDEX_IDENTIFIER,
121                         vlvinfop->ldvlv_offset,
122                         vlvinfop->ldvlv_count );
123                 if ( tag == LBER_ERROR ) {
124                         goto error_return;
125                 }
126
127         } else {
128                 tag = ber_printf( ber, "tO",
129                         LDAP_VLVBYVALUE_IDENTIFIER,
130                         vlvinfop->ldvlv_attrvalue );
131                 if ( tag == LBER_ERROR ) {
132                         goto error_return;
133                 }
134         }
135
136         if ( vlvinfop->ldvlv_context ) {
137                 tag = ber_printf( ber, "tO",
138                         LDAP_VLVCONTEXT_IDENTIFIER,
139                         vlvinfop->ldvlv_context );
140                 if ( tag == LBER_ERROR ) {
141                         goto error_return;
142                 }
143         }
144
145         tag = ber_printf( ber, /*{*/ "N}" ); 
146         if ( tag == LBER_ERROR ) {
147                 goto error_return;
148         }
149
150         if ( ber_flatten2( ber, value, 1 ) == -1 ) {
151                 ld->ld_errno = LDAP_NO_MEMORY;
152         }
153
154         if ( 0 ) {
155 error_return:;
156                 ld->ld_errno = LDAP_ENCODING_ERROR;
157         }
158
159         if ( ber != NULL ) {
160                 ber_free( ber, 1 );
161         }
162
163         return ld->ld_errno;
164 }
165
166 /*---
167    ldap_create_vlv_control
168    
169    Create and encode the Virtual List View control.
170
171    ld        (IN)  An LDAP session handle.
172    
173    vlvinfop  (IN)  The address of an LDAPVLVInfo structure whose contents 
174                                    are used to construct the value of the control
175                                    that is created.
176    
177    ctrlp     (OUT) A result parameter that will be assigned the address
178                                    of an LDAPControl structure that contains the 
179                                    VirtualListViewRequest control created by this function.
180                                    The memory occupied by the LDAPControl structure
181                                    SHOULD be freed when it is no longer in use by
182                                    calling ldap_control_free().
183                                           
184    
185    Ber encoding
186    
187    VirtualListViewRequest ::= SEQUENCE {
188                 beforeCount  INTEGER (0 .. maxInt),
189                 afterCount   INTEGER (0 .. maxInt),
190                 CHOICE {
191                                 byoffset [0] SEQUENCE, {
192                                 offset        INTEGER (0 .. maxInt),
193                                 contentCount  INTEGER (0 .. maxInt) }
194                                 [1] greaterThanOrEqual assertionValue }
195                 contextID     OCTET STRING OPTIONAL }
196           
197    
198    Note:  The first time the VLV control is created, the ldvlv_context
199                   field of the LDAPVLVInfo structure should be set to NULL.
200                   The context obtained from calling ldap_parse_vlv_control()
201                   should be used as the context in the next ldap_create_vlv_control
202                   call.
203
204  ---*/
205
206 int
207 ldap_create_vlv_control(
208         LDAP *ld,
209         LDAPVLVInfo *vlvinfop,
210         LDAPControl **ctrlp )
211 {
212         struct berval   value;
213
214         if ( ctrlp == NULL ) {
215                 ld->ld_errno = LDAP_PARAM_ERROR;
216                 return ld->ld_errno;
217         }
218
219         ld->ld_errno = ldap_create_vlv_control_value( ld, vlvinfop, &value );
220         if ( ld->ld_errno == LDAP_SUCCESS ) {
221
222                 ld->ld_errno = ldap_control_create( LDAP_CONTROL_VLVREQUEST,
223                         1, &value, 0, ctrlp );
224                 if ( ld->ld_errno != LDAP_SUCCESS ) {
225                         LDAP_FREE( value.bv_val );
226                 }
227         }
228
229         return ld->ld_errno;
230 }
231
232
233 /*---
234    ldap_parse_vlvresponse_control
235    
236    Decode the Virtual List View control return information.
237
238    ld           (IN)   An LDAP session handle.
239    
240    ctrl         (IN)   The address of the LDAPControl structure.
241    
242    target_posp  (OUT)  This result parameter is filled in with the list
243                                            index of the target entry.  If this parameter is
244                                            NULL, the target position is not returned.
245    
246    list_countp  (OUT)  This result parameter is filled in with the server's
247                                            estimate of the size of the list.  If this parameter
248                                            is NULL, the size is not returned.
249    
250    contextp     (OUT)  This result parameter is filled in with the address
251                                            of a struct berval that contains the server-
252                                            generated context identifier if one was returned by
253                                            the server.  If the server did not return a context
254                                            identifier, this parameter will be set to NULL, even
255                                            if an error occured.
256                                            The returned context SHOULD be used in the next call
257                                            to create a VLV sort control.  The struct berval
258                                            returned SHOULD be disposed of by calling ber_bvfree()
259                                            when it is no longer needed.  If NULL is passed for
260                                            contextp, the context identifier is not returned.
261    
262    errcodep     (OUT)  This result parameter is filled in with the VLV
263                                            result code.  If this parameter is NULL, the result
264                                            code is not returned.  
265    
266    
267    Ber encoding
268    
269    VirtualListViewResponse ::= SEQUENCE {
270                 targetPosition    INTEGER (0 .. maxInt),
271                 contentCount     INTEGER (0 .. maxInt),
272                 virtualListViewResult ENUMERATED {
273                 success (0),
274                 operatonsError (1),
275                 unwillingToPerform (53),
276                 insufficientAccessRights (50),
277                 busy (51),
278                 timeLimitExceeded (3),
279                 adminLimitExceeded (11),
280                 sortControlMissing (60),
281                 offsetRangeError (61),
282                 other (80) },
283                 contextID     OCTET STRING OPTIONAL }
284    
285 ---*/
286
287 int
288 ldap_parse_vlvresponse_control(
289         LDAP *ld,
290         LDAPControl *ctrl,
291         ber_int_t *target_posp,
292         ber_int_t *list_countp,
293         struct berval  **contextp,
294         ber_int_t *errcodep )
295 {
296         BerElement  *ber;
297         ber_int_t pos, count, err;
298         ber_tag_t tag, berTag;
299         ber_len_t berLen;
300
301         assert( ld != NULL );
302         assert( LDAP_VALID( ld ) );
303
304         if (contextp) {
305                 *contextp = NULL;        /* Make sure we return a NULL if error occurs. */
306         }
307
308         if (ctrl == NULL) {
309                 ld->ld_errno = LDAP_PARAM_ERROR;
310                 return(ld->ld_errno);
311         }
312
313         if (strcmp(LDAP_CONTROL_VLVRESPONSE, ctrl->ldctl_oid) != 0) {
314                 /* Not VLV Response control */
315                 ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
316                 return(ld->ld_errno);
317         }
318
319         /* Create a BerElement from the berval returned in the control. */
320         ber = ber_init(&ctrl->ldctl_value);
321
322         if (ber == NULL) {
323                 ld->ld_errno = LDAP_NO_MEMORY;
324                 return(ld->ld_errno);
325         }
326
327         /* Extract the data returned in the control. */
328         tag = ber_scanf(ber, "{iie" /*}*/, &pos, &count, &err);
329
330         if( tag == LBER_ERROR) {
331                 ber_free(ber, 1);
332                 ld->ld_errno = LDAP_DECODING_ERROR;
333                 return(ld->ld_errno);
334         }
335
336
337         /* Since the context is the last item encoded, if caller doesn't want
338            it returned, don't decode it. */
339         if (contextp) {
340                 if (LDAP_VLVCONTEXT_IDENTIFIER == ber_peek_tag(ber, &berLen)) {
341                         tag = ber_scanf(ber, "tO", &berTag, contextp);
342
343                         if( tag == LBER_ERROR) {
344                                 ber_free(ber, 1);
345                                 ld->ld_errno = LDAP_DECODING_ERROR;
346                                 return(ld->ld_errno);
347                         }
348                 }
349         }
350
351         ber_free(ber, 1);
352
353         /* Return data to the caller for items that were requested. */
354         if (target_posp) *target_posp = pos;
355         if (list_countp) *list_countp = count;
356         if (errcodep) *errcodep = err;
357
358         ld->ld_errno = LDAP_SUCCESS;
359         return(ld->ld_errno);
360 }