#!/bin/bash

set -e

GREP="env -i grep"

# we check how we are called. the only allowed mode is apache-modconf
# since apacheconfig* is now a symlink to this script to avoid
# full breakage of pkgs that did not migrate
# same goes for modules-config

CALL=`echo $0 | awk -F "/" '{print $NF}'`

if [ "$CALL" != "apache-modconf" ] && [ "$CALL" != "modules-config" ]; then
	echo "WARNING: Use of $CALL has been deprecated!"
	echo "apache-modconf should be used instead."
	exit 0
fi

#### global functions ####

go_out() {
	case "$1" in
	command)
		echo "Error: $0 has been called with invalid parameters"
		echo "Usage: $0 apache|apache-perl|apache-ssl [enable <module_name>]"
		echo "       $0 apache|apache-perl|apache-ssl [disable <module_name>] [quiet]"
		echo "       $0 apache|apache-perl|apache-ssl [query <module_name]"
	;;
	install)
		echo "Error: $FLA appears not to be installed"
	;;
	esac
	exit 1
}

restart() {
	if [ -x /usr/sbin/invoke-rc.d ]; then
		invoke-rc.d $FLA restart > /dev/null 2>&1 3>&1 || true
	else
		/etc/init.d/$FLA restart > /dev/null 2>&1 3>&1 || true
	fi
}

check_info_check_so() {

	# this should check if all the .so have an .info file
	# and viceversa

	err=0

	cd /usr/lib/apache/1.3/ && \
	for i in `ls *.so`; do \
		if [ ! "`$GREP $i$ *.info`" ]; then \
			echo Error: $i does not have a corresponding .info file.; \
			err=1; \
		fi; \
	done; \
	for i in `ls *.info`; do \
		if [ ! -e `head -n 1 $i | cut -d " " -f 3` ]; then \
			echo Error: $i does not have a valid LoadModule entry.; \
			err=1; \
		fi; \
	done;

	if [ "$err" = "1" ]; then
		echo "The above errors might cause $FLA to not work properly or start"
		echo "Please refer to the documentation on how to fix it or report it to"
		echo "Debian Apache Mailing List <debian-apache@lists.debian.org> if in doubt"
		echo "on how to proceed"
	fi
}

blacklist_modules() {
	# we need exceptions per flavour to avoid conflicts
	# NOTES:
	# mod_browser is an obsolete modules (imported from apacheconfig)
	# the others are -ssl and !-ssl conflicts

	 case "$FLA" in
	 	apache)
		BLACKLIST="mod_browser mod_auth_ssl mod_mime_ssl mod_log_config_ssl apache-ssl"
		;;
		apache-perl)
		BLACKLIST="mod_browser mod_auth_ssl mod_mime_ssl mod_log_config_ssl apache-ssl"
		;;
		apache-ssl)
		BLACKLIST="mod_browser mod_auth mod_mime mod_log_config mod_ssl"
		;;
	esac

	# removing blacklisted modules from the available list
	# and we need to care about 3 cases:
	# 1) it's the first and only one???
	# 2) it's in the middle of a list
	# 3) it's the last one

	list="$1"

	for i in $BLACKLIST; do
		list=`echo $list \
		| sed -e 's/^'$i'$//g' -e 's/'$i,'//g' -e 's/, '$i'$//g'`
	done

	# the list has a "," at the end that needs to be removed

	echo $list | sed -e 's/,$//g'
}

available_modules() {

	# this implies that ALL the modules MUST have an info file.
	# note that is called with LC_COLLATE=C to preserve the list order

	available=`\
		cd /usr/lib/apache/1.3/ &&\
		LC_COLLATE=C &&\
		ls *.info | sed -e 's/\.info$/,/g' -e 's/^...//g'`

	available=`blacklist_modules "$available"`

}

