#!/bin/sh
#
# $Id$
#-------------------------------------------------------------------------------
# TeamFile server common shell library.
#
# Copyright (c) 2006,2007 COMPUTER HI-TECH INC., All rights reserved.
#-------------------------------------------------------------------------------

#------------------
# set env
#------------------
APACHE_DIR_NAME="www"
if test -d "${TF_HOME}"; then
	TF_BINDIR="${TF_HOME}/${APACHE_DIR_NAME}/bin"
	TF_CONFDIR="${TF_HOME}/${APACHE_DIR_NAME}/conf/conf.d"
	ENVVARS_HOME="${TF_HOME}/${APACHE_DIR_NAME}/bin"
else
	TF_BINDIR="/usr/local/teamfile/www/bin"
	TF_CONFDIR="/usr/local/teamfile/www/conf/conf.d"
	ENVVARS_HOME="/usr/local/teamfile/www/bin"
	TF_HOME="/usr/local/teamfile"
fi
TF_AUTODELDIR="${TF_CONFDIR}/autodelete"
DDL_ROOT="${TF_BINDIR}/DDL"
SQLDATA_ROOT="${DDL_ROOT}"
export SQLDATA_ROOT

#
TF_SCRIPTCONFDIR="${TF_BINDIR}"

# read apache configuration
. ${ENVVARS_HOME}/envvars

# read default configuration file
if test -f ${TF_SCRIPTCONFDIR}/tfenvvars.default; then
	. ${TF_SCRIPTCONFDIR}/tfenvvars.default
fi

# read customized configuration file
if test -f ${TF_SCRIPTCONFDIR}/tfenvvars; then
	. ${TF_SCRIPTCONFDIR}/tfenvvars
fi

# type of repository database
REPOS_DBTYPE="pg"

# The temporary directory path
TMP_BASE_DIR="/tmp"

# for Oracle
TMP_SQL_FILE="${TMP_BASE_DIR}/tmp.sql"
SQLPLUS_S="${SQLPLUS} -s /nolog"

# for PostgreSQL
if test -z "${PG_ADMIN_GROUP}"; then
	PG_ADMIN_GROUP="postgres"
fi

# for tfdownloader
TF_DOWNLOADER="${TF_BINDIR}/tfdownloader"

# md5 command
TF_MD5="${TF_BINDIR}/tfsmd5"

# status mailsend command
TF_SENDMAIL="${TF_BINDIR}/sendmail.pl"

DL_ST_FOUND_LIST=0
DL_ST_NOTFOUND_LIST=1
DL_ST_NET_ERR=2
DL_ST_MISSMATCH_FILELIST=3
DL_ST_MISSMATCH_HASH=4
DL_ST_MISSING_PARAM=5
DL_ST_INVALID_PARAM=6
DL_ST_NOTFOUND_FILE=7
DL_ST_ERR=255

# for tfupdater
TF_UPDATER="${TF_BINDIR}/tfupdater"

UP_ST_OK=0
UP_ST_NOUPDATE=1
UP_ST_NOTSUPPORTED=2
UP_ST_NOPRIVILEGE=3
UP_ST_MISSING_PARAM=4
UP_ST_INVALID_PARAM=5
UP_ST_BACKUP_FAIL=6
UP_ST_MISSMATCH_HASH=7
UP_ST_ALREADY_RUNNING=8
UP_ST_NOTALLOWED_UPDATE=9
UP_ST_ABORT=128
UP_ST_ERR=255

#
UPSP_MODE_CHECKUPDATE=1
UPSP_MODE_PREINSTALL=2
UPSP_MODE_INSTALL=3
UPSP_MODE_POSTINSTALL=4

# Check for echo -n vs echo \c
if echo '\c' | grep -s c >/dev/null 2>&1 ; then
        ECHO_N="echo -n"
        ECHO_C=""
else
        ECHO_N="echo"
        ECHO_C='\c'
fi

#-----------------------------------------------------------------------
# get OS type
#-----------------------------------------------------------------------
OSTYPE_STR=
OS_RELEASE_STR=
OSTYPE_CD=
IS_DOCKER=0

UNAME_ALL=`uname -a`
UNAME_S=`uname -s`

OS_SOLARIS=10		# Solaris (SunOS)
OS_LINUX_RH7=20		# RedHat 7.3
OS_LINUX_RH8=21		# RedHat 8.0
OS_LINUX_RH9=22		# RedHat 9.0
OS_LINUX_RHEL3=23	# RedHat Enterprise Linux release 3
OS_LINUX_RHEL4=24	# RedHat Enterprise Linux release 4
OS_LINUX_WBEL3=25	# White Box Enterprise Linux release 3
OS_LINUX_WBEL4=26	# White Box Enterprise Linux release 4
OS_LINUX_CENT4=27	# CentOS release 4
OS_LINUX_CENT5=28	# CentOS release 5
OS_LINUX_CENT6=41	# CentOS release 6
OS_LINUX_DEBIAN30=29	# Debian 3 (woody)
OS_LINUX_DEBIAN31=29	# Debian 3.1 (sarge)
OS_LINUX_RHEL5=40	# RedHat Enterprise Linux release 5
OS_LINUX_RHEL6=42	# RedHat Enterprise Linux release 6
OS_LINUX_RHEL7=43	# RedHat Enterprise Linux release 7
OS_LINUX_RHEL8=44	# RedHat Enterprise Linux release 8
OS_LINUX_ROCKY8=45	# Rocky Linux 8
OS_LINUX_ALMA8=46	# AlmaLinux 8
OS_MACOSX103=30		# MacOSX 10.3
OS_MACOSX102=31		# MacOSX 10.2
OS_LINUX_AMI=70		# Amazon Linux AMI
OS_UNKNOWN=99

