17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
37c478bd9Sstevel@tonic-gate * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate */
57c478bd9Sstevel@tonic-gate
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public
87c478bd9Sstevel@tonic-gate * License Version 1.1 (the "License"); you may not use this file
97c478bd9Sstevel@tonic-gate * except in compliance with the License. You may obtain a copy of
107c478bd9Sstevel@tonic-gate * the License at http://www.mozilla.org/NPL/
117c478bd9Sstevel@tonic-gate *
127c478bd9Sstevel@tonic-gate * Software distributed under the License is distributed on an "AS
137c478bd9Sstevel@tonic-gate * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
147c478bd9Sstevel@tonic-gate * implied. See the License for the specific language governing
157c478bd9Sstevel@tonic-gate * rights and limitations under the License.
167c478bd9Sstevel@tonic-gate *
177c478bd9Sstevel@tonic-gate * The Original Code is Mozilla Communicator client code, released
187c478bd9Sstevel@tonic-gate * March 31, 1998.
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * The Initial Developer of the Original Code is Netscape
217c478bd9Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are
227c478bd9Sstevel@tonic-gate * Copyright (C) 1998-1999 Netscape Communications Corporation. All
237c478bd9Sstevel@tonic-gate * Rights Reserved.
247c478bd9Sstevel@tonic-gate *
257c478bd9Sstevel@tonic-gate * Contributor(s):
267c478bd9Sstevel@tonic-gate */
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate /* vlistctrl.c - virtual list control implementation. */
297c478bd9Sstevel@tonic-gate #include "ldap-int.h"
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate /*
347c478bd9Sstevel@tonic-gate * function to create a VirtualListViewRequest control that can be passed
357c478bd9Sstevel@tonic-gate * to ldap_search_ext() or ldap_search_ext_s(). *ctrlp will be set to a
367c478bd9Sstevel@tonic-gate * freshly allocated LDAPControl structure. Returns an LDAP error code
377c478bd9Sstevel@tonic-gate * (LDAP_SUCCESS if all goes well).
38*1da57d55SToomas Soome *
397c478bd9Sstevel@tonic-gate * Parameters
40*1da57d55SToomas Soome * ld LDAP pointer to the desired connection
417c478bd9Sstevel@tonic-gate *
427c478bd9Sstevel@tonic-gate * ldvlistp the control structure.
437c478bd9Sstevel@tonic-gate *
44*1da57d55SToomas Soome * ctrlp the address of a place to put the constructed control
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate The controlValue is an OCTET STRING
477c478bd9Sstevel@tonic-gate whose value is the BER-encoding of the following SEQUENCE:
48*1da57d55SToomas Soome
497c478bd9Sstevel@tonic-gate VirtualListViewRequest ::= SEQUENCE {
507c478bd9Sstevel@tonic-gate beforeCount INTEGER (0 .. maxInt),
517c478bd9Sstevel@tonic-gate afterCount INTEGER (0 .. maxInt),
527c478bd9Sstevel@tonic-gate CHOICE {
537c478bd9Sstevel@tonic-gate byIndex [0] SEQUENCE {
547c478bd9Sstevel@tonic-gate index INTEGER (0 .. maxInt),
557c478bd9Sstevel@tonic-gate contentCount INTEGER (0 .. maxInt) }
567c478bd9Sstevel@tonic-gate byValue [1] greaterThanOrEqual assertionValue }
57*1da57d55SToomas Soome
587c478bd9Sstevel@tonic-gate beforeCount indicates how many entries before the target entry the
597c478bd9Sstevel@tonic-gate client wants the server to send. afterCount indicates the number of
607c478bd9Sstevel@tonic-gate entries after the target entry the client wants the server to send.
617c478bd9Sstevel@tonic-gate index and contentCount identify the target entry
627c478bd9Sstevel@tonic-gate greaterThanOrEqual is an attribute assertion value defined in
637c478bd9Sstevel@tonic-gate [LDAPv3]. If present, the value supplied in greaterThanOrEqual is used
647c478bd9Sstevel@tonic-gate to determine the target entry by comparison with the values of the
657c478bd9Sstevel@tonic-gate attribute specified as the primary sort key. The first list entry who's
667c478bd9Sstevel@tonic-gate value is no less than the supplied value is the target entry.
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate */
697c478bd9Sstevel@tonic-gate
70*1da57d55SToomas Soome int
717c478bd9Sstevel@tonic-gate LDAP_CALL
ldap_create_virtuallist_control(LDAP * ld,LDAPVirtualList * ldvlistp,LDAPControl ** ctrlp)72*1da57d55SToomas Soome ldap_create_virtuallist_control(
73*1da57d55SToomas Soome LDAP *ld,
747c478bd9Sstevel@tonic-gate LDAPVirtualList *ldvlistp,
75*1da57d55SToomas Soome LDAPControl **ctrlp
767c478bd9Sstevel@tonic-gate )
777c478bd9Sstevel@tonic-gate {
787c478bd9Sstevel@tonic-gate BerElement *ber;
797c478bd9Sstevel@tonic-gate int rc;
80*1da57d55SToomas Soome
817c478bd9Sstevel@tonic-gate if (!NSLDAPI_VALID_LDAP_POINTER( ld )) {
827c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate if ( NULL == ctrlp || NULL == ldvlistp ) {
877c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
887c478bd9Sstevel@tonic-gate return ( LDAP_PARAM_ERROR );
897c478bd9Sstevel@tonic-gate }
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate /* create a ber package to hold the controlValue */
92*1da57d55SToomas Soome if ( LDAP_SUCCESS != nsldapi_alloc_ber_with_options( ld, &ber ) )
937c478bd9Sstevel@tonic-gate {
947c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
957c478bd9Sstevel@tonic-gate return( LDAP_NO_MEMORY );
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate
98*1da57d55SToomas Soome if ( LBER_ERROR == ber_printf( ber,
99*1da57d55SToomas Soome "{ii",
1007c478bd9Sstevel@tonic-gate (int)ldvlistp->ldvlist_before_count,
101*1da57d55SToomas Soome (int)ldvlistp->ldvlist_after_count ))
1027c478bd9Sstevel@tonic-gate /* XXX lossy casts */
1037c478bd9Sstevel@tonic-gate {
1047c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL );
1057c478bd9Sstevel@tonic-gate ber_free( ber, 1 );
1067c478bd9Sstevel@tonic-gate return( LDAP_ENCODING_ERROR );
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate if (NULL == ldvlistp->ldvlist_attrvalue)
1107c478bd9Sstevel@tonic-gate {
111*1da57d55SToomas Soome if ( LBER_ERROR == ber_printf( ber,
112*1da57d55SToomas Soome "t{ii}}",
1137c478bd9Sstevel@tonic-gate LDAP_TAG_VLV_BY_INDEX,
114*1da57d55SToomas Soome (int)ldvlistp->ldvlist_index,
115*1da57d55SToomas Soome (int)ldvlistp->ldvlist_size ) )
1167c478bd9Sstevel@tonic-gate /* XXX lossy casts */
1177c478bd9Sstevel@tonic-gate {
1187c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL );
1197c478bd9Sstevel@tonic-gate ber_free( ber, 1 );
1207c478bd9Sstevel@tonic-gate return( LDAP_ENCODING_ERROR );
1217c478bd9Sstevel@tonic-gate }
122*1da57d55SToomas Soome }
123*1da57d55SToomas Soome else
1247c478bd9Sstevel@tonic-gate {
125*1da57d55SToomas Soome if ( LBER_ERROR == ber_printf( ber,
126*1da57d55SToomas Soome "to}",
1277c478bd9Sstevel@tonic-gate LDAP_TAG_VLV_BY_VALUE,
1287c478bd9Sstevel@tonic-gate ldvlistp->ldvlist_attrvalue,
1297c478bd9Sstevel@tonic-gate (int)strlen( ldvlistp->ldvlist_attrvalue )) ) {
1307c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL );
1317c478bd9Sstevel@tonic-gate ber_free( ber, 1 );
1327c478bd9Sstevel@tonic-gate return( LDAP_ENCODING_ERROR );
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate
137*1da57d55SToomas Soome rc = nsldapi_build_control( LDAP_CONTROL_VLVREQUEST ,
138*1da57d55SToomas Soome ber,
139*1da57d55SToomas Soome 1,
1407c478bd9Sstevel@tonic-gate 1,
1417c478bd9Sstevel@tonic-gate ctrlp );
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
1447c478bd9Sstevel@tonic-gate return( rc );
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate /*
1507c478bd9Sstevel@tonic-gate * function to find and parse a VirtualListViewResponse control contained in
1517c478bd9Sstevel@tonic-gate * "ctrls" *target_posp, *list_sizep, and *errcodep are set based on its
1527c478bd9Sstevel@tonic-gate * contents. Returns an LDAP error code that indicates whether the parsing
1537c478bd9Sstevel@tonic-gate * itself was successful (LDAP_SUCCESS if all goes well).
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate The controlValue is an OCTET STRING, whose value
1567c478bd9Sstevel@tonic-gate is the BER encoding of a value of the following SEQUENCE:
157*1da57d55SToomas Soome
1587c478bd9Sstevel@tonic-gate VirtualListViewResponse ::= SEQUENCE {
1597c478bd9Sstevel@tonic-gate targetPosition INTEGER (0 .. maxInt),
1607c478bd9Sstevel@tonic-gate contentCount INTEGER (0 .. maxInt),
1617c478bd9Sstevel@tonic-gate virtualListViewResult ENUMERATED {
1627c478bd9Sstevel@tonic-gate success (0),
1637c478bd9Sstevel@tonic-gate operatonsError (1),
1647c478bd9Sstevel@tonic-gate unwillingToPerform (53),
1657c478bd9Sstevel@tonic-gate insufficientAccessRights (50),
1667c478bd9Sstevel@tonic-gate busy (51),
1677c478bd9Sstevel@tonic-gate timeLimitExceeded (3),
1687c478bd9Sstevel@tonic-gate adminLimitExceeded (11),
1697c478bd9Sstevel@tonic-gate sortControlMissing (60),
1707c478bd9Sstevel@tonic-gate indexRangeError (61),
1717c478bd9Sstevel@tonic-gate other (80) } }
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate */
174*1da57d55SToomas Soome int
1757c478bd9Sstevel@tonic-gate LDAP_CALL
ldap_parse_virtuallist_control(LDAP * ld,LDAPControl ** ctrls,unsigned long * target_posp,unsigned long * list_sizep,int * errcodep)1767c478bd9Sstevel@tonic-gate ldap_parse_virtuallist_control
177*1da57d55SToomas Soome (
178*1da57d55SToomas Soome LDAP *ld,
1797c478bd9Sstevel@tonic-gate LDAPControl **ctrls,
180*1da57d55SToomas Soome unsigned long *target_posp,
181*1da57d55SToomas Soome unsigned long *list_sizep,
1827c478bd9Sstevel@tonic-gate int *errcodep
1837c478bd9Sstevel@tonic-gate )
1847c478bd9Sstevel@tonic-gate {
1857c478bd9Sstevel@tonic-gate BerElement *ber;
1867c478bd9Sstevel@tonic-gate int i, foundListControl, errcode;
1877c478bd9Sstevel@tonic-gate LDAPControl *listCtrlp;
1887c478bd9Sstevel@tonic-gate unsigned long target_pos, list_size;
1897c478bd9Sstevel@tonic-gate int target_pos_int, list_size_int;
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
1927c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate /* only ldapv3 or higher can do virtual lists. */
1967c478bd9Sstevel@tonic-gate if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) {
1977c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL );
1987c478bd9Sstevel@tonic-gate return( LDAP_NOT_SUPPORTED );
1997c478bd9Sstevel@tonic-gate }
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate /* find the listControl in the list of controls if it exists */
2027c478bd9Sstevel@tonic-gate if ( ctrls == NULL ) {
2037c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL );
2047c478bd9Sstevel@tonic-gate return ( LDAP_CONTROL_NOT_FOUND );
205*1da57d55SToomas Soome }
206*1da57d55SToomas Soome
2077c478bd9Sstevel@tonic-gate foundListControl = 0;
2087c478bd9Sstevel@tonic-gate for ( i = 0; (( ctrls[i] != NULL ) && ( !foundListControl )); i++ ) {
209*1da57d55SToomas Soome foundListControl = !strcmp( ctrls[i]->ldctl_oid,
2107c478bd9Sstevel@tonic-gate LDAP_CONTROL_VLVRESPONSE );
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate if ( !foundListControl ) {
2137c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL );
2147c478bd9Sstevel@tonic-gate return ( LDAP_CONTROL_NOT_FOUND );
2157c478bd9Sstevel@tonic-gate } else {
2167c478bd9Sstevel@tonic-gate /* let local var point to the listControl */
217*1da57d55SToomas Soome listCtrlp = ctrls[i-1];
2187c478bd9Sstevel@tonic-gate }
2197c478bd9Sstevel@tonic-gate
2207c478bd9Sstevel@tonic-gate /* allocate a Ber element with the contents of the list_control's struct berval */
2217c478bd9Sstevel@tonic-gate if ( ( ber = ber_init( &listCtrlp->ldctl_value ) ) == NULL ) {
2227c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
2237c478bd9Sstevel@tonic-gate return( LDAP_NO_MEMORY );
224*1da57d55SToomas Soome }
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate /* decode the result from the Berelement */
2277c478bd9Sstevel@tonic-gate if ( LBER_ERROR == ber_scanf( ber, "{iie}", &target_pos_int, &list_size_int,
2287c478bd9Sstevel@tonic-gate &errcode ) ) {
2297c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
2307c478bd9Sstevel@tonic-gate ber_free( ber, 1 );
2317c478bd9Sstevel@tonic-gate return( LDAP_DECODING_ERROR );
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate target_pos = target_pos_int;
2357c478bd9Sstevel@tonic-gate list_size = list_size_int;
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate if ( target_posp != NULL ) {
2387c478bd9Sstevel@tonic-gate *target_posp = target_pos;
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate if ( list_sizep != NULL ) {
2417c478bd9Sstevel@tonic-gate *list_sizep = list_size;
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate if ( errcodep != NULL ) {
2447c478bd9Sstevel@tonic-gate *errcodep = errcode;
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate /* the ber encoding is no longer needed */
2487c478bd9Sstevel@tonic-gate ber_free(ber,1);
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate return(LDAP_SUCCESS);
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate }
253