add paged results support to back-ldap

This commit is contained in:
Pierangelo Masarati 2004-08-24 09:19:33 +00:00
parent 284ca3ecf0
commit 809e623cd9
3 changed files with 142 additions and 6 deletions

View file

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

View file

@ -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 );

View file

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