/*
 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved
 * Use of this product is subject to license terms.
 */
/************************************************************

 entries.c

 This source file provides examples of working with entries.

 ACTIVATING THIS PLUG-IN
 -----------------------
 1. Build the library containing the plug-in.

 2. Configure the server to log plug-in messages.

    $ dsconf set-log-prop error level:err-plugins

 3. Configure the server to load the plug-in.
     
    $ dsconf create-plugin -H <lib-path> -F entries_init -Y object "Test entries"
    $ dsconf set-plugin-prop "Test entries" feature:test-entries version:7.0 desc:"Sample plug-in for working with entries"
    $ dsconf enable-plugin "Test entries"
    Directory Server needs to be restarted for changes to take effect
    $ dsadm restart <inst-path>

************************************************************/
#include <stdio.h>
#include <string.h>
#include "slapi-plugin.h"

#define LDIF_STR "dn: dc=example,dc=com\nobjectclass: \
    top\nobjectclass: domain\ndc: example\n"

Slapi_PluginDesc entries_desc = {
    "test-entries",                           /* plug-in identifier      */
    "Oracle Corporation (test)",              /* vendor name             */
    "11.1.1.3.0",                             /* plug-in revision number */
    "Sample plug-in for working with entries" /* description             */
};

/* Get an entry from LDIF and manipulate it, writing to the log.  */
int
test_ldif()
{
    char        * ldif  = NULL;        /* Example LDIF string     */
    Slapi_Entry * entry = NULL;        /* Entry to hold LDIF      */
    char        * str   = NULL;        /* String to hold entry    */
    int           len;                 /* Length of entry as LDIF */
    Slapi_Value * values[2];           /* Attribute values        */

    /* LDIF to Slapi_Entry                                        */
    entry = slapi_entry_alloc();
    ldif  = slapi_ch_strdup(LDIF_STR);
    entry = slapi_str2entry(ldif, SLAPI_STR2ENTRY_ADDRDNVALS);
    slapi_ch_free_string(&ldif);
    if (entry == NULL) return (-1);

    /* Slapi_Entry to LDIF                                        */
    str = slapi_entry2str(entry, &len);
    if (str == NULL) return (-1);
    slapi_log_info_ex(
        SLAPI_LOG_INFO_AREA_PLUGIN,
        SLAPI_LOG_INFO_LEVEL_DEFAULT,
        SLAPI_LOG_NO_MSGID,
        SLAPI_LOG_NO_CONNID,
        SLAPI_LOG_NO_OPID,
        "test_ldif in test-entries plug-in",
        "\nOriginal entry:\n%sEntry length: %d\n", str, len 
    );
    slapi_ch_free_string(&str);

    /* Add a description by setting the value of the attribute.
     * Although this is overkill when manipulating string values,
     * it can be handy when manipulating binary values.           */
    values[0] = slapi_value_new_string("This sentence is false.");
    values[1] = NULL;
    if (slapi_entry_attr_merge_sv(entry,"description",values) != 0) 
        return (-1);

    str = slapi_entry2str(entry, &len);
    if (str == NULL) return (-1);
    slapi_log_info_ex(
        SLAPI_LOG_INFO_AREA_PLUGIN,
        SLAPI_LOG_INFO_LEVEL_DEFAULT,
        SLAPI_LOG_NO_MSGID,
        SLAPI_LOG_NO_CONNID,
        SLAPI_LOG_NO_OPID,
        "test_ldif in test-entries plug-in",
        "\nModified entry:\n%sEntry length: %d\n", str, len 
    );
    slapi_ch_free_string(&str);
    slapi_value_free(&values[0]);
    
    /* Change the description to something else. Here, we make
     * use of the fact that our attribute value is a string.      */
    slapi_entry_attr_set_charptr(entry,"description","Answer: 42.");

    str = slapi_entry2str(entry, &len);
    if (str == NULL) return (-1);
    slapi_log_info_ex(
        SLAPI_LOG_INFO_AREA_PLUGIN,
        SLAPI_LOG_INFO_LEVEL_DEFAULT,
        SLAPI_LOG_NO_MSGID,
        SLAPI_LOG_NO_CONNID,
        SLAPI_LOG_NO_OPID,
        "test_ldif in test-entries plug-in",
        "\nFurther modified entry:\n%sEntry length: %d\n", str, len 
    );
    slapi_ch_free_string(&str);

    /* Release memory allocated for the entry.                    */
    slapi_entry_free(entry);

    return (0);
}

