]> git.sur5r.net Git - openldap/blob - libraries/libldap/pagectrl.c
Merge remote-tracking branch 'origin/mdb.RE/0.9' into OPENLDAP_REL_ENG_2_4
[openldap] / libraries / libldap / pagectrl.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2017 The OpenLDAP Foundation.
5  * Copyright 2006 Hans Leidekker
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16
17 #include "portable.h"
18
19 #include <stdio.h>
20 #include <ac/stdlib.h>
21 #include <ac/string.h>
22 #include <ac/time.h>
23
24 #include "ldap-int.h"
25
26 /* ---------------------------------------------------------------------------
27     ldap_create_page_control_value
28
29     Create and encode the value of the paged results control (RFC 2696).
30
31     ld          (IN) An LDAP session handle
32     pagesize    (IN) Page size requested
33     cookie      (IN) Opaque structure used by the server to track its
34                      location in the search results.  NULL on the
35                      first call.
36     value      (OUT) Control value, SHOULD be freed by calling
37                                          ldap_memfree() when done.
38  
39     pagedResultsControl ::= SEQUENCE {
40             controlType     1.2.840.113556.1.4.319,
41             criticality     BOOLEAN DEFAULT FALSE,
42             controlValue    searchControlValue }
43
44     searchControlValue ::= SEQUENCE {
45             size            INTEGER (0..maxInt),
46                                     -- requested page size from client
47                                     -- result set size estimate from server
48             cookie          OCTET STRING }
49
50    ---------------------------------------------------------------------------*/
51
52 int
53 ldap_create_page_control_value(
54         LDAP *ld,
55         ber_int_t pagesize,
56         struct berval   *cookie,
57         struct berval   *value )
58 {
59         BerElement      *ber = NULL;
60         ber_tag_t       tag;
61         struct berval   null_cookie = { 0, NULL };
62
63         if ( ld == NULL || value == NULL ||
64                 pagesize < 1 || pagesize > LDAP_MAXINT )
65         {
66                 if ( ld )
67                         ld->ld_errno = LDAP_PARAM_ERROR;
68                 return LDAP_PARAM_ERROR;
69         }
70
71         assert( LDAP_VALID( ld ) );
72
73         value->bv_val = NULL;
74         value->bv_len = 0;
75         ld->ld_errno = LDAP_SUCCESS;
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
145         if ( ctrlp == NULL ) {
146                 ld->ld_errno = LDAP_PARAM_ERROR;
147                 return ld->ld_errno;
148         }
149
150         ld->ld_errno = ldap_create_page_control_value( ld,
151                 pagesize, cookie, &value );
152         if ( ld->ld_errno == LDAP_SUCCESS ) {
153                 ld->ld_errno = ldap_control_create( LDAP_CONTROL_PAGEDRESULTS,
154                         iscritical, &value, 0, ctrlp );
155                 if ( ld->ld_errno != LDAP_SUCCESS ) {
156                         LDAP_FREE( value.bv_val );
157                 }
158         }
159
160         return ld->ld_errno;
161 }
162
163
164 /* ---------------------------------------------------------------------------
165     ldap_parse_pageresponse_control
166
167     Decode a page control.
168
169     ld          (IN) An LDAP session handle
170     ctrl        (IN) The page response control
171     count      (OUT) The number of entries in the page.
172     cookie     (OUT) Opaque cookie.  Use ldap_memfree() to
173                      free the bv_val member of this structure.
174
175    ---------------------------------------------------------------------------*/
176
177 int
178 ldap_parse_pageresponse_control(
179         LDAP *ld,
180         LDAPControl *ctrl,
181         ber_int_t *countp,
182         struct berval *cookie )
183 {
184         BerElement *ber;
185         ber_tag_t tag;
186         ber_int_t count;
187
188         if ( ld == NULL || ctrl == NULL || cookie == NULL ) {
189                 if ( ld )
190                         ld->ld_errno = LDAP_PARAM_ERROR;
191                 return LDAP_PARAM_ERROR;
192         }
193
194         /* Create a BerElement from the berval returned in the control. */
195         ber = ber_init( &ctrl->ldctl_value );
196
197         if ( ber == NULL ) {
198                 ld->ld_errno = LDAP_NO_MEMORY;
199                 return ld->ld_errno;
200         }
201
202         /* Extract the count and cookie from the control. */
203         tag = ber_scanf( ber, "{io}", &count, cookie );
204         ber_free( ber, 1 );
205
206         if ( tag == LBER_ERROR ) {
207                 ld->ld_errno = LDAP_DECODING_ERROR;
208         } else {
209                 ld->ld_errno = LDAP_SUCCESS;
210
211                 if ( countp != NULL ) {
212                         *countp = (unsigned long)count;
213                 }
214         }
215
216         return ld->ld_errno;
217 }
218
219 /* ---------------------------------------------------------------------------
220     ldap_parse_page_control
221
222     Decode a page control.
223
224     ld          (IN) An LDAP session handle
225     ctrls       (IN) Response controls
226     count      (OUT) The number of entries in the page.
227     cookie     (OUT) Opaque cookie.  Use ldap_memfree() to
228                      free the bv_val member of this structure.
229
230    ---------------------------------------------------------------------------*/
231
232 int
233 ldap_parse_page_control(
234         LDAP            *ld,
235         LDAPControl     **ctrls,
236         ber_int_t *countp,
237         struct berval   **cookiep )
238 {
239         LDAPControl *c;
240         struct berval   cookie;
241
242         if ( cookiep == NULL ) {
243                 ld->ld_errno = LDAP_PARAM_ERROR;
244                 return ld->ld_errno;
245         }
246
247         if ( ctrls == NULL ) {
248                 ld->ld_errno =  LDAP_CONTROL_NOT_FOUND;
249                 return ld->ld_errno;
250         }
251
252         c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL );
253         if ( c == NULL ) {
254                 /* No page control was found. */
255                 ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
256                 return ld->ld_errno;
257         }
258
259         ld->ld_errno = ldap_parse_pageresponse_control( ld, c, countp, &cookie );
260         if ( ld->ld_errno == LDAP_SUCCESS ) {
261                 *cookiep = LDAP_MALLOC( sizeof( struct berval ) );
262                 if ( *cookiep == NULL ) {
263                         ld->ld_errno = LDAP_NO_MEMORY;
264                 } else {
265                         **cookiep = cookie;
266                 }
267         }
268
269         return ld->ld_errno;
270 }
271