#!/bin/sh
# Fuzzes a local HTTP server (no network access required) and checks that
# ffuf's JSON output correctly reports matched and unmatched paths.
set -e

WORKDIR=$(mktemp -d)
SERVER_PID=""

cleanup() {
	[ -n "$SERVER_PID" ] && kill "$SERVER_PID" 2>/dev/null
	rm -rf "$WORKDIR"
}
trap cleanup EXIT

echo "secret content" > "$WORKDIR/secret.txt"
echo "<html>ok</html>" > "$WORKDIR/index.html"
printf 'index.html\nsecret.txt\ndoesnotexist\n' > "$WORKDIR/wordlist.txt"

PORT=$(python3 -c 'import socket; s = socket.socket(); s.bind(("127.0.0.1", 0)); print(s.getsockname()[1]); s.close()')

python3 -m http.server "$PORT" --bind 127.0.0.1 --directory "$WORKDIR" >/dev/null 2>&1 &
SERVER_PID=$!

python3 - "$PORT" <<'PYEOF'
import socket
import sys
import time

port = int(sys.argv[1])
for _ in range(20):
    try:
        with socket.create_connection(("127.0.0.1", port), timeout=0.5):
            sys.exit(0)
    except OSError:
        time.sleep(0.25)
sys.exit("timed out waiting for local http server")
PYEOF

ffuf -w "$WORKDIR/wordlist.txt" -u "http://127.0.0.1:$PORT/FUZZ" -mc 200 -of json -o "$WORKDIR/result.json" -s

python3 - "$WORKDIR/result.json" <<'PYEOF'
import json
import sys

with open(sys.argv[1]) as fh:
    data = json.load(fh)

found = {r["input"]["FUZZ"] for r in data["results"]}

assert "index.html" in found, "expected index.html to be matched: %r" % found
assert "secret.txt" in found, "expected secret.txt to be matched: %r" % found
assert "doesnotexist" not in found, "unexpected match for doesnotexist: %r" % found

print("local-fuzz: %d matches as expected" % len(found))
PYEOF
