#!/bin/sh
#
# Copyright (c) 1999-2008 Parallels
# All rights reserved
#

#
# Plesk script
#


# Migration manager tables will be managed by plesk


#admin

set_admin_params()
{

	ADMIN_ROOT=$PRODUCT_ROOT_D/admin

	UTILS_DIR=$ADMIN_ROOT/bin

	admin_user="${product}adm"
	admin_UID=8444
	admin_group="${product}adm"
	admin_GID=8444

	admin_httpsd_conf="$ADMIN_ROOT/conf/httpsd.conf"
	ADMIN_CERT="$ADMIN_ROOT/conf/httpsd.pem"

	admin_pid_file=$ADMIN_ROOT/logs/httpsd.pid
	admin_lock_file=$ADMIN_ROOT/logs/httpsd.lock

	define_start_script
}

generate_default_certificate()
{
	# Currently I have no will to accurately rewrite the stuff below
	# so I just add support for (optional) file parameter. Actually
	# one need to accurately handle temporary files, directory creation
	# etc. Probably next time...
	local cert_file

	cert_file="${certificate_file}"
	if [ -s "$cert_file" ]; then
		p_echo "default certificate already exists"
		return
	fi

	# This var also can safely be made local. It's not used outside
	local OPENSSL_CNF is_temp_cnf rc

	OPENSSL_CNF=${PRODUCT_ROOT_D}/admin/conf/openssl.cnf
	is_temp_cnf=0

	if [ ! -f "${OPENSSL_CNF}" ]; then
		# Well, base psa package isn't yet installed. 
		# let's form a temporary config file
		OPENSSL_CNF=$(mktemp /tmp/openssl.cnf.XXXXXX)
		[ $? != 0 ] && die "Unable to create temporary file"
		cat >>${OPENSSL_CNF} <<EOF
[ req ]
attributes=req_attributes
distinguished_name=req_distinguished_name

[ req_attributes ]
challengePassword               = A challenge password
unstructuredName                = An optional company name

[ req_distinguished_name ]
countryName             = Country Name
stateOrProvinceName     = State or Province Name
localityName            = Locality Name
organizationName        = Organisation Name
organizationalUnitName  = Organization Unit Name
commonName              = Common Name
emailAddress            = Email Address
EOF
		is_temp_cnf=1
	fi

	echo "US
Virginia
Herndon
Parallels
Parallels Panel
Parallels Panel
info@parallels.com


" | openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
	-config ${OPENSSL_CNF} -set_serial `date +%s` -keyout "${cert_file}_" \
	-out "${cert_file}_" >> $product_log 2>&1

	# preserve exit code
	rc=$?

	if [ $rc -eq 0 ]; then
		cat "${cert_file}_" | sed -e 's/^\(-----END.*\)/\1\
/' > $cert_file
		set_ac 0 0 0400 "${cert_file}"
	fi
	# cleanup temporary files
	rm -f "${cert_file}_" ||:
	if [ "x$is_temp_cnf" = "x1" ]; then
		rm -f ${OPENSSL_CNF} ||:
	fi
	return $rc
}
set_apache_params()
{
	apache_user="wwwrun"
	apache_UID=80
	apache_group="www"
	apache_GID=80

	user_apxs="/usr/sbin/apxs2"

	set_apache_params_linux

	apache_service="$apache_service_name"

	apache_httpd_conf="$HTTPD_CONF_D/httpd.conf"
	apache_httpd_conf2="$HTTPD_CONF_D/httpd2.conf"
	apache_httpd_conf_in="$HTTPD_CONF_D/httpd.conf.in"

	apache_httpd_include="$HTTPD_INCLUDE_D/zz010_psa_httpd.conf"

	APACHE_CERT="$HTTPD_CONF_D/httpd.pem"
	APACHE_ROOT="/usr"

	min_suexec_UID=10000
	max_suexec_UID=16000
	min_suexec_GID=$min_suexec_UID
	max_suexec_GID=$max_suexec_UID

	suexec_storage=/usr/local/psa/suexec
	suexec=/usr/sbin/suexec2
	suexec_dir=/usr/sbin
	suexec_file=suexec2

	rpm_httpd_bin=/usr/sbin/httpd
}

set_apache_params_linux()
{
	apache_pid_file="$APACHE_ROOT/logs/httpd.pid"
	apache_lock_file="$APACHE_ROOT/logs/httpd.lock"
	product_lock_file="$HTTPD_CONF_D/cnf.lock"
	apache_service_name="apache2"

	apache_modules_d="/usr/lib/apache2"
}

# mode: shell-script

remove_tmp_state()
{
	if [ -d "/tmp/.state" ]; then
		rm -Rf "/tmp/.state" >> $product_log 2>&1
	fi
}

true apache_status_linux_debian apache_stop_BSD

apache_status_linux_debian()
{
	get_pid "/usr/sbin/apache2" false
	local pid=$common_var
	if test "$pid" -ne 1; then
# running
		return 0
	fi
	return 1
}

apache_stop_BSD()
{
	local apache_script

	if [ "$std_to_pkg" -ne 0 ]; then
		apache_script="$PRODUCT_ROOT_D/rc.d/httpd"
	else
		apache_script="$PRODUCT_RC_D/$apache_service_name"
	fi

	$apache_script stop 2>/dev/null
}

defer_apache_reconfiguration()
{
	apache_need_reconfiguration="yes"
}

read_apsc_connection_param_db()
{
	local param="$1"
	db_select "SELECT val FROM misc WHERE param like 'aps_$param'"
	echo "$db_select_output"
}

read_apsc_connection_params_db()
{
	# Warning : password can be encrypted.
	apsc_db_name=`read_apsc_connection_param_db "database"`
	apsc_db_user=`read_apsc_connection_param_db "login"`
	apsc_db_passwd=`read_apsc_connection_param_db "password"`
	apsc_db_host=`read_apsc_connection_param_db "host"`
}

save_apsc_connection_params_db()
{
	local register_script="$PRODUCT_ROOT_D/admin/plib/scripts/register_apsc_database.php"
	[ -f "$register_script" ] || die 'can not find "register_apsc_database.php"'

	sw_engine_pleskrun "$register_script" --register 		-host 'localhost' 		-port 3306 		-database "$apsc_db_name" 		-login "$apsc_db_user" 		-password "$apsc_db_passwd" >> "$product_log" 2>&1
}

check_apsc_installed()
{
	local db_name=`read_apsc_connection_param_db "database"`

	[ -n "$db_name" ] || return 1
	db_test_database "$db_name"
}

pbm_create_certificate()
{
	local inten="generate certificate for backup signing"

	[ -x "$PRODUCT_ROOT_D/admin/sbin/backup_sign" ] || return 0

	if db_select "select val from misc where param='bu_cert_id'" && [ -n "$db_select_output"  ]; then
#	Nothing to be done
		return
	fi

	echo_try $inten

	if $PRODUCT_ROOT_D/admin/sbin/backup_sign generate >> $product_log 2>&1; then
		warn "backup certificate generation"
		return 1
	fi

	suc
}

install_cron_backup()
{
	[ ! -s "/etc/cron.d/plesk-backup-manager" ] || return
	minutes=`get_random_number 15`

	cat >/etc/cron.d/plesk-backup-manager <<-EOF
$minutes,`expr $minutes + 15`,`expr $minutes + 30`,`expr $minutes + 45`	*	*	*	*	root [ -x $PRODUCT_ROOT_D/admin/sbin/backupmng ] && $PRODUCT_ROOT_D/admin/sbin/backupmng >/dev/null 2>&1
EOF
}

remove_cron_backup()
{
	rm -f "/etc/cron.d/plesk-backup-manager"
}

# import certificate into database when installing
import_default_certificate()
{
	db_select "SELECT val FROM misc WHERE param = 'default_certificate_id'"

	local default_certificate_id="$db_select_output"

	if [ -z "$default_certificate_id" ]; then
# Update misc table if needed
		echo_try "import default certificate"
		import_certificate "$certificate_file"  "default certificate"

		db_do "REPLACE INTO misc set param='default_certificate_id', val='$last_certificate_id'"
		default_certificate_id="$last_certificate_id"
		suc
	fi

	db_select "SELECT val FROM misc WHERE param = 'cert_rep_id'"
	local admin_repository_id="$db_select_output"

	if [ -z "$admin_repository_id" ]; then
		echo_try "push default certificate into repository"
		db_select "REPLACE INTO Repository SET component_id='${default_certificate_id}';SELECT LAST_INSERT_ID();"
		admin_repository_id="$db_select_output"
		db_do "REPLACE INTO misc set param='cert_rep_id', val='${admin_repository_id}'"
	else
#	simple certificate insertion to repository
		db_do "REPLACE INTO Repository SET rep_id='${admin_repository_id}', component_id='${default_certificate_id}'"
	fi
}

# import certificate from a file to certificates table
# $1 - certoificate file path
# $2 - short description of certificate
# last_certificate_id variable will contain its identifier
import_certificate()
{
	local certificate_file certificate_comment inten

	certificate_file=$1
	certificate_comment=$2

	cert_pub_val=`cat ${certificate_file} |
		awk 'BEGIN { state=0 }
		{
			if (state == 0) {
				if (index($0, "-BEGIN CERTIFICATE-") != 0) state = 1;
			};
			if (state == 1) {
				print $0;
				if (index($0, "-END CERTIFICATE-") != 0) state = 2;
			}
		}' |
		perl -n -e 's/([^ A-Za-z0-9])/"%" . sprintf("%02X", unpack("C", $1))/ge; s/ /\+/g; print $_;'`

	cert_priv_val=`cat ${certificate_file} |
		awk 'BEGIN { state=0 }
		{
			if (state == 0) {
				if ((index($0, "-BEGIN ") != 0) &&
					(index($0, " PRIVATE KEY-") != 0)) state = 1;
			};

			if (state == 1) {
				print $0;
				if ((index($0, "-END ") != 0) &&
					(index($0, " PRIVATE KEY-") != 0)) state = 2;
			}
		}' |
		perl -n -e 's/([^ A-Za-z0-9])/"%" . sprintf("%02X", unpack("C", $1))/ge; s/ /\+/g; print $_;'`

	if [ ! -d "${PRODUCT_ROOT_D}"/var/certificates ]; then
		inten="creating directory for certificates"
		mkdir -p "${PRODUCT_ROOT_D}"/var/certificates || die ${inten}
		chown root:0 "${PRODUCT_ROOT_D}"/var/certificates || die ${inten}
		chmod 500 "${PRODUCT_ROOT_D}"/var/certificates || die ${inten}
	fi

	# copy certificate file to file repository
	newcertfile=`mktemp "${PRODUCT_ROOT_D}"/var/certificates/certXXXXXXX`

	cp "${certificate_file}" "${newcertfile}"  || die "place certificate to its directory"
	chown root:0 "${newcertfile}"
	chmod 400 "${newcertfile}"

	newcertfile=`basename ${newcertfile}`
	db_select "INSERT INTO certificates (pvt_key, cert, name, ca_cert, csr, cert_file, ca_file)
		VALUES ('${cert_priv_val}', '${cert_pub_val}', '${certificate_comment}', '', '',
			'${newcertfile}', '');
		SELECT LAST_INSERT_ID()"

	last_certificate_id="$db_select_output"
}


#courier-imap

set_courier_imap_params()
{
	COURIERIMAP_CONFDIR="/etc/courier-imap"
	IMAPD_CERT="/usr/share/courier-imap/imapd.pem"
	POP3D_CERT="/usr/share/courier-imap/pop3d.pem"

	courier_service="courier-imap"
}
# vim:syntax=sh

install_cron_somely()
{
	install_cron_somely_perform
}

remove_cron_somely()
{
	remove_cron_somely_perform
}

set_cron_params()
{
    CRON_SOMELY_DIR_PREFIX=/etc/psa/plesk-cron
}

install_cron_somely_perform()
{
	set_cron_params
	set_cron_somely_params

	daily_minute=`get_random_number 60`
	weekly_minute=`get_random_number 60`
	monthly_minute=`get_random_number 60`
	daily_hour=`get_random_number 6`
	weekly_hour=`get_random_number 7`
	monthly_hour=`get_random_number 7`

	# monthly must be after daily
	if [ $monthly_hour -lt $daily_hour ]; then
		swap=$daily_hour
		daily_hour=$monthly_hour
		monthly_hour=$swap
	elif [ $monthly_hour -eq $daily_hour ]; then
		monthly_hour=$(($monthly_hour + 1))
	fi

	install_cron_somely_entry "$daily_minute $daily_hour * * *" daily
	install_cron_somely_entry "$weekly_minute $weekly_hour * * 7" weekly
	install_cron_somely_entry "$monthly_minute $monthly_hour 1 * *" monthly
}

remove_cron_somely_perform()
{
	set_cron_somely_params
	remove_from_crontab "$cron_somely_run_parts"
}

set_cron_somely_params()
{
	cron_somely_run_parts="$PRODUCT_ROOT_D/bin/run-parts.sh"
}

install_cron_somely_entry()
{
	add_to_crontab "$1 $cron_somely_run_parts $CRON_SOMELY_DIR_PREFIX.$2" \
		"$cron_somely_run_parts" "$CRON_SOMELY_DIR_PREFIX.$2" "root" "add $2 task"
}

add_to_crontab()
{
	local cron_string egrep_programm egrep_additional inten

	cron_string=$1
	egrep_programm=$2
	egrep_additional=$3
	user=$4
	inten=$5
	
	if [ "X$DEMO_VERSION" = "Xyes" ]; then 
		return 0;
	fi

	p_echo
	p_echo "===> Updating crontab..."
	
	$crontab -l 2>/dev/null > /tmp/crontab.${product}
	egrep "$egrep_programm" /tmp/crontab.${product} | egrep "$egrep_additional" | egrep -v "^#" > /dev/null 2>&1
	case "$?" in
		0)
			p_echo "$inten is already performed by cron"
			;;
		1)
			echo_try $inten
			echo "$1" >> /tmp/crontab.${product} || die $inten
			$crontab /tmp/crontab.${product} && suc || die $inten
			;;
		*)
			err
			;;
	esac

	rm -f /tmp/crontab.${product} || die
}

remove_from_crontab()
{
	program=$1

	echo_try "remove $program from crontab"

	cron_file=`mktemp /tmp/cronXXXXXX`
	$crontab -l 2>/dev/null | egrep -v "^[^#].*$program" > $cron_file
	$crontab $cron_file

	rm -f $cron_file
	suc
}