getOsType() {

	if test -n "${OSTYPE_STR}" && test -n "${OS_RELEASE_STR}" && test -n "${OSTYPE_CD}"; then
		return ${OSTYPE_CD}
	fi

	if [ -f /.dockerenv ]; then
		IS_DOCKER=1
	fi

	OSTYPE_STR=
	OS_RELEASE_STR=
	OSTYPE_CD=${OS_UNKNOWN}

	# Linux
	if test "${UNAME_S}" = "Linux"; then
		linux_release_str=
		if test -f /etc/whitebox-release; then
			OSTYPE_CD=${OS_LINUX_WBEL3}
		elif test -f /etc/redhat-release; then
			linux_release_str="`cat /etc/redhat-release`"
			case "${linux_release_str}" in
				CentOS\ release\ 6*)
					OSTYPE_STR="CentOS6 Linux"
					OS_RELEASE_STR="RHEL6"
					OSTYPE_CD=${OS_LINUX_CENT6}
					;;
				*7*Maipo* | CentOS\ Linux\ release\ 7*)
					OSTYPE_STR="CentOS7 Linux"
					OS_RELEASE_STR="RHEL7"
					OSTYPE_CD=${OS_LINUX_RHEL7}
					;;
				*8*Ootpa* | CentOS\ Linux\ release\ 8*)
					OSTYPE_STR="CentOS8 Linux"
					OS_RELEASE_STR="RHEL8"
					OSTYPE_CD=${OS_LINUX_RHEL8}
					;;
				Rocky\ Linux\ release\ 8*)
					OSTYPE_STR="Rocky Linux"
					OS_RELEASE_STR="RHEL8"
					OSTYPE_CD=${OS_LINUX_ROCKY8}
					;;
				AlmaLinux\ release\ 8*)
					OSTYPE_STR="AlmaLinux"
					OS_RELEASE_STR="RHEL8"
					OSTYPE_CD=${OS_LINUX_ALMA8}
					;;
			esac
		elif test -f /etc/debian_version; then
			linux_release_str=`cat /etc/debian_version`
			case "${linux_release_str}" in
				3.0)
					OSTYPE_STR="Debian 3.0 Linux"
					OS_RELEASE_STR="Debian3.0"
					OSTYPE_CD=${OS_LINUX_DEBIAN30}
					;;
				3.1)
					OSTYPE_STR="Debian 3.1 Linux"
					OS_RELEASE_STR="Debian3.1"
					OSTYPE_CD=${OS_LINUX_DEBIAN31}
					;;
			esac
		elif test -f /etc/SuSE-release; then
			OSTYPE_CD=${OS_UNKNOWN}
		elif test -f /etc/os-release; then
			OSTYPE_STR="Amazon Linux AMI"
			OS_RELEASE_STR=""
			OSTYPE_CD=${OS_LINUX_AMI}
		fi

	# MacOSX
	elif test "${UNAME_S}" = "Darwin"; then

		IS_MACOSX3=`echo ${UNAME_ALL} | grep '7\.[0-9]\.[0-9].*Darwin'`
		IS_MACOSX2=`echo ${UNAME_ALL} | grep '6\.[0-9]\.[0-9].*Darwin'`
		if test -n "${IS_MACOSX3}"; then
			OSTYPE_STR="MacOSX 10.3"
			OSTYPE_CD=${OS_MACOSX103}

		elif test -n "${IS_MACOSX2}"; then
			OSTYPE_STR="MacOSX 10.2"
			OSTYPE_CD=${OS_MACOSX102}
		fi
	# Solaris
	elif test "${UNAME_S}" = "SunOS"; then
		OSTYPE_STR="Solaris"
		OS_RELEASE_STR="Solaris9"
		OSTYPE_CD=${OS_SOLARIS}
	fi

	return ${OSTYPE_CD}
}

#-----------------------------------------------------------------------
# Check root privilege
#-----------------------------------------------------------------------
isRootPrivilege() {
	# check os type
	getOsType
	OSTYPE=$?

	if test "${OSTYPE}" = "${OS_SOLARIS}"; then
		UID_NUM=`/usr/xpg4/bin/id -u`
	else
		UID_NUM=`id -u`
	fi

	if test -z "${UID_NUM}" || test "${UID_NUM}" != "0"; then
		return 0
	fi

	return 1
}

#-----------------------------------------------------------------------
# Check whethere TeamFile is runing.
#-----------------------------------------------------------------------
isTeamFileRuning() {
	getOsType
	OSTYPE=$?

	if test "${OSTYPE}" = "${OS_MACOSX102}" || test "${OSTYPE}" = "${OS_MACOSX103}"; then
		is_running=`ps auxw | grep 'teamfile\/www\/bin\/httpd'`
	else
		is_running=`ps -ef | grep 'teamfile\/www\/bin\/httpd'`
	fi

	if test -n "${is_running}"; then
		return 1
	else
		return 0
	fi
}

#-----------------------------------------------------------------------
# Check whethere PostgreSQL is runing.
#-----------------------------------------------------------------------
isPostgreSQLRuning() {
	getOsType
	OSTYPE=$?

	is_running=
	if test "${OSTYPE}" = "${OS_MACOSX102}" || test "${OSTYPE}" = "${OS_MACOSX103}"; then
		is_running=`ps auxw | grep '\/usr\/local\/tfpgsql\/bin\/postmaster'`
	else
		${POSTGRESCTL} status >/dev/null 2>&1
		RETVAL=$?
		if test "${RETVAL}" = "0"; then
			is_running=1
		fi
	fi

	if test -n "${is_running}"; then
		return 1
	else
		return 0
	fi
}

