mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-27 18:19:52 -05:00
Add VLV/Sort controls (from Novell)
This commit is contained in:
parent
22b8b60e49
commit
c6e4ad6c12
2 changed files with 747 additions and 0 deletions
467
libraries/libldap/sortctrl.c
Normal file
467
libraries/libldap/sortctrl.c
Normal file
|
|
@ -0,0 +1,467 @@
|
|||
/*
|
||||
* Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
|
||||
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
|
||||
*/
|
||||
/* Adapted for inclusion into OpenLDAP by Kurt D. Zeilenga */
|
||||
/*---
|
||||
* Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
|
||||
*
|
||||
* THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
|
||||
* TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
|
||||
* TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
|
||||
* AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
|
||||
* IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
|
||||
* OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
|
||||
* PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
|
||||
* THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
|
||||
*
|
||||
*---*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ac/stdlib.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/time.h>
|
||||
#include <ac/ctype.h>
|
||||
|
||||
#include "ldap-int.h"
|
||||
|
||||
#define LDAP_MATCHRULE_IDENTIFIER 0x80L
|
||||
#define LDAP_REVERSEORDER_IDENTIFIER 0x81L
|
||||
#define LDAP_ATTRTYPES_IDENTIFIER 0x80L
|
||||
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
countKeys
|
||||
|
||||
Internal function to determine the number of keys in the string.
|
||||
|
||||
keyString (IN) String of items separated by whitespace.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static int countKeys(char *keyString)
|
||||
{
|
||||
char *p = keyString;
|
||||
int count = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
while (isspace(*p)) /* Skip leading whitespace */
|
||||
p++;
|
||||
|
||||
if (*p == '\0') /* End of string? */
|
||||
return count;
|
||||
|
||||
count++; /* Found start of a key */
|
||||
|
||||
while (!isspace(*p)) /* Skip till next space or end of string. */
|
||||
if (*p++ == '\0')
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
readNextKey
|
||||
|
||||
Internal function to parse the next sort key in the string.
|
||||
Allocate an LDAPSortKey structure and initialize it with
|
||||
attribute name, reverse flag, and matching rule OID.
|
||||
|
||||
Each sort key in the string has the format:
|
||||
[whitespace][-]attribute[:[OID]]
|
||||
|
||||
pNextKey (IN/OUT) Points to the next key in the sortkey string to parse.
|
||||
The pointer is updated to point to the next character
|
||||
after the sortkey being parsed.
|
||||
|
||||
key (OUT) Points to the address of an LDAPSortKey stucture
|
||||
which has been allocated by this routine and
|
||||
initialized with information from the next sortkey.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static int readNextKey( char **pNextKey, LDAPSortKey **key)
|
||||
{
|
||||
char *p = *pNextKey;
|
||||
int rev = 0;
|
||||
char *attrStart;
|
||||
int attrLen;
|
||||
char *oidStart = NULL;
|
||||
int oidLen = 0;
|
||||
|
||||
/* Skip leading white space. */
|
||||
while (isspace(*p))
|
||||
p++;
|
||||
|
||||
if (*p == '-') /* Check if the reverse flag is present. */
|
||||
{
|
||||
rev=1;
|
||||
p++;
|
||||
}
|
||||
|
||||
/* We're now positioned at the start of the attribute. */
|
||||
attrStart = p;
|
||||
|
||||
/* Get the length of the attribute until the next whitespace or ":". */
|
||||
attrLen = strcspn(p, " \t:");
|
||||
p += attrLen;
|
||||
|
||||
if (attrLen == 0) /* If no attribute name was present, quit. */
|
||||
return LDAP_PARAM_ERROR;
|
||||
|
||||
if (*p == ':')
|
||||
{
|
||||
oidStart = ++p; /* Start of the OID, after the colon */
|
||||
oidLen = strcspn(p, " \t"); /* Get length of OID till next whitespace */
|
||||
p += oidLen;
|
||||
}
|
||||
|
||||
*pNextKey = p; /* Update argument to point to next key */
|
||||
|
||||
/* Allocate an LDAPSortKey structure */
|
||||
*key = LDAP_MALLOC(sizeof(LDAPSortKey));
|
||||
if (*key == NULL) return LDAP_NO_MEMORY;
|
||||
|
||||
/* Allocate memory for the attribute and copy to it. */
|
||||
(*key)->attributeType = LDAP_MALLOC(attrLen+1);
|
||||
if ((*key)->attributeType == NULL) {
|
||||
LDAP_FREE(*key);
|
||||
return LDAP_NO_MEMORY;
|
||||
}
|
||||
|
||||
strncpy((*key)->attributeType, attrStart, attrLen);
|
||||
(*key)->attributeType[attrLen] = 0;
|
||||
|
||||
/* If present, allocate memory for the OID and copy to it. */
|
||||
if (oidLen) {
|
||||
(*key)->orderingRule = LDAP_MALLOC(oidLen+1);
|
||||
if ((*key)->orderingRule == NULL) {
|
||||
LDAP_FREE((*key)->attributeType);
|
||||
LDAP_FREE(*key);
|
||||
return LDAP_NO_MEMORY;
|
||||
}
|
||||
strncpy((*key)->orderingRule, oidStart, oidLen);
|
||||
(*key)->orderingRule[oidLen] = 0;
|
||||
|
||||
} else {
|
||||
(*key)->orderingRule = NULL;
|
||||
}
|
||||
|
||||
(*key)->reverseOrder = rev;
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
ldap_create_sort_keylist
|
||||
|
||||
Create an array of pointers to LDAPSortKey structures, containing the
|
||||
information specified by the string representation of one or more
|
||||
sort keys.
|
||||
|
||||
sortKeyList (OUT) Points to a null-terminated array of pointers to
|
||||
LDAPSortKey structures allocated by this routine.
|
||||
This memory SHOULD be freed by the calling program
|
||||
using ldap_free_sort_keylist().
|
||||
|
||||
keyString (IN) Points to a string of one or more sort keys.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
LIBLDAP_F(int)
|
||||
ldap_create_sort_keylist ( LDAPSortKey ***sortKeyList, char *keyString )
|
||||
{
|
||||
int numKeys, rc, i;
|
||||
char *nextKey;
|
||||
LDAPSortKey **keyList = NULL;
|
||||
|
||||
if (( sortKeyList == NULL ) || ( keyString == NULL )) {
|
||||
return LDAP_PARAM_ERROR;
|
||||
}
|
||||
*sortKeyList = NULL;
|
||||
|
||||
/* Determine the number of sort keys so we can allocate memory. */
|
||||
if (( numKeys = countKeys(keyString)) == 0) {
|
||||
return LDAP_PARAM_ERROR;
|
||||
}
|
||||
|
||||
/* Allocate the array of pointers. Initialize to NULL. */
|
||||
keyList=(LDAPSortKey**)LBER_CALLOC(numKeys+1, sizeof(LDAPSortKey*));
|
||||
if ( keyList == NULL) return LDAP_NO_MEMORY;
|
||||
|
||||
/* For each sort key in the string, create an LDAPSortKey structure
|
||||
and add it to the list.
|
||||
*/
|
||||
nextKey = keyString; /* Points to the next key in the string */
|
||||
for (i=0; i < numKeys; i++) {
|
||||
rc = readNextKey(&nextKey, &keyList[i]);
|
||||
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
ldap_free_sort_keylist(keyList);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
*sortKeyList = keyList;
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
ldap_free_sort_keylist
|
||||
|
||||
Frees the sort key structures created by ldap_create_sort_keylist().
|
||||
Frees the memory referenced by the LDAPSortKey structures,
|
||||
the LDAPSortKey structures themselves, and the array of pointers
|
||||
to the structures.
|
||||
|
||||
keyList (IN) Points to an array of pointers to LDAPSortKey structures.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
LIBLDAP_F(void)
|
||||
ldap_free_sort_keylist ( LDAPSortKey **keyList )
|
||||
{
|
||||
int i;
|
||||
LDAPSortKey *nextKeyp;
|
||||
|
||||
if (keyList == NULL) return;
|
||||
|
||||
i=0;
|
||||
while ( 0 != (nextKeyp = keyList[i++]) ) {
|
||||
if (nextKeyp->attributeType) {
|
||||
LBER_FREE(nextKeyp->attributeType);
|
||||
}
|
||||
|
||||
if (nextKeyp->orderingRule != NULL) {
|
||||
LBER_FREE(nextKeyp->orderingRule);
|
||||
}
|
||||
|
||||
LBER_FREE(nextKeyp);
|
||||
}
|
||||
|
||||
LBER_FREE(keyList);
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
ldap_create_sort_control
|
||||
|
||||
Create and encode the server-side sort control.
|
||||
|
||||
ld (IN) An LDAP session handle, as obtained from a call to
|
||||
ldap_init().
|
||||
|
||||
keyList (IN) Points to a null-terminated array of pointers to
|
||||
LDAPSortKey structures, containing a description of
|
||||
each of the sort keys to be used. The description
|
||||
consists of an attribute name, ascending/descending flag,
|
||||
and an optional matching rule (OID) to use.
|
||||
|
||||
isCritical (IN) 0 - Indicates the control is not critical to the operation.
|
||||
non-zero - The control is critical to the operation.
|
||||
|
||||
ctrlp (OUT) Returns a pointer to the LDAPControl created. This control
|
||||
SHOULD be freed by calling ldap_control_free() when done.
|
||||
|
||||
|
||||
Ber encoding
|
||||
|
||||
SortKeyList ::= SEQUENCE OF SEQUENCE {
|
||||
attributeType AttributeDescription,
|
||||
orderingRule [0] MatchingRuleId OPTIONAL,
|
||||
reverseOrder [1] BOOLEAN DEFAULT FALSE }
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
LIBLDAP_F( int )
|
||||
ldap_create_sort_control (
|
||||
LDAP *ld,
|
||||
LDAPSortKey **keyList,
|
||||
int isCritical,
|
||||
LDAPControl **ctrlp )
|
||||
{
|
||||
int i;
|
||||
BerElement *ber;
|
||||
ber_tag_t tag;
|
||||
|
||||
|
||||
if ( (ld == NULL) || (keyList == NULL) || (ctrlp == NULL) ) {
|
||||
ld->ld_errno = LDAP_PARAM_ERROR;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
|
||||
if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
|
||||
ld->ld_errno = LDAP_NO_MEMORY;
|
||||
return( ld->ld_errno );
|
||||
}
|
||||
|
||||
tag = ber_printf(ber, "{" /*}*/);
|
||||
if (tag == LBER_ERROR) goto exit;
|
||||
|
||||
for (i = 0; keyList[i] != NULL; i++) {
|
||||
tag = ber_printf(ber, "{s" /*}*/, (keyList[i])->attributeType);
|
||||
if (tag == LBER_ERROR) goto exit;
|
||||
|
||||
if ((keyList[i])->orderingRule != NULL) {
|
||||
tag = ber_printf( ber, "ts",
|
||||
LDAP_MATCHRULE_IDENTIFIER,
|
||||
(keyList[i])->orderingRule );
|
||||
|
||||
if( tag == LBER_ERROR ) goto exit;
|
||||
}
|
||||
|
||||
if ((keyList[i])->reverseOrder) {
|
||||
tag = ber_printf(ber, "tb",
|
||||
LDAP_REVERSEORDER_IDENTIFIER,
|
||||
(keyList[i])->reverseOrder );
|
||||
|
||||
if( tag == LBER_ERROR ) goto exit;
|
||||
}
|
||||
|
||||
tag = ber_printf(ber, /*{*/ "}");
|
||||
if( tag == LBER_ERROR ) goto exit;
|
||||
}
|
||||
|
||||
tag = ber_printf(ber, /*{*/ "}");
|
||||
if( tag == LBER_ERROR ) goto exit;
|
||||
|
||||
ld->ld_errno = ldap_int_create_control( LDAP_CONTROL_SORTREQUEST,
|
||||
ber, isCritical, ctrlp);
|
||||
|
||||
ber_free(ber, 1);
|
||||
|
||||
return(ld->ld_errno);
|
||||
|
||||
exit:
|
||||
ber_free(ber, 1);
|
||||
ld->ld_errno = LDAP_ENCODING_ERROR;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
ldap_parse_sort_control
|
||||
|
||||
Decode the server-side sort control return information.
|
||||
|
||||
ld (IN) An LDAP session handle, as obtained from a call to
|
||||
ldap_init().
|
||||
|
||||
ctrls (IN) The address of a NULL-terminated array of LDAPControl
|
||||
structures, typically obtained by a call to
|
||||
ldap_parse_result().
|
||||
|
||||
returnCode (OUT) This result parameter is filled in with the sort control
|
||||
result code. This parameter MUST not be NULL.
|
||||
|
||||
attribute (OUT) If an error occured the server may return a string
|
||||
indicating the first attribute in the sortkey list
|
||||
that was in error. If a string is returned, the memory
|
||||
should be freed with ldap_memfree. If this parameter is
|
||||
NULL, no string is returned.
|
||||
|
||||
|
||||
Ber encoding for sort control
|
||||
|
||||
SortResult ::= SEQUENCE {
|
||||
sortResult ENUMERATED {
|
||||
success (0), -- results are sorted
|
||||
operationsError (1), -- server internal failure
|
||||
timeLimitExceeded (3), -- timelimit reached before
|
||||
-- sorting was completed
|
||||
strongAuthRequired (8), -- refused to return sorted
|
||||
-- results via insecure
|
||||
-- protocol
|
||||
adminLimitExceeded (11), -- too many matching entries
|
||||
-- for the server to sort
|
||||
noSuchAttribute (16), -- unrecognized attribute
|
||||
-- type in sort key
|
||||
inappropriateMatching (18), -- unrecognized or inappro-
|
||||
-- priate matching rule in
|
||||
-- sort key
|
||||
insufficientAccessRights (50), -- refused to return sorted
|
||||
-- results to this client
|
||||
busy (51), -- too busy to process
|
||||
unwillingToPerform (53), -- unable to sort
|
||||
other (80)
|
||||
},
|
||||
attributeType [0] AttributeDescription OPTIONAL }
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
LIBLDAP_F( int )
|
||||
ldap_parse_sort_control(
|
||||
LDAP *ld,
|
||||
LDAPControl **ctrls,
|
||||
unsigned long *returnCode,
|
||||
char **attribute )
|
||||
{
|
||||
BerElement *ber;
|
||||
LDAPControl *pControl;
|
||||
int i;
|
||||
ber_tag_t tag, berTag;
|
||||
ber_len_t berLen;
|
||||
|
||||
if (ld == NULL) {
|
||||
ld->ld_errno = LDAP_PARAM_ERROR;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
|
||||
if (ctrls == NULL) {
|
||||
ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
|
||||
if (attribute) {
|
||||
*attribute = NULL;
|
||||
}
|
||||
|
||||
/* Search the list of control responses for a sort control. */
|
||||
for (i=0; ctrls[i]; i++) {
|
||||
pControl = ctrls[i];
|
||||
if (!strcmp(LDAP_CONTROL_SORTRESPONSE, pControl->ldctl_oid))
|
||||
goto foundSortControl;
|
||||
}
|
||||
|
||||
/* No sort control was found. */
|
||||
ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
|
||||
return(ld->ld_errno);
|
||||
|
||||
foundSortControl:
|
||||
/* Create a BerElement from the berval returned in the control. */
|
||||
ber = ber_init(&pControl->ldctl_value);
|
||||
|
||||
if (ber == NULL) {
|
||||
ld->ld_errno = LDAP_NO_MEMORY;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
|
||||
/* Extract the result code from the control. */
|
||||
tag = ber_scanf(ber, "{e" /*}*/, returnCode);
|
||||
|
||||
if( tag == LBER_ERROR ) {
|
||||
ber_free(ber, 1);
|
||||
ld->ld_errno = LDAP_DECODING_ERROR;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
|
||||
/* If caller wants the attribute name, and if it's present in the control,
|
||||
extract the attribute name which caused the error. */
|
||||
if (attribute && (LDAP_ATTRTYPES_IDENTIFIER == ber_peek_tag(ber, &berLen)))
|
||||
{
|
||||
tag = ber_scanf(ber, "ta", &berTag, attribute);
|
||||
|
||||
if (tag == LBER_ERROR ) {
|
||||
ber_free(ber, 1);
|
||||
ld->ld_errno = LDAP_DECODING_ERROR;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
}
|
||||
|
||||
ber_free(ber,1);
|
||||
|
||||
ld->ld_errno = LDAP_SUCCESS;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
280
libraries/libldap/vlvctrl.c
Normal file
280
libraries/libldap/vlvctrl.c
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
|
||||
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
|
||||
*/
|
||||
/* Adapted for inclusion into OpenLDAP by Kurt D. Zeilenga */
|
||||
/*---
|
||||
* Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
|
||||
*
|
||||
* THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
|
||||
* TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
|
||||
* TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
|
||||
* AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
|
||||
* IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
|
||||
* OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
|
||||
* PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
|
||||
* THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
|
||||
*---*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ac/stdlib.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/time.h>
|
||||
#include <ac/ctype.h>
|
||||
|
||||
#include "ldap-int.h"
|
||||
|
||||
#define LDAP_VLVBYINDEX_IDENTIFIER 0xa0L
|
||||
#define LDAP_VLVBYVALUE_IDENTIFIER 0x81L
|
||||
#define LDAP_VLVCONTEXT_IDENTIFIER 0x04L
|
||||
|
||||
|
||||
/*---
|
||||
ldap_create_vlv_control
|
||||
|
||||
Create and encode the Virtual List View control.
|
||||
|
||||
ld (IN) An LDAP session handle, as obtained from a call to
|
||||
ldap_init().
|
||||
|
||||
vlvinfop (IN) The address of an LDAPVLVInfo structure whose contents
|
||||
are used to construct the value of the control
|
||||
that is created.
|
||||
|
||||
ctrlp (OUT) A result parameter that will be assigned the address
|
||||
of an LDAPControl structure that contains the
|
||||
VirtualListViewRequest control created by this function.
|
||||
The memory occupied by the LDAPControl structure
|
||||
SHOULD be freed when it is no longer in use by
|
||||
calling ldap_control_free().
|
||||
|
||||
|
||||
Ber encoding
|
||||
|
||||
VirtualListViewRequest ::= SEQUENCE {
|
||||
beforeCount INTEGER (0 .. maxInt),
|
||||
afterCount INTEGER (0 .. maxInt),
|
||||
CHOICE {
|
||||
byoffset [0] SEQUENCE, {
|
||||
offset INTEGER (0 .. maxInt),
|
||||
contentCount INTEGER (0 .. maxInt) }
|
||||
[1] greaterThanOrEqual assertionValue }
|
||||
contextID OCTET STRING OPTIONAL }
|
||||
|
||||
|
||||
Note: The first time the VLV control is created, the ldvlv_context
|
||||
field of the LDAPVLVInfo structure should be set to NULL.
|
||||
The context obtained from calling ldap_parse_vlv_control()
|
||||
should be used as the context in the next ldap_create_vlv_control
|
||||
call.
|
||||
|
||||
---*/
|
||||
|
||||
LIBLDAP_F( int )
|
||||
ldap_create_vlv_control( LDAP *ld,
|
||||
LDAPVLVInfo *vlvinfop,
|
||||
LDAPControl **ctrlp )
|
||||
{
|
||||
ber_tag_t tag;
|
||||
BerElement *ber;
|
||||
|
||||
if ( (ld==NULL) || (vlvinfop==NULL) || (ctrlp == NULL) ) {
|
||||
ld->ld_errno = LDAP_PARAM_ERROR;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
|
||||
if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
|
||||
ld->ld_errno = LDAP_NO_MEMORY;
|
||||
return(LDAP_NO_MEMORY);
|
||||
}
|
||||
|
||||
tag = ber_printf(ber, "{ii" /*}*/,
|
||||
vlvinfop->ldvlv_before_count,
|
||||
vlvinfop->ldvlv_after_count);
|
||||
if( tag == LBER_ERROR ) goto exit;
|
||||
|
||||
if (vlvinfop->ldvlv_attrvalue == NULL) {
|
||||
tag = ber_printf(ber, "t{ii}",
|
||||
LDAP_VLVBYINDEX_IDENTIFIER,
|
||||
vlvinfop->ldvlv_offset,
|
||||
vlvinfop->ldvlv_count);
|
||||
if( tag == LBER_ERROR ) goto exit;
|
||||
|
||||
} else {
|
||||
tag = ber_printf(ber, "tO",
|
||||
LDAP_VLVBYVALUE_IDENTIFIER,
|
||||
vlvinfop->ldvlv_attrvalue);
|
||||
if( tag == LBER_ERROR ) goto exit;
|
||||
}
|
||||
|
||||
if (vlvinfop->ldvlv_context) {
|
||||
tag = ber_printf(ber, "tO",
|
||||
LDAP_VLVCONTEXT_IDENTIFIER,
|
||||
vlvinfop->ldvlv_context);
|
||||
if( tag == LBER_ERROR ) goto exit;
|
||||
}
|
||||
|
||||
tag = ber_printf(ber, /*{*/ "}");
|
||||
if( tag == LBER_ERROR ) goto exit;
|
||||
|
||||
ld->ld_errno = ldap_int_create_control(
|
||||
LDAP_CONTROL_VLVREQUEST, ber, 1, ctrlp);
|
||||
|
||||
ber_free(ber, 1);
|
||||
return(ld->ld_errno);
|
||||
|
||||
exit:
|
||||
ber_free(ber, 1);
|
||||
ld->ld_errno = LDAP_ENCODING_ERROR;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
|
||||
|
||||
/*---
|
||||
ldap_parse_vlv_control
|
||||
|
||||
Decode the Virtual List View control return information.
|
||||
|
||||
ld (IN) An LDAP session handle.
|
||||
|
||||
ctrls (IN) The address of a NULL-terminated array of
|
||||
LDAPControl structures, typically obtained
|
||||
by a call to ldap_parse_result().
|
||||
|
||||
target_posp (OUT) This result parameter is filled in with the list
|
||||
index of the target entry. If this parameter is
|
||||
NULL, the target position is not returned.
|
||||
|
||||
list_countp (OUT) This result parameter is filled in with the server's
|
||||
estimate of the size of the list. If this parameter
|
||||
is NULL, the size is not returned.
|
||||
|
||||
contextp (OUT) This result parameter is filled in with the address
|
||||
of a struct berval that contains the server-
|
||||
generated context identifier if one was returned by
|
||||
the server. If the server did not return a context
|
||||
identifier, this parameter will be set to NULL, even
|
||||
if an error occured.
|
||||
The returned context SHOULD be used in the next call
|
||||
to create a VLV sort control. The struct berval
|
||||
returned SHOULD be disposed of by calling ber_bvfree()
|
||||
when it is no longer needed. If NULL is passed for
|
||||
contextp, the context identifier is not returned.
|
||||
|
||||
errcodep (OUT) This result parameter is filled in with the VLV
|
||||
result code. If this parameter is NULL, the result
|
||||
code is not returned.
|
||||
|
||||
|
||||
Ber encoding
|
||||
|
||||
VirtualListViewResponse ::= SEQUENCE {
|
||||
targetPosition INTEGER (0 .. maxInt),
|
||||
contentCount INTEGER (0 .. maxInt),
|
||||
virtualListViewResult ENUMERATED {
|
||||
success (0),
|
||||
operatonsError (1),
|
||||
unwillingToPerform (53),
|
||||
insufficientAccessRights (50),
|
||||
busy (51),
|
||||
timeLimitExceeded (3),
|
||||
adminLimitExceeded (11),
|
||||
sortControlMissing (60),
|
||||
offsetRangeError (61),
|
||||
other (80) },
|
||||
contextID OCTET STRING OPTIONAL }
|
||||
|
||||
---*/
|
||||
|
||||
LIBLDAP_F( int )
|
||||
ldap_parse_vlv_control(
|
||||
LDAP *ld,
|
||||
LDAPControl **ctrls,
|
||||
unsigned long *target_posp,
|
||||
unsigned long *list_countp,
|
||||
struct berval **contextp,
|
||||
int *errcodep )
|
||||
{
|
||||
BerElement *ber;
|
||||
LDAPControl *pControl;
|
||||
int i;
|
||||
unsigned long pos, count, err;
|
||||
ber_tag_t tag, berTag;
|
||||
ber_len_t berLen;
|
||||
|
||||
if (contextp) {
|
||||
*contextp = NULL; /* Make sure we return a NULL if error occurs. */
|
||||
}
|
||||
|
||||
if (ld == NULL) {
|
||||
ld->ld_errno = LDAP_PARAM_ERROR;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
|
||||
if (ctrls == NULL) {
|
||||
ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
|
||||
/* Search the list of control responses for a VLV control. */
|
||||
for (i=0; ctrls[i]; i++) {
|
||||
pControl = ctrls[i];
|
||||
if (!strcmp(LDAP_CONTROL_VLVRESPONSE, pControl->ldctl_oid))
|
||||
goto foundVLVControl;
|
||||
}
|
||||
|
||||
/* No sort control was found. */
|
||||
ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
|
||||
return(ld->ld_errno);
|
||||
|
||||
foundVLVControl:
|
||||
/* Create a BerElement from the berval returned in the control. */
|
||||
ber = ber_init(&pControl->ldctl_value);
|
||||
|
||||
if (ber == NULL) {
|
||||
ld->ld_errno = LDAP_NO_MEMORY;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
|
||||
/* Extract the data returned in the control. */
|
||||
tag = ber_scanf(ber, "{iie" /*}*/, &pos, &count, &err);
|
||||
|
||||
if( tag == LBER_ERROR) {
|
||||
ber_free(ber, 1);
|
||||
ld->ld_errno = LDAP_DECODING_ERROR;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
|
||||
|
||||
/* Since the context is the last item encoded, if caller doesn't want
|
||||
it returned, don't decode it. */
|
||||
if (contextp) {
|
||||
if (LDAP_VLVCONTEXT_IDENTIFIER == ber_peek_tag(ber, &berLen)) {
|
||||
tag = ber_scanf(ber, "tO", &berTag, contextp);
|
||||
|
||||
if( tag == LBER_ERROR) {
|
||||
ber_free(ber, 1);
|
||||
ld->ld_errno = LDAP_DECODING_ERROR;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ber_free(ber, 1);
|
||||
|
||||
/* Return data to the caller for items that were requested. */
|
||||
if (target_posp) {
|
||||
*target_posp = pos;
|
||||
}
|
||||
if (list_countp) {
|
||||
*list_countp = count;
|
||||
}
|
||||
if (errcodep) {
|
||||
*errcodep = err;
|
||||
}
|
||||
|
||||
ld->ld_errno = LDAP_SUCCESS;
|
||||
return(ld->ld_errno);
|
||||
}
|
||||
Loading…
Reference in a new issue