# ─── Freebuff Image Host — Apache Configuration ──────────────────
# Place this file in the public/ directory (DocumentRoot).
# Requires: AllowOverride All (or AuthConfig + FileInfo + Options)
#           mod_rewrite enabled
# ─────────────────────────────────────────────────────────────────

# Enable rewrite engine
RewriteEngine On

# ─── Force HTTPS (optional) ──────────────────────────────────────
# Most cPanel accounts have a "Force HTTPS Redirect" toggle in the
# Domains panel — prefer that if available, since it runs before
# .htaccess is even read. Uncomment below only if that toggle isn't
# available and SSL is already active on this domain/subdomain.
# RewriteCond %{HTTPS} off
# RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# ─── Image serving: /i/{64-char-hex-token} → serve.php ──────────
# Route clean URLs to the PHP image server.
# Token must be exactly 64 lowercase hex characters.
RewriteRule ^i/([a-f0-9]{64})$ serve.php?token=$1 [L,QSA]

# ─── Deny access to any dot-file or dot-directory ────────────────
# Covers .env, .git, .htaccess itself, .user.ini, etc. at any depth —
# not just the top-level filename, unlike a plain <FilesMatch>.
RewriteRule "(^|/)\." - [F]

<FilesMatch "^\.">
    Require all denied
</FilesMatch>

# ─── Deny access to other non-public source/config files ─────────
<FilesMatch "\.(sql|log|lock|md|ini|conf|sh|bak|zip)$">
    Require all denied
</FilesMatch>

# ─── Protect sensitive directories ───────────────────────────────
# Block access to config/, src/, storage/, cron/, and .env
# These rules apply even if Apache is misconfigured to serve from parent,
# or if the app root itself is ever exposed as a document root by mistake.
<DirectoryMatch "^/.*/(config|src|storage|cron)">
    Require all denied
</DirectoryMatch>

# Deny .env at any level
<Files ".env">
    Require all denied
</Files>

# ─── Prevent PHP execution inside storage/ ───────────────────────
# If somehow a .php file ends up in storage/, it must not execute.
# This uses both <FilesMatch> and a directory-level rule for defense-in-depth.
<DirectoryMatch ".*/storage(/|$)">
    <FilesMatch "\.php$">
        Require all denied
    </FilesMatch>
</DirectoryMatch>

# ─── Security headers ───────────────────────────────────────────
<IfModule mod_headers.c>
    Header set X-Content-Type-Options "nosniff"
    Header set X-Frame-Options "DENY"
    Header set Referrer-Policy "strict-origin-when-cross-origin"
    Header set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()"
    # HSTS: enable if serving over HTTPS in production
    # Header set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    # Remove server identification
    Header unset X-Powered-By
    Header unset Server
</IfModule>

# ─── Disable server signature ───────────────────────────────────
ServerSignature Off

# ─── Prevent directory listing ──────────────────────────────────
Options -Indexes

# ─── Content Security Policy for HTML pages ─────────────────────
# Applied to PHP responses that don't already set CSP.
# The image serving endpoint (serve.php) sets its own restrictive CSP.
<IfModule mod_headers.c>
    Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.tailwindcss.com; style-src 'self' 'unsafe-inline' https://cdn.tailwindcss.com; img-src 'self' data: blob: https:; connect-src 'self'; font-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'" env=REDIRECT_STATUS
</IfModule>
