#!/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.
# 
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception. 
# 
# 
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#

$nshome = $ENV{'NETSITE_ROOT'};

# If there is no nshome, then assume that we're running 
# as a commandline script.
if (!$nshome ) {
    $script_mode = 1;

# get the commandline options
    if (!getopts('h:i:d:e:s:t:n:') || !$opt_n || !$opt_h ) {
	print "usage: " . $0 . " -n nshome -h current_slapd_host:current_slapd_port [options]\n";
	print "\nrequired:\n";
	print "    -n directory\tthe directory where 1.0 is installed (NS-HOME)\n";
	print "    -h host[:port]\tthe current host and port of the directory server\n";
	print "                  \tto which the gateway connects.\n";
	print "\noptions:\n";
	print "    -i host[:port]\tthe new host and port of the directory server\n";
	print "    -s suffix\t\tthe old suffix of the directory server\n";
	print "    -t suffix\t\tthe new ESCAPED suffix of the directory server\n";
	print "    -d dirmgrdn\t\tthe old manager dn of the directory server\n";
	print "    -e dirmgrdn\t\tthe new manager dn of the directory server\n";
	print "\nexample:\n " . $0 . "  -n /home/servers/ds10/ -h gargoyle:1974 -i brooklyn -s \"dc=example,dc=com\" -t \"o%3Ddirectory.fedora.redhat.com\" -d \"cn=directory manager\" -e \"cn=directory guru\"\n";
	
	exit;
    }

    # Parse the commandline options
    handle_script_input();
    
} else {
# output cgi header
    print "Content-type: text/plain\n\n";

#    print "Done\n";
# parse the input
    while ( <> ) {
	&parse_input( $_ );
    }
    
    if ( !$vars{'old_host'}) {
	rpt_err( -13, "host"); 
# -13 = null parameter.
#	print "Invalid input for DSGW changer CGI\n\n";
	exit;
    }

#    print "$nshome $vars{'old_host'} $vars{'old_port'}\n";
}

# setup the path separator
$isNT = -d '\\';
$PS = $isNT ? "\\" : "/";

$contextdir = "$nshome"."$PS"."dsgw"."$PS"."context";

#make sure that the target directory exists
if (! -e "$contextdir") {
    rpt_err( -16 ,"$contextdir");
# -16 = not a directory
#    print "$contextdir does not exist\n";
    exit;
}


# cd into NS-HOME/dsgw/context directory
chdir "$contextdir" or die "Unable to cd to $contextdir: $!\n";

# read the files 
    opendir DSGW_CONTEXT, "." or die "$!";
    @dsgwconfs = grep !/^\.\.?$/, readdir DSGW_CONTEXT;
    closedir DSGW_CONTEXT;


# unescape the new and old suffixes
if ($vars{'old_suffix'} && $vars{'new_suffix'}) {
    $escaped_suffix = $vars{'new_suffix'};
    $vars{'new_suffix'} =~ s/%(\w\w)/chr(hex($1))/eg;
    $unescaped_suffix = $vars{'new_suffix'};
#    print "Normal new suffix: $unescaped_suffix\n";
#    print "Escaped new suffix: $escaped_suffix\n";
    $unescaped_oldsuffix = $vars{'old_suffix'};
    $unescaped_oldsuffix =~ s/%(\w\w)/chr(hex($1))/eg;
}

#unescape the digmrs
if ($vars{'new_dirmgr'}){
    $vars{'new_dirmgr'} =~ s/%(\w\w)/chr(hex($1))/eg;
}

