#!/bin/bash
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
#

#
# Plesk script
#


### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
upgrade_transfer_pmm_logs_11_6_1()
{
	local old_dir="${PRODUCT_ROOT_D}/PMM/logs"
	local new_dir="${PRODUCT_LOGS_D}/PMM"

	if [ -d "$old_dir" -a ! -L "$old_dir" ] ; then
		local moved='false'
		if [ ! -e "$new_dir" ] ; then
			mv -f "$old_dir" "$new_dir"
			if [ "$?" = "0" ] ; then
				moved='true'
			else
				warn "move '$old_dir' to '$new_dir'"
			fi
		fi
		if [ "$moved" = 'false' ]; then
			new_dir="${new_dir}.$product_suff"
			mv -f "$old_dir" "$new_dir" || \
				{ warn "move '$old_dir' to '$new_dir'"; return 1; }
		fi

		ln -s "$new_dir" "$old_dir" || \
			warn "unable to create compatibility symlink '$old_dir' to '$new_dir'"
	fi
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
# vim:syntax=sh

generate_encryption_key()
{
	local key_file="/etc/psa/private/secret_key"
	local key_dir="`dirname $key_file`"
	local rc=0

	[ -d "$key_dir" ] || mkdir -p "$key_dir"

	if [ ! -e "$key_file" ]; then
		dd if=/dev/urandom of="$key_file" bs=16 count=1 2>/dev/null
	else
		rc=1
	fi
	fix_key_permissions
	return $rc
}

fix_key_permissions()
{
	local key_file="/etc/psa/private/secret_key"
	local key_dir="`dirname $key_file`"

	if [ -e "$key_file" ]; then
		chown psaadm:0 "$key_file"
		chmod 0600 "$key_file"
	fi

	if [ -d "$key_dir" ]; then
		chown psaadm:0 "$key_dir"
		chmod 0700 "$key_dir"
	fi
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
set_apache_params()
{
	apache_user="apache"
	apache_UID=80
	apache_group="apache"
	apache_GID=80

	user_apxs="/usr/sbin/apxs"

	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="httpd"

	apache_modules_d="/usr/lib/httpd/modules"

	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/lib/plesk-9.0/suexec
	suexec=/usr/sbin/suexec
	suexec_dir=/usr/sbin
	suexec_file=suexec

	rpm_httpd_bin=/usr/sbin/httpd
}

php_upgrade_system_handlers_pre_12_1_18()
{
	local php_versions_json="/etc/psa/php_versions.json"
	cp -f "${php_versions_json}" "${php_versions_json}.pre_upg"
}

php_upgrade_system_handlers_post_12_1_18()
{
	local php_versions_json="/etc/psa/php_versions.json"
	if [ -e "${php_versions_json}.pre_upg" ]; then
		mv -f "${php_versions_json}.pre_upg" "${php_versions_json}"
	fi
	rm -f "${php_versions_json}.rpmsave"
}

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. Don't use it.
	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"`
}

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

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

## @@constructor set_awstats_params

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

update_statistics_path_in_awstats_confs()
{
	[ -z "$*" ] && return
	sed -i '{ /\/system\/[^/]\+\/statistics\//b; s:\(DirData=\)\"\(.*\)/\([^/]\+\)/statistics/\(.*\)\":\1\"\2/system/\3/statistics/\4\": }' "$@"
}

upgrade_domains_awstats_conf_11_5_24()
{
	update_statistics_path_in_awstats_confs `ls $PRODUCT_ROOT_D/etc/awstats/*.conf 2>/dev/null`
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
# Backup manager tables will be managed by plesk

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
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
# vim:ft=sh:

#courier-imap

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

	# Certificate paths for Courier-IMAP <= 3.0.8
	OLD_IMAPD_CERT="/usr/share/courier-imap/imapd.pem"
	OLD_POP3D_CERT="/usr/share/courier-imap/pop3d.pem"

	COURIER_DELIVER_QUOTA="/usr/bin/deliverquota"

	courier_imapd_service="courier-imapd"
	courier_imaps_service="courier-imaps"
	courier_pop3d_service="courier-pop3d"
	courier_pop3s_service="courier-pop3s"
	courier_authdaemon_service="courier-authdaemon"

	# Service name for Courier-IMAP <= 3.0.8
	old_courier_service="courier-imap"
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
upgrade_courier_imap_auth_1013()
{
	set_courier_imap_params
	local IMAP_CFG="$COURIERIMAP_CONFDIR/imapd"
	local POP3_CFG="$COURIERIMAP_CONFDIR/pop3d"
	local imap_pci_comp pop3_pci_comp

	ls $IMAP_CFG.pci.* 1>/dev/null 2>&1 && imap_pci_comp="on"
	ls $POP3_CFG.pci.* 1>/dev/null 2>&1 && pop3_pci_comp="on"

	# sed code is taken from 10.4.4/MU5/MU-imapd.sh
	if [ "$imap_pci_comp" != "on" ]; then
		if ! egrep -q '^IMAP_CAPABILITY="?[^"]*AUTH=[^"]*"?\s*$' $IMAP_CFG 2>/dev/null ; then
			cp $IMAP_CFG $IMAP_CFG.plesk.bak && \
			sed -e "s/^IMAP_CAPABILITY=\(.*\) IDLE\\\"$/IMAP_CAPABILITY=\\1 AUTH=CRAM-MD5 AUTH=PLAIN IDLE\\\"/g" \
				-e "s/^IMAP_CAPABILITY_ORIG=\(.*\) IDLE\\\"$/IMAP_CAPABILITY_ORIG=\\1 AUTH=PLAIN IDLE\\\"/g" \
				-e "s/^IMAP_CAPABILITY_TLS=.*$/IMAP_CAPABILITY_TLS=\\\"\\\$IMAP_CAPABILITY\\\"/g" \
				-e "s/^IMAP_CAPABILITY_TLS_ORIG=.*$/IMAP_CAPABILITY_TLS_ORIG=\\\"\\\$IMAP_CAPABILITY_ORIG\\\"/g" \
				<$IMAP_CFG >$IMAP_CFG.plesk.tmp &&
			mv $IMAP_CFG.plesk.tmp $IMAP_CFG || rm -f $IMAP_CFG.plesk.{tmp,bak}
		fi
	fi

	if [ "$pop3_pci_comp" != "on" ]; then
		if egrep -q '^POP3AUTH(_TLS)?=("\s*")?\s*$' $POP3_CFG 2>/dev/null ; then
			cp $POP3_CFG $POP3_CFG.plesk.bak && \
			sed -e "s/^POP3AUTH=.*$/POP3AUTH=\\\"LOGIN CRAM-MD5 PLAIN\\\"/g" \
				-e "s/^POP3AUTH_ORIG=.*$/POP3AUTH_ORIG=\\\"LOGIN CRAM-MD5 PLAIN\\\"/g" \
				-e "s/^POP3AUTH_TLS=.*$/POP3AUTH_TLS=\\\"LOGIN CRAM-MD5 PLAIN\\\"/g" \
				-e "s/^POP3AUTH_TLS_ORIG=.*$/POP3AUTH_TLS_ORIG=\\\"LOGIN CRAM-MD5 PLAIN\\\"/g" \
				<$POP3_CFG >$POP3_CFG.plesk.tmp && \
			mv $POP3_CFG.plesk.tmp $POP3_CFG || rm -f $POP3_CFG.plesk.{tmp,bak}
		fi
	fi
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
# vim:ft=sh:

set_poplock_params()
{
	set_mail_params

	PLESK_POSTFIX_DB_ROOT="/var/spool/postfix/plesk"
	PLESK_POSTFIX_POP_DB_ROOT="/var/spool/postfix/plesk-pop"
	PLESK_POSTFIX_POPLOCK_DB="hash:/var/spool/postfix/plesk-pop/poplock"
	POSTFIX_POPLOCK_DB_PATH="/var/spool/postfix/plesk-pop/poplock.db"
	POSTFIX_POPLOCK_DB_PERM="0460"
	POSTFIX_POPLOCK_DB_USER="postfix"
	POSTFIX_POPLOCK_DB_GROUP="$MAIL_USERGROUP"

	QMAIL_POPLOCK_DB_DIR="/var/lib/plesk/mail/poplock"
	QMAIL_POPLOCK_DB_PATH="/var/lib/plesk/mail/poplock/poplock.db"
	QMAIL_POPLOCK_DB_PERM="0660"
	QMAIL_POPLOCK_DB_USER="$MAIL_USERGROUP"
	QMAIL_POPLOCK_DB_GROUP="nofiles"
}

poplock_db_qmail_upgrade_to_courier_4_12()
{
	[ -d "$QMAIL_POPLOCK_DB_DIR" ] || return 0
	[ -f "$QMAIL_POPLOCK_DB_PATH" ] || return 0
	get_userID "$QMAIL_POPLOCK_DB_USER" && get_groupID "$QMAIL_POPLOCK_DB_GROUP" || return 0

	set_ac "$QMAIL_POPLOCK_DB_USER" "$QMAIL_POPLOCK_DB_GROUP" 0770 "$QMAIL_POPLOCK_DB_DIR"
	set_ac "$QMAIL_POPLOCK_DB_USER" "$QMAIL_POPLOCK_DB_GROUP" "$QMAIL_POPLOCK_DB_PERM" "$QMAIL_POPLOCK_DB_PATH"
}

poplock_db_postfix_upgrade_to_courier_4_12()
{
	[ -d "$PLESK_POSTFIX_DB_ROOT" -a -d "$PLESK_POSTFIX_POP_DB_ROOT" ] || return 0
	local old_poplock_db_path="$PLESK_POSTFIX_DB_ROOT/`basename $POSTFIX_POPLOCK_DB_PATH`"
	[ -f "$old_poplock_db_path" -a ! -L "$old_poplock_db_path" ] || return 0
	get_userID "$POSTFIX_POPLOCK_DB_USER" && get_groupID "$POSTFIX_POPLOCK_DB_GROUP" || return 0

	mv -f "$old_poplock_db_path" "$POSTFIX_POPLOCK_DB_PATH" 2>>"$product_log"
	set_ac "$POSTFIX_POPLOCK_DB_USER" "$POSTFIX_POPLOCK_DB_GROUP" "$POSTFIX_POPLOCK_DB_PERM" "$POSTFIX_POPLOCK_DB_PATH"
	ln -s "../`basename $PLESK_POSTFIX_POP_DB_ROOT`/`basename $POSTFIX_POPLOCK_DB_PATH`" "$old_poplock_db_path" 2>>"$product_log"

	# we should be able to skip reconfiguring Postfix thanks to compatibility symlink, but we'll do it nonetheless
	[ -s "/etc/postfix/main.cf" ] || return 0
	
	set_postfix_params

	local poplock_hash_basename="`basename $PLESK_POSTFIX_POPLOCK_DB`"
	local filtered_value="`read_postconf_value 'mynetworks' | sed -e 's|^.*/'$poplock_hash_basename'$|'$PLESK_POSTFIX_POPLOCK_DB'|'`"
	write_postconf_value 'mynetworks' "$filtered_value" || return 1
	pleskrc postfix reload
}

upgrade_courier_to_4_12_pop_before_smtp_11_5_23()
{
	set_poplock_params

	# poplock.db files for both QMail and Postfix may be present (e.g., if there was a mail provider switch before upgrade)
	# therefore we attempt to run both upgraders. Each of them just does nothing if not applicable, so that's OK.
	poplock_db_qmail_upgrade_to_courier_4_12 && poplock_db_postfix_upgrade_to_courier_4_12
}

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
}


# add_db_changes [--fix] version
# Runs ${PRODNAME}_db_upgrade_${version}.sql
# (with --fix, runs ${PRODNAME}_db_upgrade_${version}_fix.sql)
add_db_changes()
{
	if [ "$db_fix_check_stage" = "yes" ]; then
		return
	fi

	local inten upgrade_db_sql fix
	fix=""
	eval `sh_get_args '--fix) fix="_fix";;'`
	inten="upgrade SQL database from $1"
	upgrade_db_sql="$PRODUCT_BOOTSTRAPPER_DIR/db/${PRODNAME}_db_upgrade_${1}${fix}.sql"
	mysql < $upgrade_db_sql >> "$product_log" 2>&1 || die "$inten"
}

# db_fix_add_column [--init def_value] table column type
# Adds a column of the specified type to the table, optionally
# initializing it with def_value, which is an SQL expression. If the
# column already exists, does nothing
db_fix_add_column()
{
	local def_value=""
	eval `sh_get_args '--init) def_value="$2"; shift;;'`
	local table="$1"
	local column="$2"
	local type="$3"

	if [ "$db_fix_check_stage" = "yes" ]; then
		if ! db_test "DESC $table" "\$1 == \"$column\""; then
			if [ -z "$db_added_columns" ]; then
				db_added_columns="$table.$column"
			else
				db_added_columns="$db_added_columns|$table.$column"
			fi
		fi
		return
	fi

	local query="ALTER TABLE \`$table\` ADD \`$column\` $type"
	if [ -n "$def_value" ]; then
		query="$query; UPDATE \`$table\` SET \`$column\`=$def_value"
	fi
	db_do_if_not "DESC $table" "\$1 == \"$column\"" "$query"
}

# db_fix_change_column [--init def_value] table column type
# Changes a column of the specified type to the table, optionally
# initializing it with def_value, which is an SQL expression.
# Changes a column from the table if it exists
db_fix_change_column()
{
	if [ "$db_fix_check_stage" = "yes" ]; then
		return
	fi

	local def_value=""
	eval `sh_get_args '--init) def_value="$2"; shift;;'`
	local table="$1"
	local old_column="$2"
	local new_column="$3"
	local type="$4"

	local query="ALTER TABLE \`$table\` CHANGE \`$old_column\` \`$new_column\` $type"
	if [ -n "$def_value" ]; then
		query="$query; UPDATE \`$table\` SET \`$new_column\`=$def_value"
	fi
	db_do_if "DESC \`$table\`" "\$1 == \"$old_column\"" "$query"
}

# db_fix_del_column table column
# Deletes a column from the table if it exists
db_fix_del_column()
{
	if [ "$db_fix_check_stage" = "yes" ]; then
		return
	fi

	local table="$1"
	local column="$2"

	db_do_if "DESC \`$table\`" "\$1 == \"$column\"" "ALTER TABLE \`$table\` DROP \`$column\`"
}

# subset set1 set2
# Return true if set1 is subset of set2, false otherwise
# set1 and set2 are comma separated lists of strings
subset()
{
	local first=$1
	shift
	local second=$1

	local f=`mktemp`
	echo $first | tr ',' '\n' | sort | uniq > $f

	local s=`mktemp`
	echo $second | tr ',' '\n' | sort | uniq > $s

	local rc=`comm -23 $f $s | head -1`
	rm -f $f $s
	[ -z $rc ] && return 0 || return 1
}

# db_fix_add_key [--name key_name] table column [column ...]
# Adds a non-unique [compound] key on the specified columns of the
# table. If the key already exists, or there is another key that
# substitutes this one, nothing is done. Existing keys that are
# substituted by the new one are dropped. Explicit key name
# can be specified by option --name
db_fix_add_key()
{
	if [ "$db_fix_check_stage" = "yes" ]; then
		return
	fi

	local name=""
	eval `sh_get_args '--name) name="$2"; shift;;'`
	local table="$1"
	local columns="$2"
	shift 2
	local i
	for i; do
		columns="$columns,\`$i\`"
	done
	local type iname icolumns
	local found=no
	db_get_keys "$table" | (
		while read type iname icolumns; do
			if subset "$icolumns" "$columns" && [ "$name" = "$iname" ]; then
				found=yes
				break
			elif [ "$name" = "$iname" ] || subset "$columns" "$icolumns"; then
				if [ "$type" = "KEY" ]; then
					db_do "ALTER TABLE \`$table\` DROP KEY \`$iname\`"
				fi
			fi
		done

		if [ "$found" = no ]; then
			if [ -z "$name" ]; then
				db_do "ALTER TABLE \`$table\` ADD KEY ($columns)"
			else
				db_do "ALTER TABLE \`$table\` ADD KEY \`$name\` ($columns)"
			fi
		fi
		exit 0
	)
	local status="$?"
	if [ "$status" -ne 0 ]; then
		exit "$status"
	fi
}

# db_fix_drop_key [--name key_name] table column [column ...]
# Drops a non-unique [compound] key on the specified columns of the
# table. If the key does not exist, nothing is done
# if key_name is present, it will be removed by name, columns arguments 
# are ignored
db_fix_drop_key()
{
	if [ "$db_fix_check_stage" = "yes" ]; then
		return
	fi

	local name=""
	eval `sh_get_args '--name) name="$2"; shift;;'`

	local table="$1"
	shift

	local columns=`implode "," "$@"`
	local type iname icolumns
	local found=no
	db_get_keys "$table" | (
		while read type iname icolumns; do
			if [ -n "$name" -a "$name" = "$iname" ] || [ "$icolumns" = "$columns" ]; then
				if [ "$type" = "KEY" ]; then
					db_do "ALTER TABLE $table DROP KEY $iname"
					break
				fi
			fi
		done
		exit 0
	)
	local status="$?"
	if [ "$status" -ne 0 ]; then
		exit "$status"
	fi
}

# db_fix_add_unique_key [--check-where condition] [--name key_name] table column [column ...]
# Adds a unique [compound] key on the specified columns of the table.
# If the key already exists, or there is another key that substitutes
# this one, nothing is done. Existing keys that are substituted by the
# new one are dropped. If --check-where is specified, limit checking
# to rows that satisfy the given SQL condition. Explicit key name
# can be specified by option --name
db_fix_add_unique_key()
{
	local check_where="" name=""
	eval `sh_get_args '--check-where) check_where="--where \"$2\""; shift;; --name) name="$2"; shift;;'`
	if [ "$db_fix_check_stage" = "yes" ]; then
		eval db_check_unique $check_where "$@"
		return
	fi

	local table="$1"
	local columns="$2"
	local esc_columns="$2"
	shift 2
	local i
	for i; do
		columns="$columns,$i"
		esc_columns="$esc_columns,\`$i\`"
	done
	local type iname icolumns
	local found=no
	db_get_keys "$table" | (
		while read type iname icolumns; do
			if subset "$icolumns" "$columns" && [ "$name" = "$iname" ]; then
				if [ "$type" != "KEY" ]; then
					found=yes
					break
				fi
			elif [ "$name" = "$iname" ] || subset "$columns" "$icolumns"; then
				if [ "$type" != "PRIMARY" ]; then
					db_do "ALTER TABLE \`$table\` DROP KEY \`$iname\`"
				fi
			fi
		done
		if [ "$found" = no ]; then
			if [ -z "$name" ]; then
				db_do "ALTER TABLE \`$table\` ADD UNIQUE ($esc_columns)"
			else
				db_do "ALTER TABLE \`$table\` ADD UNIQUE \`$name\` ($esc_columns)"
			fi
		fi
		exit 0
	)
	local status="$?"
	if [ "$status" -ne 0 ]; then
		exit "$status"
	fi
}

# db_fix_drop_unique_key [--name key_name] table column [column ...]
# Drops an unique [compound] key on the specified columns of the
# table. If the key does not exist, nothing is done
# if key_name is present, it will be removed by name, columns arguments 
# are ignored
db_fix_drop_unique_key()
{
	if [ "$db_fix_check_stage" = "yes" ]; then
		return
	fi

	local name=""
	eval `sh_get_args '--name) name="$2"; shift;;'`

	local table="$1"
	shift
	local columns=`implode "," "$@"`
	local type iname icolumns
	local found=no
	db_get_keys "$table" | (
		while read type iname icolumns; do
			if [ -n "$name" -a "$name" = "$iname" ] || [ "$icolumns" = "$columns" ]; then
				if [ "$type" = "UNIQUE" ]; then
					db_do "ALTER TABLE $table DROP KEY $iname"
					break
				fi
			fi
		done
		exit 0
	)
	local status="$?"
	if [ "$status" -ne 0 ]; then
		exit "$status"
	fi
}

# db_fix_drop_table table_name
db_fix_drop_table()
{
	local table_name
	table_name="$1"

	db_do "DROP TABLE IF EXISTS \`$table_name\`"
}

# 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_do_if test_query awk_script query
# If db_test test_query awk_script returns zero (true), run the query.
# If any query fails, die
db_do_if()
{
	if [ "$db_fix_check_stage" = "yes" ]; then
		return
	fi

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

	if db_test "$test_query" "$awk_script"; then
		db_do "$query"
	fi
}

# db_do_if_not test_query awk_script query
# If db_test test_query awk_script returns nonzero (false), run the
# query. If any query fails, die
db_do_if_not()
{
	if [ "$db_fix_check_stage" = "yes" ]; then
		return
	fi

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

	if ! db_test "$test_query" "$awk_script"; then
		db_do "$query"
	fi
}

# db_check_not test_query awk_script message
# If db_test test_query awk_script returns zero (true), die with
# message
db_check_not()
{
	local test_query="$1"
	local awk_script="$2"
	local message="$3"

	if db_test "$test_query" "$awk_script"; then
		p_echo "$message"
		die
	fi
}

# db_check_unique [--where condition] table column [column ...]
# If the table contains duplicate tuples of values in the specified
# columns, die. If --where is specified, limit checking to rows that
# satisfy the given SQL condition
db_check_unique()
{
	local where=""
	eval `sh_get_args '--where) where="WHERE $2"; shift;;'`
	local table="$1"
	shift
	local columns="$1"
	shift
	local i
	for i; do
		if [ -n "$db_added_columns" ]; then
			eval "case $table.$i in $db_added_columns) return ;; esac"
		fi
		columns="$columns, \`$i\`"
	done
	db_check_not "SELECT COUNT(*) FROM \`$table\` $where GROUP BY $columns HAVING COUNT(*) > 1 LIMIT 1" 1 		"Database integrity check failed: duplicate values of ($columns) exist in table $table"
}

# db_get_keys table
# Outputs the list of keys for a table, one on a row, in the following format:
# name type columns
# Where type is one of PRIMARY, UNIQUE, and KEY, name is always
# PRIMARY for primary keys, and columns is a comma-separated list of
# columns without embedded spaces. All backtick characters are removed
db_get_keys()
{
	local table="$1"
	local query="SHOW CREATE TABLE \`$table\`"
	local output="`mysql_raw -e "$query"`"
	local status=$?
	if [ "$status" -ne 0 ]; then
		p_echo "$output"
		die "run the following SQL query: $1"
	fi

	echo "$output" | awk '
		$1 == "PRIMARY"	{ print "PRIMARY", "PRIMARY", $3 }
		$1 == "UNIQUE"	{ print "UNIQUE", $3, $4 }
		$1 == "KEY"		{ print "KEY", $2, $3 }' | 		sed -e 's/[`()]//g' -e 's/,[[:space:]]*$//g'
}

# 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
}

# db_test_column table column
# Returns 0 if table.column exists
db_test_column()
{
	local table="$1"
	local column="$2"

	db_test "DESC \`$table\`" "\$1 == \"$column\""
}

db_update_notifications()
{
	sw_engine_pleskrun $PRODUCT_ROOT_D/admin/plib/scripts/update_notifications.php 2>>"$product_log"
	[ "$?" -eq 0 ] || 		warn "cannot update notifications. Please rerun $PRODUCT_ROOT_D/admin/plib/scripts/update_notifications.php manually"
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
db_upgrade_configurations_1013()
{
	db_fix_add_column "Configurations" "active" "enum('false', 'true') NOT NULL DEFAULT 'true'"
}

db_upgrade_subdomains_zones_1013()
{
	echo_try "Upgrade mode of DNS zones for subdomains"
# Script named in compatibility with windows
	sw_engine_pleskrun $PRODUCT_ROOT_D/admin/plib/scripts/upgrade_subdomains_zones_1013.php && suc || warn "fail\nnCannot upgrade mode of DNS zones for subdomains. Please run $PRODUCT_ROOT_D/admin/plib/scripts/upgrade_subdomains_zones_1013.php manually."
}

db_upgrade_dns_1013()
{
    db_do "delete from dns_refs where status = 'syn'"
    sw_engine_pleskrun $PRODUCT_ROOT_D/admin/plib/scripts/upgrade_dns_1011.php && suc || warn "fail\nfix upgrade dns"
    db_do "update dns_zone set syncSoa='skip', syncRecords='skip' where id not in (select val from misc where param='default_dns_zone_id')"
}

db_upgrade_secret_key_1013()
{
    db_fix_add_column "secret_keys" "client_id" "INT UNSIGNED DEFAULT NULL"
    db_do_if_not "SHOW INDEX FROM secret_keys" "\$3 == \"client_id\"" "ALTER TABLE secret_keys ADD INDEX (client_id)"
}

db_upgrade_secret_key_fix_1013()
{
	sw_engine_pleskrun $PRODUCT_ROOT_D/admin/plib/scripts/upgrade_secret_keys_1013.php && suc || warn "fail\nfix secret keys clients ids"
}

db_upgrade_admin_simple_plan_permissions_1013()
{
    echo_try "Upgrade permissions for Admin Simple Plan"
    sw_engine_pleskrun $PRODUCT_ROOT_D/admin/plib/scripts/upgrade_admin_simple_plan_permissions_1013.php && suc || warn "fail\nnCannot upgrade permissions for Admin Simple Plan. Please run $PRODUCT_ROOT_D/admin/plib/scripts/upgrade_admin_simple_plan_permissions_1013.php manually."
}

db_upgrade_aps_settings_1013()
{
	db_do "delete from smb_apsSettings"
}

db_upgrade_sessions_1013()
{
    db_fix_add_column "sessions" "ip_dual_stack" "VARCHAR(39) CHARACTER SET ascii COLLATE ascii_general_ci"
}

db_smb_upgrade_1013()
{
# 45
	db_fix_add_column smb_productUpgrades version "VARCHAR(255)"
# 46
	db_fix_add_column smb_users subscriptionDomainId "INT DEFAULT 0"
# 47
	db_do_if_not "SHOW INDEX FROM smb_roles" "\$3 == \"ownerId\"" "CREATE INDEX ownerId_idx ON smb_roles (ownerId)"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_add_indexes_for_performance_11_1_11()
{
    db_do_if_not "SHOW INDEX FROM clients" "\$3 == \"type\"" "CREATE INDEX type ON clients (type)"
    db_do_if_not "SHOW INDEX FROM domains" "\$3 == \"external_id\"" "CREATE INDEX external_id ON domains (external_id)"
}

db_upgrade_change_sys_users_home_to_utf8()
{
	db_fix_change_column "sys_users" "home" "home" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL"
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_service_node_properties_move_property_to_configuration_11_1_12()
{
    local sourceName="$1"
    local destinationName="$3"
    local destinationSection="$2"
    db_select "SELECT \`serviceNodeId\` FROM \`ServiceNodeProperties\` WHERE \`name\` = '$sourceName'"
    for serviceNodeId in $db_select_output; do
        db_do_if_not \
            "SELECT \`name\` FROM \`ServiceNodeConfiguration\` WHERE \`serviceNodeId\` = $serviceNodeId AND \`section\` = '$destinationName' AND \`name\` = '$destinationSection'" 1 \
            "INSERT INTO \`ServiceNodeConfiguration\` (\`serviceNodeId\`, \`section\`, \`name\`, \`value\`) SELECT '$serviceNodeId', '$destinationSection', '$destinationName', \`value\` FROM \`ServiceNodeProperties\` WHERE \`serviceNodeId\` = '$serviceNodeId' AND \`name\` = '$sourceName'"
    done
}

db_upgrade_service_node_properties_move_misc_to_configuration_11_1_12()
{
    local sourceName="$1"
    local destinationName="$3"
    local destinationSection="$2"
    db_select "SELECT \`id\` FROM \`ServiceNodes\` WHERE \`ipAddress\` = 'local'"
    for serviceNodeId in $db_select_output; do
        db_do_if_not \
            "SELECT \`name\` FROM \`ServiceNodeConfiguration\` WHERE \`serviceNodeId\` = $serviceNodeId AND \`section\` = '$destinationSection' AND \`name\` = '$destinationName'" 1 \
            "INSERT INTO \`ServiceNodeConfiguration\` (\`serviceNodeId\`, \`section\`, \`name\`, \`value\`) SELECT '$serviceNodeId', '$destinationSection', '$destinationName', \`val\` FROM misc WHERE \`param\` = '$sourceName'"
    done
    db_do "DELETE FROM \`misc\` WHERE \`param\`= '$sourceName'"
}

db_upgrade_service_node_properties_11_1_12()
{
    if db_test_table 'ServiceNodeProperties'; then
        db_upgrade_service_node_properties_move_property_to_configuration_11_1_12 'server.nginx.enabled'             'webProxy' 'enabled'
        db_upgrade_service_node_properties_move_property_to_configuration_11_1_12 'server.nginx.backend-port'       'webProxy' 'backendPort'
        db_upgrade_service_node_properties_move_property_to_configuration_11_1_12 'server.nginx.ssl-backend-port'   'webProxy' 'sslBackendPort'
        db_upgrade_service_node_properties_move_property_to_configuration_11_1_12 'server.nginx.frontend-port'      'webProxy' 'frontendPort'
        db_upgrade_service_node_properties_move_property_to_configuration_11_1_12 'server.nginx.ssl-frontend-port'  'webProxy' 'sslFrontendPort'

        db_upgrade_service_node_properties_move_property_to_configuration_11_1_12 'server.webserver.httpPort'       'webServer' 'httpPort'
        db_upgrade_service_node_properties_move_property_to_configuration_11_1_12 'server.webserver.httpsPort'      'webServer' 'httpsPort'

        db_upgrade_service_node_properties_move_misc_to_configuration_11_1_12 'http_port' 'webServer' 'httpPort'
        db_upgrade_service_node_properties_move_misc_to_configuration_11_1_12 'https_port' 'webServer' 'httpsPort'

        db_select "SELECT SUBSTR(\`name\`, 26) FROM \`ServiceNodeProperties\` WHERE \`name\` LIKE 'coldfusionservice.config.%' GROUP BY \`name\`"
        for cfName in $db_select_output; do
            db_upgrade_service_node_properties_move_property_to_configuration_11_1_12 'coldfusionservice.config.$cfName' 'coldfusion' '$cfName'
        done

        db_upgrade_service_node_properties_move_property_to_configuration_11_1_12 'server.configuration.crontabSecureShell' 'scheduler' 'crontabSecureShell'

        db_fix_drop_table ServiceNodeProperties
    fi

    if db_test_table 'MailServerProperties'; then
        db_do "REPLACE INTO \`ServiceNodeConfiguration\` (\`serviceNodeId\`, \`section\`, \`name\`, \`value\`) SELECT \`serviceNodeId\`, 'mailServer', \`name\`, \`value\` FROM \`MailServerProperties\`";

        db_fix_drop_table 'MailServerProperties'
    fi
}

db_upgrade_custom_buttons_11_1_12()
{
    echo_try "Converting custom buttons from domain to client level"
    db_do "UPDATE custom_buttons cb, (SELECT cb.id, 4 AS level, d.cl_id AS level_id FROM custom_buttons cb INNER JOIN domains d on cb.level_id = d.id WHERE level = 8) sq SET cb.level = sq.level, cb.level_id = sq.level_id WHERE cb.id = sq.id"
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_service_node_configuration_11_1_13()
{
    db_select "SELECT DISTINCT serviceNodeId FROM ServiceNodeConfiguration WHERE serviceNodeId NOT IN (SELECT serviceNodeId FROM ServiceNodeConfiguration WHERE section = 'WebProxy' AND name = 'enabled')"
    for serviceNodeId in $db_select_output; do

        p_echo "Fix web proxy settings for service node $serviceNodeId"

        db_select "SELECT value FROM ServiceNodeConfiguration WHERE section = 'WebProxy' AND name = 'backendPort' AND serviceNodeId = '$serviceNodeId'"
        local backendPort="$db_select_output"
        if [ -z "$backendPort" ]; then
            backendPort="7080"
        fi

        db_select "SELECT value FROM ServiceNodeConfiguration WHERE section = 'WebProxy' AND name = 'sslBackendPort' AND serviceNodeId = '$serviceNodeId'"
        local sslBackendPort="$db_select_output"
        if [ -z "$backendPort" ]; then
            backendPort="7081"
        fi

        local proxyEnabled="false"
        if db_test "SELECT * FROM ServiceNodeConfiguration WHERE name = 'webServer' AND (section = 'httpPort' AND value = '$backendPort' OR section = 'httpsPort' AND value = '$sslBackendPort') AND serviceNodeId = '$serviceNodeId'" 1; then
            proxyEnabled="true"
        fi

        p_echo "Frontend port = $frontendPort, backend port = $backendPort, proxy enabled = $proxyEnabled"

        db_do "INSERT INTO ServiceNodeConfiguration (serviceNodeId, section, name, value) VALUES ('$serviceNodeId', 'WebProxy', 'enabled', '$proxyEnabled')"

    done


    db_do "UPDATE IGNORE ServiceNodeConfiguration SET name = section, section = 'webServer' WHERE name = 'webServer'"
    db_do "DELETE FROM ServiceNodeConfiguration WHERE name = 'webServer'"

    db_do "UPDATE IGNORE ServiceNodeConfiguration SET name = section, section = 'webProxy' WHERE name = 'webProxy'"
    db_do "DELETE FROM ServiceNodeConfiguration WHERE name = 'webProxy'"

    db_do "UPDATE ServiceNodeConfiguration SET section = 'webProxy' WHERE section = 'WebProxy'"
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_dns_templates_11_1_14()
{
	echo_try "drop rows from psa.dns_recs_t with empty values of column 'type'"
	db_do "DELETE from dns_recs_t WHERE \`type\`=''"
	suc
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_subscription_properties_11_1_15()
{
	echo_try "Create subscription records"
	sw_engine_pleskrun $PRODUCT_ROOT_D/admin/plib/scripts/upgrade_subscriptions_108.php && suc || warn "fail\nCannot update subscriptions information. Please run $PRODUCT_ROOT_D/admin/plib/scripts/upgrade_subscriptions_108.php manually."

	echo_try "Move limits and permissions from main domain of subscription to subscription properties"
	sw_engine_pleskrun $PRODUCT_ROOT_D/admin/plib/scripts/upgrade_subscription_properties_11.1.16.php && suc || warn "fail\nCannot update subscription properties. Please run $PRODUCT_ROOT_D/admin/plib/scripts/upgrade_subscription_properties_11.1.16.php manually."
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_forwarding_11_1_17()
{
    db_fix_add_column "forwarding" "http_code" "INT UNSIGNED NOT NULL DEFAULT 301"
}

db_upgrade_seo_safe_domain_aliases_11_1_17()
{
    db_fix_add_column "domain_aliases" "seoRedirect" "ENUM('false', 'true') NOT NULL DEFAULT 'false'"
}

db_upgrade_db_user_unique_key_11_1_17()
{
    db_fix_drop_unique_key "db_users" "db_id" "login"
    db_fix_drop_unique_key "db_users" "db_server_id" "login"
    db_fix_add_unique_key "db_users" "db_server_id" "db_id" "login"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_php_handler_id_11_1_18()
{
    db_fix_add_column --init php_handler_type hosting php_handler_id "varchar(255) NOT NULL DEFAULT 'module'"
    db_do "REPLACE INTO \`TmplData\` (\`tmpl_id\`, \`element\`, \`value\`) SELECT \`tmpl_id\`, 'php_handler_id', \`value\` FROM \`TmplData\` WHERE \`element\` = 'php_handler_type'"
    db_do "DELETE from \`TmplData\` WHERE \`element\` = 'php_handler_type'"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_drop_php_version_11_5_19()
{
	if db_test_column 'hosting' 'php_handler_type' && db_test_column 'hosting' 'php_version'; then
	    db_do "update ServiceNodeEnvironment e, ServiceNodes n, hosting h, sys_users u\
	        set h.php_handler_id = concat(php_handler_type, '-', php_version)\
    	    where n.id = e.serviceNodeId and name='PLATFORM' and value='windows' and h.sys_user_id = u.id and u.serviceNodeId = n.id;"
	fi
    db_fix_del_column 'hosting' 'php_handler_type'
    db_fix_del_column 'hosting' 'php_version'
}

db_upgrade_webmails_11_5_19()
{
    db_fix_add_column Webmails serviceNodeId "int(10) unsigned NOT NULL default 1"
}

db_upgrade_smb_11_5_19()
{
# 51
	db_fix_add_column smb_apsPackages isNonStorefrontCommercial "INT DEFAULT 0"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_enable_dns_connector_11_5_21()
{
	local connector=

	db_select "select p.val from cl_param p INNER JOIN clients c ON c.id = p.cl_id WHERE c.type = 'admin' AND p.param = 'dns-connector-class-name' LIMIT 1"
	case "$db_select_output" in
		Service_Dns_PoaConnector)
			connector="poa"
		;;
		Service_Dns_PleskConnector)
			connector="plesk"
		;;
	esac

	if [ -n "$connector" ]; then
		db_select "SELECT \`id\` FROM \`ServiceNodes\` WHERE \`ipAddress\` = 'local'"
		local nodes="$db_select_output"
		for serviceNodeId in $nodes; do
			db_do_if_not \
				"SELECT \`value\` FROM \`ServiceNodeConfiguration\` WHERE \`serviceNodeId\` = $serviceNodeId AND \`section\` = 'dnsConnector' AND \`name\` = '$connector'" 1 \
				"INSERT INTO \`ServiceNodeConfiguration\` (\`serviceNodeId\`, \`section\`, \`name\`, \`value\`) values ($serviceNodeId, 'dnsConnector', '$connector', 'true')"
		done
	fi
	db_do "DELETE FROM cl_param WHERE param='dns-connector-class-name'"
}

db_upgrade_set_force_update_applications_notification_11_5_21()
{
	db_select "SELECT DISTINCT d.cl_id AS clientId FROM Subscriptions AS s INNER JOIN apsContexts AS a ON (s.id = a.subscriptionId) INNER JOIN domains AS d ON (s.object_type = 'domain' AND s.object_id = d.id) LEFT JOIN cl_param AS clp ON (d.cl_id = clp.cl_id AND clp.param = 'show_force_update_applications_notification') WHERE clp.cl_id IS NULL"
	for clientId in $db_select_output; do
		db_do "INSERT INTO \`cl_param\` (\`cl_id\`, \`param\`, \`val\`) values ($clientId, 'show_force_update_applications_notification', 'true')"
	done
}

db_add_public_ip_11_5_21()
{
	db_fix_add_column "IP_Addresses" "public_ip_address" "VARCHAR(39) CHARACTER SET ascii COLLATE ascii_general_ci  DEFAULT NULL"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_drop_ip_address_id_11_5_22()
{
    db_fix_del_column "hosting" "ip_address_id"
    db_fix_del_column "forwarding" "ip_address_id"
}

db_upgrade_set_property_unpaid_website_status_for_plans_11_5_22()
{
    db_select "SELECT t.id AS planId FROM Templates AS t LEFT JOIN TmplData AS td ON (t.id = td.tmpl_id AND td.element = 'unpaid_website_status') WHERE t.type='domain' AND td.value IS NULL"
    for planId in $db_select_output; do
        db_do "INSERT INTO \`TmplData\` (\`tmpl_id\`, \`element\`, \`value\`) values ($planId, 'unpaid_website_status', 'disabled')"
    done
}

db_upgrade_set_property_unpaid_website_status_for_subscriptions_11_5_22()
{
    db_select "SELECT s.id AS subscriptionId FROM Subscriptions AS s LEFT JOIN SubscriptionProperties AS sp ON (s.id = sp.subscription_id AND sp.name = 'unpaid_website_status') WHERE s.object_type='domain' AND sp.value IS NULL"
    for subscriptionId in $db_select_output; do
        db_do "INSERT INTO \`SubscriptionProperties\` (\`subscription_id\`, \`name\`, \`value\`) values ($subscriptionId, 'unpaid_website_status', 'disabled')"
    done
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_correcting_property_unpaid_website_status_for_plans_11_5_24()
{
	db_do "UPDATE \`TmplData\` SET \`element\` = 'unpaid_website_status' WHERE \`element\` = 'unpaidWebsiteStatus';"
}

db_upgrade_correcting_property_unpaid_website_status_for_subscriptions_11_5_24()
{
	db_do "UPDATE \`SubscriptionProperties\` SET \`name\` = 'unpaid_website_status' WHERE \`name\` = 'unpaidWebsiteStatus';"
}

db_upgrade_maintenance_mode_id_11_5_24()
{
	db_select "SELECT \`d\`.\`id\` AS \`domainId\`, \`d\`.\`status\` AS \`domainStatus\`, COALESCE(\`w\`.\`id\`, \`d\`.\`id\`) AS \`webspaceId\`, \`d\`.\`cl_id\` AS \`clientId\`, COALESCE(\`w\`.\`permissions_id\`, \`d\`.\`permissions_id\`) AS \`permissionsId\` FROM \`hosting\` AS \`h\` INNER JOIN \`domains\` AS \`d\` ON \`d\`.\`id\` = \`h\`.\`dom_id\` LEFT JOIN \`domains\` AS \`w\` ON \`w\`.\`id\` = \`d\`.\`webspace_id\` WHERE \`h\`.\`maintenance_mode\` = 'true' AND \`d\`.\`status\` = 0"
    test -z "$db_select_output" && return 0
	echo "$db_select_output" | while read row; do
		domainId=`echo $row | awk '{print $1}'`
		domainStatus=`echo $row | awk '{print $2}'`
		webspaceId=`echo $row | awk '{print $3}'`
		clientId=`echo $row | awk '{print $4}'`
		permissionsId=`echo $row | awk '{print $5}'`

		if db_test "SELECT \`p\`.\`value\` FROM \`Subscriptions\` AS  \`s\` LEFT JOIN \`SubscriptionProperties\` AS \`sp\` ON \`sp\`.\`subscription_id\` = \`s\`.\`id\` AND \`sp\`.\`name\` = 'permissionsId' INNER JOIN \`Permissions\` AS \`p\` ON \`p\`.\`id\` = COALESCE(\`sp\`.\`value\`, $permissionsId) AND \`p\`.\`permission\` = 'manage_website_maintenance' AND \`p\`.\`value\` = 'false' WHERE \`s\`.\`object_id\` = $webspaceId AND \`s\`.\`object_type\` = 'domain'" 1; then
			if db_test "SELECT \`p\`.\`type\` FROM \`clients\` as \`c\` INNER JOIN \`clients\` as \`p\` ON \`p\`.\`id\` = \`c\`.\`parent_id\` AND \`p\`.\`type\` = 'reseller' WHERE \`c\`.\`id\` = $clientId" 1; then
				domainStatus=$(( $domainStatus | 32 ))
			else
				domainStatus=$(( $domainStatus | 16 ))
			fi
		else
			domainStatus=$(( $domainStatus | 64 ))
		fi

		db_do "UPDATE \`domains\` SET \`status\` = $domainStatus WHERE \`id\` = $domainId"
		db_do_if_not \
			"SELECT \`dom_id\` FROM \`dom_param\` WHERE \`param\` = 'turnOffAction' AND \`dom_id\` = $domainId" 1 \
			"INSERT INTO \`dom_param\` (\`dom_id\`, \`param\`, \`val\`) VALUES ($domainId, 'turnOffAction', 'suspend')"
		db_do_if_not \
			"SELECT \`dom_id\` FROM \`dom_param\` WHERE \`param\` = 'selfTurnOffAction' AND \`dom_id\` = $domainId" 1 \
			"INSERT INTO \`dom_param\` (\`dom_id\`, \`param\`, \`val\`) VALUES ($domainId, 'selfTurnOffAction', 'suspend')"
	done
}

db_upgrade_service_node_configuration_11_5_24()
{
    db_fix_change_column "ServiceNodeEnvironment" "value" "value" "TEXT CHARACTER SET utf8 COLLATE utf8_general_ci"
    db_fix_change_column "ServiceNodeConfiguration" "value" "value" "TEXT CHARACTER SET utf8 COLLATE utf8_general_ci"
}

db_upgrade_secret_keys_11_5_24()
{
    db_fix_add_column "secret_keys" "lookup_id" "VARCHAR(255) CHARACTER SET ascii COLLATE ascii_general_ci DEFAULT NULL"
    db_do_if_not "SHOW INDEX FROM secret_keys" "\$3 == \"lookup_id\"" "ALTER TABLE secret_keys ADD INDEX (lookup_id)"
    sw_engine_pleskrun $PRODUCT_ROOT_D/admin/plib/scripts/upgrade_secret_keys_11.5.25.php && suc || warn "fail\nencryption of secret keys"
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
db_upgrade_correcting_aps_tokens_11_5_29()
{
    db_fix_change_column "ApsTokens" "packageId" "applicationId" "VARCHAR(2000) CHARACTER SET binary NOT NULL"
}

db_smb_upgrade_11_5_29()
{
	db_fix_add_column smb_users locale "VARCHAR(17)"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_external_id_11_5_99()
{
    db_fix_add_column "Subscriptions" "external_id" "VARCHAR(255) CHARACTER SET ascii COLLATE ascii_bin NOT NULL DEFAULT ''"
    db_fix_add_column "dns_zone" "external_id" "VARCHAR(255) CHARACTER SET ascii COLLATE ascii_bin NOT NULL DEFAULT ''"
    db_fix_add_column "dns_recs" "external_id" "VARCHAR(255) CHARACTER SET ascii COLLATE ascii_bin NOT NULL DEFAULT ''"
}

db_upgrade_move_configuration_11_5_99()
{
    db_upgrade_move_cl_param_to_servicenode_config_11_5_99 'poa-api-url' 'POA'
    db_upgrade_move_cl_param_to_servicenode_config_11_5_99 'poa-api-login' 'POA'
    db_upgrade_move_cl_param_to_servicenode_config_11_5_99 'poa-api-password' 'POA'
    db_upgrade_move_cl_param_to_servicenode_config_11_5_99 'poa-ui-dispatcher-url' 'POA'

    db_upgrade_move_cl_param_to_servicenode_config_11_5_99 'ppb-url' 'Billing'
    db_upgrade_move_cl_param_to_servicenode_config_11_5_99 'integration-api-version' 'Billing'
    db_upgrade_move_cl_param_to_servicenode_config_11_5_99 'ppb-remote' 'Billing'
}

db_upgrade_move_cl_param_to_servicenode_config_11_5_99()
{
    local sourceName="$1"
    local destinationName="$sourceName"
    local destinationSection="$2"

    db_select "SELECT \`id\` FROM \`ServiceNodes\` WHERE \`ipAddress\` = 'local'"
    local serviceNodeId="$db_select_output";
    if [ "X${serviceNodeId}" = "X" ]; then
        die "Management service node record not found"
    fi

    db_select "SELECT \`id\` FROM \`clients\` WHERE \`type\` = 'admin'"
    local adminClientId="$db_select_output";
    if [ "X${adminClientId}" = "X" ]; then
        die "Admin client record not found"
    fi

    db_do_if_not \
        "SELECT \`name\` FROM \`ServiceNodeConfiguration\` WHERE \`serviceNodeId\` = $serviceNodeId AND \`section\` = '$destinationSection' AND \`name\` = '$destinationName'" 1 \
        "INSERT INTO \`ServiceNodeConfiguration\` (\`serviceNodeId\`, \`section\`, \`name\`, \`value\`) SELECT '$serviceNodeId', '$destinationSection', '$destinationName', \`val\` FROM cl_param WHERE \`cl_id\` = $adminClientId AND \`param\` = '$sourceName'"

    db_do "DELETE FROM \`cl_param\` WHERE \`cl_id\` = $adminClientId AND \`param\` = '$sourceName'"
}

db_upgrade_iis_app_pools_cpu_limit_11_5_99()
{
    db_fix_add_column "IisAppPools" "cpuLimitAction" "enum('NoAction','KillW3wp','Throttle','ThrottleUnderLoad') NOT NULL default 'NoAction'"
    db_fix_add_column "IisAppPools" "cpuLimitInterval" "int(10) unsigned NOT NULL default '5'"
}


db_upgrade_sdk_add_services_11_5_99()
{
    db_upgrade_sdk_add_service "PleskDns"
    db_upgrade_sdk_add_service "PleskFileSystem"
}
 
db_upgrade_sdk_add_service()
{
    local serviceName="$1"
 
    db_do_if_not \
      "SELECT id FROM ServiceInstallations WHERE name = '${serviceName}' AND serviceNodeId = 1" 1 \
      "INSERT INTO ServiceInstallations (name, status, serviceNodeId) values ('${serviceName}', 1, 1)"
 
    db_select "SELECT id FROM ServiceInstallations WHERE name = '${serviceName}' LIMIT 1"
    local serviceInstallationId="${db_select_output}"
 
    db_select "SELECT id FROM Subscriptions WHERE object_type='domain'"
    for subscriptionId in ${db_select_output}; do
      db_do_if_not \
        "SELECT si.id FROM ServiceInstances AS si INNER JOIN Subscriptions AS s ON (si.servicePackageId = s.id) WHERE si.serviceInstallationId = ${serviceInstallationId} AND s.id = ${subscriptionId} LIMIT 1" 1 \
        "INSERT INTO ServiceInstances (serviceInstallationId, servicePackageId, status, enabled) values (${serviceInstallationId}, ${subscriptionId}, 1, 1)"
    done
}

db_upgrade_web_server_configurations_11_6_2()
{
    db_fix_add_column "Configurations" "errorFile" "blob NOT NULL"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_mail_description_11_6_2()
{
    db_fix_add_column "mail" "description" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci"
}

db_upgrade_clients_description_11_6_2()
{
    db_fix_add_column "clients" "description" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_domains_description_11_6_3()
{
    db_fix_add_column "domains" "adminDescription" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci"
    db_fix_add_column "domains" "resellerDescription" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci"
    db_fix_add_column "domains" "description" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
db_upgrade_heterogenous_1100()
{
    db_fix_add_column "hosting" "maintenance_mode" "ENUM('false','true') NOT NULL DEFAULT 'false'"

    db_fix_add_column "clients" "passwd" "VARCHAR(20) NOT NULL DEFAULT ''"
    db_fix_add_column "clients" "ownership" "ENUM('false','true') NOT NULL DEFAULT 'true'"

    db_fix_add_column "dom_level_usrs" "passwd" "VARCHAR(20) NOT NULL DEFAULT ''"
    db_fix_add_column "dom_level_usrs" "uid" "VARCHAR(255) DEFAULT NULL"
    db_fix_add_column "dom_level_usrs" "ownership" "ENUM('false','true') NOT NULL DEFAULT 'true'"

    db_fix_change_column "domains" "guid" "guid" "VARCHAR(255) CHARACTER SET ascii COLLATE ascii_bin NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'"

    db_fix_add_column "disk_usage" "mysql_dbases" "BIGINT(20) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_add_column "disk_usage" "mssql_dbases" "BIGINT(20) UNSIGNED NOT NULL DEFAULT '0'"

    db_fix_change_column "hosting" "fp_adm" "fp_adm" "VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NOT NULL"
    db_fix_change_column "hosting" "webstat" "webstat" "VARCHAR(20) NOT NULL DEFAULT 'none'"
    db_fix_add_column "hosting" "fp_no_index" "ENUM('false','true') NOT NULL DEFAULT 'false'"
    db_fix_add_column "hosting" "ssi_html" "ENUM('false','true') NOT NULL DEFAULT 'false'"
    db_fix_add_column "hosting" "php_isapi" "ENUM('false','true') NOT NULL DEFAULT 'false'"
    db_fix_add_column "hosting" "php_version" "VARCHAR(255) NOT NULL DEFAULT '4'"
    db_fix_add_column "hosting" "managed_runtime_version" "VARCHAR(255) NOT NULL DEFAULT '1.1'"
    db_fix_add_column "hosting" "at_domains" "ENUM('false','true') NOT NULL DEFAULT 'false'"
    db_fix_add_column "hosting" "write_modify" "VARCHAR(255) NOT NULL DEFAULT ''"
    db_fix_add_column "hosting" "webdeploy" "ENUM('false','true') NOT NULL DEFAULT 'false'"

    db_fix_add_column "web_users" "ssi_html" "ENUM('false','true') NOT NULL DEFAULT 'false'"
    db_fix_add_column "web_users" "php_isapi" "ENUM('false','true') NOT NULL DEFAULT 'false'"
    db_fix_add_column "web_users" "managed_runtime_version" "VARCHAR(255) NOT NULL DEFAULT '1.1'"
    db_fix_add_column "web_users" "write_modify" "VARCHAR(255) DEFAULT NULL"

    db_fix_add_column "ftp_users" "permission" "INT UNSIGNED NOT NULL DEFAULT 3";

    db_fix_add_column "DatabaseServers" "parameters_id" "INT(10) UNSIGNED NOT NULL"
	db_fix_add_column "DatabaseServers" "type" "ENUM('mysql','postgresql','mssql') NOT NULL"
	db_fix_change_column "DatabaseServers" "type" "type" "ENUM('mysql','postgresql','mssql') NOT NULL"

    db_fix_add_column "db_users" "passwd" "VARCHAR(16) NOT NULL DEFAULT ''"
    db_fix_add_column "db_users" "status" "ENUM('normal','orphaned') NOT NULL DEFAULT 'normal'"

    db_fix_change_column "TmplData" "element" "element" "VARCHAR(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL"
    db_fix_change_column "longtaskparams" "param" "param" "VARCHAR(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL"

    db_fix_add_column "protected_dirs" "dom_type" "ENUM('domain','subdomain') NOT NULL default 'domain'"

    db_fix_change_column "hosting" "php_handler_type" "php_handler_type" "ENUM('cgi', 'fastcgi', 'module', 'isapi') NOT NULL default 'module'"
    db_fix_change_column "subdomains" "php_handler_type" "php_handler_type" "ENUM('cgi', 'fastcgi', 'module', 'isapi') NOT NULL default 'module'"

    db_fix_add_column "mail" "disk_usage" "BIGINT DEFAULT 0 NOT NULL"

	if ! db_test_table "domain_aliases"; then
        db_do "RENAME TABLE domainaliases TO domain_aliases"
    fi
}

db_upgrade_apsmail_1100()
{
    db_fix_add_column "mail" "apsServiceAccountInstanceId" "INT UNSIGNED DEFAULT 0 NOT NULL"
    db_fix_add_column "mail" "apsAntivirusServiceInstanceId" "INT UNSIGNED DEFAULT 0 NOT NULL"
    db_fix_add_column "mail_aliases" "apsServiceInstanceId"  "INT UNSIGNED DEFAULT 0 NOT NULL"
    db_fix_add_column "mail_resp" "apsServiceInstanceId"  "INT UNSIGNED DEFAULT 0 NOT NULL"
    db_fix_add_column "mail_redir" "apsServiceInstanceId" "INT UNSIGNED DEFAULT 0 NOT NULL"
    db_fix_add_column "mail" "apsAntispamServiceInstanceId" "INT UNSIGNED DEFAULT 0 NOT NULL"
}

db_upgrade_service_nodes_1100()
{
    db_fix_drop_unique_key "ServiceNodes" "name"
    db_fix_change_column "ServiceNodes" "name" "description" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT ''"
    db_fix_change_column "ServiceNodes" "remoteIpAddress" "ipAddress" "VARCHAR(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT 'local'"
    db_fix_add_unique_key "ServiceNodes" "ipAddress"
    db_fix_add_column "ServiceNodes" "type" "VARCHAR(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT 'plesk'"
    db_do "UPDATE ServiceNodes SET ipAddress='local' WHERE ISNULL(ipAddress) OR ipAddress=''"
}

db_upgrade_webusers_miva_1100()
{
	db_fix_add_column "web_users" "miva" "ENUM('false','true') NOT NULL DEFAULT 'false'"
}

db_upgrade_mail_server_settings_1100()
{
    db_select "SELECT \`param\` FROM \`misc\` WHERE \`param\` IN ( \
        'spf_enabled', 'spf_behavior', 'spf_guess', 'spf_rules', 'spf_exp', \
        'disable_pop_auth', 'disable_smtp_auth', \
        'message_submission', 'message_submission_ip', \
        'password_strength', 'poplock_time', 'rbl', 'rbl_server', 'spf_rule', 'relay', \
        'domain_keys_sign', 'domain_keys_verify', 'ml_size', \
        'spamfilter_enabled', 'spamfilter_use_mailuser_prefs', 'spamfilter_max_children', 'spamfilter_max_addr_list_length', \
        'virusfilter' \
    )";
    for propertyName in $db_select_output; do
            db_do "DELETE FROM \`MailServerProperties\` WHERE \`name\`='$propertyName' AND \`serviceNodeId\`=1";
            db_do "INSERT INTO \`MailServerProperties\` (\`serviceNodeId\`, \`name\`, \`value\`) SELECT 1, \`param\`, \`val\` FROM \`misc\` WHERE \`param\` = '$propertyName'";
            db_do "DELETE FROM \`misc\` WHERE \`param\`='$propertyName'";
    done;
	db_fix_add_column "badmailfrom" "serviceNodeId" "INT UNSIGNED NOT NULL DEFAULT 1"
	db_fix_add_column "smtp_poplocks" "serviceNodeId" "INT UNSIGNED NOT NULL DEFAULT 1"

    db_fix_add_column "spamfilter" "serviceNodeId" "INT UNSIGNED NOT NULL DEFAULT 1"
	db_do_if \
		"SHOW KEYS FROM spamfilter WHERE Key_name = 'username' AND Column_name = 'username'" 1 \
		"ALTER TABLE spamfilter DROP KEY \`username\`"
	db_do_if_not \
		"SHOW KEYS FROM spamfilter WHERE Key_name = 'spamfilter_username_serviceNodeId' AND Column_name = 'serviceNodeId'" 1 \
		"ALTER TABLE spamfilter ADD UNIQUE KEY spamfilter_username_serviceNodeId (\`username\`, serviceNodeId)"

    db_fix_add_column "GL_settings" "serviceNodeId" "INT UNSIGNED NOT NULL DEFAULT 1"
	db_do_if \
		"SHOW KEYS FROM GL_settings WHERE Key_name = 'param' AND Column_name = 'param'" 1 \
		"ALTER TABLE GL_settings DROP KEY \`param\`"
	db_do_if \
		"SHOW KEYS FROM GL_settings WHERE Key_name = 'PRIMARY' AND Column_name = 'param'" 1 \
		"ALTER TABLE GL_settings DROP PRIMARY KEY"
	db_do_if_not \
		"SHOW KEYS FROM GL_settings WHERE Key_name = 'PRIMARY' AND Column_name = 'serviceNodeId'" 1 \
		"ALTER TABLE GL_settings ADD PRIMARY KEY (serviceNodeId, \`param\`)"

    db_fix_add_column "GL_remote_domains" "serviceNodeId" "INT UNSIGNED NOT NULL DEFAULT 1"
	db_do_if \
		"SHOW KEYS FROM GL_remote_domains WHERE Key_name = 'domain' AND Column_name = 'domain'" 1 \
		"ALTER TABLE GL_remote_domains DROP KEY \`domain\`"
	db_do_if_not \
		"SHOW KEYS FROM GL_remote_domains WHERE Key_name = 'PRIMARY' AND Column_name = 'serviceNodeId'" 1 \
		"ALTER TABLE GL_remote_domains ADD PRIMARY KEY (serviceNodeId, \`domain\`)"
}

db_smb_upgrade_1100()
{
# 48
    db_do_if_not "SHOW INDEX FROM smb_users" "\$3 == \"ownerId\"" "CREATE INDEX ownerId_idx ON smb_users (ownerId)"
# 49
    db_do_if_not "SHOW INDEX FROM smb_roleGeneralPermissions" "\$3 == \"roleId\"" "CREATE INDEX roleId_idx ON smb_roleGeneralPermissions (roleId)"
# 50
    db_do_if_not "SHOW INDEX FROM smb_users" "\$3 == \"isBuiltIn\"" "CREATE INDEX isBuiltIn_idx ON smb_users (isBuiltIn)"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_longtasks_1101()
{
    db_fix_add_column "longtasks" "context" "VARCHAR(255) CHARACTER SET ascii COLLATE ascii_general_ci DEFAULT NULL"
    db_fix_change_column "longtasks" "status" "status" "VARCHAR(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT 'not_started'"
    db_fix_add_column "longtasks" "statusProcessed" "INT UNSIGNED NOT NULL DEFAULT 0"

    db_fix_change_column "longtasks" "progress_text" "progressStatus" "VARCHAR(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT 'queue'"
    db_fix_add_column "longtasks" "progressParams" "BLOB DEFAULT NULL"
    db_fix_change_column "longtasks" "progress_max" "progressMax" "INT UNSIGNED NOT NULL DEFAULT 1"
    db_fix_change_column "longtasks" "progress_value" "progressValue" "INT UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "longtasks" "start_time" "startTime" "TIMESTAMP"
    db_fix_change_column "longtasks" "finish_time" "finishTime" "TIMESTAMP"

    db_fix_del_column "longtasks" "title"
    db_fix_del_column "longtasks" "owner"
    db_fix_del_column "longtasks" "owner_type"

    db_fix_change_column "longtaskparams" "val" "val" "BLOB DEFAULT NULL"

    db_do "DELETE FROM \`longtasks\`";
    db_do "DELETE FROM \`longtaskparams\`";
}

db_upgrade_db_users_1101()
{
    db_fix_add_column "db_users" "dom_id" "INT UNSIGNED NOT NULL DEFAULT 0"
    db_fix_add_column "db_users" "db_server_id" "INT UNSIGNED NOT NULL DEFAULT 0"
    db_do "UPDATE db_users, data_bases SET db_users.dom_id = data_bases.dom_id, db_users.db_server_id = data_bases.db_server_id WHERE data_bases.id = db_users.db_id"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
db_upgrade_enable_sendmail_default_values_12_0_10()
{
    db_plan_properties_default_values_12_0_9 'outgoing_messages_enable_sendmail'
    db_subscription_properties_default_values_12_0_9 'outgoing_messages_enable_sendmail'
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
db_upgrade_default_php_handler_12_0_12()
{
    db_fix_change_column "hosting" "php_handler_id" "php_handler_id" "varchar(255) NOT NULL DEFAULT 'fastcgi'"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_wordpress_instances_12_0_17()
{
    db_fix_drop_unique_key "WordpressInstances" "path"
    db_fix_add_unique_key "WordpressInstances" "subscriptionId" "path"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

upgrade_cgi_bin_mode_defaults_12_0_5()
{
    local script="$PRODUCT_ROOT_D/admin/plib/scripts/upgrade_cgi_bin_mode.php"
    if [ -f "$script" ]; then
        sw_engine_pleskrun "$script" >> "$product_log" 2>&1
    fi
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_service_plan_domain_12_0_6()
{
    db_select "SELECT t.id AS planId FROM Templates AS t LEFT JOIN TmplData AS td ON (t.id = td.tmpl_id AND td.element = 'mailservice') WHERE t.type='domain' AND td.value IS NULL"
    for planId in $db_select_output; do
        db_do "INSERT INTO \`TmplData\` (\`tmpl_id\`, \`element\`, \`value\`) values ($planId, 'mailservice', 'true')"
    done
}

db_upgrade_iis_app_pools_12_0_6()
{
    db_fix_add_column "IisAppPools" "maxProcesses" "int(10) unsigned NOT NULL default 1"
    db_fix_add_column "IisAppPools" "idleTimeout" "int(10) unsigned NOT NULL default 5"
    db_fix_add_column "IisAppPools" "idleTimeoutAction" "enum('Terminate','Suspend') NOT NULL default 'Terminate'"
    db_fix_add_column "IisAppPools" "recyclingByTime" "int(11) NOT NULL default 1740"
    db_fix_add_column "IisAppPools" "recyclingByRequests" "int(11) NOT NULL default -1"
    db_fix_add_column "IisAppPools" "recyclingByVirtualMemory" "bigint(11) NOT NULL default -1"
    db_fix_add_column "IisAppPools" "recyclingByPrivateMemory" "bigint(11) NOT NULL default -1"
}

db_upgrade_subscription_outgoing_messages_overlimit_percent_to_default_12_0_6()
{
    db_select "SELECT s.id FROM Subscriptions s LEFT JOIN SubscriptionProperties sp ON (s.id = sp.subscription_id AND sp.name = 'outgoing_messages_overlimit_percent')  WHERE sp.value IS NULL AND s.object_type = 'domain'"

    for subscription_id in $db_select_output; do
        db_do "INSERT INTO SubscriptionProperties (subscription_id, name, value) VALUES ('$subscription_id', 'outgoing_messages_overlimit_percent', '0')"
    done
}

db_upgrade_plan_outgoing_messages_overlimit_percent_to_default_12_0_6()
{
    db_select "SELECT t.id FROM Templates t LEFT JOIN TmplData td ON (t.id = td.tmpl_id AND td.element = 'outgoing_messages_overlimit_percent')  WHERE td.value IS NULL AND t.type = 'domain'"

    for tmpl_id in $db_select_output; do
        db_do "INSERT INTO TmplData (tmpl_id, element, value) VALUES ('$tmpl_id', 'outgoing_messages_overlimit_percent', '0')"
    done
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_sessions_12_0_7()
{
    db_do "delete from sessions"
    db_fix_del_column "sessions" "click_time"
    db_fix_change_column "sessions" "login_time" "login_time" "INT UNSIGNED"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_subscription_properties_default_values_12_0_8()
{
        local subscription_ids
        local property_name="$1"

        db_select "SELECT s.id FROM Subscriptions s LEFT JOIN SubscriptionProperties sp ON (s.id = sp.subscription_id AND sp.name = '$property_name')  WHERE sp.value IS NULL AND s.object_type = 'domain'"
        subscription_ids="$db_select_output"

        for subscription_id in $subscription_ids; do
            db_do "INSERT INTO SubscriptionProperties (subscription_id, name, value) VALUES ('$subscription_id', '$property_name', 'default')"
        done
}

db_plan_properties_default_values_12_0_8()
{
        local tmpl_ids
        local property_name="$1"

        db_select "SELECT t.id FROM Templates t LEFT JOIN TmplData td ON (t.id = td.tmpl_id AND td.element = '$property_name')  WHERE td.value IS NULL AND t.type = 'domain'"
        tmpl_ids="$db_select_output"

        for tmpl_id in $tmpl_ids; do
            db_do "INSERT INTO TmplData (tmpl_id, element, value) VALUES ('$tmpl_id', '$property_name', 'default')"
        done
}

db_upgrade_subscription_properties_default_values_12_0_8()
{
	db_subscription_properties_default_values_12_0_8 'outgoing_messages_enable_sendmail'
}

db_upgrade_plan_properties_default_values_12_0_8()
{
	db_plan_properties_default_values_12_0_8 'outgoing_messages_enable_sendmail'
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_subscription_properties_default_values_12_0_9()
{
        local subscription_ids
        local property_name="$1"

        db_select "SELECT s.id FROM Subscriptions s LEFT JOIN SubscriptionProperties sp ON (s.id = sp.subscription_id AND sp.name = '$property_name')  WHERE sp.value IS NULL AND s.object_type = 'domain'"
        subscription_ids="$db_select_output"

        for subscription_id in $subscription_ids; do
            db_do "INSERT INTO SubscriptionProperties (subscription_id, name, value) VALUES ('$subscription_id', '$property_name', 'default')"
        done
}

db_plan_properties_default_values_12_0_9()
{
        local tmpl_ids
        local property_name="$1"

        db_select "SELECT t.id FROM Templates t LEFT JOIN TmplData td ON (t.id = td.tmpl_id AND td.element = '$property_name')  WHERE td.value IS NULL AND t.type = 'domain'"
        tmpl_ids="$db_select_output"

        for tmpl_id in $tmpl_ids; do
            db_do "INSERT INTO TmplData (tmpl_id, element, value) VALUES ('$tmpl_id', '$property_name', 'default')"
        done
}

db_upgrade_mbox_outgoing_messages_to_default_12_0_9()
{
    db_select "SELECT m.id FROM mail AS m LEFT JOIN mn_param AS mnp ON (m.id = mnp.mn_id AND mnp.param = 'outgoing_messages_limit') WHERE mnp.val IS NULL"

    for mail_id in $db_select_output; do
        db_do "INSERT INTO mn_param (mn_id, param, val) VALUES ('$mail_id', 'outgoing_messages_limit', 'default')"
    done
}

db_upgrade_domain_outgoing_messages_to_default_12_0_9()
{
    db_select "SELECT d.id FROM domains AS d LEFT JOIN Parameters AS p ON (d.id = p.id AND p.parameter = 'outgoing_messages_limit') WHERE p.value IS NULL"

    for domain_id in $db_select_output; do
        db_do "INSERT INTO Parameters (id, parameter, value) VALUES ('$domain_id', 'outgoing_messages_limit', 'default')"
    done
}

db_upgrade_subscription_properties_default_values_12_0_9()
{
    db_subscription_properties_default_values_12_0_9 'outgoing_messages_domain_limit'
    db_subscription_properties_default_values_12_0_9 'outgoing_messages_mbox_limit'
    db_subscription_properties_default_values_12_0_9 'outgoing_messages_subscription_limit'
}

db_upgrade_plan_properties_default_values_12_0_9()
{
    db_plan_properties_default_values_12_0_9 'outgoing_messages_domain_limit'
    db_plan_properties_default_values_12_0_9 'outgoing_messages_mbox_limit'
    db_plan_properties_default_values_12_0_9 'outgoing_messages_subscription_limit'
}

db_upgrade_wordpress_instances_12_0_9()
{
    db_fix_add_column "WordpressInstances" "apsInstanceId" "INT UNSIGNED DEFAULT NULL"
    db_fix_del_column 'WordpressInstances' 'isAttached'
    db_do_if_not "SHOW INDEX FROM WordpressInstances" "\$3 == \"subscriptionId\"" "CREATE INDEX subscriptionId ON WordpressInstances (subscriptionId)"
}

db_upgrade_sessions_12_0_9()
{
    db_fix_drop_table "WhpSessions"
    db_fix_del_column "sessions" "data"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_iis_app_pools_12_1_4()
{
    db_fix_add_column "IisAppPools" "managedPipelineMode" "enum('Classic','Integrated') NOT NULL default 'Integrated'"
}

db_upgrade_features_new_12_1_4()
{
    db_do "DELETE FROM cl_param WHERE param LIKE 'feature_%'"
}

db_12_1_4_fix_default_null()
{
	db_do "UPDATE \`$1\` SET \`$2\` = 0 WHERE \`$2\` IS NULL"
}

db_upgrade_unified_db_12_1_4()
{
	# Set engine
	if db_test_table "LimitsReservation"; then
		db_do "ALTER TABLE LimitsReservation ENGINE=InnoDB"
	fi

	# Set collation to utf8
	#for table in accounts actions apsContexts apsContextsApplications APSLicenses APSLicenseTypes apsResources \
	#	BackendCache Cards certificates cl_param clients Configurations cp_access custom_buttons data_bases \
	#	DatabaseUserRemoteAccessRules db_users dns_recs dns_recs_t dns_refs dns_zone dom_param domain_aliases \
	#	domains event_handlers exp_event GL_remote_domains GL_settings hosting IP_Addresses key_history \
	#	key_history_params Limits locales log_actions log_components log_rotation Logos longtaskparams longtasks \
	#	mail mail_aliases mail_resp MailLists misc mn_param Modules Notifications Parameters password_secrets \
	#	pd_users Permissions PersistentCache PlanItems protected_dirs report_section resp_freq SBConfig SBResellers \
	#	secret_keys ServiceNodeCache ServiceNodeCertificates ServiceNodeConfiguration ServiceNodeEnvironment \
	#	ServiceNodes SessionContexts sessions Skins smtp_poplocks spamfilter spamfilter_preferences subdomains \
	#	Subscriptions sys_users Templates TmplData upgrade_history WebApps Webmails \
	#	LimitsReservation; do
	#		db_set_utf8 $table
	#done

    # add indexes
    db_fix_add_key --name "license_type_id" "APSLicenses" "license_type_id"
    db_fix_add_key --name "date_type" "avstatistics" "type" "date"
    db_fix_add_key --name "uid" "dom_level_usrs" "uid"
    db_fix_add_key --name "displayName" "domain_aliases" "displayName"
    db_fix_add_key --name "dns_zone_id" "domains" "dns_zone_id"
    db_fix_add_key --name "source" "exp_event" "source" "event_type"
    db_fix_add_key --name "source_2" "exp_event" "source" "event_type" "obj_class"
    db_fix_add_key --name "source_3" "exp_event" "source" "event_time" "event_type" "obj_class"
    db_fix_add_key --name "flushed" "exp_event" "flushed"
    db_fix_add_key --name "action_id" "log_components" "action_id"

    # rename indexes
    db_fix_drop_key --name "collectionRef" "LimitsReservation"
    db_fix_add_key --name "collection" "LimitsReservation" "collectionRef" "limitName"
    db_fix_add_key --name "subscriptionId_idx" "WordpressInstances" "subscriptionId"

    # rename unique keys
    db_fix_add_unique_key --name "client_app_item" "APSClientApplicationItems" "client_id" "app_item_id"
    db_fix_add_unique_key --name "id" "BackupsSettings" "id" "type" "param"
    db_fix_add_unique_key --name "name_and_db_server_id" "data_bases" "name" "db_server_id"
    db_fix_add_unique_key --name "mm_cl" "mass_mail_clients" "mm_id" "cl_id"
    db_fix_add_unique_key --name "mm_dom" "mass_mail_domains" "mm_id" "dom_id"
    db_fix_add_unique_key --name "reference" "ServiceInstances" "serviceInstallationId" "servicePackageId" "reference"
    db_fix_add_unique_key --name "object_id_and_type" "Subscriptions" "object_id" "object_type"
    db_fix_add_unique_key --name "login" "sys_users" "serviceNodeId" "login"
    db_fix_add_unique_key --name "path" "WordpressInstances" "subscriptionId" "path"

    # add default 0 to be same as Windows
    db_fix_change_column "anon_ftp" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "APSApplicationItems" "license_type_id" "license_type_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "apscategories" "parent_id" "parent_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "APSLicenses" "license_type_id" "license_type_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "BackupsScheduled" "obj_id" "obj_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "BackupsScheduled" "period" "period" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "cl_param" "cl_id" "cl_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "clients" "limits_id" "limits_id" "INT(10) UNSIGNED DEFAULT '0'"
    db_12_1_4_fix_default_null "clients" "params_id"
    db_fix_change_column "clients" "params_id" "params_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_12_1_4_fix_default_null "clients" "perm_id"
    db_fix_change_column "clients" "perm_id" "perm_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_12_1_4_fix_default_null "clients" "pool_id"
    db_fix_change_column "clients" "pool_id" "pool_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_12_1_4_fix_default_null "clients" "logo_id"
    db_fix_change_column "clients" "logo_id" "logo_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_12_1_4_fix_default_null "clients" "tmpl_id"
    db_fix_change_column "clients" "tmpl_id" "tmpl_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_12_1_4_fix_default_null "clients" "sapp_pool_id"
    db_fix_change_column "clients" "sapp_pool_id" "sapp_pool_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_12_1_4_fix_default_null "clients" "parent_id"
    db_fix_change_column "clients" "parent_id" "parent_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "ClientsTraffic" "cl_id" "cl_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "data_bases" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "db_users" "db_id" "db_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "db_users" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "db_users" "db_server_id" "db_server_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "disk_usage" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "dom_level_usrs" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "dom_level_usrs" "account_id" "account_id" "INT(10) UNSIGNED"
    db_fix_change_column "dom_param" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "domain_aliases" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "domains" "cl_id" "cl_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "domains" "cert_rep_id" "cert_rep_id" "INT(10) UNSIGNED DEFAULT '0'"
    db_12_1_4_fix_default_null "domains" "limits_id"
    db_fix_change_column "domains" "limits_id" "limits_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_12_1_4_fix_default_null "domains" "params_id"
    db_fix_change_column "domains" "params_id" "params_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_12_1_4_fix_default_null "domains" "vendor_id"
    db_fix_change_column "domains" "vendor_id" "vendor_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "DomainServices" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_12_1_4_fix_default_null "DomainServices" "parameters_id"
    db_fix_change_column "DomainServices" "parameters_id" "parameters_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_12_1_4_fix_default_null "DomainServices" "ipCollectionId"
    db_fix_change_column "DomainServices" "ipCollectionId" "ipCollectionId" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "DomainsTraffic" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "event_handlers" "action_id" "action_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_12_1_4_fix_default_null "externalWebmails" "enabled"
    db_fix_change_column "externalWebmails" "enabled" "enabled" "INT(10) NOT NULL DEFAULT '0'"
    db_fix_change_column "forwarding" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "ftp_users" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "ftp_users" "sys_user_id" "sys_user_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "hosting" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "hosting" "sys_user_id" "sys_user_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "IP_Addresses" "ssl_certificate_id" "ssl_certificate_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_12_1_4_fix_default_null "IP_Addresses" "default_domain_id"
    db_fix_change_column "IP_Addresses" "default_domain_id" "default_domain_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "key_history_params" "key_id" "key_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "log_actions" "action_id" "action_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "log_actions" "object_id" "object_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "log_components" "action_id" "action_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "mail" "account_id" "account_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "mail" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "mail" "perm_id" "perm_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "mail_aliases" "mn_id" "mn_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "mail_redir" "mn_id" "mn_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "mail_resp" "mn_id" "mn_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "MailLists" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "mn_param" "mn_id" "mn_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "ModuleSettings" "module_id" "module_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "pd_users" "account_id" "account_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "pd_users" "pd_id" "pd_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "PhpSettingsParameters" "id" "id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "PlanItemProperties" "plan_item_id" "plan_item_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "protected_dirs" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "report" "type" "type" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "report" "user_type" "user_type" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "report_auto" "report_id" "report_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "report_auto" "client" "client" "INT(10) UNSIGNED DEFAULT '0'"
    db_fix_change_column "report_auto" "domain" "domain" "INT(10) UNSIGNED DEFAULT '0'"
    db_fix_change_column "report_section" "report_id" "report_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "Repository" "component_id" "component_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "resp_attach" "rn_id" "rn_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "resp_forward" "rn_id" "rn_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "resp_freq" "rn_id" "rn_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "sessions" "type" "type" "SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "subdomains" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "subdomains" "sys_user_id" "sys_user_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "SubscriptionProperties" "subscription_id" "subscription_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "sys_users" "account_id" "account_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "TmplData" "tmpl_id" "tmpl_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "web_users" "dom_id" "dom_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "web_users" "sys_user_id" "sys_user_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "WebApps" "domain_service_id" "domain_service_id" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
    db_fix_change_column "ftp_users" "permission" "permission" "BIGINT(20) UNSIGNED NOT NULL DEFAULT '0'"

    # add other defaults to be same as Windows
    db_fix_change_column "APSCatalogUpdates" "update_type" "update_type" "ENUM('patch','upgrade') NOT NULL DEFAULT 'patch'"
    db_fix_change_column "DatabaseServers" "type" "type" "ENUM('mysql','postgresql','mssql') NOT NULL DEFAULT 'mysql'"
    db_fix_change_column "domains" "htype" "htype" "ENUM('none','vrt_hst','std_fwd','frm_fwd') NOT NULL DEFAULT 'none'"
    db_fix_change_column "exp_event" "event_type" "event_type" "ENUM('started','stopped','created','updated','deleted','status_changed','terminated','flushed','installed','uninstalled','siteapp_added','siteapp_removed','expired','exceeded','guid_changed') NOT NULL DEFAULT 'started'"
    db_fix_change_column "exp_event" "obj_class" "obj_class" "varchar(255) NOT NULL DEFAULT 'license'"
    db_do 'UPDATE `ip_pool` SET `type` = "shared" WHERE `type` IS NULL'
    db_fix_change_column "ip_pool" "type" "type" "ENUM('shared','exclusive') NOT NULL DEFAULT 'shared'"

    db_fix_change_column "APSCatalogUpdates" "received" "received" "DATETIME DEFAULT '0000-00-00 00:00:00'"
    db_fix_change_column "upgrade_history" "upgrade_date" "upgrade_date" "DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00'"
    db_fix_change_column "ClientsTraffic" "date" "date" "DATE NOT NULL DEFAULT '0000-00-00'"
    db_fix_change_column "DomainsTraffic" "date" "date" "DATE NOT NULL DEFAULT '0000-00-00'"
    db_fix_change_column "MailMessagesStat" "date" "date" "DATE NOT NULL DEFAULT '0000-00-00'"
    db_fix_change_column "PleskPagesStat" "date" "date" "DATE NOT NULL DEFAULT '0000-00-00'"
    db_fix_change_column "SitePagesStat" "date" "date" "DATE NOT NULL DEFAULT '0000-00-00'"

    db_fix_change_column "exp_event" "event_time" "event_time" "TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP"

    # add notNull attribute where default is available
    db_fix_change_column "apsContexts" "subscriptionId" "subscriptionId" "INT(10) UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "BackupsScheduled" "content_type" "content_type" "ENUM('backup_content_all_at_domain','backup_content_vhost_only','backup_content_mail_only') NOT NULL DEFAULT 'backup_content_all_at_domain'"
    db_fix_change_column "PhpSettings" "noteId" "noteId" "INT(10) UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "PlanItems" "isVisible" "isVisible" "INT(10) UNSIGNED NOT NULL DEFAULT 1"
    db_fix_change_column "PlanItems" "applicableToSubscription" "applicableToSubscription" "INT(10) UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "PlanItems" "applicableToEmail" "applicableToEmail" "INT(10) UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "PlanItems" "applicableToSite" "applicableToSite" "INT(10) UNSIGNED NOT NULL DEFAULT 0"

    # drop NOT NULL DEFAULT ''
    db_fix_change_column "apsResourcesParameters" "value" "value" "VARCHAR(255)"
    db_fix_change_column "clients" "external_id" "external_id" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "DatabaseUserRemoteAccessRules" "firewallRuleId" "firewallRuleId" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "dns_recs" "external_id" "external_id" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "dns_zone" "external_id" "external_id" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "domains" "external_id" "external_id" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "hosting" "write_modify" "write_modify" "VARCHAR(255)"
    db_fix_change_column "ServiceNodeCertificates" "certFile" "certFile" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "ServiceNodeCertificates" "caFile" "caFile" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "ServiceNodes" "externalId" "externalId" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "Subscriptions" "external_id" "external_id" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "Templates" "external_id" "external_id" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin"

    # fix wrong type attributes
    db_fix_change_column "accounts" "password" "password" "TEXT CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "ai_vendor_sources" "url" "url" "VARCHAR(255) NOT NULL DEFAULT ''"
    db_fix_change_column "ai_vendor_sources" "login" "login" "VARCHAR(255) DEFAULT ''"
    db_fix_change_column "ai_vendor_sources" "password" "password" "VARCHAR(255) DEFAULT ''"
    db_fix_change_column "APSLicenseTypes" "application_name" "application_name" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL"
    db_fix_change_column "APSLicenseTypes" "application_versions" "application_versions" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL"
    db_fix_change_column "ApsTokens" "applicationId" "applicationId" "VARCHAR(2000) NOT NULL"
    db_fix_change_column "BackupsScheduled" "backup_time" "backup_time" "VARCHAR(8) NOT NULL default '00:00:00'"
    db_fix_change_column "BackendCache" "data" "data" "TEXT NOT NULL"
    db_fix_change_column "cl_param" "val" "val" "VARCHAR(255)"
    db_fix_change_column "data_bases" "name" "name" "VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL"
    db_fix_change_column "DatabaseServers" "server_version" "server_version" "CHAR(255) NOT NULL"
    db_fix_change_column "DatabaseServers" "admin_login" "admin_login" "CHAR(255) NOT NULL"
    db_fix_change_column "DatabaseServers" "admin_password" "admin_password" "CHAR(255) NOT NULL"
    db_fix_change_column "dom_level_usrs" "passwd" "passwd" "VARCHAR(255) NOT NULL DEFAULT ''"
    db_fix_change_column "dom_param" "val" "val" "VARCHAR(255)"
    db_fix_change_column "domain_aliases" "status" "status" "BIGINT(20) UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "DomainOutgoingMessagesPeaks" "rejected" "rejected" "BIGINT(20) UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "DomainOutgoingMessagesStats" "limitValue" "limitValue" "BIGINT(20) NOT NULL DEFAULT -1"
    db_fix_change_column "DomainOutgoingMessagesStats" "passed" "passed" "BIGINT(20) UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "DomainOutgoingMessagesStats" "rejected" "rejected" "BIGINT(20) UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "DomainServices" "status" "status" "BIGINT(20) NOT NULL DEFAULT 0"
    db_fix_change_column "hosting" "www_root" "www_root" "TEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL"
    db_fix_change_column "key_history_params" "val" "val" "VARCHAR(255) NOT NULL"
    db_fix_change_column "Limits" "limit_name" "limit_name" "VARCHAR(255) NOT NULL"
    db_fix_change_column "Limits" "value" "value" "VARCHAR(255)"
    db_fix_change_column "LimitsReservation" "value" "value" "BIGINT(20)"
    db_fix_change_column "log_components" "component" "component" "VARCHAR(255) NOT NULL"
    db_fix_change_column "log_components" "old_value" "old_value" "VARCHAR(255) NOT NULL"
    db_fix_change_column "log_components" "new_value" "new_value" "VARCHAR(255) NOT NULL"
    db_fix_change_column "longtaskparams" "val" "val" "MEDIUMTEXT"
    db_fix_change_column "mail" "disk_usage" "disk_usage" "BIGINT UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "MailOutgoingMessagesPeaks" "rejected" "rejected" "BIGINT(20) UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "MailOutgoingMessagesStats" "limitValue" "limitValue" "BIGINT(20) NOT NULL DEFAULT -1"
    db_fix_change_column "MailOutgoingMessagesStats" "passed" "passed" "BIGINT(20) UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "MailOutgoingMessagesStats" "rejected" "rejected" "BIGINT(20) UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "misc" "val" "val" "VARCHAR(2000)"
    db_fix_change_column "mn_param" "val" "val" "VARCHAR(255)"
    db_fix_change_column "Parameters" "parameter" "parameter" "VARCHAR(255) NOT NULL"
    db_fix_change_column "Parameters" "value" "value" "VARCHAR(255)"
    db_fix_change_column "Permissions" "permission" "permission" "VARCHAR(255) NOT NULL"
    db_fix_change_column "Permissions" "value" "value" "VARCHAR(255)"
    db_fix_change_column "SubscriptionOutgoingMessagesPeaks" "rejected" "rejected" "BIGINT(20) UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "SubscriptionOutgoingMessagesStats" "limitValue" "limitValue" "BIGINT(20) NOT NULL DEFAULT -1"
    db_fix_change_column "SubscriptionOutgoingMessagesStats" "passed" "passed" "BIGINT(20) UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "SubscriptionOutgoingMessagesStats" "rejected" "rejected" "BIGINT(20) UNSIGNED NOT NULL DEFAULT 0"
    db_fix_change_column "ServiceNodeCache" "path" "path" "TEXT CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "ServiceNodeCache" "cache" "cache" "TEXT CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "ServiceNodes" "accessKey" "accessKey" "TEXT CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "SessionContexts" "data" "data" "MEDIUMTEXT"
    db_fix_change_column "subdomains" "www_root" "www_root" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT 'httpdocs'"
    db_fix_change_column "suspend_handler_history" "session_id" "session_id" "VARCHAR(255)"
    db_fix_change_column "TmplData" "value" "value" "VARCHAR(255) NOT NULL"
    db_fix_change_column "WordpressInstanceProperties" "value" "value" "MEDIUMTEXT NOT NULL"

    # drop default=0 for foreign key columns
    db_fix_change_column "admin_aliases" "account_id" "account_id" "INT(10) UNSIGNED NOT NULL"
    db_fix_change_column "cf_dsn" "domain_id" "domain_id" "INT(10) UNSIGNED NOT NULL"
    db_fix_change_column "cf_dsn_params" "cf_dsn_id" "cf_dsn_id" "INT(10) UNSIGNED NOT NULL"
    db_fix_change_column "clients" "account_id" "account_id" "INT(10) UNSIGNED NOT NULL"
    db_fix_change_column "DatabaseServers" "parameters_id" "parameters_id" "INT(10) UNSIGNED"
    db_fix_change_column "dom_level_usrs" "account_id" "account_id" "INT(10) UNSIGNED"
    db_fix_change_column "IisAppPoolDomains" "domainId" "domainId" "INT(10) UNSIGNED NOT NULL"
    db_fix_change_column "IisAppPoolDomains" "poolId" "poolId" "INT(10) UNSIGNED NOT NULL"
    db_fix_change_column "IisAppPools" "ownerId" "ownerId" "INT(10) UNSIGNED NOT NULL"
    db_fix_change_column "mail" "userId" "userId" "INT(10) UNSIGNED"
    db_fix_change_column "shared_ssl_links" "sharedSslId" "sharedSslId" "INT(10) UNSIGNED NOT NULL"
    db_fix_change_column "SharedSslDomains" "clientId" "clientId" "INT(10) UNSIGNED NOT NULL"
    db_fix_change_column "SharedSslDomains" "domainId" "domainId" "INT(10) UNSIGNED NOT NULL"

    # drop NOT NULL where this constraint cannot be added on Windows
    db_fix_change_column "APSLicenses" "source" "source" "TEXT"
    db_fix_change_column "custom_buttons" "text" "text" "VARCHAR(255)"
    db_fix_change_column "DatabaseServers" "server_version" "server_version" "CHAR(255)"
    db_fix_change_column "domain_aliases" "dns_zone_id" "dns_zone_id" "INT(10) UNSIGNED"
    db_fix_change_column "domains" "dns_zone_id" "dns_zone_id" "INT(10) UNSIGNED"
    db_fix_change_column "event_handlers" "command" "command" "TEXT CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "key_history_params" "val" "val" "VARCHAR(255)"
    db_fix_change_column "log_actions" "date" "date" "DATETIME"
    db_fix_change_column "mail" "userId" "userId" "INT(10) UNSIGNED"
    db_fix_change_column "Notifications" "send2reseller" "send2reseller" "VARCHAR(1) CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "report" "name" "name" "VARCHAR(255)"
    db_fix_change_column "sessions" "login" "login" "VARCHAR(255)"
    db_fix_change_column "sessions" "ip_address" "ip_address" "VARCHAR(39)"
    db_fix_change_column "upgrade_history" "version_info" "version_info" "VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_bin"
    db_fix_change_column "upgrade_history" "db_version" "db_version" "VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_bin"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_unified_db_12_1_5()
{
    db_fix_change_column "certificates" "csr" "csr" "BLOB"
    db_fix_change_column "certificates" "pvt_key" "pvt_key" "BLOB"
    db_fix_change_column "certificates" "cert" "cert" "BLOB"
    db_fix_change_column "certificates" "ca_cert" "ca_cert" "BLOB"
    db_fix_change_column "certificates" "cert_file" "cert_file" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT ''"
    db_fix_change_column "certificates" "ca_file" "ca_file" "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT ''"
    db_fix_change_column "certificates" "name" "name" "VARCHAR(255) NOT NULL DEFAULT ''"
    db_fix_change_column "Configurations" "file" "file" "BLOB"
    db_fix_change_column "Configurations" "errorFile" "errorFile" "BLOB"
    db_fix_change_column "db_users" "login" "login" "VARCHAR(128) NOT NULL"
    db_fix_change_column "GL_remote_domains" "serviceNodeId" "serviceNodeId" "INT(11) NOT NULL DEFAULT 1"
    db_fix_change_column "GL_settings" "serviceNodeId" "serviceNodeId" "INT(11) NOT NULL DEFAULT 1"
    db_fix_change_column "secret_keys" "client_id" "client_id" "INT(10) UNSIGNED"
    db_fix_change_column "Limits" "value" "value" "BIGINT(20)"
    db_fix_del_column "longtasks" "can_cancel"
    db_fix_del_column "ServiceNodes" "transport"
    db_fix_drop_unique_key --name "name" "dsn"
    db_fix_add_unique_key --name "name" "dsn" "name" "serviceNodeId"
    db_fix_add_key --name "parentDomainId" "domains" "parentDomainId"
}

db_upgrade_subscriptions_12_1_5()
{
    db_fix_change_column "Subscriptions" "uuid" "uuid" "VARCHAR(36)"
}

db_upgrade_generate_service_instance_references_12_1_5()
{
    sw_engine_pleskrun $PRODUCT_ROOT_D/admin/plib/scripts/upgrade_service_instance_references_12.1.5.php && suc || warn "fail\nCannot generate references for ServiceInstances"
}

db_drop_pmm_tables_12_1_5()
{
	db_fix_drop_table "PMM"
	db_fix_drop_table "PMMDefault"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_upgrade_smb_unified_12_1_6()
{
	db_fix_add_key --name "subscriptionDomainId_idx" "smb_users" "subscriptionDomainId"

	db_fix_add_key --name "filterId_idx" "smb_apsBundleFilterItems" "filterId"
	db_fix_add_key --name "roleId_idx" "smb_roleGeneralPermissions" "roleId"
	db_fix_add_key --name "ownerId_idx" "smb_roles" "ownerId"
	db_fix_add_key --name "ownerId_idx" "smb_users" "ownerId"
	db_fix_add_key --name "isBuiltIn_idx" "smb_users" "isBuiltIn"
	db_fix_drop_unique_key --name "cacheId_2" "smb_apsPackages"

	db_fix_change_column "smb_apsBundleFilterItems" "filterId" "filterId" "INT(10) UNSIGNED NOT NULL DEFAULT '0'"
	db_fix_change_column "smb_users" "isDomainAdmin" "isDomainAdmin" "INT(11) DEFAULT '0'"
	db_fix_change_column "smb_users" "isLegacyUser" "isLegacyUser" "INT(11) DEFAULT '0'"
	db_fix_change_column "smb_apsPackages" "installed" "installed" "VARCHAR(26)"
	db_fix_change_column "smb_users" "subscriptionDomainId" "subscriptionDomainId" "INT(11) DEFAULT 0"
}

db_remove_tables_12_1_6()
{
	db_fix_drop_table "smb_apsImportedResources"
	db_fix_drop_table "smb_apsImportedSettings"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

db_drop_storefront_12_1_7()
{
	db_fix_del_column "smb_apsPackages" "isNonStorefrontCommercial"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

refresh_trusted_ips_12_1_8()
{
	sw_engine_pleskrun $PRODUCT_ROOT_D/admin/plib/scripts/refresh-trusted-ips.php && suc || warn "fail\nrefresh trusted ips for site preview"
}

db_upgrade_backups_scheduled_12_1_8()
{
	db_fix_change_column "BackupsScheduled" "split_size" "split_size" "BIGINT(20) UNSIGNED NOT NULL DEFAULT '0'"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
upgrade_proftpd_107()
{
	echo_try "upgrade anon_ftp quota to new format"
	local domain;
	for domain in $HTTPD_VHOSTS_D/*; do
		[ -e $domain/anon_ftp/incoming/quotadir ] || continue
		rm -f $domain/anon_ftp/incoming/quotadir/.undeletable \
			$domain/anon_ftp/incoming/quotadir/.quota >> $product_log 2>&1
		rmdir $domain/anon_ftp/incoming/quotadir >> $product_log 2>&1
	done
	sw_engine_pleskrun $PRODUCT_ROOT_D/admin/plib/scripts/upgrade_proftpd_107.php && suc || warn "fail\nupgrade anon_ftp quota to new format"
}

upgrade_transfer_proftpd_logs_11_6_1()
{
	transfer_log_with_compat_symlink "${PRODUCT_ROOT_D}/var/log/xferlog" "${PRODUCT_LOGS_D}/xferlog"
	transfer_log_with_compat_symlink "${PRODUCT_ROOT_D}/var/log/ftp_tls.log" "${PRODUCT_LOGS_D}/ftp_tls.log"

	if ls ${PRODUCT_ROOT_D}/var/log/ftp_tls.log.*.gz > /dev/null 2>&1; then
		mv -f ${PRODUCT_ROOT_D}/var/log/ftp_tls.log.*.gz "${PRODUCT_LOGS_D}"
	fi

	if ls ${PRODUCT_ROOT_D}/var/log/xferlog.processed* > /dev/null 2>&1; then
		mv -f ${PRODUCT_ROOT_D}/var/log/xferlog.processed* "${PRODUCT_LOGS_D}"
	fi
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
# vim:ft=sh
# Usage:  pleskrc <service> <action>
pleskrc()
{
	[ 2 -le $# ] || die "Not enough arguments"

	local service_name=$1
	local action=$2
	local ret=0
	local inten
	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"

	service_ctl "$action" "$service" "$service_name"

	ret="$?"
	if [ "$action" != "status" -a "${action}" != "exists" ]; then
		if [ "$ret" -eq 0 ]; then
			suc
		else
			[ ! -x "/bin/systemctl" ] || /bin/systemctl status "${service}.service" >> "$product_log" 2>&1
			warn "$inten"
		fi
	fi

	return $ret
}

# NOTE:
#	Function service_ctl is just helper for pleskrc().
#	Do not call it directly, use pleskrc()!!!
service_ctl()
{
	local action=$1
	local service=$2
	local service_name=$3

	if [ "$action" != "exists" ]; then
		_service_exec $service exists;
		if [ "$?" != "0" ]; then
			warn "attempt to ${inten} - control script doesn't exist or isn't executable"
			return 1
		fi
	fi

	case "$action" in
		start)
			pleskrc "$service_name" status || _service_exec "$service" "$action"
			;;
		stop)
			! pleskrc "$service_name" status || _service_exec "$service" "$action"
			;;
		restart)
			if pleskrc "$service_name" status; then
				_service_exec "$service" "$action"
			else
				_service_exec "$service" start
			fi
			;;
		reload)
			! pleskrc "$service_name" status || _service_exec "$service" "$action"
			;;
		status)
			_service_exec "$service" status
			;;
		*)
			_service_exec "$service" "$action"
			;;
	esac >> "$product_log"
}

_service_exec()
{
	local service=$1
	local action=$2

	local action_cmd
	local sysvinit_service="/etc/init.d/$service"

	if [ -x "/bin/systemctl" ]; then
		case "${action}" in
			exists)
				if /bin/systemctl list-unit-files | awk 'BEGIN { rc = 1 } $1 == "'$service'.service" { rc = 0;} END { exit rc }'; then
					return 0 # systemd unit
				elif [ -x "$sysvinit_service" ]; then
					return 0 # sysvinit compat
				fi
				return 1 # not found
				;;
			status)
				action="is-active"
				;;
			reload)
				action='reload-or-try-restart'
				;;
		esac
		/bin/systemctl "$action" "${service}.service"
	else
		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 [ -x "/usr/sbin/service" ]; then
			action_cmd="/usr/sbin/service $service"
		else
			action_cmd="$sysvinit_service"
		fi

		if [ "$action" = "exists" ]; then
			[ -x "$sysvinit_service" ] && return 0 || return 1
		else
			$action_cmd $action
		fi
	fi
}

is_function()
{
	local type_output="`type \"$1\" 2>/dev/null | head -n1 | awk '{print $NF}'`"
	test "X${type_output}" = "Xfunction"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

# 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="$*"

	printf "\a\a"
	report_problem \
		"ERROR while trying to $*" \
		"Check the error reason(see log file: ${product_log}), fix and try again"

	selinux_close

	exit 1
}

simply_die()
{
	report_problem "$@"
	exit 1
}

# This function needs for some print warning when some services cannot restart
# if called with arg, then we add arg to variable SR_WARNING and print warning
# message for arg, else print warning message for SR_WARNING
service_restart_warning()
{
	if [ "X$1" != "X" ]; then
		if [ "X${SR_WARNING}" = "X" ]; then
			SR_WARNING=$1
		else
			for i in ${SR_WARNING}; do
				if [ "$i" = "$1" ]; then
					break
				fi
			done
			if [ "$1" != "$i" ]; then
				SR_WARNING=$SR_WARNING" "$1
			fi
		fi
		p_echo "WARNING!"
		p_echo "Some problems occured when $1 restart, check it after installation/upgrade complete"
	        p_echo
	 	p_echo "Continue..."
		p_echo
	else
		if [ "X${SR_WARNING}" != "X" ]; then
			p_echo "WARNING!"
		        p_echo "Some problems occured when following services restart:"
			for i in ${SR_WARNING}; do
				p_echo $i
			done
			p_echo "Don't forget to check it after installation/upgrade complete"
        		p_echo
	       	        p_echo "More information can be found in log file: ${product_log}"
			p_echo
		fi
	fi
}

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_with_input "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()
{
	[ -n "$product_problems_log" ] || product_problems_log="/dev/stderr"

	p_echo
	if [ "0$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_with_input "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"
}

# do not call it w/o input! Use send_error_report in these cases.
send_error_report_with_input()
{
	get_product_versions
	{
		echo "$@"
		echo ""
		if [ -n "$error_report_context" ]; then
			echo "Context: $error_report_context"
			echo ""
		fi
		if [ -n "$RP_LOADED_PATCHES" ]; then
			echo "Loaded runtime patches: $RP_LOADED_PATCHES"
			echo ""
		fi
		cat -
	} | $PRODUCT_ROOT_D/admin/bin/send-error-report --version "$product_this_version" install >/dev/null 2>&1
}

set_error_report_context()
{
	error_report_context="$*"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

# vim:ft=sh

mk_backup()
{
	local target dup opts
	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_suffo"
					;;
				cp)
					cp -fp $target $target.$product_suffo || die "cp -fp $target $target.$product_suffo"
					;;
				*)
					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()
{
	local u_owner g_owner perms node
	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"
}

set_default_locale_params()
{
	local default_locale_file="$PRODUCT_ROOT_D/admin/htdocs/locales/default"

	if [ -f $default_locale_file ]; then
		test -r "$default_locale_file" || die "set up default locale: cannot read '$default_locale_file'"
		default_locale="`cat $default_locale_file | sed 's/^\([^:]*\):.*/\1/'`"
		default_locale_name="`cat $default_locale_file | sed 's/^[^:]*:\([^:]*\):.*/\1/'`"
		default_locale_country="`cat $default_locale_file | sed 's/^[^:]*:[^:]*:[^:]*:\([^:]*\);.*/\1/'`"
	else
		default_locale="en-US"
		default_locale_name="ENGLISH"
		default_locale_country="UNITED STATES"
	fi
}

detect_vz()
{
	PLESK_VZ=0
	PLESK_VE_HW_NODE=0
	PLESK_VZ_TYPE=

	local issue_file="/etc/issue"
	local vzcheck_file="/proc/self/status"
	[ -f "$vzcheck_file" ] || return 1

	local env_id=`sed -ne 's|^envID\:[[:space:]]*\([[:digit:]]\+\)$|\1|p' "$vzcheck_file"`
	[ -n "$env_id" ] || return 1
	if [ "$env_id" = "0" ]; then
		# Either VZ/OpenVZ HW node or unjailed CloudLinux
		PLESK_VE_HW_NODE=1
		return 1
	fi

	if grep -q "CloudLinux" "$issue_file" >/dev/null 2>&1 ; then
		return 1
	fi

	if [ -f "/proc/vz/veredir" ]; then
		PLESK_VZ_TYPE="vz"
	elif [ -d "/proc/vz" ]; then
		PLESK_VZ_TYPE="openvz"
	fi

	PLESK_VZ=1
	return 0
}

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 IFS="$2"
	get_narg $3 $1
}

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

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
}

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
}

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
}

