]> git.sur5r.net Git - openldap/blob - libraries/libldap/pagectrl.c
67f648c37b6c24d48dd187522ba7fe3271d12014
[openldap] / libraries / libldap / pagectrl.c
1 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
2  *
3  * Copyright 1998-2006 The OpenLDAP Foundation.
4  * Copyright 2006 Hans Leidekker
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 /* ---------------------------------------------------------------------------
44     ldap_create_page_control_value
45
46     Create and encode the value of the paged results control (RFC 2696).
47
48     ld          (IN) An LDAP session handle, as obtained from a call to
49                      ldap_init().
50
51     pagesize    (IN) The number of entries to return per page.
52
53     cookie      (IN) Opaque structure used by the server to track its
54                      location in the search results. Pass in NULL on the
55                      first call.
56
57     value      (OUT) the pointer to a struct berval; it is filled by this function
58                      with the value that must be assigned to the ldctl_value member
59                      of the LDAPControl structure.  The bv_val member of the berval
60                      structure SHOULD be freed by calling ldap_memfree() when done.
61  
62     Ber encoding
63
64     pagedResultsControl ::= SEQUENCE {
65             controlType     1.2.840.113556.1.4.319,
66             criticality     BOOLEAN DEFAULT FALSE,
67             controlValue    searchControlValue }
68
69     searchControlValue ::= SEQUENCE {
70             size            INTEGER (0..maxInt),
71                                     -- requested page size from client
72                                     -- result set size estimate from server
73             cookie          OCTET STRING }
74
75    ---------------------------------------------------------------------------*/
76
77 int
78 ldap_create_page_control_value(
79         LDAP            *ld,
80         unsigned long   pagesize,
81         struct berval   *cookie,
82         struct berval   *value )
83 {
84         BerElement      *ber = NULL;
85         ber_tag_t       tag;
86         struct berval   null_cookie = { 0, NULL };
87
88         if ( ld == NULL || value == NULL ) {
89                 ld->ld_errno = LDAP_PARAM_ERROR;
90                 return ld->ld_errno;
91         }
92
93         assert( LDAP_VALID( ld ) );
94
95         value->bv_val = NULL;
96         value->bv_len = 0;
97
98         if ( cookie == NULL ) {
99                 cookie = &null_cookie;
100         }
101
102         ber = ldap_alloc_ber_with_options( ld );
103         if ( ber == NULL ) {
104                 ld->ld_errno = LDAP_NO_MEMORY;
105                 return ld->ld_errno;
106         }
107
108         tag = ber_printf( ber, "{iO}", pagesize, cookie );
109         if ( tag == LBER_ERROR ) {
110                 goto error_return;
111         }
112
113         if ( ber_flatten2( ber, value, 1 ) == -1 ) {
114                 ld->ld_errno = LDAP_NO_MEMORY;
115         }
116
117         if ( 0 ) {
118 error_return:;
119                 ld->ld_errno = LDAP_ENCODING_ERROR;
120         }
121
122         if ( ber != NULL ) {
123                 ber_free( ber, 1 );
124         }
125
126         return ld->ld_errno;
127 }
128
129
130 /* ---------------------------------------------------------------------------
131     ldap_create_page_control
132
133     Create and encode a page control.
134
135     ld          (IN) An LDAP session handle, as obtained from a call to
136                      ldap_init().
137
138     pagesize    (IN) The number of entries to return per page.
139
140     cookie      (IN) Opaque structure used by the server to track its
141                      location in the search results. Pass in NULL on the
142                      first call.
143
144     iscritical  (IN) 0 - The control is not critical to the operation.
145                      non-zero - The control is critical to the operation.
146
147     ctrlp      (OUT) Returns a pointer to the LDAPControl created. This
148                      control SHOULD be freed by calling ldap_control_free()
149                      when done.
150  
151     Ber encoding
152
153     pagedResultsControl ::= SEQUENCE {
154             controlType     1.2.840.113556.1.4.319,
155             criticality     BOOLEAN DEFAULT FALSE,
156             controlValue    searchControlValue }
157
158     searchControlValue ::= SEQUENCE {
159             size            INTEGER (0..maxInt),
160                                     -- requested page size from client
161                                     -- result set size estimate from server
162             cookie          OCTET STRING }
163
164    ---------------------------------------------------------------------------*/
165
166 int
167 ldap_create_page_control(
168         LDAP            *ld,
169         unsigned long   pagesize,
170         struct berval   *cookie,
171         int             iscritical,
172         LDAPControl     **ctrlp )
173 {
174         struct berval   value;
175
176         if ( ctrlp == NULL ) {
177                 ld->ld_errno = LDAP_PARAM_ERROR;
178                 return ld->ld_errno;
179         }
180
181         ld->ld_errno = ldap_create_page_control_value( ld, pagesize, cookie, &value );
182         if ( ld->ld_errno == LDAP_SUCCESS ) {
183                 ld->ld_errno = ldap_create_control( LDAP_CONTROL_PAGEDRESULTS,
184                         NULL, iscritical, ctrlp );
185                 if ( ld->ld_errno == LDAP_SUCCESS ) {
186                         (*ctrlp)->ldctl_value = value;
187                 } else {
188                         LDAP_FREE( value.bv_val );
189                 }
190         }
191
192         return ld->ld_errno;
193 }
194
195
196 /* ---------------------------------------------------------------------------
197     ldap_parse_pageresponse_control
198
199     Decode a page control.
200
201     ld          (IN) An LDAP session handle, as obtained from a call to
202                      ldap_init().
203
204     ctrls       (IN) The address of a NULL-terminated array of
205                      LDAPControl structures, typically obtained by a
206                      call to ldap_parse_result(). The array SHOULD include
207                      a page control.
208
209     count      (OUT) The number of entries returned in the page.
210
211     cookie     (OUT) Opaque structure used by the server to track its
212                      location in the search results. Use ldap_memfree() to
213                      free the bv_val member of this structure.
214
215    ---------------------------------------------------------------------------*/
216
217 int
218 ldap_parse_pageresponse_control(
219         LDAP            *ld,
220         LDAPControl     *ctrl,
221         unsigned long   *countp,
222         struct berval   *cookie )
223 {
224         BerElement *ber;
225         ber_tag_t tag;
226         ber_int_t count;
227
228         if ( ld == NULL || ctrl == NULL || cookie == NULL ) {
229                 ld->ld_errno = LDAP_PARAM_ERROR;
230                 return ld->ld_errno;
231         }
232
233         /* Create a BerElement from the berval returned in the control. */
234         ber = ber_init( &ctrl->ldctl_value );
235
236         if ( ber == NULL ) {
237                 ld->ld_errno = LDAP_NO_MEMORY;
238                 return ld->ld_errno;
239         }
240
241         /* Extract the count and cookie from the control. */
242         tag = ber_scanf( ber, "{io}", &count, cookie );
243         ber_free( ber, 1 );
244
245         if ( tag == LBER_ERROR ) {
246                 ld->ld_errno = LDAP_DECODING_ERROR;
247         } else {
248                 ld->ld_errno = LDAP_SUCCESS;
249
250                 if ( countp != NULL ) {
251                         *countp = (unsigned long)count;
252                 }
253         }
254
255         return ld->ld_errno;
256 }
257
258 /* ---------------------------------------------------------------------------
259     ldap_parse_page_control
260
261     Decode a page control.
262
263     ld          (IN) An LDAP session handle, as obtained from a call to
264                      ldap_init().
265
266     ctrls       (IN) The address of a NULL-terminated array of
267                      LDAPControl structures, typically obtained by a
268                      call to ldap_parse_result(). The array SHOULD include
269                      a page control.
270
271     count      (OUT) The number of entries returned in the page.
272
273     cookie     (OUT) Opaque structure used by the server to track its
274                      location in the search results. Use ber_bvfree() to
275                      free it.
276
277    ---------------------------------------------------------------------------*/
278
279 int
280 ldap_parse_page_control(
281         LDAP            *ld,
282         LDAPControl     **ctrls,
283         unsigned long   *countp,
284         struct berval   **cookiep )
285 {
286         struct berval   cookie;
287         int             i;
288
289         if ( cookiep == NULL ) {
290                 ld->ld_errno = LDAP_PARAM_ERROR;
291                 return ld->ld_errno;
292         }
293
294         if ( ctrls == NULL ) {
295                 ld->ld_errno =  LDAP_CONTROL_NOT_FOUND;
296                 return ld->ld_errno;
297         }
298
299         /* Search the list of control responses for a page control. */
300         for ( i = 0; ctrls[i]; i++ ) {
301                 if ( strcmp( LDAP_CONTROL_PAGEDRESULTS, ctrls[ i ]->ldctl_oid ) == 0 ) {
302                         break;
303                 }
304         }
305
306         /* No page control was found. */
307         if ( ctrls[ i ] == NULL ) {
308                 ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
309                 return ld->ld_errno;
310         }
311
312         ld->ld_errno = ldap_parse_pageresponse_control( ld, ctrls[ i ], countp, &cookie );
313         if ( ld->ld_errno == LDAP_SUCCESS ) {
314                 *cookiep = LDAP_MALLOC( sizeof( struct berval * ) );
315                 if ( *cookiep == NULL ) {
316                         ld->ld_errno = LDAP_NO_MEMORY;
317                 } else {
318                         **cookiep = cookie;
319                 }
320         }
321
322         return ld->ld_errno;
323 }
324