#!/bin/bash

# debian-edu-router_refresh-generated-ips: Generated .generated filterlists
# from .ldap, .dist, .org, and .local Proxy*SiteIP filterlists.
# See Debian Edu Router Plugin: Content filter.
# Documentation can be found under: /usr/share/doc/debian-edu-router*/

# Copyright (C) 2024 Pädagogisches Landesinstitut Rheinland-Pfalz
# Copyright (C) 2024 Daniel Teichmann <daniel.teichmann@das-netzwerkteam.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

set -eo pipefail

common_file="/usr/share/debian-edu-router/debian-edu-router.common"

# Load common functions, variables and stuff.
if [ -s "$common_file" ]; then
	source "$common_file"
else
	echo "Could not load common file at "$common_file"."
	exit 0;
fi

SUPPORTED_FILE_EXTENSION=("local" "org" "ldap" "dist")
GENERATED_FILE_EXTENSION="generated"

FILTERLISTS_PATH="/var/lib/debian-edu-router/filterlists.d/"
function finish {
	# If we crash, do not keep file there, delete it.
	rm -f "${FILTERLISTS_PATH}/work-in-progress"
}
trap finish EXIT

function magic() {
	local file="$1"
	local filterlist="$(basename $file)"
    # Extract the base name of the file (without extension)
    local filterlist_group="$(echo "${filterlist}" | sed -e 's/\.[^.]*$//')"
	local path="$(dirname $file)"

	# Example /path/filterlists/ProxyAllowSiteIP.generated.
	local newfile="${path}"/"${filterlist_group}IP.${GENERATED_FILE_EXTENSION}"

	local is_new_str=""
	if ! [ -s "${newfile}" ]; then
		is_new_str="new "
		cat <<-EOF > "${newfile}"
		# Debian Edu Router Plugin: Content filter
		# DON'T MODIFY THIS FILE - CHANGES WILL GET OVERWRITTEN
		# The content of this file was automatically generated
		# by "$0" at $(date).

		EOF
	fi

	notice_log "Processing $(printf "%-25s" "${filterlist}") into ${is_new_str}${newfile}..."

	# Parsing filterlist file
	while IFS= read -r line; do
    	# Skip comments or empty lines.
		if [[ "${line}" =~ ^[[:space:]]*\#.*$ ]]; then 
			continue
		elif [[ -z "${line}" ]]; then
			continue
		fi

		local domain="${line#.}" # Strips first dot from domain (.debian.org -> debian.org)

		local stdout_tmp="$(mktemp)"
		local stderr_tmp="$(mktemp)"
		set +e # Pause -e, because we do error handling manually for 'dig' (and NOT exit incase of error).
		dig "${domain}" A "${domain}" AAAA +short +timeout=3 1> "${stdout_tmp}" 2> "${stderr_tmp}"

		# Error handling
		if [ "$?" -ne 0 ] || [ -n "$(cat ${stderr_tmp})" ] || [ -z "$(cat ${stdout_tmp})" ]; then
			warning_log "IP address(es) of domain '${domain}' could not be resolved (stdout):"
			[ -n "$(cat ${stdout_tmp})" ] && warning_log "$(cat ${stdout_tmp})"
			warning_log "IP address(es) of domain '${domain}' could not be resolved (stderr):"
			[ -n "$(cat ${stderr_tmp})" ] && warning_log "$(cat ${stderr_tmp})"

			echo "# $domain ($line)"                              >> "${newfile}"
			echo "# Could not resolve IP address(es) of domain!"  >> "${newfile}"
			echo                                                  >> "${newfile}"

			rm -f "${stdout_tmp}" "${stderr_tmp}"
			continue
		fi
		set -e

		#
		#	Actually write interesting stuff to filterlist files here.
		#
		local ip_addresses="$(cat ${stdout_tmp})"
		local formatted="$(echo ${ip_addresses} | tr '\n' ' ')"

		debug_log "Found IP addresses: [${domain}] ${formatted% }."

		echo "# $domain ($line)"                                  >> "${newfile}"
		echo "${ip_addresses}"                                    >> "${newfile}"
		echo                                                      >> "${newfile}"

		rm -f "${stdout_tmp}" "${stderr_tmp}"
	done < "$file"
}

function main() {
	# Do not let Squid-ACL-watcher reload all instances of Squid again and again.
	echo "$(LANG=C.UTF-8 date)" > "${FILTERLISTS_PATH}/work-in-progress"

	has_internet_connection
	if [ "$has_internet_connection" = "false" ]; then
		error_log "This machine has no working internet connection!"
		exit 1
	fi

	debug_log "Removing old .generated filterlists files..."
	rm -f "${FILTERLISTS_PATH}"/Proxy*SiteIP.generated

	for extension in "${SUPPORTED_FILE_EXTENSION[@]}"; do
		local files=( $(find "${FILTERLISTS_PATH}" -name 'Proxy*Site'."${extension}" -type f) )

		for file in "${files[@]}"; do
			magic "$file"
		done
	done
	set +x

	# Squid may be reloaded now too :)
	rm -f "${FILTERLISTS_PATH}/work-in-progress"
	systemctl start squid_d-e-r_acl_watcher.service 1>/dev/null || true
}

main