register_sw_engine_service()
{
	register_service sw-engine
}

implode()
{
	local IFS="$1"
	shift
	echo "$*"
}

configure_ssl_ciphers_protocols()
{
    local inten="configure SSL ciphers and protocols"
	echo_try "$inten"
    if $PRODUCT_ROOT_D/admin/sbin/sslmng >>$product_log 2>&1; then
        suc
    else
        warn "$inten"
		return 1
    fi
}

lookup_command()
{
	test $# -eq 1 || die 'lookup_command() not enough arguments'
	local _path=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin:${PATH}
	
	local utility_path=`env PATH=${_path} which "$1" 2>/dev/null`
	if [ -z "$utility_path" ]; then
		p_echo "Unable to find utility '$1'in ${_path}"
		return
	fi
	echo $utility_path
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
#-*- 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_12.5.30${action:+_$action}${aux_descr}.log"
	fi
}

product_log_name()
{
	product_log_name_ex
}

product_problems_log_name()
{
	product_log_name_ex "problems"
}

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

set_log_action_name()
{
	CUSTOM_LOG_ACTION_NAME="$1"
}

mktemp_log()
{
	local logname="$1"
	local dir="$2"

	if ! expr match "$logname" '/' > /dev/null; then
		logname="$dir/$logname"
	fi
	dir="`dirname $logname`"
	if [ ! -d "$dir" ]; then
		mkdir -p "$dir" || { echo "Unable to create log directory : $dir"; exit 1; }
		if [ "`id -u`" = "0" ]; then
			set_ac root 0 0700 "$dir"
		fi
	fi

	if echo $logname  | grep -q XXX > /dev/null; then
		mktemp "$logname"
	else
		echo "$logname"
	fi
}

