#!/bin/bash

# TZ DDoS Protection v2.0.1 - INSTALLER
# Auto-starts daemon. Installs cron watchdog. No manual setup needed.

GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
CYAN='\033[0;36m'
NC='\033[0m'

echo -e "${GREEN}  TZ DDoS Protection v2.0.1    ${NC}"
echo -e "${GREEN}====================================${NC}"

if [ "$EUID" -ne 0 ]; then
  echo -e "${RED}Error: Run as root.${NC}"
  exit 1
fi

echo -e "${YELLOW}[0/7] System Checks...${NC}"
HAS_IONCUBE=false
if command -v php >/dev/null 2>&1 && php -v 2>&1 | grep -qi "ioncube"; then
    HAS_IONCUBE=true
elif [ -x "/usr/local/cpanel/3rdparty/bin/php" ] && /usr/local/cpanel/3rdparty/bin/php -v 2>&1 | grep -qi "ioncube"; then
    HAS_IONCUBE=true
elif [ -x "/usr/local/bin/php" ] && /usr/local/bin/php -v 2>&1 | grep -qi "ioncube"; then
    HAS_IONCUBE=true
fi

if [ "$HAS_IONCUBE" = false ]; then
  echo -e "${RED}Error: ionCube Loader is not installed or enabled for CLI PHP.${NC}"
  echo -e "${YELLOW}Please enable ionCube Loader in WHM -> Tweak Settings -> PHP or install it via EasyApache 4 before installing this plugin.${NC}"
  exit 1
fi

DOCROOT="/usr/local/cpanel/whostmgr/docroot"
PLUGIN_SUBDIR="ddosprotection"
FULL_PATH="$DOCROOT/cgi/$PLUGIN_SUBDIR"
APPS_CONF="/var/cpanel/apps/ddosprotection.conf"

UPDATE_MODE=false
for arg in "$@"; do
  case $arg in
    --update)
      UPDATE_MODE=true
      shift
      ;;
    --install)
      UPDATE_MODE=false
      shift
      ;;
  esac
done

# 1. Kill & Clean
if [ "$UPDATE_MODE" = true ]; then
    echo -e "${YELLOW}[1/7] Updating to new version (preserving logs and quarantines)...${NC}"
else
    echo -e "${YELLOW}[1/7] Removing old version...${NC}"
fi

pkill -9 -f "daemon.php" > /dev/null 2>&1
crontab -l 2>/dev/null | grep -v "ddosprotection" | crontab - 2>/dev/null
/usr/local/cpanel/bin/unregister_appconfig ddosprotection > /dev/null 2>&1

if [ "$UPDATE_MODE" = false ]; then
    # Release any active quarantines before removing files
    if [ -f "$FULL_PATH/logs/quarantine.json" ]; then
        echo -e "${CYAN}  Releasing active quarantines...${NC}"
        # Parse quarantine file and clean up .htaccess files
        if command -v php > /dev/null 2>&1; then
        php -r '
                $q = json_decode(@file_get_contents("'$FULL_PATH'/logs/quarantine.json"), true);
                if (is_array($q)) {
                    foreach ($q as $domain => $data) {
                        $dr = isset($data["docroot"]) ? $data["docroot"] : "";
                        if ($dr && is_dir($dr)) {
                            $ht = "$dr/.htaccess";
                            if (file_exists($ht)) {
                                $c = @file_get_contents($ht);
                                if ($c !== false) {
                                    // Safe strpos/substr removal — no regex, no risk of data loss
                                    $s = strpos($c, "# DDOS_PROTECTION_START");
                                    $e = strpos($c, "# DDOS_PROTECTION_END");
                                    if ($s !== false && $e !== false && $e > $s) {
                                        $e += strlen("# DDOS_PROTECTION_END");
                                        // Eat trailing newlines after end marker
                                        while ($e < strlen($c) && ($c[$e] === "\n" || $c[$e] === "\r")) $e++;
                                        $c = substr($c, 0, $s) . substr($c, $e);
                                    }
                                    @file_put_contents($ht, $c);
                                }
                            }
                            // Thorough cleanup of all challenge variants
                            $oldFiles = glob("$dr/__tz_protection_challenge*");
                            if($oldFiles) foreach($oldFiles as $f) @unlink($f);
                            @unlink("$dr/ddos_challenge.php");
                            @unlink("$dr/ddos_challenge.html");
                            echo "  Released: $domain\n";
                        }
                    }
                }
            ' 2>/dev/null
        fi
    fi
fi

if [ "$UPDATE_MODE" = true ] && [ -d "$FULL_PATH/logs" ]; then
    # Backup logs before rm
    mv "$FULL_PATH/logs" /tmp/ddos_logs_backup_$$
fi

