#!/bin/sh -f

alterator_api_version=1
po_domain="alterator-ahttpd"
ahttpdconffile='/etc/ahttpd/ahttpd.conf'
ahttpdlogdir="/var/log/ahttpd"

servername="ahttpd"
certconffile="/etc/ahttpd/$servername.cnf"

rdelim='[[:space:]]\+'
wdelim='	'

. alterator-sh-functions
. shell-config
. cert-sh-functions

##############

ipv4num_re='\([1-9]\?[0-9]\|1[0-9]\{2\}\|2[0-4][0-9+]\|25[0-5]\)'
ipv4addr_re="$ipv4num_re[.]$ipv4num_re[.]$ipv4num_re[.]$ipv4num_re"
hostname_re='^[a-zA-Z_][.a-zA-Z0-9_-]*$'
country_re='^[a-zA-Z][a-zA-Z]$'
name_re='^[a-zA-Z_[:space:]]\+$'

config_get()
{
    shell_config_get "$ahttpdconffile" "$1" "$rdelim"
}

cert_get()
{
    shell_config_get "$certconffile" "$1"
}

config_set_simple()
{
    shell_config_set "$ahttpdconffile" "$1" "$2" "$rdelim" "$wdelim"
}

config_set()
{
    local name="$1";shift;
    local value="$1";shift;
    local re="$1";shift;
    local msg="${1:-invalid value}"

    if [ -n "$name" ];then
	if echo "$value"|grep -qs "$re"; then
	    config_set_simple "$name" "$value"
	else
	    write_error "$msg"
	    return 1
	fi
    fi
    return 0
}

cert_set()
{
    local name="$1";shift;
    local value="$1";shift;
    local re="$1";shift;
    local msg="${1:-invalid value}"

    if [ -n "$name" ];then
	if echo "$value"|grep -qs "$re"; then
	    shell_config_set "$certconffile" "$name" "$value"
	else
	    write_error "$msg"
	    return 1
	fi
    fi
    return 0
}

do_reload()
{
    sleep 1
    /sbin/service  ahttpd reload >/dev/null 2>/dev/null
}

sure_certconf()
{
    [ -f "$certconffile" ] && return

    local HOSTNAME="$(hostname)"
    HOSTNAME="${HOSTNAME:-localhost.localdomain}"

    echo "$DEFAULT_CERT" |
	sed -e "s|@HOSTNAME@|$HOSTNAME|" \
	    -e "s|@PRODUCT@|$servername|" \
	    -e "/^O=/ a C=RU\nL=Moscow\nOU=HTTP Interface\n" \
	    >"$certconffile"
}

create_cert()
{
     ssl_check_key "$@" || ssl_make_key "$@"
     ssl_check_req "$@" || ssl_make_req "$@"
     ssl_check_cert "$@" || ssl_make_cert "$@"
}

update_cert()
{
    local certfile="$SSL_CERTDIR/$servername.cert"
    local certfile_temp="$SSL_CERTDIR/$servername-temp.cert"
    local keyfile="$SSL_KEYDIR/$servername.key"
    local keyfile_temp="$SSL_KEYDIR/$servername-temp.key"
    local scrfile="$SSL_CSRDIR/$servername.csr"
    local scrfile_temp="$SSL_CSRDIR/$servername-temp.csr"

    (create_cert "$servername-temp" "$certconffile") &&
	mv -f "$certfile_temp" "$certfile" &&
	mv -f "$keyfile_temp" "$keyfile" &&
	mv -f "$scrfile_temp" "$scrfile"
}

on_message()
{
	case "$in_action" in
		list)
			case "$in__objects" in
			    avail_log_mode)
				write_enum_item "all" "`_ "all connections"`"
				write_enum_item "errors" "`_ "errors only"`"
				write_enum_item "none" "`_ "nothing"`"
				;;
			esac
			;;
		write)
			config_set server-port "$in_port" "$number_re" "invalid port" || return
			config_set server-host "$in_host" "$hostname_re" "invalid hostname" || return
			if [ "$in_listen" = '*' ];then
			    config_set_simple server-listen "$in_listen"
			else
			    config_set server-listen "$in_listen" "$ipv4addr_re" "invalid ipv4 address" || return
			fi
			config_set log-mode "$in_log_mode" '.*' "invalid log mode" || return
			;;
		reload)
			do_reload &
			;;
		read)
			sure_certconf

			write_string_param port "$(config_get server-port)"
			write_string_param host "$(config_get server-host)"
			write_string_param log_mode "$(config_get log-mode)"
			write_string_param listen "$(config_get server-listen)" #FIXME: write_bool_param

			write_string_param CN "$(cert_get CN)"
			write_string_param C "$(cert_get C)"
			write_string_param L "$(cert_get L)"
			write_string_param O "$(cert_get O)"
			write_string_param OU "$(cert_get OU)"

			;;
		recreate)
			sure_certconf

			cert_set "CN" "$in_CN" "$hostname_re" "invalid hostname" || return
			cert_set "C" "$in_C" "$country_re" "invalid country code" || return
			cert_set "L" "$in_L" "$name_re" "invalid location name" || return
			cert_set "O" "$in_O" "$name_re" "invalid organization name"  || return
			cert_set "OU" "$in_OU" "$name_re" "invalid organizational unit name" || return

			update_cert
			;;
		upload)
			local tempfile="$(mktemp -t cert.XXXXXX)"
			local certfile="$SSL_CERTDIR/$servername.cert"
			local keyfile="$SSL_KEYDIR/$servername.key"
			[ -n "$in_certificate" ] && echo "$in_certificate" >"$tempfile"

			if certvalidate "$tempfile" "$keyfile"; then
			    mv -f "$tempfile" "$certfile"
			    chmod 644 "$certfile"
			else
			    rm -f "$tempfile"
			    write_error "`_ "Invalid certificate file"`"
			fi
			;;
	esac
}

message_loop
