5.5. Working with Entries, Attributes, and Values

In certain situations, you will need to pass directory entries between the frontend and the client. For example, it you create a custom add function, the frontend passes an entry to your function in the parameter block. When you perform a search operation, you return each matching search entry to the client.
When working with entries, use the Section 14.22, “Slapi_Entry” data type to get attribute value pairs. The frontend routines listed in Table 5.1, “Frontend Functions for Manipulating Entries and Attributes” are designed to help you manipulate entries passed in parameter blocks. These functions are described in more detail in the following sections.

Table 5.1. Frontend Functions for Manipulating Entries and Attributes

Frontend Function Description
Allocate memory for a new entry.
Initialize the entry created with slapi_entry_alloc().

Important

This must be done before any other operation can occur on the entry. Otherwise, severe memory errors may occur.
Copy an entry.
Free an unused entry from memory.
Convert an entry to an LDIF string representation and vice versa.
Get or set the DN for an entry.
Verify that an entry complies with the schema.
Get the attributes of an entry.
Find the values for a specified attribute.
Merge an attribute and its values into an entry.
Add values to an attribute in an entry.

5.5.1. Creating a New Entry

In some situations, you might need to create a new entry. You can create a new entry in two ways:
  • By allocating memory for a new entry.
    To allocate memory for a new entry, call the slapi_entry_alloc() function. This function returns a pointer to a new entry of the opaque datatype Section 14.22, “Slapi_Entry”. Then, call the function slapi_entry_init() to initialize the entry for use with the other slapi functions. Once you create and initialize a new entry, you should call other frontend routines to set the DN and attributes of the entry.

    Note

    Failing to call slapi_entry_init() after slapi_entry_alloc() may cause severe memory problems.
  • By copying an existing entry.
    To make a copy of an existing entry, call the slapi_entry_dup() routine. This function returns a pointer to a new entry of the data type Slapi_Entry that contains the copied data.
When you are finished using the entry, you should free it from memory by calling the slapi_entry_free() function.

5.5.2. Converting Between Entries and Strings

Entries can be stored in LDIF files. When stored in these files, entries are converted into a string representation. The following format is the LDIF string representation for a directory entry:
dn:[:]dn\n
[<attr>:[:]<value>\n]
[<attr>:[:]<value>\n]
[<spacecontinuedvalue>\n]*
...
To continue the specification of a value on additional lines (that is, if the value wraps to another line), use a single space (the ASCII 32 character) at the beginning of subsequent lines. For example:
dn: cn=Jane Doe
 inski, ou=Accoun
 ting, dc=ex
 ample
 dc=com
Refer to the Red Hat Directory Server Administration Guide for details on DN syntax.
If a double-colon is used after a data type, it indicates that the value after the double-colon is encoded as a base-64 string. Data is sometimes encoded as a base-64 string. For example, it might be encoded this way if the value contains a non-printing character or newline.
You can use the following functions to convert between the LDIF string representation of an entry and its Slapi_Entry data type:
  • To convert an entry from the Slapi_Entry data type to its LDIF string representation, call the slapi_entry2str() and slapi_entry2str_with_options() functions.
    This function returns the LDIF string representation of the entry, or NULL if an error occurs. When the string is no longer required, free it from memory by calling the slapi_ch_free_string()* function.
  • To convert an LDIF string representation back to an entry of the data type Slapi_Entry, call the slapi_str2entry() function.
    This function returns an entry of the data type Slapi_Entry*. If an error occurred during the conversion process, the function returns NULL instead.
When you are finished working with the entry, call the slapi_entry_free() function.

Note

Calling the slapi_str2entry() function modifies the value of the string argument passed into the function (not a copy). To use the string representation of the entry still, make a copy of the string using slapi_ch_strdup() before calling this function. Then, call slapi_ch_free_string() to free the copied string after use.

5.5.3. Miscellaneous Operations

5.5.3.1. Getting and Setting the DN of an Entry

You can call the following two frontend routines to get and set the DN for an entry:

5.5.3.2. Verifying Compliance with the Schema

Before you add or modify an entry in the database, you may want to verify that the new or changed entry still complies with the database schema.
To verify that an entry complies with the schema, call the slapi_entry_schema_check() function.

5.5.3.3. Getting the Attributes and Values of an Entry

You can use either of the following methods to obtain the attributes and values of an entry:
  • Iterate through the attributes of the entry, testing each one to determine if it is the required attribute.
  • Use the slapi_entry_attr_find() function to determine if an entry has a specific attribute.
