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