]> git.sur5r.net Git - openldap/blob - libraries/libldap/vlvctrl.c
ITS#4844 add missing overlays
[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         BerElement      *ber;
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                 if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
223                         ld->ld_errno = LDAP_NO_MEMORY;
224                         return LDAP_NO_MEMORY;
225                 }
226
227                 ld->ld_errno = ldap_create_control( LDAP_CONTROL_VLVREQUEST,
228                         ber, 1, ctrlp );
229                 if ( ld->ld_errno == LDAP_SUCCESS ) {
230                         (*ctrlp)->ldctl_value = value;
231                 } else {
232                         LDAP_FREE( value.bv_val );
233                 }
234                 ber_free(ber, 1);
235         }
236
237         return ld->ld_errno;
238 }
239
240
241 /*---
242    ldap_parse_vlvresponse_control
243    
244    Decode the Virtual List View control return information.
245
246    ld           (IN)   An LDAP session handle.
247    
248    ctrl         (IN)   The address of the LDAPControl structure.
249    
250    target_posp  (OUT)  This result parameter is filled in with the list
251                                            index of the target entry.  If this parameter is
252                                            NULL, the target position is not returned.
253    
254    list_countp  (OUT)  This result parameter is filled in with the server's
255                                            estimate of the size of the list.  If this parameter
256                                            is NULL, the size is not returned.
257    
258    contextp     (OUT)  This result parameter is filled in with the address
259                                            of a struct berval that contains the server-
260                                            generated context identifier if one was returned by
261                                            the server.  If the server did not return a context
262                                            identifier, this parameter will be set to NULL, even
263                                            if an error occured.
264                                            The returned context SHOULD be used in the next call
265                                            to create a VLV sort control.  The struct berval
266                                            returned SHOULD be disposed of by calling ber_bvfree()
267                                            when it is no longer needed.  If NULL is passed for
268                                            contextp, the context identifier is not returned.
269    
270    errcodep     (OUT)  This result parameter is filled in with the VLV
271                                            result code.  If this parameter is NULL, the result
272                                            code is not returned.  
273    
274    
275    Ber encoding
276    
277    VirtualListViewResponse ::= SEQUENCE {
278                 targetPosition    INTEGER (0 .. maxInt),
279                 contentCount     INTEGER (0 .. maxInt),
280                 virtualListViewResult ENUMERATED {
281                 success (0),
282                 operatonsError (1),
283                 unwillingToPerform (53),
284                 insufficientAccessRights (50),
285                 busy (51),
286                 timeLimitExceeded (3),
287                 adminLimitExceeded (11),
288                 sortControlMissing (60),
289                 offsetRangeError (61),
290                 other (80) },
291                 contextID     OCTET STRING OPTIONAL }
292    
293 ---*/
294
295 int
296 ldap_parse_vlvresponse_control(
297         LDAP *ld,
298         LDAPControl *ctrl,
299         ber_int_t *target_posp,
300         ber_int_t *list_countp,
301         struct berval  **contextp,
302         ber_int_t *errcodep )
303 {
304         BerElement  *ber;
305         ber_int_t pos, count, err;
306         ber_tag_t tag, berTag;
307         ber_len_t berLen;
308
309         assert( ld != NULL );
310         assert( LDAP_VALID( ld ) );
311
312         if (contextp) {
313                 *contextp = NULL;        /* Make sure we return a NULL if error occurs. */
314         }
315
316         if (ctrl == NULL) {
317                 ld->ld_errno = LDAP_PARAM_ERROR;
318                 return(ld->ld_errno);
319         }
320
321         if (strcmp(LDAP_CONTROL_VLVRESPONSE, ctrl->ldctl_oid) != 0) {
322                 /* Not VLV Response control */
323                 ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
324                 return(ld->ld_errno);
325         }
326
327         /* Create a BerElement from the berval returned in the control. */
328         ber = ber_init(&ctrl->ldctl_value);
329
330         if (ber == NULL) {
331                 ld->ld_errno = LDAP_NO_MEMORY;
332                 return(ld->ld_errno);
333         }
334
335         /* Extract the data returned in the control. */
336         tag = ber_scanf(ber, "{iie" /*}*/, &pos, &count, &err);
337
338         if( tag == LBER_ERROR) {
339                 ber_free(ber, 1);
340                 ld->ld_errno = LDAP_DECODING_ERROR;
341                 return(ld->ld_errno);
342         }
343
344
345         /* Since the context is the last item encoded, if caller doesn't want
346            it returned, don't decode it. */
347         if (contextp) {
348                 if (LDAP_VLVCONTEXT_IDENTIFIER == ber_peek_tag(ber, &berLen)) {
349                         tag = ber_scanf(ber, "tO", &berTag, contextp);
350
351                         if( tag == LBER_ERROR) {
352                                 ber_free(ber, 1);
353                                 ld->ld_errno = LDAP_DECODING_ERROR;
354                                 return(ld->ld_errno);
355                         }
356                 }
357         }
358
359         ber_free(ber, 1);
360
361         /* Return data to the caller for items that were requested. */
362         if (target_posp) *target_posp = pos;
363         if (list_countp) *list_countp = count;
364         if (errcodep) *errcodep = err;
365
366         ld->ld_errno = LDAP_SUCCESS;
367         return(ld->ld_errno);
368 }