# LDAP URLs With &DirectorySDKForC;

This chapter describes how to use LDAP URLs to search and retrieve data from the directory.

This chapter covers the following topics:

- Checking an LDAP URL With Directory SDK for C

- Getting the Components of an LDAP URL With Directory SDK for C

- Freeing the Components of an LDAP URL With Directory SDK for C

- Processing an LDAP URL With Directory SDK for C

## Checking an LDAP URL With &DirectorySDKForC;

To determine whether a URL is an LDAP URL, call the `ldap_is_ldap_url` function. This function returns a nonzero value if the URL is an LDAP URL. If the URL is not an LDAP URL, the function returns `0`. The following example determines if a URL is an LDAP URL.

### Determining Whether a URL Is an LDAP URL

    #include <stdio.h>
    #include "ldap.h"
    ...
    char *my_url = "ldap://ldap.example.com/dc=example,dc=com";
    ...
    if ( ldap_is_ldap_url( my_url ) != 0 ) {
      printf( "%s is an LDAP URL.\n", my_url );
    } else {
      printf( "%s is not an LDAP URL.\n", my_url );
    }
    ...

`ldap_is_ldap_url` determines whether a URL is an LDAP URL. To verify that an LDAP URL complies with the LDAP URL syntax, you should call the `ldap_url_parse` function as detailed in Getting the Components of an LDAP URL With Directory SDK for C.

## Getting the Components of an LDAP URL With &DirectorySDKForC;

To retrieve the individual components of an LDAP URL, call `ldap_url_parse` . This function returns the LDAP URL components in an LDAPURLDesc structure as shown in this example.

### LDAPURLDesc Structure

    typedef struct ldap_url_desc {
      char *lud_host;
      int lud_port;
      char *lud_dn;
      char **lud_attrs;
      int lud_scope;
      char *lud_filter;
      unsigned long lud_options;
    } LDAPURLDesc;

The following table describes the structure's fields.

## LDAPURLDesc Field Descriptions

Field Name | Description
lud_host | The name of the host in the URL.
lud_port | The number of the port in the URL.
lud_dn | The distinguished name in the URL.
lud_attrs | A pointer to a `NULL` terminated array of the attributes specified in the URL.
lud_scope | The scope of the search specified in the URL. This field can have the following values: `LDAP_SCOPE_BASE` specifies a search of the base entry. `LDAP_SCOPE_ONELEVEL` specifies a search of all entries one level under the base entry, not including the base entry. `LDAP_SCOPE_SUBTREE` specifies a search of all entries at all levels under the base entry, including the base entry.
lud_filter | Search filter included in the URL.
lud_options | Options. If `LDAP_URL_OPT_SECURE`, indicates that the protocol is `ldaps://` instead of `ldap://`.

The following example parses an LDAP URL.

### Parsing an LDAP URL

    #include <stdio.h>
    #include "ldap.h"
    ...
    char *my_url =
      "ldap://ldap.example.com:1389/dc=example,dc=com?
       cn,mail,telephoneNumber?sub?(sn=Jensen)";
    LDAPURLDesc *ludpp;
    int res, i;
    ...
    if ( ( res = ldap_url_parse( my_url, &ludpp ) ) != 0 ) {
      switch( res ){
        case LDAP_URL_ERR_NOTLDAP:
          printf( "URL does not begin with \"ldap://\"\n" );
          break;
        case LDAP_URL_ERR_NODN:
          printf( "URL missing trailing slash after host or port\n" );
          break;
        case LDAP_URL_ERR_BADSCOPE:
          printf( "URL contains an invalid scope\n" );
          break;
        case LDAP_URL_ERR_MEM:
          printf( "Not enough memory\n" );
          break;
        default:
          printf( "Unknown error\n" );
      }
      return( 1 );
    }
    printf( "Components of the URL:\n" );
    printf( "Host name: %s\n", ludpp->lud_host );
    printf( "Port number: %d\n", ludpp->lud_port );
    if ( ludpp->lud_dn != NULL ) {
      printf( "Base entry: %s\n", ludpp->lud_dn );
    } else {
      printf( "Base entry: Root DN\n" );
    }
    if ( ludpp->lud_attrs != NULL ) {
      printf( "Attributes returned: \n" );
      for ( i=0; ludpp->lud_attrs[i] != NULL; i++ ) {
        printf( "\t%s\n", ludpp->lud_attrs[i] );
      }
    } else {
      printf( "No attributes returned.\n" );
    }
    printf( "Scope of the search: " );
    switch( ludpp->lud_scope ) {
      case LDAP_SCOPE_BASE:
        printf( "base\n" );
        break;
      case LDAP_SCOPE_ONELEVEL:
        printf( "one\n" );
        break;
      case LDAP_SCOPE_SUBTREE:
        printf( "sub\n" );
        break;
      default:
        printf( "Unknown scope\n" );
    }
    printf( "Filter: %s\n", ludpp->lud_filter );
    ...