license_show_request()
{
	inten="shedule license displaying for admin login"
	echo_try $inten

	query="DELETE FROM misc where param='not_showLicense'"
	echo $query | mysql || die "$inten"

	suc
}

# db_test test_query awk_script
# Runs test_query and processes it with awk_script. If the output is
# not empty, return 0, otherwise return 1. Hint: supply '1' for
# awk_script to test just for the presence of any output.
db_test()
{
	local any_db=
	eval `sh_get_args '--any-db) any_db=yes;;'`

	local test_query="$1"
	local awk_script="$2"

	if [ -n "$any_db" ]; then
		local output="`mysql_raw_anydb -e \"$test_query\" 2>>\"$product_log\"`"
	else
		local output="`mysql_raw -e \"$test_query\" 2>>\"$product_log\"`"
	fi
	local status=$?
	if [ "$status" -ne 0 ]; then
		p_echo "$output"
		die "run the following SQL query: $1"
	fi

	echo -n "$output" | awk -F '\t' -- "$awk_script" | test `wc -l` -ne 0
}

# db_do [--inten <inten>] query
# Runs query. If it fails, die
# the inten string describes the query reason (to make finding the bug simpler)
db_do()
{
	local desc="execute SQL query"
	eval `sh_get_args '--inten) desc=" (to $2)"; shift;;'`
	if [ "$db_fix_check_stage" = "yes" ]; then
		return
	fi

	local query="$1"

	mysql -e "$query" >>"$product_log" 2>&1 || die "$desc, the query was: $query"
}

# db_select <query>
# runs <query> via mysql_raw
# writes output to db_select_output
# if query fails, output errors and return 1
db_select()
{
	local desc="execute SQL query"
	local query="$1"
	local output="`mysql_raw -e \"$query\" 2>>\"$product_log\"`"
	local status="$?"
	if [ "$status" -ne "0" ]; then
		p_echo "$output"
		die "run the following SQL query: $query"
	fi

	db_select_output="$output"
	return 0
}

# db_test_database database
# Returns 0 if the database exists
db_test_database()
{
	local database="$1"

	local mysql_db_name="mysql"
	db_test "SHOW DATABASES" "\$1 == \"$database\""
}

# db_test_table table
# Returns 0 if the table exists
db_test_table()
{
	local table="$1"

	db_test "SHOW TABLES LIKE '$table'" 1
}

proftpd_super_server_config()
{
	local action="$1"

	case "$superserver" in
	    inetd)
		    ftp_rec="ftp stream tcp nowait root $PROFTPD_ROOT/sbin/proftpd proftpd -c $PROFTPD_ETC_D/proftpd.conf"
		    ;;
	    xinetd)
		    ftp_rec="service ftp
{
	socket_type		= stream
	protocol		= tcp
	wait			= no
	disable			= no
	user			= root
	instances		= UNLIMITED
	server			= $PROFTPD_ROOT/sbin/proftpd
	server_args		= -c $PROFTPD_ETC_D/proftpd.conf
}"
		    ;;
	    *)
		    die "Super server name unknown"
		    ;;
	esac

	super_server_action "$action" ftp "$ftp_rec"
}
# Usage:  pleskrc <service> <action>
pleskrc()
{
	[ 2 -le $# ] || die "Not enough arguments"

	local service_name=$1
	local action=$2
	local ret=0
	local inten
	local service_script
	shift
	shift

	# Now check redefined functions
	if test "$machine" = "linux" && is_function "${service_name}_${action}_${machine}_${linux_distr}"; then
		"${service_name}_${action}_${machine}_${linux_distr}" $@
		return $?
	elif is_function "${service_name}_${action}_${machine}"; then
		"${service_name}_${action}_${machine}" $@
		return $?
	elif is_function "${service_name}_${action}"; then
		"${service_name}_${action}" $@
		return $?
	fi

	# Not redefined - call default action
	eval "service=\$${service_name}_service"
	[ -n "$service" ] || die "$action $service_name service (Empty service name for '$service_name')"

	inten="$action service $service"
	[ "$action" = "status" -o "$action" = "exists" ] || echo_try "$inten"

	local scr_path=${SYSTEM_RC_D}/${service}
	if [ -x ${scr_path} ]; then
        service_script=${scr_path}
    fi

	if [ "$action" = "exists" ]; then 
		[ -n "$service_script" ] && return 0 || return 1
	else
		if [ -z "$service_script" ]; then
            warn "Unable to ${inten} - control script is not exist or not executable"
            return 1
        fi
	fi


	if [ -x "/usr/sbin/invoke-rc.d" ]; then
		action_cmd="/usr/sbin/invoke-rc.d $service"
	elif [ -x "/sbin/service" ]; then
		action_cmd="/sbin/service $service"
	elif [ -n ${service_script} ]; then
		action_cmd="$service_script"
	fi


	case "$action" in
		start)
			pleskrc $service_name status || $action_cmd $action $@ >>$product_log 2>&1
			;;
		stop)
			if pleskrc $service_name status; then
				$action_cmd $action $@
			else
				true
			fi
		    ;;
		restart)
			if pleskrc $service_name status; then 
				$action_cmd "restart" $@
			else 
				$action_cmd "start" $@
			fi
		    ;;
		reload)
		    if pleskrc $service_name status; then
				$action_cmd "reload" $@
			else
				true
			fi
		    ;;
		status)
		    $action_cmd "status"
		    ;;
	    *)
		    $action_cmd $action $@ 
		    ;;
	esac >> $product_log 2>&1

	ret="$?"
	if [ "$action" != "status" ]; then
		[ "$ret" -eq 0 ] && suc || warn $inten
	fi

	return $ret
}

is_function()
{
	local type_output="`type -t \"$1\" 2>/dev/null`"
	case "$type_output" in
		*function)
			return 0
		;;
		*)
			return 1
		;;
	esac
}


# echo message to product log and console (always visible)
pp_echo()
{
    if [ -n "$product_log" ] ; then
        echo "$@" >> "$product_log" 2>&1
    fi
    echo "$@"
}

# echo message to product log, unless debug
p_echo()
{
    if [ -n "$PLESK_INSTALLER_DEBUG" -o -n "$PLESK_INSTALLER_VERBOSE" -o -z "$product_log" ] ; then
        echo "$@"
    else
        echo "$@" >> "$product_log" 2>&1
    fi
}

# echo message to product log without new line, unless debug
pnnl_echo()
{
    if [ -n "$PLESK_INSTALLER_DEBUG" -o -n "$PLESK_INSTALLER_VERBOSE" -o -z "$product_log" ] ; then
        echo -n "$*"
    else
        echo -n "$*" >> "$product_log" 2>&1
    fi
}

die()
{
	PACKAGE_SCRIPT_FAILED="$*"

	if [ "X$trigger_uninstall" != "X1" ]; then
		printf "\a\a"
		report_problem \
			"ERROR while trying to $*" \
			"Check the error reason(see log file: ${product_log}), fix and try again"
	fi

	smart_undo_install

	selinux_close

	exit 1
}

warn()
{
local inten
inten="$1"
p_echo
p_echo "WARNING!"
pnnl_echo "Some problems are found during $inten"
p_echo "(see log file: ${product_log})"
p_echo
p_echo "Continue..."
p_echo

product_log_tail | send_error_report "Warning: $inten"

[ -n "$PLESK_INSTALLER_DEBUG" -o -n "$PLESK_INSTALLER_VERBOSE" ] || \
	product_log_tail
}

# Use this function to report failed actions.
# Typical report should contain
# - reason or problem description (example: file copying failed)
# - how to resolve or investigate problem (example: check file permissions, free disk space)
# - how to re-run action (example: perform specific command, restart bootstrapper script, run installation again)
report_problem()
{
	p_echo
	if [ $problems_occured -eq 0 ]; then
		echo "***** $process problem report *****" >> "$product_problems_log" 2>&1
	fi
	for problem_message in "$@"; do
		p_echo "$problem_message"
		echo "$problem_message" >> "$product_problems_log" 2>&1
	done
	p_echo

	product_log_tail | send_error_report "Problem: $@"

	[ -n "$PLESK_INSTALLER_DEBUG" -o -n "$PLESK_INSTALLER_VERBOSE" ] || \
		product_log_tail

	problems_occured=1
}

echo_try()
{
	msg="$*"
	pnnl_echo " Trying to $msg... "
}

suc()
{
	p_echo "done"
}

send_error_report()
{
	{
		echo $@
		echo ""
		if [ -n "$error_report_context" ]; then
			echo "Context: $error_report_context"
			echo ""
		fi
		test -t 0 || cat -
	} | $PRODUCT_ROOT_D/admin/bin/send-error-report "install" >/dev/null 2>&1
}

set_error_report_context()
{
	error_report_context="$@"
}

# vim:syntax=sh

mk_backup()
{
	target="$1"
	dup="$2"
	opts="$3"

	if [ -L "$target" ]; then
		rm "$target"
	elif [ -$opts "$target" ]; then
		if [ ! -$opts "$target.$product_suffo" ]; then
			case "$dup" in
				mv)
					mv -f $target $target.$product_suffo || die "mv -f $target $target.$product_suff"
					;;
				cp)
					cp -fp $target $target.$product_suffo || die "cp -fp $target $target.$product_suff"
					;;
				*)
					p_echo " mk_backup: wrong option -- must be 'cp' or 'mv'"
					die "mk_backup"
					;;
			esac
		else
			case "$dup" in
				mv)
					mv -f $target $target.$product_suff || die "mv -f $target $target.$product_suff"
					;;
				cp)
					cp -fp $target $target.$product_suff || die "cp -fp $target $target.$product_suff"
					;;
				*)
					p_echo " mk_backup: wrong option -- must be 'cp' or 'mv'"
					die "mk_backup"
					;;
			esac
		fi
	else
		case "$opts" in
			f|d)
				;;
			*)
				p_echo " mk_backup: wrong option -- must be 'f' or 'd'"
				die "mk_backup"
				;;
		esac
	fi
}

# accumulates chown and chmod
set_ac()
{
	u_owner="$1"
	g_owner="$2"
	perms="$3"
	node="$4"

	chown $u_owner:$g_owner $node || die "chown $u_owner:$g_owner $node"
	chmod $perms $node || die "chmod $perms $node"
}

detect_vz()         
{                   
    local vzcheck_file
        
    PLESK_VZ=0
    vzcheck_file="/proc/self/status"
                    
    if [ ! -f ${vzcheck_file} ]; then
        return 1; 
    fi              
                    
    grep -q -E '^envID\:[[:space:]]*([[:digit:]]+)$' < ${vzcheck_file} >/dev/null 2>&1
                    
    if [ $? -eq 0 ]; then
        PLESK_VZ=1  
        return 0;
    fi      
    return 1;
}       

call_optional_function()
{
	export LANG=C LC_MESSAGES=C LC_ALL=C
	local type_output="`type \"$1\" 2>/dev/null | head -n 1`"
	case "$type_output" in
		*function)
			"$@"
			;;
		*)
			return 0
			;;
	esac
}

sh_get_args()
{
	echo 'while true; do case "$1" in '"$1"'*) break;; esac; shift; done'
}

### the function similar to awk -F'$fs' 'print $N'
get_narg_fs()
{
	local OLD_IFS="$IFS"
	IFS="$2"
	get_narg $3 $1
	IFS="$OLD_IFS"
}

get_narg()
{
	shift $1 2>/dev/null || return
	echo $1
}

get_random_number()
{
	perl -e '
	 my $res = int(rand($ARGV[0]));
	 if (exists $ARGV[1]) {
	  $res = $res + $ARGV[1];
	 }
	 print $res;
	' "$@"
}

get_random_string()
{
	local str_length="$1"
	local str_symbols="$2"
	if [ -x "$PRODUCT_ROOT_D/admin/sbin/random_str" -a -z "$str_symbols" ]; then
		"$PRODUCT_ROOT_D/admin/sbin/random_str" "$str_length"
	else
		# random_str utility may be unavailable in pre phase
		if [ -z "$str_length" ]; then
			str_length="14"
		fi
		if [ -z "$str_symbols" ]; then
			str_symbols="A-Za-z0-9_"
		fi

		< /dev/urandom tr -dc "$str_symbols" 2>/dev/null | head -c "$str_length" 2>/dev/null
	fi
}

sequence()
{
	if type seq >/dev/null 2>&1; then
		seq $*
	elif type jot >/dev/null 2>&1; then
		jot $*
	else
		die "Unable to find seq or jot command"
	fi
}

get_ini_conf_var()
{
	local conf="$1"
	local section="$2"
	local param="$3"

	[ -n "$conf" -a -n "$param" ] || die "get_ini_conf_var(): required parameters missing"

	local section_empty=0
	[ -n "$section" ] || section_empty=1

	perl -n -e 'BEGIN { $insect='$section_empty' }
				next if (/^\s*;/);
				$insect=0 if (/^\s*\[.*\]/);
				$insect=1 if (/^\s*\['$section'\]/);
				$val = $2, $val =~ s/\s+$//, print $val . "\n" 
					if ($insect && /^\s*('$param')\s*=\s*([^;\n]*)(;.*)?$/);' $conf | head -n 1
}

set_ini_conf_var()
{
	local conf="$1"
	local section="$2"
	local param="$3"
	local value="$4"

	[ -n "$conf" -a -n "$param" ] || die "set_ini_conf_var(): required parameters missing"

	local section_empty=0
	[ -n "$section" ] || section_empty=1

	perl -n -e 'BEGIN { $insect='$section_empty' }
				if (not /^\s*;/) {
					$insect=0 if (/^\s*\[.*\]/);
					$insect=1 if (/^\s*\['$section'\]/);
					if ($insect && /^(\s*('$param')\s*=\s*)([^;\n]*)((;.*)?)$/) {
						$tail = $4; chomp($tail); $tail = "    " . $tail if ($tail);
						print $1 . "'$value'" . $tail . "\n";
						next;
					}
				}
				print $_;' $conf > $conf.tmp && 	cat $conf.tmp > $conf && rm -f $conf.tmp
}

