]> git.sur5r.net Git - openldap/blob - libraries/libldap/pagectrl.c
40093cb6fd5ed48ead9b6d6d3d8cd16b6a1a9ace
[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) The Internet Society (1999)
16  * ASN.1 fragments are from RFC 2696; see RFC for full legal notices.
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 /* ---------------------------------------------------------------------------
29     ldap_create_page_control_value
30
31     Create and encode the value of the paged results control (RFC 2696).
32
33     ld          (IN) An LDAP session handle
34     pagesize    (IN) Page size requested
35     cookie      (IN) Opaque structure used by the server to track its
36                      location in the search results.  NULL on the
37                      first call.
38     value      (OUT) Control value, SHOULD be freed by calling
39                                          ldap_memfree() when done.
40  
41     pagedResultsControl ::= SEQUENCE {
42             controlType     1.2.840.113556.1.4.319,
43             criticality     BOOLEAN DEFAULT FALSE,
44             controlValue    searchControlValue }
45
46     searchControlValue ::= SEQUENCE {
47             size            INTEGER (0..maxInt),
48                                     -- requested page size from client
49                                     -- result set size estimate from server
50             cookie          OCTET STRING }
51
52    ---------------------------------------------------------------------------*/
53
54 int
55 ldap_create_page_control_value(
56         LDAP *ld,
57         ber_int_t pagesize,
58         struct berval   *cookie,
59         struct berval   *value )
60 {
61         BerElement      *ber = NULL;
62         ber_tag_t       tag;
63         struct berval   null_cookie = { 0, NULL };
64
65         if ( ld == NULL || value == NULL ||
66                 pagesize < 1 || pagesize > LDAP_MAXINT )
67         {
68                 ld->ld_errno = LDAP_PARAM_ERROR;
69                 return ld->ld_errno;
70         }
71
72         assert( LDAP_VALID( ld ) );
73
74         value->bv_val = NULL;
75         value->bv_len = 0;
76
77         if ( cookie == NULL ) {
78                 cookie = &null_cookie;
79         }
80
81         ber = ldap_alloc_ber_with_options( ld );
82         if ( ber == NULL ) {
83                 ld->ld_errno = LDAP_NO_MEMORY;
84                 return ld->ld_errno;
85         }
86
87         tag = ber_printf( ber, "{iO}", pagesize, cookie );
88         if ( tag == LBER_ERROR ) {
89                 ld->ld_errno = LDAP_ENCODING_ERROR;
90                 goto done;
91         }
92
93         if ( ber_flatten2( ber, value, 1 ) == -1 ) {
94                 ld->ld_errno = LDAP_NO_MEMORY;
95         }
96
97 done:;
98         if ( ber != NULL ) {
99                 ber_free( ber, 1 );
100         }
101
102         return ld->ld_errno;
103 }
104
105
106 /* ---------------------------------------------------------------------------
107     ldap_create_page_control
108
109     Create and encode a page control.
110
111     ld          (IN) An LDAP session handle
112     pagesize    (IN) Page size requested
113     cookie      (IN) Opaque structure used by the server to track its
114                      location in the search results.  NULL on the
115                      first call.
116     value      (OUT) Control value, SHOULD be freed by calling
117                                          ldap_memfree() when done.
118     iscritical  (IN) Criticality
119     ctrlp      (OUT) LDAP control, SHOULD be freed by calling
120                                          ldap_control_free() when done.
121  
122     pagedResultsControl ::= SEQUENCE {
123             controlType     1.2.840.113556.1.4.319,
124             criticality     BOOLEAN DEFAULT FALSE,
125             controlValue    searchControlValue }
126
127     searchControlValue ::= SEQUENCE {
128             size            INTEGER (0..maxInt),
129                                     -- requested page size from client
130                                     -- result set size estimate from server
131             cookie          OCTET STRING }
132
133    ---------------------------------------------------------------------------*/
134
135 int
136 ldap_create_page_control(
137         LDAP            *ld,
138         ber_int_t       pagesize,
139         struct berval   *cookie,
140         int             iscritical,
141         LDAPControl     **ctrlp )
142 {
143         struct berval   value;
144         BerElement      *ber;
145
146         if ( ctrlp == NULL ) {
147                 ld->ld_errno = LDAP_PARAM_ERROR;
148                 return ld->ld_errno;
149         }
150
151         ld->ld_errno = ldap_create_page_control_value( ld,
152                 pagesize, cookie, &value );
153         if ( ld->ld_errno == LDAP_SUCCESS ) {
154                 if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
155                         ld->ld_errno = LDAP_NO_MEMORY;
156                         return LDAP_NO_MEMORY;
157                 }
158
159                 ld->ld_errno = ldap_create_control( LDAP_CONTROL_PAGEDRESULTS,
160                         ber, iscritical, ctrlp );
161                 if ( ld->ld_errno == LDAP_SUCCESS ) {
162                         (*ctrlp)->ldctl_value = value;
163                 } else {
164                         LDAP_FREE( value.bv_val );
165                 }
166                 ber_free(ber, 1);
167         }
168
169         return ld->ld_errno;
170 }
171
172
173 /* ---------------------------------------------------------------------------
174     ldap_parse_pageresponse_control
175
176     Decode a page control.
177
178     ld          (IN) An LDAP session handle
179     ctrl        (IN) The page response control
180     count      (OUT) The number of entries in the page.
181     cookie     (OUT) Opaque cookie.  Use ldap_memfree() to
182                      free the bv_val member of this structure.
183
184    ---------------------------------------------------------------------------*/
185
186 int
187 ldap_parse_pageresponse_control(
188         LDAP *ld,
189         LDAPControl *ctrl,
190         ber_int_t *countp,
191         struct berval *cookie )
192 {
193         BerElement *ber;
194         ber_tag_t tag;
195         ber_int_t count;
196
197         if ( ld == NULL || ctrl == NULL || cookie == NULL ) {
198                 ld->ld_errno = LDAP_PARAM_ERROR;
199                 return ld->ld_errno;
200         }
201
202         /* Create a BerElement from the berval returned in the control. */
203         ber = ber_init( &ctrl->ldctl_value );
204
205         if ( ber == NULL ) {
206                 ld->ld_errno = LDAP_NO_MEMORY;
207                 return ld->ld_errno;
208         }
209
210         /* Extract the count and cookie from the control. */
211         tag = ber_scanf( ber, "{io}", &count, cookie );
212         ber_free( ber, 1 );
213
214         if ( tag == LBER_ERROR ) {
215                 ld->ld_errno = LDAP_DECODING_ERROR;
216         } else {
217                 ld->ld_errno = LDAP_SUCCESS;
218
219                 if ( countp != NULL ) {
220                         *countp = (unsigned long)count;
221                 }
222         }
223
224         return ld->ld_errno;
225 }
226
227 /* ---------------------------------------------------------------------------
228     ldap_parse_page_control
229
230     Decode a page control.
231
232     ld          (IN) An LDAP session handle
233     ctrls       (IN) Response controls
234     count      (OUT) The number of entries in the page.
235     cookie     (OUT) Opaque cookie.  Use ldap_memfree() to
236                      free the bv_val member of this structure.
237
238    ---------------------------------------------------------------------------*/
239
240 int
241 ldap_parse_page_control(
242         LDAP            *ld,
243         LDAPControl     **ctrls,
244         ber_int_t *countp,
245         struct berval   **cookiep )
246 {
247         LDAPControl *c;
248         struct berval   cookie;
249
250         if ( cookiep == NULL ) {
251                 ld->ld_errno = LDAP_PARAM_ERROR;
252                 return ld->ld_errno;
253         }
254
255         if ( ctrls == NULL ) {
256                 ld->ld_errno =  LDAP_CONTROL_NOT_FOUND;
257                 return ld->ld_errno;
258         }
259
260         c = ldap_find_control( LDAP_CONTROL_PAGEDRESULTS, ctrls );
261         if ( c == NULL ) {
262                 /* No page control was found. */
263                 ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
264                 return ld->ld_errno;
265         }
266
267         ld->ld_errno = ldap_parse_pageresponse_control( ld, c, countp, &cookie );
268         if ( ld->ld_errno == LDAP_SUCCESS ) {
269                 *cookiep = LDAP_MALLOC( sizeof( struct berval * ) );
270                 if ( *cookiep == NULL ) {
271                         ld->ld_errno = LDAP_NO_MEMORY;
272                 } else {
273                         **cookiep = cookie;
274                 }
275         }
276
277         return ld->ld_errno;
278 }
279