log_is_in_dev()
{
	local logfile="$1"
	expr match "$logfile" '/dev/' > /dev/null
	return $?
}

start_writing_logfile()
{
	local logfile="$1"
	local title="$2"
	! log_is_in_dev "$logfile" || return 0
	echo "START $title" >> "$logfile" || { echo "Cannot write installation log $logfile" >&2; exit 1; }
	[ ! "`id -u`" = "0" ] || set_ac root 0 0600 "$logfile"
}

create_product_log_symlink()
{
	local logfile="$1"
	local prevdir="$2"

	local prevlog="$prevdir/`basename $logfile`"
	[ -e "$prevlog" ] || ln -sf "$logfile" "$prevlog"
}

log_start()
{
	true product_log_name product_problems_log_name mktemp_log

	local title="$1"
	local custom_log="$2"
	local custom_problems_log="$3"

	local product_log_dir="/var/log/plesk/install"

	product_log="$product_log_dir/`product_log_name`"
	product_problems_log="$product_log_dir/`product_problems_log_name`"
	problems_occured=0

	# init product log
	[ ! -n "$custom_log" ] || product_log="$custom_log"
	product_log=`mktemp_log "$product_log" "$product_log_dir"`

	# init problems log
	if [ -n "$custom_problems_log" ]; then
		product_problems_log=`mktemp_log "$custom_problems_log" "$product_log_dir"`
	elif [ -n "$custom_log" ]; then
		product_problems_log="$product_log"
	else
		product_problems_log=`mktemp_log "$product_problems_log" "$product_log_dir"`
	fi

	# write starting message into logs
	start_writing_logfile "$product_log" "$title"
	if [ "$product_log" != "$product_problems_log" ]; then
		start_writing_logfile "$product_problems_log" "$title"
	fi

	# create compat symlinks if logs are written to default localtions
	if [ -z "$custom_log" -a -z "$CUSTOM_LOG_NAME" ]; then
		create_product_log_symlink "$product_log" "/tmp"
		[ ! -z "$custom_problems_log" ] || create_product_log_symlink "$product_problems_log" "/tmp"
	fi

	is_function profiler_setup && profiler_setup "$title" || :
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

#
# Support for runtime patching of shell scripts (including utilities and package scripts).
#

# --- Service functions ---

# Load and apply a patch in a relatively safe way
rp_safe_load_patch()
{
	local patch_file="$1"
	echo_try "load shell patch '$patch_file'"
	/bin/sh -n "$RP_BASEDIR/$patch_file" && 
	{
		. "$RP_BASEDIR/$patch_file"
		RP_LOADED_PATCHES="$RP_LOADED_PATCHES $patch_file"
	} &&
	suc
}

# Apply patches specific to the current context (e.g., depending on utility basename or package name)
# This is currently not implemented. This may be overriden by "spark".
rp_patch_runtime_context_specific()
{
	:
}

# --- Main entry points ---

rp_patch_runtime()
{
	# List of loaded patch files
	RP_LOADED_PATCHES=

	local RP_BASEDIR="$PRODUCT_BOOTSTRAPPER_DIR/rp"
	[ -d "$RP_BASEDIR" ] || return 0

	if [ -r "$RP_BASEDIR/spark" ]; then
		rp_safe_load_patch "spark"
	fi

	call_optional_function rp_patch_runtime_context_specific "$@"
}

txtdb_set_params()
{
	db_file=""
	db_owner=""
	db_group=""
	db_perms="0644"
	db_delim=':'
	db_key_field="1"
	"$@"
	[ -n "$db_file" -a -n "$db_delim" ] || die "set txtdb parameters. Check arguments for 'txtdb_*' calls."
}

txtdb_fix_perms()
{
	[ -n "$db_owner" -a -n "$db_group" ] && chown "$db_owner":"$db_group" "$db_file"
	[ -n "$db_perms" ] && chmod "$db_perms" "$db_file"
	:
}

# Create new empty DB or replace an existing one
txtdb_truncate()
{
	local set_params_func="$1"
	local db_file db_owner db_group db_perms db_delim db_key_field
	txtdb_set_params "$set_params_func"

	rm -f "$db_file" && touch "$db_file" && txtdb_fix_perms
}

# Check whether DB file already exists and is writable
txtdb_exists()
{
	local set_params_func="$1"
	local db_file db_owner db_group db_perms db_delim db_key_field
	txtdb_set_params "$set_params_func"

	[ -w "$db_file" ]
}

txtdb_do_update()
{
	local set_params_func="$1"
	local awk_script="$2"
	local key_value="$3"
	local data_value="$4"
	local db_file db_owner db_group db_perms db_delim db_key_field
	txtdb_set_params "$set_params_func"

	awk -F "$db_delim" -v KEY="$key_value" -v DATA="$data_value" -v KEY_FIELD="$db_key_field" \
		"$awk_script" "$db_file" > "$db_file.new" 2>> $product_log && \
		mv -f "$db_file.new" "$db_file" && txtdb_fix_perms
}

txtdb_do_select()
{
	local set_params_func="$1"
	local awk_script="$2"
	local key_value="$3"
	local data_value="$4"
	local db_file db_owner db_group db_perms db_delim db_key_field
	txtdb_set_params "$set_params_func"

	awk -F "$db_delim" -v KEY="$key_value" -v DATA="$data_value" -v KEY_FIELD="$db_key_field" \
		"$awk_script" "$db_file" 2>> $product_log
}

# Insert or replace existing record identified by key field
txtdb_replace()
{
	local db_file db_owner db_group db_perms db_delim db_key_field
	txtdb_set_params "$1"

	# Note that records order is not preserved
	local replace_with="$2"
	local key_to_replace=`get_narg_fs "$replace_with" "$db_delim" "$db_key_field"`
	txtdb_do_update "$1" 'END { print DATA } ( $KEY_FIELD != KEY )' "$key_to_replace" "$replace_with"
}

# Select entire record by key field
txtdb_select()
{
	local key_to_select="$2"
	txtdb_do_select "$1" '( $KEY_FIELD == KEY )' "$key_to_select"
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

#
# Unified per-component cumulative upgrade support.
#

# --- Upgrader utility functions ---

cu_get_continue_stage()
{
	local continue_from="$1"
	get_narg_fs "$continue_from" '-' 1
}

cu_get_continue_id()
{
	local continue_from="$1"
	echo "`  get_narg_fs "$continue_from" '-' 2  `-`  get_narg_fs "$continue_from" '-' 3  `"
}

cu_get_current_continue_from()
{
	echo "$CU_LAST_STAGE-$CU_LAST_ACTION_ID"
}

# Remove extraneous delimiters (usually spaces) between array elements
normalize_array()
{
	echo $@
}

# Check that first argument is in array (other arguments)
is_in_array()
{
	local needle="$1"
	shift # everything else is haystack
	for elem in $@; do
		[ "$elem" = "$needle" ] && return 0
	done
	return 1
}

# Remove all instances of first argument from array (other arguments). Echoes normalized array with space delimiters.
remove_from_array()
{
	local what="$1"
	shift # everything else is array
	local new_array=
	for elem in $@; do
		[ "$elem" = "$what" ] || new_array="$new_array $elem"
	done
	echo $new_array
}

array_length_helper()
{
	echo $#
}

# Get number of elements in a given array
array_length()
{
	array_length_helper $@
}

# --- Chained upgrade actions checks ---

# cu_do <upgrade action> [<arguments>]: Execute an action or echo information about it
cu_do()
{
	if [ -n "$CU_DO_GET_ACTION_NAME" ]; then
		echo "$1"
		return
	fi

	if [ -n "$CU_CONTINUE_FROM_ID" ]; then
		# Run only actions starting from CU_CONTINUE_FROM_ID
		# WARNING: this will not work properly if there is a subshell execution somewhere along the chain!
		[ "$CU_LAST_ACTION_ID" = "$CU_CONTINUE_FROM_ID" ] && CU_CONTINUE_FROM_ID= || return 0
	fi

	if "$@"; then
		cu_remove_failed_action "$CU_LAST_ACTION_ID"
		return 0
	else
		cu_add_failed_action "$CU_LAST_ACTION_ID"
		return 1
	fi
}

# Echo resulting action name (function name) or empty if skipped
cu_get_action_name()
{
	local CU_DO_GET_ACTION_NAME="yes"
	"$@"
}

# Execute action only if it wasn't applied before (by timestamp, e.g. use `date '+%Y%m%d%H%M%S'` or even `date '+%Y/%m/%d %H:%M:%S'`)
cu_check_timestamp()
{
	local timestamp="`echo \"$1\" | tr -dc '[:digit:]'`"
	shift

	true cu_get_action_name
	CU_LAST_ACTION_ID="$timestamp-`cu_get_action_name "$@"`"

	# Skip timestamp check if this action should be done again (during repair)
	if [ -z "$CU_FAILED_ACTIONS" ] || ! is_in_array "$CU_LAST_ACTION_ID" "$CU_FAILED_ACTIONS"; then
		[ "$timestamp" -gt "$CU_START_TIMESTAMP" ] || return 0
	fi

	if [ "$timestamp" -gt "$CU_LATEST_TIMESTAMP" ]; then
		CU_LATEST_TIMESTAMP="$timestamp"
	fi

	"$@"
}

# Execute action only if it wasn't applied before (by version)
cu_check_version()
{
	true cu_get_action_name
	CU_LAST_ACTION_ID="$CU_UPGRADE_VERSION_FROM-`cu_get_action_name "$@"`"

	# Skip version check if this action should be done again (during repair)
	if [ -z "$CU_FAILED_ACTIONS" ] || ! is_in_array "$CU_LAST_ACTION_ID" "$CU_FAILED_ACTIONS"; then
		[ "$CU_UPGRADE_VERSION_FROM" -ge "$CU_START_VERSION_FROM" ] || return 0
	fi

	"$@"
}

# Execute action only if it belongs to a current stage
cu_check_stage()
{
	local stage="$1"
	shift

	[ "$stage" = "$CU_STAGE" ] || return 0

	"$@"
}

# Check that all previous cu_check_timestamp actions contain timestamps less than a given one
cu_verify_latest_timestamp_lt()
{
	local timestamp="`echo \"$1\" | tr -dc '[:digit:]'`"
	[ "$CU_LATEST_TIMESTAMP" -lt "$timestamp" ] || simply_die "Upgrader actions for '$CU_STAGE' stage of '$CU_LAST_DB_UPGRADER_NAME' upgrader are not valid. Timestamp values MUST be less than $timestamp. Please fix upgrader definition!"
}

# --- Upgrader bookkeeping functions ---

# Start a block of upgrade actions that should be executed when upgrading from a given version
cu_start_upgrade_from_version()
{
	CU_UPGRADE_VERSION_FROM="$1"
}

# Remember failed upgrade action (to be able to rerun it afterwards)
cu_add_failed_action()
{
	local action_id="$1"
	[ -n "$action_id" ] && CU_FAILED_ACTIONS="$CU_FAILED_ACTIONS $action_id" && CU_HAS_NEW_FAILED_ACTIONS="yes"
}

cu_remove_failed_action()
{
	local action_id="$1"
	[ -n "$CU_FAILED_ACTIONS" -a -n "$action_id" ] && CU_FAILED_ACTIONS="` remove_from_array "$action_id" "$CU_FAILED_ACTIONS" `"
}

# Store configuration data using supplied callback. Duplicate to default location if necessary.
cu_do_store_config_data()
{
	local upgrader_name="$1"
	local store_config_data_func="$2"

	$store_config_data_func "$upgrader_name"
	# Duplicate into default storage, if custom one was used. This is mostly for humans.
	[ "$store_config_data_func" = "cu_txtdb_store_config_data" ] || cu_txtdb_store_config_data "$upgrader_name"
}

# Handler for cases when critical action fails and there is no rollback procedure defined
cu_critical_failure_handler()
{
	[ -n "$CU_LAST_DB_UPGRADER_NAME" -a -z "$CU_LAST_DB_CONTINUE_FROM" ] || {
		p_echo "Can't handle upgrader critical failure - upgrader state is broken. Probably a programming error."
		return
	}

	p_echo "Updating '$CU_LAST_DB_UPGRADER_NAME' configuration status after a critical failure during upgrade stage '$CU_LAST_STAGE' on '$CU_LAST_ACTION_ID' action"

	local cu_db_current_timestamp cu_db_continue_from cu_db_failed_actions_list cu_db_latest_timestamp
	# Update only continue_from and failed_actions_list fields.
	cu_db_current_timestamp="$CU_LAST_DB_CURRENT_TIMESTAMP"
	cu_db_continue_from="`cu_get_current_continue_from`"
	cu_db_failed_actions_list="$CU_FAILED_ACTIONS"
	cu_db_latest_timestamp="$CU_LAST_DB_LATEST_TIMESTAMP"

	cu_do_store_config_data "$CU_LAST_DB_UPGRADER_NAME" "$CU_LAST_STORE_CONFIG_DATA_FUNC"

	CU_LAST_DB_UPGRADER_NAME=
}

# Check that following upgrader run will actually have any actions executed
cu_check_upgrade_required()
{
	local upgrader_func="$1"
	local CU_DO_GET_ACTION_NAME="yes"
	local upgrade_actions="`$upgrader_func`"
	[ -n "$upgrade_actions" ]
}

# --- Upgrader set up functions ---

# Set up installed (product/package) version and installed configuration timestamp
cu_set_initial_versions()
{
	CU_START_VERSION_FROM="${1:-starting_component_version_not_specified}"
	CU_START_TIMESTAMP="${2:-0}"
}

# Reset upgrader global variables
cu_set_globals()
{
	local upgrader_name="$1"
	local stage="$2"
	local store_config_data_func="$3"

	CU_DO_GET_ACTION_NAME=
	CU_LATEST_TIMESTAMP=0
	CU_LAST_ACTION_ID=

	# Initial DB record values. Used by cu_critical_failure_handler()
	CU_LAST_DB_UPGRADER_NAME="$upgrader_name"
	CU_LAST_DB_CURRENT_TIMESTAMP="$cu_db_current_timestamp"
	CU_LAST_DB_CONTINUE_FROM="$cu_db_continue_from"
	CU_LAST_DB_FAILED_ACTIONS_LIST="$cu_db_failed_actions_list"
	CU_LAST_DB_LATEST_TIMESTAMP="$cu_db_latest_timestamp"
	CU_LAST_STAGE="$stage"
	CU_LAST_STORE_CONFIG_DATA_FUNC="$store_config_data_func"
}

# --- Default implementations to load/store configuration data ---

cu_txtdb_config_data_params()
{
	db_file="$PLESK_DB_DIR/components-configuration-state.db"
	db_delim='#'
}

# Path to default upgrader configuration db changed in Plesk 11.5.26. This function moves existing db.
cu_txtdb_try_upgrade_location()
{
	local old_db_file="$PRODUCT_ROOT_D/var/components-configuration-state.db"
	local db_file db_owner db_group db_perms db_delim db_key_field
	txtdb_set_params cu_txtdb_config_data_params

	if [ -s "$old_db_file" -a ! -e "$db_file" ]; then
		mv -f "$old_db_file" "$db_file"
	fi
}

cu_txtdb_ensure_config_data_exists()
{
	cu_txtdb_try_upgrade_location
	txtdb_exists cu_txtdb_config_data_params >/dev/null 2>&1 || txtdb_truncate cu_txtdb_config_data_params
}

cu_txtdb_load_config_data()
{
	local upgrader_name="$1"

	cu_txtdb_ensure_config_data_exists
	local record="`txtdb_select cu_txtdb_config_data_params "$upgrader_name"`"

	cu_db_current_timestamp="`  get_narg_fs "$record" '#' 2`"
	cu_db_continue_from="`      get_narg_fs "$record" '#' 3`"
	cu_db_failed_actions_list="`get_narg_fs "$record" '#' 4`"
	cu_db_latest_timestamp="`   get_narg_fs "$record" '#' 5`"
}

cu_txtdb_store_config_data()
{
	local upgrader_name="$1"
	local record="$upgrader_name#$cu_db_current_timestamp#$cu_db_continue_from#$cu_db_failed_actions_list#$cu_db_latest_timestamp"
	cu_txtdb_ensure_config_data_exists
	txtdb_replace cu_txtdb_config_data_params "$record"
}

# No-op config loader. For use with cu_run_upgrader --init for the first stage.
cu_dummy_load_config_data()
{
	:
}

# --- Main code for generic cumulative upgrader ---

cu_run_upgrader()
{
	local opt_upgrader_name="$1"
	local opt_upgrader_func="$2"
	shift 2

	local opt_prepare_func=	opt_rollback_func= opt_commit_func= opt_start_version= opt_stage= opt_do_repair= opt_do_update_version_in_db= opt_do_init=
	local opt_load_config_data_func=cu_txtdb_load_config_data opt_store_config_data_func=cu_txtdb_store_config_data

	local inten="perform upgrade for $opt_upgrader_name"

	while [ "$#" -gt 0 ]; do
		case "$1" in
			--prepare)
				opt_prepare_func="$2"
				[ "$#" -ge 2 ] && shift 2 || break
				;;
			--rollback)
				opt_rollback_func="$2"
				[ "$#" -ge 2 ] && shift 2 || break
				;;
			--commit)
				opt_commit_func="$2"
				[ "$#" -ge 2 ] && shift 2 || break
				;;
			--load-config-data)
				opt_load_config_data_func="$2"
				[ "$#" -ge 2 ] && shift 2 || break
				;;
			--store-config-data)
				opt_store_config_data_func="$2"
				[ "$#" -ge 2 ] && shift 2 || break
				;;
			--from-version)
				opt_start_version="$2"
				[ "$#" -ge 2 ] && shift 2 || break
				;;
			--stage)
				opt_stage="$2"
				[ "$#" -ge 2 ] && shift 2 || break
				;;
			--repair)
				opt_do_repair="yes"
				shift
				;;
			--update-version)
				opt_do_update_version_in_db="yes"
				shift
				;;
			--init)
				opt_do_init="yes"
				shift
				;;
			*)
				die "$inten: unknown key '$1'"
				;;
		esac
	done

	# Sanity checks
	[ -n "$opt_upgrader_name"          ] || die "$inten: empty component upgrader name argument"
	[ -n "$opt_upgrader_func"          ] && is_function "$opt_upgrader_func"          || die "$inten: invalid component upgrader function argument"
	[ -n "$opt_load_config_data_func"  ] && is_function "$opt_load_config_data_func"  || die "$inten: invalid value for --load-config-data argument"
	[ -n "$opt_store_config_data_func" ] && is_function "$opt_store_config_data_func" || die "$inten: invalid value for --store-config-data argument"
	[ -z "$opt_prepare_func"           ] || is_function "$opt_prepare_func"           || die "$inten: invalid value for --prepare argument"
	[ -z "$opt_rollback_func"          ] || is_function "$opt_rollback_func"          || die "$inten: invalid value for --rollback argument"
	[ -z "$opt_commit_func"            ] || is_function "$opt_commit_func"            || die "$inten: invalid value for --commit argument"
	[ -n "$opt_do_init" -a \( -n "$opt_do_repair" -o -n "$opt_prepare_func" -o -n "$opt_rollback_func" -o -n "$opt_commit_func" \) ] && die "$inten: excessive options prohibited for use with --init"

	# Upgrader setup
	local CU_STAGE="$opt_stage"
	local cu_db_current_timestamp cu_db_continue_from cu_db_failed_actions_list cu_db_latest_timestamp
	$opt_load_config_data_func "$opt_upgrader_name"
	cu_set_initial_versions "$opt_start_version" "$cu_db_current_timestamp"
	cu_set_globals "$opt_upgrader_name" "$opt_stage" "$opt_store_config_data_func"

	local CU_CONTINUE_FROM_ID= CU_FAILED_ACTIONS= CU_HAS_NEW_FAILED_ACTIONS=
	if [ -z "$opt_do_init" ]; then
		if [ -n "$cu_db_continue_from" ]; then
			if [ -z "$opt_do_repair" ]; then
				pp_echo "Unable to upgrade '$opt_upgrader_name' to the latest version, since its configuration is in broken state. Run bootstrapper repair to fix."
				return 2
			fi

			local cu_continue_from_stage="` cu_get_continue_stage "$cu_db_continue_from" `"
			CU_CONTINUE_FROM_ID="` cu_get_continue_id "$cu_db_continue_from" `"
			if [ "$cu_continue_from_stage" != "$CU_STAGE" ]; then
				p_echo "Skipping stage '$CU_STAGE' of upgrade for '$opt_upgrader_name' as previous upgrade attempt was not finished on another stage."
				return 3
			fi
		elif [ -n "$cu_db_failed_actions_list" ]; then
			if [ -z "$opt_do_repair" ]; then
				p_echo "Before start of upgrade for '$opt_upgrader_name' (stage '$CU_STAGE') following actions are registered as failed: $cu_db_failed_actions_list."
			else
				CU_FAILED_ACTIONS="` normalize_array "$cu_db_failed_actions_list" `"
			fi
		fi

		if ! cu_check_upgrade_required "$opt_upgrader_func" ; then
			p_echo "Upgrade or repair for '$opt_upgrader_name' (stage '$CU_STAGE') is not required"
			[ -n "$opt_prepare_func" ] && $opt_prepare_func "$opt_upgrader_name" "$CU_STAGE" noop-stage
			[ -n "$opt_commit_func" ] && $opt_commit_func "$opt_upgrader_name" "$CU_STAGE" noop-stage
			return 0
		fi

		# Preparation step
		[ -n "$opt_prepare_func" ] && $opt_prepare_func "$opt_upgrader_name" "$CU_STAGE"

		# Register rollback actions.
		# Note that rollback scope currently spans to the end of upgrade procedure (this function).
		if [ -n "$opt_rollback_func" ]; then
			transaction_add_rollback_action "$opt_rollback_func"
			# Rollback function contract: everything changed in this upgrader pass will be 
			# rolled back. Component version should not change. Therefore there is no need 
			# to update anything in DB.
		else
			transaction_add_rollback_action "cu_critical_failure_handler"
		fi

		# Run upgrade actions
		$opt_upgrader_func

		# Commit (post) step - if we are here upgrade has completed (but there may be failed actions)
		[ -n "$opt_commit_func" ] && $opt_commit_func "$opt_upgrader_name" "$CU_STAGE"
	else
		# This is just an initialization run to set proper upgrader configuration on component installation
		p_echo "Initializing '$opt_upgrader_name' upgrader configuration (stage '$CU_STAGE')"
		local CU_DO_GET_ACTION_NAME="yes"
		$opt_upgrader_func >/dev/null 2>&1
	fi

	# Update DB record if there are changes. Update current_timestamp only if explicitly allowed (e.g. this is the last stage).
	cu_db_continue_from=

	if [ -n "$opt_do_repair" -o -z "$CU_LAST_DB_FAILED_ACTIONS_LIST" ]; then
		cu_db_failed_actions_list="$CU_FAILED_ACTIONS"
	else
		# Append failed actions from this stage. Don't care for duplicates - they will be removed when a given action succeeds.
		cu_db_failed_actions_list="` normalize_array "$CU_LAST_DB_FAILED_ACTIONS_LIST" "$CU_FAILED_ACTIONS" `"
	fi

	if [ -z "$cu_db_latest_timestamp" -a "$CU_LATEST_TIMESTAMP" -gt 0 ] || [ "0$cu_db_latest_timestamp" -lt "$CU_LATEST_TIMESTAMP" ]; then
		cu_db_latest_timestamp="$CU_LATEST_TIMESTAMP"
	fi

	[ -n "$opt_do_update_version_in_db" -a "0$cu_db_latest_timestamp" -gt 0 ] && cu_db_current_timestamp="$cu_db_latest_timestamp"

	if [    "$cu_db_current_timestamp" != "$CU_LAST_DB_CURRENT_TIMESTAMP" \
		 -o "$cu_db_latest_timestamp" != "$CU_LAST_DB_LATEST_TIMESTAMP" \
		 -o "$cu_db_failed_actions_list" != "$CU_LAST_DB_FAILED_ACTIONS_LIST" \
		 -o "$cu_db_continue_from" != "$CU_LAST_DB_CONTINUE_FROM" ]; then
		cu_do_store_config_data "$opt_upgrader_name" "$opt_store_config_data_func"
	fi

	# If this is just an initialization, we don't need to disarm rollback, etc.
	[ -z "$opt_do_init" ] || return 0

	# Upgrade is complete - disarm rollback actions
	if [ -n "$opt_rollback_func" ]; then
		transaction_remove_rollback_action "$opt_rollback_func"
	else
		transaction_remove_rollback_action "cu_critical_failure_handler"
	fi

	if [ -n "$cu_db_failed_actions_list" ]; then
		p_echo "After end of upgrade for '$opt_upgrader_name' (stage '$CU_STAGE') following actions are registered as failed: $cu_db_failed_actions_list."
	fi

	[ ! -n "$CU_HAS_NEW_FAILED_ACTIONS" ]
}