if ($vars{'old_dirmgr'}){
    $vars{'old_dirmgr'} =~ s/%(\w\w)/chr(hex($1))/eg;
}


				# 
    $changed = "";
    foreach $file (@dsgwconfs){	

#	print "working on $file\n";
	
	# If it's not a .conf file, skip it.
	if ( $file !~ m/.*?\.conf$/ ) {
#	    print "skipping $file\n\n\n\n";
	    next;	      
	}
	
	$relevant_conf = 0;
	$relevant_suffix = 0;

        # open the old file
	open(OLDFILE, "$file") or die "Cannot read $file. $!\n"; # 
	
        # Need to test to see if this conf file has a baseurl that 
        # matches the old host and port
	for ($line=<OLDFILE>; $line ; $line=<OLDFILE>) { # 	    

	    # If we find the matching baseurl, then set a flag and break out of the loop.
	    if ($line =~ m:^baseurl\s*("){0,1}\s*ldap(s){0,1}\://$vars{'old_host'}(\:$vars{'old_port'}){0,1}/:) { #") 
		# Also check for a matching suffix.
		if ($vars{'old_suffix'} && $vars{'new_suffix'}) {
		    @baseurl = split("/", $line);
		    $curr_suff = $baseurl[3];

		    # Get rid of any double quotes.
		    @baseurl = split("\"", $curr_suff);
		    $curr_suff = $baseurl[0];

		    $unescaped_currsuffix = $curr_suff;
		    $unescaped_currsuffix =~ s/%(\w\w)/chr(hex($1))/eg;

#		    print "curr Suffix: $curr_suff\n";
#		    print "old Suffix: $vars{'old_suffix'}\n";
#		    print "unescaped curr Suffix: $unescaped_currsuffix\n";
#		    print "unescaped old Suffix: $unescaped_oldsuffix\n";

		    if ($unescaped_currsuffix eq $unescaped_oldsuffix) {
			$relevant_suffix = 1;
#			print "suffix match for $file\n";
		    }
		    
		}
		# set a flag
		$relevant_conf = 1;
#		print "host:port match for $file\n";
		last;
	    }


	}
	
	# If there was no match, then go on to the next file.
	if (! $relevant_conf) {
	    close(OLDFILE);
#	    print "no match for $file\n";
	    next;
	}

	# Else, there is a match start over at the beginning of the file
	seek OLDFILE, 0, 0;
	if ($changed eq "") {
		$changed = $file;
	}

	# open the new file
	open(NEWFILE, ">"."tmpcp_"."$file"."1") or die "Cannot write $contextdir$PStmpcp_$file1. $!\n";
    
	# Go through each line, replacing the relevant information
	for ($line=<OLDFILE>; $line ; $line=<OLDFILE>) { # 	    
	
	    # If there is a new host
	    if ($vars{'new_host'}) {
		$line =~ s:^baseurl\s*("){0,1}\s*ldap(s){0,1}\://.*?(\:\d*){0,1}/:baseurl\t$1ldap$2\://$vars{'new_host'}$3/:og; #")
#		print "new host for $file\n";

	    }

	    # a new port
	    if ($vars{'new_port'}) {
		$line =~ s:^baseurl\s*("){0,1}\s*ldap(s){0,1}\://(.*?)(\:\d*){0,1}/:baseurl\t$1ldap$2\://$3\:$vars{'new_port'}/:og; #")
#		print "new port for $file\n";
	    }

	    # new dirmgr
	    if ($vars{'new_dirmgr'} && $vars{'old_dirmgr'}) {
		$line =~ s:(?i)^dirmgr\s*("){0,1}$vars{'old_dirmgr'}("){0,1}:dirmgr\t"$vars{'new_dirmgr'}":g;
#		print "new dirmgr for $file\n";
	    }
	    
	    # new suffix
	    if ($relevant_suffix) {
		$line =~ s:(^baseurl\s*("){0,1}\s*ldap(s){0,1}\://.*?(\:\d*){0,1}/)((.*?("))|(.*?)):$1$escaped_suffix$7:og; # 
	    $line =~ s:^location-suffix.*:location-suffix\t"$unescaped_suffix":og; 
#	    print "new suffix for $file\n";
	    }


	    print NEWFILE $line;

	}
	# 
	close(OLDFILE);
	close(NEWFILE);
	    
	rename "tmpcp_" . "$file"."1", "$file";

    }
rpt_err(0, $changed);


sub parse_input
{
    local( $line ) = @_;
    local($var, $value, $assign );


    foreach $assign ( split( /&/, $line ) ) {
        ( $var, $value ) = split( /=/, $assign );
        $value =~ s/\+/ /g;
        $value =~ s/ /%20/g;
#        $value =~ s/%(\w\w)/chr(hex($1))/eg;
        $var =~ s/\+/ /g;
#        $var =~ s/%(\w\w)/chr(hex($1))/eg;


	$vars{$var} = $value;
    }
}


sub handle_script_input 
{

    if ($opt_h) {
	@temp_array = split(":", $opt_h);

	$vars{'old_host'} = $temp_array[0];
	$vars{'old_port'} = $temp_array[1];

#	print "host: $vars{'old_port'}\n";
#	print "port: $vars{'old_host'}\n";
    }

    if ($opt_i) {
	@temp_array = split(":", $opt_i);

	$vars{'new_host'} = $temp_array[0];
	$vars{'new_port'} = $temp_array[1];

#	print "	$vars{'new_port'}\n";
#	print "	$vars{'new_host'}\n";
    }
    if ($opt_d) {
	$vars{'old_dirmgr'} = $opt_d;
    }
    if ($opt_e) {
	$vars{'new_dirmgr'} = $opt_e;
    }
    if ($opt_s) {
	$vars{'old_suffix'} = $opt_s;
    }
    if ($opt_t) {
	$vars{'new_suffix'} = $opt_t;
    }
    if ($opt_n) {
	$nshome = $opt_n;
    }

}


sub rpt_err
{
    my	$code = shift;
    my	$err_string = shift;

    print "NMC_ErrInfo: " . "$err_string" . "\n";
    print "NMC_STATUS: " . "$code"."\n";

}

sub getopts {
    local($argumentative) = @_;
    local(@args,$_,$first,$rest);
    local($errs) = 0;
    local($[) = 0;

    @args = split( / */, $argumentative );
    while(@ARGV && ($_ = $ARGV[0]) =~ /^-(.)(.*)/) {
        ($first,$rest) = ($1,$2);
        $pos = index($argumentative,$first);
        if($pos >= $[) {
            if($args[$pos+1] eq ':') {
                shift(@ARGV);
                if($rest eq '') {
                    ++$errs unless @ARGV;
                    $rest = shift(@ARGV);
                }
                eval "\$opt_$first = \$rest;";
            }
            else {
                eval "\$opt_$first = 1";
                if($rest eq '') {
                    shift(@ARGV);
                }
                else {
                    $ARGV[0] = "-$rest";
                }
            }
        }
        else {
            print STDERR "Unknown option: $first\n";
            ++$errs;
            if($rest ne '') {
                $ARGV[0] = "-$rest";
            }
            else {
                shift(@ARGV);
            }
        }
    }
    $errs == 0;
}

