#!/bin/bash
set -euo pipefail

# Portable paths - works from any directory
ROOT="${PRUVA_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
CODING="$ROOT/coding"

cd "$ROOT"

# Load the prepared project cache directory.
PROJECT_CACHE_DIR="$(python3 - "$ROOT/project_cache_context.json" <<'PY'
import json, sys
data = json.load(open(sys.argv[1]))
print(data.get("project_cache_dir") or "")
PY
)"

if [ -z "$PROJECT_CACHE_DIR" ]; then
    echo "ERROR: project_cache_dir not found in project_cache_context.json"
    exit 1
fi

VENV="$PROJECT_CACHE_DIR/repo/venv_google_provider_22.1.0"
PY="$VENV/bin/python"
FAKE_GCS="$PROJECT_CACHE_DIR/repo/tools/fake-gcs-server"
SITE_PKG="$VENV/lib/python3.14/site-packages"
SOURCE="$SITE_PKG/airflow/providers/google/cloud/transfers/gcs_to_sftp.py"
CANONICAL_ORIGINAL="$PROJECT_CACHE_DIR/repo/pkg/v2210/airflow/providers/google/cloud/transfers/gcs_to_sftp.py"
PATCH="$CODING/proposed_fix.diff"

if [ ! -f "$PATCH" ]; then
    echo "ERROR: patch file not found: $PATCH"
    exit 1
fi
if [ ! -f "$CANONICAL_ORIGINAL" ]; then
    echo "ERROR: canonical original source not found: $CANONICAL_ORIGINAL"
    exit 1
fi
if [ ! -f "$SOURCE" ]; then
    echo "ERROR: installed source file not found: $SOURCE"
    exit 1
fi
if [ ! -x "$FAKE_GCS" ]; then
    echo "ERROR: fake-gcs-server binary not found: $FAKE_GCS"
    exit 1
fi

# Always start from a clean original and restore it on exit.
restore() {
    echo "[verify] Restoring original gcs_to_sftp.py"
    cp "$CANONICAL_ORIGINAL" "$SOURCE"
}
trap restore EXIT
restore

echo "[verify] Applying proposed fix to installed provider source"
cd "$SITE_PKG"
patch -p1 < "$PATCH"
cd "$ROOT"

echo "[verify] === Test 1: original CVE-2026-49297 '..' traversal is rejected ==="
CVE_ROOT="$CODING/verify_cve"
CVE_OUT="$CODING/verify_cve.json"
rm -rf "$CVE_ROOT"
"$PY" "$ROOT/repro/product_harness.py" \
    --version 22.1.0 \
    --attempt 1 \
    --root "$CVE_ROOT" \
    --out "$CVE_OUT" \
    --fake-gcs-binary "$FAKE_GCS" || true

python3 - "$CVE_OUT" <<'PY'
import json, sys
path = sys.argv[1]
if not open(path).read().strip():
    print("FAILED: CVE test produced no output JSON")
    sys.exit(1)
data = json.load(open(path))
if data.get("escaped_file_exists") is not False:
    print("FAILED: '..' traversal still wrote outside destination_path")
    sys.exit(1)
if data.get("exception_type") != "ValueError":
    print("FAILED: expected ValueError for '..' traversal, got", data.get("exception_type"))
    sys.exit(1)
print("OK: '..' traversal rejected before SFTP write")
PY

echo "[verify] === Test 2: symlink bypass variant is rejected ==="
VAR_ROOT="$CODING/verify_variant"
VAR_OUT="$CODING/verify_variant.json"
rm -rf "$VAR_ROOT"
"$PY" "$ROOT/vuln_variant/symlink_variant_harness.py" \
    --version 22.1.0 \
    --attempt 1 \
    --root "$VAR_ROOT" \
    --out "$VAR_OUT" \
    --fake-gcs-binary "$FAKE_GCS" || true

python3 - "$VAR_OUT" <<'PY'
import json, sys
path = sys.argv[1]
if not open(path).read().strip():
    print("FAILED: variant test produced no output JSON")
    sys.exit(1)
data = json.load(open(path))
if data.get("escaped_file_exists") is not False:
    print("FAILED: symlink bypass still wrote outside destination_path")
    sys.exit(1)
if data.get("exception_type") != "ValueError":
    print("FAILED: expected ValueError for symlink bypass, got", data.get("exception_type"))
    sys.exit(1)
if data.get("object_contains_dotdot") is not False:
    print("FAILED: variant object should not contain '..' segment")
    sys.exit(1)
print("OK: symlink bypass rejected before SFTP write")
PY

echo "[verify] === Test 3: allow_destination_symlinks=True preserves legitimate symlink writes ==="
"$PY" "$CODING/test_symlink_allowed.py"

echo "[verify] === All verification checks passed ==="
