#!/usr/bin/sh
# httpd-iworx-sync-conf (CPS-60): run by the package's %post, before the old
# package's %postun restarts httpd-iworx.
#
# Usage: httpd-iworx-sync-conf [--upgrade]
#
# 1. The app configs in conf.d/iworx-apps belong to this package, which
#    replaces them on upgrade, but NodeWorx turns Roundcube on and off by
#    commenting out the Alias line in 10-webmail-roundcube.conf and keeps
#    the setting in iworx.ini. Put that setting back into the file.
# 2. httpd-iworx no longer loads mod_fastcgi, so a mod_fastcgi directive in
#    any file httpd.conf loads (httpd-custom.conf, say, or an admin's own
#    file) stops httpd-iworx starting. Comment those out, keeping the
#    original in /var/lib/httpd-iworx/backups, which nothing Includes.
# 3. With --upgrade, check that the config loads, and say why if it doesn't.
#
# Leaves a symlinked config file alone (with a warning), and always exits 0,
# so it can't fail the package install. HTTPD_IWORX_TEST_HOME and
# HTTPD_IWORX_TEST_BACKUP_DIR override /home/interworx and the backup
# directory, for testing only.

UPGRADE=
[ "$1" = --upgrade ] && UPGRADE=1

IWORX_HOME=${HTTPD_IWORX_TEST_HOME:-/home/interworx}
HTTPD_CONF=$IWORX_HOME/etc/httpd/httpd.conf
ROUNDCUBE_CONF=$IWORX_HOME/etc/httpd/conf.d/iworx-apps/10-webmail-roundcube.conf
INI=$IWORX_HOME/iworx.ini
BACKUP_DIR=${HTTPD_IWORX_TEST_BACKUP_DIR:-/var/lib/httpd-iworx/backups}
# Relative Include paths resolve against ServerRoot.
SERVERROOT=$IWORX_HOME/html

warn() {
    echo "httpd-iworx: $1" >&2
    logger -t httpd-iworx "$1" 2>/dev/null || :
}

# Replace $1 with the already-written temp file $2, keeping $1's owner and
# mode, after copying $1 to $3 if given. The swap is a single rename, so $1
# is never missing; on failure $1 is left as it was.
replace_with() {
    chown --reference="$1" "$2" 2>/dev/null
    chmod --reference="$1" "$2" 2>/dev/null
    if { [ -z "$3" ] || cp -p "$1" "$3"; } && mv -f "$2" "$1"; then
        return 0
    fi
    rm -f "$2"
    return 1
}

