Mozilla LDAP C SDK Programmer's Guide
Chapter 7 - Using Filter Configuration Files
This chapter explains how to use API functions to work with filter configuration files. Filter configuration files can help simplify the process of selecting the appropriate search filter for a search request.
The chapter contains the following sections:
- Understanding Filter Configuration Files
- Understanding the Configuration File Syntax
- Understanding Filter Parameters
- Loading a Filter Configuration File
- Retrieving Filters
- Adding Filter Prefixes and Suffixes
- Freeing Filters from Memory
- Creating Filters Programmatically
Understanding Filter Configuration Files
Suppose that you are writing a client that allows users to search
the directory. You might want to use different search filters
tailored for specific types of search criteria. For example, suppose
the user wants to search for this:
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, like this:
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 (based on the user's search criteria), you can include the filters in a filter configuration file.
A filter configuration file contains a list of filters that you can load and use in your searches.
Understanding the Configuration File Syntax
A filter configuration file has the following format:
tag pattern1 delimiters filter1-1 desc1-1 [scope] filter1-2 desc1-2 [scope] pattern2 delimiters filter2-1 desc2-1 [scope] ...
This format is explained below:
-
tag
identifies a group of filters. You can use different tags to distinguish filters for different types of objects. For example, you can use a tag to represent filters for person entries, a 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 likeldap_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. -
pattern1
andpattern2
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 beginning with a number."people" "^[0-9]" ...
For more information on regular expressions, consult your UNIX documentation (for example, documentation on theed
command contains some information on regular expressions). -
delimiters
specifies the delimiters used to distinguish one field from another within the search criteria. For example, if the search criteria consists of a city name and state abbreviation separated by a comma, specify ",
" as the delimiter. -
filter1-1
,filter1-2
, andfilter2-1
are filters. Use%v
to represent the search criteria. For example, to search e-mail addresses, use the filter(mail=%v)
. During runtime, if the search criteriabjensen@example.com
is entered, the filter becomes(mail=bjensen@example.com)
. If the search criteria consists of a number of delimited fields (for example, a "last name, first name" format like "Jensen, Barbara
"), use%v1, %v2, ... , %vn
to represent the different fields within the search criteria. For example:"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, and the word after the delimiter replaces%v2
in the filter. If the user searches for:Jensen, Barbara
the resulting filter is:(&(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$
. -
desc1-1
,desc1-2
, anddesc2-1
are phrases briefly describing the filters.
For example, the following section of a filter configuration file
specifies a filter for telephone numbers and two filters for email
addresses. The telephone number filter is used if the search
criteria contains one or more numbers. The email filters are used if
the search criteria contains 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 them 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.
Understanding Filter Parameters
Within a filter, you can use the following parameters:
-
%v
This parameter means that the entire search criteria is inserted in place of%v
. For example, if the filter is(mail=%v)
, entering the wordjensen
results in the filter(mail=jensen)
. -
%v$
This parameter means that the last word in the search criteria is inserted in place of%v
. For example, if the filter is(sn=%v)
, entering the wordsBarbara Jensen
results in the filter(sn=Jensen)
. -
%vN
N
is a single digit between 1 and 9. This parameter means that theN
th word in the search criteria is inserted in place of%vN.
For example, if the filter is(sn=%v2)
, entering the wordsBarbara Jensen
results in the filter(sn=Jensen)
. -
%vM-N
M
andN
are single digits between 1 and 9. This parameter means that the sequence of theM
th through theN
th words in the search criteria is inserted in place of%vM-N.
For example, if the filter is(cn=%v1-2)
, entering the wordsBarbara Jensen
results in the filter(cn=Barbara Jensen)
. -
%vN-
N
is a single digit between 1 and 9. This parameter means that the sequence of theN
th through the last words in the search criteria is inserted in place of%vN-
. For example, if the filter is(cn=%v2-)
, entering the wordsMs. Barbara Jensen
results in the filter(cn=Barbara Jensen)
.
Loading a Filter Configuration File
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, if the
search criteria is an e-mail address
(bjensen@example.com
), you can 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.
The following section of code uses a filter configuration file containing the following filters:
"people" "^[0-9][0-9-]*$" " "(telephoneNumber=*%v))" "phone number ends with" "@" " " "(mail=%v)" "email address is" "(mail=%v*)" "email address starts with"
This section of code retrieves filters that match the search criteria.
Code Example 7-1 - Retrieving configuration filters
#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 the client application finds
one matching entry. In this case, the application prints the
following output:
Found 1 match where email address is bjensen@example.com
Adding Filter Prefixes and Suffixes
If you need to apply a filter to all searches, you can add a
filter prefix and suffix to all filters (rather than add the
criteria to all filters). For example, if your client searches only
for person entries, you can add the following filter prefix to
restrict the search:
(&(objectClass=person)
Note that this filter now requires a suffix ")" to balance the
number of parentheses. This prefix is automatically added to any
filter retrieved through the
ldap_getfirstfilter()
and ldap_getnextfilter()
functions. (See "Retrieving Filters"
for details.) For example, suppose you use this filter in a filter
configuration file:
(cn=Babs Jensen)
If you retrieve this filter through the
ldap_getfirstfilter()
or
ldap_getnextfilter()
function, you get the following
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 section of code loads the filter configuration file
named myfilters.conf
into memory and adds the prefix
(&(objectClass=person)
and the suffix
")
" to each filter retrieved:
Code Example 7-2 - Adding prefixes and suffixes
... 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
When you complete your search, you should free the
LDAPFiltDesc
structure
from memory. To free the LDAPFiltDesc
structure, call
the ldap_getfilter_free()
function.
The following section of code frees the LDAPFiltDesc
structure from memory after all searches are completed.
Code Example 7-3 - Freeing filters from memory
... 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
You can build your own filters by calling the
ldap_create_filter()
function.
The following section of code builds the filter
(mail=bjensen@example.com)
.
Code Example 7-4 - Creating filters
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 ); ...