#-----------------------------------------------------------------------
# check directory permission
#-----------------------------------------------------------------------
isRightPermission() {
	target_dir="$1"

	if test -z "${target_dir}"; then
		echo "The argument of target directory is EMPTY."
		return 1
	fi

	if test ! -d "${target_dir}"; then
		echo "\"${target_dir}\" is not directory or missing."
		return 1
	fi

	# check write permission
	dummy_file="${target_dir}/file.dummy.`date +%Y%m%d%H%M%S`"
	touch ${dummy_file} >/dev/null 2>&1
	RETVAL=$?
	if test "${RETVAL}" != "0"; then
		if test -f "${dummy_file}"; then
			rm -f ${dummy_file}
		fi
		return 1
	fi

	rm -f ${dummy_file}

	return 0
}

#-----------------------------------------------------------------------
# search configuration file path list
# (note)
#    This function set file path to "CONFIGFILE_LIST" env.
#-----------------------------------------------------------------------
CONFIGFILE_LIST=""
search_configuration_files() {

	confbase=""
	if test -z "${APACHE_HOME}"; then
		confbase="/usr/local/teamfile/www/conf/conf.d"
	else
		confbase="${APACHE_HOME}/conf/conf.d"
	fi

	CONFIGFILE_LIST=`find ${confbase} -name '*.conf' -print | sed -n -e '/new_[a-zA-Z0-9_-][a-zA-Z0-9_-]*.conf/p' 2>/dev/null`
}

#-----------------------------------------------------------------------
# Display path of configuration files.
#-----------------------------------------------------------------------
show_configuration_files() {

	confbase=""
	if test -z "${APACHE_HOME}"; then
		confbase="/usr/local/teamfile/www/conf/conf.d"
	else
		confbase="${APACHE_HOME}/conf/conf.d"
	fi

	list=`find ${confbase} -name '*.conf' -print | sed -n -e '/new_[a-zA-Z0-9_-][a-zA-Z0-9_-]*.conf/p' 2>/dev/null`
	for f in ${list};
	do
		locationname=`sed -n -e 's/>//g' -e 's/^<Location[ ][ ]*\///p' ${f}`
		if test -z "${locationname}"; then
			continue
		fi
		echo ${f}
	done
}

#-----------------------------------------------------------------------
# get package version string
#-----------------------------------------------------------------------
PKG_VERSION_STR=""
get_package_version_string() {

	# get os type string
	getOsType
	OSTYPE=$?

	PKG_VERSION_STR=""

	# Solaris
	if test "${OSTYPE}" = "${OS_SOLARIS}"; then
		PKG_VERSION_STR=`/usr/bin/pkginfo -l TFmoddavtf | sed -n -e 's/[ ]*VERSION:[ ]*//p'`
		[ "$?" != "0" ] && return 1
	# MacOSX
	elif test "${OSTYPE}" = "${OS_MACOSX102}" || test "${OSTYPE}" = "${OS_MACOSX103}"; then
		PACKAGE_BASE="/Library/Receipts"
		plist="${PACKAGE_BASE}/mod_dav_tf.pkg/Contents/Info.plist"
		if test -f "${plist}"; then
			PKG_VERSION_STR=`grep '<string>mod_dav_tf [0-9]*' ${plist} | tr '\t' ' ' | sed -e 's/<string>//g' -e 's/<\/string>//g' -e 's/[ ]//g' -e 's/mod_dav_tf//p' | sort -u`
			[ "$?" != "0" ] && return 1
		fi
	# Linux
	else
		pname=`rpm -q pk-mod_dav_tf-pg9`
		[ "$?" != "0" ] && return 1

		PKG_VERSION_STR=`rpm -q --queryformat='%{Version}-%{Release}\n' ${pname}`
		[ "$?" != "0" ] && return 1
	fi

	return 0
}

#-----------------------------------------------------------------------
# Check RPM package whthere install or not
# [ args ]
#	$1: package path
# [ return ]
#	RPM_VALIDATE_ST_NEWER      : $1 is new or updated package
#	RPM_VALIDATE_ST_INSTALLED  : $1 is already installed. (same version)
#	RPM_VALIDATE_ST_OLDER      : $1 is older version package
#	RPM_VALIDATE_ST_DEPENDENCY : $1 has failed-dependency
#	RPM_VALIDATE_ST_BROKEN     : $1 may be broken
#	RPM_VALIDATE_ST_ERROR      : unexpected error
#-----------------------------------------------------------------------
RPM_VALIDATE_ST_NEWER=1
RPM_VALIDATE_ST_INSTALLED=2
RPM_VALIDATE_ST_OLDER=3
RPM_VALIDATE_ST_DEPENDENCY=4
RPM_VALIDATE_ST_BROKEN=5
RPM_VALIDATE_ST_ERROR=9

validate_rpm_update() {
	rpm_pkg="$1"

	if test -z "${rpm_pkg}"; then
		return ${RPM_VALIDATE_ST_ERROR} 
	fi

	# check Update
	rpm -U --test ${rpm_pkg} >/dev/null 2>&1 
	RETVAL=$?
	if test "${RETVAL}" = "0"; then
		# rpm_pkg is new or update package
		return ${RPM_VALIDATE_ST_NEWER} 
	elif test "${RETVAL}" = "2"; then
		# rpm_pkg is older version package
		return ${RPM_VALIDATE_ST_OLDER}
	fi

	# check same version
	rpm -U --test --replacepkgs ${rpm_pkg} >/dev/null 2>&1
	RETVAL=$?
	if test "${RETVAL}" = "0"; then
		# rpm_pkg is already installed
		return ${RPM_VALIDATE_ST_INSTALLED}
	fi

	# check faile dependency
	rpm -U --test --nodeps ${rpm_pkg} >/dev/null 2>&1
	RETVAL=$?
	if test "${RETVAL}" = "0"; then
		# rpm_pkg has failed-dependency
		return ${RPM_VALIDATE_ST_DEPENDENCY}
	fi

	# check conflict
	rpm -U --test --replacefiles ${rpm_pkg} >/dev/null 2>&1
	RETVAL=$?
	if test "${RETVAL}" = "0"; then
		return ${RPM_VALIDATE_ST_BROKEN}
	elif test "${RETVAL}" = "1"; then
		# rpm_pkg is already installed
		return ${RPM_VALIDATE_ST_INSTALLED}
	fi

	return ${RPM_VALIDATE_ST_BROKEN}
}

