]> git.sur5r.net Git - openldap/blob - libraries/libldap/vlvctrl.c
Update (and rename) Sort and VLV parse routines to expect actual
[openldap] / libraries / libldap / vlvctrl.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2006 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 /* Portions Copyright (C) The Internet Society (1997)
31  * ASN.1 fragments are from RFC 2251; see RFC for full legal notices.
32  */
33
34 #include "portable.h"
35
36 #include <stdio.h>
37 #include <ac/stdlib.h>
38 #include <ac/string.h>
39 #include <ac/time.h>
40
41 #include "ldap-int.h"
42
43 #define LDAP_VLVBYINDEX_IDENTIFIER     0xa0L
44 #define LDAP_VLVBYVALUE_IDENTIFIER     0x81L
45 #define LDAP_VLVCONTEXT_IDENTIFIER     0x04L
46
47
48 /*---
49    ldap_create_vlv_control
50    
51    Create and encode the Virtual List View control.
52
53    ld        (IN)  An LDAP session handle, as obtained from a call to
54                                    ldap_init().
55    
56    vlvinfop  (IN)  The address of an LDAPVLVInfo structure whose contents 
57                                    are used to construct the value of the control
58                                    that is created.
59    
60    ctrlp     (OUT) A result parameter that will be assigned the address
61                                    of an LDAPControl structure that contains the 
62                                    VirtualListViewRequest control created by this function.
63                                    The memory occupied by the LDAPControl structure
64                                    SHOULD be freed when it is no longer in use by
65                                    calling ldap_control_free().
66                                           
67    
68    Ber encoding
69    
70    VirtualListViewRequest ::= SEQUENCE {
71                 beforeCount  INTEGER (0 .. maxInt),
72                 afterCount   INTEGER (0 .. maxInt),
73                 CHOICE {
74                                 byoffset [0] SEQUENCE, {
75                                 offset        INTEGER (0 .. maxInt),
76                                 contentCount  INTEGER (0 .. maxInt) }
77                                 [1] greaterThanOrEqual assertionValue }
78                 contextID     OCTET STRING OPTIONAL }
79           
80    
81    Note:  The first time the VLV control is created, the ldvlv_context
82                   field of the LDAPVLVInfo structure should be set to NULL.
83                   The context obtained from calling ldap_parse_vlv_control()
84                   should be used as the context in the next ldap_create_vlv_control
85                   call.
86
87  ---*/
88
89 int
90 ldap_create_vlv_control( LDAP *ld,
91                                                  LDAPVLVInfo *vlvinfop,
92                                                  LDAPControl **ctrlp )
93 {
94         ber_tag_t tag;
95         BerElement *ber;
96
97         assert( ld != NULL );
98         assert( LDAP_VALID( ld ) );
99         assert( vlvinfop != NULL );
100         assert( ctrlp != NULL );
101
102         if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
103                 ld->ld_errno = LDAP_NO_MEMORY;
104                 return(LDAP_NO_MEMORY);
105         }
106
107         tag = ber_printf(ber, "{ii" /*}*/,
108                 vlvinfop->ldvlv_before_count,
109                 vlvinfop->ldvlv_after_count);
110         if( tag == LBER_ERROR ) goto exit;
111
112         if (vlvinfop->ldvlv_attrvalue == NULL) {
113                 tag = ber_printf(ber, "t{iiN}",
114                         LDAP_VLVBYINDEX_IDENTIFIER,
115                         vlvinfop->ldvlv_offset,
116                         vlvinfop->ldvlv_count);
117                 if( tag == LBER_ERROR ) goto exit;
118
119         } else {
120                 tag = ber_printf(ber, "tO",
121                         LDAP_VLVBYVALUE_IDENTIFIER,
122                         vlvinfop->ldvlv_attrvalue);
123                 if( tag == LBER_ERROR ) goto exit;
124         }
125
126         if (vlvinfop->ldvlv_context) {
127                 tag = ber_printf(ber, "tO",
128                         LDAP_VLVCONTEXT_IDENTIFIER,
129                         vlvinfop->ldvlv_context);
130                 if( tag == LBER_ERROR ) goto exit;
131         }
132
133         tag = ber_printf(ber, /*{*/ "N}"); 
134         if( tag == LBER_ERROR ) goto exit;
135
136         ld->ld_errno = ldap_create_control(     LDAP_CONTROL_VLVREQUEST,
137                 ber, 1, ctrlp);
138
139         ber_free(ber, 1);
140         return(ld->ld_errno);
141
142 exit:
143         ber_free(ber, 1);
144         ld->ld_errno = LDAP_ENCODING_ERROR;
145         return(ld->ld_errno);
146 }
147
148
149 /*---
150    ldap_parse_vlvresponse_control
151    
152    Decode the Virtual List View control return information.
153
154    ld           (IN)   An LDAP session handle.
155    
156    ctrl         (IN)   The address of the LDAPControl structure.
157    
158    target_posp  (OUT)  This result parameter is filled in with the list
159                                            index of the target entry.  If this parameter is
160                                            NULL, the target position is not returned.
161    
162    list_countp  (OUT)  This result parameter is filled in with the server's
163                                            estimate of the size of the list.  If this parameter
164                                            is NULL, the size is not returned.
165    
166    contextp     (OUT)  This result parameter is filled in with the address
167                                            of a struct berval that contains the server-
168                                            generated context identifier if one was returned by
169                                            the server.  If the server did not return a context
170                                            identifier, this parameter will be set to NULL, even
171                                            if an error occured.
172                                            The returned context SHOULD be used in the next call
173                                            to create a VLV sort control.  The struct berval
174                                            returned SHOULD be disposed of by calling ber_bvfree()
175                                            when it is no longer needed.  If NULL is passed for
176                                            contextp, the context identifier is not returned.
177    
178    errcodep     (OUT)  This result parameter is filled in with the VLV
179                                            result code.  If this parameter is NULL, the result
180                                            code is not returned.  
181    
182    
183    Ber encoding
184    
185    VirtualListViewResponse ::= SEQUENCE {
186                 targetPosition    INTEGER (0 .. maxInt),
187                 contentCount     INTEGER (0 .. maxInt),
188                 virtualListViewResult ENUMERATED {
189                 success (0),
190                 operatonsError (1),
191                 unwillingToPerform (53),
192                 insufficientAccessRights (50),
193                 busy (51),
194                 timeLimitExceeded (3),
195                 adminLimitExceeded (11),
196                 sortControlMissing (60),
197                 offsetRangeError (61),
198                 other (80) },
199                 contextID     OCTET STRING OPTIONAL }
200    
201 ---*/
202
203 int
204 ldap_parse_vlvresponse_control(
205         LDAP           *ld,
206         LDAPControl    *ctrl,
207         unsigned long  *target_posp,
208         unsigned long  *list_countp,
209         struct berval  **contextp,
210         int            *errcodep )
211 {
212         BerElement  *ber;
213         LDAPControl *pControl;
214         int i;
215         unsigned long pos, count, err;
216         ber_tag_t tag, berTag;
217         ber_len_t berLen;
218
219         assert( ld != NULL );
220         assert( LDAP_VALID( ld ) );
221
222         if (contextp) {
223                 *contextp = NULL;        /* Make sure we return a NULL if error occurs. */
224         }
225
226         if (ctrl == NULL) {
227                 ld->ld_errno = LDAP_PARAM_ERROR;
228                 return(ld->ld_errno);
229         }
230
231         if (strcmp(LDAP_CONTROL_VLVRESPONSE, ctrl->ldctl_oid) != 0) {
232                 /* Not VLV Response control */
233                 ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
234                 return(ld->ld_errno);
235         }
236
237         /* Create a BerElement from the berval returned in the control. */
238         ber = ber_init(&ctrl->ldctl_value);
239
240         if (ber == NULL) {
241                 ld->ld_errno = LDAP_NO_MEMORY;
242                 return(ld->ld_errno);
243         }
244
245         /* Extract the data returned in the control. */
246         tag = ber_scanf(ber, "{iie" /*}*/, &pos, &count, &err);
247
248         if( tag == LBER_ERROR) {
249                 ber_free(ber, 1);
250                 ld->ld_errno = LDAP_DECODING_ERROR;
251                 return(ld->ld_errno);
252         }
253
254
255         /* Since the context is the last item encoded, if caller doesn't want
256            it returned, don't decode it. */
257         if (contextp) {
258                 if (LDAP_VLVCONTEXT_IDENTIFIER == ber_peek_tag(ber, &berLen)) {
259                         tag = ber_scanf(ber, "tO", &berTag, contextp);
260
261                         if( tag == LBER_ERROR) {
262                                 ber_free(ber, 1);
263                                 ld->ld_errno = LDAP_DECODING_ERROR;
264                                 return(ld->ld_errno);
265                         }
266                 }
267         }
268
269         ber_free(ber, 1);
270
271         /* Return data to the caller for items that were requested. */
272         if (target_posp) {
273                 *target_posp = pos;
274         }
275         if (list_countp) {
276                 *list_countp = count;
277         }
278         if (errcodep) {
279                 *errcodep = err;
280         }
281
282         ld->ld_errno = LDAP_SUCCESS;
283         return(ld->ld_errno);
284 }