#!/usr/bin/perl -w
################################################################################
# Filename: ./src/plugins/ldap/bin/qrm-ldap-install
# 
# The contents of this file are subject to the Qlusters Public License
# Version 1.1 (the License); you may not use this file except in compliance
# with the License.
# You may obtain a copy of the License at
# http://www.openqrm.org/content/view/33/69/.
# 
# Software distributed under the License is distributed on an AS IS basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
# the specific language governing rights and limitations under the License.
# 
# The Original Code is openQRM.
# 
# The Initial Developer of the Original Code is Qlusters Corporation. Portions
# created by Qlusters Corporation are Copyright (C) 2003-2005. All Rights
# Reserved.
# 
# Contributor(s):
# 
# Description:
# 
# Comments:
################################################################################
# $Id: qrm-ldap-install,v 1.2 2005/12/27 13:00:55 ittayd Exp $
# This script will convert an existing QRM installation to be authenticated
# via LDAP.
# This has been changed for 2.1 to remove the user add

use strict;
use File::Copy;
use Getopt::Std;
use File::Basename;
use Switch;
$|=1;

# These vars all come from the config file
my ($login_config, $search_start, $search_stop, $template_prefix, $template_postfix, $vpre, $vpost, $vcpre, $vcpost, %ldap_params);

# See qrm_ldap-install.cfg for more details
# %ldap_params is a hash of arrays keyed by parameter name.
# These are the array indices.
my $idx_used=0;    # Whether this parameter is used
my $idx_prompt=1;  # If we use the default or prompt for it
my $idx_default=2; # The default value for the parameter
my $idx_desc=3;    # The description of the parameter (mostly for prompting)

my $dirname=dirname $0;
my $config=$dirname . "/../etc/qrm_ldap-install-2.1.cfg";
my $qrm_cli="qrm-cli";

my $abs_config;
my $replace;
my $new_config;
my $verbose=0;

$Getopt::Std::STANDARD_HELP_VERSION="1"; # keep -w happy (TODO find correct way)
$Getopt::Std::STANDARD_HELP_VERSION="1";  
our($opt_c, $opt_h, $opt_v);
my $qrm_base=$ENV{'QRM_SERVER_BASE_DIR'};


# --------------------------------------------------------------------------------
# usage
# ----------------------
sub usage {
	print "usage: $0 [-c {config file}] [-h] [-v]\n";
	print "\t-h is help, and -v is verbose\n";
	print "\tThis will convert a QRM isntallation to authenticate via LDAP\n";
	exit 1;

}

# --------------------------------------------------------------------------------
# read_config
# ----------------------
sub read_config {
	my $lconfig=shift(@_);
	my @config;
	#read in config file
	if ( -r $lconfig ) {
		open(CONFIG, "<$lconfig") || die "Can't open config file: $lconfig";
		@config = <CONFIG>;
		close(CONFIG);
		if (!@config) {
			print "Empty or bad config file ($lconfig), exiting now...\n";
			exit 1;
		}
		eval("@config");
		die "$@\nError with config file" if $@;
	} else {
		print "Can't open config file: $lconfig\nExiting now...\n";
		exit 1;
	}

}

# --------------------------------------------------------------------------------
# get_abs_config
# ----------------------
sub get_abs_config {
	# get the absolute login-config file	
	my $found=0;
	my $qrm_base;
	while(!$found) {
		print "\nPlease enter the QRM base directory:\n";
		print " (for example /usr or /opt)\n";
		$qrm_base=<>;
		chomp($qrm_base);

		$abs_config=$qrm_base . "/" . $login_config;
		if( ! -w $abs_config ) {	
			print "Can't find or write to file $abs_config\n";
			print "Please try again\n\n"
		} else {
			$found=1;
		}
	}
	return $abs_config;
}

# --------------------------------------------------------------------------------
# backup
# ----------------------
sub backup { 
	my $lconfig=shift(@_);
	my $backup=$lconfig . ".ldap-bak_" . time;
	copy($lconfig, $backup) || die "ERROR can't copy file $lconfig";
	print "\nNotice: Backed up file \n  \"$lconfig\" \n\tto \n  \"$backup\"\n\n";
}