cu_upgrader_conf_init()
{
	local opt_upgrader_name="$1"
	local opt_upgrader_func="$2"
	shift 2

	local opt_stages= opt_load_config_data_func= opt_store_config_data_func=

	local inten="initialize upgrader configuration for $opt_upgrader_name"

	while [ "$#" -gt 0 ]; do
		case "$1" in
			--stages)
				opt_stages="$2"
				[ "$#" -ge 2 ] && shift 2 || break
				;;
			--load-config-data)
				opt_load_config_data_func="$2"
				[ "$#" -ge 2 ] && shift 2 || break
				;;
			--store-config-data)
				opt_store_config_data_func="$2"
				[ "$#" -ge 2 ] && shift 2 || break
				;;
			*)
				die "$inten: unknown key '$1'"
				;;
		esac
	done

	# Sanity checks
	[ -n "$opt_upgrader_name"          ] || die "$inten: empty component upgrader name argument"
	[ -n "$opt_stages"                 ] || die "$inten: empty value for --stages argument, should be space separated list of stages"

	# Preparations
	local num_stages="`array_length $opt_stages`"
	local cur_stage_idx=1

	# Run all stages through cu_run_upgrader. First stage resets configuration, last one upgrades current timestamp.
	for stage in $opt_stages; do
		local store_option="${opt_store_config_data_func:+--store-config-data $opt_store_config_data_func}"

		local load_option="${opt_load_config_data_func:+--load-config-data $opt_load_config_data_func}"
		if [ "$cur_stage_idx" -eq 1 ]; then
			load_option="--load-config-data cu_dummy_load_config_data"
		fi

		local update_option=
		if [ "$cur_stage_idx" -eq "$num_stages" ]; then
			update_option="--update-version"
		fi

		cu_run_upgrader "$opt_upgrader_name" "$opt_upgrader_func" --init --from-version 0 --stage "$stage" $load_option $store_option $update_option

		cur_stage_idx=$(( cur_stage_idx + 1 ))
	done
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
get_userID()
{
# try to get UID
	common_var=`id -u "$1" 2>/dev/null` 

# if id returns 0 the all is ok
	test "$?" -eq "0" -a -n "$common_var"
}

