#! /bin/bash
# FusionForge Installation Dependency Setup
#
# Copyright 2006 GForge, LLC
# Copyright 2011 Christian Bayle <bayle@debian.org>
# Copyright 2014, Franck Villaume - TrivialDev
# http://fusionforge.org/
#
# @version
#
# This file is part of GInstaller, it is called by install.sh.
#
# FusionForge is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# FusionForge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with FusionForge; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

PG_VERSIONS="8.3 8.4 9.0 9.1 9.2 9.3 9.4"

msg(){
	GREEN="[01;32m"
	NORMAL="[00m"
	RED="[01;31m"
	if [ "$1" = "noreturn" ]
	then
		extra="-n"
		shift
	else
		extra=""
	fi
	color=$1 ; shift
	case $color in
		red)
			echo $extra "$RED $1 $NORMAL"
			;;
		green)
			echo $extra "$GREEN $1 $NORMAL"
			;;
	esac
}

create_db_admin_user(){
	gforge_db="$1"
	admin_user="$2"
	su - postgres -c "psql $gforge_db -c \"INSERT INTO users (user_name, realname, firstname, lastname, email, user_pw, unix_pw, status, theme_id) VALUES ('$admin_user', 'Forge Admin', 'Forge', 'Admin', 'root@localhost.localdomain', 'INVALID', 'INVALID', 'A', (SELECT theme_id FROM themes WHERE dirname='funky')); INSERT INTO pfo_user_role (user_id, role_id) VALUES (currval('users_pk_seq'), 3)\""
}

find_psql_init(){
	initpsql="/etc/init.d/postgresql"
	for v in $PG_VERSIONS ; do
	    initpsql="$initpsql postgresql-$v"
	done
	initpsql="$initpsql /etc/init.d/cswpostgres"
	for i in $initpsql
	do
		if [ -f $i ]
		then
			pgservice=$i
		fi
	done
	if [ -z "$pgservice" ]
	then
		msg red "Error: Looks like postgresql is not installed. Die here."
		exit 1
	fi
}
		
psql_startdb(){
	# Fedora9 (an maybe newer) requires running initdb
	if [ "$pgservice" = '/etc/init.d/postgresql' ]
	then
		if [ ! -d /var/lib/pgsql/data/base ]
		then
			service postgresql initdb &>/dev/null
		fi
	fi

	# Might fail if it's already running, so we'll ingnore the result
	$pgservice start
}

psql_stopdb(){
	# Fedora9 (an maybe newer) requires running initdb
	if [ "$pgservice" = '/etc/init.d/postgresql' ]
	then
		if [ ! -d /var/lib/pgsql/data/base ]
		then
			service postgresql initdb #&>/dev/null
		fi
	fi

	# Might fail if it's already running, so we'll ingnore the result
	$pgservice stop
}

get_config(){
	if [ ! -d "$fusionforge_src_dir" ]
	then
		msg red "Error: $fusionforge_src_dir folder doesn't exist. Run install2 first."
		exit 2
	fi
}

# Where the pghba config file is
find_pghba(){
	pghbafile="/var/lib/pgsql/data/pg_hba.conf"
	for v in $PG_VERSIONS ; do
	    pghbafile="$pghbafile /etc/postgresql/$v/main/pg_hba.conf"
	done
	pghbafile="$pghbafile /opt/csw/var/pgdata/pg_hba.conf"
	for i in $pghbafile
	do
		if [ -f $i ]
		then
			pghba="$i"
		fi
	done
	if [ -z "$pghba" ]
	then
		msg red "ERROR: Could not find pg_hba.conf file"
		exit 1
	fi
}