#-----------------------------------------------------------------------
# get MD5 message
# [ args ]
#     $1: filepath
# [ output ]
#     $MD5_DIGEST
#-----------------------------------------------------------------------
get_md5() {
	which md5sum >/dev/null 2>&1
	RETVAL=$?
	if test "${RETVAL}" = "0"; then
		MD5_DIGEST=`md5sum $1 | cut -d ' ' -s -f1`
	else
		MD5_DIGEST=`openssl md5 -hex $1 | cut -d ' ' -s -f2`
	fi
	return 0
}

#-----------------------------------------------------------------------
# Start Apache
# [ args ]
#     $1: 1 = slient mode
#-----------------------------------------------------------------------
start_teamfile() {
	INTERACTIVE=1
	if test -z "$1" || test "$1" != "1"; then
		INTERACTIVE=0
	fi

	if test ${INTERACTIVE} = 1; then
		echo ""
	fi

	# check root privilege
	isRootPrivilege
	RETVAL=$?
	if test "${RETVAL}" = "0"; then
		if test ${INTERACTIVE} = 1; then
			echo "Need to root privilege !"
		fi
		return 1
	fi

	getOsType
	OSTYPE=$?

	# MacOSX
	if test "${OSTYPE}" = "${OS_MACOSX102}" || test "${OSTYPE}" = "${OS_MACOSX103}"; then
		SystemStarter -v start TeamFileServer
	# Linux
	elif test ${OSTYPE_CD} -lt "${OS_LINUX_RHEL7}"; then
		${APACHECTL} start
	else
		/usr/bin/systemctl start teamfile
	fi
	return $?
}

#--------------------------------------
# Stop TeamFile
# [ args ]
#     $1: 1 = slient mode
#--------------------------------------
stop_teamfile() {
	INTERACTIVE=1
	if test -z "$1" || test "$1" != "1"; then
		INTERACTIVE=0
	fi

	if test ${INTERACTIVE} = 1; then
		echo ""
	fi

	# check root privilege
	isRootPrivilege
	RETVAL=$?
	if test "${RETVAL}" = "0"; then
		if test ${INTERACTIVE} = 1; then
			echo "Need to root privilege !"
		fi
		return 1
	fi

	getOsType
	OSTYPE=$?

	# MacOSX
	if test "${OSTYPE}" = "${OS_MACOSX102}" || test "${OSTYPE}" = "${OS_MACOSX103}"; then
		SystemStarter -v stop TeamFileServer
	# Linux
	elif test ${OSTYPE_CD} -lt "${OS_LINUX_RHEL7}"; then
		${APACHECTL} stop
	else
		/usr/bin/systemctl stop teamfile
	fi
	return $?
}

#--------------------------------------
# Restart TeamFile
# [ args ]
#     $1: 1 = slient mode
#--------------------------------------
restart_teamfile() {
	INTERACTIVE=1
	if test -z "$1" || test "$1" != "1"; then
		INTERACTIVE=0
	fi

	if test ${INTERACTIVE} = 1; then
		echo ""
	fi

	# check root privilege
	isRootPrivilege
	RETVAL=$?
	if test "${RETVAL}" = "0"; then
		if test ${INTERACTIVE} = 1; then
			echo "Need to root privilege !"
		fi
		return 1
	fi

	getOsType
	OSTYPE=$?
	
	# MacOSX
	if test "${OSTYPE}" = "${OS_MACOSX102}" || test "${OSTYPE}" = "${OS_MACOSX103}"; then
		SystemStarter -v restart TeamFileServer
	# Linux
	elif test ${OSTYPE_CD} -lt "${OS_LINUX_RHEL7}"; then
		${APACHECTL} restart
	else
		/usr/bin/systemctl restart teamfile
	fi
	return $?
}

#--------------------------------------
# Reload TeamFile
# [ args ]
#     $1: 1 = slient mode
#--------------------------------------
reload_teamfile() {
	INTERACTIVE=1
	if test -z "$1" || test "$1" != "1"; then
		INTERACTIVE=0
	fi

	if test ${INTERACTIVE} = 1; then
		echo ""
	fi

	# check root privilege
	isRootPrivilege
	RETVAL=$?
	if test "${RETVAL}" = "0"; then
		if test ${INTERACTIVE} = 1; then
			echo "Need to root privilege !"
		fi
		return 1
	fi

	getOsType
	OSTYPE=$?
	
	# MacOSX
	if test "${OSTYPE}" = "${OS_MACOSX102}" || test "${OSTYPE}" = "${OS_MACOSX103}"; then
		if test ${INTERACTIVE} = 1; then
			echo "Sorry, MacOSX does not support this operation."
		fi
		return 1
	# Linux
	elif test ${OSTYPE_CD} -lt "${OS_LINUX_RHEL7}"; then
		${APACHECTL} reload
	else
		/usr/bin/systemctl reload teamfile
	fi
	return $?
}