sw_engine_pleskrun()
{
	if [ -x $PRODUCT_ROOT_D/bin/sw-engine-pleskrun ]; then
		$PRODUCT_ROOT_D/bin/sw-engine-pleskrun "$@"
	elif [ -x "/usr/bin/sw-engine" ]; then
		local args
		if [ -e "$PRODUCT_ROOT_D/admin/conf/php.ini" ]; then
			args="-c $PRODUCT_ROOT_D/admin/conf/php.ini"
		else
			args="-d psasem.semfile=\"$PRODUCT_ROOT_D/var/psasem.sem\""
		fi
		/usr/bin/sw-engine $args "$@"
	else
		echo "No Plesk PHP interpreter found"
		return 1
	fi
}

install_default_license_key()
{
	pnnl_echo "install default license key ..."

# key from 8.x?
	if 	db_test_table "key_history" && 		db_test "SELECT COUNT(*) FROM key_history WHERE filename = '/etc/psa/psa.key' LIMIT 1" '$1!="0"'; then
			p_echo "not needed, license from 8.x found"
			return;
	fi

# check OF-key
	if sw_engine_pleskrun -r 'exit(of_get_key_by_product("plesk-unix") === false ? 1 :0);'; then
			p_echo "not needed, license from 9.x found"
			return
	fi

	local dest_dir="/etc/sw/keys/keys"
	local key=plesk-default-key.xml

    [ ! -s "$dest_dir/$key" ] || return

    cp -f "${PRODUCT_ROOT_D}/tmp/$key" "$dest_dir/"
    chown root:swkey-data "$dest_dir/$key"
    chmod 0660 "$dest_dir/$key"
    suc
}
label_file_once()
{
	local _fname _mess _messLines _fileHead _tmpFile

	test $# -eq 2 || die 'label_file_once() not enough arguments'
	
	_fname="${1}"
	_mess="${2}"

	inten="add header to file ${_fname}"
	echo_try $inten

	test -f "${_fname}" || die "file ${_fname} does not exist"
    _messLines=`printf "${_mess}" | wc -l | awk '{print $NF}'`

	_tmpFile=`basename "${_fname}"`
	_tmpFile=`mktemp "/tmp/${_tmpFile}.XXXXXX"` || die "can not create temporary file"
	head -n ${_messLines} "${_fname}" > "${_tmpFile}"

	printf "${_mess}" | diff -q - "${_tmpFile}" 1>/dev/null
	if [ $? -eq 0 ]; then
		p_echo "file ${_fname} already contains required header"
		rm -f "${_tmpFile}"
		return
	fi
	rm -f "${_tmpFile}"

	# preserve permissions, not optimal, need to rework
	cp -p "${_fname}" "${_fname}.tmp"

	printf "${_mess}" | cat - "${_fname}" > "${_fname}.tmp"
	cp -f "${_fname}.tmp" "${_fname}"
	rm -f "${_fname}.tmp"
	p_echo "completed successfully"
}

superserver_reconfig()
{
    pleskrc superserver reload
}

configure_xinetd_compat()
{
	local inten="configure xinetd compatibility mode with $superserver"
	if [ "$linux_distr" = "debian" -o "$linux_distr" = "ubuntu" ]; then
		[ "$superserver_service" = "xinetd" ] || return 1
		[ -f "/etc/default/xinetd" ] || return 1
		grep -q 'XINETD_OPTS=.*-inetd_compat' /etc/default/xinetd && return 1
		echo_try $inten

		if ! grep -q '^\s*XINETD_OPTS' /etc/default/xinetd; then
			echo 'XINETD_OPTS="-inetd_compat"' >>/etc/default/xinetd
			suc
			return 0
		fi

		eval `grep '^\s*XINETD_OPTS' /etc/default/xinetd`
		XINETD_OPTS="$XINETD_OPTS -inetd_compat"
		local tmp_file=`mktemp /tmp/xinetdXXXXXX`
		sed -e "s/XINETD_OPTS.*/XINETD_OPTS=\"$XINETD_OPTS\"/g" /etc/default/xinetd > $tmp_file && mv -f $tmp_file /etc/default/xinetd
		suc
		return 0
	fi
	return 1
}


super_server_action()
{
    local in out
    local action="$1"
    local service="$2"
    local template="$3"

    inten="$action $service service record for $superserver_service daemon"

    case "$action" in
	remove) ;;
	register)
		[ -z "$template" ] && die "Template for super server $action was not defined"
		;;
	comment|disable)
		;; 
	configure)
		case "$superserver_mode" in
		    native)
			register_service $superserver_service defaults defaults
			;;
		    compat)
			configure_xinetd_compat && pleskrc superserver restart
			;;
		    *)
			die "Mode for $superserver_service was not defined"
			;;
		esac

		return 0
		;;
	*)
		die "Some arguments was not defined or defined incorrect for action with super server"
		;;
    esac 

    case "$superserver" in
	inetd)
		super_server_modify_inetd "$service" "$action" "$template"
		;;
	xinetd)
		super_server_modify_xinetd "$service" "$action" "$template"
		;;
	*)
		die "Unable to define super server type"
		;;	
    esac

    if [ $? -ne 0 ]; then
	die $inten 
    fi
}

super_server_modify_inetd()
{
	local service="$1"
	local action="$2"
	local template="$3"

	case "$action" in
		comment|disable)
			grep -q "^$service[[:space:]]" $superserver_conf || return 0
			sed -e "s|^$service|#$service|g" < "$superserver_conf" > "$superserver_conf.tmp" 			&& mv -f "$superserver_conf.tmp" "$superserver_conf" 			|| return 1
			;;
		remove)
			if [ -x /usr/sbin/update-inetd ]; then
				/usr/sbin/update-inetd --enable "$service"
				/usr/sbin/update-inetd --remove "$service"
			else
				grep -q "^$service[[:space:]]" $superserver_conf || return 0
				sed -e "s|^$service[[:space:]].*||g" < "$superserver_conf" > "$superserver_conf.tmp" 			    	&& mv -f "$superserver_conf.tmp" "$superserver_conf" 			    	|| return 1
			fi
			;;
		register)
			if [ -x /usr/sbin/update-inetd ]; then
				/usr/sbin/update-inetd --enable "$service"
				/usr/sbin/update-inetd --remove "$service"
				/usr/sbin/update-inetd --add "$template"
			else
				egrep -q "$template" $superserver_conf
				if [ "$?" -ne "0" ]; then 
					super_server_modify_inetd comment $service && 					echo "$template" >> $superserver_conf || return 1
				fi
			fi
			;;
	esac

	return 0
}

super_server_modify_xinetd()
{
	local file
	local service="$1"
	local action="$2"
	local template="$3"

	for file in $superserver_dir/*; do
		grep -q "$service" $file 1>>$product_log 2>&1 || continue

		case "$action" in
		    remove)
			    awk "/^[[:space:]]*(#|[[:space:]])*service[[:space:]]+$service($|[[:space:]]+)/,/.*}.*/ 				{next;} {print}
			    " <$file >$file.tmp 			    && mv -f $file.tmp $file || return 1
			    ;;
		    comment)
			    awk "/^[[:space:]]*service[[:space:]]+$service($|[[:space:]]+)/,/.*}.*/ 			       { print \"#\"\$0; next; }
			       {print}
			    " < $file > $file.tmp 			    && mv -f $file.tmp $file || return 1
			    ;;
		esac
	done

	case "$action" in
	    register)
		    echo "$template" > "$superserver_dir/${service}_psa" || return 1
		    label_file_once "$superserver_dir/${service}_psa" "${AUTOGENERATED_CONFIGS_UPGRADE}"
		    ;;
	    disable)
			[ -f "$superserver_dir/${service}_psa" ] && mv -f "$superserver_dir/${service}_psa" "$superserver_dir/${service}.psa"
		    ;;
	esac

	return 0
}

true superserver_status_linux_debian
superserver_status_linux_debian()
{
    get_pid "/usr/sbin/xinetd" false
    local pid=$common_var
    if test "$pid" -ne 1; then
# running
        return 0
    fi
    return 1
}
#-*- vim:syntax=sh

product_log_name_ex()
{
	local aux_descr="$1"
	local action="${CUSTOM_LOG_ACTION_NAME-installation}"

	if [ -n "$aux_descr" ]; then
		aux_descr="_${aux_descr}"
	fi

	if [ -n "$CUSTOM_LOG_NAME" ]; then
		echo "${CUSTOM_LOG_NAME}${action:+_$action}${aux_descr}.log"
	else
		echo "plesk_11.0.9${action:+_$action}${aux_descr}.log"
	fi
}

product_log_name()
{
	product_log_name_ex
}

product_problems_log_name()
{
	product_log_name_ex "problems"
}

problems_log_tail()
{
	[ -f "$product_problems_log" ] || return 0
	tac "$product_problems_log" | awk '/^START/ { exit } { print }' | tac
}

product_log_tail()
{
	[ -f "$product_log" ] || return 0
	tac "$product_log" | awk '/^START/ { exit } { print }' | tac
}

cleanup_problems_log()
{
	awk 'BEGIN 						{ st = "" } 
		 /^START/ 					{ st=$0; next } 
		 /^STOP/ && (st ~ /^START/) { st=""; next } 
		 (st != "") 				{ print st; st="" } 
		 							{ print }
		' "$product_problems_log" > "$product_problems_log.tmp" && 	mv -f "$product_problems_log.tmp" "$product_problems_log" || 	rm -f "$product_problems_log.tmp"
	
	if [ ! -s "$product_problems_log" ]; then 
		rm -f "$product_problems_log"
	fi
}

set_log_action_name()
{
	CUSTOM_LOG_ACTION_NAME="$1"
}

log_start()
{
	true product_log_name product_problems_log_name

	local title="$1"
	product_log="/tmp/`product_log_name`"
	product_problems_log="/tmp/`product_problems_log_name`"
	problems_occured=0

	echo "START $title" >>"$product_log" 	&& echo "START $title" >>"$product_problems_log" 	&& chmod 600 "$product_log" "$product_problems_log" 	|| {
		echo "Cannot write installation log $product_log, $product_problems_log" >&2
		exit 1
	}
}

log_stop()
{
	local title="$1"
	local subject="$2"
	if [ -z "$subject" ]; then
		subject="[${title}]"
	fi

	# check if problems are non-empty, check for problems_occured
	local status
	local problem_lines="`problems_log_tail | wc -l`"
	if [ "$problem_lines" -eq 0 ]; then
		status="completed successfully"
	else
		if [ $problems_occured -ne 0 ]; then
			status="failed"
		else
			status="completed with warnings"
		fi
	fi

	p_echo
	p_echo "**** $subject $status."
	p_echo

	if [ "$problem_lines" -ne 0 ]; then
		problems_log_tail >>"$product_log" 2>&1
		problems_log_tail
	fi

	echo "STOP $title" >>"$product_log"
	if [ $problems_occured -ne 0 ]; then
		echo "STOP $title: PROBLEMS FOUND" >>"$product_problems_log"
	else
		echo "STOP $title: OK" >>"$product_problems_log"
	fi

	if [ "X${PLESK_INSTALLER_KEEP_PROBLEMS_LOG}" = "X" ]; then
		cleanup_problems_log
	fi
}


generate_password_file()
{
	local passwd_file="$1"
	local title="$2"
	local user="$3"
	local group="$4"
	local mode="$5"

	if [ "$#" -ne 5 ]; then 
		die "Some arguments was not defined for this function"
	fi

	local passwd
	local inten="generate random password for $title"

	echo_try $inten

	if [ ! -s "$passwd_file" ]; then 
		passwd=`get_random_string` || die $inten
		echo "$passwd" > "$passwd_file" || die $inten
		set_ac $user $group $mode $passwd_file || die $inten
	else
		set_ac $user $group $mode $passwd_file || die $inten
	fi
}

get_pid()
{
	local i

	local ex_f="$1"
	local opt="$2"
	local owner="$3"

	local min_num="1"

#	Use pidof by default, bug 121868, except for FreeBSD - 140182
	if type pidof >/dev/null 2>&1 && [ "$os" != "BSD" ]; then
		for pid in `pidof -o $$ -o $PPID -o %PPID -x $ex_f`; do
#	Check for owner
			[ "$opt" = "true" -a "$owner" != "`ps -p $pid -o ruser=`" ] && continue
			min_num=$pid
			break
		done
		common_var=$min_num
		return $min_num
	fi

	case "$opt" in
		false)
			for i in `$ps_long | grep $ex_f | grep -v grep | grep -v httpsdctl | grep -v apachectl | awk '{print $2}' -`; do
				min_num=$i
				break
			done
			;;
		true)
			for i in `$ps_long | grep $ex_f | grep -v grep | grep -v httpsdctl | grep -v apachectl | grep "$owner" | awk '{print $2}' -`; do
				min_num=$i
				break
			done
			;;
		*)
			p_echo "get_pid: wrong parameter"
			die "get_pid $ex_f $opt $owner"
			;;
	esac

	common_var=$min_num
	return $min_num
}

kill_pids()
{
	ex_f="$1"
	owner="$2"

	for i in `$ps_long | grep $ex_f | grep -v grep | grep -v httpsdctl | grep -v apachectl | grep $owner | awk '{print $2}' -`; do
		if [ $i -gt 1 ]; then
			$K_TERM $i >> $product_log 2>&1
		fi
	done
}

delete_user()
{
	local rm_user

	rm_user="$1"

	# if it is mailman user, remove its crontab from system
	if [ "X${rm_user}" = "X${mailman_user}" ]; then

		inten="remove crontab of ${rm_user}"
		echo "y" | $crontab -u "${mailman_user}" -r >> $product_log 2>&1 || die "$inten"

	fi

	inten="remove user $rm_user"
	echo_try "$inten"

	userdel  $rm_user>> $product_log 2>&1 && suc || die "$inten"
}

