#!/usr/bin/env perl
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
# 
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# 
# Copyright (C) 2007 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#

use lib qw(/usr/lib/dirsrv/perl);

use strict;

use File::Basename;
use File::Path;
use CGI qw(:cgi :oldstyle_urls);
use Inf;
use AdminUtil;
use Util;
use FileConn;
use Resource;

# remove_tree($centry, $key, $instname, [$isparent, [$dontremove]])
#     $centry: entry to look for the path to be removed
#     $key: key to look for the path in the entry
#     $instname: instance name "slapd-<ID>" to check the path
#     $isparent: specify 1 to remove from the parent dir
#     $dontremove: pattern not to be removed (e.g., ".db$")
sub remove_tree
{
    my $centry = shift;
    my $key = shift;
    my $instname = shift;
    my $isparent = shift;
    my $dontremove = shift;

    foreach my $path ( @{$centry->{$key}} )
    {
        my $rmdir = "";
        my $rc = 0;
        if ( 1 == $isparent )
        {
            $rmdir = dirname($path);
        }
        else
        {
            $rmdir = $path;
        }
        if ( -d $rmdir && $rmdir =~ /$instname/ )
        {
            if ( "" eq "$dontremove" )
            {
                $rc = rmtree($rmdir);
                if ( 0 == $rc )
                {
                    print "Content-type: text/plain\n\n";
                    print "NMC_ErrInfo: $rmdir was not removed.\n";
                    print STDERR "Warning: $rmdir was not removed.\n";
                }
            }
            else
            {
                # Skip the dontremove files
                $rc = opendir(DIR, $rmdir);
                if ($rc)
                {
                    while (defined(my $file = readdir(DIR)))
                    {
                        next if ( "$file" =~ /$dontremove/ );
                        next if ( "$file" eq "." );
                        next if ( "$file" eq ".." );
                        my $rmfile = $rmdir . "/" . $file;
                        my $rc0 = rmtree($rmfile);
                        if ( 0 == $rc0 )
                        {
                            print "Content-type: text/plain\n\n";
                            print "NMC_ErrInfo: $rmfile was not removed.\n";
                            print STDERR "Warning: $rmfile was not removed.\n";
                        }
                    }
                    closedir(DIR);
                }
                my $newrmdir = $rmdir . ".removed";
                my $rc1 = 1;
                if ( -d $newrmdir )
                {
                    $rc1 = rmtree($newrmdir);
                    if ( 0 == $rc1 )
                    {
                        print "Content-type: text/plain\n\n";
                        print "NMC_ErrInfo: $newrmdir was not removed.\n";
                        print STDERR "Warning: $newrmdir was not removed.\n";
                    }
                }
                if ( 0 < $rc1 )
                {
                    rename($rmdir, $newrmdir);
                }
            }
        }
    }
}

sub remove_pidfile
{
    my ($type, $instdir, $instname) = @_;

    my $pattern = "^" . $type . ".*=";
    my $pidline = `grep $pattern $instdir/start-slapd`;
    chomp($pidline);
    my ($key, $pidfile) = split(/=/, $pidline);
    if ( -e $pidfile && $pidfile =~ /$instname/ )
    {
        unlink($pidfile);
    }
}

my $res = new Resource("/usr/share/dirsrv/properties/ds_remove.res",
                       "/usr/share/dirsrv/properties/setup-ds-admin.res",
                       "/usr/share/dirsrv/properties/setup-ds.res");

# parse the input parameters
my $query = new CGI;

# call ds_newinst as a GET (GET or POST works, GET is simpler)
$ENV{REQUEST_METHOD} = "GET";
$ENV{QUERY_STRING} = $query->query_string();

my $force = $query->param('force');
my $instname = $query->param('InstanceName');
my ($slapd, $inst) = split(/-/, $instname, 2);
my $configdir = "/etc/dirsrv/slapd-$inst";
if ( ! -d $configdir )
{
    print "Content-type: text/plain\n\n";
    print "NMC_ErrInfo: $configdir does not exist\n";
    print "NMC_Status: 1\n";
    print STDERR "Error: $configdir does not exist\n";
    exit 1;
}
my @errs;
my $inf = createInfFromConfig($configdir, $inst, \@errs);
if (@errs)
{
    print "Content-type: text/plain\n\n";
    print "NMC_ErrInfo: ", $res->getText(@errs), "\n";
    print "NMC_Status: 1\n";
    print STDERR "Error: ", $res->getText(@errs), "\n";
    exit 1;
}