#--------------------------------------
# Start PostgreSQL
# [ args ]
#     $1: 1 = slient mode
#--------------------------------------
start_postgresql() {
	INTERACTIVE=1
	if test -z "$1" || test "$1" != "1"; then
		INTERACTIVE=0
	fi

	if test ${INTERACTIVE} = 1; then
		echo ""
	fi

	# check root privilege
	isRootPrivilege
	RETVAL=$?
	if test "${RETVAL}" = "0"; then
		if test ${INTERACTIVE} = 1; then
			echo "Need to root privilege !"
		fi
		return 1
	fi

	getOsType
	OSTYPE=$?
	
	# MacOSX
	if test "${OSTYPE}" = "${OS_MACOSX102}" || test "${OSTYPE}" = "${OS_MACOSX103}"; then
		SystemStarter -v start PostgreSQL
		return $?
	# Linux
	elif test ${OSTYPE_CD} -lt "${OS_LINUX_RHEL7}"; then
		if test -f ${POSTGRESCTL}; then
			${POSTGRESCTL} start
		fi
	else
		/usr/bin/systemctl start tfpostgresql
	fi
	return $?
}

#--------------------------------------
# Stop PostgreSQL
# [ args ]
#     $1: 1 = slient mode
#--------------------------------------
stop_postgresql() {
	INTERACTIVE=1
	if test -z "$1" || test "$1" != "1"; then
		INTERACTIVE=0
	fi

	if test ${INTERACTIVE} = 1; then
		echo ""
	fi

	# check root privilege
	isRootPrivilege
	RETVAL=$?
	if test "${RETVAL}" = "0"; then
		if test ${INTERACTIVE} = 1; then
			echo "Need to root privilege !"
		fi
		return 1
	fi

	getOsType
	OSTYPE=$?
	
	# MacOSX
	if test "${OSTYPE}" = "${OS_MACOSX102}" || test "${OSTYPE}" = "${OS_MACOSX103}"; then
		SystemStarter -v stop PostgreSQL
	# Linux
	elif test ${OSTYPE_CD} -lt "${OS_LINUX_RHEL7}"; then
		if test -f ${POSTGRESCTL}; then
			${POSTGRESCTL} stop
		fi
	else
		/usr/bin/systemctl stop tfpostgresql
	fi
	return $?
}

#--------------------------------------
# Restart PostgreSQL
# [ args ]
#     $1: 1 = slient mode
#--------------------------------------
restart_postgresql() {
	INTERACTIVE=1
	if test -z "$1" || test "$1" != "1"; then
		INTERACTIVE=0
	fi

	if test ${INTERACTIVE} = 1; then
		echo ""
	fi

	# check root privilege
	isRootPrivilege
	RETVAL=$?
	if test "${RETVAL}" = "0"; then
		if test ${INTERACTIVE} = 1; then
			echo "Need to root privilege !"
		fi
		return 1
	fi

	getOsType
	OSTYPE=$?
	
	# MacOSX
	if test "${OSTYPE}" = "${OS_MACOSX102}" || test "${OSTYPE}" = "${OS_MACOSX103}"; then
		SystemStarter -v restart PostgreSQL
		return $?
	# Linux
	elif test ${OSTYPE_CD} -lt "${OS_LINUX_RHEL7}"; then
		if test -f ${POSTGRESCTL}; then
			${POSTGRESCTL} restart
		fi
	else
		/usr/bin/systemctl restart tfpostgresql
	fi
	return $?
}

#--------------------------------------
# Reload PostgreSQL
# [ args ]
#     $1: 1 = slient mode
#--------------------------------------
reload_postgresql() {
	INTERACTIVE=1
	if test -z "$1" || test "$1" != "1"; then
		INTERACTIVE=0
	fi

	if test ${INTERACTIVE} = 1; then
		echo ""
	fi

	# check root privilege
	isRootPrivilege
	RETVAL=$?
	if test "${RETVAL}" = "0"; then
		if test ${INTERACTIVE} = 1; then
			echo "Need to root privilege !"
		fi
		return 1
	fi

	getOsType
	OSTYPE=$?
	
	# MacOSX
	if test "${OSTYPE}" = "${OS_MACOSX102}" || test "${OSTYPE}" = "${OS_MACOSX103}"; then
		if test ${INTERACTIVE} = 1; then
			echo "Sorry, MacOSX does not support this operation."
		fi
		return 1
	# Linux
	elif test ${OSTYPE_CD} -lt "${OS_LINUX_RHEL7}"; then
		if test -f ${POSTGRESCTL}; then
			${POSTGRESCTL} reload
		fi
	else
		/usr/bin/systemctl reload tfpostgresql
	fi
	return $?
}

#-----------------------------------------------------------------------
# create backup directory
# [ args ]
#	$1: directory path that you want to create
#       $2: 1 = interactive mode
#-----------------------------------------------------------------------
create_backup_dir() {

	BACKUP_DIR="$1"
	INTERACTIVE=1
	if test -z "$2" || test "$2" != "1"; then
		INTERACTIVE=0
	fi

	if test -z "${BACKUP_DIR}"; then
		echo "The backup directory name was missing."
		return 1
	fi

	# create backup directory
	if test ! -d ${BACKUP_DIR}; then
		mkdir -p ${BACKUP_DIR}
		RETVAL=$?
		if test "${RETVAL}" != "0"; then
			echo "Failed to create backup directory. (name = ${BACKUP_DIR})"
			return 1
		fi
	else
		if test ${INTERACTIVE} = 1; then
			echo "The directory \"${BACKUP_DIR}\" already exist."
			$ECHO_N "Do you overwrite it ? (y/n) : "$ECHO_C
			read ANS
			if test "${ANS}" != "y"; then
				echo "OK. we aborted. Please rename this directory."
				return 1
			fi
		else
			return 1
		fi
	fi
	return 0
}

