#!/bin/bash
#
# VERSION=13
# CHANGES="if php-cgi-guard is missing, run lighttpd on a tmpfs copy of lighttpd.conf with plain php-cgi; mark update mode for the guard"

# global variables #
export PATH='/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/bin:/usr/local/sbin:/usr/fallback'
BEROCONF=/usr/fallback/beroconf

export OPENSSL_CONF=/usr/local/ssl/openssl.cnf

# functions #
function log {
	prefix="[init_lighttpd]"

	if [ -z "${2}" ]; then
		echo "${prefix} ${1}"
	else
		echo "${prefix} ${1}" >> ${2}
	fi
}

function fix_conf {

	HTTP_CONF=/etc/lighttpd.conf
	HTTP_INIT=/etc/init.d/S60httpd

	HTTP_CONF_CONT=$(cat ${HTTP_CONF})

	CHANGED=0

	# check if mod_fastcgi is still enabled
	grep "mod_fastcgi" ${HTTP_CONF} > /dev/null
	res0=${?}

	# check if certificate is mentioned in lighttpd.conf
	grep "/usr/conf/berofix.pem" ${HTTP_CONF} > /dev/null
	res1=${?}

	# remove dependency to mod_fastcgi, if it isn't available.
	if [ ! -f /usr/lib/mod_fastcgi.so ] && [ "${res0}" = "0" ]; then
		HTTP_CONF_CONT=$(echo "${HTTP_CONF_CONT/\"mod_fastcgi\", /}")
		CHANGED=1
	fi

	# is cert mentioned in conf?
	if [ "${res1}" = "0" ]; then
		# pem-file does not exist, we remove the section
		if [ ! -f /etc/lighttpd.pem ]; then
			HTTP_CONF_CONT=$(echo "${HTTP_CONF_CONT/\$SERVER\[\"socket\"\] == \":443\" \{*\}/}")
			HTTP_CONF_CONT=$(echo "${HTTP_CONF_CONT/\#VERSION=6/\#VERSION=4}")
			CHANGED=1
		fi
	fi

	# if content of lighttpd.conf has changed, write it to disk.
	# remove the VERSION-file cause this is a non-version-change.
	if [ "${CHANGED}" = "1" ]; then
		mount -oremount,rw /
		echo "${HTTP_CONF_CONT}" > ${HTTP_CONF}
		sync; sleep 1; sync
		mount -oremount,ro /
	fi
}

function check_pem {
	HTTP_PEM=/usr/conf/berofix.pem
	HTTP_PEM_BACKUP=/etc/lighttpd.pem
	if /usr/local/bin/openssl version 2>&1 >/dev/null; then
		openssl x509 -in ${HTTP_PEM} -noout -text &> /dev/null	
		res0=${?}

		openssl rsa -in ${HTTP_PEM} -check &>/dev/null 
		res1=${?}
		if [[ ! "${res0}" = "0" ]] && [[ ! "${res1}" = "1" ]]; then
			echo "1" > /tmp/error_certificate.log
			rm -f ${HTTP_PEM}
		fi

		cert=$(openssl x509 -noout -modulus -in ${HTTP_PEM} | openssl md5)
		privkey=$(openssl rsa -noout -modulus -in ${HTTP_PEM} | openssl md5)
		if [ ! "${cert}" = "${privkey}" ]; then
			echo "1" > /tmp/error_certificate.log
			rm -f ${HTTP_PEM}
		fi
	else
		## openssl not working
		## remove VERSION.openssl to be reinstalled
		mount -o remount,rw /
		rm -f /pkginfo/VERSION.openssl
		mount -o remount,ro /
		${BEROCONF} set root TLSv1.2-disabled ERROR_TLS_DISABLED
	fi
	if [ ! -f ${HTTP_PEM} ]; then
		ln -s ${HTTP_PEM_BACKUP} ${HTTP_PEM} &> /dev/null
	fi
}

