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