#-----------------------------------------------------------------------
# backup configuration files
# [ args   ]
#	$1 : Backup directory
#       $2: 1 = interactive mode
#-----------------------------------------------------------------------
backup_configuration() {

	BACKUP_DIR="$1"
	INTERACTIVE=1
	if test -z "$2" || test "$2" != "1"; then
		INTERACTIVE=0
	fi

	create_backup_dir ${BACKUP_DIR}
	RETVAL=$?
	if test "${RETVAL}" != "0"; then
		return 1
	fi

	# backup apache configuration
	APACHE_BACKUPFILES="${TF_BINDIR}/envvars ${TF_BINDIR}/tfenvvars.default ${TF_BINDIR}/tfenvvars"
	for f in ${APACHE_BACKUPFILES};
	do
		if test -f $f; then
			cp -p ${APACHE_BACKUPFILES} ${BACKUP_DIR}/
			RETVAL=$?
			if test "${RETVAL}" != "0"; then
				echo "Failed to copy apache configuration files."
				return 1
			fi
		fi
	done
	if test -d ${APACHE_HOME}/conf; then
		cp -pR ${APACHE_HOME}/conf ${BACKUP_DIR}/
	fi

	if test "${REPOS_DBTYPE}" = "pg"; then

		# backup postgresql configuration
		SCRIPT_CONFIG_DEFAULT="/var/lib/tfpgsql/script_config.default"
		if test -f "${SCRIPT_CONFIG_DEFAULT}"; then
				. ${SCRIPT_CONFIG_DEFAULT}
		fi
		SCRIPT_CONFIG="/var/lib/tfpgsql/script_config"
		if test -f "${SCRIPT_CONFIG}"; then
			. ${SCRIPT_CONFIG}
		fi
		if test -z "${PGDATA}"; then
			PGDATA="/var/lib/tfpgsql/PGDATA"
		fi

		if test ${INTERACTIVE} = 1; then
			echo ""
			$ECHO_N "Input path of PGDATA directory (default: ${PGDATA}) : "$ECHO_C
			read tmp
			if test -n "${tmp}"; then
				PGDATA=${tmp}
			fi
		fi

		EXTRA_FILES=
		if test ! -d "${PGDATA}"; then
			if test ${INTERACTIVE} = 1; then
				echo "The directory \"${PGDATA}\" is not valid directory."
				$ECHO_N "Continue ? (y/n) (default: n) : "$ECHO_C
				read ANS
				if test "${ANS}" != 'y'; then
					return 1
				fi
				EXTRA_FILES="${PGDATA}/postgresql.conf ${PGDATA}/pg_hba.conf ${PGDATA}/pg_ident.conf"
			fi
		fi

		# backup postgresql files
		POSTGRESQL_BACKUPFILES="/var/lib/tfpgsql/script_config /var/lib/tfpgsql/script_config.default /var/lib/tfpgsql/.bash_profile ${EXTRA_FILES}"
		for f in ${POSTGRESQL_BACKUPFILES};
		do
			if test -f $f; then
				cp -p ${POSTGRESQL_BACKUPFILES} ${BACKUP_DIR}/
				RETVAL=$?
				if test "${RETVAL}" != "0"; then
					echo "Failed to copy postgresql configuration files.(file = "$f")"
					return 1
				fi
			fi
		done
	fi

	return 0
}

#-----------------------------------------------------------------------
# backup binary files
# [ args   ]
#	$1 : Backup directory
#       $2: 1 = interactive mode
#-----------------------------------------------------------------------
backup_binary() {

	BACKUP_DIR="$1"
	INTERACTIVE=1
	if test -z "$2" || test "$2" != "1"; then
		INTERACTIVE=0
	fi

	create_backup_dir ${BACKUP_DIR}
	RETVAL=$?
	if test "${RETVAL}" != "0"; then
		return 1
	fi

	rsync -av --delete --exclude=logs ${TF_HOME} ${BACKUP_DIR}/
	RETVAL=$?
	if test "${RETVAL}" != "0"; then
		echo "Failed to copy binary files."
		return 1
	fi

	return 0
}

#-----------------------------------------------------------------------
# backup postgresql data directory
# [ args   ]
#	$1 : Backup directory
#       $2: 1 = interactive mode
#-----------------------------------------------------------------------
backup_pgdata_directory() {

	BACKUP_DIR="$1"
	INTERACTIVE=1
	if test -z "$2" || test "$2" != "1"; then
		INTERACTIVE=0
	fi

	create_backup_dir ${BACKUP_DIR}
	RETVAL=$?
	if test "${RETVAL}" != "0"; then
		return 1
	fi

	# backup postgresql configuration
	if test -f "${SCRIPT_CONFIG}"; then
		. ${SCRIPT_CONFIG}
	else
		if test -z "${PGDATA}"; then
			PGDATA="/var/lib/tfpgsql/PGDATA"
		fi

		if test ${INTERACTIVE} = 1; then
			echo ""
			$ECHO_N "Input path of PGDATA directory (default: ${PGDATA}) : "$ECHO_C
			read tmp
			if test -n "${tmp}"; then
				PGDATA=${tmp}
			fi
		fi
	
		if test ! -d "${PGDATA}" && test ${INTERACTIVE} = 1; then
			$ECHO_N "The directory \"${PGDATA}\" is not valid directory. Continue (y/n) : "$ECHO_C
			read ANS
			if test "${ANS}" != "y"; then
				echo "OK, abort"
				return 1;
			fi
		fi
	fi

	# backup postgresql files
	if test -d "${PGDATA}"; then
		cp -pR ${PGDATA} ${BACKUP_DIR}/
		RETVAL=$?
		if test "${RETVAL}" != "0"; then
			echo "Failed to copy PGDATA."
			return 1
		fi
	fi

	return 0
}

