xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/pagectrl.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: pagectrl.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $	*/
2 
3 /* OpenLDAP: pkg/ldap/libraries/libldap/pagectrl.c,v 1.5.2.6 2009/01/22 00:00:55 kurt Exp */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1998-2009 The OpenLDAP Foundation.
7  * Copyright 2006 Hans Leidekker
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
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 	ld->ld_errno = LDAP_SUCCESS;
78 
79 	if ( cookie == NULL ) {
80 		cookie = &null_cookie;
81 	}
82 
83 	ber = ldap_alloc_ber_with_options( ld );
84 	if ( ber == NULL ) {
85 		ld->ld_errno = LDAP_NO_MEMORY;
86 		return ld->ld_errno;
87 	}
88 
89 	tag = ber_printf( ber, "{iO}", pagesize, cookie );
90 	if ( tag == LBER_ERROR ) {
91 		ld->ld_errno = LDAP_ENCODING_ERROR;
92 		goto done;
93 	}
94 
95 	if ( ber_flatten2( ber, value, 1 ) == -1 ) {
96 		ld->ld_errno = LDAP_NO_MEMORY;
97 	}
98 
99 done:;
100 	if ( ber != NULL ) {
101 		ber_free( ber, 1 );
102 	}
103 
104 	return ld->ld_errno;
105 }
106 
107 
108 /* ---------------------------------------------------------------------------
109     ldap_create_page_control
110 
111     Create and encode a page control.
112 
113     ld          (IN) An LDAP session handle
114     pagesize    (IN) Page size requested
115     cookie      (IN) Opaque structure used by the server to track its
116                      location in the search results.  NULL on the
117                      first call.
118     value      (OUT) Control value, SHOULD be freed by calling
119 					 ldap_memfree() when done.
120     iscritical  (IN) Criticality
121     ctrlp      (OUT) LDAP control, SHOULD be freed by calling
122 					 ldap_control_free() when done.
123 
124     pagedResultsControl ::= SEQUENCE {
125             controlType     1.2.840.113556.1.4.319,
126             criticality     BOOLEAN DEFAULT FALSE,
127             controlValue    searchControlValue }
128 
129     searchControlValue ::= SEQUENCE {
130             size            INTEGER (0..maxInt),
131                                     -- requested page size from client
132                                     -- result set size estimate from server
133             cookie          OCTET STRING }
134 
135    ---------------------------------------------------------------------------*/
136 
137 int
138 ldap_create_page_control(
139 	LDAP		*ld,
140 	ber_int_t	pagesize,
141 	struct berval	*cookie,
142 	int		iscritical,
143 	LDAPControl	**ctrlp )
144 {
145 	struct berval	value;
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 		ld->ld_errno = ldap_control_create( LDAP_CONTROL_PAGEDRESULTS,
156 			iscritical, &value, 0, ctrlp );
157 		if ( ld->ld_errno != LDAP_SUCCESS ) {
158 			LDAP_FREE( value.bv_val );
159 		}
160 	}
161 
162 	return ld->ld_errno;
163 }
164 
165 
166 /* ---------------------------------------------------------------------------
167     ldap_parse_pageresponse_control
168 
169     Decode a page control.
170 
171     ld          (IN) An LDAP session handle
172     ctrl        (IN) The page response control
173     count      (OUT) The number of entries in the page.
174     cookie     (OUT) Opaque cookie.  Use ldap_memfree() to
175                      free the bv_val member of this structure.
176 
177    ---------------------------------------------------------------------------*/
178 
179 int
180 ldap_parse_pageresponse_control(
181 	LDAP *ld,
182 	LDAPControl *ctrl,
183 	ber_int_t *countp,
184 	struct berval *cookie )
185 {
186 	BerElement *ber;
187 	ber_tag_t tag;
188 	ber_int_t count;
189 
190 	if ( ld == NULL || ctrl == NULL || cookie == NULL ) {
191 		if ( ld )
192 			ld->ld_errno = LDAP_PARAM_ERROR;
193 		return LDAP_PARAM_ERROR;
194 	}
195 
196 	/* Create a BerElement from the berval returned in the control. */
197 	ber = ber_init( &ctrl->ldctl_value );
198 
199 	if ( ber == NULL ) {
200 		ld->ld_errno = LDAP_NO_MEMORY;
201 		return ld->ld_errno;
202 	}
203 
204 	/* Extract the count and cookie from the control. */
205 	tag = ber_scanf( ber, "{io}", &count, cookie );
206         ber_free( ber, 1 );
207 
208 	if ( tag == LBER_ERROR ) {
209 		ld->ld_errno = LDAP_DECODING_ERROR;
210 	} else {
211 		ld->ld_errno = LDAP_SUCCESS;
212 
213 		if ( countp != NULL ) {
214 			*countp = (unsigned long)count;
215 		}
216 	}
217 
218 	return ld->ld_errno;
219 }
220 
221 /* ---------------------------------------------------------------------------
222     ldap_parse_page_control
223 
224     Decode a page control.
225 
226     ld          (IN) An LDAP session handle
227     ctrls       (IN) Response controls
228     count      (OUT) The number of entries in the page.
229     cookie     (OUT) Opaque cookie.  Use ldap_memfree() to
230                      free the bv_val member of this structure.
231 
232    ---------------------------------------------------------------------------*/
233 
234 int
235 ldap_parse_page_control(
236 	LDAP		*ld,
237 	LDAPControl	**ctrls,
238 	ber_int_t *countp,
239 	struct berval	**cookiep )
240 {
241 	LDAPControl *c;
242 	struct berval	cookie;
243 
244 	if ( cookiep == NULL ) {
245 		ld->ld_errno = LDAP_PARAM_ERROR;
246 		return ld->ld_errno;
247 	}
248 
249 	if ( ctrls == NULL ) {
250 		ld->ld_errno =  LDAP_CONTROL_NOT_FOUND;
251 		return ld->ld_errno;
252 	}
253 
254 	c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL );
255 	if ( c == NULL ) {
256 		/* No page control was found. */
257 		ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
258 		return ld->ld_errno;
259 	}
260 
261 	ld->ld_errno = ldap_parse_pageresponse_control( ld, c, countp, &cookie );
262 	if ( ld->ld_errno == LDAP_SUCCESS ) {
263 		*cookiep = LDAP_MALLOC( sizeof( struct berval ) );
264 		if ( *cookiep == NULL ) {
265 			ld->ld_errno = LDAP_NO_MEMORY;
266 		} else {
267 			**cookiep = cookie;
268 		}
269 	}
270 
271 	return ld->ld_errno;
272 }
273 
274