#!/usr/bin/env bash
#
# onx-modsec-vendor-list — Kurulu ModSecurity vendor ruleset'leri listele.
#
# v43: AlmaLinux mod_modsecurity_crs RPM destegi eklendi.
#
# Output: {"vendors":[{slug, name, version, rules_count, install_path, is_official, installed}]}

set -uo pipefail

# Per-vendor: slug:name:check_paths:version_paths
# CRS için birden fazla path desteklenir.
detect_vendor() {
    local slug="$1" name="$2" is_official="$3"
    local found_path=""
    local version=""
    local rules_count=0
    local installed="false"

    # Vendor-specific path discovery
    case "$slug" in
        owasp_crs)
            # v52: Manuel install (CRS Update sayfasi /etc/httpd/modsecurity.d/owasp-crs)
            # RPM'den (May 2024 3.3.5) ONCELIKLI. RPM path en sona.
            for p in \
                "/etc/httpd/modsecurity.d/owasp-crs/rules" \
                "/etc/modsecurity.d/owasp-crs/rules" \
                "/usr/local/owasp-crs/rules" \
                "/etc/httpd/modsecurity.d/activated_rules" \
                "/usr/share/mod_modsecurity_crs/rules"; do
                [[ -d "$p" ]] && { found_path="$p"; installed="true"; break; }
            done
            # v52b: Version detection oncelik:
            #   1. DB modsecurity_settings.crs_version (UI Update sayfasi yazar - en guncel)
            #   2. CHANGES.md path (manuel install)
            #   3. RPM (en eski)
            # NOT: RPM paket + manuel install ayni anda olabilir; RPM eski kalir.
            if [[ -r /etc/onoxsoft/db.env ]] && command -v mysql >/dev/null; then
                db_version=$(set -a; source /etc/onoxsoft/db.env; set +a
                    MYSQL_PWD="$DB_PASSWORD" mysql -h"$DB_HOST" -u"$DB_USERNAME" \
                        -D"$DB_DATABASE" -BNe "SELECT value FROM modsecurity_settings WHERE \`key\`='crs_version' LIMIT 1" 2>/dev/null)
                [[ -n "$db_version" ]] && version="$db_version"
            fi
            # 2. CHANGES.md path (manuel install onceli, RPM son)
            if [[ -z "$version" ]]; then
                for vf in \
                    /etc/httpd/modsecurity.d/owasp-crs/CHANGES.md \
                    /etc/modsecurity.d/owasp-crs/CHANGES.md \
                    /usr/local/owasp-crs/CHANGES.md \
                    /usr/share/doc/mod_security_crs/CHANGES.md \
                    /usr/share/doc/mod_modsecurity_crs/CHANGES.md \
                    /usr/share/mod_modsecurity_crs/CHANGES.md; do
                    [[ -r "$vf" ]] || continue
                    version=$(grep -oE '^(##?[[:space:]]+)?v?[0-9]+\.[0-9]+\.[0-9]+' "$vf" 2>/dev/null \
                        | head -1 | sed -E 's/^#+[[:space:]]*v?//;s/^v//')
                    [[ -n "$version" ]] && break
                done
            fi
            # 3. RPM fallback (en eski olabilir, manuel install RPM'i bozmaz)
            if [[ -z "$version" ]]; then
                for pkg in mod_modsecurity_crs mod_security_crs; do
                    if rpm -q "$pkg" >/dev/null 2>&1; then
                        version="$(rpm -q --qf '%{VERSION}' "$pkg" 2>/dev/null)"
                        [[ -n "$version" ]] && break
                    fi
                done
            fi
            ;;
        comodo_cwaf)
            for p in /etc/httpd/modsecurity.d/comodo /etc/modsecurity.d/comodo /opt/comodo-cwaf; do
                [[ -d "$p" ]] && { found_path="$p"; installed="true"; break; }
            done
            ;;
        atomicorp)
            for p in /etc/httpd/modsecurity.d/atomicorp /etc/modsecurity.d/atomicorp /opt/atomicorp; do
                [[ -d "$p" ]] && { found_path="$p"; installed="true"; break; }
            done
            ;;
    esac

    [[ -z "$version" ]] && version="unknown"

    # Rules count
    if [[ -n "$found_path" && -d "$found_path" ]]; then
        # SecRule count (grep -hc her dosya)
        local total=0
        for f in "$found_path"/*.conf; do
            [[ -f "$f" ]] || continue
            local c
            c=$(grep -cE '^[[:space:]]*SecRule' "$f" 2>/dev/null || echo 0)
            total=$((total + c))
        done
        # Symlink dosyalari (activated_rules) varsa onlari da say
        if [[ -d "$found_path" && "$found_path" =~ activated_rules ]]; then
            for f in "$found_path"/*.conf; do
                [[ -L "$f" ]] || continue
                local tgt
                tgt=$(readlink -f "$f" 2>/dev/null)
                [[ -f "$tgt" ]] && total=$((total + $(grep -cE '^[[:space:]]*SecRule' "$tgt" 2>/dev/null || echo 0)))
            done
        fi
        rules_count=$total
    fi

    [[ -z "$found_path" ]] && found_path="(not installed)"

    jq -nc \
        --arg slug "$slug" --arg name "$name" --arg version "$version" \
        --argjson rules_count "${rules_count:-0}" --arg path "$found_path" \
        --argjson is_official "$is_official" --argjson installed "$installed" \
        '{slug:$slug, name:$name, version:$version, rules_count:$rules_count, install_path:$path, is_official:$is_official, installed:$installed}'
}

vendors_json="["
first=1
for vendor_def in \
    "owasp_crs:OWASP Core Rule Set:true" \
    "comodo_cwaf:Comodo WAF:false" \
    "atomicorp:Atomicorp Free WAF:false"; do
    IFS=: read -r slug name official <<<"$vendor_def"
    rec=$(detect_vendor "$slug" "$name" "$official")
    [[ -z "$rec" ]] && continue
    [[ $first -eq 0 ]] && vendors_json+=","
    first=0
    vendors_json+="$rec"
done
vendors_json+="]"

jq -nc --argjson vendors "$vendors_json" '{ok:true, vendors:$vendors}'