enabled_modules() {

	# we only consider httpd.conf and modules.conf. This should be enough
	# for everyone and users will still have total freedom to add whatever
	# they want.

	CONFFILES="/etc/$FLA/httpd.conf"
	if [ -e /etc/$FLA/modules.conf ]; then
		CONFFILES="$CONFFILES /etc/$FLA/modules.conf"
	fi

	# we should always working queue but enabled_modules is a read only function
	# so we just copy the file (modules.conf.dpkg-inst.queue will be regenerated)

	cp /etc/$FLA/httpd.conf /etc/$FLA/httpd.conf.dpkg-inst.queue

	# importing all the LoadModules lines that contain /usr/lib/apache/1.3
	# since they are supposed to be shipped by Debian with a proper .info file

	enabled=`\
		cat $CONFFILES | $GREP -v "#" | \
		sed -e 's/AddModule mod_perl.c/LoadModule perl_module \/usr\/lib\/apache\/1.3\/mod_perl.so/g' | \
		$GREP "/usr/lib/apache/1.3" | cut -d " " -f 3\
		| sed -e 's/\/usr\/lib\/apache\/1.3\///g' -e 's/\.so$//g' | sort -u`

	# this creates a map between the .so names found in the configfiles and
	# the .info since the names used for the .info have a meaning for the users

	cd /usr/lib/apache/1.3 && \
	for i in $enabled; do \
		mapped="`$GREP -l $i.so$ *.info | sed -e 's/\.info$/,/g' -e 's/^...//g'` $mapped"; \
	done

	# this enable or disable a module
	# note that the enable now checks if the module is already there
	# and take more appropriate actions such as not adding it twice
	# and goes in quite mode if already there.
	# disable is safe in all cases

	if [ "$CMD" = "enable" ]; then
		if [ ! "`echo $mapped | $GREP $MOD`" ]; then
			mapped=`echo $mapped $MOD`
		else
			QUIET=true
		fi
	fi

	if [ "$CMD" = "disable" ]; then
		mapped=`echo $mapped | sed -e 's/^'$MOD'$//g' -e 's/'$MOD,'//g' -e 's/, '$MOD'$//g'`
	fi

	if [ "$CMD" = "query" ]; then
		if [ "`echo $mapped | $GREP $MOD`" ]; then
			echo "$MOD"
		fi
		exit 0
	fi

	# the list has a "," at the end that needs to be removed

	enabled=`blacklist_modules "$mapped"`
}

## this is brutal but i don't think it can be solved otherwise

update_config() {
	TMP=/etc/$FLA/httpd.conf.tmp.$$

	# this will remove any reference to LoadModule inside httpd.conf
	# that should be installed by Debian (/usr/lib/apache/1.3) and
	# we do not touch the others.

	cat /etc/$FLA/httpd.conf.dpkg-inst.queue | $GREP -v "/usr/lib/apache/1.3" > $TMP

	LOADMOD=`$GREP -n "# Please keep this LoadModule: line here" $TMP \
		| cut -d ":" -f 1`
	
	# The echo swallows the return code from grep.
	INCLUDE=`$GREP -n "Include /etc/$FLA/modules.conf" \
		/etc/$FLA/httpd.conf.dpkg-inst.queue | cut -d ":" -f 1`

	# if we are converting from an old httpd.conf we need to insert the
	# Include /etc/$FLA/modules.conf

	if [ -z "$INCLUDE" -a -n "$LOADMOD" ]; then

		# this calculate the offsets on how to split httpd.conf

		LAST=`wc -l < $TMP`
		DIFF=`expr $LAST - $LOADMOD`

		# splitting the conf and insert the Include

		head -n $LOADMOD $TMP > /etc/$FLA/httpd.conf.dpkg-inst.queue
		echo "Include /etc/$FLA/modules.conf" >> /etc/$FLA/httpd.conf.dpkg-inst.queue
		tail -n $DIFF $TMP >> /etc/$FLA/httpd.conf.dpkg-inst.queue

	else

		# otherwise we just copy the config back

		cp -f $TMP /etc/$FLA/httpd.conf.dpkg-inst.queue

	fi

	rm -f $TMP
}

