1 /*
2 * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 #pragma ident "%Z%%M% %I% %E% SMI"
7
8 /*
9 * The contents of this file are subject to the Netscape Public
10 * License Version 1.1 (the "License"); you may not use this file
11 * except in compliance with the License. You may obtain a copy of
12 * the License at http://www.mozilla.org/NPL/
13 *
14 * Software distributed under the License is distributed on an "AS
15 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
16 * implied. See the License for the specific language governing
17 * rights and limitations under the License.
18 *
19 * The Original Code is Mozilla Communicator client code, released
20 * March 31, 1998.
21 *
22 * The Initial Developer of the Original Code is Netscape
23 * Communications Corporation. Portions created by Netscape are
24 * Copyright (C) 1998-1999 Netscape Communications Corporation. All
25 * Rights Reserved.
26 *
27 * Contributor(s):
28 */
29
30 /* vlistctrl.c - virtual list control implementation. */
31 #include "ldap-int.h"
32
33
34
35 /*
36 * function to create a VirtualListViewRequest control that can be passed
37 * to ldap_search_ext() or ldap_search_ext_s(). *ctrlp will be set to a
38 * freshly allocated LDAPControl structure. Returns an LDAP error code
39 * (LDAP_SUCCESS if all goes well).
40 *
41 * Parameters
42 * ld LDAP pointer to the desired connection
43 *
44 * ldvlistp the control structure.
45 *
46 * ctrlp the address of a place to put the constructed control
47
48 The controlValue is an OCTET STRING
49 whose value is the BER-encoding of the following SEQUENCE:
50
51 VirtualListViewRequest ::= SEQUENCE {
52 beforeCount INTEGER (0 .. maxInt),
53 afterCount INTEGER (0 .. maxInt),
54 CHOICE {
55 byIndex [0] SEQUENCE {
56 index INTEGER (0 .. maxInt),
57 contentCount INTEGER (0 .. maxInt) }
58 byValue [1] greaterThanOrEqual assertionValue }
59
60 beforeCount indicates how many entries before the target entry the
61 client wants the server to send. afterCount indicates the number of
62 entries after the target entry the client wants the server to send.
63 index and contentCount identify the target entry
64 greaterThanOrEqual is an attribute assertion value defined in
65 [LDAPv3]. If present, the value supplied in greaterThanOrEqual is used
66 to determine the target entry by comparison with the values of the
67 attribute specified as the primary sort key. The first list entry who's
68 value is no less than the supplied value is the target entry.
69
70 */
71
72 int
73 LDAP_CALL
ldap_create_virtuallist_control(LDAP * ld,LDAPVirtualList * ldvlistp,LDAPControl ** ctrlp)74 ldap_create_virtuallist_control(
75 LDAP *ld,
76 LDAPVirtualList *ldvlistp,
77 LDAPControl **ctrlp
78 )
79 {
80 BerElement *ber;
81 int rc;
82
83 if (!NSLDAPI_VALID_LDAP_POINTER( ld )) {
84 return( LDAP_PARAM_ERROR );
85 }
86
87
88 if ( NULL == ctrlp || NULL == ldvlistp ) {
89 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
90 return ( LDAP_PARAM_ERROR );
91 }
92
93 /* create a ber package to hold the controlValue */
94 if ( LDAP_SUCCESS != nsldapi_alloc_ber_with_options( ld, &ber ) )
95 {
96 LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
97 return( LDAP_NO_MEMORY );
98 }
99
100 if ( LBER_ERROR == ber_printf( ber,
101 "{ii",
102 (int)ldvlistp->ldvlist_before_count,
103 (int)ldvlistp->ldvlist_after_count ))
104 /* XXX lossy casts */
105 {
106 LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL );
107 ber_free( ber, 1 );
108 return( LDAP_ENCODING_ERROR );
109 }
110
111 if (NULL == ldvlistp->ldvlist_attrvalue)
112 {
113 if ( LBER_ERROR == ber_printf( ber,
114 "t{ii}}",
115 LDAP_TAG_VLV_BY_INDEX,
116 (int)ldvlistp->ldvlist_index,
117 (int)ldvlistp->ldvlist_size ) )
118 /* XXX lossy casts */
119 {
120 LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL );
121 ber_free( ber, 1 );
122 return( LDAP_ENCODING_ERROR );
123 }
124 }
125 else
126 {
127 if ( LBER_ERROR == ber_printf( ber,
128 "to}",
129 LDAP_TAG_VLV_BY_VALUE,
130 ldvlistp->ldvlist_attrvalue,
131 (int)strlen( ldvlistp->ldvlist_attrvalue )) ) {
132 LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL );
133 ber_free( ber, 1 );
134 return( LDAP_ENCODING_ERROR );
135 }
136 }
137
138
139 rc = nsldapi_build_control( LDAP_CONTROL_VLVREQUEST ,
140 ber,
141 1,
142 1,
143 ctrlp );
144
145 LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
146 return( rc );
147
148 }
149
150
151 /*
152 * function to find and parse a VirtualListViewResponse control contained in
153 * "ctrls" *target_posp, *list_sizep, and *errcodep are set based on its
154 * contents. Returns an LDAP error code that indicates whether the parsing
155 * itself was successful (LDAP_SUCCESS if all goes well).
156
157 The controlValue is an OCTET STRING, whose value
158 is the BER encoding of a value of the following SEQUENCE:
159
160 VirtualListViewResponse ::= SEQUENCE {
161 targetPosition INTEGER (0 .. maxInt),
162 contentCount INTEGER (0 .. maxInt),
163 virtualListViewResult ENUMERATED {
164 success (0),
165 operatonsError (1),
166 unwillingToPerform (53),
167 insufficientAccessRights (50),
168 busy (51),
169 timeLimitExceeded (3),
170 adminLimitExceeded (11),
171 sortControlMissing (60),
172 indexRangeError (61),
173 other (80) } }
174
175 */
176 int
177 LDAP_CALL
ldap_parse_virtuallist_control(LDAP * ld,LDAPControl ** ctrls,unsigned long * target_posp,unsigned long * list_sizep,int * errcodep)178 ldap_parse_virtuallist_control
179 (
180 LDAP *ld,
181 LDAPControl **ctrls,
182 unsigned long *target_posp,
183 unsigned long *list_sizep,
184 int *errcodep
185 )
186 {
187 BerElement *ber;
188 int i, foundListControl, errcode;
189 LDAPControl *listCtrlp;
190 unsigned long target_pos, list_size;
191 int target_pos_int, list_size_int;
192
193 if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
194 return( LDAP_PARAM_ERROR );
195 }
196
197 /* only ldapv3 or higher can do virtual lists. */
198 if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) {
199 LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL );
200 return( LDAP_NOT_SUPPORTED );
201 }
202
203 /* find the listControl in the list of controls if it exists */
204 if ( ctrls == NULL ) {
205 LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL );
206 return ( LDAP_CONTROL_NOT_FOUND );
207 }
208
209 foundListControl = 0;
210 for ( i = 0; (( ctrls[i] != NULL ) && ( !foundListControl )); i++ ) {
211 foundListControl = !strcmp( ctrls[i]->ldctl_oid,
212 LDAP_CONTROL_VLVRESPONSE );
213 }
214 if ( !foundListControl ) {
215 LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL );
216 return ( LDAP_CONTROL_NOT_FOUND );
217 } else {
218 /* let local var point to the listControl */
219 listCtrlp = ctrls[i-1];
220 }
221
222 /* allocate a Ber element with the contents of the list_control's struct berval */
223 if ( ( ber = ber_init( &listCtrlp->ldctl_value ) ) == NULL ) {
224 LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
225 return( LDAP_NO_MEMORY );
226 }
227
228 /* decode the result from the Berelement */
229 if ( LBER_ERROR == ber_scanf( ber, "{iie}", &target_pos_int, &list_size_int,
230 &errcode ) ) {
231 LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
232 ber_free( ber, 1 );
233 return( LDAP_DECODING_ERROR );
234 }
235
236 target_pos = target_pos_int;
237 list_size = list_size_int;
238
239 if ( target_posp != NULL ) {
240 *target_posp = target_pos;
241 }
242 if ( list_sizep != NULL ) {
243 *list_sizep = list_size;
244 }
245 if ( errcodep != NULL ) {
246 *errcodep = errcode;
247 }
248
249 /* the ber encoding is no longer needed */
250 ber_free(ber,1);
251
252 return(LDAP_SUCCESS);
253
254 }
255