get_groupID()
{
# try to get GID, id -g doesn't show groups without users
	common_var=`getent group $1 2>/dev/null | awk -F':' '{print $3}'`

# We have non-empty value if success
	test -n "$common_var"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
# vim:ft=sh

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=""

	EXTERNAL_PACKAGES=""
	EXTERNAL_PACKAGES_DIR=""

	BUILDER_UID="10007"

	PERL5LIB=/usr/local/psa/lib/perl5/site_perl/5.8.8:/usr/local/psa/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi
	export PERL5LIB

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

	product_version="12.5.30"
	product_db_version="012005030"
	conceived_os_vendor=RedHat
	conceived_os_version="el5"
	osrels="rhel5"

	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}"

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

 #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=/var/www/vhosts
HTTPD_CONF_D=/etc/httpd/conf
HTTPD_INCLUDE_D=/etc/httpd/conf.d
HTTPD_BIN=/usr/sbin/httpd
HTTPD_LOG_D=/var/log/httpd
HTTPD_SERVICE=httpd
QMAIL_ROOT_D=/var/qmail
PLESK_MAILNAMES_D=/var/qmail/mailnames
RBLSMTPD=/usr/sbin/rblsmtpd
NAMED_RUN_ROOT_D=/var/named/run-root
NAMED_OPTIONS_CONF=
NAMED_ZONES_CONF=
WEB_STAT=/usr/bin/webalizer
MYSQL_VAR_D=/var/lib/mysql
MYSQL_BIN_D=/usr/bin
MYSQL_SOCKET=/var/lib/mysql/mysql.sock
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.6
CATALINA_HOME=/usr/share/tomcat5
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=/var/www/cgi-bin/awstats
AWSTATS_TOOLS_D=/usr/share/awstats
AWSTATS_DOC_D=/var/www/html/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=false
APS_DB_DRIVER_LIBRARY=/usr/lib/libmysqlserver.so.2
IPv6_DISABLED=false
SA_MAX_MAIL_SIZE=256000

}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

