379 lines
16 KiB
HTML
379 lines
16 KiB
HTML
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||
|
<html>
|
||
|
<head>
|
||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||
|
<meta name="Copyright" content="Copyright (c) 2006 by IBM Corporation">
|
||
|
<title>Paged LDAP Search Results</title>
|
||
|
<!-- Begin Header Records -->
|
||
|
<!-- All rights reserved. Licensed Materials Property of IBM -->
|
||
|
<!-- US Government Users Restricted Rights -->
|
||
|
<!-- Use, duplication or disclosure restricted by -->
|
||
|
<!-- GSA ADP Schedule Contract with IBM Corp. -->
|
||
|
<!-- Change History: -->
|
||
|
<!-- YYMMDD USERID Change description -->
|
||
|
<!-- Created for V5R3 by bethvh -->
|
||
|
<link rel="stylesheet" type="text/css" href="../rzahg/ic.css">
|
||
|
</head>
|
||
|
<body>
|
||
|
<!--End Header Records -->
|
||
|
<!-- Java sync-link -->
|
||
|
<script language="Javascript" src="../rzahg/synch.js" type="text/javascript">
|
||
|
</script>
|
||
|
|
||
|
<h2>Paged LDAP Search Results</h2>
|
||
|
|
||
|
<p>These routines are used to control the number of entries displayed in one page for the search result returned from the server following an LDAP search operation. </p>
|
||
|
<ul>
|
||
|
<li><a href="ldap_create_page_control.htm">ldap_create_page_control()</a> -- Create a paged results control.</li>
|
||
|
|
||
|
<li><a href="ldap_parse_page_control.htm">ldap_parse_page_control()</a> -- Retrieve values in a paged results control.</li>
|
||
|
|
||
|
</ul>
|
||
|
|
||
|
<p>The ldap_create_page_control() function uses the page size and the cookie
|
||
|
to build the paged results control. The control output from
|
||
|
ldap_create_page_control() function includes the criticality set based on the
|
||
|
value of the isCritical flag. This control is added to the list of
|
||
|
client controls sent to the server on the LDAP search request.</p>
|
||
|
|
||
|
<p>When a paged results control is returned by the server, the
|
||
|
ldap_parse_page_control() function can be used to retrieve the values from the
|
||
|
control. The function takes as input the server controls returned by
|
||
|
the server, and returns a cookie to be used on the next paged results request
|
||
|
for this search operation. </p>
|
||
|
|
||
|
<DL>
|
||
|
<DT><strong>Note:</strong></DT>
|
||
|
<DD>If the page size is greater than or equal to the search sizeLimit value , the
|
||
|
server ignores the paged results control because the request can be satisfied
|
||
|
in a single page. No paged results control value is returned by the
|
||
|
server in this case. In all other cases, error or not, the server
|
||
|
returns a paged results control to the client.
|
||
|
</DD>
|
||
|
</DL>
|
||
|
<P><H4><A NAME="HDRSIMPPAGE">Simple paged results of search results</A></H4>
|
||
|
|
||
|
<p>Simple Paged Results provides paging capabilities for LDAP clients that
|
||
|
want to receive just a subset of search results (page) instead of the entire
|
||
|
list. The next page of entries is returned to the client application
|
||
|
for each subsequent paged results search request submitted by the client until
|
||
|
the operation is canceled or the last result is returned. The server
|
||
|
ignores a simple paged results request if the page size is greater than or
|
||
|
equal to the sizeLimit value for the server because the request can be
|
||
|
satisfied in a single operation.</p>
|
||
|
|
||
|
<p>The ldap_create_page_control() API takes as input a page size and a cookie,
|
||
|
and outputs an LDAPControl structure that can be added to the list of client
|
||
|
controls sent to the server on the LDAP search request. The page size
|
||
|
specifies how many search results must be returned for this request, and the
|
||
|
cookie is an opaque structure returned by the server. (On the initial
|
||
|
paged results search request, the cookie must be a zero-length string).
|
||
|
No assumptions must be made about the internal organization or value of the
|
||
|
cookie. The cookie is used on subsequent paged results search requests
|
||
|
when more entries are to be retrieved from the results set. The cookie
|
||
|
must be the value of the cookie returned on the last response returned from
|
||
|
the server on all subsequent paged results search requests. The cookie
|
||
|
is empty when there are no more entries to be returned by the server, or when
|
||
|
the client application abandons the paged results request by sending in a zero
|
||
|
page size. After the paged results search request has been completed,
|
||
|
the cookie must not be used because it is no longer valid.</p>
|
||
|
|
||
|
<p>The LDAPControl structure returned by ldap_create_page_control() can be
|
||
|
used as input to ldap_search_ext() or ldap_search_ext_s(), which are used to
|
||
|
make the actual search request.</p>
|
||
|
|
||
|
<DL>
|
||
|
<DT><strong>Note:</strong></DT>
|
||
|
<DD>Server side simple paged results is an optional extension of the LDAP v3
|
||
|
protocol, so the server you have bound to prior to the ldap_search_ext() or
|
||
|
ldap_search_ext_s() call might not support this function.
|
||
|
</DD>
|
||
|
</DL>
|
||
|
|
||
|
<p>Upon completion of the search request you submitted using ldap_search_ext()
|
||
|
or ldap_search_ext_s(), the server returns an LDAP result message that
|
||
|
includes a paged results control. The client application can parse this
|
||
|
control using ldap_parse_page_control(), which takes the returned server
|
||
|
response controls (a null terminated array of pointers to LDAPControl
|
||
|
structures) as input. ldap_parse_page_control() outputs a cookie and
|
||
|
the total number of entries in the entire search result set. Servers
|
||
|
that cannot provide an estimate for the total number of entries might set this
|
||
|
value to zero. Use ldap_controls_free() to free the memory used by the
|
||
|
client application to hold the server controls when you are finished
|
||
|
processing all controls returned by the server for this search request.</p>
|
||
|
|
||
|
<p>The server might limit the number of outstanding paged results operations
|
||
|
from a given client or for all clients. A server with a limit on the
|
||
|
number of outstanding paged results requests might return either
|
||
|
LDAP_UNWILLING_TO_PERFORM in the sortResultsDone message or age out an older
|
||
|
paged results request. There is no guarantee to the client application
|
||
|
that the results of a search query have remained unchanged throughout the life
|
||
|
of a set of paged results request/response sequences. If the result set
|
||
|
for that query has changed since the initial search request specifying paged
|
||
|
results, the client application might not receive all the entries matching the
|
||
|
given search criteria. When chasing referrals, the client application
|
||
|
must send in an initial paged results request, with the cookie set to null, to
|
||
|
each of the referral servers. It is up to the application using the
|
||
|
client's services to decide whether or not to set the criticality as to
|
||
|
the support of paged results, and to handle a lack of support of this control
|
||
|
on referral servers as appropriate, based on the application.
|
||
|
Additionally, the LDAP server does not ensure that the referral server
|
||
|
supports the paged results control. Multiple lists can be returned to
|
||
|
the client application, some not paged. It is the client
|
||
|
application's decision as to how best to present this information to the
|
||
|
end user. Possible solutions include: </p>
|
||
|
|
||
|
<ul>
|
||
|
<li>Combine all referral results before presenting to the end user</li>
|
||
|
<li>Show multiple lists and the corresponding referral server host name</li>
|
||
|
<li>Take no extra steps and show all results to the end user as they are
|
||
|
returned from the server</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>The client application must turn off referrals to get one truly paged
|
||
|
list; otherwise, when chasing referrals with the paged results search
|
||
|
control specified, unpredictable results might occur.</p>
|
||
|
|
||
|
<p>More information about the simple paged results search control, with
|
||
|
control OID of
|
||
|
1.2.840.113556.1.4.319, can be found
|
||
|
in RFC 2686 - LDAP Control Extension for Simple Paged Results
|
||
|
Manipulation.</p>
|
||
|
|
||
|
<h3>Related Information</h3>
|
||
|
|
||
|
<ul>
|
||
|
<li><a href="ldap_create_page_control.htm">ldap_create_page_control()</a> -- Create a paged results control.</li>
|
||
|
|
||
|
<li><a href="ldap_parse_page_control.htm">ldap_parse_page_control()</a> -- Retrieve values in a paged results control.</li>
|
||
|
|
||
|
<li><a href="ldap_create_sort_keylist.htm">ldap_create_sort_keylist()</a> -- Create a structure with sort key values.</li>
|
||
|
|
||
|
<li><a href="ldap_free_sort_keylist.htm">ldap_free_sort_keylist()</a> -- Free all memory used by the sort key list.</li>
|
||
|
|
||
|
<li><a href="ldap_create_sort_control.htm">ldap_create_sort_control()</a> -- Create a sorted results control.</li>
|
||
|
|
||
|
<li><a href="ldap_parse_sort_control.htm">ldap_parse_sort_control()</a> -- Retrieve values in a sorted results control.</li>
|
||
|
|
||
|
<li><a href="ldap_search.htm">ldap_search()</a> -- Asynchronously search the
|
||
|
directory.</li>
|
||
|
|
||
|
<li><a href="ldap_search_ext.htm">ldap_search_ext()</a> -- Asynchronously
|
||
|
search the directory with controls.</li>
|
||
|
|
||
|
<li><a href="ldap_search_ext_s.htm">ldap_search_ext_s()</a> -- Synchronously
|
||
|
search the directory with controls.</li>
|
||
|
|
||
|
<li><a href="ldap_parse_result.htm">ldap_parse_result()</a> -- Extract information from results.</li>
|
||
|
|
||
|
<li><a href="ldap_cntrl_free.htm">ldap_control_free()</a> -- Free a single
|
||
|
LDAPControl structure.</li>
|
||
|
|
||
|
<li><a href="ldap_cntrls_free.htm">ldap_controls_free()</a> -- Free an array of
|
||
|
LDAPControl structures.</li>
|
||
|
|
||
|
</ul>
|
||
|
|
||
|
<br>
|
||
|
<h3><a name="example.htm">Example</a></h3>
|
||
|
|
||
|
<p>See <a href="../apiref/aboutapis.htm#codedisclaimer">Code disclaimer information</a>
|
||
|
for information pertaining to code examples.</p>
|
||
|
|
||
|
<p>The following example shows how to use the LDAP paged search APIs:</p>
|
||
|
|
||
|
<pre>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <unistd.h>
|
||
|
#include <time.h>
|
||
|
#include <ldap.h>
|
||
|
#include <lber.h>
|
||
|
|
||
|
static char ibmid[] = "Copyright IBM Corporation 2003 LICENSED MATERIAL - PROGRAM PROPERTY OF IBM";
|
||
|
#define BIND_DN "cn=administrator"
|
||
|
#define BIND_PW "adminpwd"
|
||
|
|
||
|
char *server, *base, *filter, *scopes[] = { "BASE", "ONELEVEL", "SUBTREE" };
|
||
|
int scope;
|
||
|
LDAP *ld;
|
||
|
|
||
|
int main (int argc, char *argv[])
|
||
|
{
|
||
|
int l_rc, l_entries, l_port, l_entry_count=0, morePages, l_errcode=0, page_nbr;
|
||
|
unsigned long pageSize;
|
||
|
struct berval *cookie=NULL;
|
||
|
char pagingCriticality = 'T', *l_dn;
|
||
|
unsigned long totalCount;
|
||
|
LDAPControl *pageControl=NULL, *M_controls[2] = { NULL, NULL }, **returnedControls = NULL;
|
||
|
LDAPMessage *l_result, *l_entry;
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Check input parameters */
|
||
|
/* */
|
||
|
if (argc < 5)
|
||
|
{
|
||
|
printf("The input parameters are as follows:\n");
|
||
|
printf(" 1. Search base\n");
|
||
|
printf(" 2. Filter\n");
|
||
|
printf(" 3. Search Scope (0=base, 1=onelevel, OR 2=subtree)\n");
|
||
|
printf(" 4. Page size\n");
|
||
|
return 0;
|
||
|
}
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Set default values: Server and Port. And then parse */
|
||
|
/* input parameters into program variables */
|
||
|
/* */
|
||
|
server = NULL;
|
||
|
l_port = LDAP_PORT;
|
||
|
|
||
|
base = argv[1];
|
||
|
filter = argv[2];
|
||
|
scope = atoi(argv[3]);
|
||
|
pageSize = atoi(argv[4]);
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Initialize an LDAP session */
|
||
|
/* */
|
||
|
ld = ldap_init(server, l_port);
|
||
|
/* Check if connection is OK */
|
||
|
if (ld == NULL)
|
||
|
{
|
||
|
printf("==Error==");
|
||
|
printf(" Init of server %s at port %d failed.\n", server, l_port);
|
||
|
return 0;
|
||
|
}
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Bind as the ldap administrator */
|
||
|
/* */
|
||
|
l_rc = ldap_simple_bind_s (ld, BIND_DN , BIND_PW);
|
||
|
if ( l_rc != LDAP_SUCCESS)
|
||
|
{
|
||
|
printf("==Error== %s");
|
||
|
printf(" Unable to Bind to the LDAP server. Return code is %d.\n", l_rc);
|
||
|
return 0;
|
||
|
}
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
printf(" The search parms were:\n");
|
||
|
printf(" base: %s\n",base);
|
||
|
printf(" scope: %s\n",scopes[scope]);
|
||
|
printf(" filter: %s\n",filter);
|
||
|
printf(" page size: %d\n",pageSize);
|
||
|
printf(" The entries returned were:\n");
|
||
|
page_nbr = 1;
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Get one page of the returned results each time */
|
||
|
/* through the loop */
|
||
|
do
|
||
|
{
|
||
|
l_rc = ldap_create_page_control(ld, pageSize, cookie, pagingCriticality, &pageControl);
|
||
|
|
||
|
/* Insert the control into a list to be passed to the search. */
|
||
|
M_controls[0] = pageControl;
|
||
|
|
||
|
/* Search for entries in the directory using the parmeters. */
|
||
|
l_rc = ldap_search_ext_s(ld, base, scope, filter, NULL, 0, M_controls, NULL, NULL, 0, &l_result);
|
||
|
if ((l_rc != LDAP_SUCCESS) & (l_rc != LDAP_PARTIAL_RESULTS))
|
||
|
{
|
||
|
printf("==Error==");
|
||
|
printf(" Failure during a search. Return code is %d.\n",l_rc);
|
||
|
ldap_unbind(ld);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* Parse the results to retrieve the contols being returned. */
|
||
|
l_rc = ldap_parse_result(ld, l_result, &l_errcode, NULL, NULL, NULL, &returnedControls, LDAP_FALSE);
|
||
|
|
||
|
if (cookie != NULL)
|
||
|
{
|
||
|
ber_bvfree(cookie);
|
||
|
cookie = NULL;
|
||
|
}
|
||
|
|
||
|
/* Parse the page control returned to get the cookie and */
|
||
|
/* determine whether there are more pages. */
|
||
|
l_rc = ldap_parse_page_control(ld, returnedControls, &totalCount, &cookie);
|
||
|
|
||
|
/* Determine if the cookie is not empty, indicating there are more pages for these search parameters. */
|
||
|
if (cookie && cookie->bv_val != NULL && (strlen(cookie->bv_val) > 0))
|
||
|
{
|
||
|
morePages = LDAP_TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
morePages = LDAP_FALSE;
|
||
|
}
|
||
|
|
||
|
/* Cleanup the controls used. */
|
||
|
if (returnedControls != NULL)
|
||
|
{
|
||
|
ldap_controls_free(returnedControls);
|
||
|
returnedControls = NULL;
|
||
|
}
|
||
|
M_controls[0] = NULL;
|
||
|
ldap_control_free(pageControl);
|
||
|
pageControl = NULL;
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Disply the returned result */
|
||
|
/* */
|
||
|
/* Determine how many entries have been found. */
|
||
|
if (morePages == LDAP_TRUE)
|
||
|
printf("===== Page : %d =====\n", page_nbr);
|
||
|
l_entries = ldap_count_entries(ld, l_result);
|
||
|
|
||
|
if (l_entries > 0)
|
||
|
{
|
||
|
l_entry_count = l_entry_count + l_entries;
|
||
|
}
|
||
|
|
||
|
for ( l_entry = ldap_first_entry(ld, l_result);
|
||
|
l_entry != NULL;
|
||
|
l_entry = ldap_next_entry(ld, l_entry) )
|
||
|
{
|
||
|
l_dn = ldap_get_dn(ld, l_entry);
|
||
|
printf(" %s\n",l_dn);
|
||
|
}
|
||
|
|
||
|
/* Free the search results. */
|
||
|
ldap_msgfree(l_result);
|
||
|
page_nbr = page_nbr + 1;
|
||
|
|
||
|
} while (morePages == LDAP_TRUE);
|
||
|
|
||
|
printf("\n %d entries found during the search",l_entry_count);
|
||
|
/* Free the cookie since all the pages for these search parameters */
|
||
|
/* have been retrieved. */
|
||
|
ber_bvfree(cookie);
|
||
|
cookie = NULL;
|
||
|
|
||
|
/* Close the LDAP session. */
|
||
|
ldap_unbind(ld);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
</pre>
|
||
|
|
||
|
<hr>
|
||
|
<table align="center" cellpadding="2" cellspacing="2">
|
||
|
<tr align="center">
|
||
|
<td valign="middle" align="center"><a href="dirserv1.htm">LDAP
|
||
|
APIs</a> | <a href="aplist.htm">APIs by category</a></td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
</body>
|
||
|
</html>
|
||
|
|