]> git.sur5r.net Git - openldap/blob - libraries/libldap/vlvctrl.c
b1638cfe893ef63de613b0542f681b44f5f90108
[openldap] / libraries / libldap / vlvctrl.c
1 /*
2  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5 /* Adapted for inclusion into OpenLDAP by Kurt D. Zeilenga */
6 /*---
7  * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
8  *
9  * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
10  * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
11  * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
12  * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
13  * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
14  * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
15  * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
16  * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
17  *---*/
18
19 #include "portable.h"
20
21 #include <stdio.h>
22 #include <ac/stdlib.h>
23 #include <ac/string.h>
24 #include <ac/time.h>
25
26 #include "ldap-int.h"
27
28 #define LDAP_VLVBYINDEX_IDENTIFIER     0xa0L
29 #define LDAP_VLVBYVALUE_IDENTIFIER     0x81L
30 #define LDAP_VLVCONTEXT_IDENTIFIER     0x04L
31
32
33 /*---
34    ldap_create_vlv_control
35    
36    Create and encode the Virtual List View control.
37
38    ld        (IN)  An LDAP session handle, as obtained from a call to
39                                    ldap_init().
40    
41    vlvinfop  (IN)  The address of an LDAPVLVInfo structure whose contents 
42                                    are used to construct the value of the control
43                                    that is created.
44    
45    ctrlp     (OUT) A result parameter that will be assigned the address
46                                    of an LDAPControl structure that contains the 
47                                    VirtualListViewRequest control created by this function.
48                                    The memory occupied by the LDAPControl structure
49                                    SHOULD be freed when it is no longer in use by
50                                    calling ldap_control_free().
51                                           
52    
53    Ber encoding
54    
55    VirtualListViewRequest ::= SEQUENCE {
56                 beforeCount  INTEGER (0 .. maxInt),
57                 afterCount   INTEGER (0 .. maxInt),
58                 CHOICE {
59                                 byoffset [0] SEQUENCE, {
60                                 offset        INTEGER (0 .. maxInt),
61                                 contentCount  INTEGER (0 .. maxInt) }
62                                 [1] greaterThanOrEqual assertionValue }
63                 contextID     OCTET STRING OPTIONAL }
64           
65    
66    Note:  The first time the VLV control is created, the ldvlv_context
67                   field of the LDAPVLVInfo structure should be set to NULL.
68                   The context obtained from calling ldap_parse_vlv_control()
69                   should be used as the context in the next ldap_create_vlv_control
70                   call.
71
72  ---*/
73
74 int
75 ldap_create_vlv_control( LDAP *ld,
76                                                  LDAPVLVInfo *vlvinfop,
77                                                  LDAPControl **ctrlp )
78 {
79         ber_tag_t tag;
80         BerElement *ber;
81
82         assert( ld != NULL );
83         assert( vlvinfop != NULL );
84         assert( ctrlp != NULL );
85
86         if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
87                 ld->ld_errno = LDAP_NO_MEMORY;
88                 return(LDAP_NO_MEMORY);
89         }
90
91         tag = ber_printf(ber, "{ii" /*}*/,
92                 vlvinfop->ldvlv_before_count,
93                 vlvinfop->ldvlv_after_count);
94         if( tag == LBER_ERROR ) goto exit;
95
96         if (vlvinfop->ldvlv_attrvalue == NULL) {
97                 tag = ber_printf(ber, "t{iiN}",
98                         LDAP_VLVBYINDEX_IDENTIFIER,
99                         vlvinfop->ldvlv_offset,
100                         vlvinfop->ldvlv_count);
101                 if( tag == LBER_ERROR ) goto exit;
102
103         } else {
104                 tag = ber_printf(ber, "tO",
105                         LDAP_VLVBYVALUE_IDENTIFIER,
106                         vlvinfop->ldvlv_attrvalue);
107                 if( tag == LBER_ERROR ) goto exit;
108         }
109
110         if (vlvinfop->ldvlv_context) {
111                 tag = ber_printf(ber, "tO",
112                         LDAP_VLVCONTEXT_IDENTIFIER,
113                         vlvinfop->ldvlv_context);
114                 if( tag == LBER_ERROR ) goto exit;
115         }
116
117         tag = ber_printf(ber, /*{*/ "N}"); 
118         if( tag == LBER_ERROR ) goto exit;
119
120         ld->ld_errno = ldap_create_control(     LDAP_CONTROL_VLVREQUEST,
121                 ber, 1, ctrlp);
122
123         ber_free(ber, 1);
124         return(ld->ld_errno);
125
126 exit:
127         ber_free(ber, 1);
128         ld->ld_errno = LDAP_ENCODING_ERROR;
129         return(ld->ld_errno);
130 }
131
132
133 /*---
134    ldap_parse_vlv_control
135    
136    Decode the Virtual List View control return information.
137
138    ld           (IN)   An LDAP session handle.
139    
140    ctrls        (IN)   The address of a NULL-terminated array of 
141                                            LDAPControl structures, typically obtained 
142                                            by a call to ldap_parse_result().
143    
144    target_posp  (OUT)  This result parameter is filled in with the list
145                                            index of the target entry.  If this parameter is
146                                            NULL, the target position is not returned.
147    
148    list_countp  (OUT)  This result parameter is filled in with the server's
149                                            estimate of the size of the list.  If this parameter
150                                            is NULL, the size is not returned.
151    
152    contextp     (OUT)  This result parameter is filled in with the address
153                                            of a struct berval that contains the server-
154                                            generated context identifier if one was returned by
155                                            the server.  If the server did not return a context
156                                            identifier, this parameter will be set to NULL, even
157                                            if an error occured.
158                                            The returned context SHOULD be used in the next call
159                                            to create a VLV sort control.  The struct berval
160                                            returned SHOULD be disposed of by calling ber_bvfree()
161                                            when it is no longer needed.  If NULL is passed for
162                                            contextp, the context identifier is not returned.
163    
164    errcodep     (OUT)  This result parameter is filled in with the VLV
165                                            result code.  If this parameter is NULL, the result
166                                            code is not returned.  
167    
168    
169    Ber encoding
170    
171    VirtualListViewResponse ::= SEQUENCE {
172                 targetPosition    INTEGER (0 .. maxInt),
173                 contentCount     INTEGER (0 .. maxInt),
174                 virtualListViewResult ENUMERATED {
175                 success (0),
176                 operatonsError (1),
177                 unwillingToPerform (53),
178                 insufficientAccessRights (50),
179                 busy (51),
180                 timeLimitExceeded (3),
181                 adminLimitExceeded (11),
182                 sortControlMissing (60),
183                 offsetRangeError (61),
184                 other (80) },
185                 contextID     OCTET STRING OPTIONAL }
186    
187 ---*/
188
189 int
190 ldap_parse_vlv_control(
191         LDAP           *ld,
192         LDAPControl    **ctrls,
193         unsigned long  *target_posp,
194         unsigned long  *list_countp,
195         struct berval  **contextp,
196         int            *errcodep )
197 {
198         BerElement  *ber;
199         LDAPControl *pControl;
200         int i;
201         unsigned long pos, count, err;
202         ber_tag_t tag, berTag;
203         ber_len_t berLen;
204
205         assert( ld != NULL );
206
207         if (contextp) {
208                 *contextp = NULL;        /* Make sure we return a NULL if error occurs. */
209         }
210
211         if (ctrls == NULL) {
212                 ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
213                 return(ld->ld_errno);
214         }
215
216         /* Search the list of control responses for a VLV control. */
217         for (i=0; ctrls[i]; i++) {
218                 pControl = ctrls[i];
219                 if (!strcmp(LDAP_CONTROL_VLVRESPONSE, pControl->ldctl_oid))
220                         goto foundVLVControl;
221         }
222
223         /* No sort control was found. */
224         ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
225         return(ld->ld_errno);
226
227 foundVLVControl:
228         /* Create a BerElement from the berval returned in the control. */
229         ber = ber_init(&pControl->ldctl_value);
230
231         if (ber == NULL) {
232                 ld->ld_errno = LDAP_NO_MEMORY;
233                 return(ld->ld_errno);
234         }
235
236         /* Extract the data returned in the control. */
237         tag = ber_scanf(ber, "{iie" /*}*/, &pos, &count, &err);
238
239         if( tag == LBER_ERROR) {
240                 ber_free(ber, 1);
241                 ld->ld_errno = LDAP_DECODING_ERROR;
242                 return(ld->ld_errno);
243         }
244
245
246         /* Since the context is the last item encoded, if caller doesn't want
247            it returned, don't decode it. */
248         if (contextp) {
249                 if (LDAP_VLVCONTEXT_IDENTIFIER == ber_peek_tag(ber, &berLen)) {
250                         tag = ber_scanf(ber, "tO", &berTag, contextp);
251
252                         if( tag == LBER_ERROR) {
253                                 ber_free(ber, 1);
254                                 ld->ld_errno = LDAP_DECODING_ERROR;
255                                 return(ld->ld_errno);
256                         }
257                 }
258         }
259
260         ber_free(ber, 1);
261
262         /* Return data to the caller for items that were requested. */
263         if (target_posp) {
264                 *target_posp = pos;
265         }
266         if (list_countp) {
267                 *list_countp = count;
268         }
269         if (errcodep) {
270                 *errcodep = err;
271         }
272
273         ld->ld_errno = LDAP_SUCCESS;
274         return(ld->ld_errno);
275 }