# lighttpd.conf runs .php through php-cgi-guard, which ships in this package.
# Should the guard be missing or not run (broken install), lighttpd would answer
# every PHP page with 500 and the GUI - including the update tool needed to
# repair the device - would be gone. Then start lighttpd on a runtime copy in
# tmpfs whose cgi.assign points at php-cgi itself, and say so in the log.
# /etc/lighttpd.conf stays as shipped and this is decided again on every start
# (boot, S60httpd restart): once the guard works again, the shipped config is
# used. enter-flashmode.sh picks up the runtime copy if it exists.
# Sets HTTP_RUN_CONF to the config lighttpd is to be started with.
HTTP_RUN_CONF=/etc/lighttpd.conf
HTTP_NOGUARD_CONF=/tmp/lighttpd-noguard.conf
function check_php_guard {
	HTTP_CONF=/etc/lighttpd.conf
	PHP_GUARD=/usr/bin/php-cgi-guard
	PHP_CGI=/usr/bin/php-cgi
	LOG_FILE=/usr/conf/permlog/lighttpd-php-cgi-guard.log

	HTTP_RUN_CONF=${HTTP_CONF}
	rm -f ${HTTP_NOGUARD_CONF}

	grep -q "\"${PHP_GUARD}\"" ${HTTP_CONF} || return 0

	# the guard passes argv on to php-cgi, so -v runs both
	if [ -x ${PHP_GUARD} ] && ${PHP_GUARD} -v 2>/dev/null | grep -q '^PHP '; then
		return 0
	fi

	log "WARNING: ${PHP_GUARD} missing or not working, running .php through ${PHP_CGI} directly"
	log "$(date): ${PHP_GUARD} missing or not working, lighttpd started on ${HTTP_NOGUARD_CONF} (.php -> ${PHP_CGI})" ${LOG_FILE}
	logger -t S60httpd "${PHP_GUARD} missing or not working, lighttpd started on ${HTTP_NOGUARD_CONF} (.php -> ${PHP_CGI})" 2>/dev/null
	# noclobber: never write through a file or link someone put there since the rm
	if ( umask 022; set -C; sed "s:\"${PHP_GUARD}\":\"${PHP_CGI}\":" ${HTTP_CONF} > ${HTTP_NOGUARD_CONF} ); then
		HTTP_RUN_CONF=${HTTP_NOGUARD_CONF}
	else
		log "WARNING: could not write ${HTTP_NOGUARD_CONF}, starting with ${HTTP_CONF}"
		log "$(date): could not write ${HTTP_NOGUARD_CONF}, started with ${HTTP_CONF}" ${LOG_FILE}
		rm -f ${HTTP_NOGUARD_CONF}
	fi
}

# php-cgi-guard lets /cgi-bin/update-tool.php take an upload without a GUI
# session only in update mode. The mode is fixed at boot (every switch into or
# out of it reboots), so mark it here, in tmpfs, for the guard to find.
function mark_update_mode {
	FWUPDATE_MARKER=/tmp/fwupdate.active

	rm -f ${FWUPDATE_MARKER}
	if [ "$(${BEROCONF} get root boot_fwupdate | grep -v failed)" = "1" ]; then
		touch ${FWUPDATE_MARKER}
	fi
}

function startFallback() {
	log "Starting lighttpd from fallback"
	mount -oremount,rw /
	## removing modules with openssl required and moving the backups
	rm -f /usr/lib/mod_authn_file.so
	cp /usr/fallback/lib/mod_authn_file.so /usr/lib
	## remove VERSION.openssl, VERSION.curl and VERSION.lighttpd to be reinstalled
	rm -f /pkginfo/VERSION.curl
	rm -f /pkginfo/VERSION.lighttpd
	rm -f /pkginfo/VERSION.openssl
	mount -oremount,ro /
	## running the fallback lighttpd
	/usr/fallback/lighttpd -f /usr/fallback/lighttpd.conf
}

# main #
case ${1} in
	start)
		fix_conf
		check_pem
		check_php_guard
		mark_update_mode

		## recovery mode and openssl issue => starting fallback
		if [[ "$(${BEROCONF} get root boot_recoverymode | grep -v PHP)" = "1" ]] && [[ ! "$(${BEROCONF} get root TLSv1.2-disabled | grep -v failed)" = "" ]]; then
			startFallback
			exit 0
		fi

		## testing lighttpd binary
		if ! /usr/bin/lighttpd -v; then
			log "lighttpd does not work. rebooting in recovery-mode"
			## lighttpd does not work. reboot in recovery-mode with a warning message
			${BEROCONF} set root boot_recoverymode 1
			${BEROCONF} set root TLSv1.2-disabled ERROR_TLS_DISABLED
			/sbin/reboot
			exit 0
		fi

		log "Starting lighttpd."
		lighttpd -f ${HTTP_RUN_CONF}
		;;
	stop)
		log "Stopping lighttpd."
		killall lighttpd
		;;
	restart)
		${0} stop
		${0} start
		;;
	*)
		echo "Usage: ${0} {start|stop|restart}" >&2
		exit 1
		;;
esac
