1/*	$NetBSD$	*/
2
3/* OpenLDAP: pkg/ldap/libraries/libldap/pagectrl.c,v 1.5.2.7 2010/04/13 20:22:59 kurt Exp */
4/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 1998-2010 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
54int
55ldap_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
99done:;
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
137int
138ldap_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
179int
180ldap_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
234int
235ldap_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