#!/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 Cwd;

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

$maxidx = 50;
$nowrap = 0;
$nobase64 = 0;
$noversion = 0;
$nouniqueid = 0;
$useid2entry = 0;
$onefile = 1;
$printkey = 1;
$doreplica = 0;
$verbose = 0;
$i = 0;
$insti = 0;
$incli = 0;
$excli = 0;
$decrypt_on_export = 0;
$cwd = cwd();

sub usage {
    print(STDERR "Usage: db2ldif.pl [-Z serverID] [-D rootdn] { -w password | -w - | -j pwfilename }\n");
    print(STDERR "                  [-P protocol] {-n backendname}* | {-s include}* [{-x exclude}*] [-h]\n");
    print(STDERR "                  [-a filename] [-m] [-M] [-r] [-u] [-C] [-N] [-U] [-E] [-1] [-a filename]\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 "        -Z serverID     - Server instance identifier\n");
    print(STDERR "        -j pwfilename   - Read Directory Manager's password from file\n");
    print(STDERR "        -n backendname  - Backend database name.  Example: userRoot\n");
    print(STDERR "        -a filename     - Output ldif file\n");
    print(STDERR "        -s include      - Included suffix(es)\n");
    print(STDERR "        -x exclude      - Excluded suffix(es)\n");
    print(STDERR "        -m              - Minimal base64 encoding\n");
    print(STDERR "        -M              - Output ldif is stored in multiple files\n");
    print(STDERR "                          these files are named : <instance>_<filename>\n");
    print(STDERR "                          by default, all instances are stored in <filename>\n");
    print(STDERR "        -r              - Export replication data\n");
    print(STDERR "        -u              - Do not export unique id\n");
    print(STDERR "        -C              - Use main db file only\n");
    print(STDERR "        -N              - Suppress printing sequential number\n");
    print(STDERR "        -U              - Output ldif is not folded\n");
    print(STDERR "        -E              - Decrypt encrypted data when exporting\n");
    print(STDERR "        -1              - Do not print version line\n");
    print(STDERR "        -P protocol     - STARTTLS, LDAPS, LDAPI, LDAP (default: uses most secure protocol available)\n");
    print(STDERR "        -h              - Display usage\n");
}

@instances = (
    "", "", "", "", "", "", "", "", "", "",
    "", "", "", "", "", "", "", "", "", "",
    "", "", "", "", "", "", "", "", "", "",
    "", "", "", "", "", "", "", "", "", "",
    "", "", "", "", "", "", "", "", "", "",
    ""
);
@included = (
    "", "", "", "", "", "", "", "", "", "",
    "", "", "", "", "", "", "", "", "", "",
    "", "", "", "", "", "", "", "", "", "",
    "", "", "", "", "", "", "", "", "", "",
    "", "", "", "", "", "", "", "", "", "",
    ""
);
@excluded = (
    "", "", "", "", "", "", "", "", "", "",
    "", "", "", "", "", "", "", "", "", "",
    "", "", "", "", "", "", "", "", "", "",
    "", "", "", "", "", "", "", "", "", "",
    "", "", "", "", "", "", "", "", "", "",
    ""
);

while ($i <= $#ARGV) {
    if ( "$ARGV[$i]" eq "-n" ) {    # instances
        $i++;
        if ($insti < $maxidx) {
            $instances[$insti] = $ARGV[$i]; $insti++;
        } else {
            &usage; exit(1);
        }
    } elsif ("$ARGV[$i]" eq "-s") {    # included suffix
        $i++;
        if ($incli < $maxidx) {
            $included[$incli] = $ARGV[$i]; $incli++;
        } else {
            &usage; exit(1);
        }
    } elsif ("$ARGV[$i]" eq "-x") {    # excluded suffix
        $i++;
        if ($excli < $maxidx) {
            $excluded[$excli] = $ARGV[$i]; $excli++;
        } else {
            &usage; exit(1);
        }
    } elsif ("$ARGV[$i]" eq "-a") {    # ldif file
        $i++; $ldiffile = $ARGV[$i];
    } 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 "-M") {    # multiple ldif file
        $onefile = 0;
    } elsif ("$ARGV[$i]" eq "-o") {    # one ldif file
        $onefile = 1;
    } elsif ("$ARGV[$i]" eq "-u") {    # no dump unique id
        $nouniqueid = 1;
    } elsif ("$ARGV[$i]" eq "-C") {    # use id2entry
        $useid2entry = 1;
    } elsif ("$ARGV[$i]" eq "-N") {    # does not print key
        $printkey = 0;
    } elsif ("$ARGV[$i]" eq "-r") {    # export replica
        $doreplica = 1;
    } elsif ("$ARGV[$i]" eq "-m") {    # no base64
        $nobase64 = 1;
    } elsif ("$ARGV[$i]" eq "-U") {    # no wrap
        $nowrap = 1;
    } elsif ("$ARGV[$i]" eq "-1") {    # no version line
        $noversion = 1;
    } elsif ("$ARGV[$i]" eq "-E") {    # decrypt
        $decrypt_on_export = 1;
    } elsif ("$ARGV[$i]" eq "-Z") { # server instance
        $i++; $servid = $ARGV[$i];
    } elsif ("$ARGV[$i]" eq "-h") { # help
        &usage; exit(0);
    } elsif ("$ARGV[$i]" eq "-P") { # protocol preference
        $i++; $protocol = $ARGV[$i];
    } elsif ("$ARGV[$i]" eq "-c") {    # cwd
        $i++; $cwd = $ARGV[$i];
    } 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);
