Mozilla LDAP SDK Programmer's Guide/Using Filter Configuration Files With LDAP C SDK

From MozillaWiki
Jump to: navigation, search

This section explains how to use LDAP C API functions to work with filter configuration files.

Understanding Filter Configuration Files for LDAP C SDK

Filter configuration files can help simplify the process of selecting the appropriate filter for a search request. A filter configuration file contains a list of filters that you can load and use in your searches. You might be writing a client that allows users to search the directory. Use different search filters tailored for specific types of search criteria.

For example, if the user wants to search for the email address bjensen@example.com, you might want to use this search filter:

(mail=bjensen@example.com)

Similarly, suppose the search term entered by the user contains numbers, as in 555-1212. In this case, you might want to use this search filter:

(telephoneNumber=555-1212)

Rather than write code to find and select the appropriate filter, you can include the filters in a filter configuration file. For example, the following section of a filter configuration file specifies one filter for telephone numbers and two filters for email addresses. The telephone number filter is used if the search criteria contain one or more numbers. The email filters are used if the search criteria contain an at sign, @.

"people"
  "^[0-9][0-9-]*$"           " "
  "(telephoneNumber=*%v))"   "phone number ends with"
  "@"    " "  "(mail=%v)"    "email address is"
  "(mail=%v*)"               "email address starts with"

You should specify the filters in the order that you want the filters to be used. For example, if you want to apply the (mail=%v) filter before the (mail=%v*) filter, make sure that the filters appear in that order.


Syntax for Filter Configuration Files


A filter configuration file has the following format. The variables are discussed in the following sections.

''tag''
  ''pattern1''    ''delimiters''    ''filter1-1''  ''desc1-1''  [''scope'']
  ''filter1-2''   ''desc1-2''                           [''scope'']
  ''pattern2''    ''delimiters''    ''filter2-1''  ''desc2-1''  [''scope'']

Tag for Filter Groups


A tag identifies a group of filters. You can use different tags to distinguish filters for different types of objects. For example, you can use one tag to represent filters for person entries, another tag to represent filters for organization entries, and so on.

"people"
     (filters for searching "person" entries) 
"organization"
     (filters for "organization" entries)

When you call functions like ldap_getfirstfilter() to retrieve a filter, you can specify a tag, or part of a tag, as a parameter. The tag narrows the list of filters that the function can retrieve.


Patterns to Select Filters


pattern1 and pattern2 are regular expressions used to determine which filter is selected, based on the search criteria. For example, if you specify "^[0-9]" as the pattern for a filter, the filter is selected for all search criteria that begin with a number.

"people"
  "^[0-9]" 

Delimiters for Fields


Delimiters specifies the delimiters used to distinguish one field from another field within the search criteria. For example, if the search criteria consist of a city name and a state abbreviation separated by a comma, specify a comma as the delimiter.


Filter Lists


filter1-1, filter1-2, and filter2-1 are filters. Use %v to represent the search criteria. For example, to search email addresses, use the filter (mail=%v). During runtime, if the search criteria bjensen@example.com is entered, the filter becomes (mail=bjensen@example.com).

The search criteria might consist of a number of delimited fields. For example, the criteria might have a last name, first name format such as Jensen, Barbara. Use %v1, %v2, , %vn to represent the different fields within the search criteria as shown here:

"people"
  "^[A-Z]*,"      ","    ((sn=%v1)(givenName=%v2))

In this example, the delimiter is a comma. The word before the delimiter replaces %v1 in the filter. The word after the delimiter replaces %v2 in the filter. If the user searches for Jensen, Barbara , the resulting filter is as follows:

((sn=Jensen)(givenName=Barbara)) You can also specify ranges of fields. For example, to specify the values in the first three fields, use %v1-3. To specify values from the third field to the last field, use %v3-. To specify the value in the last field, use %v$.


Descriptions of Filters


desc1-1, desc1-2, and desc2-1 are phrases that briefly describe the filters.


Filter Parameters


Filter specifications in the configuration file support the following parameters:

  • %v
    Insert the search criterion as is in place of %v.
    For example, if the filter specification is (mail=%v), entering bjensen results in the filter (mail=bjensen).
  • %v$
    Insert the last word of the search criterion as is in place of %v.
    For example, if the filter specification is (sn=%v$), entering Barbara Jensen results in the filter (sn=Jensen).
  • %vN
    Insert the Nth word of the criteria in place of %v, where N is a single digit between 1 and 9.
    For example, if the filter specification is (sn=%v2), entering Barbara Jensen results in the filter (sn=Jensen).
  • %vM-N
    Insert the sequence of the Mth through Nth words of the criteria in place of %v. Here, M and N are single digits between 1 and 9.
    For example, if the filter specification is (cn=%v1-2), entering Barbara Jensen results in the filter (cn=Barbara Jensen).
  • %vN-
    Insert the sequence of the Nth through last words of the criteria in place of %v. Here, N is a single digit between 1 and 9.
    For example, if the filter specification is (cn=%v2-), entering Ms. Barbara Jensen results in the filter (cn=Barbara Jensen).