# The file, then every file it Includes, as httpd.conf loads them: an
# included directory is read recursively. $2 is the nesting depth, capped so
# an Include loop can't recurse forever.
MAX_DEPTH=10
list_conf() {
    [ "$2" -lt "$MAX_DEPTH" ] || return 0
    if [ -d "$1" ]; then
        for G in "$1"/*; do
            [ -e "$G" ] && list_conf "$G" $(($2 + 1))
        done
        return 0
    fi
    [ -f "$1" ] || return 0
    echo "$1"
    grep -Ei '^[[:space:]]*Include(Optional)?[[:space:]]' "$1" | awk '{ sub(/\r$/, ""); p = $2; gsub(/["\047]/, "", p); print p }' | while IFS= read -r INC; do
        case $INC in
            /*) ;;
            *) INC=$SERVERROOT/$INC ;;
        esac
        for F in $INC; do
            list_conf "$F" $(($2 + 1))
        done
    done
}

# 1. NodeWorx's Roundcube setting: [roundcube] enabled in iworx.ini, 1 or 0.
ENABLED=
[ -r "$INI" ] && ENABLED=$(awk '/^[[:space:]]*\[/ { s = $0; gsub(/[[:space:]]/, "", s); next }
    s == "[roundcube]" && /^[[:space:]]*enabled[[:space:]]*=/ {
        v = $0; sub(/^[^=]*=/, "", v); gsub(/["[:space:]]/, "", v); print v; exit
    }' "$INI")
if [ -f "$ROUNDCUBE_CONF" ] && { [ "$ENABLED" = 0 ] || [ "$ENABLED" = 1 ]; }; then
    if [ -L "$ROUNDCUBE_CONF" ]; then
        warn "WARNING: $ROUNDCUBE_CONF is a symlink, so it was left alone and Roundcube may not match NodeWorx (enabled=$ENABLED); turn it off and on again in NodeWorx."
    elif TMP=$(mktemp "$ROUNDCUBE_CONF.XXXXXX") &&
        awk -v on="$ENABLED" '$1 ~ /^#*[Aa][Ll][Ii][Aa][Ss]$/ && $2 == "/roundcube" {
                 sub(/^[ \t]*#+/, "")
                 if (on != 1) $0 = "#" $0
             }
             { print }' "$ROUNDCUBE_CONF" > "$TMP" && [ -s "$TMP" ]; then
        if cmp -s "$TMP" "$ROUNDCUBE_CONF"; then
            rm -f "$TMP"
        else
            replace_with "$ROUNDCUBE_CONF" "$TMP" || warn "WARNING: could not set Roundcube in $ROUNDCUBE_CONF to match NodeWorx (enabled=$ENABLED); turn it off and on again in NodeWorx."
        fi
    else
        rm -f "$TMP"
        warn "WARNING: could not set Roundcube in $ROUNDCUBE_CONF to match NodeWorx (enabled=$ENABLED); turn it off and on again in NodeWorx."
    fi
fi

# 2. mod_fastcgi directives anywhere httpd.conf loads. Files it doesn't
# load, such as iworx-mod_fastcgi's own fastcgi.conf, are left alone.
list_conf "$HTTPD_CONF" 0 | sort -u | while IFS= read -r CONF; do
    grep -Eqi '^[[:space:]]*FastCGI[[:alnum:]]*[[:space:]]' "$CONF" || continue
    HOW="Convert them to mod_proxy_fcgi if still needed (see conf.d/iworx-apps/10-*.conf for the pattern)."
    if [ -L "$CONF" ]; then
        warn "WARNING: $CONF uses mod_fastcgi directives, which stop httpd-iworx starting now that it no longer loads mod_fastcgi; it is a symlink, so it was left alone. Comment them out. $HOW"
        continue
    fi
    # The package's own root directory, outside /home/interworx, so no
    # Include loads the backup and the panel's cvspermsfix leaves it alone.
    if [ ! -d "$BACKUP_DIR" ] || [ -L "$BACKUP_DIR" ] || [ "$(stat -c %u "$BACKUP_DIR")" != 0 ]; then
        warn "WARNING: $CONF uses mod_fastcgi directives, which stop httpd-iworx starting now that it no longer loads mod_fastcgi, and $BACKUP_DIR can't be used for a backup, so it was left alone. Comment them out. $HOW"
        continue
    fi
    BAK=$BACKUP_DIR/$(printf '%s' "$CONF" | tr / _).$(date +%Y%m%d%H%M%S).$$
    if TMP=$(mktemp "$CONF.XXXXXX") &&
        awk 'c || tolower($0) ~ /^[ \t]*fastcgi[a-z0-9]*[ \t]/ {
                 print "#[httpd-iworx: disabled, httpd-iworx no longer loads mod_fastcgi] " $0
                 c = ($0 ~ /\\$/)
                 next
             }
             { print }' "$CONF" > "$TMP" && [ -s "$TMP" ] && replace_with "$CONF" "$TMP" "$BAK"; then
        warn "WARNING: $CONF used mod_fastcgi directives, which stopped httpd-iworx starting now that it no longer loads mod_fastcgi. They are commented out, marked with \"httpd-iworx: disabled\"; the original is saved as $BAK. $HOW"
    else
        rm -f "$TMP"
        warn "WARNING: $CONF uses mod_fastcgi directives, which stop httpd-iworx starting now that it no longer loads mod_fastcgi, and it could not be rewritten. Comment them out. $HOW"
    fi
done

# 3. Diagnostic only, never changes anything: if the upgraded config won't
# load, say why now rather than leaving a silently dead panel.
if [ -n "$UPGRADE" ] && ! CFGTEST=$("$IWORX_HOME/bin/httpd/httpd" -t -DSSL -f "$HTTPD_CONF" 2>&1); then
    echo "httpd-iworx: WARNING: the panel web server configuration does not load, so httpd-iworx will not start:" >&2
    printf '%s\n' "$CFGTEST" >&2
    logger -t httpd-iworx "panel web server configuration does not load after upgrade: $(printf '%s' "$CFGTEST" | tail -n 1)" 2>/dev/null || :
fi
exit 0