forge_save_db_config(){
	if [ -z "$FFORGE_DB" ]
	then
		while test -z "$FFORGE_DB"
		do
			msg noreturn green "* Enter the Database Name (fusionforge): "
			read FFORGE_DB
		done
	fi
	gforge_db="$FFORGE_DB"
	msg green " ...using $gforge_db"

	if [ -z "$FFORGE_USER" ]
	then
		while test -z "$FFORGE_USER"
		do
			msg noreturn green "* Enter the Database Username (gforge): "
			read FFORGE_USER
		done
	fi
	gforge_user="$FFORGE_USER"
	msg green " ...using $gforge_user"

	if [ ! -d "$fusionforge_etc_dir" ]
	then
		mkdir $fusionforge_etc_dir
	fi
	if [ ! -d "$fusionforge_etc_dir/config.ini.d" ]
	then
		mkdir $fusionforge_etc_dir/config.ini.d
	fi
	
	msg green " * Saving database configuration in FForge config file"
	if [ ! -f "$fusionforge_etc_dir/config.ini.d/rpm-install.ini" ]
	then
		cat > $fusionforge_etc_dir/config.ini.d/rpm-install.ini <<-EOF
; You can edit the values here or move them to other files.
[core]
forge_name=FusionForge
web_host=`hostname -f`

; This file was generated by the RPM installation system.
EOF
	fi

	if [ ! -f "$fusionforge_etc_dir/config.ini.d/rpm-install-secrets.ini" ]
	then
		if [ -c /dev/urandom ]; then  # ...using /dev/urandom when possible
			sk=$(dd if=/dev/urandom count=1 bs=16 2> /dev/null | md5sum | cut -c-32)
		else
			sk=$(date +"%s:%N" | md5sum | cut -c-32)
		fi

		cat > $fusionforge_etc_dir/config.ini.d/rpm-install-secrets.ini <<-EOF
; You can edit the values here or move them to other files.
; These values should not go into world-readable files!

[core]
database_host=""
database_name=$gforge_db
database_user=$gforge_user
database_port=5432
; database_password=""

session_key=$sk
; This file was generated by the RPM installation system.
EOF
	fi
	msg green " * Saving installation log in /tmp/gforge-import.log"
}

dropdbifexists()
{
	if [ -z "$1" ]
	then
		export PATH=$PATH:$fusionforge_bin_dir:$fusionforge_dir/utils
		database=`FUSIONFORGE_NO_PLUGINS=true forge_get_config database_name`
	else
		database=$1
	fi
	if [ -z "$database" ]
	then
        	echo "Forge database name not found"
		find_psql_init
		psql_stopdb
		psql_startdb
	else
		find_psql_init
		psql_stopdb
		sleep 5
		psql_startdb
		sleep 5
		echo "Droping database $database"
		su - postgres -c "dropdb -e $database"
	fi
}