rm -rf "$FULL_PATH"
rm -f "$APPS_CONF"
mkdir -p "$FULL_PATH"
mkdir -p "$FULL_PATH/templates"

if [ "$UPDATE_MODE" = true ] && [ -d "/tmp/ddos_logs_backup_$$" ]; then
    mv /tmp/ddos_logs_backup_$$ "$FULL_PATH/logs"
else
    mkdir -p "$FULL_PATH/logs"
fi


# 2. Download & Extract
TMP_DIR="/tmp/ddos_v2.0.1_$$"
mkdir -p "$TMP_DIR"
cd "$TMP_DIR"
PKG_NAME="pkg_$(date +%s).zip"
echo -e "${YELLOW}[2/7] Downloading v2.0.1 TZ DDoS Protection...${NC}"
TS=$(date +%s)
HTTP_CODE=$(curl -sL -w "%{http_code}" -H "Cache-Control: no-cache" -A "Mozilla/5.0 (compatible; GuardianInstaller/2.0.1)" "https://ddos-protection.tzsmm.com/2_0_1.zip?t=$TS" -o "$PKG_NAME")

if [ "$HTTP_CODE" -ne 200 ] || [ ! -s "$PKG_NAME" ]; then
    echo -e "${RED}  Download failed! HTTP Code: $HTTP_CODE. Trying alternative...${NC}"
    curl -sL -H "Cache-Control: no-cache" -A "Mozilla/5.0" "https://dedos-sheild.tzsmm.com/1_2_0.zip?t=$TS" -o "$PKG_NAME"
fi

if ! unzip -t "$PKG_NAME" >/dev/null 2>&1; then
    echo -e "${RED}  Error: Downloaded file is not a valid zip archive.${NC}"
    echo -e "${RED}  This usually happens if the server blocks the download (e.g. Cloudflare captcha).${NC}"
    rm -rf "$TMP_DIR"
    exit 1
fi

unzip -q "$PKG_NAME" -d data
cd data || exit 1

# 3. Deploy Files
echo -e "${YELLOW}[3/7] Deploying Engine...${NC}"
find . -name "index.cgi"   -exec cp -f {} "$FULL_PATH/" \;
find . -name "plugin.php"  -exec cp -f {} "$FULL_PATH/" \;
find . -name "daemon.php"  -exec cp -f {} "$FULL_PATH/" \;
find . -name "functions.php" -exec cp -f {} "$FULL_PATH/" \;
find . -name "ddos-protection.png" -exec cp -f {} "$FULL_PATH/" \;
find . -name "tailwind.js"  -exec cp -f {} "$FULL_PATH/" \;
find . -name "tailwind.min.css" -exec cp -f {} "$FULL_PATH/" \;
find . -name "challenge.html" -exec cp -f {} "$FULL_PATH/templates/" \;
find . -name "challenge.php"  -exec cp -f {} "$FULL_PATH/templates/" \;

cp -f ddosprotection.conf "$APPS_CONF" 2>/dev/null
# Update ddosprotection.conf icon path
sed -i 's|^icon=.*|icon=cgi/ddosprotection/ddos-protection.png|' "$APPS_CONF"

mkdir -p "$DOCROOT/addon_plugins"
cp -f install.json "$DOCROOT/addon_plugins/ddosprotection.json" 2>/dev/null
cp -f ddos-protection.png "$DOCROOT/addon_plugins/ddos-protection.png" 2>/dev/null
chmod 644 "$DOCROOT/addon_plugins/ddosprotection.json" 2>/dev/null
chmod 644 "$DOCROOT/addon_plugins/ddos-protection.png" 2>/dev/null

# 4. Permissions
echo -e "${YELLOW}[4/7] Setting permissions...${NC}"
chown -R root:root "$FULL_PATH"
chmod -R 755 "$FULL_PATH"
chmod 777 "$FULL_PATH/logs"
touch "$FULL_PATH/logs/ddos.log" && chmod 666 "$FULL_PATH/logs/ddos.log"
touch "$FULL_PATH/logs/telemetry.json" && chmod 666 "$FULL_PATH/logs/telemetry.json"
touch "$FULL_PATH/logs/quarantine.json" && chmod 666 "$FULL_PATH/logs/quarantine.json"
touch "$FULL_PATH/logs/settings.json" && chmod 666 "$FULL_PATH/logs/settings.json"

chown root:root "$APPS_CONF" 2>/dev/null
chmod 644 "$APPS_CONF" 2>/dev/null

# Default settings (only if they don't exist, to preserve license key across updates)
if [ ! -s "$FULL_PATH/logs/settings.json" ]; then
    echo '{"rps_threshold":500,"quarantine_duration":5,"admin_email":"","auto_protect":true,"license_key":"","quarantine_mode":"captcha"}' > "$FULL_PATH/logs/settings.json"
