mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-23 16:19:35 -05:00
add paged results support to back-ldap
This commit is contained in:
parent
284ca3ecf0
commit
809e623cd9
3 changed files with 142 additions and 6 deletions
|
|
@ -37,6 +37,8 @@ static int search_candidates(
|
|||
ID *ids,
|
||||
ID *scopes );
|
||||
|
||||
static int parse_paged_cookie( Operation *op, SlapReply *rs );
|
||||
|
||||
static void send_paged_response(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
|
|
@ -786,7 +788,14 @@ dn2entry_retry:
|
|||
tentries = BDB_IDL_N(candidates);
|
||||
}
|
||||
|
||||
if ( get_pagedresults(sop) > SLAP_NO_CONTROL ) {
|
||||
if ( get_pagedresults( sop ) > SLAP_NO_CONTROL ) {
|
||||
/* deferred cookie parsing */
|
||||
rs->sr_err = parse_paged_cookie( sop, rs );
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||
send_ldap_result( sop, rs );
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( (ID)( sop->o_pagedresults_state.ps_cookie ) == 0 ) {
|
||||
id = bdb_idl_first( candidates, &cursor );
|
||||
|
||||
|
|
@ -1739,6 +1748,125 @@ static int search_candidates(
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_paged_cookie( Operation *op, SlapReply *rs )
|
||||
{
|
||||
LDAPControl **c;
|
||||
int rc = LDAP_SUCCESS;
|
||||
ber_tag_t tag;
|
||||
ber_int_t size;
|
||||
BerElement *ber;
|
||||
struct berval cookie = BER_BVNULL;
|
||||
|
||||
/* this function must be invoked only if the pagedResults
|
||||
* control has been detected, parsed and partially checked
|
||||
* by the frontend */
|
||||
assert( get_pagedresults( op ) > SLAP_NO_CONTROL );
|
||||
|
||||
/* look for the appropriate ctrl structure */
|
||||
for ( c = op->o_ctrls; c[0] != NULL; c++ ) {
|
||||
if ( strcmp( c[0]->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS ) == 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( c[0] == NULL ) {
|
||||
rs->sr_text = "missing pagedResults control";
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Already tested by frontend */
|
||||
assert( c[0]->ldctl_value.bv_len > 0 );
|
||||
#if 0
|
||||
if ( c[0]->ldctl_value.bv_len == 0 ) {
|
||||
rs->sr_text = "paged results control value is empty (or absent)";
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Parse the control value
|
||||
* realSearchControlValue ::= SEQUENCE {
|
||||
* size INTEGER (0..maxInt),
|
||||
* -- requested page size from client
|
||||
* -- result set size estimate from server
|
||||
* cookie OCTET STRING
|
||||
* }
|
||||
*/
|
||||
ber = ber_init( &c[0]->ldctl_value );
|
||||
if ( ber == NULL ) {
|
||||
rs->sr_text = "internal error";
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
tag = ber_scanf( ber, "{im}", &size, &cookie );
|
||||
|
||||
/* Already tested by frontend */
|
||||
assert( tag != LBER_ERROR );
|
||||
#if 0
|
||||
if ( tag == LBER_ERROR ) {
|
||||
rs->sr_text = "paged results control could not be decoded";
|
||||
rc = LDAP_PROTOCOL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Already tested by frontend */
|
||||
assert( size >= 0 );
|
||||
#if 0
|
||||
if ( size < 0 ) {
|
||||
rs->sr_text = "paged results control size invalid";
|
||||
rc = LDAP_PROTOCOL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* cookie decoding/checks deferred to backend... */
|
||||
if ( cookie.bv_len ) {
|
||||
PagedResultsCookie reqcookie;
|
||||
if( cookie.bv_len != sizeof( reqcookie ) ) {
|
||||
/* bad cookie */
|
||||
rs->sr_text = "paged results cookie is invalid";
|
||||
rc = LDAP_PROTOCOL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
AC_MEMCPY( &reqcookie, cookie.bv_val, sizeof( reqcookie ));
|
||||
|
||||
if ( reqcookie > op->o_pagedresults_state.ps_cookie ) {
|
||||
/* bad cookie */
|
||||
rs->sr_text = "paged results cookie is invalid";
|
||||
rc = LDAP_PROTOCOL_ERROR;
|
||||
goto done;
|
||||
|
||||
} else if ( reqcookie < op->o_pagedresults_state.ps_cookie ) {
|
||||
rs->sr_text = "paged results cookie is invalid or old";
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Initial request. Initialize state. */
|
||||
#if 0
|
||||
if ( op->o_conn->c_pagedresults_state.ps_cookie != 0 ) {
|
||||
/* There's another pagedResults control on the
|
||||
* same connection; reject new pagedResults controls
|
||||
* (allowed by RFC2696) */
|
||||
rs->sr_text = "paged results cookie unavailable; try later";
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
op->o_pagedresults_state.ps_cookie = 0;
|
||||
op->o_pagedresults_state.ps_count = 0;
|
||||
}
|
||||
|
||||
done:;
|
||||
(void)ber_free( ber, 1 );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
send_paged_response(
|
||||
Operation *op,
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ fail:;
|
|||
} else {
|
||||
rc = ldap_parse_result( lc->ld, res, &rs->sr_err,
|
||||
&match.bv_val, (char **)&rs->sr_text,
|
||||
NULL, NULL, 1 );
|
||||
NULL, &rs->sr_ctrls, 1 );
|
||||
if (rc != LDAP_SUCCESS ) {
|
||||
rs->sr_err = rc;
|
||||
}
|
||||
|
|
@ -307,6 +307,11 @@ finish:;
|
|||
}
|
||||
#endif /* LDAP_BACK_PROXY_AUTHZ */
|
||||
|
||||
if ( rs->sr_ctrls ) {
|
||||
ldap_controls_free( rs->sr_ctrls );
|
||||
rs->sr_ctrls = NULL;
|
||||
}
|
||||
|
||||
if ( match.bv_val ) {
|
||||
if ( rs->sr_matched != match.bv_val ) {
|
||||
free( (char *)rs->sr_matched );
|
||||
|
|
|
|||
|
|
@ -873,26 +873,28 @@ static int parsePagedResults (
|
|||
* }
|
||||
*/
|
||||
ber = ber_init( &ctrl->ldctl_value );
|
||||
if( ber == NULL ) {
|
||||
if ( ber == NULL ) {
|
||||
rs->sr_text = "internal error";
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
tag = ber_scanf( ber, "{im}", &size, &cookie );
|
||||
|
||||
if( tag == LBER_ERROR ) {
|
||||
if ( tag == LBER_ERROR ) {
|
||||
rs->sr_text = "paged results control could not be decoded";
|
||||
rc = LDAP_PROTOCOL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if( size < 0 ) {
|
||||
if ( size < 0 ) {
|
||||
rs->sr_text = "paged results control size invalid";
|
||||
rc = LDAP_PROTOCOL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if( cookie.bv_len ) {
|
||||
#if 0
|
||||
/* defer cookie decoding/checks to backend... */
|
||||
if ( cookie.bv_len ) {
|
||||
PagedResultsCookie reqcookie;
|
||||
if( cookie.bv_len != sizeof( reqcookie ) ) {
|
||||
/* bad cookie */
|
||||
|
|
@ -930,6 +932,7 @@ static int parsePagedResults (
|
|||
op->o_pagedresults_state.ps_cookie = 0;
|
||||
op->o_pagedresults_state.ps_count = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
op->o_pagedresults_size = size;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue