Mozilla LDAP SDK Programmer's Guide/Comparing Attribute Values With LDAP C SDK

From MozillaWiki
Jump to: navigation, search

This section describes how to compare the value of an attribute in an entry against a specified value.

Functions for Comparing Attribute Values With LDAP C SDK

LDAP C SDK has functions to determine if an attribute contains a certain string or binary value.

  • The synchronous ldap_compare_s() function
  • The asynchronous ldap_compare() function
  • The synchronous ldap_compare_ext_s() function
  • The asynchronous ldap_compare_ext() function

Performing Synchronous Comparison Operations With LDAP C SDK

You can wait for the results of the compare operation to complete before continuing. Call the synchronous ldap_compare_ext_s() function to compare values in berval structures or the synchronous ldap_compare_s() 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.

  • LDAP_COMPARE_TRUE indicates that the attribute contains the specified value.
  • LDAP_COMPARE_FALSE indicates that the attribute does not contain the specified value.

An error code indicates that a problem has occurred during the operation.

The following example calls the synchronous ldap_compare_s() function to determine if an entry has the value bjensen@example.com in the mail attribute.

#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 );
...

The following sample program calls the synchronous ldap_compare_s() function. The sample program uses this function to determine if a user entry has the value bjensen@example.com in the mail attribute.

#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;
}

Performing Asynchronous Comparison Operations With LDAP C SDK

You can perform other work in parallel while waiting for the comparison to complete. Call the asynchronous ldap_compare_ext() function to compare values in berval structures or the asynchronous ldap_compare function to compare string values. These functions send a compare request to the server and return an LDAP_SUCCESS result code if the request was successfully sent, or an LDAP result code if an error occurred.

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 ldap_result() function and pass in the message ID. The ldap_result() function uses the message ID to determine if the server sent the results of the compare operation. The ldap_result() function passes back the results in an LDAPMessage structure. You can call the ldap_parse_result() function to parse the LDAPMessage structure to determine if the operation was successful.

  • LDAP_COMPARE_TRUE indicates that the attribute contains the specified value.
  • LDAP_COMPARE_FALSE indicates that the attribute does not contain the specified value.

An error code indicates that a problem occurred during the operation.

The following example calls the asynchronous ldap_compare() function to determine if an entry has the value bjensen@example.com in the mail attribute.

#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;
    }
  }
}
...

The following sample program calls the asynchronous ldap_compare() function. The sample program uses this function to determine if a user entry has the value bjensen@example.com in the mail attribute.

#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++;
}