#--------------------------------------
# build download status line
# [ args ]
#     $1: status string
#     $2: filepath
#--------------------------------------
build_status_line() {
	sp_padding="                                                  "
	DL_STATUS_LINE=`echo "$1  $2${sp_padding}" | awk '{print substr($0, 1, 50)}'`
}

#-----------------------------------------------------------------------
# LOCK this script for single
# [ args ]
#     $1: The lock file path
#-----------------------------------------------------------------------
lockscript() {
	_LOCKFILE="$1"

	if test -z "${_LOCKFILE}"; then
		echo ""
		echo "The lock file path is EMPTY."
		return 1
	fi

	if test -f "${_LOCKFILE}"; then
		BT_PID=`cat ${_LOCKFILE}`
		if test -n "${BT_PID}"; then
			ps -p "${BT_PID}" >/dev/null 2>&1
			RETVAL=$?
			if test "${RETVAL}" = 0; then
				echo ""
				echo "$0 has been already started. Maybe anyone use it."
				echo "If NOT, Please check \"${BT_PID}\" process and remove ${_LOCKFILE} file manually."
				echo ""
				return 1
			else
				rm -f ${_LOCKFILE}
			fi
		fi
	fi

	echo "$$" > ${_LOCKFILE}
	return 0
}

#-----------------------------------------------------------------------
# UNLOCK this script for single
# [ args ]
#     $1: The lock file path
#-----------------------------------------------------------------------
unlockscript() {
	_LOCKFILE="$1"

	if test -z "${_LOCKFILE}"; then
		echo ""
		echo "The lock file path is EMPTY."
		return 1
	fi
	rm -f ${_LOCKFILE}
	RETVAL=$?
	if test "${RETVAL}" != "0"; then
		echo "Failed to unlock exclusive lock."
		echo "Please remove ${_LOCKFILE} file manually."
	fi
	return 0
}

#-----------------------------------------------------------------------
# Parse location config and load these values.
# You can access "ENV_xxxx" (xxxx: Directive name).
#
# (parsed env vars)
#	ENV_LocationName  : Location name without "/" (ex, teamfile)
#	ENV_TfDbDbmstype  : Repository database type (ex, pg)
#	ENV_TfDbDbname    : Repository database name (ex, db_xxx)
#	ENV_TfDbHostname  : Repository database hostname (ex, localhost)
#	ENV_TfDbHostport  : Repository database port (ex, 5432)
#	ENV_TfDbUsername  : Repository database access username (ex, xxxuser)
#	ENV_TfDbPassword  : Repository database access password (ex, xxxpass)
#	ENV_TfFsRootPath  : The storage root path (ex, /var/lib/teamfile/STORAGE/xxx)
#	ENV_TfTrashFolder : Use Trash-Folder (on/off)
#	ENV_TfEncryptPassword  : Encrypt password (on/off)
#	ENV_TfExtendUserStatus : Use extended user status (on/off)
#	ENV_TfMail        : Mail function (on/off)
#	ENV_TfMlHostname  : SMTP servername
#	ENV_TfMlHostport  : SMTP serverport
#	ENV_TfMlAdminaddr : The administrator's mailaddr
#	ENV_TfMlEncoding  : The sending mail encoding (on/off)
#	ENV_TfMlServerSend: Use server-sending mail (on/off)
#	ENV_TfMlNotifyAction      : (on/off)
#	ENV_TfMlEnableOneClickURL : (on/off)
#	ENV_TfSyncGroupUri: (on/off/middle)
#	ENV_TfMaxUser : max users(ex, 20)
#
# [ args ]
#     $1: The file path of location config
#-----------------------------------------------------------------------
parse_locationconf() {

	LFILE="$1"
	SED_FILE="${TMP_BASE_DIR}/_extractlocation.sed"
	ENVVAL_FILE="${TMP_BASE_DIR}/_vals"

	# unset values
	unset ENV_LocationName ENV_TfDbDbmstype ENV_TfDbDbname ENV_TfDbHostname \
	      ENV_TfDbHostport ENV_TfDbUsername ENV_TfDbPassword \
		  ENV_TfFsRootPath ENV_TfTrashFolder ENV_TfEncryptPassword ENV_TfExtendUserStatus \
		  ENV_TfMail ENV_TfMlHostname ENV_TfMlHostport ENV_TfMlAdminaddr ENV_TfMlEncoding \
		  ENV_TfMlServerSend ENV_TfMlNotifyAction ENV_TfMlEnableOneClickURL ENV_TfSyncGroupUri ENV_TfMaxUser

	if test -z "${LFILE}" || test ! -f "${LFILE}"; then
		return 1
	fi

	# get data from configuration file
	ENV_LocationName=`sed -n -e 's/>//g' -e 's/^<Location[ ][ ]*\///p' ${LFILE}`
	if test -z "${ENV_LocationName}"; then
		# not error for this function
		return 0
	fi

	# set default values
	ENV_TfTrashFolder="off"
	ENV_TfEncryptPassword="off"
	ENV_TfExtendUserStatus="off"
	ENV_TfMlEnableOneClickURL="off"
	ENV_TfSyncGroupUri="off"

	# build sed script
	cat - > ${SED_FILE} <<_EOF_
/^<Location[ ][ ]*\/${ENV_LocationName}/,/^<\/Location>/{
	/^#/d
	/[\t ][\t ]*#/d
	s/^[\t ][\t ]*//g
	/^$/d
	s/$/"/g
	s:TfDbDbmstype[ ][ ]*:ENV_TfDbDbmstype=":p
	s:TfDbDbname[ ][ ]*:ENV_TfDbDbname=":p
	s:TfDbHostname[ ][ ]*:ENV_TfDbHostname=":p
	s:TfDbHostport[ ][ ]*:ENV_TfDbHostport=":p
	s:TfDbUsername[ ][ ]*:ENV_TfDbUsername=":p
	s:TfDbPassword[ ][ ]*:ENV_TfDbPassword=":p
	s:TfFsRootPath[ ][ ]*:ENV_TfFsRootPath=":p
	s:TfTrashFolder[ ][ ]*:ENV_TfTrashFolder=":p
	s:TfEncryptPassword[ ][ ]*:ENV_TfEncryptPassword=":p
	s:TfExtendUserStatus[ ][ ]*:ENV_TfExtendUserStatus=":p
	s:TfMail[ ][ ]*:ENV_TfMail=":p
	s:TfMlHostname[ ][ ]*:ENV_TfMlHostname=":p
	s:TfMlHostport[ ][ ]*:ENV_TfMlHostport=":p
	s:TfMlAdminaddr[ ][ ]*:ENV_TfMlAdminaddr=":p
	s:TfMlEncoding[ ][ ]*:ENV_TfMlEncoding=":p
	s:TfMlServerSend[ ][ ]*:ENV_TfMlServerSend=":p
	s:TfMlNotifyAction[ ][ ]*:ENV_TfMlNotifyAction=":p
	s:TfMlEnableOneClickURL[ ][ ]*:ENV_TfMlEnableOneClickURL=":p
	s:TfSyncGroupUri[ ][ ]*:ENV_TfSyncGroupUri=":p
	s:TfMaxUser[ ][ ]*:ENV_TfMaxUser=":p
}
_EOF_

	sed -n -f ${SED_FILE} ${LFILE} > ${ENVVAL_FILE}
	if test -f ${ENVVAL_FILE}; then
		# load values
		. ${ENVVAL_FILE}
	else
		return 1
	fi

	# remove temporary files
	rm -f ${ENVVAL_FILE} ${SED_FILE}

	return 0
}

