Back to index

openldap  2.4.31
vlvctrl.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 1998-2012 The OpenLDAP Foundation.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted only as authorized by the OpenLDAP
00009  * Public License.
00010  *
00011  * A copy of this license is available in the file LICENSE in the
00012  * top-level directory of the distribution or, alternatively, at
00013  * <http://www.OpenLDAP.org/license.html>.
00014  */
00015 /* Portions Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
00016  *
00017  * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
00018  * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
00019  * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
00020  * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
00021  * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
00022  * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
00023  * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
00024  * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
00025  *---
00026  * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License
00027  * can be found in the file "build/LICENSE-2.0.1" in this distribution
00028  * of OpenLDAP Software.
00029  */
00030 
00031 #include "portable.h"
00032 
00033 #include <stdio.h>
00034 #include <ac/stdlib.h>
00035 #include <ac/string.h>
00036 #include <ac/time.h>
00037 
00038 #include "ldap-int.h"
00039 
00040 #define LDAP_VLVBYINDEX_IDENTIFIER     0xa0L
00041 #define LDAP_VLVBYVALUE_IDENTIFIER     0x81L
00042 #define LDAP_VLVCONTEXT_IDENTIFIER     0x04L
00043 
00044 
00045 /*---
00046    ldap_create_vlv_control
00047    
00048    Create and encode the Virtual List View control.
00049 
00050    ld        (IN)  An LDAP session handle.
00051    
00052    vlvinfop  (IN)  The address of an LDAPVLVInfo structure whose contents 
00053                                are used to construct the value of the control
00054                                that is created.
00055    
00056    value     (OUT) A struct berval that contains the value to be assigned to the ldctl_value member
00057                                of an LDAPControl structure that contains the 
00058                                VirtualListViewRequest control.
00059                                The bv_val member of the berval structure
00060                                SHOULD be freed when it is no longer in use by
00061                                calling ldap_memfree().
00062                                      
00063    
00064    Ber encoding
00065    
00066    VirtualListViewRequest ::= SEQUENCE {
00067               beforeCount  INTEGER (0 .. maxInt),
00068               afterCount   INTEGER (0 .. maxInt),
00069               CHOICE {
00070                             byoffset [0] SEQUENCE, {
00071                             offset        INTEGER (0 .. maxInt),
00072                             contentCount  INTEGER (0 .. maxInt) }
00073                             [1] greaterThanOrEqual assertionValue }
00074               contextID     OCTET STRING OPTIONAL }
00075          
00076    
00077    Note:  The first time the VLV control is created, the ldvlv_context
00078                 field of the LDAPVLVInfo structure should be set to NULL.
00079                 The context obtained from calling ldap_parse_vlv_control()
00080                 should be used as the context in the next ldap_create_vlv_control
00081                 call.
00082 
00083  ---*/
00084 
00085 int
00086 ldap_create_vlv_control_value(
00087        LDAP *ld,
00088        LDAPVLVInfo *vlvinfop,
00089        struct berval *value )
00090 {
00091        ber_tag_t tag;
00092        BerElement *ber;
00093 
00094        if ( ld == NULL || vlvinfop == NULL || value == NULL ) {
00095               if ( ld )
00096                      ld->ld_errno = LDAP_PARAM_ERROR;
00097               return LDAP_PARAM_ERROR;
00098        }
00099 
00100        assert( LDAP_VALID( ld ) );
00101 
00102        value->bv_val = NULL;
00103        value->bv_len = 0;
00104        ld->ld_errno = LDAP_SUCCESS;
00105 
00106        ber = ldap_alloc_ber_with_options( ld );
00107        if ( ber == NULL ) {
00108               ld->ld_errno = LDAP_NO_MEMORY;
00109               return ld->ld_errno;
00110        }
00111 
00112        tag = ber_printf( ber, "{ii" /*}*/,
00113               vlvinfop->ldvlv_before_count,
00114               vlvinfop->ldvlv_after_count );
00115        if ( tag == LBER_ERROR ) {
00116               goto error_return;
00117        }
00118 
00119        if ( vlvinfop->ldvlv_attrvalue == NULL ) {
00120               tag = ber_printf( ber, "t{iiN}",
00121                      LDAP_VLVBYINDEX_IDENTIFIER,
00122                      vlvinfop->ldvlv_offset,
00123                      vlvinfop->ldvlv_count );
00124               if ( tag == LBER_ERROR ) {
00125                      goto error_return;
00126               }
00127 
00128        } else {
00129               tag = ber_printf( ber, "tO",
00130                      LDAP_VLVBYVALUE_IDENTIFIER,
00131                      vlvinfop->ldvlv_attrvalue );
00132               if ( tag == LBER_ERROR ) {
00133                      goto error_return;
00134               }
00135        }
00136 
00137        if ( vlvinfop->ldvlv_context ) {
00138               tag = ber_printf( ber, "tO",
00139                      LDAP_VLVCONTEXT_IDENTIFIER,
00140                      vlvinfop->ldvlv_context );
00141               if ( tag == LBER_ERROR ) {
00142                      goto error_return;
00143               }
00144        }
00145 
00146        tag = ber_printf( ber, /*{*/ "N}" ); 
00147        if ( tag == LBER_ERROR ) {
00148               goto error_return;
00149        }
00150 
00151        if ( ber_flatten2( ber, value, 1 ) == -1 ) {
00152               ld->ld_errno = LDAP_NO_MEMORY;
00153        }
00154 
00155        if ( 0 ) {
00156 error_return:;
00157               ld->ld_errno = LDAP_ENCODING_ERROR;
00158        }
00159 
00160        if ( ber != NULL ) {
00161               ber_free( ber, 1 );
00162        }
00163 
00164        return ld->ld_errno;
00165 }
00166 
00167 /*---
00168    ldap_create_vlv_control
00169    
00170    Create and encode the Virtual List View control.
00171 
00172    ld        (IN)  An LDAP session handle.
00173    
00174    vlvinfop  (IN)  The address of an LDAPVLVInfo structure whose contents 
00175                                are used to construct the value of the control
00176                                that is created.
00177    
00178    ctrlp     (OUT) A result parameter that will be assigned the address
00179                                of an LDAPControl structure that contains the 
00180                                VirtualListViewRequest control created by this function.
00181                                The memory occupied by the LDAPControl structure
00182                                SHOULD be freed when it is no longer in use by
00183                                calling ldap_control_free().
00184                                      
00185    
00186    Ber encoding
00187    
00188    VirtualListViewRequest ::= SEQUENCE {
00189               beforeCount  INTEGER (0 .. maxInt),
00190               afterCount   INTEGER (0 .. maxInt),
00191               CHOICE {
00192                             byoffset [0] SEQUENCE, {
00193                             offset        INTEGER (0 .. maxInt),
00194                             contentCount  INTEGER (0 .. maxInt) }
00195                             [1] greaterThanOrEqual assertionValue }
00196               contextID     OCTET STRING OPTIONAL }
00197          
00198    
00199    Note:  The first time the VLV control is created, the ldvlv_context
00200                 field of the LDAPVLVInfo structure should be set to NULL.
00201                 The context obtained from calling ldap_parse_vlv_control()
00202                 should be used as the context in the next ldap_create_vlv_control
00203                 call.
00204 
00205  ---*/
00206 
00207 int
00208 ldap_create_vlv_control(
00209        LDAP *ld,
00210        LDAPVLVInfo *vlvinfop,
00211        LDAPControl **ctrlp )
00212 {
00213        struct berval value;
00214 
00215        if ( ctrlp == NULL ) {
00216               ld->ld_errno = LDAP_PARAM_ERROR;
00217               return ld->ld_errno;
00218        }
00219 
00220        ld->ld_errno = ldap_create_vlv_control_value( ld, vlvinfop, &value );
00221        if ( ld->ld_errno == LDAP_SUCCESS ) {
00222 
00223               ld->ld_errno = ldap_control_create( LDAP_CONTROL_VLVREQUEST,
00224                      1, &value, 0, ctrlp );
00225               if ( ld->ld_errno != LDAP_SUCCESS ) {
00226                      LDAP_FREE( value.bv_val );
00227               }
00228        }
00229 
00230        return ld->ld_errno;
00231 }
00232 
00233 
00234 /*---
00235    ldap_parse_vlvresponse_control
00236    
00237    Decode the Virtual List View control return information.
00238 
00239    ld           (IN)   An LDAP session handle.
00240    
00241    ctrl         (IN)   The address of the LDAPControl structure.
00242    
00243    target_posp       (OUT)  This result parameter is filled in with the list
00244                                       index of the target entry.  If this parameter is
00245                                       NULL, the target position is not returned.
00246    
00247    list_countp  (OUT)  This result parameter is filled in with the server's
00248                                       estimate of the size of the list.  If this parameter
00249                                       is NULL, the size is not returned.
00250    
00251    contextp     (OUT)  This result parameter is filled in with the address
00252                                       of a struct berval that contains the server-
00253                                       generated context identifier if one was returned by
00254                                       the server.  If the server did not return a context
00255                                       identifier, this parameter will be set to NULL, even
00256                                       if an error occured.
00257                                       The returned context SHOULD be used in the next call
00258                                       to create a VLV sort control.  The struct berval
00259                                       returned SHOULD be disposed of by calling ber_bvfree()
00260                                       when it is no longer needed.  If NULL is passed for
00261                                       contextp, the context identifier is not returned.
00262    
00263    errcodep     (OUT)  This result parameter is filled in with the VLV
00264                                       result code.  If this parameter is NULL, the result
00265                                       code is not returned.  
00266    
00267    
00268    Ber encoding
00269    
00270    VirtualListViewResponse ::= SEQUENCE {
00271               targetPosition    INTEGER (0 .. maxInt),
00272               contentCount     INTEGER (0 .. maxInt),
00273               virtualListViewResult ENUMERATED {
00274               success (0),
00275               operatonsError (1),
00276               unwillingToPerform (53),
00277               insufficientAccessRights (50),
00278               busy (51),
00279               timeLimitExceeded (3),
00280               adminLimitExceeded (11),
00281               sortControlMissing (60),
00282               offsetRangeError (61),
00283               other (80) },
00284               contextID     OCTET STRING OPTIONAL }
00285    
00286 ---*/
00287 
00288 int
00289 ldap_parse_vlvresponse_control(
00290        LDAP *ld,
00291        LDAPControl *ctrl,
00292        ber_int_t *target_posp,
00293        ber_int_t *list_countp,
00294        struct berval  **contextp,
00295        ber_int_t *errcodep )
00296 {
00297        BerElement  *ber;
00298        ber_int_t pos, count, err;
00299        ber_tag_t tag, berTag;
00300        ber_len_t berLen;
00301 
00302        assert( ld != NULL );
00303        assert( LDAP_VALID( ld ) );
00304 
00305        if (contextp) {
00306               *contextp = NULL;     /* Make sure we return a NULL if error occurs. */
00307        }
00308 
00309        if (ctrl == NULL) {
00310               ld->ld_errno = LDAP_PARAM_ERROR;
00311               return(ld->ld_errno);
00312        }
00313 
00314        if (strcmp(LDAP_CONTROL_VLVRESPONSE, ctrl->ldctl_oid) != 0) {
00315               /* Not VLV Response control */
00316               ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
00317               return(ld->ld_errno);
00318        }
00319 
00320        /* Create a BerElement from the berval returned in the control. */
00321        ber = ber_init(&ctrl->ldctl_value);
00322 
00323        if (ber == NULL) {
00324               ld->ld_errno = LDAP_NO_MEMORY;
00325               return(ld->ld_errno);
00326        }
00327 
00328        /* Extract the data returned in the control. */
00329        tag = ber_scanf(ber, "{iie" /*}*/, &pos, &count, &err);
00330 
00331        if( tag == LBER_ERROR) {
00332               ber_free(ber, 1);
00333               ld->ld_errno = LDAP_DECODING_ERROR;
00334               return(ld->ld_errno);
00335        }
00336 
00337 
00338        /* Since the context is the last item encoded, if caller doesn't want
00339           it returned, don't decode it. */
00340        if (contextp) {
00341               if (LDAP_VLVCONTEXT_IDENTIFIER == ber_peek_tag(ber, &berLen)) {
00342                      tag = ber_scanf(ber, "tO", &berTag, contextp);
00343 
00344                      if( tag == LBER_ERROR) {
00345                             ber_free(ber, 1);
00346                             ld->ld_errno = LDAP_DECODING_ERROR;
00347                             return(ld->ld_errno);
00348                      }
00349               }
00350        }
00351 
00352        ber_free(ber, 1);
00353 
00354        /* Return data to the caller for items that were requested. */
00355        if (target_posp) *target_posp = pos;
00356        if (list_countp) *list_countp = count;
00357        if (errcodep) *errcodep = err;
00358 
00359        ld->ld_errno = LDAP_SUCCESS;
00360        return(ld->ld_errno);
00361 }