#!/bin/bash

###########################################################################
#
# MODULE:       Commands
# COPYRIGHT:    (C) 2009-2025 by CacheGuard Technologies Ltd (UK)
# COPYRIGHT:    (C) 2026-2026 by CacheGuard Technologies SAS (FR)
#
# 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 3 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, see <http://www.gnu.org/licenses/>.
#
###########################################################################

source functions

transaction-exec-command()
{
    local log=${1}
    local apl_command=${ARGS[0]}

    if test "${log}" == log ; then
	local tag arg i

	if test ${TERM} == ${WADMIN_TERM} ; then
	    tag="${COMMAND_TAG} "
	    ARGS[0]=$(get-html-bold-command ${apl_command})
	fi

	case ${apl_command} in
	    access)
		case ${ARGS[1]} in
		    manager)
			case ${ARGS[2]} in
			    add)
				echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} ${ARGS[4]} ${ARGS[5]} '${ARGS[6]}'" >&2
				;;
			    *)
				echo "${tag}${ARGS[@]}" >&2
				;;
			esac
			;;
		    *)
			echo "${tag}${ARGS[@]}" >&2
			;;
		esac
		;;
	    admin)
		case ${ARGS[1]} in
		    snmp)
			case ${ARGS[2]} in
			    'trap')
				case ${ARGS[3]} in
				    add)
					case ${ARGS[4]} in
					    v1|v2c)
						echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} ${ARGS[4]} ${ARGS[5]} ${ARGS[6]} ..." >&2
						;;
					    v3)
						echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} ${ARGS[4]} ${ARGS[5]} ${ARGS[6]} ${ARGS[7]} ${ARGS[8]} ${ARGS[9]} ..." >&2
						;;
					    *)
						;;
					esac
					;;
				    *)
					echo "${tag}${ARGS[@]}" >&2
					;;
				esac
				;;
			    community|privacy)
				echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ..." >&2
				;;
			    *)
				echo "${tag}${ARGS[@]}" >&2
				;;
			esac
			;;
		    ssh)
			case ${ARGS[2]} in
			    key)
				case ${ARGS[3]} in
				    'set')
					echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} ${ARGS[4]} '${ARGS[5]}'" >&2
					;;
				    *)
					;;
				esac
				;;
			    *)
				;;
			esac
			;;
		    user)
			case ${ARGS[2]} in
			    add)
				echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} ..." >&2
				;;
			    *)
				echo "${tag}${ARGS[@]}" >&2
				;;
			esac
			;;
		    *)
			echo "${tag}${ARGS[@]}" >&2
			;;
		esac
		;;
	    authenticate)
		case ${ARGS[1]} in
		    ldap)
			case ${ARGS[2]} in
			    request)
				arg=${ARGS[5]}
				test -n "${arg}" || arg="''"
				echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} '${ARGS[3]}' ${ARGS[4]} ${arg} '${ARGS[6]}' ..." >&2
				;;
			    binddn)
				echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} '${ARGS[3]}' ${ARGS[4]} ..." >&2
				;;
			    *)
				echo "${tag}${ARGS[@]}" >&2
				;;
			esac
			;;
		    ad)
			case ${ARGS[2]} in
			    account)
				echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} ..." >&2
				;;
			    rdn)
				echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} '${ARGS[3]}'" >&2
				;;				
			    *)
				echo "${tag}${ARGS[@]}" >&2
				;;
			esac
			;;

		    *)
			echo "${tag}${ARGS[@]}" >&2
			;;
		esac
		;;
	    dynamicdns)
		case ${ARGS[1]} in
		    on)
			case ${ARGS[2]} in
			    changeip|myonlineportal|noip)
				echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} ${ARGS[4]} ..." >&2
				;;
			    *)
				echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} ..." >&2
				;;
			esac
			;;
		    *)
			echo "${tag}${ARGS[@]}" >&2
			;;
		esac
		;;
	    email)
		case ${ARGS[1]} in
		    account)
			echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} ${ARGS[4]} ..." >&2
			;;
		    admin)
			echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} '${ARGS[3]}'" >&2
			;;
		    *)
			echo "${tag}${ARGS[@]}" >&2
			;;
		esac
		;;
	    guard)
		case ${ARGS[1]} in
		    filter)
			case ${ARGS[2]} in
			    ldap)
				echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} ${ARGS[4]} '${ARGS[5]}' ${ARGS[6]} '${ARGS[7]}'" >&2
				;;
			    *)
				echo "${tag}${ARGS[@]}" >&2
				;;
			esac
			;;
		    *)
			echo "${tag}${ARGS[@]}" >&2
			;;
		esac
		;;
	    ip)
		case ${ARGS[1]} in
		    external)
			case ${ARGS[2]} in
			    pppoe)
				echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} '${ARGS[3]}' '${ARGS[4]}' ..." >&2
				;;
			    *)
				echo "${tag}${ARGS[@]}" >&2
				;;
			esac
			;;
		    *)
			echo "${tag}${ARGS[@]}" >&2
			;;
		esac
		;;
	    manager)
		case ${ARGS[1]} in
		    sync)
			case ${ARGS[2]} in
			    peer)
				echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} '${ARGS[4]}'" >&2
				;;
			    *)
				echo "${tag}${ARGS[@]}" >&2
				;;
			esac
			;;
		    *)
			echo "${tag}${ARGS[@]}" >&2
			;;
		esac
		;;
	    password)
		case ${ARGS[1]} in
		    console)
			echo "${tag}${ARGS[0]} ${ARGS[1]}" >&2
			;;
		    ldap|wadmin|login|ad)
			echo "${tag}${ARGS[0]} ${ARGS[1]} ..." >&2
			;;
		    email)
			echo "${tag}${ARGS[0]} ${ARGS[1]} ..." >&2
			;;
		    file)
			case ${ARGS[2]} in
			    add)
				echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} ${ARGS[4]} ${ARGS[5]} ..." >&2
				;;
			    *)
				echo "${tag}${ARGS[@]}" >&2
				;;
			esac
			;;
		    snmp)
			case ${ARGS[2]} in
			    community|privacy)
				echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ..." >&2
				;;
			    *)
				echo "${tag}${ARGS[@]}" >&2
				;;
			esac
			;;
		    *)
			echo "${tag}${ARGS[@]}" >&2
			;;
		esac
		;;
	    vpnipsec)
		case ${ARGS[1]} in
		    access)
			case ${ARGS[2]} in
			    access)
				arg=${ARGS[4]}
 				if test "${arg//=}" == "${arg}" ; then
				    echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} ${arg}" >&2
				else
				    echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} '${arg}'" >&2
				fi
				;;
			    *)
				echo "${tag}${ARGS[@]}" >&2
				;;
			esac
			;;
		    site)
			case ${ARGS[5]} in
			    tls)
				case ${ARGS[6]} in
				    dn)
					echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} ${ARGS[4]} ${ARGS[5]} ${ARGS[6]} '${ARGS[7]}'" >&2
					;;
				    *)
					echo "${tag}${ARGS[@]}" >&2
					;;
				esac
				;;
			    *)
				echo "${tag}${ARGS[@]}" >&2
				;;
			esac
			;;
		    *)
			echo "${tag}${ARGS[@]}" >&2
			;;
		esac
		;;
	    waf)
		case ${ARGS[1]} in
		    reputation)
			case ${ARGS[2]} in
			    rbl)
				case ${ARGS[3]} in
				    set)
					echo "${tag}${ARGS[0]} ${ARGS[1]} ${ARGS[2]} ${ARGS[3]} ..." >&2
					;;
				    *)
					;;
				esac
				;;
			    *)
				echo "${tag}${ARGS[@]}" >&2
				;;
			esac
			;;
		    *)
			echo "${tag}${ARGS[@]}" >&2
			;;
		esac
		;;
	    *)
		echo "${tag}${ARGS[@]}" >&2
		;;
	esac
    fi

    source ${ROOT_DIR}${APPLIANCE_DIR}/bin/${apl_command}
}