The code in Example 13–3 prints each component of the URL as shown in the following example.

### Results of Parsing an LDAP URL

    Components of the URL:
    Host name: ldap.example.com
    Port number: 1389
    Base entry: dc=example,dc=com
    Attributes returned:
      cn
      mail
      telephoneNumber
    Scope of the search: sub
    Filter: (sn=Jensen)

## Freeing the Components of an LDAP URL With &DirectorySDKForC;

When you have finished working with the components of an LDAP URL, you should free the LDAPURLDesc structure from memory by calling the `ldap_free_urldesc` function. The following example parses an LDAP URL. The example then frees the LDAPURLDesc structure from memory, after verifying that the LDAP URL is valid.

### Freeing the LDAPURLDesc Structure From Memory

    #include <stdio.h>
    #include "ldap.h"
    ...
    char *my_url = "ldap://ldap.example.com:1389/dc=example,dc=com?cn,mail,
                    telephoneNumber?sub?(sn=Jensen)";
    LDAPURLDesc *ludpp;
    int res, i;
    ...
    if ( ( res = ldap_url_parse( my_url, &ludpp ) ) != 0 ) {
      switch( res ){
        case LDAP_URL_ERR_NOTLDAP:
          printf( "URL does not begin with \"ldap://\"\n" );
          break;
        case LDAP_URL_ERR_NODN:
          printf( "URL does not contain a distinguished name\n" );
          break;
        case LDAP_URL_ERR_BADSCOPE:
          printf( "URL contains an invalid scope\n" );
          break;
        case LDAP_URL_ERR_MEM:
          printf( "Not enough memory\n" );
          break;
        default:
          printf( "Unknown error\n" );
      }
      return( 1 );
    }
    printf( "URL is a valid LDAP URL\n" );
    ldap_free_urldesc( ludpp );
    ...

## Processing an LDAP URL With &DirectorySDKForC;

To process an LDAP URL search request, call one of the following functions:

- `ldap_url_search_s` is a synchronous function that completes the search operation before returning. Call this function if you need to wait for the operation to finish before continuing other work. The function returns LDAP_SUCCESS if the operation completed successfully. If an error occurred, the function returns an error code.

- `ldap_url_search_st` is a synchronous function that allows a certain amount of time for the completion of the search operation. Call this function to wait for the operation to complete, and to set a timeout period for the operation.

- `ldap_url_search` is an asynchronous function that initiates the search operation but does not wait for the operation to complete. Call this function if you want to perform other work in parallel while waiting for the operation to complete. The function returns a message ID identifying the search operation. To determine whether the operation is completed or still in progress, call the `ldap_result` function.

  After the operation is completed, call the `ldap_result2error` function to determine if the operation was successful. If the operation completed successfully, the `ldap_result2error` function returns LDAP_SUCCESS. If an error occurred, the function returns an error code.

The following example processes a search request from an LDAP URL.

### Processing an LDAP URL Search Request

    #include <stdio.h>
    #include "ldap.h"
    ...
    LDAP *ld;
    LDAPMessage *result;
    char *my_url = "ldap://ldap.example.com/dc=example,dc=com?cn,mail,
                    telephoneNumber?sub?(sn=Jensen)";
    /* Process the search request in the URL. */
    if ( ldap_url_search_s( ld, my_url, 0, &result ) != LDAP_SUCCESS ) {
      ldap_perror( ld, "ldap_url_search_s" );
      return( 1 );
    }