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.
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.
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.
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.
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.
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.
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.
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:
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.
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.
See Code disclaimer information for information pertaining to code examples.
The following example shows how to use the LDAP paged search APIs:
#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; }
LDAP APIs | APIs by category |