enable_config() {
	for i in httpd.conf modules.conf; do
		ucf --debconf-ok /etc/$FLA/$i.dpkg-inst.queue /etc/$FLA/$i
		rm -f /etc/$FLA/$i.dpkg-inst.queue
		if [ -e /etc/$FLA/$i.dpkg-dist ]; then
			if [ "`md5sum /etc/$FLA/$i.dpkg-dist | awk '{print $1}'`" = "`md5sum /etc/$FLA/$i | awk '{print $1}'`" ]; then
				rm -f /etc/$FLA/$i.dpkg-dist
			fi
		fi
	done
}

write_config() {

	# pain of upgrading from older config version of apache
	# we check both if modules.conf exists or if any reference inside
	# httpd.conf still exists and in case we update the config

	if [ ! "`$GREP -n "Include /etc/$FLA/modules.conf" /etc/$FLA/httpd.conf.dpkg-inst.queue`" ] || [ "`$GREP /usr/lib/apache/1.3 /etc/$FLA/httpd.conf.dpkg-inst.queue`" ]; then
		update_config
	fi

	# writing header
	echo "# Autogenerated file - do not edit!" > /etc/$FLA/modules.conf.dpkg-inst.queue
	echo "# This file is maintained by the $FLA package." >> /etc/$FLA/modules.conf.dpkg-inst.queue
	echo "# To update it, run the command:" >> /etc/$FLA/modules.conf.dpkg-inst.queue
	echo "#    /usr/sbin/apache-modconf $FLA" >> /etc/$FLA/modules.conf.dpkg-inst.queue

	# global fix to allign mod_perl priority when statically compiled

	# this section is common to all the flavours
	echo "ClearModuleList" >> /etc/$FLA/modules.conf.dpkg-inst.queue
	echo "AddModule mod_so.c" >> /etc/$FLA/modules.conf.dpkg-inst.queue
	echo "AddModule mod_macro.c" >> /etc/$FLA/modules.conf.dpkg-inst.queue

	# fullavailable contains XXX<modname>.info and for sure is sorted correctly
	# note: it seems like LC_COLLATE=C is enough to avoid resorting in ls.
	# The problem seems to be debconf that returns a random sorted $LIST
	# so we use a reversed approch starting from something known.

	cd /usr/lib/apache/1.3 && \
	fullavailable=`LC_COLLATE=C && ls *.info` && \
	for i in $fullavailable; do \
		temp=`echo $i | sed -e 's/\.info$//g' -e 's/^...//g'`; \
		if [ "`echo $LIST | $GREP $temp,`" ] || [ "`echo $LIST | $GREP $temp$`" ]; then \
			head -n 1 $i | sed -e 's/\://g' >> /etc/$FLA/modules.conf.dpkg-inst.queue ;\
		fi; \
	done; \
	if [ $FLA = apache-perl ]; then \
		cat /etc/$FLA/modules.conf.dpkg-inst.queue |\
		sed -e 's/.*mod_perl.so$/AddModule mod_perl.c/g' > /etc/$FLA/modules.conf.perlfix.dpkg-inst.queue; \
		mv -f /etc/$FLA/modules.conf.perlfix.dpkg-inst.queue /etc/$FLA/modules.conf.dpkg-inst.queue; \
	fi;
}