delete_group()
{
	local rm_group

	rm_group="$1"

	inten="remove group $rm_group"
	echo_try "$inten"

	mk_backup "/etc/group" cp f
	if [ -f "/etc/group" ]; then
		sed -e "/$rm_group/d" < /etc/group > /etc/group.tmp || die $inten
		mv -f /etc/group.tmp /etc/group  >> $product_log 2>&1
		if [ "$?" -ne 0 ]; then
			rsr_backup "/etc/group" cp f
			die $inten
		fi
	fi
	suc
}
initial_conf()
{
	DEMO_VERSION="no"
	PRODNAME="psa"
	PRODUCT_NAME="psa"
	product_full="Plesk"
	product=${PRODNAME}
	PRODUCT_FULL_NAME="Plesk"

	product_etc="/etc/${PRODNAME}"
	prod_conf_t="/etc/psa/psa.conf"
	prodkey="$product_etc/$PRODNAME.key"

	minimal_changes="0"

	EXTERNAL_PACKAGES=""
	EXTERNAL_PACKAGES_DIR=""

	BUILDER_UID="10007"

	PERL5LIB=/usr/local/psa/lib/perl5/site_perl/5.14.2:/usr/local/psa/lib/perl5/site_perl/5.14.2/i586-linux-thread-multi
	export PERL5LIB

        support_contact="http://www.parallels.com/support"
	sales_email="sales@parallels.com"

	product_version="11.0.9"
	product_db_version="011009"
	conceived_os_vendor=SuSE
	conceived_os_version="12.1"
	osrels="suse12.1"

	# This variable contains all versions, which is supported by
	# cumulative upgrade
	known_product_versions="80 81 82 83 84 86 90 92 93 95 100 101 107 108 109 1010 1011 1012 1013 1100"

	prev_product="plesk"
	prev_clients_group="${prev_product}cln"

        clients_group="${product}cln"
        clients_GID=10001

        services_group="psaserv"
        services_GID=10003

        product_suff="saved_by_${product}".`date "+%m.%d;%H:%M"`
        product_suffo="saved_by_${product}"

	PREV_PRODUCT_ROOT_D="/usr/local/${prev_product}"

	# plesk default password
	if [ "X$DEMO_VERSION" = "Xyes" ]; then
		PRODUCT_DEFAULT_PASSWORD="plesk"
	else
		PRODUCT_DEFAULT_PASSWORD="setup"
	fi
}

read_conf()
{
	[ -n "$prod_conf_t" ] || prod_conf_t=/etc/psa/psa.conf

	if [ -s $prod_conf_t ]; then
		tmp_var=`perl -e 'undef $/; $_=<>; s/#.*$//gm;
				s/^\s*(\S+)\s*/$1=/mg;
				print' $prod_conf_t`
		eval $tmp_var
	else
		if [ "X$do_upgrade" = "X1" ]; then
			[ 0$ignore_miss_conf -ne 1 ] && p_echo "Unable to find product configuration file: $prod_conf_t"
			return 1
		fi
	fi
	return 0
}

get_my_cnf_param()
{
	local my_cnf cnf_files

	cnf_files="/etc/my.cnf /etc/mysql/my.cnf /var/db/mysql/my.cnf"

	for my_cnf in ${cnf_files}; do
		if [ -f ${my_cnf} ]; then
			break
		fi
	done

	[ -f ${my_cnf} ] && r=`perl -e '$p="'"$1"'";
	undef $/; $_=<>; s/#.*$//gm;
	/\[mysqld\](.*?)\[/sg;
	$_=substr($1, rindex $1,"$p") and
	/$p\s*=(.*)/m and print $1
	' ${my_cnf}`
	echo $r
}

get_mysql_socket()
{
	mysql_socket="/var/run/mysql/mysql.sock"

	local mysqlsock=`get_my_cnf_param  socket`
	local MYSQL_SOCKETS="/var/lib/mysql/mysql.sock /tmp/mysql.sock /var/run/mysqld/mysqld.sock"

	for i in $mysql_socket $mysqlsock $MYSQL_SOCKETS; do
	    if [ -S "$i" ]; then
		    MYSQL_UNIX_PORT=$i
		    export MYSQL_UNIX_PORT
		    mysql_socket="$i"
		    break
	    fi
	done
}

 #default values

product_default_conf()
{

PRODUCT_ROOT_D=/usr/local/psa
PRODUCT_RC_D=/etc/init.d
PRODUCT_ETC_D=/usr/local/psa/etc
PLESK_LIBEXEC_DIR=/usr/lib/plesk-9.0
HTTPD_VHOSTS_D=/srv/www/vhosts
HTTPD_CONF_D=/etc/apache2
HTTPD_INCLUDE_D=/etc/apache2/conf.d
HTTPD_BIN=/usr/sbin/httpd2
HTTPD_LOG_D=/var/log/apache2
HTTPD_SERVICE=apache2
QMAIL_ROOT_D=/var/qmail
PLESK_MAILNAMES_D=/var/qmail/mailnames
RBLSMTPD=/usr/sbin/rblsmtpd
COURIER_IMAP_ROOT_D=/
FTPD_CONF=/etc/proftpd.conf
FTPD_CONF_INC=/etc/proftpd.include
FTPD_BIN_D=/usr/bin
FTPD_VAR_D=/usr/local/psa/var/run
FTPD_SCOREBOARD=/usr/local/psa/var/run/scoreboard
NAMED_RUN_ROOT_D=/var/lib/named
NAMED_OPTIONS_CONF=/etc/named.conf.include.plesk-options
NAMED_ZONES_CONF=/etc/named.conf.include.plesk-zones
WEB_STAT=/usr/bin/webalizer
MYSQL_VAR_D=/var/lib/mysql
MYSQL_BIN_D=/usr/bin
PGSQL_DATA_D=/var/lib/pgsql/data
PGSQL_CONF_D=/var/lib/pgsql/data
PGSQL_BIN_D=/usr/bin
DUMP_D=/var/lib/psa/dumps
DUMP_TMP_D=/tmp
MAILMAN_ROOT_D=/usr/lib/mailman
MAILMAN_VAR_D=/var/lib/mailman
PYTHON_BIN=/usr/bin/python2.7
CATALINA_HOME=/usr/share/tomcat6
DRWEB_ROOT_D=/opt/drweb
DRWEB_ETC_D=/etc/drweb
GPG_BIN=/usr/bin/gpg
TAR_BIN=/bin/tar
AWSTATS_ETC_D=/etc/awstats
AWSTATS_BIN_D=/srv/www/cgi-bin/awstats
AWSTATS_TOOLS_D=/usr/share/awstats
AWSTATS_DOC_D=/usr/share/apache2/icons/awstats
OPENSSL_BIN=/usr/bin/openssl
LIB_SSL_PATH=/lib/libssl.so
LIB_CRYPTO_PATH=/lib/libcrypto.so
CLIENT_PHP_BIN=/usr/local/psa/bin/php-cli
SNI_SUPPORT=true
APS_DB_DRIVER_LIBRARY=/usr/lib/libmysqlserver.so.2

}

#-*- vim:syntax=sh

register_service(){

	[ -n "$1" ] || die "register_service: service name not specified"
	local inten="register service $1"
	echo_try "$inten"


# insserv for SuSE
	 /sbin/insserv -f "$1" >/dev/null 2>&1

	suc
}

#Need for register/unregister services into /etc/rc.conf for BSD OSes.
#Create or change strings such as service_option_variable="variable"
rc_service()
{
   local service="$1"
   local option="$2"
   local variable="$3"
   local comment="$4"
 
   local config="/etc/rc.conf"

   if [ "X$variable" = "Xdefault" ]; then
      remove_option_string "${service}_${option}" "$config"
      return 0
   fi

   if [ ! -f /etc/rc.conf ]; then
      die 'File /etc/rc.conf not found!'
   fi

   if [ "X$service" = "X" -o "X$option" = "X" -o "X$variable" = "X" ]; then
      die
   fi

   local flag="`grep "${service}_${option}" $config`"
   
   if [ "X$flag" = "X" ]; then
        if [ "X$comment" = "Xyes" ]; then
           echo "#Option for $service created by Plesk installer." >> $config
	fi
	echo "${service}_${option}=\"${variable}\"" >> $config || die 
   else
        sed -i "" -e 's|\('"${service}_${option}"'.*=\"\).*|\1'"${variable}"'\"|' $config  || die
   fi

   return 0
}

remove_option_string()
{
    #using: remove_option_string <option> <file>
    substring="$1"
    file="$2"

    awk '{
	if ($0 ~ "^'"$substring"'") {
	    next;
	}; 
	print $0; 
    }' < $file  > $file.tmp

    mv $file.tmp $file
}

selinux_close()
{
	if [ -z "$SELINUX_ENFORCE" -o "$SELINUX_ENFORCE" = "Disabled" ]; then
		return
	fi

	setenforce "$SELINUX_ENFORCE"
}

#set_params

set_common_params()
{
	common_var=0

	PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
	LANG=C
	export PATH LANG
	umask 022
	ulimit -n 65535 2>/dev/null

	K_HUP="/bin/kill -HUP"
	K_KILL="/bin/kill -KILL"
	K_TERM="/bin/kill -TERM"
	K_USR2="/bin/kill -USR2"

	users_created=""
	groups_created=""

	certificate_file="$PRODUCT_ETC_D/httpsd.pem"
	services="/etc/services"
	mtab="/etc/mtab"
	get_hostname="hostname"
	get_domainname="domainname"

	#VZP used to determine that we're inside SVE
	vza_file="/var/vzagent"

	#default parameters
	tar="tar"
	crontab="/usr/bin/crontab"

	cp_preserve="cp -p"
	SYSTEM_RC_D=/etc/init.d
	PLESK_LIBEXEC_DIR="/usr/lib/plesk-9.0"
	PLESK_DB_DIR="/var/lib/plesk"
	POSTFIX_LIBEXEC_DIR="/usr/lib/postfix"
	PRODUCT_BOOTSTRAPPER_DIR="/usr/local/psa/bootstrapper/pp11.0.9-bootstrapper"
	AUTOGENERATED_CONFIGS="#ATTENTION!\n#\n#DO NOT MODIFY THIS FILE BECAUSE IT WAS GENERATED AUTOMATICALLY,\n#SO ALL YOUR CHANGES WILL BE LOST THE NEXT TIME THE FILE IS GENERATED.\n"
    AUTOGENERATED_CONFIGS_UPGRADE="#ATTENTION!\n#\n#DO NOT MODIFY THIS FILE BECAUSE IT WAS GENERATED AUTOMATICALLY,\n#SO ALL YOUR CHANGES WILL BE LOST AFTER YOU UPGRADE PARALLELS PLESK PANEL.\n"

	set_common_params_linux 

	detect_vz
}

set_common_params_linux()
{
	get_hostname="hostname -f"
	fstab="/etc/fstab"
	cp_preserve="cp --preserve=all --remove-destination"
	machine="linux"
	sendmail="/usr/sbin/sendmail"
	ps="ps axw"
	ps_long="ps axuw"
	false_shell="/bin/false"
	dummy_home="/"
	compress="gzip -9 -c"
	uncompress="gunzip -c"
	uudecode="uudecode -o /dev/stdout"
	ifconfig="/sbin/ifconfig -a"
	inet_str="inet addr"

	if [ -f /etc/slackware-version ]; then
	    linux_distr="slackware"
	    useradd_options=""
	    sndml_ini="/etc/rc.d/init.d/sendmail"
	    mail_local="/usr/libexec/mail.local"
	    dummy_shell=""
	    named_osrelease=0
	else
	    useradd_options="-M"
	    if [ -f /etc/mandrake-release ]; then
		linux_distr="mandrake"
	    elif [ -f /etc/fedora-release ]; then
		linux_distr="fedora"
	    elif [ -f /etc/SuSE-release ]; then
		linux_distr="suse"
		useradd_options="-r"
	    elif [ -f /etc/debian_version ]; then
		linux_distr="debian"
		get_domainname="dnsdomainname"
		useradd_options=""
	    else
		linux_distr="redhat"
	    fi

	    sndml_ini="/etc/init.d/sendmail"
	    mail_local="/usr/libexec/mail.local"
	    if [ -x /sbin/nologin ]; then
		dummy_shell="/sbin/nologin"
	    else
		dummy_shell="/bin/false"
	    fi
	    bash_shell="/bin/bash"
	    rbash_shell="/bin/rbash"
	    uudecode_full="/usr/bin/uudecode"
	    named_osrelease=`cat /proc/sys/kernel/osrelease | perl -F"/[.-]/" -n -a  -e 'printf "%02u%02u%02u\n", $F[0],$F[1],$F[2]'`
	fi

	return 0
}

define_start_script()
{
	if [ -f "$PRODUCT_RC_D/${product}.sh" ]; then
		START_SH="$PRODUCT_RC_D/${product}.sh"
	else
		START_SH="$PRODUCT_RC_D/${product}"
	fi
}
## @@constructor set_syslog_params

true syslog_status_linux_debian
syslog_status_linux_debian()
{
	get_pid "$syslog_binary" false
	local pid=$common_var
	if test "$pid" -ne 1; then
		# running
		return 0
	fi
	return 1
}