fi
echo '{}' > "$FULL_PATH/logs/quarantine.json"

# Fix Perl line endings
sed -i 's/\r$//' "$FULL_PATH/index.cgi"

# 5. Register with WHM
echo -e "${YELLOW}[5/7] Registering with WHM...${NC}"
/usr/local/cpanel/bin/register_appconfig "$APPS_CONF"

# 6. Kill ALL old daemon instances (aggressive — must be confirmed dead before new start)
echo -e "${YELLOW}[6/7] Stopping old daemon...${NC}"

# Disable cron watchdog FIRST so it can't resurrect the old daemon during our install
touch "$FULL_PATH/logs/.service_disabled"

# Kill any running daemon.php process (multiple attempts)
pkill -9 -f "daemon\.php" > /dev/null 2>&1
sleep 1
pkill -9 -f "daemon\.php" > /dev/null 2>&1
sleep 1

# Wait up to 10 seconds to confirm all old processes are dead
WAIT=0
while pgrep -f "daemon\.php" > /dev/null 2>&1; do
    pkill -9 -f "daemon\.php" > /dev/null 2>&1
    sleep 1
    WAIT=$((WAIT+1))
    if [ $WAIT -ge 10 ]; then
        echo -e "${RED}  WARNING: Could not kill old daemon after 10s. Forcing...${NC}"
        kill -9 $(pgrep -f "daemon\.php") > /dev/null 2>&1
        sleep 2
        break
    fi
done
echo -e "${GREEN}  Old daemon stopped.${NC}"

PHP_BIN=""
if [ -x "/usr/local/cpanel/3rdparty/bin/php" ]; then
    PHP_BIN="/usr/local/cpanel/3rdparty/bin/php"
elif [ -x "/usr/bin/php" ]; then
    PHP_BIN="/usr/bin/php"
elif [ -x "/usr/local/bin/php" ]; then
    PHP_BIN="/usr/local/bin/php"
elif command -v php > /dev/null 2>&1; then
    PHP_BIN=$(command -v php)
fi

if [ -n "$PHP_BIN" ]; then
    echo -e "${CYAN}  PHP Binary: $PHP_BIN${NC}"
    cd "$FULL_PATH"
    # Re-enable watchdog (remove the lock) BEFORE starting so cron can also auto-recover later
    rm -f "$FULL_PATH/logs/.service_disabled"
    nohup nice -n 19 $PHP_BIN "$FULL_PATH/daemon.php" > /dev/null 2>&1 &
    NEW_PID=$!
    sleep 2
    # Verify the new daemon actually started
    if kill -0 $NEW_PID 2>/dev/null; then
        echo -e "${GREEN}  Daemon started. PID: $NEW_PID${NC}"
    else
        echo -e "${RED}  WARNING: Daemon may have crashed on start. Check logs.${NC}"
    fi
else
    rm -f "$FULL_PATH/logs/.service_disabled"
    echo -e "${RED}  PHP binary not found! Daemon will not start.${NC}"
    echo -e "${RED}  Install PHP CLI: yum install php-cli${NC}"
fi

# 7. Cron Watchdog
echo -e "${YELLOW}[7/7] Installing Watchdog Cron...${NC}"
CRON_CMD="* * * * * test -f $FULL_PATH/logs/.service_disabled || pgrep -f 'daemon.php' > /dev/null 2>&1 || cd $FULL_PATH && nice -n 19 $PHP_BIN $FULL_PATH/daemon.php > /dev/null 2>&1 &"
(crontab -l 2>/dev/null | grep -v "ddosprotection"; echo "# ddosprotection watchdog"; echo "$CRON_CMD") | crontab -

/usr/local/cpanel/scripts/rebuild_whm_chrome > /dev/null 2>&1
/usr/local/cpanel/etc/init/startcpsrvd > /dev/null 2>&1

# Cleanup
rm -rf "$TMP_DIR"

echo ""
echo -e "${GREEN}╔════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║  TZ DDoS Protection v2.0.1 INSTALLED  ║${NC}"
echo -e "${GREEN}╠════════════════════════════════════════╣${NC}"
echo -e "${GREEN}║  Daemon:         AUTO-STARTED          ║${NC}"
echo -e "${GREEN}║  Watchdog:       ACTIVE (cron)         ║${NC}"
if [ "$UPDATE_MODE" = false ]; then
echo -e "${GREEN}║  Auto-Quarantine: ENABLED              ║${NC}"
echo -e "${GREEN}║  Threshold:      500 RPS (configurable)║${NC}"
else
echo -e "${GREEN}║  Update:         COMPLETED             ║${NC}"
echo -e "${GREEN}║  Data:           PRESERVED             ║${NC}"
fi
echo -e "${GREEN}║  Live RPS:       YES (no caching)      ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════╝${NC}"
