#!/bin/bash
#
# /usr/local/sbin/localezcreate
# Copyright 2001-2002 Jonas Smedegaard <dr@jones.dk>
#
# $Id: localezcreate,v 1.25 2003/04/25 04:07:17 jonas Exp $
#
# Create local eZ Publish site
#
# This script makes use of the Debian package wwwconfig-common if installed
#
# TODO: Ask for and set default language and theme
# TODO: Make a note about installed languages and themes (for smooth upgrades)
# TODO: Make md5 of all files (for smooth upgrades)
# TODO: Make script (mostly) work as noon-root
# TODO: Include all mail addresses in site.ini.override
# TODO: Add a --dry-run or --test option showing what would be done (how options are set, and a descriptive text about how they are used)

set -e

prg=`basename $0`

TEMP=`getopt -o hu:g:d:a:m:N:U:D:Z:i::v::q::f:: --long help,user:,group:,domain:,mailuser:,maildomain:,dbname:,dbuser:,dbserver:,dballow:,info::,verbose::,debug::,query::,force:: -n "$prg" -- "$@"`

# Check for non-GNU getopt
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

eval set -- "$TEMP"

# Defaults are evaluated at runtime in this order
# (If changing defaults, you might need to change these as well)
opts1="user group domain maildomain dbserver dballow templates languages sqlchunks templatedirs languagedirs sqldirs" # Options with self-contained defaults
opts2="dbuser home" # Options requiring $opts1 to resolve default
opts3="mailuser dbname basedir adminhost webcfg" # Options requiring $opts1, $opts2 or $host to resolve default
optsboolean="debug verbose info query force" # Do not touch these!

# Defaults
defaultuser="www-data"
defaultgroup="www-data"
defaultdomain="ez."`hostname -d`
defaultmailuser='$dbuser'
defaultmaildomain=`cat /etc/mailname 2> /dev/null || hostname -d`
defaultdbname='$dbuser_ez_$host'
defaultdbuser='$user'
defaultdbserver="localhost"
defaultdballow="localhost"
defaultinfo="on"
defaultverbose="off"
defaultdebug="off"
defaultquery="on"
defaultforce="off"

# Defaults not (yet) user configurable
defaulttemplates=""
defaultlanguages="en_GB en_GB_org"
defaultsqlchunks="publish data"
defaulthome="/var/www"
defaultbasedir='/var/www/ez-$host.$domain'
defaultadminhost='admin.$host.$domain'
defaultwebcfg='/etc/apache/vhosts.d/ez-$host.$domain'
defaulttemplatedirs="/usr/src/ezpublish/templates"
defaultlanguagedirs="/usr/src/ezpublish/lang"
defaultsqldirs="/usr/share/ezpublish/sql"

# Override defaults from config file if available
if [ -e /etc/local/localezcreate.conf ]; then
	. /etc/local/localezcreate.conf
fi

# These are unlikely to change
sourcedirs="/usr/src/ezpublish"
sources="lib data tpl www"
bindir="/usr/share/ezpublish/bin"

# This needs to exist from before parsing options
debug="off"

function usage() {
	echo "Usage: $prg [OPTION]... HOST [HOST]..."
	echo "Create local eZ Publish sites"
	echo
	echo "Mandatory arguments to long options are mandatory for short options too."
	echo "  -h, --help               Show this help"
	echo "  -u, --user=UID           System user id (default: $defaultuser)"
	echo "  -g, --group=GID          System group id (default: $defaultgroup)"
	echo "  -d, --domain=DOMAIN      Domain name with hostname stripped off (default:"
	echo "                             $defaultdomain)"
	echo "  -a, --mailuser=UID       User part (account) of mail address (default: $defaultmailuser)"
	echo "  -m, --maildomain=DOMAIN  Domain part of mail address (default:"
	echo "                             $defaultmaildomain)"
	echo "  -N, --dbname=DB          MySQL database name (default:"
	echo "                             $defaultdbname)"
	echo "  -U, --dbuser=UID         MySQL database user (default: $defaultdbuser)"
	echo "  -D, --dbserver=HOST      IP or host of MySQL server (default:"
	echo "                             $defaultdbserver)"
	echo "  -Z, --dballow=HOST       IP or host of eZ server (default:"
	echo "                             $defaultdballow)"
	echo "  -i, --info[=on|off]      Show info during installation (default: $defaultinfo)"
	echo "  -v, --verbose[=on|off]   Show details during installation (default: $defaultverbose)"
	echo "      --debug[=on|off]     Show debug during installation (default: $defaultdebug)"
	echo "  -q, --query[=on|off]     Ask for missing options (default: $defaultquery)"
	echo "  -f, --force[=on|off]     Replace existing installation (default: $defaultforce)"
	echo
	echo "Each HOST is a simple hostname, without the domain part."
	echo
	echo "MySQL password for \$dbuser can be stored in \$HOME/.my.cnf of \$user."
}