remove_modules()
{
	p_echo
	p_echo "===> Removing modules"

	local moduledir
	for moduledir in $PRODUCT_ROOT_D/var/modules/*; do
		if [ -d "$moduledir" -a -x "$moduledir/uninstall" ]; then
			local module=`basename $moduledist`
			echo_try "uninstall $module module"
			"$moduledir/uninstall" && suc || warn "uninstallation of $module module"
		fi
	done
}

## @@constructor set_mysqld_params

set_mysql_server_params()
{
	local service

	MYSQL_ROOT="$PRODUCT_ROOT_D/mysql"
	mysql_bindir="$MYSQL_BIN_D"

	get_mysql_socket

	if [ -x "${PRODUCT_RC_D}/mysql" ]; then
	    mysql_service="mysql"
	elif [ -x "${PRODUCT_RC_D}/mysql.sh" ]; then
	    mysql_service="mysql.sh"
	elif [ -x "${PRODUCT_RC_D}/mysqld" ]; then
	    mysql_service="mysqld"
	elif [ -x "${PRODUCT_RC_D}/mysql" ]; then
	    mysql_service="mysql"
	elif [ "X$DEMO_VERSION" = "Xyes" ]; then
	    mysql_service="mysqld"
	else
	    die "$inten"	
	fi
}

true mysql_stop mysql_status

set_mysql_client_params()
{
	mysql_client="$MYSQL_BIN_D/mysql"

#	Override these variables as needed
	mysql_db_name="$PRODNAME"
	mysql_passwd_file="$product_etc/.${PRODNAME}.shadow"
	prev_mysql_passwd_file="$PREV_PRODUCT_ROOT_D/admin/conf/admin.conf"

 	if [ -z "$mysql_unconfigured" ];then
#	Need for mysql_status related function
		set_mysql_server_params	
		set_mysql_auth
	fi

	mysql_args="-N"
	mysql_args_raw="-Br"

	# For backward compatibility only, should use mysql() and mysql_raw() instead
	mysql=mysql
	mysql_raw=mysql_raw
}

# iF YOUR package want to use mysql db you must call this function directly
set_mysql_auth()
{
	local inten="set up mysql authentification"
	get_admin_passwd

	pleskrc mysql start

	mysql_user="--user=admin"
	mysql_passwd="--password=$admin_passwd"
	unset mysql_defaults

	if [ -z "$MYSQL_AUTH_SKIP_CONNECTION_CHECK" ]; then
		mysql_test_connection 60 || die "$inten"
	fi
	suc
}

get_admin_passwd()
{
    [ -z "$admin_passwd" ] || return 0

    if [ -f "$mysql_passwd_file" ]; then
		admin_passwd=`cat "$mysql_passwd_file"`
		return 0
    fi

	admin_passwd=`get_random_string 12 'A-Za-z0-9_'`

	[ -n "$admin_passwd" ] || admin_passwd="$PRODUCT_DEFAULT_PASSWORD"
}

#Invoke mysql
mysql()
{
	mysql_anydb -D$mysql_db_name "$@"
}

mysql_anydb()
{
	$mysql_client $mysql_user $mysql_passwd $mysql_args "$@" 2>>"$product_log"

	local status=$?
	if [ $status -gt 0 ]; then
		$mysql_client $mysql_user $mysql_passwd $mysql_args -D$mysql_db_name $mysql_args_raw -e "SHOW ENGINE innodb status" >>"$product_log" 2>&1
	fi
	return $status
}

# Invoke mysql without any wrapper or something else
mysql_direct()
{
	$mysql_client $mysql_defaults $mysql_user $mysql_passwd $mysql_args "$@" 2>>"$product_log"
}

# Invoke mysql in raw mode
mysql_raw()
{
	mysql $mysql_args_raw "$@"
}

mysql_raw_anydb()
{
	mysql_anydb $mysql_args_raw "$@"
}

mysql_start_linux_suse_ex()
{
	if [ -x "/sbin/service" ]; then
		action_cmd="/sbin/service mysql"
	else
		action_cmd="$SYSTEM_RC_D/$mysql_service"
	fi

	$action_cmd start >> $product_log 2>&1
}

true mysql_start_linux_suse
mysql_start_linux_suse()
{
	inten="start service mysql"
	echo_try "$inten"

	mysql_start_linux_suse_ex
	local rc="$?"

# bug 52690. MySQL init script reports failure if protected mysqld is running (true for SuSE >= 11.3)
	if [ "$rc" -ne 0 ]; then
		local mysqld_bin="/usr/sbin/mysqld"
		killall -TERM mysqld >> $product_log 2>&1
		if [ -x "$mysqld_bin" ]; then
			for i in 2 4 8 16 32; do
				get_pid "$mysqld_bin" false
				local pid="$common_var"
				if test "$pid" -eq 1; then
					break
				fi
				killall -TERM mysqld >> $product_log 2>&1
				sleep $i
			done
		fi
		mysql_start_linux_suse_ex
		rc="$?"
	fi

	[ "$rc" -eq 0 ] && suc || warn "$inten"
	return $rc
}

mysql_test_connection()
{
	inten="establish test connection"
	echo_try $inten
	attempts=${1:-1}	
	for i in `sequence $attempts`; do
		echo "" | mysql_direct mysql >> "$product_log" 2>&1
		if [ "$?" -eq "0" ]; then
			p_echo "connected"
			return 0
		fi
		[ "$attempts" -eq "1" ] || sleep 2
	done

	p_echo "failed"
	return 1
}

###	FIXME: probably need var service_restart warn
mysql_stop()
{
	local op_result i

	inten="stop MySQL server"
	echo_try $inten

	$PRODUCT_RC_D/$mysql_service stop >> $product_log 2>&1

	op_result=$?

	if [ "X$linux_distr" = "Xdebian" ]; then
# Debian has well designed mysql stopping code
		[ "$op_result" -eq 0 ] || die $inten
		suc
		return 0
	fi

	for i in 2 4 6 8 16; do
		if ! mysql_status ; then
			suc
			return 0
		fi

		case $machine in
			BSD*|Darwin*)
				#In BSD systems mysqld must to be killed without -9 flag
				killall mysqld mysqld_safe >> $product_log 2>&1
			;;
			*)
				# I just want to be sure that mysql really stopped
				killall -TERM mysqld mysql safe_mysqld mysqld_safe >> $product_log 2>&1
			;;
		esac
		sleep $i
	done

	die "$inten"
}

mysql_status()
{
	local file

    #Check with native script first
	#debian script always return 0. bug #111825
	[ "X$linux_distr" = "Xdebian" ] && msqld_status_supported="no"
	
	if [ -z "$msqld_status_supported" ]; then
# MySQL AB packages doesn't know about status command
		if LC_MESSAGES=C $PRODUCT_RC_D/$mysql_service 2>&1 | grep -q "status"; then
			msqld_status_supported="yes"
		else
			msqld_status_supported="no"
		fi
	fi

	if [ "$msqld_status_supported" = "yes" ]; then
# Common RPM mysql's and FreeBSD
	$PRODUCT_RC_D/$mysql_service status >> $product_log 2>&1 		&& return 0
	fi

	if [  "$msqld_status_supported" = "no" ]; then
# MySQL AB packages
		file="/usr/sbin/mysqld"
	fi

    if [ -x "$file" ]; then
		#standard build and debian
		get_pid "$file" false
		pid=$common_var
		if test "$pid" -ne 1; then
			echo "$file (pid $pid) is running..." >>$product_log 2>&1
			return 0
		else
			echo "$file is stopped" >>$product_log 2>&1
			return 1
		fi
	fi

	return 1
}

reset_user_password()
{
	local user="$1"
	local passwd="$2"
	local host="${3:-localhost}"

	echo "SET PASSWORD FOR '$user'@'$host' = PASSWORD('$passwd')" | mysql_direct mysql || 
	[ "$host" = "127.0.0.1" -o "$host" = "::1" ] && host="localhost" && \
	echo "SET PASSWORD FOR '$user'@'$host' = PASSWORD('$passwd')" | mysql_direct mysql ||
	echo "SET PASSWORD FOR '$user'@'%'     = PASSWORD('$passwd')" | mysql_direct mysql
}

is_local_mysql_instance()
{
	local host="$1"
	[ -z "$host" -o "$host" = "localhost" -o "$host" = "127.0.0.1" -o "$host" = "::1" ]
}

check_db_accessible()
{
	local mysql_db_name="$1"
	local mysql_user="--user=$2"
	local mysql_passwd="--password=$3"

	db_do --inten "check that DB $1 is accessible to user $2" ""
}

reset_sitebuilder_passwd()
{
	local sb_conf="/usr/local/sb/config"
	[ -f "$sb_conf" ] || return 0

	local sb_host=`    get_ini_conf_var "$sb_conf" "database" "host"`
	local sb_username=`get_ini_conf_var "$sb_conf" "database" "username"`
	local sb_password=`get_ini_conf_var "$sb_conf" "database" "password"`
	local sb_dbname=`  get_ini_conf_var "$sb_conf" "database" "dbname"`

	is_local_mysql_instance "$sb_host" || return 0

	reset_user_password "$sb_username" "$sb_password" "$sb_host" && \
	check_db_accessible "$sb_dbname" "$sb_username" "$sb_password"
}

reset_billing_passwd()
{
	local billing_db_bin="/usr/share/plesk-billing/billing-db"
	local bil_host bil_user bil_passwd bil_dbname bil_mysql_local bil_info

	[ -x "$billing_db_bin" ] || return 0
	bil_mysql_local=`$billing_db_bin --is-local 2>/dev/null`
	if [ "$?" -eq 0 ]; then
		# New billing-db version is shell-friendly
		bil_dbname=`$billing_db_bin --get name`
		bil_user=`  $billing_db_bin --get user`
		bil_host=`  $billing_db_bin --get host`
	else
		# Slightly older ones provide --info option
		bil_info=`$billing_db_bin --info 2>/dev/null`
		if [ "$?" -eq 0 ]; then
			bil_dbname=`echo "$bil_info" | sed -ne 's/Database Name:\s*\(.*\)/\1/p'`
			bil_user=`  echo "$bil_info" | sed -ne 's/Database User:\s*\(.*\)/\1/p'`
			bil_host=`  echo "$bil_info" | sed -ne 's/Database Hostname:\s*\(.*\)/\1/p'`
			bil_mysql_local=
		fi
	fi
	if [ -z "$bil_dbname" -o -z "$bil_user" ]; then
		# And finally, if invoked w/o arguments, billing-db switches into MySQL prompt
		bil_info=`echo 'select database() \G select current_user() \G' | $billing_db_bin`
		[ "$?" -eq 0 ] || return 1
		local bil_auth=`echo "$bil_info" | sed -ne 's/current_user():\s*\(.*\)/\1/p'`
		bil_dbname=`    echo "$bil_info" | sed -ne 's/database():\s*\(.*\)/\1/p'`
		bil_user=`get_narg_fs "$bil_auth" '@' 1`
		bil_host=`get_narg_fs "$bil_auth" '@' 2`
		bil_mysql_local=
	fi
	bil_passwd=`get_random_string 12 'A-Za-z0-9_'`

	is_local_mysql_instance "$bil_host" || return 0
	[ -z "$bil_mysql_local" -o "$bil_mysql_local" = "yes" ] || return 0

	reset_user_password "$bil_user" "$bil_passwd" "$bil_host" && \
	$billing_db_bin --set --password "$bil_passwd" && \
	check_db_accessible "$bil_dbname" "$bil_user" "$bil_passwd" && 
	{
		$billing_db_bin --is-configured 2>/dev/null | grep -q yes || \
		$billing_db_bin --is_configured 2>/dev/null | grep -q yes 
	}
}

get_webmail_config_param()
{
	local webmail_config="$1"
	local config_var="$2"
	local param="$3"
	local default_val="$4"
	local result=`sw_engine_pleskrun -n -r 'include "'$webmail_config'"; echo $'${config_var}${param}';' 2>/dev/null`
	[ -n "$result" ] || result="$default_val"
	echo "$result"
}

get_horde_config_param()
{
	get_webmail_config_param "/usr/share/psa-horde/config/conf.php" "conf" "$1" "$2"
}

get_atmail_config_param()
{
	get_webmail_config_param "/var/www/atmail/libs/Atmail/Config.php" "pref" "$1" "$2"
}

reset_horde_passwd()
{
	set_horde_params

	local horde_shadow="$horde_passwd_file"
	[ -f "$horde_shadow" ] || horde_shadow="/etc/psa/.webmail.shadow"
	local hor_host=`  get_horde_config_param "['sql']['hostspec']" "localhost"`
	local hor_user=`  get_horde_config_param "['sql']['username']" "horde"`
	local hor_dbname=`get_horde_config_param "['sql']['database']" "horde"`
	local hor_passwd=`get_horde_config_param "['sql']['password']"`
	[ -n "$hor_passwd" ] || hor_passwd=`cat "$horde_shadow" 2>/dev/null`
	[ -n "$hor_passwd" -a -n "$hor_user" -a -n "$hor_dbname" ] || return 0

	is_local_mysql_instance "$hor_host" || return 0

	reset_user_password "$hor_user" "$hor_passwd" "$hor_host" && \
	check_db_accessible "$hor_dbname" "$hor_user" "$hor_passwd"
}

reset_atmail_passwd()
{
	set_atmail_params

	local atmail_shadow="$atmail_passwd_file"
	local at_host=`  get_atmail_config_param "['sql_host']" "localhost"`
	local at_user=`  get_atmail_config_param "['sql_user']" "atmail"`
	local at_dbname=`get_atmail_config_param "['sql_table']" "atmail"`
	local at_passwd=`get_atmail_config_param "['sql_pass']"`
	[ -n "$at_passwd" ] || at_passwd=`cat "$atmail_shadow" 2>/dev/null`
	[ -n "$at_passwd" -a -n "$at_user" -a -n "$at_dbname" ] || return 0

	is_local_mysql_instance "$at_host" || return 0

	reset_user_password "$at_user" "$at_passwd" "$at_host" && \
	check_db_accessible "$at_dbname" "$at_user" "$at_passwd"
}

true named_status_linux_debian
named_status_linux_debian()
{
    get_pid "/usr/sbin/named" false
    local pid=$common_var
    if test "$pid" -ne 1; then
# running
		return 0
    fi
    return 1
}

phpmyadmin_config_backup()
{
	set_phpmyadmin_params
	[ -f "$PHPMYADMIN_CONFIG" ] && cp "$PHPMYADMIN_CONFIG" "$PHPMYADMIN_CONFIG.save"
}

set_phpmyadmin_params()
{
	PHPMYADMIN_D="$PRODUCT_ROOT_D/admin/htdocs/domains/databases/phpMyAdmin"
	PHPMYADMIN_CONFIG="$PHPMYADMIN_D/libraries/config.default.php"
}

pma__read_values_from_config_backup()
{
	if [ -f "$PHPMYADMIN_CONFIG.save" ]; then
		# looking for values of following variables in config.default.php.save
		pma__set_values_from_config "$PHPMYADMIN_CONFIG.save" 'controluser' 'controlpass' 'pmadb' 'bookmarktable' 'relation' 'table_info' 'table_coords' 'pdf_pages' 'column_info' 'history' 'designer_coords' 'tracking' 'userconfig'
	fi
}

pma__write_values_to_config()
{
	# write new config.inc.php
	sed -e "`pma__sed_script`" < "$PHPMYADMIN_CONFIG.tpl" > "$PHPMYADMIN_CONFIG"
}

pma__set_values_from_config()
{
	eval `pma__read_values "$@"`
}

pma__read_values()
{
	local PHPMYADMIN_CONFIG="$1"
	shift

	[ -f $PHPMYADMIN_CONFIG ] && sw_engine_pleskrun -r '
			try {
				error_reporting(0);
				$GLOBALS["db_host"] = "localhost";
				class vz {
					public static function in_vzcp_proxy() { return false; }
				}
				function in_vzcp_proxy() { return false; }
				require_once("'$PHPMYADMIN_CONFIG'");
				for ($i = 1; $i < $argc; $i++)
					if (isset($cfg["Servers"][1][$argv[$i]]))
						echo $argv[$i] . "=\"" . $cfg["Servers"][1][$argv[$i]] . "\"\n";
			} catch (Exception $e) {}' -- "$@" 2>/dev/null || true
}

pma__sed_script()
{
	echo "\
	s/@@CONTROLUSER@@/$controluser/g
	s/@@CONTROLPASS@@/$controlpass/g
	s/@@PMADB@@/$pmadb/g
	s/@@PMA_BOOKMARK@@/$bookmarktable/g
	s/@@PMA_COLUMN_INFO@@/$column_info/g
	s/@@PMA_HISTORY@@/$history/g
	s/@@PMA_PDF_PAGES@@/$pdf_pages/g
	s/@@PMA_RELATION@@/$relation/g
	s/@@PMA_TABLE_COORDS@@/$table_coords/g
	s/@@PMA_TABLE_INFO@@/$table_info/g
	s/@@PMA_DESIGNER_COORDS@@/$designer_coords/g
	s/@@PMA_TRACKING@@/$tracking/g
	s/@@PMA_USERCONFIG@@/$userconfig/g\
	"
}

poppassd_super_server_config()
{
	local action="$1"

	if [ -f /proc/net/if_inet6 ]; then 
		FLAGS="flags                   = KEEPALIVE IPv6"
	else
		FLAGS="flags                   = KEEPALIVE"
	fi

	case "$superserver" in
	    inetd)
		poppassd_rec="poppassd stream tcp nowait/1000 root /usr/sbin/tcpd $PRODUCT_ROOT_D/admin/sbin/poppassd"
		;;	
	    xinetd)
		poppassd_rec="service poppassd
{
socket_type             = stream
protocol                = tcp
port                    = 106
wait                    = no
disable                 = no
user                    = root
instances               = 1000
$FLAGS
server                  = $PRODUCT_ROOT_D/admin/sbin/poppassd
}"
		;;
	    *)
		    die "Super server name unknown"
		;;
	esac

	super_server_action "$action" poppassd "$poppassd_rec"
}

true exim_status_linux_debian
exim_status_linux_debian()
{
	get_pid /usr/lib/exim/exim3 false
	local pid=$common_var

	if test "$pid" -ne 1; then
		#running
		return 0;
	fi
	return 1
}

set_postfix_auth()
{
	local run="$PRODUCT_ROOT_D/admin/sbin/mailmng --set-mail-params"

	if db_test "SELECT val FROM misc WHERE param='relay' AND val='open'" 1 ; then
		run="$run --relayclient"
	fi

	if db_test "SELECT * FROM misc WHERE param='disable_smtp_auth' and val=0" 1 ; then
		run="$run --smtpauth"
	fi

	if db_test "SELECT * FROM misc WHERE param='disable_pop_auth' and val=0" 1 ; then
		run="$run --popauth"
	fi

	db_select "SELECT val FROM misc WHERE param='poplock_time'"
	if [ -n "$db_select_output" ]; then
		# this will also set correct crontab for poplock.db cleanup
		run="$run --poplock-time=$db_select_output"
	fi

	$run >> $product_log 2>&1
}

update_postfix_poplockdb_cleanup_crontab()
{
	[ -x "${PRODUCT_RC_D}/postfix" -a ! -f "${PRODUCT_RC_D}/qmail" ] || return 0
	set_postfix_auth
}

# $1 - openssl binary
# $2 - openssl args
# $3 - cert file name
# $4 - bits number
qmail_tls_cert()
{
	local QMAIL_CONTROL_D TLS_CERT

	QMAIL_CONTROL_D=${QMAIL_ROOT_D}/control
	TLS_CERT=${QMAIL_CONTROL_D}/$3

	if [ ! -f ${TLS_CERT} ]; then
		$1 $2 -out ${TLS_CERT} $4 >> $product_log 2>&1
		if [ $? -ne 0 ]; then
			report_problem "Certificate for qmail TLS sessions ${TLS_CERT} was not generated. Qmail will generate it at each TLS session. It is too slow and will make high CPU load."
		fi
		p_echo
	fi

	if [ -f ${TLS_CERT} ]; then
		chmod 600 ${TLS_CERT} && chown qmaild:0 ${TLS_CERT}
		if [ $? -ne 0 ]; then
			# Fallback for case when qmail is not installed
			chmod 600 ${TLS_CERT} && chown root:0 ${TLS_CERT}
			report_problem "Unable to set proper permission to ${TLS_CERT} Normally, owner user and group should be qmaild:0 and access should be 0600."
		fi
	fi
}

generate_tls_certificates()
{
	local SSL_BIN inten umask_sav

	inten="generate SSL certificates for TLS sessions"

	echo_try $inten

	SSL_BIN=/usr/bin/openssl

	# store old umask and set very secure one
	umask_sav=`umask`
	umask 0077

	qmail_tls_cert ${SSL_BIN} "genrsa" rsa512.pem 512
	#qmail_tls_cert ${SSL_BIN} "dhparam -2" dh512.pem 512
	#qmail_tls_cert ${SSL_BIN} "dhparam -2" dh1024.pem 1024

	umask ${umask_sav}

	suc
}
#qmail

set_qmail_params()
{
    QMAIL_DIR="/var/qmail"
    QMAIL_USERS="alias:2021:nofiles:false:alias  qmaild:2020:nofiles:false:  qmaill:2022:nofiles:false:  qmailp:2023:nofiles:false:  qmailq:2520:qmail:  qmailr:2521:qmail:  qmails:2522:qmail:"
    QMAIL_GROUPS="qmail:2520  nofiles:2020"

    #variable from psa.conf but used in mail-qc-driver
    #so we need define this before install psa base package
    if [ -z "$QMAIL_ROOT_D" ]; then 
	    QMAIL_ROOT_D="/var/qmail"
    fi

    mm_mailgroup=12

    qmail_service="qmail"
    qmail_extra_cmd=""
    qmail_log="/var/log/maillog"
}

## @@constructor set_qmail_params
qmail_super_server_config()
{
    local action="$1"
    local service="$2"
    qmail_xinetd_templates

    eval "template=\$${service}_rec"
    super_server_action "$action" "$service" "$template"
}

qmail_xinetd_templates()
{
    local TRUE_BIN
    TRUE_BIN=$QMAIL_DIR/bin/true

    if [ -f /proc/net/if_inet6 ]; then
	    V6_FLAGS="flags		= IPv6"
    else
	    V6_FLAGS=""
    fi

smtp_rec="service smtp
{
	socket_type     = stream
	protocol        = tcp
	wait            = no
	disable		= no
	user            = root
	$V6_FLAGS
	instances       = UNLIMITED
	env             = SMTPAUTH=1
	server          = $QMAIL_DIR/bin/tcp-env
	server_args     = -Rt0 $QMAIL_DIR/bin/relaylock $QMAIL_DIR/bin/qmail-smtpd $QMAIL_DIR/bin/smtp_auth $TRUE_BIN $QMAIL_DIR/bin/cmd5checkpw $TRUE_BIN
}" 

smtps_rec="service smtps
{
	socket_type     = stream
	protocol        = tcp
	wait            = no
	disable		= no
	user            = root
	$V6_FLAGS
	instances       = UNLIMITED
	env             = SMTPAUTH=1
	server          = $QMAIL_DIR/bin/tcp-env
	server_args     = -Rt0 $QMAIL_DIR/bin/relaylock $QMAIL_DIR/bin/qmail-smtpd $QMAIL_DIR/bin/smtp_auth $TRUE_BIN $QMAIL_DIR/bin/cmd5checkpw $TRUE_BIN
}" 

submission_rec="service submission
{
	socket_type     = stream
	protocol        = tcp
	wait            = no
	disable		= no
	user            = qmaild
	$V6_FLAGS
	instances       = UNLIMITED
	env             = SUBMISSION=1 SMTPAUTH=1
	server          = $QMAIL_DIR/bin/tcp-env
	server_args     = -Rt0 $QMAIL_DIR/bin/qmail-smtpd $QMAIL_DIR/bin/smtp_auth $TRUE_BIN $QMAIL_DIR/bin/cmd5checkpw $TRUE_BIN
}" 

}


rsr_backup()
{
	target="$1"
	dup="$2"
	opts="$3"
	common_var=0

#	if [ -$opts "$target" ]; then
		if [ -$opts "$target.$product_suff" ]; then
			case "$dup" in
				mv)
					mv -f  $target.$product_suff $target>> $product_log 2>&1
					common_var=1
					return 1
					;;
				cp)
					cp -fp  $target.$product_suff $target>> $product_log 2>&1
					common_var=1
					return 1
					;;
				*)
					p_echo " rsr_backup: wrong option -- must be 'cp' or 'mv'"
					;;
			esac
		else
			if [ -$opts "$target.$product_suffo" ]; then
			    case "$dup" in
				mv)
					mv -f  $target.$product_suffo $target>> $product_log 2>&1
					common_var=1
					return 1
					;;
				cp)
					cp -fp  $target.$product_suffo $target>> $product_log 2>&1
					common_var=1
					return 1
					;;
				*)
					p_echo " rsr_backup: wrong option -- must be 'cp' or 'mv'"
					;;
			    esac
			fi
		fi
#	else
#		case "$opts" in
#			f|d)
#				;;
#			*)
#				p_echo " rsr_backup: wrong option -- must be 'f' or 'd'"
#				;;
#		esac
#	fi
}

restore_named()
{
	cd "$PRODUCT_ROOT_D" >> $product_log 2>&1
	[ -f /etc/sysconfig/named ] && mv -f "/etc/sysconfig/named" "/etc/sysconfig/named.bak"
	rsr_backup "/etc/sysconfig/named" mv f

	[ -L $named_conf ] && rm -f "$named_conf"
	rsr_backup "$named_conf" mv f

	[ -L $rndc_conf ] && rm -f "$rndc_conf"
	rsr_backup "$rndc_conf" mv f

	case "$machine" in
		BSD*)
			rsr_backup /etc/named.boot mv f
			;;
		linux)
		    case "$linux_distr" in
			redhat)
			    chkconfig --add named >> $product_log 2>&1
#			    std_named_sh="/etc/rc.d/init.d/named"
#			    rsr_backup $std_named_sh mv f
#				if [ -f "$std_named_sh" ]; then
#					mv -f "$std_named_sh.${product}" "$std_named_sh"
#				fi
				;;
			slackware)
			    rsr_backup /etc/rc.d/rc.inet2 cp f
				;;
		    esac
			rsr_backup /etc/named.boot mv f
			;;
		solaris)
			rsr_backup /etc/named.boot mv f
			;;
	esac
}


restore_sendmail()
{
	[ -L $sendmail ] && rm -f "$sendmail"
	[ -L /usr/lib/sendmail ] && rm -f "/usr/lib/sendmail"

	rsr_backup "$sendmail" mv f

	case "$machine" in
		BSDI)
			rsr_backup /etc/sendmail.cf mv f
			;;
		*)
			;;
	esac

	if [ -f "$mail_local" ]; then
#		case "$machine" in
#			BSD)
#				chflags schg "$mail_local" >> $product_log 2>&1
#				;;
#			*)
#				;;
#		esac

		rsr_backup "$mail_local" mv f

		chmod 4555 "$mail_local" >> $product_log 2>&1
	fi
	case "$machine" in
		linux )
		    case "$linux_distr" in
			redhat)
			    chkconfig --add sendmail >> $product_log 2>&1
#			    rsr_backup "$sndml_ini" mv f
				;;
			slackware)
			     rsr_backup /etc/rc.d/rc.M mv f
				;;
		    esac
			;;
		solaris)
			rsr_backup "$sndml_ini" mv f
			;;
		*)
			;;
	esac

}

delete_startup_scripts()
{
	cd "$PRODUCT_ROOT_D" >> $product_log 2>&1

	case "$machine" in
		BSD)
			rm -f /usr/local/etc/rc.d/${product}.sh >> $product_log 2>&1
	#		rsr_backup /etc/rc.conf cp f

			rc_service "sendmail" "enable" "YES"
			rc_service "named" "enable" "YES"
			rc_service "mysqld" "enable" "NO"
			;;
		BSDI)
			if [ -f /etc/rc.local.${product} ]; then
				cp -p  /etc/rc.local.${product} /etc/rc.local >> $product_log 2>&1
			fi
			;;
		linux)
		    case "$linux_distr" in
			redhat)
			    chkconfig --del ${product}
			    rm -f /etc/rc.d/init.d/${product} >> $product_log 2>&1
#			    rm -f /etc/rc.d/rc0.d/K15${product} >> $product_log 2>&1
#			    rm -f /etc/rc.d/rc1.d/K15${product} >> $product_log 2>&1
#			    rm -f /etc/rc.d/rc2.d/K15${product} >> $product_log 2>&1
#			    rm -f /etc/rc.d/rc3.d/S77${product} >> $product_log 2>&1
#			    rm -f /etc/rc.d/rc4.d/S77${product} >> $product_log 2>&1
#			    rm -f /etc/rc.d/rc5.d/S77${product} >> $product_log 2>&1
#			    rm -f /etc/rc.d/rc6.d/K15${product} >> $product_log 2>&1
				;;
			slackware)
			    if [ -f /etc/rc.d/rc.local.${product} ]; then
				cp -p  /etc/rc.d/rc.local.${product} /etc/rc.d/rc.local >> $product_log 2>&1
			    fi
				;;
		    esac
		    ;;
		solaris)
			rm -f  /etc/init.d/${product} >> $product_log 2>&1
			if [ -f /etc/rc0.d/K01${product} ]; then
				rm -f /etc/rc0.d/K01${product} >> $product_log 2>&1
			fi

			if [ -f /etc/rc1.d/K01${product} ]; then
				rm -f /etc/rc1.d/K01${product} >> $product_log 2>&1
			fi

			if [ -f /etc/rc2.d/S77${product} ]; then
				rm -f /etc/rc2.d/S77${product} >> $product_log 2>&1
			fi
			;;
	esac
}

delete_crontab()
{

	$crontab -l 2>/dev/null > /tmp/crontab.${product}

	sed -e "s/^.*\/${product}\/admin\/sbin\/statistics.*//g" \
		-e "s/^.*\/${product}\/bin\/mysqldump.*//g" \
		-e "s/^.*\/usr\/sbin\/ntpdate.*//g" \
		< /tmp/crontab.${product} > /tmp/crontab.${product}_tmp

	mv -f /tmp/crontab.${product}_tmp /tmp/crontab.${product} >> $product_log 2>&1

	$crontab /tmp/crontab.${product}  >> $product_log 2>&1

	rm -f /tmp/crontab.${product} >> $product_log 2>&1

}

