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 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 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