function setopts () {
	for opt in $@; do
		defaultvalue="`eval echo \$\{default$opt\}`"
		value="`eval echo \$\{$opt:-$defaultvalue\}`"
		if [ "$value" = '[[ASK]]' ]; then
			if [ -n "$query" ]; then
				echo -n "Enter value for $opt: "
				read value
				echo
			else
				echo "ERROR: value for $opt requested, but not running interactively!"
				exit 1
			fi
		fi
		if [ -z "$value" ]; then
			echo "ERROR: Value of \"$opt\" is empty!"
			exit 1
		fi
		eval $opt=\"$value\"
		if [ "$debug" = "1" -o "$debug" = "on" ]; then
			echo "----> $opt=\"$value\" (default: \"$defaultvalue\")"
		fi
	done
}

while true ; do
	case "$1" in
		-h|--help) usage; exit 0;;
		-u|--user) user="$2"; shift 2;;
		-g|--group) group="$2"; shift 2;;
		-d|--domain) domain="$2"; shift 2;;
		-a|--mailuser) mailuser="$2"; shift 2;;
		-m|--maildomain) maildomain="$2"; shift2 ;;
		-N|--dbname) dbname="$2"; shift 2;;
		-U|--dbuser) dbuser="$2"; shift 2;;
		-D|--dbserver) dbserver="$2"; shift 2;;
		-Z|--dballow) dballow="$2"; shift 2;;
		-i|--info) case "$2" in ""|on) info="on";; *) info="off";; esac; shift 2;;
		-v|--verbose) case "$2" in ""|on) verbose="on";; *) verbose="off";; esac; shift 2;;
		--debug) case "$2" in ""|on) debug="on";; *) debug="off";; esac; shift 2;;
		-q|--query) case "$2" in ""|on) query="on";; *) query="off";; esac; shift 2;;
		-f|--force) case "$2" in ""|on) force="on";; *) force="off";; esac; shift 2;;
		--) shift; break;;
		*) echo "Internal error!" ; exit 1 ;;
	esac
done

setopts $optsboolean
if [ "$debug" = "1" -o "$debug" = "on" ]; then
	verbose="on" # Debug implies verbose
fi
for boolean in $optsboolean; do
	case `eval echo \$\{$boolean\}` in
		on) eval $boolean="1";;
		off) eval $boolean="";;
		*) echo "ERROR: Value of boolean option \"$boolean\" must be \"on\" or \"off\"!"; exit 1;;
	esac
done
setopts $opts1
setopts $opts2
optdbserver="-p$dbserver"
if [ "$dbserver" = "localhost" ]; then
	optdbserver="" # Do not force TCP/IP access when connecting locally
fi

if [ -n "$verbose" ]; then
	echo "--> Figure out database users and passwords"
fi
if [ -z "$dbpass" ]; then
	if [ -f $home/.my.cnf ]; then
		dbpass=$(grep password $home/.my.cnf | awk -F= '{print $2}' | head -1 | sed 's/^ //g')
	fi
	if [ -z "$dbpass" ]; then
		if [ -n "$query" ]; then
			echo -n "Enter database password for MySQL user $dbuser: "
			read -s dbpass
			echo
		else
			echo "ERROR: Database password for MySQL $dbuser not found!"
			exit 1
		fi
	fi
fi
if [ -e /usr/share/wwwconfig-common/mysql-localadmpass.get -a "$dbserver" = "localhost" ] ; then
	status=""
	. /usr/share/wwwconfig-common/mysql-localadmpass.get
	if [ "$status" = "error" ] ; then
		if [ -n "$info" ]; then
			echo "--> $error"
		fi
	fi
fi
if [ -z "$dbadmin" ]; then
	if [ -n "$query" ]; then
		echo -n "Enter database administrator user (usually root): "
		read dbadmin
		echo
	else
		echo "ERROR: Database administrator user not resolved!"
		exit 1
	fi