remove_ftpuser()
{
	user=$1
	ftpusers_file="/etc/ftpusers"

	egrep "^$user" $ftpusers_file >> /dev/null 2>&1

	case "$?" in
			0)
				sed -e "/$user/d" < $ftpusers_file > $ftpusers_file.tmp
				mv -f $ftpusers_file.tmp $ftpusers_file
				;;
			1)
				;;
			*)
				;;
	esac

}

remove_product_users_groups()
{

#	delete users of this(unsuccessful) installation
	for i in $users_created; do
		delete_user "$i"
	done
#	delete users with group=psacln (ftpusers and webusers)
	for i in `perl -e '$gid=getgrnam("'$clients_group'"); exit if (($gid eq "") || ($gid == 0)); while(($n,$u,$g) = (getpwent)[0,2,3]) {print "$n\n" if (($gid == $g) && ($u >= 500))}'`
	do
		delete_user "$i"
		remove_ftpuser "$i"
	done
#	delete users psaadm, psaftp
#	delete_user "$admin_user"  >> "$product_log" 2>&1
#	delete_user "$anonftp_user"  >> "$product_log" 2>&1

#	delete groups of this(unsuccessful) installation
	for i in $groups_created; do
		delete_group "$i"
	done
#	delete groups psaadm, psaftp, psacln
	delete_group "$admin_group"  >> "$product_log" 2>&1
	delete_group "$anonftp_group"  >> "$product_log" 2>&1
	delete_group "$clients_group"  >> "$product_log" 2>&1

}


