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