#!/bin/sh -f

squid_conf="/etc/squid/squid.conf"
network_conf="/etc/squid/our_networks"
black_conf="/etc/squid/blacklist"

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

alterator_api_version=1

. alterator-sh-functions
. shell-config
. shell-quote

squid_conf_get()
{
    shell_config_get  "$squid_conf" "$1" "$rdelim"|head -n1
}

squid_conf_set()
{
    shell_config_set "$squid_conf" "$1" "$2" "$rdelim" "$wdelim"
}

squid_conf_del()
{
    shell_config_del "$squid_conf" "$1" "$rdelim"
}

list_all()
{
    cat "$1"
}

list_has()
{
    grep -qs "^$(quote_sed_regexp "$2")\$" "$1"
}

list_add()
{
	printf "$2\n" >>"$1"
}

list_del()
{
    sed \
	-e "/^$(quote_sed_regexp "$2")\$/ d" \
	-i "$1"
}

tcp_port_mask="^[0-9]+$"
network_mask="^([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])([.]([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9+]|25[0-5])){3}/([1-9]|[12][0-9]|3[0-1])$"

# initial hacks

# enable our_networks rule
grep -qs "^[[:space:]]*acl our_networks src \"$network_conf\"" "$squid_conf" ||
    sed "s/^#[[:space:]]*acl our_networks src.*\$/acl our_networks src \"$(quote_sed_regexp "$network_conf")\"/" \
	-i "$squid_conf"

grep -qs "^[[:space:]]*http_access allow our_networks" "$squid_conf" ||
    sed "s/^#[[:space:]]*http_access allow our_networks.*$/http_access allow our_networks/" \
	-i "$squid_conf"

# enable blacklist
grep -qs "^[[:space:]]*acl blacklist url_regex \"$black_conf\"" "$squid_conf" ||
    sed "/# INSERT YOUR OWN RULE/ a \
	acl blacklist url_regex \"$black_conf\"\nhttp_access deny blacklist" \
	-i "$squid_conf"

on_message()
{
	case "$in_action" in
		constraints)
		    printf '%s (label "%s" match ("%s" "%s"))\n' http_port_number "`_ "Port:"`" "$tcp_port_mask" "`_ "invalid TCP port"`" >&3
		    printf '%s (label "%s" ipv4-address #t)\n'   http_port_host "`_ "Listen address:"`" >&3
		    printf '%s            (hostname #t)\n'       black >&3
		    printf '%s (label "%s" hostname #t)\n'       new_black "`_ "Blocked sites:"`" >&3
		    printf '%s            (match ("%s" "%s"))\n' network "$network_mask" "`_ "invalid IP network specification"`" >&3
		    printf '%s (label "%s" match ("%s" "%s"))\n' new_network "`_ "Allowed client networks:"`" "$network_mask" "`_ "invalid IP network specification"`" >&3
		    printf '%s (label "%s" hostname #t)\n'       append_domain "`_ "Search domain:"`" >&3
		    ;;
		list)
		    case "$in__objects" in
			avail_network)  list_all "$network_conf"|write_enum;;
			avail_black) list_all "$black_conf"|write_enum;;
		    esac
		    ;;
		read)
		    local http_port="$(squid_conf_get http_port)"
		    local http_port_number="${http_port##*:}"
		    local http_port_host="${http_port%:*}"
		    [ "$http_port_host" != "$http_port_number" ] || http_port_host=""

		    write_string_param http_port_host "$http_port_host"
		    write_string_param http_port_number "$http_port_number"

		    local append_domain="$(squid_conf_get append_domain)"
		    write_string_param append_domain "${append_domain#.}"

		    write_string_param cache_mgr "$(squid_conf_get cache_mgr)"
		    ;;
		write)
		    if [ -n "$in_general" ];then
			local http_port="$in_http_port_number"
			[ -z "$in_http_port_host" ] || http_port="$in_http_port_host:$http_port"
			[ -z "$http_port" ] || squid_conf_set http_port "$http_port"

			[ -z "$in_cache_mgr" ] || squid_conf_set cache_mgr "$in_cache_mgr"

			if [ -n "$in_append_domain" ] ;then
			    squid_conf_set append_domain ".$in_append_domain"
			else
			    squid_conf_del append_domain
			fi
		    elif [ -n "$in_add_network" -a -n "$in_new_network" ]; then
			if list_has "$network_conf" "$in_new_network";then
			    write_error "`_ "Same entry already exists"`"
			else
			    list_add "$network_conf" "$in_new_network"
			fi
		    elif [ -n "$in_del_network" -a "$in_network" ];then
			list_del "$network_conf" "$in_network"
		    elif [ -n "$in_add_black" -a -n "$in_new_black" ];then
			if list_has "$black_conf" "$in_new_black"; then
			    write_error "`_ "Same entry already exists"`"
			else
			    list_add "$black_conf" "$in_new_black"
			fi
		    elif [ -n "$in_del_black" -a -n "$in_black" ];then
			list_del "$black_conf" "$in_black"
		    fi
		    ;;
	esac
}

message_loop