#-*- vim:ft=sh

register_service() {

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

	{


		# chkconfig for RedHat based
		/sbin/chkconfig --add "$1"
		/sbin/chkconfig "$1" on

	}

	suc
}

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

	setenforce "$SELINUX_ENFORCE"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
# vim:ft=sh:

#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"
	K_TEST="/bin/kill -0"

	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/libexec/postfix"
	PRODUCT_BOOTSTRAPPER_DIR="/usr/local/psa/bootstrapper/pp12.5.30-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"
	PRODUCT_LOGS_D="/var/log/plesk"

	set_common_params_linux 

	rp_patch_runtime

	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"

	useradd_options="-r"
	if [ -f /etc/SuSE-release ]; then
		linux_distr="suse"
	elif [ -f /etc/debian_version ]; then
		linux_distr="debian"
		get_domainname="dnsdomainname"
	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]'`

	return 0
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
# -*- vim:syntax=sh

set_syslog_params()
{
	syslog_conf_ng="/etc/syslog-ng/syslog-ng.conf"

	syslog_conf=""
	for config in rsyslog.conf rsyslog.early.conf syslog.conf; do
		[ -f "/etc/$config" ] && syslog_conf="$syslog_conf /etc/$config"
	done

	syslog_service=""
	syslog_binary=""

	# Make sure the sequence of services is correlate with binaries
	local syslog_services="syslog sysklogd rsyslog syslog-ng"
	local syslog_binaries="syslogd syslogd rsyslogd syslog-ng"

	for service in $syslog_services; do
		[ -x "$PRODUCT_RC_D/${service}" ] && 			syslog_service="$service" && break
	done

	for binary in $syslog_binaries; do
		for bin_path in /sbin /usr/sbin; do
			[ -x "$bin_path/${binary}" ] && 				syslog_binary="$bin_path/${binary}" && break
		done
		[ -n "$syslog_binary" ] && break
	done

}