After you have found the required attribute, use the slapi_attr_value_find() function to return the value of that attribute, or use slapi_attr_value_first() and slapi_attr_value_next() to iterate through all of the values of a multi-valued attribute.
5.5.3.3.1.  Iterating through the Attributes in an Entry
To iterate through the attributes associated with an entry, call the slapi_entry_first_attr() function to get the first attribute of the entry. This function returns a pointer to the first attribute in the entry. You can use the pointer to the attribute to determine if it is the attribute that you want.
To retrieve the subsequent parameters in the entry, call slapi_entry_next_attr(), and pass it the pointer to the current parameter in the cookie parameter of the function. The slapi_entry_next_attr() function returns a pointer to the current parameter in the same fashion as the slapi_entry_first_attr() function.
After finding the required attribute, it is possible to retrieve its value using slapi_attr_value_find() or using slapi_attr_value_first() and slapi_attr_value_next() to iterate through all of the values of a multi-valued attribute.
5.5.3.3.2.  Finding a Specific Attribute in an Entry
To determine if an entry contains a specific attribute, call the slapi_entry_attr_find() function. This function returns 0 if the entry contains the attribute, -1 if it does not.

5.5.3.4. Adding and Removing Values

You can call frontend routines to add or remove attributes and values in an entry. The frontend provides the following functionality:
There are many convenience functions provided to get and set values of attributes in an entry, beginning with slapi_entry_attr_get* and slapi_entry_attr_set*, respectively. These functions allow you to get and set specific values in a Slapi_Entry. Because they are convenience functions, there are some limitations about their use.

Example 5.1. Get Functions

char **slapi_entry_attr_get_charray(const Slapi_Entry* e, const char *type);
char *slapi_entry_attr_get_charptr(const Slapi_Entry* e, const char *type);
int slapi_entry_attr_get_int(const Slapi_Entry* e, const char *type);
unsigned int slapi_entry_attr_get_uint(const Slapi_Entry* e, const char *type);
long slapi_entry_attr_get_long( const Slapi_Entry* e, const char *type);
unsigned long slapi_entry_attr_get_ulong( const Slapi_Entry* e, const char *type);
long long slapi_entry_attr_get_longlong( const Slapi_Entry* e, const char *type);
unsigned long long slapi_entry_attr_get_ulonglong( const Slapi_Entry* e, const char *type);
PRBool slapi_entry_attr_get_bool( const Slapi_Entry* e, const char *type);
The type parameter is the name of the attribute.
If the attribute does not exist in the entry, the get function return a 0 or NULL value. Some attributes may actually exist and have a 0 value, so to verify that an attribute exists before getting the value, use slapi_entry_attr_find() first.
These functions return only the first value of an attribute. For multi-valued attributes, use a function to get the Slapi_Attr*, then iterate through the values using the slapi_attr_first_value() and slapi_attr_next_value() functions.
Values are usually stored as strings. The functions that return integral values (such as get_int and get_uint) use atoi(3) to get the int values, atol(3) to get the long values, and strtoll(3) to get the longlong values. Check the platform documentation for these functions for information about how these functions deal with non-integral values. They usually return a 0 if the value could not be converted to the specified type. To continue these functions, ensure the value is of the correct type.
slapi_entry_attr_get_charray() returns either NULL or allocated memory that must be freed with slapi_ch_array_free(). The last element of the array is (char *)NULL, so you can iterate through the values looking for this as the termnator. slapi_entry_attr_get_charptr() returns either NULL or allocated memory that must be freed with slapi_ch_free_string().
slapi_entry_attr_get_bool() returns a PR_TRUE if the value is present and is equivalent to true, yes, or a non-zero numeric value. It returns PR_FALSE if the value is absent, empty, or any of the values false, no, or a numeric 0 value. String comparisons are case-insensitive, so TRUE is the same as True or true.

Example 5.2. Set Functions

void slapi_entry_attr_set_charptr(Slapi_Entry* e, const char *type, const char *value);
void slapi_entry_attr_set_int( Slapi_Entry* e, const char *type, int l);
void slapi_entry_attr_set_uint( Slapi_Entry* e, const char *type, unsigned int l);
void slapi_entry_attr_set_long(Slapi_Entry* e, const char *type, long l);
void slapi_entry_attr_set_ulong(Slapi_Entry* e, const char *type, unsigned long l);
The type parameter is the name of the attribute. If the attribute does not exist in the entry, the set function creates it and sets the value. If the attribute exists in the entry, the set function will replace all values with the new specified value. To add values without replacing, use slapi_entry_add_values_sv().
slapi_entry_attr_set_charptr() makes a copy of the specified value, so this function is ok to use with a string constant or other non-writable string value. Passing a value of NULL deletes the specified attribute from the entry, just like calling slapi_entry_attr_delete(Slapi_Entry *, const char *type).
There is no slapi_entry_attr_set_charray() nor slapi_entry_attr_set_bool() function. For the former function, use a Slapi_Attr* or Slapi_Value* API function to add the multiple values. For the latter, use slapi_entry_attr_set_charptr() or slapi_entry_attr_set_int() to set the value to the true or false value.