# --------------------------------------------------------------------------------
# create_user
# ----------------------
sub create_user { 
	my ($ldap_uid, $su, $supass, $cli, $action, $return);
	my $continue=1;

	# Check for qrm_cli so that we can add a user
	$qrm_cli=`which $qrm_cli`;
	chomp($qrm_cli);
	if($qrm_cli eq "") {
		print "Sorry, I can't find qrm-cli in your path, can't add user...\n";
		return 1;
	}

	while	($continue==1) {
		$ldap_uid=""; $su=""; $supass=""; 
		print "\nWe need to associate to a user in LDAP with super user so you can manage\n";
		print "user permissions in the future.  What user should this be?\n";
		print "(or you can type exactly \'exit\' to exit):\n";

		while($ldap_uid eq "") {
			$ldap_uid=<>;
			chomp($ldap_uid);
		}
		if($ldap_uid eq "exit") {
			print "Exiting now...\n";
			exit 1;
		}

		while($su eq "") {
			print "What is the name of the current super user (qrm by default): ";
			$su=<>;
			chomp($su);
		}
		while($supass eq "") {
			print "What is the password of the current super user: ";
			$supass=<>;
			chomp($supass);
		}
	
		$cli="$qrm_cli user add -u $su -p $supass -uu $ldap_uid -up \"null\" -r \"super user\"";
		$return=system($cli);

		if($return==0) {
			print "User added successfully, and associated to \"super user\"\n";
			return 0;
		}
		$action="";
		while($action eq "") {
			print "Adding the user to the local database failed, would you like to continue?\n";
			print "\t a) Abort this action, but continue\n";
			print "\t r) Retry this action\n";
			print "\t f) Fail (exit)\n";
			$action=<>;	
			$action=~s/[^\w]//;
			chomp($action);

			# for some reason switch.pm has a utf8 bug in it, so doing this instead
			if($action=~/[aA]/) {
				# cancel this loop
				print "Aborting user add\n\n"; $continue=0; 

			} elsif($action=~/[rR]/) { 
				# retry the whole loop	
				print "Retrying user add\n\n"; $continue=1; 

			} elsif($action=~/[fF]/) { 
				print "Exiting now...\n"; exit 1; 

			} else { 
				# retry just getting action
				print "Try again\n\n"; $action=""; 
			}   
		}

	}
}

# --------------------------------------------------------------------------------
# generate_config
# ----------------------
sub generate_config {
	# Assemble replacement
	my $lreplace=$template_prefix;
	my $found;
	my ($value, $used, $prompt, $default, $desc, $name);
	foreach my $key (keys %ldap_params) {

		# Setup local vars for readability
		$used=    $ldap_params{"$key"}[$idx_used];
		$prompt=  $ldap_params{"$key"}[$idx_prompt];
		$default= $ldap_params{"$key"}[$idx_default];
		$desc=    $ldap_params{"$key"}[$idx_desc];
		$name=    $key;
		$found=0;

		# Continue prompting while the field 
		#		(is used) and (we want to prompt for it)
		#		and (hasn't been found)
		while(($used) && ($prompt) && (!$found)) {
			print "Please enter " . $desc . ":\n";

			$value=<>;
			chomp($value);
			if($value ne "") {
				# put together the module line
				($verbose) && print "\n** Setting " . $name . " to \"$value\" in config\n\n";
				$lreplace .= $vpre . $name . "=\"\$QRM_LDAP_" . uc($name) . $vpost;	
				print `. $qrm_base/qrm/include/qrm-setup-functions; qrm_set_ini_value $qrm_base/qrm/plugins/ldap/etc/ldap.ini config $name $value`;
				$found=1;
				$value="";
			} 
		}

		# Setup the default when prompting is turned off
		if(($used) && (!$prompt)) {
			$lreplace .= $vpre . $name . "=\"" . $default . $vpost;
		}
	}
	# Finish up the replacement string
	$lreplace .= $template_postfix;
	
	return $lreplace;
}

# --------------------------------------------------------------------------------
# new_config
# ----------------------
sub new_config {

	# actually replace
	undef $/; #slurp mode
	open(CONFIG, "<$abs_config") || die "Can't open $abs_config for editing";
	$new_config=<CONFIG>;
	close(CONFIG) || die "Can't close $abs_config\n";

  if ($new_config=~
    s|
       ^\s*            # Grab the leading spaces
       ($search_start) # This is the start of the string to replace
       .*?             # Grab everything in the middle (non-greedy)
       ($search_stop)  # The end of the string to replace
     |$1
       $replace\n$2
     |xms) {
		print "Successfully replaced authentication section\n";
	} else {
		print "Couldn't find config section to replace, please check your config file\n";
		print "Not writing config, and exiting now...\n";
		exit 1;
	}

	$/="\n"; # end slurp mode

	return $new_config;
}

# --------------------------------------------------------------------------------
# write_config
# ----------------------
sub write_config {
	my $lnconfig=shift(@_);
	# Double check whether you want to write this config
	my $answer="";
	while(($answer !~ /^yes$/i) && ($answer !~ /^no$/i)) {
		print "Are you sure you want to write this config? (yes|no) \n";
		$answer=<>;
		chomp($answer);
	}

	# write new file
	if ($answer =~ /^yes$/i) {
		print "Writing $abs_config\n";
		open(CONFIG, ">$abs_config") || die "Can't open $abs_config for editing\n";
		print CONFIG $lnconfig;
		close(CONFIG) || die "Can't close $abs_config\n";
	} else {
		print "OK, exiting now...\n";
		exit 1;
	}
}

# ################################################################################
# --------------------------------------------------------------------------------
# Main
# --------------------------------------------------------------------------------
# ################################################################################

# Get config option if defined
getopts ("c:hv");
$config=$opt_c if(defined $opt_c);
$verbose=$opt_v if(defined $opt_v);
usage() unless (!defined($opt_h));

# Get the configuration for this script
read_config($config);

# get the full filename of the login configuration
$abs_config=$qrm_base . "/" . $login_config;

# Create backup
backup($abs_config);

# Create new user so ldap has a "super user"
# commenting out for 2.1 for now
#create_user;

# Generate the replacement chunk
$replace=generate_config();

# Get the entire new file
$new_config=new_config();

# Actually write the file
write_config($new_config);

print "Done.\n";
exit 0;

# vim:ts=2:sw=2:sts=0