installandrundb()
{
	# USING $gforge_user, $gforge_db, $pghba, $fusionforge_src_dir, $fusionforge_etc_dir, $tsearch, $pgservice, $STDIN, $STDOUT;
	msg green " * Modifying DB Access Permissions..."
	
	if [ ! -f $pghba.fforge.backup ]
	then 
		cp $pghba $pghba.fforge.backup
	fi
	cat > $pghba <<-EOF
# FUSIONFORGE
local all all trust
host all all 127.0.0.1/32 trust
EOF
	msg green " * Restarting PostgreSQL..."
	$pgservice stop
	$pgservice start

	msg green " * Creating $gforge_user Group..."
	/usr/sbin/groupadd $gforge_user;

	msg green " * Creating '$gforge_user' User..."
	/usr/sbin/useradd -m -g $gforge_user $gforge_user
	
	# Let's give some time for PostgreSQL to start
	sleep 5 

	msg green " * Creating Database User $gforge_user..."
	su - postgres -c "createuser -A -R -d -E $gforge_user"

	msg green " * Creating Language..."
	su - postgres -c "createlang plpgsql template1"

	if [ -d /home/$gforge_user ]
	then
		susufix=''
	else
		susufix='- -s /bin/sh'
	fi

	msg green " * Creating $gforge_db Database..."
	su $susufix $gforge_user -c "createdb $dboption --encoding UNICODE $gforge_db"

	# Enable plpgsql language
        if [ -f /usr/bin/createlang ]
        then
                if [ `su -s /bin/sh postgres -c "/usr/bin/createlang -l $gforge_db | grep plpgsql | wc -l"` != 1 ]
                then
                        su -s /bin/sh postgres -c "/usr/bin/createlang plpgsql $gforge_db"
                else
                        echo "Procedural language on $gforge_db already enabled"
                fi
        else
                echo "No way found to enable plpgsql on $gforge_db here" 
        fi

	# Detect postgresql version, require at least 8.3
	pgv=
	for i in postgres psql ; do
	    if [ "$(type -p $i)" != '' ] ; then
		pgv=$($i --version | cut -d" " -f3)
	    fi
	done
	if [ "$pgv" = '' ] ; then
		msg red "Error: Can't find command-line PostgreSQL client."
		exit 2
	fi	    
	case $pgv in
		7.*|8.1*|8.2*)
			msg red " * Unsupported PostgreSQL version; 8.3 or later is required"
			exit 2
			;;
	esac

	msg green " * Loading FusionForge DB"
	su $susufix $gforge_user -c "psql $gforge_db < $fusionforge_dir/db/gforge.sql" >> /tmp/gforge-import.log 2>&1

	msg green " * Running php db/upgrade-db.php"
        if ! php $fusionforge_src_dir/db/upgrade-db.php >> /tmp/gforge-upgrade.log ; then
		msg red "upgrade-db.php failed."
		exit 1
	fi

	if [ -z "$FFORGE_ADMIN_USER" ]
	then
		while test -z "$FFORGE_ADMIN_USER"
		do
			msg noreturn green " * Enter the Admin Username (fforgeadmin): "
			read FFORGE_ADMIN_USER
		done
	fi
	admin_user=$FFORGE_ADMIN_USER
	msg green " ...using $admin_user"

	if [ -z "$FFORGE_ADMIN_PASSWORD" ]
	then
		retry=5
		while test -z "$FFORGE_ADMIN_PASSWORD" -a $retry -gt 0
		do
			msg noreturn green " * Enter the Site Admin Password:"
			read -s FFORGE_ADMIN_PASSWORD1
			if validatePassword "$FFORGE_ADMIN_PASSWORD1"
			then
				msg noreturn green " * Please enter it again:"
				read -s FFORGE_ADMIN_PASSWORD2
				if [ "$FFORGE_ADMIN_PASSWORD1" = "$FFORGE_ADMIN_PASSWORD2" ]
				then
					FFORGE_ADMIN_PASSWORD="$FFORGE_ADMIN_PASSWORD1"
				else
					msg green "Passwords don't match. Please try again."
				fi
			fi
			retry=`expr $retry - 1`
		done
		if [ -z "$FFORGE_ADMIN_PASSWORD" ]
		then
			msg green "Passwords didn't match! Aborting."
			exit 1
		else
			create_db_admin_user "$gforge_db" "$admin_user"
			$fusionforge_src_dir/utils/forge_set_password "$admin_user" "$FFORGE_ADMIN_PASSWORD"
		fi
	else
		create_db_admin_user "$gforge_db" "$admin_user"
		$fusionforge_src_dir/utils/forge_set_password "$admin_user" "$FFORGE_ADMIN_PASSWORD"
	fi
}

validatePassword() {
	password="$1"
	strlen=`echo "$1" | wc -m`
	if [ $strlen -le 7 ]
	then
		msg red "Password is too short. Please try again"
		return 1
	fi
        CHECK=`echo $password | grep -E "[[:alnum:]]*"`
        if [ "$CHECK" = "" ]
        then
                msg red "Password contains invalid characters. Please try again."
		return 2
	else
		return 0
        fi
}

install3_db(){
	msg green "-=# Welcome to FusionForge DB-Installer #=-"
	find_psql_init
	psql_startdb
	get_config
	find_pghba
	forge_save_db_config
	installandrundb
	msg green "Done."
}

install3_db_redhat()
{
	export dboption="--template=template0"
	install3_db
}

install3_db_suse()
{
	install3_db
}

install3_db_debian()
{
	export dboption="--template=template0"
	install3_db
}

install3_db_ubuntu()
{
	export dboption="--template=template0"
	install3_db
}

install3_db_unknown()
{
	echo "Install 3 db not implemented"
}