/* Create an entry and a modified duplicate; log both DNs.        */
int
test_create_entry()
{
    Slapi_Entry * entry = NULL;        /* Original entry          */
    Slapi_Entry * ecopy = NULL;        /* Copy entry              */

    /* Build a new entry, using a shortcut method for
     * adding string attribute values.                            */
    entry = slapi_entry_alloc();
    slapi_entry_set_dn(entry, slapi_ch_strdup("dc=example,dc=com"));
    slapi_entry_add_string(entry, "objectclass", "top");
    slapi_entry_add_string(entry, "objectclass", "domain");
    slapi_entry_add_string(entry, "dc", "example");

    /* Copy the entry and change the DN.
     * Here we use slapi_ch_strdup() when changing the
     * DN to make sure the old DN gets freed before
     * the new DN is added.                                       */
    ecopy = slapi_entry_dup(entry);
    slapi_entry_set_dn(ecopy, slapi_ch_strdup("dc=example,dc=org"));

    /* Log the resulting DNs.                                     */
    slapi_log_info_ex(
        SLAPI_LOG_INFO_AREA_PLUGIN,
        SLAPI_LOG_INFO_LEVEL_DEFAULT,
        SLAPI_LOG_NO_MSGID,
        SLAPI_LOG_NO_CONNID,
        SLAPI_LOG_NO_OPID,
        "test_create_entry in test-entries plug-in",
        "\nEntry DN:\n%s\nCopy entry DN:\n%s\n",
        slapi_entry_get_dn(entry),
        slapi_entry_get_dn(ecopy)
    );

    /* Add a description.                                         */
    slapi_entry_add_string(ecopy, "description", "A copy of the orig.");
    
    /* Does the resulting copy comply with our schema?            */
    if (slapi_entry_schema_check(NULL, ecopy) == 0) {
        slapi_log_info_ex(
            SLAPI_LOG_INFO_AREA_PLUGIN,
            SLAPI_LOG_INFO_LEVEL_DEFAULT,
            SLAPI_LOG_NO_MSGID,
            SLAPI_LOG_NO_CONNID,
            SLAPI_LOG_NO_OPID,
            "test_create_entry in test-entries plug-in",
            "Copy entry complies with schema\n"
        );
    } else {
        slapi_log_info_ex(
            SLAPI_LOG_INFO_AREA_PLUGIN,
            SLAPI_LOG_INFO_LEVEL_DEFAULT,
            SLAPI_LOG_NO_MSGID,
            SLAPI_LOG_NO_CONNID,
            SLAPI_LOG_NO_OPID,
            "test_create_entry in test-entries plug-in",
            "Copy entry does not comply with schema\n"
        );
    }

    /* Release memory allocated for the entries.                  */
    slapi_entry_free(entry);
    slapi_entry_free(ecopy);

    return (0);
}

/* Register the plug-in with the server                           */
#ifdef _WIN32
__declspec(dllexport)
#endif
int
entries_init(Slapi_PBlock * pb)
{
    int rc = 0;                        /* 0 means success         */
    rc |= slapi_pblock_set(            /* Plug-in API version     */
        pb,
        SLAPI_PLUGIN_VERSION,
        SLAPI_PLUGIN_CURRENT_VERSION
    );
    rc |= slapi_pblock_set(            /* Plug-in description     */
        pb,
        SLAPI_PLUGIN_DESCRIPTION,
        (void *) &entries_desc
    );
    rc |= slapi_pblock_set(            /* Startup function        */
        pb,
        SLAPI_PLUGIN_START_FN,
        (void *) test_ldif
    );
    rc |= slapi_pblock_set(            /* Shutdown function       */
        pb,
        SLAPI_PLUGIN_CLOSE_FN,
        (void *) test_create_entry
    );
    return rc;
}