# add the parmeters necessary to configure this DS to be managed
# by the console and to be registered with the config DS - these
# are usually passed in via the CGI params, or use reasonable
# default values
my $admConf = getAdmConf("/etc/dirsrv/admin-serv");
$inf->{General}->{ConfigDirectoryLdapURL} = $query->param('ldap_url') ||
    $admConf->{ldapurl};
$inf->{General}->{AdminDomain} = $query->param('admin_domain') ||
    $admConf->{AdminDomain};

# read the config file to find out the paths
my $dseldif = "/etc/dirsrv/$instname/dse.ldif";
my $conn = new FileConn($dseldif);

my $dn = "cn=config";
my $entry = $conn->search($dn, "base", "(cn=*)", 0);
if (!$entry)
{
    print "Content-type: text/plain\n\n";
    print "NMC_ErrInfo: Search $dn in $dseldif failed: $entry\n";
    print "NMC_Status: 1\n";
    print STDERR "Error: Search $dn in $dseldif failed: $entry\n";
    exit 1;
}

# Unregister the server from the configuration ds
# get config ds url from input or admconf
# get admin id from input or admconf
# must get admin password from input (PASSWORD_PIPE?)
# get admin domain
# config ds info
if (!unregisterDSWithConfigDS($inst, \@errs, $inf) && !$force)
{
    print "Content-type: text/plain\n\n";
    print "NMC_ErrInfo: ", $res->getText(@errs), "\n";
    print "NMC_Status: 1\n";
    print STDERR "Error:", $res->getText(@errs), "\n";
    exit 1;
}

$dn = "cn=config,cn=ldbm database,cn=plugins,cn=config";
my $dbentry = $conn->search($dn, "base", "(cn=*)", 0);
if (!$dbentry)
{
    print "Content-type: text/plain\n\n";
    print "NMC_ErrInfo: Search $dn in $dseldif failed: $dbentry\n";
    print "NMC_Status: 1\n";
    print "Error: Search $dn in $dseldif failed: $dbentry\n";
    exit 1;
}
$conn->close();

# stop the server
my $instdir = "";
foreach my $path ( @{$entry->{"nsslapd-instancedir"}} )
{
    if ( -d $path )
    {
        my $prog = $path . "/stop-slapd";
        if (-x $prog) {
            $? = 0;
            # run the CGI
            my $output = `$prog 2>&1`;
            my $status = $?;
            if ($status) {
                # Ignore the stop failure
                print "Content-type: text/plain\n\n";
                print "NMC_ErrInfo: Could not stop directory server: $output\n";
                print STDERR "Warning: Could not stop directory server: $output\n";
            }
            $instdir = $path;    # need to use it later...
        } elsif (!$force) {
            print "Content-type: text/plain\n\n";
            print "NMC_ErrInfo: The program $prog does not exist\n";
            print "NMC_Status: 1\n";
            print STDERR "Error: The program $prog does not exist\n";
            exit 1;
        }
    }
}
    
# remove physical dirs/files
remove_tree($dbentry, "nsslapd-directory", $instname, 1);
remove_tree($dbentry, "nsslapd-db-logdirectory", $instname, 1);
remove_tree($entry, "nsslapd-lockdir", $instname);
remove_tree($entry, "nsslapd-tmpdir", $instname);
remove_tree($entry, "nsslapd-bakdir", $instname, 1);
remove_tree($entry, "nsslapd-errorlog", $instname, 1);

# instance dir
if ( -d $instdir && $instdir =~ /$instname/ )
{
    # clean up pid files (if any)
    remove_pidfile("STARTPIDFILE", $instdir, $instname);
    remove_pidfile("PIDFILE", $instdir, $instname);

    if ( 1 == isConfigDS($instname, "/etc/dirsrv/admin-serv") )
    {
        # if it is the Config DS, adm.conf and local.conf needs to be removed.
        unlink("/etc/dirsrv/admin-serv/adm.conf");
        unlink("/etc/dirsrv/admin-serv/local.conf");
    }

    my $rc = rmtree($instdir);
    if ( 0 == $rc )
    {
        print "Content-type: text/plain\n\n";
        print "NMC_ErrInfo: $instdir was not removed.\n";
        print STDERR "Warning: $instdir was not removed.\n";
    }
}
# Finally, config dir
remove_tree($entry, "nsslapd-schemadir", $instname, 1, "\.db\$");

# if we got here, report success
print "Content-type: text/plain\n\n";
print "NMC_Status: 0\n";
exit 0;