#-----------------------------------------------------------
# Show update script's Usage
#-----------------------------------------------------------
up_usage() {
	echo "Usage: xxxscript.sh [-s] [-m mode] [-R] [-d download dir] [-u filelist path] [-p script temporary dir] [-h]"
	exit 1
}


#---------------------------------------------------------------------------
# Read update script's arguments and Callback functions (for update script ONLY)
# [ arg ]
#	$@ : update script's arguments
#---------------------------------------------------------------------------
process_upscript_arg() {

	SILENT_MODE=0
	SCRIPT_MODE=
	ROLLBACK_MODE=0
	DL_DIR_PATH=
	UP_FILELIST_PATH=
	UP_SCRIPT_TMP_PATH=


	while getopts sm:Rd:u:p:h OPT;
	do
		case $OPT in
			s)
				SILENT_MODE=1
				;;
			m)
				SCRIPT_MODE="$OPTARG"
				;;
			R)
				ROLLBACK_MODE=1
				;;
			d)
				DL_DIR_PATH="$OPTARG"
				;;
			u)
				UP_FILELIST_PATH="$OPTARG"
				;;
			p)
				UP_SCRIPT_TMP_PATH="$OPTARG"
				;;
			h)
				up_usage
				;;
			\?)
				up_usage
				;;
		esac
	done
	shift `expr $OPTIND - 1`

	# check arguments
	if test -z "${SCRIPT_MODE}"; then
		echo "The script_mode is EMPTY."
		up_usage
	fi

	if test ! -d "${DL_DIR_PATH}"; then
		echo "The path of downloaded module directory is not valid."
		up_usage
	fi

	if test ! -f "${UP_FILELIST_PATH}"; then
		echo "The filelist path is not valid."
		up_usage
	fi

	# execute callbackup functions
	case "${SCRIPT_MODE}" in
		${UPSP_MODE_CHECKUPDATE})
			upscript_checkupdate
			RETVAL=$?
			;;
		${UPSP_MODE_PREINSTALL})
			upscript_preinstall
			RETVAL=$?
			;;
		${UPSP_MODE_INSTALL})
			upscript_install
			RETVAL=$?
			;;
		${UPSP_MODE_POSTINSTALL})
			upscript_postinstall
			RETVAL=$?
			;;
	esac

	return ${RETVAL};
}

#---------------------------------------------------------------------------
# Remove autodelete configuration
# [ args ]
#	$1: The location name
#---------------------------------------------------------------------------
remove_autodel_config() {
	_lcname="$1"

	if test ! -d "${TF_AUTODELDIR}"; then
		return 0
	fi

	if test -z "${_lcname}"; then
		echo "The location name is EMPTY."
		return 1
	fi

	_lcname=`echo "/${_lcname}" | sed -e 's:[/]\+::g'`
	if test -z "${_lcname}"; then
		echo "The location name is \"/\" path."
		return 1
	fi
	F_AUTODEL_GLIST="${TF_AUTODELDIR}/${_lcname}.list.xml"
	F_AUTODEL_GLIST_BAK="${TF_AUTODELDIR}/${_lcname}.list.xml.bak"
	F_AUTODEL_BATCH="${TF_AUTODELDIR}/${_lcname}.set.xml"
	F_AUTODEL_BATCH_BAK="${TF_AUTODELDIR}/${_lcname}.set.xml.bak"

	rm -f ${F_AUTODEL_GLIST} ${F_AUTODEL_GLIST_BAK} ${F_AUTODEL_BATCH} ${F_AUTODEL_BATCH_BAK}
	find ${TF_AUTODELDIR} -name "${_lcname}\.del\.[0-9][0-9]*\.xml" -exec rm -f {} \;
	find ${TF_AUTODELDIR} -name "${_lcname}\.del\.[0-9][0-9]*\.xml\.bak" -exec rm -f {} \;

	return 0
}