$ldifdir = "/var/lib/dirsrv/slapd-$servid/ldif";
$info{rootdnpw} = DSUtil::get_password_from_file($passwd, $passwdfile);
$info{protocol} = $protocol;
$info{args} = "-a";
if ($instances[0] eq "" && $included[0] eq ""){ 
    &usage; 
    exit(1); 
}

# 
# Construct the task entry
#
($s, $m, $h, $dy, $mn, $yr, $wdy, $ydy, $r) = localtime(time);
$mn++; $yr += 1900;
$taskname = "export_${yr}_${mn}_${dy}_${h}_${m}_${s}";
$dn = "dn: cn=$taskname, cn=export, cn=tasks, cn=config\n";
$misc = "objectclass: top\nobjectclass: extensibleObject\n";
$cn =  "cn: $taskname\n";
$i = 0;
$be = "";
$nsinstance = "";
while ("" ne "$instances[$i]") {
    $nsinstance = "${nsinstance}nsInstance: $instances[$i]\n";
    if ( "" eq "$be" ) {
        $be = "$instances[$i]";
    } else {
        $be = "${be}-$instances[$i]";
    }
    $i++;
}
$i = 0;
$nsincluded = "";
while ("" ne "$included[$i]") {
    $nsincluded = "${nsincluded}nsIncludeSuffix: $included[$i]\n";
    my ($rdn, $rest) = split(/,/, $included[$i]);
    my ($rest, $tmpbe) = split(/=/, $rdn);
    if ( "" eq "$be" ) {
        $be = "$tmpbe";
    } else {
        $be = "${be}-$tmpbe";
    }
    $i++;
}
$i = 0;
$nsexcluded = "";
while ("" ne "$excluded[$i]") {
    $nsexcluded = "${nsexcluded}nsExcludeSuffix: $excluded[$i]\n";
    $i++;
}
if ($ldiffile eq "") {
    if ($onefile == 0) {
        $ldiffile = "${ldifdir}/${servid}-${yr}_${mn}_${dy}_${h}_${m}_${s}.ldif";
    } else {
        $ldiffile = "${ldifdir}/${servid}-${be}-${yr}_${mn}_${dy}_${h}_${m}_${s}.ldif";
    }
} elsif ($ldiffile =~ "^/") { 
    ; # full path 
} else { 
    $ldiffile = $cwd . "/" . $ldiffile; 
} 
$nsreplica = "";
if ($doreplica != 0) { $nsreplica = "nsExportReplica: true\n"; }
$nsnobase64 = "";
if ($nobase64 != 0) { $nsnobase64 = "nsMinimalEncoding: true\n"; }
$nsnowrap = "";
if ($nowrap != 0) { $nsnowrap = "nsNoWrap: true\n"; }
$nsnoversion = "";
if ($noversion != 0) { $nsnoversion = "nsNoVersionLine: true\n"; }
$nsnouniqueid = "";
if ($nouniqueid != 0) { $nsnouniqueid = "nsDumpUniqId: false\n"; }
$nsuseid2entry = "";
if ($useid2entry != 0) { $nsuseid2entry = "nsUseId2Entry: true\n"; }
$nsonefile = "";
if ($onefile != 0) { $nsonefile = "nsUseOneFile: true\n"; }
if ($onefile == 0) { $nsonefile = "nsUseOneFile: false\n"; }
$nsexportdecrypt = "";
if ($decrypt_on_export != 0) { $nsexportdecrypt = "nsExportDecrypt: true\n"; }
$nsprintkey = "";
if ($printkey == 0) { $nsprintkey = "nsPrintKey: false\n"; }
$nsldiffile = "nsFilename: ${ldiffile}\n";
$ttl = "ttl: 86400";
$entry = "${dn}${misc}${cn}${nsinstance}${nsincluded}${nsexcluded}${nsreplica}${nsnobase64}${nsnowrap}${nsnoversion}${nsnouniqueid}${nsuseid2entry}${nsonefile}${nsexportdecrypt}${nsprintkey}${nsldiffile}${ttl}";

print("Exporting to ldif file: ${ldiffile}\n");
$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);

