#!/usr/bin/env perl
#
# BEGIN COPYRIGHT BLOCK
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
# Copyright (C) 2013 Red Hat, Inc.
# All rights reserved.
#
# License: GPL (version 3 or any later version).
# See LICENSE for details. 
# END COPYRIGHT BLOCK
#

use lib qw(/usr/lib/dirsrv/perl);
use DSUtil;
use Getopt::Std;

DSUtil::libpath_add("");
DSUtil::libpath_add("/usr/lib");
DSUtil::libpath_add("/usr/lib64");
$ENV{'PATH'} = ":/usr/bin";
$ENV{'SHLIB_PATH'} = "$ENV{'LD_LIBRARY_PATH'}";

$i = 0;
$attr_count = 0;
$vlv_count = 0;

sub usage {
    print(STDERR "Usage: db2index.pl [-Z serverID] [-D rootdn] { -w password | -w - | -j filename } [-P protocol]\n");
    print(STDERR "                   -n backendname [-t attributeName[:indextypes[:matchingrules]]] [-T vlvTag] [-h]\n");
    print(STDERR "Options:\n");
    print(STDERR "        -D rootdn       - Directory Manager\n");
    print(STDERR "        -w password     - Directory Manager's password\n");
    print(STDERR "        -w -            - Prompt for Directory Manager's password\n");
    print(STDERR "        -j filename     - Read Directory Manager's password from file\n");
    print(STDERR "        -Z serverID     - Server instance identifer\n");
    print(STDERR "        -n backendname  - Backend database name.  Example: userRoot\n");
    print(STDERR "        -t attributeName[:indextypes[:matchingrules]]\n");
    print(STDERR "                        - attributeName: name of the attribute to be indexed\n");
    print(STDERR "                          If omitted, all the indexes defined for that instance are generated.\n");
    print(STDERR "                        - indextypes: comma separated index types\n");
    print(STDERR "                        - matchingrules: comma separated matrules\n");
    print(STDERR "                              Example: -t foo:eq,pres\n");
    print(STDERR "        -T vlvTag       - VLV index name\n");
    print(STDERR "        -P protocol     - STARTTLS, LDAPS, LDAPI, LDAP (default: uses most secure protocol available)\n");
    print(STDERR "        -h              - Display usage\n");
}

while ($i <= $#ARGV) {
    if ("$ARGV[$i]" eq "-t") {         # attribute
        $i++; $attr[$attr_count] = $ARGV[$i]; $attr_count++;
    } elsif ("$ARGV[$i]" eq "-T") {    # VLV index
        $i++; $vlv_attr[$vlv_count] = $ARGV[$i]; $vlv_count++;
    } elsif ("$ARGV[$i]" eq "-D") {    # Directory Manager
        $i++; $rootdn = $ARGV[$i];
    } elsif ("$ARGV[$i]" eq "-w") {    # Directory Manager's password
        $i++; $passwd = $ARGV[$i];
    } elsif ("$ARGV[$i]" eq "-j") {    # Read Directory Manager's password from a file
        $i++; $passwdfile = $ARGV[$i];
    } elsif ("$ARGV[$i]" eq "-n") {    # backend instance name
        $i++; $instance = $ARGV[$i];
    } elsif ("$ARGV[$i]" eq "-Z") {    # server instance name
        $i++; $servid = $ARGV[$i];
    } elsif ("$ARGV[$i]" eq "-P") {    # protocol preference
        $i++; $protocol = $ARGV[$i];
    } elsif ("$ARGV[$i]" eq "-h") {    # help
        &usage; exit(0);
    } else {
        print "ERROR - Unknown option: $ARGV[$i]\n";
        &usage; exit(1);
    }
    $i++;
}

#
# Gather all our config settings
#
($servid, $confdir) = DSUtil::get_server_id($servid, "/etc/dirsrv");
%info = DSUtil::get_info($confdir, $host, $port, $rootdn);
$info{rootdnpw} = DSUtil::get_password_from_file($passwd, $passwdfile);
$info{protocol} = $protocol;
$info{args} = "-a";
if ($instance eq ""){ 
    &usage; 
    exit(1);
}

# 
# No attribute name has been specified: let's get them from the configuration
#
chdir("/usr/bin");
if ( $#attr == -1 && $#vlv_attr == -1 )
{
    # Get the list of indexes from the entry
    $info{base} = "cn=index,cn=\"$instance\", cn=ldbm database,cn=plugins,cn=config";
    $info{filter} = "(&(objectclass=*)(nsSystemIndex=false))";
    $info{scope} = "one";
    $info{attrs} = "cn";
    $info{srch_args} = $vstr;
    $indexes_list=DSUtil::ldapsrch(%info);
    
    # build the values of the attribute nsIndexAttribute
    open(LDAP1, "$indexes_list |");
    while (<LDAP1>){
        s/\n //g;
        if (/^cn: (.*)\n/) {
            $IndexAttribute="nsIndexAttribute";
            $attribute="$attribute$IndexAttribute: $1\n";
        }
    }
    close(LDAP1);
    if($? != 0){
        $ret=$?>>8;
        print(STDERR "Failed to search the server for indexes, error ($ret)\n");
        exit($ret);
    }
    if ( $attribute eq "" ){
        # No attribute to index, just exit
        print "Failed to add task entry - no attributes found for backend \"$instance\"\n";
        exit(1);
    }

    # Get the list of indexes from the entry
    $info{base} = "cn=\"$instance\",cn=ldbm database,cn=plugins,cn=config";
    $info{filter} = "objectclass=vlvIndex";
    $info{scope} = "sub";
    $info{attrs} = "cn";
    $info{srch_args} = $vstr;
    $vlvindexes_list=DSUtil::ldapsrch(%info);

    # build the values of the attribute nsIndexVlvAttribute
    open(LDAP1, "$vlvindexes_list |");
    while (<LDAP1>) {
        s/\n //g;
        if (/^cn: (.*)\n/) {
            $vlvIndexAttribute="nsIndexVlvAttribute";
            $vlvattribute="$vlvattribute$vlvIndexAttribute: $1\n";
        }
    }
    close(LDAP1);
    if($? != 0){
        $ret=$?>>8;
        print(STDERR "Failed to search the server for VLV indexes, error ($ret)\n");
        exit($ret);
    }
}
else
{
    foreach $arg (@attr){
        $attribute = $attribute . "nsIndexAttribute: $arg\n";
    }
    foreach $arg (@vlv_attr){
        $vlvattribute = $vlvattribute . "nsIndexVlvAttribute: $arg\n";
    }
}

# 
# Construct the task entry
#
($s, $m, $h, $dy, $mn, $yr, $wdy, $ydy, $r) = localtime(time);
$mn++; $yr += 1900;
$taskname = "db2index_${yr}_${mn}_${dy}_${h}_${m}_${s}";
$dn = "dn: cn=$taskname, cn=index, cn=tasks, cn=config\n";
$misc = "objectclass: top\nobjectclass: extensibleObject\n";
$cn =  "cn: $taskname\n";
$nsinstance = "nsInstance: ${instance}\n";
$entry = "${dn}${misc}${cn}${nsinstance}${attribute}${vlvattribute}";

$rc = DSUtil::ldapmod($entry, %info);

$dn =~ s/^dn: //;
$dn =~ s/\n//;
if($rc == 0){
    print "Successfully added task entry \"$dn\"\n";
} else {
    print "Failed to add task entry \"$dn\" error ($rc)\n";
}

exit($rc);