get_product_versions()
{
	local prod_root_d="/usr/local/psa"
	
	product_name="psa"
	product_this_version="12.5.30"
	product_this_version_tag="testing"
	if [ -z "$product_prev_version" ]; then
		if [ -r "$prod_root_d/version.upg" ]; then
			product_prev_version=`cat "$prod_root_d/version.upg" | awk '{ print $1 }'`
		elif [ -r "$prod_root_d/version" ]; then
			product_prev_version=`cat "$prod_root_d/version" | awk '{ print $1 }'`
		else
			product_prev_version="$product_this_version"
		fi
	fi
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
upgrade_modules_permissions_1013()
{
	chown psaadm:0 ${PRODUCT_ROOT_D}/var/modules
}

set_mysql_remote_auth()
{
	# Set auth parameters using the specified values, as opposed to retrieving them from filesystem (set_mysql_auth)
	if [ $# -ne 3 ]; then simply_die "set_mysql_remote_auth requires three arguments: host_name user_name password, but $# arguments are specified."; fi

	mysql_host="--host=$1"
	mysql_user="--user=$2"
	mysql_passwd="$3"
}

mysql_quote_string()
{
	echo "$1" | perl -pe 's|\\|\\\\|g'
}

reset_admin_passwd()
{
	true mysql_quote_string

	[ -n "$admin_passwd" ] || die "admin_passwd is not set yet"
	# I bet someone somewhere replaces 'localhost' with '%' (for weird automation purposes), so be nice
	echo "SET PASSWORD FOR 'admin'@'localhost' = PASSWORD('`mysql_quote_string $admin_passwd`')" | mysql_direct mysql || 	echo "SET PASSWORD FOR 'admin'@'%'         = PASSWORD('`mysql_quote_string $admin_passwd`')" | mysql_direct mysql
}

configure_mysql_disable_old_passwords()
{
	local my_cnf="$1"
	local awk_script='/^[[:space:]]*old_passwords/ { print "# Forced OLD_PASSWORD format is turned OFF by Plesk\n#" $0; next } { print }'

	if awk "$awk_script" "$my_cnf" > "$my_cnf.tmp" || die "edit $my_cnf"; then
		if diff -q "$my_cnf" "$my_cnf.tmp" 1>/dev/null ; then
			rm -f "$my_cnf.tmp"
		else
			mv "$my_cnf.tmp" "$my_cnf" || die "disable old_passwords in $my_cnf"
			need_mysql_restart=yes
		fi
	fi
}

find_my_cnf()
{
	local non_fatal="$1"
	local 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" -o -n "$non_fatal" ] || die "find MySQL server configuration file. " 		"If you use thirdparty MySQL server build, make sure you don't use implicit default configuration " 		"and have MySQL configuration file in one of the following locations: $cnf_files"
	[ -f "$my_cnf" ]
}

run_configure_mysql_funcs()
{
	local need_mysql_restart=
	local my_cnf=
	find_my_cnf

	for func in "$@"; do
		eval "$func $my_cnf"
	done

	if [ -n "$need_mysql_restart" ]; then
		pleskrc mysql restart
	fi
}

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

	# Override this variable as needed
	mysql_db_name="$PRODNAME"
	mysql_passwd_file="$product_etc/.${PRODNAME}.shadow"

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

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

mysql_anydb()
{
	(
		export MYSQL_PWD="$mysql_passwd"
		$mysql_client $mysql_host $mysql_user $mysql_args "$@" 2>>"$product_log"
		local status=$?

		if [ $status -gt 0 ]; then
			$mysql_client $mysql_host $mysql_user $mysql_args -D$mysql_db_name $mysql_args_raw -e "SHOW ENGINE innodb status" >>"$product_log" 2>&1
		fi
		unset MYSQL_PWD
		return $status
	)
}

# Invoke mysql without any wrapper or something else
mysql_direct()
{
	# a bit dirty but it works properly for passwords with spaces, quotes and double quotes:
	if [ -n "$mysql_passwd" ]; then
		(
			export MYSQL_PWD="$mysql_passwd"
			$mysql_client $mysql_host $mysql_defaults $mysql_user $mysql_args "$@" 2>>"$product_log"
			rc=$?
			unset MYSQL_PWD
			return $rc
		)
	else
		$mysql_client $mysql_host $mysql_defaults $mysql_user $mysql_args "$@" 2>>"$product_log"
	fi
}

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

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

product_db_installer()
{
	# DB schema installation and initialization not bound to this machine
	mysql < "$product_db_sql" || die "Cannot initialize $PRODNAME database from $product_db_sql"
	set_db_version
}

db_init_default_locale()
{
	local default_locale default_locale_name default_locale_country

	p_echo 'Setting the default locale'
	set_default_locale_params

	db_do "replace into misc (param, val) values('def_locale', '$default_locale')"
	db_do "replace into locales(id) values('$default_locale')"
	db_do "alter table clients alter locale set default '$default_locale'"

	p_echo "The default locale is set to $default_locale ($default_locale_name, $default_locale_country)"
}

set_db_version()
{
	# Install or update db version
	echo_try "set psa database version to $product_db_version"
	db_do "replace into misc (param,val) values('version', '$product_db_version')"
	suc
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
# -- start of mysqlnd old passwords upgrade --

# The reason why this code is not in the db/upgrade_db_1100.sh file is the following:
# It turned out that during the upgrade from 8.6 to 11.0 sw-engine may be installed to
# satisfy bootstrapper's dependency; new sw-engine with the mysqlnd extenstion refused to work 
# with the passwords in the old format. So passwords upgrade should be done prior to the database upgrade.
# This is vital as there are PHP-scripts (working with the database) invoked during the upgrade.

upgrade_mysqlnd_old_passwd()
{
	# It's probably better to extract all child functions into .in file
	run_configure_mysql_funcs configure_mysql_disable_old_passwords

	db_test "SELECT length(PASSWORD('test'))" '$1 == 41' || die "disable old_passwords=1 in my.cnf"
	check_mysql_users_with_old_passwd_format || return 0

	inten="upgrade MySQL password format"
	reset_admin_passwd || die "$inten for admin"
	reset_sitebuilder_passwd || die "$inten for Sitebuilder user"
	reset_billing_passwd || die "$inten for Billing user"
	reset_apsc_passwd || die "$inten for APS controller user"
	reset_horde_passwd || die "$inten for Horde webmail user"
	reset_atmail_passwd || die "$inten for AtMail webmail user"
	reset_mysql_dbusers_passwd || die "$inten for Panel DB users"
	reset_phpmyadmin_passwd || die "$inten for phpMyAdmin control user"
	reset_siteeditor_passwd || die "$inten for SiteEditor user"

	check_mysql_users_with_old_passwd_format && warn_mysql_old_passwd_users && return 1 || :
}

check_mysql_users_with_old_passwd_format()
{
	local mysql_db_name=mysql
	local user="$1"
	local query="SELECT User FROM user WHERE length(Password) != 41"
	if [ -n "$user" ]; then
		query="${query} AND User = '$user'"
	fi
	db_test "${query} LIMIT 1" '1'
}

reset_user_password()
{
	true mysql_quote_string

	local user="$1"
	local passwd="$2"
	local hosts="${3:-localhost}"

	local inten="reset database user password for '${user}@${host}'"
	echo_try "${inten}"

	if [ "$hosts" = "127.0.0.1" -o "$hosts" = "::1" ] ; then
		hosts="${hosts} localhost"
	fi
	hosts="${hosts} %"

	for host in $hosts; do
		if echo "SET PASSWORD FOR '$user'@'$host' = PASSWORD('`mysql_quote_string $passwd`')" | mysql_direct mysql; then
			suc
			return 0
		fi
	done

	warn "$inten - database user does not exist."
	return 1
}

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="$3"

	#INFO: we should not die here
	echo "" | mysql_direct 
}

reset_sitebuilder_passwd()
{
	local no_force="$1"
	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

	if [ -n "$no_force" ]; then
		check_db_accessible "$sb_dbname" "$sb_username" "$sb_password" && return 0 || :
	fi

	if reset_user_password "$sb_username" "$sb_password" "$sb_host"; then
		check_db_accessible "$sb_dbname" "$sb_username" "$sb_password"
	else
		# https://jira.sw.ru/browse/PPP-4676
		return 0
	fi
}

reset_siteeditor_passwd()
{
	local no_force="$1"

	local se_conf="/usr/local/siteeditor/config"
	[ -f "${se_conf}" ] || return 0

	local se_host=`    get_ini_conf_var "${se_conf}" "database" "host"`
	local se_username=`get_ini_conf_var "${se_conf}" "database" "username"`
	local se_password=`get_ini_conf_var "${se_conf}" "database" "password"`
	local se_dbname=`  get_ini_conf_var "${se_conf}" "database" "dbname"`

	is_local_mysql_instance "$se_host" || return 0

	if [ -n "$no_force" ]; then
		! check_db_accessible "$se_dbname" "$se_username" "$se_password" || return 0
	fi

	reset_user_password "${se_username}" "${se_password}" "${se_host}" && \
	check_db_accessible "$se_dbname" "$se_username" "$se_password"
}

reset_billing_passwd()
{
	local no_force="$1"

	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

	if [ -n "$no_force" ]; then
		if $billing_db_bin --is-configured 2>/dev/null | grep -q yes || $billing_db_bin --is_configured 2>/dev/null | grep -q yes; then
			! check_db_accessible "$bil_dbname" "$bil_user" "$bil_passwd" || return 0
		fi
	fi

	reset_user_password "$bil_user" "$bil_passwd" "$bil_host" && 
	{
		(
			export BILLING_DB_PASSWORD="$bil_passwd"
			$billing_db_bin --set --with-password >/dev/null 2>&1
		) || \
		$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 
	}
}

reset_apsc_passwd()
{
	check_apsc_installed || return 0
	read_apsc_connection_params_db
	check_mysql_users_with_old_passwd_format "$apsc_db_user" || return 0

	is_local_mysql_instance "$apsc_db_host" || return 0

	if reset_user_password "$apsc_db_user" "$apsc_db_passwd" "$apsc_db_host"; then
		check_db_accessible "$apsc_db_name" "$apsc_db_user" "$apsc_db_passwd" || return 1
	fi
}

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()
{
	local no_force="$1"

	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

	if [ -n "$no_force" ]; then
		! check_db_accessible "$hor_dbname" "$hor_user" "$hor_passwd" || return 0
	fi

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

reset_atmail_passwd()
{
	local no_force="$1"

	local atmail_shadow="/etc/psa-webmail/atmail/.atmail.shadow"
	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

	if [ -n "$no_force" ]; then
		! check_db_accessible "$at_dbname" "$at_user" "$at_passwd" || return 0
	fi

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

reset_mysql_dbusers_passwd()
{
	local mysql_db_name=mysql
	db_do --inten "Convert MySQL DB users passwords to new format" \
		"UPDATE mysql.user m 
				INNER JOIN psa.db_users u ON (m.User = u.login) 
				INNER JOIN psa.accounts a ON (u.account_id = a.id) 
				INNER JOIN psa.data_bases d ON (u.db_id = d.id) 
		SET m.Password = PASSWORD(a.password) 
		WHERE d.type = 'mysql' AND a.type = 'plain'; 
		FLUSH PRIVILEGES;"
}

reset_phpmyadmin_passwd()
{
	local no_force="$1"

	local pmahost="localhost"
	local controlpass pmadb
	set_phpmyadmin_params

	local pma_config="$PHPMYADMIN_CONFIG.save"
	[ -f "$pma_config" ] || pma_config="$PHPMYADMIN_CONFIG"
	pma__set_values_from_config "$pma_config" 'controluser' 'controlpass' 'pmadb'

	[ -n "$controlpass" -a -n "$controluser" -a -n "$pmadb" ] || return 0

	if [ -n "$no_force" ]; then
		check_db_accessible "$pmadb" "$controluser" "$controlpass" || return 0
	fi

	reset_user_password "$controluser" "$controlpass" "$pmahost" && \
	check_db_accessible "$pmadb" "$controluser" "$controlpass"
}

warn_mysql_old_passwd_users()
{
	local mysql_db_name=mysql
	local query="SELECT concat(User, '@', Host) FROM user WHERE length(Password) != 41"

	if [ -n "$controluser" ]; then
		# There is an error in old phpMyAdmin upgrade routine: DB was recreated every time
		query="$query AND (User not like 'pma\_%' OR User = '$controluser')"
	fi

	query="$query AND (User != 'debian-sys-maint')"

	db_select "$query"
	local problem_users="$db_select_output"

	[ -n "$problem_users" ] || return 0
	report_problem "Passwords for some MySQL users were not upgraded." \
		"All MySQL DB users that may be used by Panel MUST have passwords in new 41-character format in order for Panel to function properly." \
		"Currently following users have passwords in old format: `echo -n $problem_users | sed -e 's/ /, /g'`." \
		"Please ensure that MySQL server is not forced to use old password hashing algorithm and upgrade password format manually for users from the list above. Consult with MySQL server manual on detailed steps." \
		"You may skip certain users if you are sure they weren't created and aren't used by Panel."
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
#-*- vim:syntax=sh

set_named_params()
{
	# set up default values
	bind_UID=53
	bind_GID=53
	bind_user="named";
	bind_group="named";

	# get UID of named user, if exists
	if get_userID $bind_user; then
	    bind_UID=$common_var;
	fi

	# get GID of named group, if exists
	if get_groupID $bind_group; then
	    bind_GID=$common_var;
	fi

	# path to directory of internal named
	NAMED_ROOT_D="${PRODUCT_ROOT_D:?'PRODUCT_ROOT_D is undefined'}/named"

	# path to directory of named pid file
	bind_run="${NAMED_RUN_ROOT_D:?'NAMED_RUN_ROOT_D is undefined'}/var/run/named"

	named_service="named"
	named_log="/dev/null"
	
	# path to named config file
	named_conf="/etc/named.conf"
	rndc_conf="/etc/rndc.conf"
	rndc_namedb_conf="/etc/namedb/rndc.conf"
	rndc_bind_conf="/etc/bind/rndc.conf"

	#140025. Restrict CPU cores for Bind
	bind_number_of_workers=2
}

sysconfig_named_redhat()
{
	[ -d /etc/sysconfig ] || mkdir /etc/sysconfig

	local named_sysconf_file="/etc/sysconfig/named"
	local config_rebuild=0

	if [ "$bind_user" = "root" ]; then
		NAMED_START_AS_USER=""
	else
		NAMED_START_AS_USER="-u $bind_user"
	fi

	if [ -f "$named_sysconf_file" ]; then
		cat ${named_sysconf_file} | sed -e 's|#.*$||g' | grep -E "ROOTDIR=\"$NAMED_RUN_ROOT_D\"" > /dev/null 2>&1
		[ $? -eq 0 ] || config_rebuild=1
		
		cat ${named_sysconf_file} | sed -e 's|#.*$||g' | grep -E "OPTIONS=.*$NAMED_START_AS_USER" > /dev/null 2>&1
		[ $? -eq 0 ] || config_rebuild=1

		cat ${named_sysconf_file} | sed -e 's|#.*$||g' | grep -E "OPTIONS=.*\-c /etc/named.conf" > /dev/null 2>&1
		[ $? -eq 0 ] || config_rebuild=1

		cat ${named_sysconf_file} | sed -e 's|#.*$||g' | grep -E "OPTIONS=.*[[:space:]]-n[[:space:]]" > /dev/null 2>&1
		[ $? -eq 0 ] || config_rebuild=1
	else
		config_rebuild=1
	fi

	if [ 0${config_rebuild} -gt 0 ] ; then
		[ ! -f "$named_sysconf_file" ] || mk_backup "$named_sysconf_file" cp f

		sed -e "s|##NAMED_RUN_ROOT_D##|$NAMED_RUN_ROOT_D|g" 			-e "s|##NAMED_START_AS_USER##|$NAMED_START_AS_USER|g" 			-e "s|##NUMBER_OF_CPUS##|-n $bind_number_of_workers|g" 			< "$PRODUCT_ETC_D/sysconfig.named.in" 			> "$named_sysconf_file"
	fi
}

sysconfig_named()
{
	sysconfig_named_redhat

	return 0
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
# vim:ft=sh

upgrade_named_restrict_number_of_workers_11_5_29()
{
	set_named_params
	sysconfig_named
	! pleskrc named status || pleskrc named restart
}

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

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
}

install_postfix_smtpd_sasl_config()
{
	local smtpd_sasl_conf smtpd_sasl_conf_bak saslauthd_path saslauthd_path_relative

	saslauthd_path_relative=/private/plesk_saslauthd

	saslauthd_path=/var/spool/postfix${saslauthd_path_relative}
	
	smtpd_sasl_conf='/usr/lib/sasl2/smtpd.conf'

	if [ -f "$smtpd_sasl_conf" ]; then
	   smtpd_sasl_conf_bak="${smtpd_sasl_conf}.saved_by_plesk.`date +%s`"
	   rm -f "$smtpd_sasl_conf_bak" ||:
	   if ! ln "$smtpd_sasl_conf" "$smtpd_sasl_conf_bak" ; then
	      simply_die "unable to preserve $smtpd_sasl_conf to $smtpd_sasl_conf_bak"
	   fi
	fi
	mkdir -p "$(dirname $smtpd_sasl_conf)"
	cat >"$smtpd_sasl_conf" <<EOF
pwcheck_method: auxprop saslauthd
auxprop_plugin: plesk
saslauthd_path: $saslauthd_path
mech_list: DIGEST-MD5 CRAM-MD5 PLAIN LOGIN
sql_engine: intentionally disabled
log_level: 4
EOF
}

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

	if db_test "SELECT value FROM ServiceNodeConfiguration WHERE name='relay' AND value='open' AND serviceNodeId=1 AND section='mailServer'" 1 ; then
		run="$run --relayclient"
	fi

	if db_test "SELECT * FROM ServiceNodeConfiguration WHERE name='disable_smtp_auth' and value=0 AND serviceNodeId=1 AND section='mailServer'" 1 ; then
		run="$run --smtpauth"
	fi

	if db_test "SELECT * FROM ServiceNodeConfiguration WHERE name='disable_pop_auth' and value=0 AND serviceNodeId=1 AND section='mailServer'" 1 ; then
		run="$run --popauth"
	fi

	db_select "SELECT value FROM ServiceNodeConfiguration WHERE name='poplock_time' AND serviceNodeId=1 AND section='mailServer'"
	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
}

upgrade_sendmail_wrapper_12_0_5()
{
	# This upgrade action removes sendmail-wrapper (then called psa-sendmail) installed by 12.0.5
	# Installation (if needed) will be done later in Postfix/QMail driver bootstrapper post-install

	local old_sendmail_wrapper="$PLESK_LIBEXEC_DIR/psa-sendmail"

	local old_sendmail_vendor="$sendmail.postfix"

	[ -L "$sendmail" ] || return 0
	local sendmail_points_to="`readlink -f \"$sendmail\"`"
	[ "$sendmail_points_to" = "$old_sendmail_wrapper" -o "$sendmail_points_to" = "/var/qmail/bin/sendmail" ] || return 0

	{
		if type update-alternatives >/dev/null 2>&1; then
			/usr/sbin/update-alternatives --remove mta "$old_sendmail_wrapper"
		fi
	} >> $product_log 2>&1
}

upgrade_sendmail_wrapper_12_0_9()
{
	# fix protected column
	local handler_db_path="/var/lib/plesk/mail/handlers/handlers.db"
	local query="ALTER TABLE handlers ADD COLUMN protected BOOLEAN NOT NULL default 0"
	if [ -w "${handler_db_path}" ]; then
		local sqlite3_binary=`lookup_command sqlite3`
		if [ -n "${sqlite3_binary}" ]; then
			${sqlite3_binary} "${handler_db_path}" "$query" || true
		fi
	fi

	# add check-quota into before-sendmail queue
	"$PLESK_LIBEXEC_DIR/mail_mailbox_restore" --handlers-only

	set_postfix_params
	set_qmail_params
	if pleskrc postfix exists >/dev/null 2>&1; then
		pleskrc postfix reload
	elif pleskrc qmail exists >/dev/null 2>&1; then
		pleskrc qmail reload
	fi
}

remove_unused_postfix_milters_12_0_18()
{
	local commtouch_marker_file='/etc/init.d/ctmilter_initd'
	local commtouch_milter_pattern='unix:\/var\/spool\/postfix\/ctmilter\/ctmilter.sock'

	# edit postfix configuration to remove non-smtpd milter
	[ -s "/etc/postfix/main.cf" ] || return 0

	set_postfix_params
	local filtered_value="`read_postconf_value 'non_smtpd_milters' | sed -e '/^\(inet:127.0.0.1:12768\|inet:localhost:12768\)$/d'`"
	write_postconf_value 'non_smtpd_milters' "$filtered_value" || return 1

	if [ ! -e "$commtouch_marker_file" ]; then
		for milters in non_smtpd_milters smtpd_milters; do
			filtered_value="`read_postconf_value "$milters" | sed -e "/^${commtouch_milter_pattern}$/d"`"
			write_postconf_value "$milters" "$filtered_value" || return 1
		done
	fi

	pleskrc postfix reload
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

set_mail_params()
{
	HANDLERS_USER="mhandlers-user"
	MAIL_USERGROUP="popuser"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

mailname_to_lowercase_11_1_15()
{
	local res=0

	echo_try "rename mailboxes to lower case format"

	$PRODUCT_ROOT_D/admin/sbin/mailmng-service --stop-service
	if ! $PRODUCT_ROOT_D/bin/repair --convert-mailboxes-to-lowercase -no-mchk; then
		warn "rename mailboxes to lower case format. Please run $PRODUCT_ROOT_D/bin/repair --convert-mailboxes-to-lowercase manually."
		res=1
	else
		suc
	fi
	$PRODUCT_ROOT_D/admin/sbin/mailmng-service --start-service

	deferred_mail_restore_all

	return $res
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
## vim:filetype=sh

upgrade_drweb_storage()
{
	# should we move files from old quarantine into new?
	[ -e "/etc/drweb/drweb_handler.conf" ] || return 0
	sed -i 		-e 's|^\s*Spool\s*=.*|Spool = /var/spool/drweb/spool|g' 		-e 's|^\s*SpoolFilesMode\s*=.*|SpoolFilesMode = 0664|g' 		-e 's|^\s*Quarantine\s*=.*|Quarantine = /var/spool/drweb/infected|g' 		-e 's|^\s*QuarantineFilesMode\s*=.*|QuarantineFilesMode = 0660|g' 		/etc/drweb/drweb_handler.conf || warn "update drweb handler config"

	# as far as we change dir location and config, drweb daemon reload is required
	if [ -x "/usr/local/psa/admin/sbin/drwebmng" ] ; then
		/usr/local/psa/admin/sbin/drwebmng --reload || service_restart_warning drweb
	fi
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
## vim:filetype=sh

upgrade_greylisting_permissions()
{
	local gl_db_dir="/var/lib/plesk/mail/greylist"

	[ -d "$gl_db_dir" ] || return 0
	chown -R root:popuser ${gl_db_dir} || pp_echo 'Failed to set correct ownership for grey listing databases'
	chmod 770 ${gl_db_dir} || pp_echo 'Failed to set correct grey listing databases directory permissions'
	chmod 660 ${gl_db_dir}/* || pp_echo 'Failed to set correct grey listing databases permissions'

	#may be call restore if there is(are) failures?
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

# vim:ft=sh

upgrade_rsyslog_maillog_configuration_12_1_6()
{
	true
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

upgrade_outgoing_mail_rate_limiting_handlers_12_0_7()
{
	local mhc="$UTILS_DIR/mail_handlers_control"
	[ -x "$mhc" ] || return 0

	# Since we dropped "in" limits, we should remove all old mail rate limiting handlers
	{
		$mhc --remove --queue before-queue    --type global --name limit-in
		$mhc --remove --queue before-sendmail --type global --name limit-in
		$mhc --remove --queue before-remote   --type global --name limit-out
	} >> $product_log 2>&1

	# as well as install new ones and recreate backend DB
	deferred_mail_outgoing_restore_full
}

upgrade_drop_sender_ip_mail_handler_12_0_10()
{
	local mhc="$UTILS_DIR/mail_handlers_control"
	[ -x "$mhc" ] || return 0

	$mhc --remove --queue before-queue --type global --name sender-ip >> $product_log 2>&1
	:
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
## vim:filetype=sh

upgrade_quota_handler_address_11_1_13()
{
	local common_mess="update check-quota handler recipients address column in handlers DB"
	echo_try ${common_mess}

	local handler_db_path=/var/lib/plesk/mail/handlers/handlers.db

	if [ ! -w "${handler_db_path}" ]; then
		# This is more probably an upgrade from earlier versions than a broken machine
		p_echo "Unable to ${common_mess} - missing DB '${handler_db_path}'. Will call mail_restore later."
		deferred_mail_restore_all
		return 0
	fi

	local sqlite3_binary=`lookup_command sqlite3`
	if [ -z "${sqlite3_binary}" ]; then
		pp_echo "Unable to ${common_mess} - missing sqlite3 binary"
		return 1
	fi

	local query='UPDATE `handlers` SET `address`="all-recipients" WHERE `name`="check-quota"'
	${sqlite3_binary} "${handler_db_path}" "$query"
	if [ $? -ne 0 ]; then
		pp_echo "Unable to ${common_mess} - execution of DB query '$query' failed"
		return 1
	fi

	suc
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
#-*- vim:syntax=sh

maillog_create_compat_symlink()
{
	mkdir -p "$PRODUCT_ROOT_D/var/log"
	[ -e "$PRODUCT_ROOT_D/var/log/maillog" -a ! -L "$PRODUCT_ROOT_D/var/log/maillog" ] || ln -sf "$mail_log" "$PRODUCT_ROOT_D/var/log/maillog"
}

select_maillog()
{
	local mail_log inten
	mail_log="/var/log/maillog"
	inten="set maillog file to $mail_log"

	set_syslog_params

	local logrot_syslog_conf="/etc/logrotate.d/syslog"
	unset_logrotate_maillog "$logrot_syslog_conf" "$mail_log"


	touch $mail_log
	chmod 0640 $mail_log

	local rsyslog_mail_log="${mail_log}"

	for config in $syslog_conf; do
		if [ -f "$config" ]; then
			if [ "${config}" = "/etc/rsyslog.conf" ]; then
				set_maillog $config "${rsyslog_mail_log}" "${inten}" >> $product_log 2>&1
			else
				set_maillog $config "${mail_log}" "${inten}" >> $product_log 2>&1
			fi
		fi
	done

	[ -f $syslog_conf_ng ] && set_maillog_ng "$mail_log" "$inten"  >> "$product_log" 2>&1

	pleskrc syslog reload
	maillog_create_compat_symlink
}

_set_maillog_ng_change()
{
    local conf_file mail_log inten bak_ext

    conf_file=$1
    mail_log=$2
    inten=$3
    bak_ext=$4

    echo_try "$inten"

    local mloc_cmd mloc_arg
    local ws
    ws=$(echo -ne " \t")

    ## Set log to $mail_log
    mloc_cmd="-e"
    mloc_arg='s|^\(['"$ws"']*destination['"$ws"']\+mail['"$ws"']*{[^"]*"\)[^"]*\(.*\)$|\1'"$mail_log"'\2|'

    ## By default SuSE-9.3 and SuSE-10 syslog-ng settings
    ## doesn't allow any 'mail' log messages to be put into
    ## /var/log/messages. We wish to allow mail.warn to pass
    ## through the filter, so we need to tune the conditions...
    ## So we change
    ## filter f_messages   { not facility(news, mail) and not filter(f_iptables); };
    ## to
    ## filter f_messages   { not (facility(news) or filter(f_iptables)) or filter(f_mailwarn); };
    ##
    ## I'm not sure if the whole filter is well optimized though
    ##
    ## Here I don't try to perform a sofisticated replace. The proper way
    ## would require a deep analisys of the current configuration and
    ## I don't see any sense to do it at this time, probably once in a future...

    local mfmt_cmd mfmt_arg
    mfmt_cmd=-e
    mfmt_arg='s|^\(['"$ws"']*filter['"$ws"']\+f_messages['"$ws"']*{\).*|\1 not (facility(news) or filter(f_iptables)) or filter(f_mailwarn); };|'

    ## now execute the entire command *IN-PLACE*
    ## all modern sed's (well at least on supported systems
    ## do support this option.

    ## One HAVE NOT TO quite mail_log_expr and mf_expr below!
    sed $mloc_cmd "$mloc_arg" $mfmt_cmd "$mfmt_arg" "-i$bak_ext" "$conf_file" || die "$intent"
}

set_maillog_ng() {
    local mail_log intent
    mail_log=$1
    intent=$2

	if [ -f "${syslog_conf_ng}.in" ]; then
	    _set_maillog_ng_change "${syslog_conf_ng}.in" "$mail_log" "$intent" ".bak" && 		/sbin/SuSEconfig --module syslog-ng
	else
# Modest SuSE 1.20 doens't rule syslog through SuSE-config, bug 118238
		_set_maillog_ng_change "${syslog_conf_ng}" "$mail_log" "$intent" ".bak"
	fi

}

set_maillog()
{
	local syslog_conf mail_log inten mail_log_str log_str num
	syslog_conf=$1
	mail_log=$2
	inten=$3

	mail_log_str="-$mail_log"

	echo_try "$inten"

	log_str="^mail.*[[:space:]]*$mail_log*"
	grep "$log_str" $syslog_conf > /dev/null
	if [ "$?" -ne 0 ]; then
		grep '^mail\.\*' $syslog_conf > /dev/null
		if [ "$?" -eq 0 ]; then
			## if line "mail.*       ..." is exist then
			## replace this with new line
			grep -q '^mail\.\*.*;' $syslog_conf
			if [ $? -eq 0 ]; then
				sed -e "s|^mail\.\*.*\(;.*\)$|mail.*					$mail_log_str\1|" 					< $syslog_conf > $syslog_conf.tmp
			else
				sed -e "s|^mail\.\*.*$|mail.*						$mail_log_str|" 					< $syslog_conf > $syslog_conf.tmp
			fi
			mv -f $syslog_conf.tmp $syslog_conf
		else
			## if line "mail.*       ..." is NOT exist then
			## search "*.       ..." line
			num=`awk '{if ((my==0) && (index($1, "*.") == 1)) {my=1; print FNR;}}' < $syslog_conf`
			if [ "0$num" -gt "0" ]; then
				## if line "*.       ..." is exist then
				## disable all lines beginning with "mail."
				## and insert new line "mail.*      ..." before this
				sed -e 's/^\(mail\.\)/#\1/' 					-e ''${num}'i					mail.*						'$mail_log_str'' 					< $syslog_conf > $syslog_conf.tmp && 				mv -f $syslog_conf.tmp $syslog_conf || die "$inten"
			else
				## if line "*.       ..." is NOT exist then
				## disable all lines beginning with "mail."
				## and insert new line "mail.*      ..." at the end of file
				sed -e 's/^\(mail\.\)/#\1/'	< $syslog_conf > $syslog_conf.tmp && 				echo "mail.*						$mail_log_str" >> $syslog_conf.tmp && 				mv -f $syslog_conf.tmp $syslog_conf || die "$inten"
			fi
		fi
	fi

	sed -e 's|\(^.*\)maili\none\;\(.*\)|\1\2|g' < $syslog_conf > $syslog_conf.tmp &&           mv -f $syslog_conf.tmp $syslog_conf || die "$inten"
	echo 'mail.none			-/var/log/messages' >> /var/log/messages 

	suc
}

unset_logrotate_maillog()
{
	local logrotate_conf="$1"
	local mail_log="$2"
	_unset_logtorate_maillog "$mail_log" < "$logrotate_conf" > "${logrotate_conf}.new" 		&& mv "${logrotate_conf}.new" "${logrotate_conf}"
}

_unset_logtorate_maillog()
{
	local exclude_path="$1"
	perl -ple 's{^([[:space:]]*|.*[[:space:]])'"$exclude_path"'([[:space:]].*|[[:space:]]*)$}{$1$2}g' | egrep -v '^\s*$'
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
#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=""
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

upgrade_qmail_reduce_suids_11_1_12()
{
	if ! /usr/local/psa/admin/sbin/mailmng-server --features | egrep -q "SMTP_Server_package.*qmail" 2>/dev/null; then
		p_echo "Skip qmail specific upgrade actions"
		return
	fi

	upgrade_qmail_permissions
	drop_unused_mailman_wrapper
}

upgrade_qmail_permissions()
{
	local inten="setup correct owner and permissions on poplock and mail authentication DB"
	echo_try "$inten"

	local res=0

	local perm_err="set correct permissions on"
	local ownership_err="set correct ownership for"
	
	if [ -d "/var/lib/plesk/mail/poplock" ]; then
		if ! chown -R root:nofiles /var/lib/plesk/mail/poplock; then
			warn "${ownership_err} poplock DB"
			res=1
		fi

		if ! chmod 770 /var/lib/plesk/mail/poplock; then
			warn "${perm_err} poplock DB directory"
			res=1
		fi

		if ! chmod 660 /var/lib/plesk/mail/poplock/poplock.db; then
			warn "${perm_err} poplock DB file"
			res=1
		fi
	fi

	if [ -d "/var/lib/plesk/mail/auth" ]; then
		if ! chown -R root:nofiles /var/lib/plesk/mail/auth; then
			warn "${ownership_err} auth DB"
			res=1
		fi

		if ! chmod 750 /var/lib/plesk/mail/auth; then
			warn "${perm_err} auth DB directory"
			res=1
		fi

		if ! chmod 0640 /var/lib/plesk/mail/auth/passwd.db; then
			warn "${perm_err} auth DB file"
			res=1
		fi

		if ! chmod 440 /var/lib/plesk/mail/auth/passwd_db_key; then
			res=1
			warn "${perm_err} auth passwd file "
		fi
	fi

	if [ $res = 0 ]; then
		suc
	else
		warn "$inten"
	fi
}

drop_unused_mailman_wrapper()
{
	:
}

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_remove_rollback_action()
{
	[ -z "$TRANSACTION_STARTED" ] && die "Transaction is not started!"
	# Preserves order of remaining records
	TRANSACTION_ROLLBACK_FUNCS=`remove_from_array "$1" "$TRANSACTION_ROLLBACK_FUNCS"`
}

core_init_upgrader_conf()
{
	echo_try "initialize Plesk DB and files upgrader configuration"
	cu_upgrader_conf_init "core" core_upgrader \
		--load-config-data core_cu_load_config_data --store-config-data core_cu_store_config_data \
		--stages "prep post"
	suc
}

core_read_misc_attr()
{
	db_select "SELECT val FROM misc WHERE param = '$1'"
	echo "$db_select_output"
}

core_cu_load_config_data()
{
	local upgrader_name="$1"

	[ "$upgrader_name" = "core" ] || return 0
	db_test_table "misc" || return 0

	cu_db_current_timestamp="`  core_read_misc_attr 'upgrader_config_current_timestamp'`"
	cu_db_continue_from="`      core_read_misc_attr 'upgrader_config_continue_from'`"
	cu_db_failed_actions_list="`core_read_misc_attr 'upgrader_config_failed_actions_list'`"
	cu_db_latest_timestamp="`   core_read_misc_attr 'upgrader_config_latest_timestamp'`"
}

core_cu_store_config_data()
{
	local upgrader_name="$1"

	[ "$upgrader_name" = "core" ] || return 0
	db_test_table "misc" || die "save core upgrader state to 'misc' table"

	db_do "REPLACE INTO misc (param, val) VALUES \
		('upgrader_config_current_timestamp', '$cu_db_current_timestamp'), \
		('upgrader_config_continue_from', '$cu_db_continue_from'), \
		('upgrader_config_failed_actions_list', '$cu_db_failed_actions_list'), \
		('upgrader_config_latest_timestamp', '$cu_db_latest_timestamp')"
}

core_upgrader()
{
	local db="cu_check_stage prep"
	local files="cu_check_stage post"
	local ver="cu_check_version"
	local ts="cu_check_timestamp"
	local do="cu_do"

	# Some upgrade actions might rely on MySQL passwords being upgraded. Note that rollback won't work for Billing.
	$db    $ts '2011/11/15 17:13:14' $do upgrade_mysqlnd_old_passwd

	cu_start_upgrade_from_version 1013
	$db    $ver $do add_db_changes 10130
	$db    $ver $do db_smb_upgrade_1013
	$files $ver $do upgrade_courier_imap_auth_1013
	$files $ver $do db_upgrade_subdomains_zones_1013
	$db    $ver $do db_upgrade_configurations_1013
	$files $ver $do generate_encryption_key
	$files $ver $do upgrade_postfix_sasl_1013
	$files $ver $do db_upgrade_dns_1013
	$files $ver $do upgrade_modules_permissions_1013
	$files $ver $do db_upgrade_aps_settings_1013 # This function is executed on post stage only due to absence of table in early versions of plesk
	$db    $ver $do db_upgrade_secret_key_1013
	$files $ver $do db_upgrade_secret_key_fix_1013
	$files $ver $do db_upgrade_admin_simple_plan_permissions_1013
	$db    $ver $do db_upgrade_sessions_1013
#	$files $ver $do license_upgrade_1013

	cu_start_upgrade_from_version 1100
	$db    $ver $do add_db_changes 11000
	$db    $ver $do db_smb_upgrade_1100
	$db    $ver $do db_upgrade_heterogenous_1100
	$db    $ver $do db_upgrade_apsmail_1100
	$db    $ver $do db_upgrade_service_nodes_1100
	$db    $ver $do db_upgrade_mail_server_settings_1100
	$db    $ver $do db_upgrade_webusers_miva_1100
	$files $ver $do pbm_create_certificate # We should generate certificate on upgrade since backup was merged into core
	$files $ver $do upgrade_adminlogs_permissions_1100

	cu_start_upgrade_from_version 1101
	$db    $ver $do db_upgrade_longtasks_1101
	$db    $ver $do db_upgrade_db_users_1101

	cu_start_upgrade_from_version 011001011
	$db    $ver $do db_upgrade_add_indexes_for_performance_11_1_11
	$db    $ver $do db_upgrade_change_sys_users_home_to_utf8
	$files $ver $do deferred_mail_restore_all

	cu_start_upgrade_from_version 011001012
	$db    $ver $do add_db_changes 11.1.12
	$db    $ver $do db_upgrade_service_node_properties_11_1_12
	$db    $ver $do db_upgrade_custom_buttons_11_1_12
	$files $ver $do upgrade_greylisting_permissions
	$files $ver $do upgrade_drweb_storage
	$files $ver $do upgrade_qmail_reduce_suids_11_1_12

	cu_start_upgrade_from_version 011001013
	$db    $ver $do db_upgrade_service_node_configuration_11_1_13
	$files $ver $do upgrade_quota_handler_address_11_1_13

	cu_start_upgrade_from_version 011001014
	$db    $ver $do db_upgrade_dns_templates_11_1_14

	cu_start_upgrade_from_version 011001015
	$files $ts '2012/12/06 13:03:47' $do db_upgrade_subscription_properties_11_1_15
	$files $ts '2013/07/09 17:45:00' $do mailname_to_lowercase_11_1_15
	$files $ts '2012/12/12 14:44:47' $do register_sw_engine_service
	$files $ts '2012/12/14 09:26:01' $do upgrade_pci_compliance_11_1_15

	cu_start_upgrade_from_version 011001016
	$db    $ts '2012/12/19 18:57:31' $do add_db_changes 11.1.16

	cu_start_upgrade_from_version 011001017
	$db    $ts '2013/01/15 17:41:18' $do db_upgrade_forwarding_11_1_17
	$db    $ts '2013/01/21 16:34:00' $do db_upgrade_seo_safe_domain_aliases_11_1_17
	$files $ts '2013/01/21 17:11:13' $do upgrade_postfix_allow_authenticated_dnsbled_clients_11_1_17
	$db    $ts '2013/01/25 09:37:00' $do db_upgrade_db_user_unique_key_11_1_17

	cu_start_upgrade_from_version 011001018
	$db    $ts '2013/01/29 15:00:00' $do add_db_changes 11.1.18
	$db    $ts '2013/02/04 19:10:05' $do db_upgrade_php_handler_id_11_1_18
	$files $ts '2013/05/24 18:13:37' $do upgrade_skel_remove_statistics_11_1_18

	cu_start_upgrade_from_version 011005019
	$db    $ts '2013/02/22 09:43:00' $do add_db_changes 11.5.19
	$db    $ver $do						 db_upgrade_smb_11_5_19
	$db    $ts '2013/02/14 17:51:00' $do db_upgrade_drop_php_version_11_5_19
	$db    $ts '2013/02/25 14:43:00' $do db_upgrade_webmails_11_5_19

	cu_start_upgrade_from_version 011005021
	$db    $ts '2013/03/07 12:57:01' $do db_upgrade_enable_dns_connector_11_5_21
	$db    $ts '2013/03/19 15:19:00' $do add_db_changes 11.5.21
	$db    $ts '2013/03/25 14:24:01' $do db_upgrade_set_force_update_applications_notification_11_5_21
	$db    $ts '2013/03/28 09:40:01' $do db_add_public_ip_11_5_21

	cu_start_upgrade_from_version 011005022
	$files $ts '2013/04/01 17:38:44' $do db_upgrade_drop_ip_address_id_11_5_22
	$files $ts '2013/06/05 18:07:46' $do upgrade_vhost_directories_11_1_18
	$db    $ts '2013/04/08 18:18:44' $do db_upgrade_set_property_unpaid_website_status_for_plans_11_5_22
	$db    $ts '2013/04/08 18:18:44' $do db_upgrade_set_property_unpaid_website_status_for_subscriptions_11_5_22

	cu_start_upgrade_from_version 107
	# Moved from 107 and 1012 because of the BL (#80977) and backend (#136372) dependencies. Should be after upgrade_vhost_directories_11_1_18.
	$files $ver $do upgrade_proftpd_107

	cu_start_upgrade_from_version 011005023
	$files $ts '2013/04/18 15:25:35' $do fix_file_sharing_permissions_from_10_0_0
	$files $ts '2013/04/18 19:44:02' $do upgrade_courier_to_4_12_pop_before_smtp_11_5_23

	cu_start_upgrade_from_version 011005024
	$db    $ts '2013/04/26 14:00:44' $do db_upgrade_correcting_property_unpaid_website_status_for_plans_11_5_24
	$db    $ts '2013/04/26 14:00:44' $do db_upgrade_correcting_property_unpaid_website_status_for_subscriptions_11_5_24
	$db    $ts '2013/04/26 16:58:00' $do db_upgrade_maintenance_mode_id_11_5_24
	$db    $ts '2013/04/30 13:45:00' $do db_upgrade_service_node_configuration_11_5_24
	$files $ts '2013/04/30 12:37:00' $do db_upgrade_secret_keys_11_5_24
	$files $ts '2013/05/14 14:11:38' $do upgrade_domains_awstats_conf_11_5_24

	cu_start_upgrade_from_version 011005029
	$db    $ts '2013/06/20 10:30:00' $do add_db_changes 11.5.29
	$db    $ver $do						 db_smb_upgrade_11_5_29
	$db    $ts '2013/06/25 13:39:00' $do db_upgrade_correcting_aps_tokens_11_5_29
	$files $ts '2013/07/22 14:44:38' $do upgrade_named_restrict_number_of_workers_11_5_29

	cu_start_upgrade_from_version 011005030
	$db    $ts '2013/07/22 15:01:00' $do db_upgrade_db_user_unique_key_11_1_17

### Below month numbers are increased by 10 due to published screw-up in 11.5.30 upgrader (see r327259)
	cu_start_upgrade_from_version 011005099
	$db    $ts '2013/18/20 13:33:24' $do add_db_changes 11.5.99
	$db    $ts '2013/18/20 13:34:26' $do db_upgrade_external_id_11_5_99
	$db    $ts '2013/18/20 13:35:28' $do db_upgrade_move_configuration_11_5_99
	$files $ts '2013/18/27 11:44:17' $do upgrade_postfix_remove_deprecated_headers_11_5_30
	$db    $ts '2013/19/02 11:36:45' $do db_upgrade_iis_app_pools_cpu_limit_11_5_99
	$db    $ts '2013/19/09 13:00:00' $do db_upgrade_sdk_add_services_11_5_99

	cu_start_upgrade_from_version 011006000
	$files $ts '2013/19/10 10:13:12' $do upgrade_panel_log_11_6_0
	$files $ts '2013/19/10 18:00:01' $do upgrade_httpsd_access_log_11_6_0
	$files $ts '2013/19/13 15:14:03' $do upgrade_transfer_rotated_logs_11_6_0

	cu_start_upgrade_from_version 011006001
	$files $ts '2013/19/17 12:35:41' $do upgrade_transfer_pmm_logs_11_6_1
	$files $ts '2013/19/18 09:30:17' $do upgrade_transfer_httpsd_access_log_processed_11_6_1
	$files $ts '2013/19/18 11:41:47' $do upgrade_transfer_proftpd_logs_11_6_1
	$db    $ts '2013/19/18 18:30:00' $do add_db_changes 11.6.1
	$files $ts '2013/19/23 14:27:14' $do deferred_mail_spam_restore_full

	cu_start_upgrade_from_version 011006002
	$files $ts '2013/21/05 10:30:04' $do upgrade_transfer_maillog_11_6_2
	$db    $ts '2013/20/01 13:00:00' $do db_upgrade_web_server_configurations_11_6_2
	$db    $ts '2013/20/01 15:50:00' $do add_db_changes 11.6.2
	$db    $ts '2013/20/07 18:30:00' $do db_upgrade_mail_description_11_6_2
	$db    $ts '2013/20/09 15:30:00' $do db_upgrade_clients_description_11_6_2

	cu_start_upgrade_from_version 011006003
	$db    $ts '2013/20/14 12:40:00' $do add_db_changes 11.6.3
	$db    $ts '2013/20/18 16:50:00' $do db_upgrade_domains_description_11_6_3
	$files $ts '2013/20/22 12:30:00' $do deferred_httpd_reconfigure_all

	cu_start_upgrade_from_version 011006004
	$files $ts '2013/21/05 12:05:30' $do reconfigure_chained_ssl_certificates_11_6_4

	cu_start_upgrade_from_version 012000005
	$files $ts '2013/21/28 16:37:15' $do deferred_mail_outgoing_restore_full
	$files $ts '2013/21/29 18:09:00' $do upgrade_cgi_bin_mode_defaults_12_0_5

	cu_start_upgrade_from_version 012000006
	$db    $ts '2013/21/29 12:30:00' $do db_upgrade_service_plan_domain_12_0_6
	$db    $ts '2013/22/03 12:30:00' $do db_upgrade_iis_app_pools_12_0_6
	$db    $ts '2013/22/06 18:00:00' $do db_upgrade_subscription_outgoing_messages_overlimit_percent_to_default_12_0_6
	$db    $ts '2013/22/06 18:00:00' $do db_upgrade_plan_outgoing_messages_overlimit_percent_to_default_12_0_6
	$db    $ts '2013/22/10 16:00:00' $do add_db_changes 12.0.6
	$files $ts '2013/22/13 16:22:59' $do upgrade_sendmail_wrapper_12_0_5

	cu_start_upgrade_from_version 012000007
	$db    $ts '2013/22/20 16:00:00' $do add_db_changes 12.0.7
	$files $ts '2013/22/20 16:27:50' $do upgrade_outgoing_mail_rate_limiting_handlers_12_0_7
	$db    $ts '2013/22/25 11:00:00' $do db_upgrade_sessions_12_0_7
### End of +10 to month number

	cu_start_upgrade_from_version 012000008
	$db	$ts    '2014/01/15 15:17:00' $do add_db_changes 12.0.8
	$files $ts '2014/01/17 15:00:00' $do db_update_notifications
	$db	$ts    '2014/01/23 17:30:00' $do db_upgrade_plan_properties_default_values_12_0_8
	$db	$ts    '2014/01/23 17:30:00' $do db_upgrade_subscription_properties_default_values_12_0_8

	cu_start_upgrade_from_version 012000009
	$db    $ts '2014/02/13 10:31:51' $do add_db_changes 12.0.9
	$db    $ts '2014/01/28 17:00:00' $do db_upgrade_plan_properties_default_values_12_0_9
	$db    $ts '2014/01/28 17:00:00' $do db_upgrade_subscription_properties_default_values_12_0_9
	$db    $ts '2014/01/28 17:00:00' $do db_upgrade_mbox_outgoing_messages_to_default_12_0_9
	$db    $ts '2014/01/28 17:00:00' $do db_upgrade_domain_outgoing_messages_to_default_12_0_9
	$files $ts '2014/02/04 12:57:05' $do upgrade_sendmail_wrapper_12_0_9
	$db    $ts '2014/02/04 17:00:00' $do db_upgrade_wordpress_instances_12_0_9
	$db    $ts '2014/02/12 17:00:00' $do db_upgrade_sessions_12_0_9

	cu_start_upgrade_from_version 012000010
	$db    $ts '2014/02/27 17:40:00' $do add_db_changes 12.0.10
	$files $ts '2014/02/25 17:48:22' $do upgrade_drop_sender_ip_mail_handler_12_0_10
	$db    $ts '2014/03/05 14:00:00' $do db_upgrade_enable_sendmail_default_values_12_0_10

	cu_start_upgrade_from_version 012000012
	$db    $ts '2014/03/18 16:30:00' $do db_upgrade_default_php_handler_12_0_12
	$files $ts '2014/03/27 12:58:00' $do upgrade_postfix_12_0_12

	cu_start_upgrade_from_version 012000013
	$db    $ts '2014/04/03 14:40:20' $do add_db_changes 12.0.13

	cu_start_upgrade_from_version 012000015
	$db    $ts '2014/04/15 15:48:00' $do add_db_changes 12.0.15

	cu_start_upgrade_from_version 012000017
	$db    $ts '2014/05/11 18:00:00' $do add_db_changes 12.0.17
	$db    $ts '2014/05/11 15:00:00' $do db_upgrade_wordpress_instances_12_0_17

    cu_start_upgrade_from_version 012000018
    $files $ts '2014/07/22 17:30:00' $do remove_unused_postfix_milters_12_0_18

	cu_start_upgrade_from_version 012001004
	$db    $ts '2014/08/08 13:00:00' $do db_upgrade_iis_app_pools_12_1_4
	$db    $ts '2014/08/18 17:28:30' $do db_upgrade_features_new_12_1_4
	$db    $ts '2014/08/26 11:10:00' $do db_upgrade_unified_db_12_1_4

	cu_start_upgrade_from_version 012001005
	$db    $ts '2014/09/01 15:00:00' $do db_upgrade_unified_db_12_1_5
	$files $ts '2014/09/03 19:10:00' $do db_upgrade_subscriptions_12_1_5 # This function is executed on post stage to fix column attributes for upgrade from 11.0.9 (there is post there)
	$files $ts '2014/09/05 14:00:00' $do db_upgrade_generate_service_instance_references_12_1_5 # This function is executed on post stage because rows are inserted on post stage on upgrades from 10.x
	$db    $ts '2014/09/11 17:00:00' $do db_drop_pmm_tables_12_1_5

	cu_start_upgrade_from_version 012001006
	$files $ts '2014/09/15 11:23:12' $do upgrade_rsyslog_maillog_configuration_12_1_6
	$db    $ts '2014/09/18 15:43:21' $do db_upgrade_smb_unified_12_1_6
	$files $ts '2014/09/23 11:33:13' $do db_remove_tables_12_1_6

	cu_start_upgrade_from_version 012001007
	$db    $ts '2014/10/02 12:57:35' $do db_drop_storefront_12_1_7
	$db    $ts '2014/10/03 17:40:00' $do add_db_changes 12.1.7

	cu_start_upgrade_from_version 012001008
	$files $ts '2014/10/14 12:19:57' $do refresh_trusted_ips_12_1_8
	$db    $ts '2014/10/16 17:55:00' $do add_db_changes 12.1.8
	$db    $ts '2014/10/20 10:28:15' $do db_upgrade_backups_scheduled_12_1_8

	cu_start_upgrade_from_version 012001013
	$files $ts '2015/01/12 14:57:11' $do regenerate_postfix_poplock_cron_task_12_1_13

	cu_start_upgrade_from_version 012001018
	$db    $ts '2015/03/26 13:25:22' $do php_upgrade_system_handlers_pre_12_1_18
	$files $ts '2015/03/26 14:01:54' $do php_upgrade_system_handlers_post_12_1_18

	cu_start_upgrade_from_version 012001020
	$files $ts '2015/04/15 14:03:10' $do register_local_postgres_12_1_20

	cu_start_upgrade_from_version 012001022
	$files $ts '2015/05/19 16:53:10' $do configure_ssl_ciphers_protocols

	cu_start_upgrade_from_version 012001024
	$files $ts '2015/06/10 12:53:10' $do upgrade_transfer_rc_actions_log

	# DO NOT MODIFY ANYTHING BELOW THIS LINE! (without approval of review from the entire Linux team)
	call_optional_function dev_core_upgrader
	cu_verify_latest_timestamp_lt '2015/08/14 12:00:00'
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

upgrade_vhost_directories_11_1_18()
{
	echo_try "upgrade vhost directories for domains"
	$PRODUCT_ROOT_D/bin/repair --update-vhosts-structure -no-reconfigure && suc || warn "fail\nCannot upgrade vhost directories for domains. Please run $PRODUCT_ROOT_D/bin/repair --update-vhosts-structure manually."
	deferred_httpd_reconfigure_all
}

upgrade_skel_remove_statistics_11_1_18()
{
	echo_try "drop unused 'statistics' directory from vhost skeletons"
	local unmodified_skel_stat_md5sum="3f5517860e8adfa4b05c9ea6268b38eb"
	local skel_stat_md5sums="`find -L $HTTPD_VHOSTS_D/.skel/*/statistics -type f 2>/dev/null | xargs --no-run-if-empty md5sum | cut -d ' ' -f 1 | sort | uniq`"
	if [ -z "$skel_stat_md5sums" -o "$skel_stat_md5sums" = "$unmodified_skel_stat_md5sum" ]; then
		rm -rf $HTTPD_VHOSTS_D/.skel/*/statistics >>"$product_log" 2>&1
	else
		pnnl_echo " 'statistics' directory seems customized, so it was preserved. Please remove it later manually. "
	fi
	suc
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
# vim:ft=sh

read_postconf_value()
{
	local param="$1"
	/usr/sbin/postconf -h "$param" 2>>"$product_log" | sed -e 's/\(\s*,\s*\|\s\+\)/\n/g' | egrep -v '^\s*$'
}

write_postconf_value()
{
	local param="$1"
	local value="$2"
	local conf_value="`echo "$value" | awk 'BEGIN { ORS=""; PORS="" } { print PORS; print; PORS=", " }'`"
	/usr/sbin/postconf -e "$param=$conf_value" >>"$product_log" 2>&1
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

set_postfix_params()
{
	postfix_service="postfix"
	pc_remote_service="pc-remote"
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
upgrade_postfix_sasl_1013()
{
	local smtpd_sasl_conf='/usr/lib/sasl2/smtpd.conf'
	[ -f "$smtpd_sasl_conf" ] || return 0
	install_postfix_smtpd_sasl_config
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
# vim:ft=sh

upgrade_postfix_allow_authenticated_dnsbled_clients_11_1_17()
{
	[ -s "/etc/postfix/main.cf" ] || return 0

	set_postfix_params

	local filtered_value="`read_postconf_value 'smtpd_client_restrictions' | sed -e '/^permit_mynetworks$/d' -e '/^permit_sasl_authenticated$/d'`"
	local extended_value="\
permit_mynetworks
permit_sasl_authenticated
$filtered_value"

	write_postconf_value 'smtpd_client_restrictions' "$extended_value" || return 1
	pleskrc postfix reload
}
### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
# vim:ft=sh


upgrade_postfix_remove_deprecated_headers_11_5_30()
{
	local filtered_value
	local inten
	local res

	[ -s "/etc/postfix/main.cf" ] || return 0

	set_postfix_params


	inten="drop header inclusion 'X-No-Auth: unauthenticated sender' from postfix"
	echo_try $inten
	filtered_value="`read_postconf_value 'smtpd_sender_restrictions' | sed -e '/^check_client_access\s\+pcre:.*non_auth.re/d'`"
	write_postconf_value 'smtpd_sender_restrictions' "$filtered_value" && suc || warn $inten

	inten="drop header inclusion 'X-No-Relay: not in my network' from postfix"
	echo_try $inten
	filtered_value="`read_postconf_value 'smtpd_recipient_restrictions' | sed -e '/^check_client_access\s\+pcre:.*no_relay.re/d'`"
	write_postconf_value 'smtpd_recipient_restrictions' "$filtered_value" && suc || warn $inten

	pleskrc postfix reload
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
# vim:ft=sh

upgrade_postfix_12_0_12()
{
	# Remove old plesk transports
	local master_cf_path=/etc/postfix/master.cf
	[ -s "$master_cf_path" ] || return 0

	cat $master_cf_path | perl -ne '
		@line = split /\s+/, $_, 8;
		next if ($line[1] == "unix" && ($line[0] =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}-/ || $line[0] =~ /^-[0-9a-fA-F-]+/));
        print $_;
    ' | perl -p -00e0 > $master_cf_path.tmp && mv -f $master_cf_path.tmp $master_cf_path

	# Call for mail_transport_restore

	/usr/lib/plesk-9.0/remote_mail_restore/mail_transport_restore
}

regenerate_postfix_poplock_cron_task_12_1_13()
{
	if /usr/local/psa/admin/sbin/mailmng-server --features | egrep -q "SMTP_Server_package.*postfix" 2>/dev/null; then
		remove_from_crontab "/usr/lib/plesk-9.0/postfix-poplockdb-clean"
		set_postfix_auth
	fi
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
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_confdir/imp"
	
	turba_datadir="$horde_datadir/turba"
	turba_sysconfd="$horde_confdir/turba"

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

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

	mnemo_datadir="$horde_datadir/mnemo"
	mnemo_sysconfd="$horde_confdir/mnemo"
	
	passwd_datadir="$horde_datadir/passwd"
	passwd_sysconfd="$horde_confdir/passwd"

	horde_user="horde_sysuser"
	horde_group="horde_sysgroup"

	horde_php_ini="/etc/psa-webmail/horde/horde/php.ini"
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

reconfigure_chained_ssl_certificates_11_6_4()
{
	local inten="reinstall chained SSL certificates"
	echo_try "${inten}"

	if ! $PRODUCT_ROOT_D/bin/repair --reconfigure-ssl-certificates >>$product_log 2>&1; then
		warn "${inten}"
		return 1
	else
		suc
	fi
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.

fix_file_sharing_permissions_from_10_0_0()
{
	set_apache_params

	local file_sharing_passwd_file="${HTTPD_VHOSTS_D}/fs-passwd/dav.passwd"

	[ -f "${file_sharing_passwd_file}" ] || return 0

	chown psaadm:${apache_group} "${file_sharing_passwd_file}" 
	chmod 640 "${file_sharing_passwd_file}"
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
upgrade_adminlogs_permissions_1100()
{
    chown psaadm:0 ${PRODUCT_ROOT_D}/admin/logs
    chmod 750 ${PRODUCT_ROOT_D}/admin/logs
}

transfer_log_with_compat_symlink()
{
	local old_path="$1"
	local new_path="$2"
	local merge="$3"
	local skip_link="$4"

	if [ -f "$old_path" -a ! -L "$old_path" ]; then
		if [ ! -f "$new_path" -o ! -s "$new_path" ] ; then
# simply move file into new place
			mv -f "$old_path" "$new_path" || { warn "move '$old_path' to '$new_path'"; return 1; }
		elif [ "$merge" = 'merge' ]; then
			local new_path_tmp=`mktemp "${new_path}.XXXX"`
			mv -f "$old_path" "$new_path_tmp" || { warn "move '$old_path' to temporary '$new_path_tmp'"; return 1; }
			cat "$new_path" >> "$new_path_tmp" || { warn "cat '$new_path' to temporary '$new_path_tmp'"; return 1; }
			mv -f "$new_path_tmp" "$new_path" || { warn "move temporary '$new_path_tmp' to '$new_path'"; return 1; }
		else
# preserve old log with suffix in target directory
			mv -f "$old_path" "$new_path.$product_suff"  || { warn "move '$old_path' to '$new_path.$product_suff'"; return 1; }
		fi
	elif [ "${skip_link}" = "skip_link_if_absent" ]; then
		return 0
	fi

	[ ! "${skip_link}" = "skip_link_always" ] || return 0

# (re-)create compatibility symlink
	if [ ! -e "$old_path" -o -L "$old_path" ]; then
		ln -sf "$new_path" "$old_path" || { warn "create symlink '$old_path' to '$new_path'"; return 1; }
	fi
}

upgrade_panel_log_11_6_0()
{
	local old_panel_log="${PRODUCT_ROOT_D}/admin/logs/panel.log"
	local new_panel_log="${PRODUCT_LOGS_D}/panel.log"

	transfer_log_with_compat_symlink "$old_panel_log" "$new_panel_log"
}

upgrade_httpsd_access_log_11_6_0()
{
	local old_path="${PRODUCT_ROOT_D}/admin/logs/httpsd_access_log"
	local new_path="${PRODUCT_LOGS_D}/httpsd_access_log"

	transfer_log_with_compat_symlink "$old_path" "$new_path"
}

upgrade_transfer_rotated_logs_11_6_0()
{
	for log in health-alarm.log panel.log sitebuilder.log; do
		if ls ${PRODUCT_ROOT_D}/admin/logs/${log}.*.gz > /dev/null 2>&1; then
			mv -f ${PRODUCT_ROOT_D}/admin/logs/${log}.*.gz "${PRODUCT_LOGS_D}"
		fi
	done
}

upgrade_transfer_httpsd_access_log_processed_11_6_1()
{
	if ls ${PRODUCT_ROOT_D}/admin/logs/httpsd_access_log.processed* > /dev/null 2>&1; then
		mv -f ${PRODUCT_ROOT_D}/admin/logs/httpsd_access_log.processed* "${PRODUCT_LOGS_D}"
	fi
}

upgrade_transfer_maillog_11_6_2()
{
	transfer_log_with_compat_symlink "${PRODUCT_ROOT_D}/var/log/maillog" "/var/log/maillog" 'merge'
	select_maillog

# transfer processed and rotated logs
	if ls ${PRODUCT_ROOT_D}/var/log/maillog.processed* > /dev/null 2>&1; then
		mv -f ${PRODUCT_ROOT_D}/var/log/maillog.processed* "/var/log"
	fi
}

upgrade_transfer_rc_actions_log()
{
	local log="${PRODUCT_ROOT_D}/tmp/rc_actions.log"
	if [ -s "$log" ]; then
		mv -f "$log" "${PRODUCT_LOGS_D}/"  > /dev/null 2>&1;
	fi
}

deferred_httpd_reconfigure_all()
{
	touch "/var/lock/plesk_deferred_httpd_reconfigure_all"
}

deferred_mail_restore_all()
{
	touch "/var/lock/plesk_deferred_mail_restore_all"
}

deferred_mail_spam_restore_full()
{
	touch "/var/lock/plesk_deferred_mail_spam_restore_full"
}

deferred_mail_outgoing_restore_full()
{
	touch "/var/lock/plesk_deferred_mail_outgoing_restore_full"
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
upgrade_pci_compliance_11_1_15()
{
	[ -s "$PRODUCT_ROOT_D/conf/cipher.lst" ] || return 0
	[ ! -e "/etc/sw-cp-server/conf.d/pci-compliance.conf" ] || return 0

	{
		echo -n "ssl_ciphers "
		cat $PRODUCT_ROOT_D/conf/cipher.lst | tr -d '\n'
		echo ";"
		echo "ssl_prefer_server_ciphers on;"
	} > /etc/sw-cp-server/conf.d/pci-compliance.conf
	/etc/init.d/sw-cp-server reload || :
}
register_local_postgres_12_1_20()
{
	db_select "SELECT COUNT(*) FROM DatabaseServers WHERE type='postgresql' AND host='localhost' AND server_version != '';"
	if [ 0$db_select_output -gt 0 ]; then
		register_service postgresql
	fi
}

### Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
# vim:ft=sh

prog="`basename $0`"

db_fill_ip_addresses()
{
	local list="$WHN_IP_LIST"
	[ -n "$list" ] || {
		pp_echo "Warning: WHN_IP_LIST is empty, IP_Addresses and ip_pool tables will not be initialized."
		return 0
	}

	for entry in $list; do
		local addr="`get_narg_fs "$entry" '|' 1`"
		local mask="`get_narg_fs "$entry" '|' 2`"
		local ifnm="`get_narg_fs "$entry" '|' 3`"
		local main="`get_narg_fs "$entry" '|' 4`"
		[ "$main" = "1" ] && main="true" || main="false"

		db_do "INSERT INTO \`IP_Addresses\` (serviceNodeId, ip_address, mask, iface, main) 
		              VALUES (1, '$addr', '$mask', '$ifnm', '$main');
		       INSERT INTO \`ip_pool\` (ip_address_id, type) 
		              VALUES (last_insert_id(), 'exclusive');"
	done
}

db_fill_hostname()
{
	local hostname="$WHN_HOSTNAME"
	[ -n "$hostname" ] || {
		pp_echo "Warning: WHN_HOSTNAME is empty, misc.FullHostName will not be initialized."
		return 0
	}

	db_do "REPLACE INTO \`misc\` (param, val) VALUES ('FullHostName', '$hostname');"
}

db_fill_admin_info()
{
	local hostname="$WHN_HOSTNAME"
	[ -n "$hostname" ] || {
		pp_echo "Warning: WHN_HOSTNAME is empty, admin information will not be initialized."
		return 0
	}

	db_do "INSERT INTO \`misc\` VALUES ('admin_email', 'root@$hostname');"
	db_do "INSERT INTO \`misc\` VALUES ('admin_info_not_required', 'true');"
}

db_fill_disable_mail_notifications()
{
	db_do "INSERT INTO \`misc\` VALUES ('disable_mail_notifications', 'true');"
}

db_fill_set_psa_configured()
{
	db_do "INSERT INTO \`misc\` VALUES ('psa_configured', 'true');"
}

db_create_admin_role()
{
	db_do "INSERT INTO \`smb_roles\` (name, isBuiltIn, ownerId) VALUES ('Admin', 1, 1);"
}

db_set_whm_dns()
{
	db_do "UPDATE ServiceInstallations SET name = 'WhmDns' WHERE name = 'PleskDns';"
}

product_db_initializer()
{
	(
		product_db_installer
	) || return 1

	db_set_whm_dns

	db_fill_hostname
	db_fill_admin_info
	db_fill_ip_addresses
	db_fill_disable_mail_notifications
	db_fill_set_psa_configured

	db_create_admin_role
	db_init_default_locale

	core_init_upgrader_conf
}

usage()
{
	cat <<-EOT >&2
		Usage: env WHN_IP_LIST='...' WHN_HOSTNAME='...' DB_HOST='...' DB_NAME='...' DB_USER_NAME='...' DB_PASSWORD='...' $0

		  where 
		  WHN_IP_LIST is WHN IP addresses list, format is equivalent to output of: 
		    # plesk sbin ifmng -l | tr ' ' '|'
		  WHN_HOSTNAME is WHN FQDN, equivalent to output of:
		    # hostname -f
		  DB_HOST is a host name or an IP address of the database's server
		  DB_NAME is the name of the database
		  DB_USER_NAME is the name of a user to access the database as
		  DB_PASSWORD is the password of that user

		  WHN_IP_LIST and WHN_HOSTNAME are optional - corresponding database configuration will be skipped if they aren't specified.
		  DB_HOST, DB_NAME, DB_USER_NAME and DB_PASSWORD are mandatory - database will not be initialized if they aren't specified.

		  This command will initialize the specified database.
		EOT
}

die_usage()
{
	usage
	cat <<-EOT >&2

		ERROR: $*
		EOT
	exit 1
}

if [ "$1" = "help" -o "$1" = "--help" -o "$1" = "-h" ]; then
	usage
	exit 2
fi

if [ -z "$DB_HOST" ]; then die_usage "DB_HOST is not specified"; fi
if [ -z "$DB_NAME" ]; then die_usage "DB_NAME is not specified"; fi
if [ -z "$DB_USER_NAME" ]; then die_usage "DB_USER_NAME is not specified"; fi
if [ -z "$DB_PASSWORD" ]; then die_usage "DB_PASSWORD is not specified"; fi

set_log_action_name "$prog"
log_start "$prog"
set_error_report_context "$prog"

product_default_conf
initial_conf
set_common_params
set_mysql_client_params
set_mysql_remote_auth "$DB_HOST" "$DB_USER_NAME" "$DB_PASSWORD"

mysql_db_name="$DB_NAME"
product_db_sql="$PRODUCT_BOOTSTRAPPER_DIR/db/${PRODNAME}_db.sql"

product_db_initializer

