#!/bin/bash
# postinst script for #PACKAGE#
#
# see: dh_installdeb(1)

set -e

# Begin vars.sh
#!/bin/bash
# DO NOT EDIT
# This file is regenerated each run.
# If you want to add or change a variable, edit debify/settings.json and the vars hashref

source /etc/os-release
export OBS_REPO="x${NAME}_${VERSION_ID}"
if ls debian/*.install &> /dev/null; then
    perl -pi -e 's/\${env:OBS_REPO}/$ENV{OBS_REPO}/' debian/*.install
fi

export DEB_INSTALL_ROOT="/usr/src/packages/BUILD/debian/tmp"
export DEB_SOURCE_ROOT="/usr/src/packages/BUILD/debian/SOURCES_FROM_SPEC"
export RPM_SOURCE_DIR="/usr/src/packages/BUILD/debian/SOURCES_FROM_SPEC"
export __isa_bits="64"
export __isa_name="x86"
export __sourcedir=""
export _bindir="/opt/cpanel//root/usr/bin"
export _datadir="/opt/cpanel//root/usr/share"
export _defaultdocdir="/opt/cpanel//root/usr/share/doc"
export _docdir="/opt/cpanel//root/usr/share/doc"
export _exec_prefix="/opt/cpanel//root/usr"
export _includedir="/opt/cpanel//root/usr/include"
export _infodir="/opt/cpanel//root/usr/share/info"
export _isa=""
export _lib="lib64"
export _libdir="/opt/cpanel//root/usr/lib64"
export _libexecdir="/opt/cpanel//root/usr/libexec"
export _localstatedir="/opt/cpanel//root/var"
export _mandir="/opt/cpanel//root/usr/share/man"
export _prefix="/opt/cpanel//root/usr"
export _root_bindir="/opt/cpanel//root/usr/bin"
export _root_datadir="/opt/cpanel//root/usr/share"
export _root_exec_prefix="/opt/cpanel//root/usr"
export _root_includedir="/opt/cpanel//root/usr/include"
export _root_infodir="/opt/cpanel//root/usr/share/info"
export _root_initddir="/opt/cpanel//root/etc/rc.d/init.d"
export _root_libdir="/opt/cpanel//root/usr/lib64"
export _root_libexecdir="/opt/cpanel//root/usr/libexec"
export _root_localstatedir="/opt/cpanel//root/var"
export _root_mandir="/opt/cpanel//root/usr/share/man"
export _root_prefix="/opt/cpanel//root/usr"
export _root_sbindir="/opt/cpanel//root/usr/sbin"
export _root_sharedstatedir="/opt/cpanel//root/usr/com"
export _root_sysconfdir="/opt/cpanel//root/etc"
export _sbindir="/opt/cpanel//root/usr/sbin"
export _scl_prefix="/opt/cpanel"
export _scl_root="/opt/cpanel//root"
export _sysconfdir="/opt/cpanel//root/etc"
export _unitdir="/usr/lib/systemd/system"
export buildroot="/usr/src/packages/BUILD"
export csf_version="16.20"
export full_package_name="cpanel-csf-16.20"
export ix86="i386"
export name="cpanel-csf"
export nil="0"
export ns_name="ea"
export pkg=""
export pkg_name=""
export pkgname=""
export previous_version="16.19"
export release="1"
export release_prefix="1"
export scl=""
export scl_name=""
export scl_name_base=""
export scl_name_version=""
export scl_prefix=""
export version="16.20"
export version_with_debian_revision="16.20-1"
export SOURCE1="$DEB_SOURCE_ROOT/pkg.preinst"
export SOURCE2="$DEB_SOURCE_ROOT/pkg.postinst"
export SOURCE3="$DEB_SOURCE_ROOT/pkg.prerm"
export SOURCE4="$DEB_SOURCE_ROOT/pkg.postrm"
# End vars.sh

# summary of how this script can be called:
#        * <postinst> `configure' <most-recently-configured-version>
#        * <old-postinst> `abort-upgrade' <new version>
#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
#          <new-version>
#        * <postinst> `abort-remove'
#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
#          <failed-install-package> <version> `removing'
#          <conflicting-package> <version>
# for details, see https://www.debian.org/doc/debian-policy/ or
# the debian-policy package


case "$1" in
    configure)
    ;;

    abort-upgrade|abort-remove|abort-deconfigure)
    ;;

    *)
        echo "postinst called with unknown argument \`$1'" >&2
        exit 1
    ;;
esac

# Contents of SOURCES/pkg.postinst
#!/bin/bash

# Touch to update cPanel's ConfigObj cache
touch /usr/local/cpanel/Cpanel/Config/ConfigObj/Driver ||:

# Register cPanel app config
/usr/local/cpanel/bin/register_appconfig /usr/local/cpanel/bin/csf.conf.appconfig ||:

# Remove deprecated AUTO_UPDATES configuration if present
# This runs on all installs (fresh and upgrade) because config may exist from tarball
sed -i '/^AUTO_UPDATES\s*=/d' /etc/csf/csf.conf ||:

# Remove auto-update cron job if it exists
rm -f /etc/cron.d/csf_update ||:
rm -f /etc/cron.daily/csget ||:

# Remove symlinks to webmin/uninstall in /etc/csf
rm -f /etc/csf/uninstall.sh ||:
rm -f /etc/csf/webmin ||:
rm -f /etc/csf/csfwebmin.tgz ||:

# Remove the uninstall script
rm -f /usr/local/csf/bin/uninstall.sh ||:

# Do config schema updates
/usr/local/csf/bin/auto.pl '14.00' ||:

# Disable and mask firewalld if present
systemctl daemon-reload ||:
systemctl disable firewalld 2>/dev/null || true
systemctl stop firewalld 2>/dev/null || true
systemctl mask firewalld 2>/dev/null || true

# Enable CSF services
systemctl enable csf.service ||:
systemctl enable lfd.service ||:
systemctl restart csf.service ||:
systemctl restart lfd.service ||:

# Ensure firewall rules are properly loaded after upgrade/downgrade
# This implements a robust validation and reload process to prevent
# iptables rule loading failures during package operations (CPANEL-52154)
RELOAD_ISSUES=0
if [ -x /usr/sbin/csf ]; then
    echo "Validating and reloading firewall rules to ensure clean state..."

    # Function to safely run CSF commands with error handling
    run_csf_safe() {
        local cmd="$1" desc="$2" output
        if ! output=$(/usr/sbin/csf $cmd 2>&1); then
            echo "WARNING: $desc failed, skipping firewall reload for safety"
            echo "CSF error output: $output"
            command -v systemd-cat >/dev/null 2>&1 && echo "CSF $desc failed: $output" | systemd-cat -t csf-postinst -p warning
            RELOAD_ISSUES=1
            return 1
        fi
        return 0
    }

    # Step 1: Verify CSF installation is valid
    if run_csf_safe "-c" "CSF installation check"; then
        # Step 2: Try to save current firewall state (validates iptables-save)
        BACKUP_DIR="/var/lib/csf/backup"
        BACKUP_TIMESTAMP=$(date +'%%Y%%m%%d-%%H%%M%%S')
        BACKUP_FILE="$BACKUP_DIR/pre-upgrade-$BACKUP_TIMESTAMP.rules"
        
        # Set restrictive umask and create secure backup directory
        old_umask=$(umask); umask 0077
        mkdir -p "$BACKUP_DIR" 2>/dev/null && chmod 0700 "$BACKUP_DIR" 2>/dev/null ||:

        if command -v iptables-save >/dev/null 2>&1; then
            # Save IPv4 rules and optionally IPv6 rules
            BACKUP_FILE_IPV6="${BACKUP_FILE%.rules}-ipv6.rules"
            if iptables-save > "$BACKUP_FILE" 2>/dev/null && chmod 0600 "$BACKUP_FILE" 2>/dev/null; then
                # Also backup IPv6 rules if available
                command -v ip6tables-save >/dev/null 2>&1 && ip6tables-save > "$BACKUP_FILE_IPV6" 2>/dev/null && chmod 0600 "$BACKUP_FILE_IPV6" 2>/dev/null
                echo "  OK: Current firewall state backed up successfully"
                umask "$old_umask"
                # Test both IPv4 and IPv6 rule syntax
                if iptables-restore --test < "$BACKUP_FILE" 2>/dev/null && { [ ! -f "$BACKUP_FILE_IPV6" ] || ip6tables-restore --test < "$BACKUP_FILE_IPV6" 2>/dev/null; }; then
                    echo "  OK: Saved rules passed syntax validation"
                    if run_csf_safe "-ra" "Firewall restart and reload"; then
                        echo "  OK: Firewall rules reloaded successfully"
                        rm -f "$BACKUP_FILE" "$BACKUP_FILE_IPV6" 2>/dev/null ||:
                    else
                        echo "  WARNING: Firewall reload failed, attempting automatic rollback"
                        # Attempt rollback to prevent exposed state
                        if iptables-restore < "$BACKUP_FILE" 2>/dev/null && { [ ! -f "$BACKUP_FILE_IPV6" ] || ip6tables-restore < "$BACKUP_FILE_IPV6" 2>/dev/null; }; then
                            echo "  OK: Automatic rollback successful, previous firewall state restored"
                        else
                            echo "  ERROR: Rollback failed - firewall may be in unsafe state"; RELOAD_ISSUES=1
                        fi
                        echo "     Backup preserved at $BACKUP_FILE for manual recovery"; RELOAD_ISSUES=1
                    fi
                else
                    echo "  WARNING: Saved rules failed syntax check, skipping reload for safety"
                    echo "     Debug backup available at $BACKUP_FILE"; RELOAD_ISSUES=1
                fi
            else
                echo "  WARNING: Could not backup current firewall state, skipping reload for safety"
                umask "$old_umask"; RELOAD_ISSUES=1
            fi
        else
            echo "  WARNING: iptables-save not available, using basic reload"
            umask "$old_umask"; run_csf_safe "-ra" "Basic firewall reload" ||:
        fi
    else
        echo "  WARNING: CSF installation check failed, skipping firewall reload"; RELOAD_ISSUES=1
    fi
else
    echo "  WARNING: CSF binary not found or not executable, skipping firewall reload"; RELOAD_ISSUES=1
fi

# Conditional completion message based on firewall reload success
if [ "$RELOAD_ISSUES" -eq 0 ]; then
    echo "CSF installation completed successfully"
else
    echo "CSF installation completed with warnings - check firewall reload status above"
fi
# End SOURCES/pkg.postinst


exit 0