fi
if [ -z "$dbadmpass" ]; then
	if [ -n "$query" ]; then
		echo -n "Enter database password for administrator $sbadmin: "
		read -s dbadmpass
		echo
	else
		echo "ERROR: Database password for administrator $dbadmin not found!"
		exit 1
	fi
fi

##############################################
# The rest of the script is host-specific... #
##############################################
for host do

if [ -n "$info" ]; then
	echo "Installing $host..."
fi

setopts $opts3

if [ -n "$verbose" ]; then
	echo "--> Check for existing installation"
fi
error=""
if [ -d $basedir ]; then
	if [ -n "$verbose" ]; then
		error="Target directory $basedir already exists."
	else
		error="Target directory already exists."
	fi
elif [ -f $webcfg ]; then
	if [ -n "$verbose" ]; then
		error="Apache config $webcfg already exists."
	else
		error="Apache config already exists."
	fi
fi
# TODO: Check for existing MySQL database
if [ -n "$error" ]; then
	if [ -n "$query" ]; then
		echo "WARNING: $error"
		echo -n "Overwrite existing installation (y/N)?: "
		read ack
		echo
		case $ack in
		    y|Y) force="1";;
		    *) echo "Installation aborted!"; exit 1;;
		esac
	fi
	if [ -n "$force" ]; then
		mysqladmin -u$dbadmin -p$dbadmpass $optdbserver -f drop $dbname
		rm -rf $basedir
		rm -f $webcfg
	else
		echo "ERROR: $error!"
		exit 1
	fi
fi

if [ -n "$verbose" -a "$dbhost" != "localhost" ]; then
	echo "--> Create database $dbname on $dbserver"
elif [ -n "$verbose" ]; then
	echo "--> Create database $dbname"
fi
if [ -e /usr/share/wwwconfig-common/mysql-createdb.sh ] ; then
	status=""
	. /usr/share/wwwconfig-common/mysql-createdb.sh
	if [ "$status" = "error" ] ; then
		echo "$error"
		exit 1
	fi
else
	# TODO: Purge existing database as the wwwconfig-common script does
	mysqladmin -u$dbadmin -p$dbadmpass $optdbserver create $dbname
fi

if [ -n "$verbose" ]; then
	echo "--> Create/update database user $dbuser"
fi
if [ -e /usr/share/wwwconfig-common/mysql-createuser.sh ] ; then
	status=""
	. /usr/share/wwwconfig-common/mysql-createuser.sh
	if [ "$status" = "error" ] ; then
		echo "$error"
		exit 1
	fi
	for h in `echo "localhost $dballow" | sort -u`; do
		echo "GRANT INDEX ON $dbname.* TO '$dbuser'@'$h';" | mysql -u$dbadmin -p$dbadmpass $optdbserver mysql
	done
else
	for h in `echo "localhost $dballow" | sort -u`; do
		echo "GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX ON $dbname.* TO '$dbuser'@'$h' IDENTIFIED BY '$dbpass';" | mysql -u$dbadmin -p$dbadmpass $optdbserver mysql
	done
fi

if [ -n "$verbose" ]; then
	echo -n "--> Fill the database: "
fi
for chunk in $sqlchunks; do
	if [ -n "$verbose" ]; then
		echo -n "$chunk "
	fi
	found=""
	sqlfile=${chunk}_mysql.sql
	for dir in $sqldirs; do
		if [ -f $dir/$sqlfile ]; then
			found="1"
			sqldir=$dir
			if [ -n "$debug" ]; then
				echo -n "($dir) "
			fi
			break
		fi
	done
	if [ "$found" = "1" ]; then
		if [ -e /usr/share/wwwconfig-common/mysql-exec.sh ] ; then
			status=""
			(cd $sqldir && . /usr/share/wwwconfig-common/mysql-exec.sh) || exit 1
			if [ "$status" = "error" ] ; then
				echo "$error"
				exit 1
			fi
		else
			cat $sqldir/$sqlfile | mysql -u$dbadmin -p$dbadmpass $optdbserver $dbname
		fi
	else
		if [ -n "$verbose" ]; then
			echo
		fi
		echo "ERROR: $chunk not found!"
		exit 1
	fi
done
if [ -n "$verbose" ]; then
	echo
	echo "--> Create base directory $basedir"