set_defaults() {

	# these are the defaults that we provide now
	# and realligned to be similar

	case "$FLA" in
		apache)
		enabled="mod_log_config, mod_mime_magic, mod_mime, mod_negotiation, mod_status, mod_autoindex, mod_dir, mod_cgi, mod_userdir, mod_alias, mod_rewrite, mod_access, mod_auth, mod_expires, mod_setenvif"
		;;
	apache-perl)
		enabled="mod_perl, mod_log_config, mod_mime_magic, mod_mime, mod_negotiation, mod_status, mod_autoindex, mod_dir, mod_cgi, mod_userdir, mod_alias, mod_rewrite, mod_access, mod_auth, mod_expires, mod_setenvif"
		;;
	apache-ssl)
		enabled="mod_log_config_ssl, mod_mime_magic, mod_mime_ssl, mod_negotiation, mod_status, mod_autoindex, mod_dir, mod_cgi, mod_userdir, mod_alias, mod_rewrite, mod_access, mod_auth_ssl, mod_expires, mod_setenvif, apache-ssl"
		;;
	esac

	# and of course at install phase we need to copy
	# the default configs

	if [ "$rollback" = "false" ]; then
		for i in httpd.conf access.conf srm.conf; do
		    cp /usr/share/apache/default-configs/$FLA/$i /etc/$FLA/$i.dpkg-inst.queue
		done
	fi
}

#### sanit(ar)y checks ####

FLA=$1

if [ "$FLA" != "apache" ] && [ "$FLA" != "apache-perl" ] && [ "$FLA" != "apache-ssl" ]; then
	go_out command
fi

if [ ! -d /etc/$FLA ]; then
	go_out install
fi

# "internal" should NEVER be used outside the apache* packages!
# also because it has no meaning for other packages or
# manual calls other than testing it

CMD=
ASKRESTART=true
QUEUECHANGES=false
if [ "$2" ]; then
	if [ "$2" != "enable" ] && [ "$2" != "disable" ] && [ "$2" != "internal" ] && [ "$2" != "query" ]; then
		go_out command
	fi
	CMD=$2

	case "$CMD" in
		internal)
			if [ "$3" = "quiet" ]; then
				QUIET=true
			fi
			ASKRESTART=false
			QUEUECHANGES=true
		;;
		*)
			if [ ! "$3" ]; then
				go_out command
			fi

			MOD=$3

			if [ "$CMD" = "disable" ]; then
				if [ "$4" = "quiet" ]; then
					QUIET=true
				fi
			fi
		;;
	esac
fi

### time to do some real work ####

check_info_check_so

available_modules

if [ -e /etc/$FLA/httpd.conf ]; then
	enabled_modules
else
	rollback=false
	set_defaults
fi

. /usr/share/debconf/confmodule
db_version 2.0
db_capb backup

db_subst apache-shared/debconf-modules choices $available
db_subst apache-shared/debconf-modules flavour $FLA
db_set apache-shared/debconf-modules $enabled

db_subst apache-shared/restart flavour $FLA

if [ "$QUIET" = "true" ]; then
	db_fset apache-shared/debconf-modules seen true
fi

db_input low apache-shared/debconf-modules || true

if [ "$QUIET" != "true" ]; then
	db_go || true
fi

db_get apache-shared/debconf-modules
LIST="$RET"
db_fset apache-shared/debconf-modules seen false

if [ "x$LIST" = "x" ]; then
	# if for a mistake the user selects NO modules we need
	# at least the defaults to be able to start
	rollback=true
	set_defaults
	LIST=$enabled
fi

write_config

# we enable the config only when we are executed in standalone
if [ "$QUEUECHANGES" = "false" ]; then
	enable_config
fi

if [ "$ASKRESTART" = "true" ]; then
	if [ "`pidof $FLA | awk '{print $0}'`" ]; then
		db_subst apache-shared/restart flavour $FLA
		if [ "$QUIET" = "true" ]; then
			db_fset apache-shared/restart seen true
		fi
		db_input low apache-shared/restart || true
	fi
fi

if [ "$QUIET" != "true" ]; then
	db_go || true
fi

if [ "$ASKRESTART" = "true" ]; then
	if [ "`pidof $FLA | awk '{print $0}'`" ]; then
		db_get apache-shared/restart
		REST="$RET"
		db_fset apache-shared/restart seen false
		if [ "$REST" = "true" ]; then
			restart
		fi
	fi
fi

exit 0
