]> git.sur5r.net Git - openldap/blob - libraries/libldap/vlvctrl.c
25241165e849e47a17b274ae4ca95d8f9eeeee6c
[openldap] / libraries / libldap / vlvctrl.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2005 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_vlv_control
151    
152    Decode the Virtual List View control return information.
153
154    ld           (IN)   An LDAP session handle.
155    
156    ctrls        (IN)   The address of a NULL-terminated array of 
157                                            LDAPControl structures, typically obtained 
158                                            by a call to ldap_parse_result().
159    
160    target_posp  (OUT)  This result parameter is filled in with the list
161                                            index of the target entry.  If this parameter is
162                                            NULL, the target position is not returned.
163    
164    list_countp  (OUT)  This result parameter is filled in with the server's
165                                            estimate of the size of the list.  If this parameter
166                                            is NULL, the size is not returned.
167    
168    contextp     (OUT)  This result parameter is filled in with the address
169                                            of a struct berval that contains the server-
170                                            generated context identifier if one was returned by
171                                            the server.  If the server did not return a context
172                                            identifier, this parameter will be set to NULL, even
173                                            if an error occured.
174                                            The returned context SHOULD be used in the next call
175                                            to create a VLV sort control.  The struct berval
176                                            returned SHOULD be disposed of by calling ber_bvfree()
177                                            when it is no longer needed.  If NULL is passed for
178                                            contextp, the context identifier is not returned.
179    
180    errcodep     (OUT)  This result parameter is filled in with the VLV
181                                            result code.  If this parameter is NULL, the result
182                                            code is not returned.  
183    
184    
185    Ber encoding
186    
187    VirtualListViewResponse ::= SEQUENCE {
188                 targetPosition    INTEGER (0 .. maxInt),
189                 contentCount     INTEGER (0 .. maxInt),
190                 virtualListViewResult ENUMERATED {
191                 success (0),
192                 operatonsError (1),
193                 unwillingToPerform (53),
194                 insufficientAccessRights (50),
195                 busy (51),
196                 timeLimitExceeded (3),
197                 adminLimitExceeded (11),
198                 sortControlMissing (60),
199                 offsetRangeError (61),
200                 other (80) },
201                 contextID     OCTET STRING OPTIONAL }
202    
203 ---*/
204
205 int
206 ldap_parse_vlv_control(
207         LDAP           *ld,
208         LDAPControl    **ctrls,
209         unsigned long  *target_posp,
210         unsigned long  *list_countp,
211         struct berval  **contextp,
212         int            *errcodep )
213 {
214         BerElement  *ber;
215         LDAPControl *pControl;
216         int i;
217         unsigned long pos, count, err;
218         ber_tag_t tag, berTag;
219         ber_len_t berLen;
220
221         assert( ld != NULL );
222         assert( LDAP_VALID( ld ) );
223
224         if (contextp) {
225                 *contextp = NULL;        /* Make sure we return a NULL if error occurs. */
226         }
227
228         if (ctrls == NULL) {
229                 ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
230                 return(ld->ld_errno);
231         }
232
233         /* Search the list of control responses for a VLV control. */
234         for (i=0; ctrls[i]; i++) {
235                 pControl = ctrls[i];
236                 if (!strcmp(LDAP_CONTROL_VLVRESPONSE, pControl->ldctl_oid))
237                         goto foundVLVControl;
238         }
239
240         /* No sort control was found. */
241         ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
242         return(ld->ld_errno);
243
244 foundVLVControl:
245         /* Create a BerElement from the berval returned in the control. */
246         ber = ber_init(&pControl->ldctl_value);
247
248         if (ber == NULL) {
249                 ld->ld_errno = LDAP_NO_MEMORY;
250                 return(ld->ld_errno);
251         }
252
253         /* Extract the data returned in the control. */
254         tag = ber_scanf(ber, "{iie" /*}*/, &pos, &count, &err);
255
256         if( tag == LBER_ERROR) {
257                 ber_free(ber, 1);
258                 ld->ld_errno = LDAP_DECODING_ERROR;
259                 return(ld->ld_errno);
260         }
261
262
263         /* Since the context is the last item encoded, if caller doesn't want
264            it returned, don't decode it. */
265         if (contextp) {
266                 if (LDAP_VLVCONTEXT_IDENTIFIER == ber_peek_tag(ber, &berLen)) {
267                         tag = ber_scanf(ber, "tO", &berTag, contextp);
268
269                         if( tag == LBER_ERROR) {
270                                 ber_free(ber, 1);
271                                 ld->ld_errno = LDAP_DECODING_ERROR;
272                                 return(ld->ld_errno);
273                         }
274                 }
275         }
276
277         ber_free(ber, 1);
278
279         /* Return data to the caller for items that were requested. */
280         if (target_posp) {
281                 *target_posp = pos;
282         }
283         if (list_countp) {
284                 *list_countp = count;
285         }
286         if (errcodep) {
287                 *errcodep = err;
288         }
289
290         ld->ld_errno = LDAP_SUCCESS;
291         return(ld->ld_errno);
292 }