439 lines
16 KiB
Plaintext
439 lines
16 KiB
Plaintext
<!--
|
|
|
|
Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
|
|
Portions copyright 1999 Netscape Communications Corporation. All
|
|
Rights Reserved.
|
|
|
|
The contents of this document are subject to the terms of the
|
|
Creative Commons Attribution-ShareAlike 2.5 license or any later
|
|
version (the "License"). You may not use this document except in
|
|
compliance with the License.
|
|
|
|
See the License for the specific language governing
|
|
permissions and limitations under the License. You can obtain
|
|
a copy of the License at
|
|
http://creativecommons.org/licenses/by-sa/2.5/legalcode.
|
|
|
|
-->
|
|
<chapter id="csdk-compare"><title>Comparing Attribute Values
|
|
With &DirectorySDKForC;</title>
|
|
<indexterm>
|
|
<primary>C SDK</primary>
|
|
<secondary>comparing attribute values</secondary>
|
|
</indexterm><highlights>
|
|
<para>This chapter describes how to compare the value of an attribute in an
|
|
entry against a specified value.</para>
|
|
<itemizedlist>
|
|
<para>This chapter covers the following topics:</para>
|
|
<listitem><para><olink targetptr="bdahc">Functions for Comparing Attribute
|
|
Values With Directory SDK for C</olink></para></listitem>
|
|
<listitem><para><olink targetptr="bdahd">Performing Synchronous Comparison
|
|
Operations With Directory SDK for C</olink></para></listitem>
|
|
<listitem><para><olink targetptr="bdahe">Performing Asynchronous Comparison
|
|
Operations With Directory SDK for C</olink></para></listitem>
|
|
</itemizedlist>
|
|
</highlights>
|
|
<sect1 id="bdahc"><title>Functions for Comparing Attribute Values With Directory
|
|
SDK for C</title>
|
|
<para>&DirectorySDKForC; has functions to determine if an attribute contains
|
|
a certain string or binary value.</para>
|
|
<itemizedlist>
|
|
<para>To determine if an attribute contains a certain <emphasis>string</emphasis> value,
|
|
call either of the following functions:</para>
|
|
<listitem><para>The synchronous <function>ldap_compare_s</function> function</para>
|
|
</listitem>
|
|
<listitem><para>The asynchronous <function>ldap_compare</function> function</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<itemizedlist>
|
|
<para>To determine if an attribute contains a certain <emphasis>binary</emphasis> value,
|
|
call either of the following functions:</para>
|
|
<listitem><para>The synchronous <function>ldap_compare_ext_s</function> function</para>
|
|
</listitem>
|
|
<listitem><para>The asynchronous <function>ldap_compare_ext</function> function</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</sect1>
|
|
<sect1 id="bdahd"><title>Performing Synchronous Comparison Operations With
|
|
Directory SDK for C</title>
|
|
<indexterm>
|
|
<primary>synchronous functions</primary>
|
|
<secondary>comparison operation</secondary>
|
|
</indexterm>
|
|
<para>You can wait for the results of the compare operation to complete before
|
|
continuing. Call the synchronous <function>ldap_compare_ext_s</function> function
|
|
to compare values in <structname>berval</structname> structures or the synchronous <function>
|
|
ldap_compare_s</function> function to compare string values. These functions
|
|
send a compare request to the server and block work until the server sends
|
|
the results of the operation back to your client.</para>
|
|
<itemizedlist>
|
|
<para>Both functions return one of the following values after the compare
|
|
operation completes:</para>
|
|
<listitem><para><errorcode>LDAP_COMPARE_TRUE</errorcode> indicates that the
|
|
attribute contains the specified value.</para></listitem>
|
|
<listitem><para><errorcode>LDAP_COMPARE_FALSE</errorcode> indicates that the
|
|
attribute does not contain the specified value.</para></listitem>
|
|
</itemizedlist>
|
|
<para>An error code indicates that a problem has occurred during the operation.</para>
|
|
<para>The following example calls the synchronous <function>ldap_compare_s</function> function
|
|
to determine if an entry has the value <literal>bjensen@example.com</literal> in
|
|
the <literal>mail</literal> attribute.</para>
|
|
<example id="compare-sync-example"><title>Performing a Synchronous Compare
|
|
Operation</title>
|
|
<programlisting>#include <stdio.h>
|
|
#include "ldap.h"
|
|
...
|
|
#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com"
|
|
#define COMPARE_ATTR "mail"
|
|
#define COMPARE_VALUE "bjensen@example.com"
|
|
...
|
|
LDAP *ld;
|
|
char *matched_msg = NULL, *error_msg = NULL;
|
|
int rc;
|
|
...
|
|
/* Perform the compare operation. */
|
|
rc = ldap_compare_s( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE );
|
|
switch( rc ) {
|
|
case LDAP_COMPARE_TRUE:
|
|
printf( "%s has the value %s in the %s attribute.\n", COMPARE_DN,
|
|
COMPARE_VALUE, COMPARE_ATTR );
|
|
break;
|
|
case LDAP_COMPARE_FALSE:
|
|
printf( "%s does not have the value %s in the %s attribute.\n",
|
|
COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR );
|
|
break;
|
|
default:
|
|
fprintf( stderr, "ldap_compare_s: %s\n", ldap_err2string( rc ) );
|
|
ldap_get_lderrno( ld, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *matched_msg != '\0' ) {
|
|
fprintf( stderr,
|
|
"Part of the DN that matches an existing entry: %s\n",
|
|
matched_msg );
|
|
}
|
|
break;
|
|
}
|
|
ldap_unbind_s( ld );
|
|
...</programlisting>
|
|
</example>
|
|
<para>The following sample program calls the synchronous <function>ldap_compare_s
|
|
</function> function. The sample program uses this function to determine if
|
|
a user entry has the value <literal>bjensen@example.com</literal> in the <literal>
|
|
mail</literal> attribute.</para>
|
|
<example id="compare-sync-full-example"><title>Sample Synchronous Compare
|
|
Program</title>
|
|
<programlisting>#include <stdio.h>
|
|
#include "ldap.h"
|
|
|
|
/* Change these as needed. */
|
|
#define HOSTNAME "localhost"
|
|
#define PORTNUMBER LDAP_PORT
|
|
#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com"
|
|
#define COMPARE_ATTR "mail"
|
|
#define COMPARE_VALUE "bjensen@example.com"
|
|
int
|
|
main( int argc, char **argv )
|
|
{
|
|
LDAP *ld;
|
|
char *matched_msg = NULL, *error_msg = NULL;
|
|
int rc;
|
|
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
|
|
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
|
|
perror( "ldap_init" );
|
|
return( 1 );
|
|
}
|
|
/* Bind anonymously to the server. */
|
|
rc = ldap_simple_bind_s( ld, NULL, NULL );
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
|
|
ldap_get_lderrno( ld, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *matched_msg != '\0' ) {
|
|
fprintf( stderr,
|
|
"Part of the DN that matches an existing entry: %s\n",
|
|
matched_msg );
|
|
}
|
|
ldap_unbind_s( ld );
|
|
return( 1 );
|
|
}
|
|
/* Perform the compare operation. */
|
|
rc = ldap_compare_s( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE );
|
|
switch( rc ) {
|
|
case LDAP_COMPARE_TRUE:
|
|
printf( "%s has the value %s in the %s attribute.\n",
|
|
COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR );
|
|
break;
|
|
case LDAP_COMPARE_FALSE:
|
|
printf( "%s does not have the value %s in the %s attribute.\n",
|
|
COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR );
|
|
break;
|
|
default:
|
|
fprintf( stderr, "ldap_compare_s: %s\n", ldap_err2string( rc ) );
|
|
ldap_get_lderrno( ld, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *matched_msg != '\0' ) {
|
|
fprintf( stderr,
|
|
"Part of the DN that matches an existing entry: %s\n",
|
|
matched_msg );
|
|
}
|
|
break;
|
|
}
|
|
ldap_unbind_s( ld );
|
|
return 0;
|
|
}</programlisting>
|
|
</example>
|
|
</sect1>
|
|
<sect1 id="bdahe"><title>Performing Asynchronous Comparison Operations With
|
|
Directory SDK for C</title>
|
|
<indexterm>
|
|
<primary>asynchronous functions</primary>
|
|
<secondary>comparison operation</secondary>
|
|
</indexterm>
|
|
<para>You can perform other work in parallel while waiting for the comparison
|
|
to complete. Call the asynchronous <function>ldap_compare_ext</function> function
|
|
to compare values in <structname>berval</structname> structures or the asynchronous <function>
|
|
ldap_compare</function> function to compare string values. These functions
|
|
send a compare request to the server and return an <errorcode>LDAP_SUCCESS</errorcode> result
|
|
code if the request was successfully sent, or an LDAP result code if an error
|
|
occurred.</para>
|
|
<para>Both functions pass back a message ID identifying the compare operation.
|
|
To determine whether the server sent a response for this operation to your
|
|
client, call the <function>ldap_result</function> function and pass in the
|
|
message ID. The <function>ldap_result</function> function uses the message
|
|
ID to determine if the server sent the results of the compare operation. The <function>
|
|
ldap_result</function> function passes back the results in an <structname>LDAPMessage
|
|
</structname> structure. You can call the <function>ldap_parse_result</function> function
|
|
to parse the <structname>LDAPMessage</structname> structure to determine if
|
|
the operation was successful.</para>
|
|
<itemizedlist>
|
|
<para>The result code should be one of the following:</para>
|
|
<listitem><para><errorcode>LDAP_COMPARE_TRUE</errorcode> indicates that the
|
|
attribute contains the specified value.</para></listitem>
|
|
<listitem><para><errorcode>LDAP_COMPARE_FALSE</errorcode> indicates that the
|
|
attribute does not contain the specified value.</para></listitem>
|
|
</itemizedlist>
|
|
<para>An error code indicates that a problem occurred during the operation.</para>
|
|
<para>The following example calls the asynchronous <function>ldap_compare</function> function
|
|
to determine if an entry has the value <literal>bjensen@example.com</literal> in
|
|
the <literal>mail</literal> attribute.</para>
|
|
<example id="compare-async-example"><title>Performing an Asynchronous Compare
|
|
Operation</title>
|
|
<programlisting>#include <stdio.h>
|
|
#include "ldap.h"
|
|
...
|
|
#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com"
|
|
#define COMPARE_ATTR "mail"
|
|
#define COMPARE_VALUE "bjensen@example.com"
|
|
...
|
|
LDAP *ld;
|
|
LDAPMessage *res;
|
|
LDAPControl **serverctrls;
|
|
char *matched_msg = NULL, *error_msg = NULL;
|
|
char **referrals;
|
|
int rc, parse_rc, msgid, finished = 0;
|
|
struct timeval zerotime;
|
|
zerotime.tv_sec = zerotime.tv_usec = 0L;
|
|
...
|
|
/* Send the LDAP compare request. */
|
|
msgid = ldap_compare( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE );
|
|
if ( msgid < 0 ) {
|
|
fprintf( stderr, "ldap_compare: %s\n", ldap_err2string( rc ) );
|
|
ldap_unbind( ld );
|
|
return( 1 );
|
|
}
|
|
/* Poll the server for the results of the LDAP compare operation. */
|
|
while ( !finished ) {
|
|
rc = ldap_result( ld, msgid, 0, &zerotime, &res );
|
|
switch ( rc ) {
|
|
|
|
case -1:
|
|
/* An error occurred. */
|
|
rc = ldap_get_lderrno( ld, NULL, NULL );
|
|
fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
|
|
ldap_unbind( ld );
|
|
return( 1 );
|
|
|
|
case 0:
|
|
/* The timeout period specified by zerotime was exceeded, so
|
|
call ldap_result() again and continue to poll for the
|
|
results. */
|
|
break;
|
|
|
|
default:
|
|
/* The client has received the results of the
|
|
LDAP compare operation from the server. */
|
|
finished = 1;
|
|
|
|
/* Parse the results received from the server.*/
|
|
parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg,
|
|
&error_msg, &referrals, &serverctrls, 1 );
|
|
if ( parse_rc != LDAP_SUCCESS ) {
|
|
fprintf( stderr, "ldap_parse_result: %s\n",
|
|
ldap_err2string( parse_rc ) );
|
|
ldap_unbind( ld );
|
|
return( 1 );
|
|
}
|
|
|
|
/* Check the results of the LDAP compare operation. */
|
|
switch ( rc ) {
|
|
case LDAP_COMPARE_TRUE:
|
|
printf( "%s has the value %s in the %s attribute.\n",
|
|
COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR );
|
|
break;
|
|
case LDAP_COMPARE_FALSE:
|
|
printf( "%s does not have the value %s in the %s attribute.\n",
|
|
COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR );
|
|
break;
|
|
default:
|
|
fprintf( stderr, "ldap_compare: %s\n", ldap_err2string( rc ) );
|
|
if ( error_msg != NULL & *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *matched_msg != '\0' ) {
|
|
fprintf( stderr,
|
|
"Part of the DN that matches an existing entry: %s\n",
|
|
matched_msg );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
...</programlisting>
|
|
</example>
|
|
<para>The following sample program calls the asynchronous <function>ldap_compare</function> function.
|
|
The sample program uses this function to determine if a user entry has the
|
|
value <literal>bjensen@example.com</literal> in the <literal>mail</literal> attribute.
|
|
</para>
|
|
<example id="compare-async-full-example"><title>Sample Asynchronous Compare
|
|
Program</title>
|
|
<programlisting>#include <stdio.h>
|
|
#include "ldap.h"
|
|
void do_other_work();
|
|
int global_counter = 0;
|
|
/* Change these as needed. */
|
|
#define HOSTNAME "localhost"
|
|
#define PORTNUMBER LDAP_PORT
|
|
#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com"
|
|
#define COMPARE_ATTR "mail"
|
|
#define COMPARE_VALUE "bjensen@example.com"
|
|
int
|
|
main( int argc, char **argv )
|
|
{
|
|
LDAP *ld;
|
|
LDAPMessage *res;
|
|
LDAPControl **serverctrls;
|
|
char *matched_msg = NULL, *error_msg = NULL;
|
|
char **referrals;
|
|
int rc, parse_rc, msgid, finished = 0;
|
|
struct timeval zerotime;
|
|
zerotime.tv_sec = zerotime.tv_usec = 0L;
|
|
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
|
|
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
|
|
perror( "ldap_init" );
|
|
return( 1 );
|
|
}
|
|
/* Bind anonymously to the server. */
|
|
rc = ldap_simple_bind_s( ld, NULL, NULL );
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
|
|
ldap_get_lderrno( ld, NULL, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
ldap_unbind_s( ld );
|
|
return( 1 );
|
|
}
|
|
/* Send the LDAP compare request. */
|
|
msgid = ldap_compare( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE );
|
|
if ( msgid < 0 ) {
|
|
fprintf( stderr, "ldap_compare: %s\n", ldap_err2string( rc ) );
|
|
ldap_unbind( ld );
|
|
return( 1 );
|
|
}
|
|
/* Poll the server for the results of the LDAP compare operation. */
|
|
while ( !finished ) {
|
|
rc = ldap_result( ld, msgid, 0, &zerotime, &res );
|
|
switch ( rc ) {
|
|
case -1:
|
|
/* An error occurred. */
|
|
rc = ldap_get_lderrno( ld, NULL, NULL );
|
|
fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
|
|
ldap_unbind( ld );
|
|
return( 1 );
|
|
case 0:
|
|
/* The timeout period specified by zerotime was exceeded.
|
|
This means that your client has not yet received the
|
|
results of the LDAP compare operation.
|
|
Break out of this switch statement, and continue calling
|
|
ldap_result() to poll for the results. */
|
|
break;
|
|
default:
|
|
/* The client has received the results of the
|
|
LDAP compare operation from the server. */
|
|
finished = 1;
|
|
/* Parse the results received from the server. Note the last
|
|
argument is a non-zero value, which indicates that the
|
|
LDAPMessage structure will be freed when done. (No need
|
|
to call ldap_msgfree().) */
|
|
parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg,
|
|
&error_msg, &referrals, &serverctrls, 1 );
|
|
if ( parse_rc != LDAP_SUCCESS ) {
|
|
fprintf( stderr,
|
|
"ldap_parse_result: %s\n",
|
|
ldap_err2string( parse_rc ) );
|
|
ldap_unbind( ld );
|
|
return( 1 );
|
|
}
|
|
/* Check the results of the LDAP compare operation. */
|
|
switch ( rc ) {
|
|
case LDAP_COMPARE_TRUE:
|
|
printf( "%s has the value %s in the %s attribute.\n"
|
|
"Counted to %d while waiting for the compare operation.\n",
|
|
COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR, global_counter );
|
|
break;
|
|
case LDAP_COMPARE_FALSE:
|
|
printf( "%s does not have the value %s in the %s attribute.\n"
|
|
"Counted to %d while waiting for the compare operation.\n",
|
|
COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR, global_counter );
|
|
break;
|
|
default:
|
|
fprintf( stderr, "ldap_compare: %s\n", ldap_err2string( rc ) );
|
|
if ( error_msg != NULL & *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *matched_msg != '\0' ) {
|
|
fprintf( stderr,
|
|
"Part of the DN that matches an existing entry: %s\n",
|
|
matched_msg );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
/* Do other work while waiting for the results of the
|
|
compare operation. */
|
|
if ( !finished ) {
|
|
do_other_work();
|
|
}
|
|
}
|
|
ldap_unbind( ld );
|
|
return 0;
|
|
}
|
|
/*
|
|
* Perform other work while polling for results. This
|
|
* doesn't do anything useful, but it could.
|
|
*/
|
|
void
|
|
do_other_work()
|
|
{
|
|
global_counter++;
|
|
}</programlisting>
|
|
</example>
|
|
</sect1>
|
|
</chapter>
|