#!/bin/sh

SQUID_CONF="/etc/squid/squid.conf"
SQUID_NETS="/etc/squid/our_networks"

_()
{
LANG=${in_language%%;*}.utf8 gettext "alterator-squid" "$1"
}

#turn off auto expansion
set -f

. /usr/share/alterator/build/backend3.sh

shell_add_or_subst()
{
	local name="$1" && shift
	local value="$1" && shift
	local file="$1" && shift

	[ -f "$file" ] || touch "$file"
	if grep -qs "^$name" "$file"; then
		/bin/sed -r -i "s,^$name.*,$name$value," -- "$file"
		return 0
	fi
	printf %s\\n "$name$value" >> "$file"
}

valid_range()
{
	local range="$1" && shift
	local EINVALMASK="Invalid mask"
	local EINVALIP="Invalid IP"
	local EINVALHOST="Invalid hostname"
	local error=`awk --re-interval "BEGIN {

		# should have only mask
		if (split(\"$range\", ip, /\//) > 2) {
			print \"$EINVALMASK\"
			exit
		}
		# mask is in 0..32
		if (ip[2] !~ /^[[:digit:]]+$/ || ip[2] < 0 || ip[2] > 32) {
			print \"$EINVALMASK\"
			exit
		}
		# give no mask for hostname or 32
		if (ip[1] ~ /[[:alpha:]]/) {
			if (ip[2] != \"\" && ip[2] < 32) {
				print \"$EINVALMASK\"
				exit
			}
			if (ip[1] ~ /^[[:alnum:].-]+$/) {
				print \"Ok\"
				exit
			}
			print \"$EINVALHOST\"
			exit
		}
		# should have four bytes in IP
		if (split(ip[1], ip, /\./) != 4) {
			print \"$EINVALIP\"
			exit
		}
		# check byte bounds
		for (i=1; i<=4; i++)
			if (ip[i] !~ /^[0-9]{1,3}$/ || ip[i] < 0 || ip[i] > 255) {
				print \"$EINVALIP\"
				exit
			}
		print \"Ok\"
	     }"`
	test "$error" != "Ok" && printf '(error "%s: %s")' "$(_ "$error")" "$range" && return 1
	return 0
}

on_message()
{
	case "$in_action" in
		constraints)
			echo '('
			case "$in_type" in
				listen)
					printf 'port (required #t match "^[[:digit:]]+$" label "%s")' "$(_ "Port")"
					printf 'host (ipv4-address #t label "%s")' "$(_ "Host")"
					;;
				*)
					printf 'port (label "%s")' "$(_ "Port")"
					printf 'host (label "%s")' "$(_ "Host")"
					printf 'range (label "%s")' "$(_ "Range")"
					printf 'domain (match "^\\\." label "%s")' "$(_ "Domain")"
					printf 'chkconfig (label "%s")' "$(_ "start, stop or restart service")"
					;;
			esac
			echo ')'
			;;
		list)
			echo '('
			case "$in__objects" in
			    listen)
			    sed -rn '/^http_port[[:space:]]+[^:[:space:]]+$/ {s,^http_port[[:space:]]+([^[:space:]]+).*,("=\1" host "" port "\1"),;p}' "$SQUID_CONF"
			    sed -rn '/^http_port[[:space:]]+[^[:space:]]+:/ {s,^http_port[[:space:]]+([^[:space:]]+):([^[:space:]]+).*,("\1=\2" host "\1" port "\2"),;p}' "$SQUID_CONF"
			    ;;
			    ournetworks)
			    sed -r 's,^[[:space:]]*([^[:space:]]+).*,(\"\1\" range \"\1\"),' "$SQUID_NETS"
			    ;;
			esac
			echo ')'
			;;
		read)
			echo '('
			sed -rn '/^cache_mgr[[:space:]]/ {s,^cache_mgr[[:space:]]+([^[:space:]]+).*,cachemgr "\1",;p}' "$SQUID_CONF" | tail -n1
			sed -rn '/^append_domain[[:space:]]/ {s,^append_domain[[:space:]]+([^[:space:]]+).*,domain "\1",;p}' "$SQUID_CONF" | tail -n1
			echo ')'
			;;
		write)
			[ -n "$in_domain" ] && shell_add_or_subst "append_domain" " $in_domain" "$SQUID_CONF"
			[ -n "$in_cachemgr" ] && shell_add_or_subst "cache_mgr" " $in_cachemgr" "$SQUID_CONF"
			service squid reload &> /dev/null ||:
			echo '()'
			;;
		new)
			case "$in_type" in
			    ournetworks)
			        if valid_range "$in_range"; then
			    	    if egrep -qs "^[[:space:]]*$in_range([[:space:]]|$)" "$SQUID_NETS"; then
					printf '(error "%s")' "$(_ "same network is already defined")"
			    	    else
					echo "$in_range" >> "$SQUID_NETS"
					# check if $SQUID_NETS file is accepted
					egrep -qs "^[[:space:]]*acl our_networks src \"$SQUID_NETS\"" "$SQUID_CONF" || \
					sed -i -e "s,^#[[:space:]]*acl our_networks src.*\$,acl our_networks src \"$SQUID_NETS\"," "$SQUID_CONF"
					egrep -qs '^[[:space:]]*http_access allow our_networks' "$SQUID_CONF" || \
					sed -i -e 's,^#[[:space:]]*http_access allow our_networks.*$,http_access allow our_networks,' "$SQUID_CONF"
					service squid reload &> /dev/null ||:
					echo '()'
			    	    fi
				fi
			    	;;
			    listen)
					if [ -n "$in_host" ]; then
						pair="$in_host:$in_port"
					else
						pair="$in_port"
					fi
			    	if egrep -qs "^http_port[[:space:]]+$pair([[:space:]]|$)" "$SQUID_CONF"; then
						printf '(error "%s")' "$(_ "same ip:port is already defined")"
			    	else
						echo "http_port $pair" >> "$SQUID_CONF"
						service squid reload &> /dev/null ||:
						echo '()'
			    	fi
			    ;;
			esac
			;;
		delete)
			if [  "$in__objects" != "/" ]; then
			    if [ "${in__objects%/*}" = "listen" ];then
					pair=${in__objects#*/}
					host=${pair%=*}
					port=${pair#*=}
					if [ -n "$host" ]; then
						sed -r "/^http_port[[:space:]]+$host:$port([[:space:]]|$)/ d" -i "$SQUID_CONF"
					else
						sed -r "/^http_port[[:space:]]+$port([[:space:]]|$)/ d" -i "$SQUID_CONF"
					fi
			    else
					range=${in__objects#*/}
					range=${range//\//\\/}
					sed -r "/^[[:space:]]*$range([[:space:]]|$)/ d" -i "$SQUID_NETS"
			    fi
			fi
			service squid reload &> /dev/null ||:
			echo '()'
			;;
		*)
			echo '#f'
			;;
	esac
}

message_loop