run()
{
    test -z "${TRANSACTION}" || return 106
    ! is-in-manager-exec-context || return 234

    local line apl_command apl_args

    local transaction_file=${TMP_DIR}/${TRANSACTION_FILE}.${USER}
    local action=${1}

    init-env-variables ${MANAGER_CONTEXT_ENV}

    case "${action}" in
	open)
	    test ! -f ${transaction_file} || return 107
	    while read apl_command apl_args
	    do
		test -n "${apl_command}" || continue
		test "${apl_command:0:1}" != "#" || continue
		test "${apl_command}" != "." || break

		if test "${apl_command}" == "transaction" ; then
		    test "${apl_args}" !=  "close" || break
		    continue
		fi
		echo ${apl_command} ${apl_args}
	    done > ${transaction_file}
	    ;;
	close)
	    rm -f ${transaction_file}
	    ;;
	show)
	    test -f ${transaction_file} || return 0
	    echo
	    cat ${transaction_file}
	    echo
	    ;;
	commit)
	    local log=${2}
	    test -f ${transaction_file} || return 0

	    initialise ${MANAGER_CONTEXT_ENV}

	    export TRANSACTION=yes

	    local args
	    declare -a args

	    local word c escaped quoted i

	    while IFS= read -r line
	    do
		test -n "${line}" || continue
		test "${line:0:1}" != "#" || continue
		test "${line}" != "." || break

		apl_command=${line%%[[:space:]]*}
		test -x ${LOCAL_DIR}/${TECHNICAL_NAME}/bin/${apl_command} || continue

		if test "${apl_command}" == "${line}" ; then
		    apl_args=""
		else
		    apl_args=${line#*[[:space:]]}
		    apl_args=${apl_args#"${apl_args%%[![:space:]]*}"}
		fi

		if test "${apl_command}" == "transaction" ; then
		    test "${apl_args/ *}" !=  "close" || break
		    continue
		fi

		case ${apl_command} in
		    access|admin|authenticate|dynamicdns|email|ip|manager|password|vpnipsec|waf)
			args=("${apl_command}")
			word=""
			quoted=0
			escaped=0

			for ((i=0; i<${#apl_args}; i++))
			do
			    c="${apl_args:i:1}"
			    if test "${quoted}" -eq 1 ; then
				if test "${escaped}" -eq 1 ; then
				    word="${word}${c}"
				    escaped=0
				elif test "${c}" = '\' ; then
				    escaped=1
				elif test "${c}" = "'" ; then
				    quoted=0
				else
				    word="${word}${c}"
				fi
			    else
				if test "${c}" = "'" ; then
				    quoted=1
				elif test "${c}" = " " || test "${c}" = "$(printf '\t')" ; then
				    args+=("${word}")
				    word=""
				else
				    word="${word}${c}"
				fi
			    fi
			done

			if test -n "${word}" ; then
			    args+=("${word}")
			fi
			;;
		    *)
			read -a args <<< "${apl_command} ${apl_args}"
			;;
		esac

		push-args-1 "${args[@]}"
                transaction-exec-command ${log}

	    done < ${transaction_file}

	    unset TRANSACTION
	    rm -f ${transaction_file}
	    commit-env
	    ;;
	*)
	    return 1
	    ;;
    esac
}

main __noenv "${@}"
