This section shows how to develop functionality called by Directory Server before and after a client add operation.
Example 39–10 prepends the string ADD to the description attribute of the entry to be added to the directory. For complete example code, refer to instance-path/examples/testpreop.c.
Before using the plug-in function as described here, set up the example suffix and register the plug-in. See Extending the Bind Operation and “To register the Plug-in”, as described previously.
To try the preoperation add function, add an entry for Quentin Cubbins who recently joined Example.com. Quentin’s LDIF entry, quentin.ldif, reads as shown in the following example.
dn: uid=qcubbins,ou=People,dc=example,dc=com objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson uid: qcubbins givenName: Quentin sn: Cubbins cn: Quentin Cubbins mail: qcubbins@example.com userPassword: qcubbins secretary: uid=bjensen,ou=People,dc=example,dc=com description: Entry for Quentin Cubbins |
The following example performs the prepend.
#include "slapi-plugin.h" int testpreop_add(Slapi_PBlock * pb) { Slapi_Entry * entry; /* Entry to add */ Slapi_Attr * attribute; /* Entry attributes */ Slapi_Value ** values; /* Modified, duplicate vals*/ int connId, opId, rc = 0; long msgId; /* Get the entry. */ rc |= slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &entry); rc |= slapi_pblock_get(pb, SLAPI_OPERATION_MSGID, &msgId); rc |= slapi_pblock_get(pb, SLAPI_CONN_ID, &connId); rc |= slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opId); /* Prepend ADD to values of description attribute. */ rc |= slapi_entry_attr_find(entry, "description", &attribute); if (rc == 0) { /* Found a description, so... */ int nvals, i, count = 0; const Slapi_Value * value; slapi_attr_get_numvalues(attribute, &nvals); values = (Slapi_Value **) slapi_ch_malloc((nvals+1)*sizeof(Slapi_Value *)); for ( /* ...loop for value... */ i = slapi_attr_first_value_const(attribute, &value); i != -1; i = slapi_attr_next_value_const(attribute, i, &value) ) { /* ...prepend "ADD ". */ const char * string; char * tmp; values[count] = slapi_value_dup(value); string = slapi_value_get_string(values[count]); tmp = slapi_ch_malloc(5+strlen(string)); strcpy(tmp, "ADD "); strcpy(tmp+4, string); slapi_value_set_string(values[count], tmp); slapi_ch_free((void **)&tmp); ++count; } values[count] = NULL; } else { /* entry has no desc. */ slapi_log_info_ex( SLAPI_LOG_INFO_AREA_PLUGIN, SLAPI_LOG_INFO_LEVEL_DEFAULT, msgId, connId, opId, "testpreop_add in test-preop plug-in", "Entry has no description attribute.\n" ); } rc = slapi_entry_attr_replace_sv(entry, "description", values); if (rc != 0) { slapi_log_info_ex( SLAPI_LOG_INFO_AREA_PLUGIN, SLAPI_LOG_INFO_LEVEL_DEFAULT, msgId, connId, opId, "testpreop_add in test-preop plug-in", "Description attribute(s) not modified.\n" ); } slapi_valuearray_free(&values); return 0; }
Add Quentin’s entry to the directory. For example, if the entry is in quentin.ldif, type:
$ ldapmodify -h localhost -p 1389 -a -f quentin.ldif \ -D uid=kvaughan,ou=people,dc=example,dc=com -w bribery adding new entry uid=qcubbins,ou=People,dc=example,dc=com $ |
At this point, search the directory for Quentin’s entry.
$ ldapsearch -h localhost -p 1389 -b dc=example,dc=com uid=qcubbins version: 1 dn: uid=qcubbins,ou=People,dc=example,dc=com objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson uid: qcubbins givenName: Quentin sn: Cubbins cn: Quentin Cubbins mail: qcubbins@example.com secretary: uid=bjensen,ou=People,dc=example,dc=com description: ADD Entry for Quentin Cubbins $ |
Notice the value of the description attribute.
Delete Quentin’s entry so you can use it again later as an example.
$ ldapdelete -D uid=kvaughan,ou=people,dc=example,dc=com -w bribery \ uid=qcubbins,ou=people,dc=example,dc=com |
Turn off the preoperation plug-in to avoid prepending ADD to all the entries that you add.
$ dsconf disable-plugin -h localhost -p 1389 "Test Preop" $ dsadm restart instance-path |
Logging the Entry to Add logs the entry to add. For complete example code, refer to instance-path/examples/testpostop.c.
Before using the plug-in function as described here, set up the example suffix and register the plug-in. See Extending the Bind Operation.
The testpostop_add() function logs the DN of the added entry and also writes the entry to a log created by the plug-in, changelog.txt. The location of changelog.txt depends on the platform, as shown in the following example. The changelog.txt file managed by the plug-in is not related to other change logs managed by Directory Server.
#include "slapi-plugin.h" int testpostop_add(Slapi_PBlock * pb) { char * dn; /* DN of entry to add */ Slapi_Entry * entry; /* Entry to add */ int is_repl = 0; /* Is this replication? */ int connId, opId, rc = 0; long msgId; rc |= slapi_pblock_get(pb, SLAPI_ADD_TARGET, &dn); rc |= slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &entry); rc |= slapi_pblock_get(pb, SLAPI_OPERATION_MSGID, &msgId); rc |= slapi_pblock_get(pb, SLAPI_CONN_ID, &connId); rc |= slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opId); rc |= slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_repl); if (rc != 0) return (rc); slapi_log_info_ex( SLAPI_LOG_INFO_AREA_PLUGIN, SLAPI_LOG_INFO_LEVEL_DEFAULT, msgId, connId, opId, "testpostop_add in test-postop plug-in", "Added entry (%s)\n", dn ); /* In general, do not interfere in replication operations. */ /* Log the DN and the entry to the change log file. */ if (!is_repl) write_changelog(_ADD, dn, (void *) entry, 0); return (rc); }
After activating the plug-in, add Quentin’s entry:
$ ldapmodify -a -D uid=kvaughan,ou=people,dc=example,dc=com \ -h localhost -p 1389 -w bribery -f quentin.ldif adding new entry uid=qcubbins,ou=People,dc=example,dc=com $ |
Search instance-path/logs/errors for the log message. If you ignore housekeeping information, you get the following message:
Added entry (uid=qcubbins,ou=people,dc=example,dc=com)
Notice also the entry logged to changelog.txt. The entry resembles the LDIF that was added, except that the change log has time stamps attached for internal use as shown in the following example.
time: 21120506172445 dn: uid=qcubbins,ou=people,dc=example,dc=com changetype: add objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson uid: qcubbins givenName: Quentin sn: Cubbins cn: Quentin Cubbins mail: qcubbins@example.com secretary: uid=bjensen,ou=People,dc=example,dc=com userPassword: qcubbins creatorsName: cn=Directory Manager modifiersName: cn=Directory Manager createTimestamp: 21120506152444Z modifyTimestamp: 21120506152444Z