fi
mkdir $basedir
for area in source language template; do
	if [ -n "$verbose" ]; then
		echo -n "--> Unpacking $area files: "
	fi
	for tarball in `eval echo \$\{${area}s\}`; do
		if [ -n "$verbose" ]; then
			echo -n "$tarball "
		fi
		found=""
		for dir in `eval echo \$\{${area}dirs\}`; do
			if [ -f $dir/$tarball.tar.gz ]; then
				found="1"
				tarballdir=$dir
				if [ -n "$debug" ]; then
					echo -n "($dir) "
				fi
				break
			fi
		done
		if [ "$found" = "1" ]; then
			(cd $basedir && tar -xz -C $basedir -f $tarballdir/$tarball.tar.gz) || exit 1
		else
			if [ -n "$verbose" ]; then
				echo
			fi
			echo "ERROR: $area $tarball not found!"
			exit 1
		fi
	done
	if [ -n "$verbose" ]; then
		echo
	fi
done

if [ -n "$verbose" ]; then
	echo "--> Configuring website"
fi
(cd $basedir && $bindir/modfix.sh >/dev/null) || exit 1 # TODO: Check if these are in sync and disable one of them
(cd $basedir && $bindir/secure_modfix.sh $user $group >/dev/null) || exit 1
mkdir -p $basedir/override
echo "[site]
SiteURL=$host.$domain
AdminSiteURL=$adminhost
UserSiteURL=$host.$domain
SiteTitle=$host eZ site
Keywords=$host $maildomain
SiteAuthor=someone at $maildomain
SiteCopyright=someone &copy; 2001
SiteDescription=a web application suite
SiteKeywords=Content Management System, CMS, e-commerce
Database=$dbname
User=$dbuser
Server=$dbserver
Password=$dbpass

[eZUserMain]
DefaultCountry=58

[eZTradeMain]
OrderSenderEmail=$mailuser@$maildomain
OrderReceiverEmail=$mailuser@$maildomain
mailToAdmin=$mailuser@$maildomain
ForceSSL=disabled
ApacheUser=UserApacheRunsAs

[eZForumMain]
ReplyAddress=$mailuser@$maildomain
" > $basedir/override/site.ini.append

chown -R $user:$group $basedir

if [ -n "$verbose" ]; then
	echo "--> Configuring Apache"
fi
echo "# Generated by $prg
<VirtualHost *>
	ServerName	$host.$domain
	ServerAdmin	$mailuser@$maildomain
	DocumentRoot	$basedir
	user		$user
	group		$group
	<Directory $basedir>
		Options		FollowSymLinks
		AllowOverride	None 
	</Directory>
	php_flag	magic_quotes_gpc off
	RewriteEngine	On
	RewriteRule	^/stats/store/(.*).gif\$ $basedir/ezstats/user/storestats.php [S=4]
	RewriteRule	^/filemanager/filedownload/([^/]+)/(.*)\$ $basedir/ezfilemanager/files/\$1 [T=\"application/oct-stream\",S=3]
	RewriteRule	.*/ezmediacatalogue/catalogue/(.*)\$ $basedir/ezmediacatalogue/catalogue/\$1 [T=\"application/oct-stream\",S=2]
	RewriteRule	^/xmlrpc.*\$  $basedir/index_xmlrpc.php [S=1]
	RewriteRule	!\.(gif|css|jpg|png|jar|wbmp)\$ $basedir/index.php
</VirtualHost>
<VirtualHost *>
	ServerName	$adminhost
	ServerAdmin	$mailuser@$maildomain
	DocumentRoot	$basedir
	user		$user
	group		$group
	<Directory $basedir>
		Options		FollowSymLinks
		AllowOverride	None 
	</Directory>
	php_flag	magic_quotes_gpc off
	RewriteEngine	On
	RewriteRule	.*/ezmediacatalogue/catalogue/(.*)\$ $basedir/ezmediacatalogue/catalogue/\$1 [T=\"application/oct-stream\",S=1]
	RewriteRule     !\.(gif|css|jpg|png|jar|wbmp) $basedir/index_admin.php
</VirtualHost>
<VirtualHost *>
	ServerName	www.$host.$domain
	RewriteEngine	On
	RewriteRule	/ http://$host.$domain/ [R]
	TransferLog	/dev/null
</VirtualHost>" > $webcfg

done

if [ -n "$info" ]; then
	echo "All done! (Remember to reload the webserver...)"
fi