undo_install()
{
	p_echo

	if pleskrc mysql status; then
		p_echo "===>Removing installed $PRODUCT_NAME components ... "
		remove_modules
		pleskrc mysql stop

		mysql_pid_file=$mysql_bddir/*.pid
		if [ -f "$mysql_pid_file" ]; then
			rm -f "$mysql_pid_file"
		fi
	fi

	$START_SH stop >> "$product_log" 2>&1

	proftpd_super_server_config remove

	super_server_action remove pop3
	super_server_action remove pop-3
	super_server_action remove imap4
	super_server_action remove imap2
	super_server_action remove imap
	qmail_super_server_config remove smtp
	qmail_super_server_config remove smtps
	qmail_super_server_config remove submission
	poppassd_super_server_config remove

	remove_product_users_groups

	if [ -f "/etc/ftpchroot" ]; then
	    sed -e "s/^@$clients_group//g" < /etc/ftpchroot > /etc/ftpchroot.tmp
	    mv -f /etc/ftpchroot.tmp /etc/ftpchroot  >> $product_log 2>&1
	fi

	if [ -f /etc/shells ]; then
	    case "$machine" in
		BSD|BSDI)
		    sed -e "s/[/]*sbin[/]*nologin//" < /etc/shells > /etc/shells.tmp
		;;
		linux|solaris)
		    sed -e "s/[/]*bin[/]*false//" < /etc/shells > /etc/shells.tmp
		;;
	    esac
	    mv -f /etc/shells.tmp /etc/shells  >> $product_log 2>&1
	fi

	remove_tmp_state

	restore_named
	restore_sendmail
	delete_startup_scripts
	delete_crontab

	cd /usr/local  >> $product_log 2>&1

	suc
}

smart_undo_install()
{
	[ "X$trigger_uninstall" = "X1" -o "X$do_patch" = "X1" -o "X$do_reconfigure" = "X1" ] && return
	[ "X$PLESK_INSTALLER_NOUNDO" != "X" ] && return
	# trigger_uninstall - trigger what smart_undo_install is already working now(recurrence)
	trigger_uninstall=1

	if [ "X$can_uninstall" = "X1" ]; then
		if [ "X$do_upgrade" = "X1" ]; then
			undo_upgrade
		else
		    if [ "X$machine" != "XBSD" ]; then
			undo_install
		    fi
		fi
	fi

	# put suggestions for user what to do
	call_optional_function failure_note
}

transaction_begin()
{
	[ -n "$TRANSACTION_STARTED" ] && die "Another transaction in progress!"
	TRANSACTION_STARTED="true"
	TRANSACTION_ROLLBACK_FUNCS=
	TRANSACTION_COMMIT_FUNCS=
	trap "transaction_rollback" HUP PIPE INT QUIT TERM EXIT
}

transaction_rollback()
{
	[ -z "$TRANSACTION_STARTED" ] && die "Transaction is not started!"
	# perform rollback actions
	local f
	for f in ${TRANSACTION_ROLLBACK_FUNCS}; do
		"$f"
	done
	TRANSACTION_STARTED=
	TRANSACTION_ROLLBACK_FUNCS=
	TRANSACTION_COMMIT_FUNCS=
	trap - HUP PIPE INT QUIT TERM EXIT
	exit 1
}

transaction_commit()
{
	[ -z "$TRANSACTION_STARTED" ] && die "Transaction is not started!"
	# perform commit actions
	local f
	for f in ${TRANSACTION_COMMIT_FUNCS}; do
		"$f"
	done
	TRANSACTION_STARTED=
	TRANSACTION_ROLLBACK_FUNCS=
	TRANSACTION_COMMIT_FUNCS=
	trap - HUP PIPE INT QUIT TERM EXIT
}

transaction_add_rollback_action()
{
	[ -z "$TRANSACTION_STARTED" ] && die "Transaction is not started!"
	# LIFO rollback order
	[ -z "$TRANSACTION_ROLLBACK_FUNCS" ] \
		&& TRANSACTION_ROLLBACK_FUNCS="$1" \
		|| TRANSACTION_ROLLBACK_FUNCS="$1 $TRANSACTION_ROLLBACK_FUNCS"
}

transaction_add_commit_action()
{
	[ -z "$TRANSACTION_STARTED" ] && die "Transaction is not started!"
	# FIFO commit order
	[ -z "$TRANSACTION_COMMIT_FUNCS" ] \
		&& TRANSACTION_COMMIT_FUNCS="$1" \
		|| TRANSACTION_COMMIT_FUNCS="$TRANSACTION_COMMIT_FUNCS $1"
}
undo_upgrade()
{
	p_echo   "    The attempt to upgrade $prev_product_full"
	p_echo   "    from version $prev_version to $product_full $product_version has failed."

	if [ -f "$product_sav_tar" ]; then
	
		p_echo 

		p_echo "    Now restore contents of $PRODUCT_NAME from $product_sav_tar"
		p_echo 
		get_pid $PRODUCT_ROOT_D/mysql/bin/safe_mysqld true root
		req_pid=$common_var
		if [ $req_pid -gt 1 ]; then
			$K_KILL $req_pid >> $product_log 2>&1 
			sleep 2
			mysql_pid_file=$mysql_bddir/*.pid
			kill_pids $PRODUCT_ROOT_D/mysql/libexec/mysqld mysql
			sleep 2
			if [ -f "$mysql_pid_file" ]; then
				rm -f $mysql_pid_file
			fi
		fi

		$START_SH stop >> $product_log 2>&1
		sleep 2

		rm -Rf $PRODUCT_ROOT_D
		qmail_super_server_config remove "smtp"
		qmail_super_server_config remove "smtps"
		proftpd_super_server_config remove
		poppassd_super_server_config remove
		

		cd /
        	tar xvf $product_sav_tar > /dev/null 2>&1
		case "$?" in
			0)
#				rm -f $product_sav_tar 		
			;;
			*)
				p_echo 
				p_echo 
				p_echo "ERROR: restoration of files from $product_sav_tar has failed."
				p_echo "       Please restore them manually."
				p_echo 
				p_echo "Exiting..."
				p_echo 
				exit 0
			;;
		esac
	fi
	
}

true postfix_status
postfix_status()
{
	# here be dragons.
	# the practical experience shows that simple checking of status of
	# Postfix "master" process is not enough. So we read Postfix master
	# process pid file if any, then try to look for a process with
	# name ``qmgr'' and parent pid being equal to
	# the pid read from the pidfile. If pgrep finds such a process
	# it returns 0, if not its exit status is non-zero.
	# pgrep is portable enough to prefer it to "hand-made" alternatives
	# such as famous ``ps | grep $name | grep -v grep...'' pipes
	# bug 147822. do not interrupt installation for FreeBSD

	[ -f "/var/spool/postfix/pid/master.pid" ] || return 1

	local ppid

	read ppid </var/spool/postfix/pid/master.pid 2>/dev/null
	if [ $? -ne 0 -o -z "$ppid" ]; then
		# not found or other error
		return 1;
	fi
	pgrep -P $ppid qmgr >/dev/null 2>/dev/null
}

set_horde_params()
{
	horde_datadir="/usr/share/psa-horde"
	horde_confdir="/etc/psa-webmail/horde"
	horde_sysconfd="$horde_confdir/horde"
	horde_logdir="/var/log/psa-horde"
	horde_passwd_file="/etc/psa-webmail/horde/.horde.shadow"
	horde_title="Horde Web Based mail client"

	imp_datadir="$horde_datadir/imp"
	imp_sysconfd="$horde_sysconfd/imp"
	
	mimp_datadir="$horde_datadir/mimp"
	mimp_sysconfd="$horde_sysconfd/mimp"

	turba_datadir="$horde_datadir/turba"
	turba_sysconfd="$horde_sysconfd/turba"

	kronolith_datadir="$horde_datadir/kronolith"
	kronolith_sysconfd="$horde_sysconfd/kronolith"

	ingo_datadir="$horde_datadir/ingo"
	ingo_sysconfd="$horde_sysconfd/ingo"

	mnemo_datadir="$horde_datadir/mnemo"
	mnemo_sysconfd="$horde_sysconfd/mnemo"
	
	passwd_datadir="$horde_datadir/passwd"
	passwd_sysconfd="$horde_sysconfd/passwd"
}

generate_horde_password()
{
	generate_password_file "$horde_passwd_file" "$horde_title" root "$apache_group" 640
	horde_password=`cat $horde_passwd_file` || die $inten
}
set_atmail_params()
{
    atmail_passwd_file="/etc/psa-webmail/atmail/.atmail.shadow"
    atmail_db_tables_template="/srv/www/atmail/install/atmail.mysql"
    atmail_db_create_template="/etc/psa-webmail/atmail/create_db.sql"
    atmail_title="Atmail Web Based mail client"
    atmail_root_d="/srv/www/atmail"
}

## @@constructor set_atmail_params
generate_atmail_password()
{
	generate_password_file "$atmail_passwd_file" "$atmail_title" root $apache_group 640
	atmail_password=`cat $atmail_passwd_file` || die "get atmail password"
}
prog="`basename $0`"
cmds_num="$#"

usage() {
cat << EOT
Usage: $prog --do-what-I-say [ --force ]

    --force         Reset instance-specific data regardless of currently 
                    active cloning mode options.

WARNING: 

You probably don't want to invoke this utility directly. It will reset ALL 
global instance-specific data on this machine, including but not limited to 
passwords, certificates, and optionally license keys.

If you are preparing a public master image for a cloud platform or 
virtualization solution take a look at 'cloning' utility.

If you are sure you need to invoke this utility directly, pass --do-what-I-say
option. Note that this utility is not designed to reset any customer data, but
only global and admin data.
EOT
	exit 1
}

# --- args check ---

while [ "$#" -gt 0 ]; do
	case "$1" in
		--do-what-I-say)
			opt_do_what_i_say="yes"
			shift
			;;
		--force)
			opt_force_instance_reset="yes"
			shift
			;;
		--psa-init)
			opt_psa_init_context="yes"
			shift
			;;
		-h|--help)
			usage
			;;
		*)
			echo "Unknown argument '$1'"
			echo
			usage
			;;
	esac
done

[ "$opt_do_what_i_say" = "yes" ] || usage

# --- logging ---

rstinst_log_title()
{
	local title="Doing $prog"
	if [ "$opt_force_instance_reset" = "yes" ]; then
		title="$title --force"
	fi
	if [ "$opt_psa_init_context" = "yes" ]; then
		title="$title --psa-init"
	fi
	title="$title AT `date`"
	echo "$title"
}

rstinst_transaction_begin()
{
	set_log_action_name "$prog"
	log_start "`rstinst_log_title`"
	set_error_report_context "`rstinst_log_title`"

	product_default_conf
	initial_conf
	set_common_params
	read_conf
	set_mysql_client_params
	set_apache_params

	transaction_begin

	# LIFO rollback order
	transaction_add_rollback_action "rstinst_log_stop"
}

rstinst_transaction_end()
{
	# FIFO commit order
	transaction_add_commit_action "rstinst_log_stop"
	transaction_commit
}

rstinst_log_stop()
{
	log_stop "`rstinst_log_title`" "Product instance-specific data reset"
}

# --- utility functions ---

rstinst_check_bool_misc_param()
{
	local param="$1"
	local default_value="$2"
	[ -n "$param" ] || die "rstinst_check_bool_misc_param(): parameter name required"
	[ -n "$default_value" ] || default_value="false"

	db_select "SELECT val FROM misc WHERE param = '$param'"
	[ -n "$db_select_output" ] || db_select_output="$default_value"
	[ "$db_select_output" = "true" ]
}

rstinst_is_license_keys_reset_enabled()
{
	rstinst_check_bool_misc_param "vps_cloning_license_reset"
}

rstinst_is_public_image_cloning_mode_enabled()
{
	rstinst_check_bool_misc_param "vps_cloning_mode"
}

rstinst_disable_public_image_cloning_mode()
{
	db_do "DELETE FROM misc WHERE param = 'vps_cloning_mode'"
}

rstinst_reconfigure_apache()
{
	pp_echo " Reconfiguring Apache..."
	# This is at least needed to accommodate to default certificate change.
	# However, normaly there are no domains when this utility is called, 
	# so it shouldn't take long.
	#reconfigure_apache_if_needed

	# Unfortunately there is a bug #93128, which will make the call above
	# fail if there are any domains. Workaround - reconfigure-domains first.
	if [ -n "$apache_need_reconfiguration" ]; then
		echo_try "reconfigure webserver"

		local httpdmng_bin="$PRODUCT_ROOT_D/admin/sbin/httpdmng"
		db_select "SELECT name FROM domains"
		if [ -n "$db_select_output" ]; then
			local domains=`echo "$db_select_output" | tr '\n' ',' | sed -e 's/,$//'`
			if [ -n "$domains" ]; then
				echo_try "reconfigure domains (fail on 'apache-config -t' is OK)"
				p_echo "[ " "$httpdmng_bin" --reconfigure-domains "$domains" -no-restart " ]"
				"$httpdmng_bin" --reconfigure-domains "$domains" -no-restart >> $product_log 2>&1
			fi
		fi

		local restart_action
		# Apache (re)start is done by psa init script
		[ "$opt_psa_init_context" = "yes" ] && restart_action="-no-restart"

		echo_try "reconfigure server (all)"
		p_echo "[ " "$httpdmng_bin" --reconfigure-all $restart_action " ]"
		"$httpdmng_bin" --reconfigure-all $restart_action >> $product_log 2>&1 && \
		suc && \
		unset apache_need_reconfiguration
	fi
}

rstinst_reread_admin_passwd()
{
	admin_passwd=
	set_mysql_auth
}

rstinst_set_admin_passwd()
{
	local new_admin_passwd="$1"
	local init_conf_bin="$PRODUCT_ROOT_D/bin/init_conf"
	if PSA_PASSWORD="$new_admin_passwd" "$init_conf_bin" --set-admin-password -passwd '' ; then
		rstinst_reread_admin_passwd
	else
		warn "set new admin password"
	fi
}

rstinst_show_admin_info_conf_screen()
{
	p_echo "  Sheduling admin info configuration screen to be shown on next login..."

	db_do "DELETE FROM misc WHERE param = 'admin_info_not_required'"
	db_do "UPDATE clients SET email = NULL WHERE type = 'admin'"
}

rstinst_show_ip_and_passwd_conf_screen()
{
	p_echo "  Sheduling IPs, hostname and password setup screen to be shown on next login..."

	db_do "DELETE FROM misc WHERE param = 'psa_configured'"
}

rstinst_clean_panel_sessions()
{
	# This is done by psa init script, therefore not needed here unless this script is called manually
	[ "$opt_psa_init_context" != "yes" ] || return 0

	p_echo "  Cleaning Panel sessions..."
	db_do "DELETE FROM sessions"
	rm -f $PRODUCT_ROOT_D/admin/sessions/*
}

# --- password generation ---

rstinst_gen_passwd()
{
	get_random_string 16 'A-Za-z0-9_'
}

rstinst_reset_admin_passwd()
{
	pp_echo "  Generating new admin password..."
	rstinst_set_admin_passwd `rstinst_gen_passwd`
}

rstinst_reset_sitebuilder_passwd()
{
	local sb_conf="/usr/local/sb/config"
	[ -f "$sb_conf" ] || return 0

	local sb_host=`get_ini_conf_var "$sb_conf" "database" "host"`
	is_local_mysql_instance "$sb_host" || return 0

	pp_echo "  Generating new WPB (sitebuilder) password..."

	set_ini_conf_var "$sb_conf" "database" "password" `rstinst_gen_passwd`
	reset_sitebuilder_passwd
}

rstinst_reset_billing_passwd()
{
	pp_echo "  Generating new CBM (billing) password..."
	reset_billing_passwd
}

rstinst_reset_apsc_passwd()
{
	check_apsc_installed || return 0

	read_apsc_connection_params_db
	is_local_mysql_instance "$apsc_db_host" || return 0

	pp_echo "  Generating new APS controller password..."

	apsc_db_passwd=`rstinst_gen_passwd`
	reset_user_password "$apsc_db_user" "$apsc_db_passwd" "$apsc_db_host" && \
	check_db_accessible "$apsc_db_name" "$apsc_db_user" "$apsc_db_passwd" && \
	save_apsc_connection_params_db
}

rstinst_reset_horde_passwd()
{
	set_horde_params
	[ -s "$horde_passwd_file" ] || return 0

	local hor_host=`get_horde_config_param "['sql']['hostspec']" "localhost"`
	is_local_mysql_instance "$hor_host" || return 0

	pp_echo "  Generating new $horde_title password..."

	rm -f "$horde_passwd_file" && \
	generate_horde_password && \
	reset_horde_passwd
}

rstinst_reset_atmail_passwd()
{
	set_atmail_params
	[ -s "$atmail_passwd_file" ] || return 0

	local at_host=`get_atmail_config_param "['sql_host']" "localhost"`
	is_local_mysql_instance "$at_host" || return 0

	pp_echo "  Generating new $atmail_title password..."

	rm -f "$atmail_passwd_file" && \
	generate_atmail_password && \
	reset_atmail_passwd
}

rstinst_reset_phpmyadmin_passwd()
{
	set_phpmyadmin_params
	phpmyadmin_config_backup || return 0

	pp_echo "  Generating new phpMyAdmin password..."

	local pmahost="localhost"
	local controluser controlpass pmadb bookmarktable relation table_info table_coords pdf_pages column_info history designer_coords tracking userconfig
	pma__read_values_from_config_backup
	controlpass=`rstinst_gen_passwd`

	[ -n "$controlpass" -a -n "$controluser" -a -n "$pmadb" ] && \
	pma__write_values_to_config && \
	reset_user_password "$controluser" "$controlpass" "$pmahost" && \
	check_db_accessible "$pmadb" "$controluser" "$controlpass"
}

# --- certificate generation ---

rstinst_delete_certificate_from_store()
{
	local cert_name_pattern="$1"
	[ -n "$cert_name_pattern" ] || die "rstinst_delete_certificate_from_store(): certificate pattern required"

	db_select "SELECT ca_file, cert_file FROM certificates WHERE name like '$cert_name_pattern'"
	for c_file in $db_select_output; do
		rm -f "${PRODUCT_ROOT_D}/var/certificates/${c_file}"
	done

	db_do "DELETE r, c FROM Repository r INNER JOIN certificates c ON (c.id = r.component_id)
			WHERE c.name LIKE '$cert_name_pattern'"
}

rstinst_update_default_cert_copy()
{
	local src="$certificate_file"
	local dst="$1"
	[ -n "$dst" ] || die "rstinst_update_default_cert_copy(): certificate file required"

	if diff -q "$certificate_file_old" "$dst" >/dev/null 2>&1 ; then
		cp -fp "$src" "$dst"
		set_ac 0 0 0400 "$dst"
	else
		p_echo "Not touching custom or absent certificate $dst"
	fi
}

rstinst_reset_default_cert()
{
	pp_echo "  Creating default certificate backup..."

	certificate_file_old="$certificate_file.old"
	cp -fp "$certificate_file" "$certificate_file_old"

	db_select "SELECT val FROM misc WHERE param = 'default_certificate_id'"
	local old_default_certificate_id="$db_select_output"

	pp_echo "  Generating new default certificate..."

	rstinst_delete_certificate_from_store "default certificate"
	rm -f "$certificate_file"
	last_certificate_id=

	generate_default_certificate && \
	db_do "DELETE FROM misc WHERE param = 'default_certificate_id'" && \
	# psa.misc.param='cert_rep_id' is left untouched intentionally (to be preserved on import)
	import_default_certificate && \
	db_do "UPDATE IP_Addresses SET ssl_certificate_id = '$last_certificate_id' 
			WHERE ssl_certificate_id = '$old_default_certificate_id'" && \
	# normally psa.hosting would not reference default cert directly, it would use '0' for that
	db_do "UPDATE hosting SET certificate_id = '$last_certificate_id'
			WHERE certificate_id = '$old_default_certificate_id'" && \
	defer_apache_reconfiguration
}

rstinst_wipe_old_default_cert()
{
	pp_echo "  Removing default certificate backup..."
	rm -f "$certificate_file_old"
}

rstinst_reset_admin_cert()
{
	set_admin_params
	pp_echo "  Updating Panel webserver certificate..."

	rstinst_update_default_cert_copy "$ADMIN_CERT"
}

rstinst_reset_apache_cert()
{
	set_apache_params
	pp_echo "  Updating Apache certificate..."

	rstinst_update_default_cert_copy "$APACHE_CERT" && \
	defer_apache_reconfiguration
}

rstinst_reset_courier_imap_certs()
{
	set_courier_imap_params
	pp_echo "  Updating Courier-IMAP certificates..."

	rstinst_update_default_cert_copy "$IMAPD_CERT"
	rstinst_update_default_cert_copy "$POP3D_CERT"
}

rstinst_reset_qmail_certs()
{
	set_qmail_params
	local qmail_control_d="$QMAIL_ROOT_D/control"
	local qmail_tls_cert="$qmail_control_d/rsa512.pem"
	local qmail_client_cert="$qmail_control_d/clientcert.pem"
	local qmail_server_cert="$qmail_control_d/servercert.pem"
	[ -d "$qmail_control_d" ] || return 0

	pp_echo "  Generating new QMail certificates..."

	local qmail_user=qmaild
	local qmail_group=qmail
	if ! id "$qmail_user" 1>/dev/null 2>&1 || ! groupmod "$qmail_group" 1>/dev/null 2>&1 ; then
		# Qmail may not be actually installed, but we need to update certs nonetheless
		qmail_user=root
		qmail_group=0
	fi

	rm -f "$qmail_tls_cert" && \
	[ "$qmail_user" != "root" ] && generate_tls_certificates

	rstinst_update_default_cert_copy "$qmail_server_cert" && \
	set_ac "$qmail_user" "$qmail_group" 0640 "$qmail_server_cert"

	if [ ! -L "$qmail_client_cert" ] || [ "`readlink $qmail_client_cert`" != "$qmail_server_cert" ]; then
		rstinst_update_default_cert_copy "$qmail_client_cert" && \
		set_ac "$qmail_user" "$qmail_group" 0640 "$qmail_client_cert"
	fi
}

rstinst_reset_backup_cert()
{
	db_select "SELECT val FROM misc WHERE param = 'bu_cert_id'"
	local bu_cert_id="$db_select_output"
	if [ -n "$bu_cert_id" ]; then
		pp_echo "  Generating new certificate for backup signing..."

		db_do "DELETE FROM misc WHERE param = 'bu_cert_id'; DELETE FROM certificates WHERE id = $bu_cert_id" && \
		pbm_create_certificate
	fi
}

# --- reset actions ---

rstinst_remap_ips()
{
	pp_echo " Reconfiguring IP addresses..."
	$PRODUCT_ROOT_D/bin/reconfigurator --autoconfigure >> $product_log 2>&1
}

rstinst_generate_passwords()
{
	local cu_passwd

	pp_echo " Generating new passwords..."

    rstinst_regenerate_secret_key

	rstinst_reset_admin_passwd
	rstinst_reset_sitebuilder_passwd
	rstinst_reset_billing_passwd
	rstinst_reset_apsc_passwd
	rstinst_reset_horde_passwd
	rstinst_reset_atmail_passwd
	rstinst_reset_phpmyadmin_passwd
	# Postgres is not configured by default.
}

rstinst_regenerate_secret_key()
{
    ${PLESK_LIBEXEC_DIR}/cloning_helper || warn 'Error during encrypted key regenerate'
    rstinst_reread_admin_passwd
}


rstinst_reset_libswkey_store()
{
	rstinst_is_license_keys_reset_enabled || return 0
	pp_echo " Resetting license keys store..."

	local swkey_store="/etc/sw/keys"
	rm -rf $swkey_store/backup/*
	rm -rf $swkey_store/keys/*
	rm -rf $swkey_store/instances
	rm -f  $swkey_store/registry.xml
	install_default_license_key
}

rstinst_generate_certificates()
{
	pp_echo " Generating new certificates..."
	rstinst_reset_default_cert
	rstinst_reset_admin_cert
	rstinst_reset_apache_cert
	rstinst_reset_courier_imap_certs
	rstinst_reset_qmail_certs
	rstinst_reset_backup_cert
	# We don't reset Google Apps and other customizable certs

	rstinst_wipe_old_default_cert
}

rstinst_generate_guids()
{
	pp_echo " Generating new GUIDs for BL entities..."

	db_do "UPDATE clients       SET guid = UUID();
	       UPDATE domains       SET guid = UUID();
	       UPDATE Templates     SET uuid = UUID();
	       UPDATE Subscriptions SET uuid = UUID();
	       UPDATE PlanItems     SET uuid = UUID();
	       UPDATE dns_refs      SET  uid = UUID();
	       UPDATE smb_users     SET uuid = UUID();
	       "
}

rstinst_reshuffle_cron_tasks()
{
	pp_echo " Randomizing cron tasks execution time shifts..."

	remove_cron_somely; install_cron_somely
	update_postfix_poplockdb_cleanup_crontab
	remove_cron_backup; install_cron_backup
}

rstinst_reset_thirdparties()
{
	:
}

rstinst_shedule_init_conf_screens()
{
	pp_echo " Enabling initial configuration screens on next admin login..."

	license_show_request
	rstinst_show_admin_info_conf_screen
	rstinst_show_ip_and_passwd_conf_screen
	rstinst_clean_panel_sessions
}

rstinst_reset_all()
{
	pp_echo "Resetting instance-specific settings..."
	rstinst_remap_ips
	rstinst_generate_guids
	rstinst_generate_passwords
	rstinst_generate_certificates
	rstinst_reshuffle_cron_tasks
	rstinst_reset_thirdparties
	rstinst_reset_libswkey_store
	rstinst_shedule_init_conf_screens
}

rstinst_update_all_services()
{
	pp_echo "Reloading services configuration..."
	rstinst_reconfigure_apache
	# We would also need to restart various services, if the script was run manually.
	# But that is not a top priority right now.
}

# --- the script ---

# Note: general prolicy for this script is to avoid interrupting its 
# execution unless something _extremely_ bad happened.
# Ideally we should execute each action that might fail in a separate
# subshell. But that would dramatically influence global variables 
# and therefore probably introduce a couple of new critical bugs.

rstinst_transaction_begin

if [ "$opt_force_instance_reset" != "yes" ] && ! rstinst_is_public_image_cloning_mode_enabled ; then
	pp_echo "Refusing to reset instance-specific data."
	if [ "$opt_psa_init_context" != "yes" ]; then
		echo
		usage
	fi
	exit 1
fi

rstinst_disable_public_image_cloning_mode
rstinst_reset_all
rstinst_update_all_services
pp_echo "Completed"

rstinst_transaction_end

# vim:syntax=sh
