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