Loading Filter Configuration Files With LDAP C SDK

To load a filter configuration file, call the ldap_init_getfilter() function. You can also read the filter configuration file from a buffer in memory by calling the ldap_init_getfilter_buf() function. Both functions return a pointer to an LDAPFiltDesc structure, which contains information about the filter. If an error occurs, both functions return NULL.


Retrieving Filters


After loading a filter configuration file into memory, you can retrieve filters based on the search criteria. For example, the search criteria might be an email address, (bjensen@example.com). Have your client automatically search for this value in the mail attribute of person entries.

To retrieve the first filter that matches the search criteria, call the ldap_getfirstfilter() function. To get the next filter that matches the search criteria, call the ldap_getnextfilter() function. Both functions return a pointer to an LDAPFiltInfo structure, which contains information about the filter, as shown here.

#include <stdio.h>
#include "ldap.h"

LDAP          *ld;
LDAPMessage   *result, *e;
BerElement    *ber;
char          *a, *dn;
char          **vals;
int i;
LDAPFiltDesc *ldfp;
LDAPFiltInfo *ldfi;
char buf[ 80 ]; /* contains the search criteria */
int found;

/* Load the filter configuration file into an LDAPFiltDesc structure. */
if ( ( ldfp = ldap_init_getfilter( "myfilters.conf" ) ) == NULL ) {
  perror( "Cannot open filter configuration file" );
}

/* Select a filter to use when searching for the value in buf.
Use filters under the "people" tag in the filter configuration file. */
found = 0;
for ( ldfi = ldap_getfirstfilter( ldfp, "people", buf ); ldfi != NULL;
  ldfi = ldap_getnextfilter( ldfp ) ) {

  /* Use the selected filter to search the directory. */
  if ( ldap_search_s( ld, "dc=example,dc=com", ldfi->lfi_scope,
   ldfi->lfi_filter, NULL, 0, result ) != LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
  } else {

    /* Once a filter gets results back, stop iterating through
    the different filters. */
    if ( ( found = ldap_count_entries( ld, result ) > 0 ) ) {
      break;
    } else {
      ldap_msgfree( result );
    }
  }
}

if ( found == 0 ) {
  printf( "No matching entries found.\n" );
} else {
  printf( "Found %d match%s where %s \"%s\"\n\n", found,
   found == 1 ? "" : "es", ldfi->lfi_desc, buf );
}

ldap_msgfree( result );
ldap_getfilter_free( ldfp );

Suppose that the search criteria is bjensen@example.com and that the client application finds a single matching entry. Then the application prints the following output:

Found 1 match where email address is bjensen@example.com

Filter Prefixes and Suffixes for LDAP C SDK

If you need to apply a filter to all searches, add a filter prefix and suffix to all filters. Do not add the criteria to all filters. The prefix is automatically added to any filter retrieved through the ldap_getfirstfilter() and ldap_getnextfilter() functions. The required suffix ) needed to balance the number of parentheses is also added. For example, suppose you use this filter in a filter configuration file:

(cn=Babs Jensen)

You can retrieve this filter by using ldap_getfirstfilter() or ldap_getnextfilter(). These functions get a filter that constrains your client searches to person entries for the defined filter:

((objectClass=person)(cn=Babs Jensen))

To add a prefix and suffix automatically to all filters retrieved from the filter configuration file, call the ldap_set_filter_additions() function. The following example adds the prefix ((objectClass=person) and the suffix ) to each filter retrieved.

#include "ldap.h"

LDAPFiltDesc *lfdp;
char *filter_file = "myfilters.conf";
char *prefix = "((objectClass=person)";
char *suffix = ")";

lfdp = ldap_init_getfilter( filter_file );
ldap_setfilteraffixes( lfdp, prefix, suffix );

Freeing Filters From Memory With LDAP C SDK

When you complete your search, free the LDAPFiltDesc structure from memory. To free LDAPFiltDesc, call the ldap_getfilter_free() function as shown here.

#include "ldap.h"

LDAPFiltDesc *lfdp;
char *filter_file = "myfilters.conf";

/* Read the filter configuration file into an LDAPFiltDesc structure. */
lfdp = ldap_init_getfilter( filter_file );

/* Retrieve filters and perform searches. */

/* Free the configuration file (the LDAPFiltDesc structure). */
ldap_getfilter_free( lfdp );

Creating Filters Programmatically With LDAP C SDK

You can build your own filters by calling the ldap_create_filter() function. The following example builds the filter (mail=bjensen@example.com).

char buf[LDAP_FILT_MAXSIZ];
char *pattern = "(%a=%v);
char *attr = "mail";
char *value = "bjensen@example.com";

ldap_create_filter( buf, LDAP_FILT_MAXSIZ, pattern, NULL, NULL, attr,
    value, NULL );