Accessing and Modifying Information in the NDS Database
Articles and Tips: article
Software Engineer
Novell Consulting Services
01 Oct 1997
- Introduction
- Novell Directory Services Read Operation
- Novell Directory Services List Operation
- Novell Directory Services Compare Operation
- Novell Directory Services Add Object Operation
- Novell Directory Services Modify Object Operation
- Novell Directory Services Remove Object Operation
- Novell Directory Services Modify RDN (Rename) Operation
- Novell Directory Services Search Operation
Introduction
This article is the second in a series of articles on NDS development. The first article, "Getting Started with NDS Development" appeared in the September 1997 issue of Novell Developer Notes.
Novell Directory Services is a database of object names and corresponding attribute values. The API interface for accessing and modifying these objects is very similar to the Directory Access Protocol (DAP) defined by x.500. This interface allows the developer to perform any of the standard database operations such as read, list, search, compare and modify. The following table illustrates the mapping between the x.500 DAP function definition and the NDS implementation. Click on the Novell NDS API function name to obtain specific information and sample code for each.
x.500 DAP
|
NDS Function
|
Read |
NWDSRead() |
Compare |
NWDSCompare() |
List |
NWDSList() |
Search |
NWDSSearch() |
AddEntry |
NWDSAddObject() |
RemoveEntry |
NWDSRemoveObject() |
ModifyEntry |
NWDSModifyObject() |
ModifyRDN |
NWDSModifyRDN |
Novell Directory Services Read Operation
The Read Operation is executed by calling NWDSRead(). This function is used to read attribute names and values from the supplied NDS object. NWDSRead() accepts input parameters that define the criteria for the data returned. This criteria can be defined as follows:
All Attribute Names
Specific Attribute Names
All Attribute Names And Values
Specific Attribute Names And Values
NWDSRead() Function Prototype
NWDSCCODE N_API NWDSRead ( NWDSContextHandle context, pnstr8 object, nuint32 infoType, nbool8 allAttrs, pBuf_T attrNames, pnint32 iterationHandle, pBuf_T objectInfo);
Let's take a closer look at these parameters.
Parameter
|
Description
|
context |
The context handle governs the behavior of the read operation. |
object |
This is the target NDS object for the read operation. The combination of the object namepassed as this parameter and the context variable DCK_NAME_CONTEXT determine thefull path to the object. |
infoType |
This parameter determines whether just attribute names or attribute names and values arereturned. Following are the MACRO defines for the available options for this parameter: DS_ATTRIBUTE_NAMES: Only attribute names will be returned. DS_ATTRIBUTE_VALUES: Attribute names and attribute values will be returned. |
allAttrs |
This parameter determines whether all attributes should be returned or only thosespecified in an input buffer. The available options for this parameter are: TRUE: All attributes will be returned. FALSE: Only those attributes specified in the attrNames input buffer will be returned. |
attrNames |
The value of this parameter depends on the value of allAttrs. If allAttrs is set to TRUE, thevalue of this parameter should be set to NULL. If allAttrs is set to FALSE, the value of thisparameter should be a pointer to the input buffer that defines the specific attributes thatshould be returned by the read operation. |
iterationHandle |
This handle governs the flow control between the Directory Server Agent (NDS Server) andthe requesting application. The DSA will only send data in chunks application outputbuffer can accommodate. |
objectInfo |
This is the output buffer where the results of the read operation will be placed. Rememberthat if the iterationHandle is not set to -1 after the initial call the NWDSRead(), thisfunction must be called again to read the next iteration of data from the DSA. |
The Novell SDK defines some addition read operation functions that are extensions to the standard read operation. The names of these functions are as follows:
Function Name
|
Description
|
v |
This function is identical to NWDSRead() with exception of a time filter parameter whichallows the read operation to further discriminate the data that is returned. The time filter isspecified in UTC time. Only objects that have been modified since the specified time filterare returned. |
NWDSReadObjectInfo() |
This function returns information about an NDS object that is not available by using NWDSRead() to return attribute information. This function returns the full distinguished name of the object and a structure of type Object_Info_T. |
typedef struct { nuint32 objectFlags; nuint32 subordinateCount; time_t modificationTime; nstr8 baseClass[MAX_SCHEMA_NAME_BYTES + 2]; } Object_Info_T;
Field
|
Description
|
objectFlags |
The object flags provide additional information about the object type. The possible valuesfor this field are as follows: DS_ALIAS_ENTRY DS_PARTITION_ROOT DS_CONTAINER_ENTRY |
subordinateCount |
This field returns the number of subordinates of the target object. |
modificationTime |
This field returns the modification time stamp for the object. This value is in UTC. |
baseClass |
This fields returns the NDS schema base class of the object. |
Novell Directory Services List Operation
The list operation returns the names of the immediate subordinates for the specified entry. No attribute names or values are returned.
NWDSList() Function Prototype
NWDSCCODE N_API NWDSList( NWDSContextHandle context, pnstr8 object, pnint32 iterationHandle, pBuf_T subordinates);
Let's examine these parameters:
Parameter
|
Description
|
context |
The context handle governs the behavior of the read operation. |
object |
This is the target object for the list operation. The value for this parameter must be a container object. The subordinates of the specified object will be returned. |
iterationHandle |
This handle governs the flow control between the Directory Server Agent (NDS Server) and the requesting application. The DSA will only send data in chunks application output buffer can accommodate. |
subordinates |
This is the output buffer where the results of the list operation will be placed.Remember that if the iterationHandle is not set to -1 after the initial call toNWDSList(), this function must be called again to read the next iteration ofdata from the DSA. |
The Novell NetWare SDK adds some extensions to the NWDSList() API to provide additional functionality or additional filtering capability. These list operation extensions are as follows:
Extension
|
Description
|
NWDSListByClassAndName() |
This function lists a Directory object's immediate subordinates, restricting the list to subordinate objects matching a specified object class and/or name. |
NWDSListContainers() |
This function lists only the containers beneath the specified "starting object." |
NWDSExtSyncList() |
This function is identical to NWDSList() with the additional capability of specifying a time filter parameter which allows the list operation to further discriminate the data that is returned. The time filter is specified in UTC time. Only objects that have been modified since the specified time filter are returned. This function also allows a class name filter to be specified so only objects of the specified schema class are returned. |
Novell Directory Services Compare Operation
The compare operation is used to compare an object's attribute value to a specified value. This is a very convenient mechanism to quickly determine whether an attribute value is equal to a specified value without actually reading the value from the target object. For example, if the status of a service registered with NDS is stored in an NDS attribute on the service object (such as a print server), a requesting client could simply test the value of the "status" attribute against "UP." If the match was successful, the client would be cleared to make a connection.
NWDSCompare() Function Prototype
NWDSCCODE N_API NWDSCompare( NWDSContextHandle context, pnstr8 objectName, pBuf_T buf, pnbool8 matched);
Let's take a closer look at these parameters:
Parameter
|
Description
|
context |
The context handle governs the behavior of the compare operation. |
object |
This is the target object for the compare operation. |
buf |
This is the input buffer that identifies the attribute name and value to compare. |
matched |
This parameter returns TRUE if the match is successful, otherwise, it returns FALSE. |
Novell Directory Services Add Object Operation
The Novell Directory Services add operation is implemented by the function NWDSAddObject(). This function is used to add an object to the Novell Directory Services database. Values for the mandatory attributes defined for the object class to be added must be provided in the input buffer upon calling this function, otherwise, the function will fail.
NWDSAddObject() Function Prototype
NWDSCCODE N_API NWDSAddObject( NWDSContextHandle context, pnstr8 objectName, pnint32 iterationHandle, nbool8 more, pBuf_T objectInfo);
Let's make a closer inspection of these parameters:
Parameter
|
Description
|
context |
The context handle governs the behavior of the add operation. |
objectName |
This identifies the name of the object to be added. Remember that by default, the combination of the object name passed as this parameter and the context variable DCK_NAME_CONTEXT determine the full path to the object |
iterationHandle |
This parameter is reserved and should be set to NULL. |
objectInfo |
This parameter is a pointer to an input buffer that contains the attribute names and valuesfor the mandatory and optional attributes of the class to be added. |
Novell Directory Services Modify Object Operation
The modify operation is implemented by the NWDSModifyObject() function. This operation is used to modify optional attribute values or add new optional attribute values to an existing object. The mandatory attribute values must be added upon creation of the object by NWDSAddObject().
NWDSModifyObject() Function Prototype
NWDSCCODE N_API NWDSModifyObject( NWDSContextHandle context, pnstr8 objectName, pnint32 iterationHandle, nbool8 more, pBuf_T changes);
Let's take a closer look at these parameters.
Parameter
|
Description
|
context |
The context handle governs the behavior of the modify operation. |
objectName |
This identifies the name of the object to be modified. Remember that by default, the combination of the object name passed as this parameter and the context variable DCK_NAME_CONTEXT determine the full path to the object. |
iterationHandle |
This parameter is reserved and should be set to NULL. |
more |
This parameter is reserved and should be set to zero |
objectInfo |
This parameter is a pointer to an input buffer that contains the attribute names and values for the optional attributes of the class to be modified. |
NWDSModifyObject() accepts a pointer to an input buffer wherein the attribute names and values to be added or modified reside. Following is a list of valid modification operations for NDS attributes:
DS_ADD_ATTRIBUTE 0x00 - Add first value of attribute, error if it already exists.
DS_REMOVE_ATTRIBUTE 0x01 - Remove all values, error if attribute does not exist.
DS_ADD_VALUE 0x02 - Add first or additional value, error if duplicate.
DS_REMOVE_VALUE 0x03 - Remove a value, error if it does not exist
DS_ADDITIONAL_VALUE 0x04 - Add additional value, error if duplicate or first.
DS_OVERWRITE_VALUE 0x05 - Add first or additional value, overwrite if duplicate.
DS_CLEAR_ATTRIBUTE 0x06 - Remove all values, no error if attribute does not exist.
DS_CLEAR_VALUE 0x07 - Remove value, no error if value does not exist.
Novell Directory Services Remove Object Operation
The remove object operation is implemented by the function NWDSRemoveObject(). This function is used to remove an object from the NDS database.
NWDSRemoveObject() Function Prototype
NWDSCCODE N_API NWDSRemoveObject( NWDSContextHandle context, pnstr8 object);
Let's take a closer look at these parameters:
Parameter
|
Description
|
context |
The context handle governs the behavior of the remove operation. |
objectName |
This identifies the name of the object to be removed. Remember that by default, thecombination of the object name passed as this parameter and the context variableDCK_NAME_CONTEXT determine the full path to the object. |
Novell Directory Services Modify RDN (Rename) Operation
The Modify RDN operation is implemented by the function NWDSModifyRDN(). This function is used to rename an object in the NDS database. Using this operation, the client can change the naming attribute of an existing object or the RDN of an existing object. If the naming attribute is changed, it must comply with the schema definition for the specified object or the operation will fail. Very few base schema object class definitions define multiple naming attribute definitions. The most common use for this operation is to change the RDN (name of the immediate leaf node).
NWDSModifyRDN() Function Prototype
NWDSCCODE N_API NWDSModifyRDN( NWDSContextHandle context, pnstr8 objectName, pnstr8 newRDN, nbool8 deleteOldRDN);
Let's take a closer look at these parameters:
Parameter
|
Description
|
context |
The context handle governs the behavior of the remove operation. |
objectName |
This identifies the name of the object to be removed. Remember that by default, thecombination of the object name passed as this parameter and the context variableDCK_NAME_CONTEXT determine the full path to the object. |
newRDN |
This parameter identifies the new RDN for the NDS object passed as objectName. |
deleteOldRDN |
If deleteOldRDN is set, all attributes in the old RDN which are not in the new RDN are deleted. If deleteOldRDN is not set, the old attribute values remain in the object as multiplevalues of the attribute. If this operation removes the last value of an attribute, that attribute isdeleted. |
The Novell SDK provides some extensions to the ModifyRDN operation. These include:
NWDSModifyDN(): This function is used to rename an object in one container to a new object name in another container. The new object name can be specified the same for the destination container as the source object name which simply results in a move of the object from one container to another.
NWDSMoveObject: This function is used to move an object from one container to another container. It has the same functionality as NWDSModifyDN() with the exception that the destination container and destination RDN are specified separately.
Novell Directory Services Search Operation
The Search operation provides a very powerful mechanism for defining complex search criteria which returns selected information from NDS objects that meets this user-defined criteria.
NWDSSearch() Function Prototype
NWDSCCODE N_API NWDSSearch( NWDSContextHandle context, pnstr8 baseObjectName, nint scope, nbool8 searchAliases, pBuf_T filter, nuint32 infoType, nbool8 allAttrs, pBuf_T attrNames, pnint32 iterationHandle, nint32 countObjectsToSearch, pnint32 countObjectsSearched, pBuf_T objectInfo);
Let's take a closer look at these parameters:
Parameter
|
Description
|
context |
The context handle governs the behavior of the remove operation. |
objectName |
This identifies the base object where the search will begin. Set this object to [Root] to initiate a search of the entire tree. |
scope |
This parameter defines the depth of the search. The available options for this parameter are: DS_SEARCH_ENTRY (0) - Just search the immediate entry defined by objectName. DS_SEARCH_SUBORDINATES (1) - Search the immediate subordinates of the entry defined by objectName. DS_SEARCH_SUBTREE (2) Search all "branches" of the tree beneath the entry defined by objectName. |
searchAliases |
This parameter can be set to TRUE or FALSE. If set to TRUE, will dereference any aliases found during the search and the search will proceed from the dereferenced alias object ondown the tree. Care must be taken when setting this parameter to TRUE because thedereferenced aliases could result in an endless loop. If set to FALSE, searched objects are not dereferenced. |
filter |
This parameter contains an input buffer wherein the search criteria are defined. |
infoType |
This parameter can be set to TRUE or FALSE. If set to TRUE, indicates that attribute names and values should be returned. If set to FALSE indicates that only attribute names should be returned. |
allAttrs |
This parameter can be set to TRUE or FALSE. If set to TRUE, indicates that all attributesshould be returned and the value passed to attrNames is ignored. If set to FALSE,indicates that the value of attrNames contains an input buffer wherein the attributes to be returned are defined. |
attrNames |
This parameter contains a pointer to an input buffer that defines the attributes to bereturned. If allAttrs is TRUE, this value is ignored. |
iterationHandle |
This handle governs the flow control between the Directory Server Agent (NDS Server) andthe requesting application. The DSA will only send data in chunks application outputbuffer can accommodate. |
countObjectsToSearch |
This parameter is not implemented at the current time. Reserved for use at a later time. |
countObjectsSearched |
This parameter is not implemented at the current time. Reserved for use at a later time. |
objectInfo |
This parameter contains a pointer to the result buffer wherein the data that met the searchcriteria is stored. |
The NWDSSearch()function is similar to a combination of NWDSList() and NWDSRead() with some additional powerful capabilities to further discriminate the data returned from the operation. The search operation is capable of returning the subordinate object names beginning with a specified base object like NWDSList() and it can return specific attribute names and values like NWDSRead().
The key difference is the filter parameter which allows for complex search queries to be formulated. The search filter is composed by building what is called an expression tree. An expression tree can be visualized as demonstrated in Figure 1.
Each box represents a "node" of the expression tree.
Figure 1: An expression tree.
If the expression tree is read from left to right the resultant filter criteria is: Return all objects where the Surname is equal to Smith and Title is equal to Engineer. The filter buffer is built by using the NWDSAddFilterToken() API. Each filter token represents one node of the expression tree. Each node consists of three node components:
Token - Identifies the operation of the node.
Value - Identifies the value of the node.
Syntax - Identifies the syntax (NDS data type) of the specified Value component.
There are a number of Token component types.
Relational Operators
The following table lists the relational operators.
Relational Operators
|
Description
|
7 FTOK_EQ |
Equal |
8 FTOK_GE |
Greater Than or Equal |
FTOK_LE |
Lesser Than |
10 FTOK _ APPROX |
Approximate |
15 FTOK_PRESENT |
Present - Used to test whether a value for a specific attribute is present. |
16 FTOK_RDN |
Special token which can be used to search for objects of a specific Relative Distinguished Name without requiring that the calling entity have specific rights to the CN (common name) attribute. |
17 FTOK_BASECLS |
Special token which can be used to search for objects of a specific schema Base Class without requiring that the calling entity have specific rights to the Object Class attribute. |
Logical Operators
The following is a list of logical operators:
1 FTOK_OR
2 FTOK_AND
3 FTOK_NOT
4 FTOK_LPAREN
5 FTOK_RPAREN
Other Token Specifiers
The following is a list of other token specifiers:
14 FTOK_ANAME - Attribute Name
6 FTOK_AVAL - Attribute Value
0 FTOK_END - End Token
The value supplied for each node component depends on the value of the filter Token component. For example, the code to implement this expression tree would appear as follows:
Building The Expression Tree
NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &searchFilter);& NWDSInitBuf(cx, DSV_SEARCH_FILTER, searchFilter); NWDSAllocFilter(&cur);& NWDSAddFilterToken(cur, FTOK_ANAME, "Surname", 0); NWDSAddFilterToken(cur, FTOK_EQ, NULL, 0); NWDSAddFilterToken(cur, FTOK_AVAL, "Smith", SYN_CI_STRING); NWDSAddFilterToken(cur, FTOK_AND, NULL, 0); NWDSAddFilterToken(cur, FTOK_ANAME, "Title", 0); NWDSAddFilterToken(cur, FTOK_EQ, NULL, 0); NWDSAddFilterToken(cur, FTOK_AVAL, "Engineer", SYN_CI_STRING); NWDSAddFilterToken(cur, FTOK_END, NULL, 0); NWDSPutFilter(context, searchFilter, cur, NULL);
Note that these three node components are passed to NWDSAddFilterToken(). The value of the node components depends on the filter token component. The value for each node component is determined by the following node rules:
A Value component only applies to attribute names and attribute values.
If the Token component is an operator or parenthesis, you pass a null for the value and syntax.
If the Token component is an attribute name, you pass a null for the syntax.
Use FTOK_ENDto mark the end of an expression.
The code begins by allocating an input buffer in preparation for storing the search filter. This input buffer is then initialized with DSV_SEARCH_FILTER. Then a temporary cursor buffer is allocated with NWDSAllocFilter() and the expression tree is constructed by using NWDSAddFilterToken() to add individual nodes to the cursor buffer. Once the expression tree is constructed, it is placed in the input buffer with NWDSPutFilter().
NWDSPutFilter() automatically frees the cursor buffer memory and places the constructed expression tree into the input buffer. You can provide your own routine to free the cursor buffer. This is accomplished by passing a pointer to the routine to NWDSPutFilter() (rather than NULL). This can be advantageous if the cursor buffer contains a complex expression tree that you want to use at a later time and you want to avoid having it destroyed by NWDSPutFilter().
The Novell SDK provides an extension to the search operation. This is NWDSExtSyncSearch(). This function is identical to NWDSSearch() with the exception of a time filter parameter which allows for additional filtering on object modification time stamps.
* Originally published in Novell AppNotes
Disclaimer
The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.