mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-27 03:20:22 +08:00
ITS#8983 Add draft Persistent Search
This commit is contained in:
parent
64141fda51
commit
06d289f985
@ -139,6 +139,7 @@ typedef int (*print_ctrl_fn)( LDAP *ld, LDAPControl *ctrl );
|
|||||||
static int print_preread( LDAP *ld, LDAPControl *ctrl );
|
static int print_preread( LDAP *ld, LDAPControl *ctrl );
|
||||||
static int print_postread( LDAP *ld, LDAPControl *ctrl );
|
static int print_postread( LDAP *ld, LDAPControl *ctrl );
|
||||||
static int print_paged_results( LDAP *ld, LDAPControl *ctrl );
|
static int print_paged_results( LDAP *ld, LDAPControl *ctrl );
|
||||||
|
static int print_psearch( LDAP *ld, LDAPControl *ctrl );
|
||||||
#ifdef LDAP_CONTROL_AUTHZID_RESPONSE
|
#ifdef LDAP_CONTROL_AUTHZID_RESPONSE
|
||||||
static int print_authzid( LDAP *ld, LDAPControl *ctrl );
|
static int print_authzid( LDAP *ld, LDAPControl *ctrl );
|
||||||
#endif
|
#endif
|
||||||
@ -167,6 +168,7 @@ static struct tool_ctrls_t {
|
|||||||
{ LDAP_CONTROL_PRE_READ, TOOL_ALL, print_preread },
|
{ LDAP_CONTROL_PRE_READ, TOOL_ALL, print_preread },
|
||||||
{ LDAP_CONTROL_POST_READ, TOOL_ALL, print_postread },
|
{ LDAP_CONTROL_POST_READ, TOOL_ALL, print_postread },
|
||||||
{ LDAP_CONTROL_PAGEDRESULTS, TOOL_SEARCH, print_paged_results },
|
{ LDAP_CONTROL_PAGEDRESULTS, TOOL_SEARCH, print_paged_results },
|
||||||
|
{ LDAP_CONTROL_PERSIST_ENTRY_CHANGE_NOTICE, TOOL_SEARCH, print_psearch },
|
||||||
#ifdef LDAP_CONTROL_AUTHZID_RESPONSE
|
#ifdef LDAP_CONTROL_AUTHZID_RESPONSE
|
||||||
/* this is generally deprecated in favor of LDAP WhoAmI? operation, hence only supported as a VC inner control */
|
/* this is generally deprecated in favor of LDAP WhoAmI? operation, hence only supported as a VC inner control */
|
||||||
{ LDAP_CONTROL_AUTHZID_RESPONSE, TOOL_VC, print_authzid },
|
{ LDAP_CONTROL_AUTHZID_RESPONSE, TOOL_VC, print_authzid },
|
||||||
@ -2161,6 +2163,60 @@ print_paged_results( LDAP *ld, LDAPControl *ctrl )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
print_psearch( LDAP *ld, LDAPControl *ctrl )
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
int chgtype;
|
||||||
|
int chgpres;
|
||||||
|
long chgnum;
|
||||||
|
struct berval prevdn;
|
||||||
|
|
||||||
|
rc = ldap_parse_entrychange_control( ld, ctrl, &chgtype, &prevdn,
|
||||||
|
&chgpres, &chgnum );
|
||||||
|
if ( rc == LDAP_SUCCESS ) {
|
||||||
|
char buf[ BUFSIZ ];
|
||||||
|
char *ptr = buf;
|
||||||
|
int blen = sizeof(buf), len;
|
||||||
|
|
||||||
|
switch( chgtype ) {
|
||||||
|
case LDAP_CONTROL_PERSIST_ENTRY_CHANGE_ADD:
|
||||||
|
len = snprintf( ptr, blen, "add" );
|
||||||
|
ptr += len;
|
||||||
|
blen -= len;
|
||||||
|
break;
|
||||||
|
case LDAP_CONTROL_PERSIST_ENTRY_CHANGE_DELETE:
|
||||||
|
len = snprintf( ptr, blen, "delete" );
|
||||||
|
ptr += len;
|
||||||
|
blen -= len;
|
||||||
|
break;
|
||||||
|
case LDAP_CONTROL_PERSIST_ENTRY_CHANGE_MODIFY:
|
||||||
|
len = snprintf( ptr, blen, "modify" );
|
||||||
|
ptr += len;
|
||||||
|
blen -= len;
|
||||||
|
break;
|
||||||
|
case LDAP_CONTROL_PERSIST_ENTRY_CHANGE_RENAME:
|
||||||
|
len = snprintf( ptr, blen, "moddn" );
|
||||||
|
ptr += len;
|
||||||
|
blen -= len;
|
||||||
|
if ( prevdn.bv_val != NULL ) {
|
||||||
|
len = snprintf( ptr, blen, " prevdn %s", prevdn.bv_val );
|
||||||
|
ptr += len;
|
||||||
|
blen -= len;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( chgpres ) {
|
||||||
|
len = snprintf( ptr, blen, " changeNumber %ld", chgnum) ;
|
||||||
|
ptr += len;
|
||||||
|
blen -= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
|
||||||
|
ldif ? "persistentSearch: " : "persistentSearch", buf, len );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
print_sss( LDAP *ld, LDAPControl *ctrl )
|
print_sss( LDAP *ld, LDAPControl *ctrl )
|
||||||
{
|
{
|
||||||
|
@ -129,6 +129,7 @@ usage( void )
|
|||||||
fprintf( stderr, _(" !dontUseCopy (Don't Use Copy)\n"));
|
fprintf( stderr, _(" !dontUseCopy (Don't Use Copy)\n"));
|
||||||
fprintf( stderr, _(" [!]mv=<filter> (RFC 3876 matched values filter)\n"));
|
fprintf( stderr, _(" [!]mv=<filter> (RFC 3876 matched values filter)\n"));
|
||||||
fprintf( stderr, _(" [!]pr=<size>[/prompt|noprompt] (RFC 2696 paged results/prompt)\n"));
|
fprintf( stderr, _(" [!]pr=<size>[/prompt|noprompt] (RFC 2696 paged results/prompt)\n"));
|
||||||
|
fprintf( stderr, _(" [!]ps=<changetypes>/<changesonly>/<echg> (draft persisten search)\n"));
|
||||||
fprintf( stderr, _(" [!]sss=[-]<attr[:OID]>[/[-]<attr[:OID]>...]\n"));
|
fprintf( stderr, _(" [!]sss=[-]<attr[:OID]>[/[-]<attr[:OID]>...]\n"));
|
||||||
fprintf( stderr, _(" (RFC 2891 server side sorting)\n"));
|
fprintf( stderr, _(" (RFC 2891 server side sorting)\n"));
|
||||||
fprintf( stderr, _(" [!]subentries[=true|false] (RFC 3672 subentries)\n"));
|
fprintf( stderr, _(" [!]subentries[=true|false] (RFC 3672 subentries)\n"));
|
||||||
@ -237,6 +238,9 @@ static int ldapsync = 0;
|
|||||||
static struct berval sync_cookie = { 0, NULL };
|
static struct berval sync_cookie = { 0, NULL };
|
||||||
static int sync_slimit = -1;
|
static int sync_slimit = -1;
|
||||||
|
|
||||||
|
static int psearch = 0;
|
||||||
|
static int ps_chgtypes, ps_chgsonly, ps_echg_ctrls;
|
||||||
|
|
||||||
/* cookie and morePagedResults moved to common.c */
|
/* cookie and morePagedResults moved to common.c */
|
||||||
static int pagedResults = 0;
|
static int pagedResults = 0;
|
||||||
static int pagePrompt = 1;
|
static int pagePrompt = 1;
|
||||||
@ -467,6 +471,28 @@ handle_private_option( int i )
|
|||||||
pageSize = (ber_int_t) tmp;
|
pageSize = (ber_int_t) tmp;
|
||||||
pagedResults = 1 + crit;
|
pagedResults = 1 + crit;
|
||||||
|
|
||||||
|
} else if ( strcasecmp( control, "ps" ) == 0 ) {
|
||||||
|
int num, tmp;
|
||||||
|
/* PersistentSearch control */
|
||||||
|
if ( psearch != 0 ) {
|
||||||
|
fprintf( stderr,
|
||||||
|
_("PersistentSearch previously specified\n") );
|
||||||
|
exit( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
if( cvalue != NULL ) {
|
||||||
|
num = sscanf( cvalue, "%i/%d/%d", &ps_chgtypes, &ps_chgsonly, &ps_echg_ctrls );
|
||||||
|
if ( num != 3 ) {
|
||||||
|
fprintf( stderr,
|
||||||
|
_("Invalid value for PersistentSearch, %s.\n"),
|
||||||
|
cvalue );
|
||||||
|
exit( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, _("Invalid value for PersistentSearch.\n"));
|
||||||
|
exit( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
psearch = 1 + crit;
|
||||||
|
|
||||||
#ifdef LDAP_CONTROL_DONTUSECOPY
|
#ifdef LDAP_CONTROL_DONTUSECOPY
|
||||||
} else if ( strcasecmp( control, "dontUseCopy" ) == 0 ) {
|
} else if ( strcasecmp( control, "dontUseCopy" ) == 0 ) {
|
||||||
if( dontUseCopy ) {
|
if( dontUseCopy ) {
|
||||||
@ -1097,6 +1123,7 @@ getNextPage:
|
|||||||
#endif
|
#endif
|
||||||
|| domainScope
|
|| domainScope
|
||||||
|| pagedResults
|
|| pagedResults
|
||||||
|
|| psearch
|
||||||
|| ldapsync
|
|| ldapsync
|
||||||
|| sss
|
|| sss
|
||||||
|| subentries
|
|| subentries
|
||||||
@ -1233,6 +1260,22 @@ getNextPage:
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( psearch ) {
|
||||||
|
if ( ctrl_add() ) {
|
||||||
|
tool_exit( ld, EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ldap_create_persistentsearch_control_value( ld,
|
||||||
|
ps_chgtypes, ps_chgsonly, ps_echg_ctrls, &c[i].ldctl_value ) )
|
||||||
|
{
|
||||||
|
tool_exit( ld, EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
|
||||||
|
c[i].ldctl_oid = LDAP_CONTROL_PERSIST_REQUEST;
|
||||||
|
c[i].ldctl_iscritical = psearch > 1;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
if ( sss ) {
|
if ( sss ) {
|
||||||
if ( ctrl_add() ) {
|
if ( ctrl_add() ) {
|
||||||
tool_exit( ld, EXIT_FAILURE );
|
tool_exit( ld, EXIT_FAILURE );
|
||||||
|
@ -2679,6 +2679,37 @@ ldap_parse_deref_control LDAP_P((
|
|||||||
LDAPControl **ctrls,
|
LDAPControl **ctrls,
|
||||||
LDAPDerefRes **drp ));
|
LDAPDerefRes **drp ));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* in psearch.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
LDAP_F( int )
|
||||||
|
ldap_create_persistentsearch_control_value LDAP_P((
|
||||||
|
LDAP *ld,
|
||||||
|
int changetypes,
|
||||||
|
int changesonly,
|
||||||
|
int return_echg_ctls,
|
||||||
|
struct berval *value ));
|
||||||
|
|
||||||
|
LDAP_F( int )
|
||||||
|
ldap_create_persistentsearch_control LDAP_P((
|
||||||
|
LDAP *ld,
|
||||||
|
int changetypes,
|
||||||
|
int changesonly,
|
||||||
|
int return_echg_ctls,
|
||||||
|
int isCritical,
|
||||||
|
LDAPControl **ctrlp ));
|
||||||
|
|
||||||
|
LDAP_F( int )
|
||||||
|
ldap_parse_entrychange_control LDAP_P((
|
||||||
|
LDAP *ld,
|
||||||
|
LDAPControl *ctrl,
|
||||||
|
int *chgtypep,
|
||||||
|
struct berval *prevdnp,
|
||||||
|
int *chgnumpresentp,
|
||||||
|
long *chgnump ));
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* high level LDIF to LDAP structure support
|
* high level LDIF to LDAP structure support
|
||||||
*/
|
*/
|
||||||
|
@ -29,7 +29,7 @@ SRCS = bind.c open.c result.c error.c compare.c search.c \
|
|||||||
tls2.c tls_o.c tls_g.c tls_m.c \
|
tls2.c tls_o.c tls_g.c tls_m.c \
|
||||||
turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \
|
turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \
|
||||||
assertion.c deref.c ldifutil.c ldif.c fetch.c lbase64.c \
|
assertion.c deref.c ldifutil.c ldif.c fetch.c lbase64.c \
|
||||||
msctrl.c
|
msctrl.c psearchctrl.c
|
||||||
|
|
||||||
OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \
|
OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \
|
||||||
controls.lo messages.lo references.lo extended.lo cyrus.lo \
|
controls.lo messages.lo references.lo extended.lo cyrus.lo \
|
||||||
@ -43,7 +43,7 @@ OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \
|
|||||||
tls2.lo tls_o.lo tls_g.lo tls_m.lo \
|
tls2.lo tls_o.lo tls_g.lo tls_m.lo \
|
||||||
turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \
|
turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \
|
||||||
assertion.lo deref.lo ldifutil.lo ldif.lo fetch.lo lbase64.lo \
|
assertion.lo deref.lo ldifutil.lo ldif.lo fetch.lo lbase64.lo \
|
||||||
msctrl.lo
|
msctrl.lo psearchctrl.lo
|
||||||
|
|
||||||
LDAP_INCDIR= ../../include
|
LDAP_INCDIR= ../../include
|
||||||
LDAP_LIBDIR= ../../libraries
|
LDAP_LIBDIR= ../../libraries
|
||||||
|
348
libraries/libldap/psearchctrl.c
Normal file
348
libraries/libldap/psearchctrl.c
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 1998-2019 The OpenLDAP Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted only as authorized by the OpenLDAP
|
||||||
|
* Public License.
|
||||||
|
*
|
||||||
|
* A copy of this license is available in the file LICENSE in the
|
||||||
|
* top-level directory of the distribution or, alternatively, at
|
||||||
|
* <http://www.OpenLDAP.org/license.html>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was developed by Howard Chu for inclusion in
|
||||||
|
* OpenLDAP Software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "portable.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ac/stdlib.h>
|
||||||
|
#include <ac/string.h>
|
||||||
|
#include <ac/time.h>
|
||||||
|
|
||||||
|
#include "ldap-int.h"
|
||||||
|
|
||||||
|
/* Based on draft-ietf-ldapext-c-api-psearch-00 */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------
|
||||||
|
ldap_create_persistentsearch_control_value
|
||||||
|
|
||||||
|
Create and encode the value of the server-side sort control.
|
||||||
|
|
||||||
|
ld (IN) An LDAP session handle, as obtained from a call to
|
||||||
|
ldap_init().
|
||||||
|
|
||||||
|
changetypes (IN) A bit-sensitive field that indicates which kinds of
|
||||||
|
changes the client wants to be informed about. Its
|
||||||
|
value should be LDAP_CHANGETYPE_ANY, or any logical-OR
|
||||||
|
combination of LDAP_CHANGETYPE_ADD,
|
||||||
|
LDAP_CHANGETYPE_DELETE, LDAP_CHANGETYPE_MODIFY, and
|
||||||
|
LDAP_CHANGETYPE_MODDN. This field corresponds to the
|
||||||
|
changeType element of the BER-encoded PersistentSearch
|
||||||
|
control value itself.
|
||||||
|
|
||||||
|
changesonly (IN) A Boolean field that indicates whether the client
|
||||||
|
wishes to only receive searchResultEntry messages for
|
||||||
|
entries that have been changed. If non-zero, only
|
||||||
|
entries that result from changes are returned; other-
|
||||||
|
wise, all of the static entries that match the search
|
||||||
|
criteria are returned before the server begins change
|
||||||
|
notification. This field corresponds to the changes-
|
||||||
|
Only element of the BER-encoded PersistentSearch con-
|
||||||
|
trol value itself.
|
||||||
|
|
||||||
|
return_echg_ctls (IN) A Boolean field that indicates whether the server
|
||||||
|
should send back an Entry Change Notification control
|
||||||
|
with each searchResultEntry that is returned due to a
|
||||||
|
change to an entry. If non-zero, Entry Change
|
||||||
|
Notification controls are requested; if zero, they are
|
||||||
|
not. This field corresponds to the returnECs element
|
||||||
|
of the BER-encoded PersistentSearch control value
|
||||||
|
itself.
|
||||||
|
|
||||||
|
value (OUT) Contains the control value; the bv_val member of the berval structure
|
||||||
|
SHOULD be freed by calling ldap_memfree() when done.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int
|
||||||
|
ldap_create_persistentsearch_control_value(
|
||||||
|
LDAP *ld,
|
||||||
|
int changetypes,
|
||||||
|
int changesonly,
|
||||||
|
int return_echg_ctls,
|
||||||
|
struct berval *value )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
BerElement *ber = NULL;
|
||||||
|
ber_tag_t tag;
|
||||||
|
|
||||||
|
assert( ld != NULL );
|
||||||
|
assert( LDAP_VALID( ld ) );
|
||||||
|
|
||||||
|
if ( ld == NULL ) return LDAP_PARAM_ERROR;
|
||||||
|
if ( value == NULL ) {
|
||||||
|
ld->ld_errno = LDAP_PARAM_ERROR;
|
||||||
|
return LDAP_PARAM_ERROR;
|
||||||
|
}
|
||||||
|
if (( changetypes & 0x0f ) != changetypes ) {
|
||||||
|
ld->ld_errno = LDAP_PARAM_ERROR;
|
||||||
|
return LDAP_PARAM_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
value->bv_val = NULL;
|
||||||
|
value->bv_len = 0;
|
||||||
|
ld->ld_errno = LDAP_SUCCESS;
|
||||||
|
|
||||||
|
ber = ldap_alloc_ber_with_options( ld );
|
||||||
|
if ( ber == NULL) {
|
||||||
|
ld->ld_errno = LDAP_NO_MEMORY;
|
||||||
|
return ld->ld_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = ber_printf( ber, "{ibb}", changetypes, changesonly, return_echg_ctls );
|
||||||
|
if ( tag == LBER_ERROR ) {
|
||||||
|
goto error_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ber_flatten2( ber, value, 1 ) == -1 ) {
|
||||||
|
ld->ld_errno = LDAP_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( 0 ) {
|
||||||
|
error_return:;
|
||||||
|
ld->ld_errno = LDAP_ENCODING_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ber != NULL ) {
|
||||||
|
ber_free( ber, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ld->ld_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------
|
||||||
|
ldap_create_persistentsearch_control
|
||||||
|
|
||||||
|
Create and encode the persistent search control.
|
||||||
|
|
||||||
|
ld (IN) An LDAP session handle, as obtained from a call to
|
||||||
|
ldap_init().
|
||||||
|
|
||||||
|
changetypes (IN) A bit-sensitive field that indicates which kinds of
|
||||||
|
changes the client wants to be informed about. Its
|
||||||
|
value should be LDAP_CHANGETYPE_ANY, or any logical-OR
|
||||||
|
combination of LDAP_CHANGETYPE_ADD,
|
||||||
|
LDAP_CHANGETYPE_DELETE, LDAP_CHANGETYPE_MODIFY, and
|
||||||
|
LDAP_CHANGETYPE_MODDN. This field corresponds to the
|
||||||
|
changeType element of the BER-encoded PersistentSearch
|
||||||
|
control value itself.
|
||||||
|
|
||||||
|
changesonly (IN) A Boolean field that indicates whether the client
|
||||||
|
wishes to only receive searchResultEntry messages for
|
||||||
|
entries that have been changed. If non-zero, only
|
||||||
|
entries that result from changes are returned; other-
|
||||||
|
wise, all of the static entries that match the search
|
||||||
|
criteria are returned before the server begins change
|
||||||
|
notification. This field corresponds to the changes-
|
||||||
|
Only element of the BER-encoded PersistentSearch con-
|
||||||
|
trol value itself.
|
||||||
|
|
||||||
|
return_echg_ctls (IN) A Boolean field that indicates whether the server
|
||||||
|
should send back an Entry Change Notification control
|
||||||
|
with each searchResultEntry that is returned due to a
|
||||||
|
change to an entry. If non-zero, Entry Change
|
||||||
|
Notification controls are requested; if zero, they are
|
||||||
|
not. This field corresponds to the returnECs element
|
||||||
|
of the BER-encoded PersistentSearch control value
|
||||||
|
itself.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int
|
||||||
|
ldap_create_persistentsearch_control(
|
||||||
|
LDAP *ld,
|
||||||
|
int changetypes,
|
||||||
|
int changesonly,
|
||||||
|
int return_echg_ctls,
|
||||||
|
int isCritical,
|
||||||
|
LDAPControl **ctrlp )
|
||||||
|
{
|
||||||
|
struct berval value;
|
||||||
|
|
||||||
|
assert( ld != NULL );
|
||||||
|
assert( LDAP_VALID( ld ) );
|
||||||
|
|
||||||
|
if ( ld == NULL ) {
|
||||||
|
return LDAP_PARAM_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ctrlp == NULL ) {
|
||||||
|
ld->ld_errno = LDAP_PARAM_ERROR;
|
||||||
|
return ld->ld_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
ld->ld_errno = ldap_create_persistentsearch_control_value( ld, changetypes, changesonly, return_echg_ctls, &value );
|
||||||
|
if ( ld->ld_errno == LDAP_SUCCESS ) {
|
||||||
|
ld->ld_errno = ldap_control_create( LDAP_CONTROL_PERSIST_REQUEST,
|
||||||
|
isCritical, &value, 0, ctrlp );
|
||||||
|
if ( ld->ld_errno != LDAP_SUCCESS ) {
|
||||||
|
LDAP_FREE( value.bv_val );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ld->ld_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------
|
||||||
|
ldap_parse_entrychange_control
|
||||||
|
|
||||||
|
Decode the entry change notification control return information.
|
||||||
|
|
||||||
|
ld (IN) An LDAP session handle, as obtained from a call to
|
||||||
|
ldap_init().
|
||||||
|
|
||||||
|
ctrl (IN) The address of the LDAP Control Structure.
|
||||||
|
|
||||||
|
chgtypep (OUT) This result parameter is filled in with one of the
|
||||||
|
following values to indicate the type of change that was
|
||||||
|
made that caused the entry to be returned:
|
||||||
|
LDAP_CONTROL_PERSIST_ENTRY_CHANGE_ADD (1),
|
||||||
|
LDAP_CONTROL_PERSIST_ENTRY_CHANGE_DELETE (2),
|
||||||
|
LDAP_CONTROL_PERSIST_ENTRY_CHANGE_MODIFY (4), or
|
||||||
|
LDAP_CONTROL_PERSIST_ENTRY_CHANGE_RENAME (8).
|
||||||
|
If this parameter is NULL, the change type information
|
||||||
|
is not returned.
|
||||||
|
|
||||||
|
prevdnp (OUT) This result parameter points to the DN the
|
||||||
|
entry had before it was renamed and/or moved by a
|
||||||
|
modifyDN operation. It is set to NULL for other types
|
||||||
|
of changes. If this parameter is NULL, the previous DN
|
||||||
|
information is not returned. The returned value is a
|
||||||
|
pointer to the contents of the control; it is not a
|
||||||
|
copy of the data.
|
||||||
|
|
||||||
|
chgnumpresentp (OUT) This result parameter is filled in with a non-zero
|
||||||
|
value if a change number was returned in the control
|
||||||
|
(the change number is optional and servers MAY choose
|
||||||
|
not to return it). If this parameter is NULL, no indication
|
||||||
|
of whether the change number was present is returned.
|
||||||
|
|
||||||
|
chgnump (OUT) This result paramter is filled in with the change number
|
||||||
|
if one was returned in the control. If this parameter
|
||||||
|
is NULL, the change number is not returned.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int
|
||||||
|
ldap_parse_entrychange_control(
|
||||||
|
LDAP *ld,
|
||||||
|
LDAPControl *ctrl,
|
||||||
|
int *chgtypep,
|
||||||
|
struct berval *prevdnp,
|
||||||
|
int *chgnumpresentp,
|
||||||
|
long *chgnump )
|
||||||
|
{
|
||||||
|
BerElement *ber;
|
||||||
|
ber_tag_t tag, berTag;
|
||||||
|
ber_len_t berLen;
|
||||||
|
ber_int_t chgtype;
|
||||||
|
|
||||||
|
assert( ld != NULL );
|
||||||
|
assert( LDAP_VALID( ld ) );
|
||||||
|
assert( ctrl != NULL );
|
||||||
|
|
||||||
|
if (ld == NULL) {
|
||||||
|
return LDAP_PARAM_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctrl == NULL) {
|
||||||
|
ld->ld_errno = LDAP_PARAM_ERROR;
|
||||||
|
return(ld->ld_errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !ctrl->ldctl_value.bv_val ) {
|
||||||
|
ld->ld_errno = LDAP_DECODING_ERROR;
|
||||||
|
return(ld->ld_errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a BerElement from the berval returned in the control. */
|
||||||
|
ber = ber_init(&ctrl->ldctl_value);
|
||||||
|
|
||||||
|
if (ber == NULL) {
|
||||||
|
ld->ld_errno = LDAP_NO_MEMORY;
|
||||||
|
return(ld->ld_errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( prevdnp != NULL ) {
|
||||||
|
BER_BVZERO( prevdnp );
|
||||||
|
}
|
||||||
|
if ( chgnumpresentp != NULL )
|
||||||
|
*chgnumpresentp = 0;
|
||||||
|
if ( chgnump != NULL )
|
||||||
|
*chgnump = 0;
|
||||||
|
|
||||||
|
/* Extract the change type from the control. */
|
||||||
|
tag = ber_scanf(ber, "{e" /*}*/, &chgtype);
|
||||||
|
|
||||||
|
if( tag != LBER_ENUMERATED ) {
|
||||||
|
ber_free(ber, 1);
|
||||||
|
ld->ld_errno = LDAP_DECODING_ERROR;
|
||||||
|
return(ld->ld_errno);
|
||||||
|
}
|
||||||
|
if ( chgtypep != NULL )
|
||||||
|
*chgtypep = chgtype;
|
||||||
|
|
||||||
|
tag = ber_peek_tag( ber, &berLen );
|
||||||
|
if ( berLen ) {
|
||||||
|
if (tag == LBER_OCTETSTRING) {
|
||||||
|
if (prevdnp != NULL) {
|
||||||
|
tag = ber_get_stringbv( ber, prevdnp, 0 );
|
||||||
|
} else {
|
||||||
|
struct berval bv;
|
||||||
|
tag = ber_skip_element( ber, &bv );
|
||||||
|
}
|
||||||
|
if ( tag == LBER_ERROR ) {
|
||||||
|
ber_free(ber, 1);
|
||||||
|
ld->ld_errno = LDAP_DECODING_ERROR;
|
||||||
|
return(ld->ld_errno);
|
||||||
|
}
|
||||||
|
tag = ber_peek_tag( ber, &berLen );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( chgnumpresentp != NULL || chgnump != NULL ) {
|
||||||
|
ber_int_t chgnum = 0;
|
||||||
|
int present = 0;
|
||||||
|
if (tag == LBER_INTEGER) {
|
||||||
|
present = 1;
|
||||||
|
tag = ber_get_int( ber, &chgnum );
|
||||||
|
if ( tag == LBER_ERROR ) {
|
||||||
|
ber_free(ber, 1);
|
||||||
|
ld->ld_errno = LDAP_DECODING_ERROR;
|
||||||
|
return(ld->ld_errno);
|
||||||
|
}
|
||||||
|
if ( chgnumpresentp != NULL )
|
||||||
|
*chgnumpresentp = present;
|
||||||
|
if ( chgnump != NULL )
|
||||||
|
*chgnump = chgnum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ber_free(ber,1);
|
||||||
|
|
||||||
|
ld->ld_errno = LDAP_SUCCESS;
|
||||||
|
return(ld->ld_errno);
|
||||||
|
}
|
@ -31,7 +31,7 @@ XXSRCS = apitest.c test.c \
|
|||||||
tls2.c tls_o.c tls_g.c tls_m.c \
|
tls2.c tls_o.c tls_g.c tls_m.c \
|
||||||
turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \
|
turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \
|
||||||
assertion.c deref.c ldifutil.c ldif.c fetch.c lbase64.c \
|
assertion.c deref.c ldifutil.c ldif.c fetch.c lbase64.c \
|
||||||
msctrl.c
|
msctrl.c psearchctrl.c
|
||||||
SRCS = threads.c rdwr.c tpool.c rq.c \
|
SRCS = threads.c rdwr.c tpool.c rq.c \
|
||||||
thr_posix.c thr_thr.c thr_nt.c \
|
thr_posix.c thr_thr.c thr_nt.c \
|
||||||
thr_pth.c thr_stub.c thr_debug.c
|
thr_pth.c thr_stub.c thr_debug.c
|
||||||
@ -50,7 +50,7 @@ OBJS = threads.lo rdwr.lo tpool.lo rq.lo \
|
|||||||
tls2.lo tls_o.lo tls_g.lo tls_m.lo \
|
tls2.lo tls_o.lo tls_g.lo tls_m.lo \
|
||||||
turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \
|
turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \
|
||||||
assertion.lo deref.lo ldifutil.lo ldif.lo fetch.lo lbase64.lo \
|
assertion.lo deref.lo ldifutil.lo ldif.lo fetch.lo lbase64.lo \
|
||||||
msctrl.lo
|
msctrl.lo psearchctrl.lo
|
||||||
|
|
||||||
LDAP_INCDIR= ../../include
|
LDAP_INCDIR= ../../include
|
||||||
LDAP_LIBDIR= ../../libraries
|
LDAP_LIBDIR= ../../libraries
|
||||||
|
Loading…
Reference in New Issue
Block a user