# Everything enters through index.php.
#
# Deliberately no RewriteBase. Apache uses the directory this file sits
# in as the base, so exactly this file works at a domain root, in a
# subfolder of public_html, and at http://localhost/evenz — which is the
# whole reason the entry point moved here. The previous layout needed the
# document root pointed at public/, and on a cPanel account where that
# cannot be done it put /public into every generated URL.

Options -Indexes
Options +FollowSymLinks

# ── The Authorization header ─────────────────────────────────────────
#
# Apache does not hand this to PHP under CGI or FastCGI unless told to,
# so "Authorization: Bearer <key>" — the way every HTTP client sends a
# token — arrives empty and the API answers "send your key" to a caller
# that did. It lives here as well as in public/.htaccess because this is
# the file in play when the app is served from a subfolder rather than
# with the document root pointed at public/.
<IfModule mod_setenvif.c>
  SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
</IfModule>
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTP:Authorization} .
  RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
</IfModule>

# ── Nothing outside public/ is ever served directly ──────────────────
#
# <Files> and <FilesMatch> are inherited by every subdirectory and Apache
# gives no way to scope them from here, so a blanket "deny all .php"
# would also deny index.php and 403 the whole site. Protection stays
# per-directory (config/.htaccess, lib/.htaccess, …); only rules that are
# safe to inherit live here.
<Files "router.php">
    Require all denied
</Files>

# install.php is NOT blocked here, and that is deliberate.
#
# A first run has to be able to reach it — the whole point is that
# somebody who has just unzipped this can open the site and be taken to
# a setup form rather than told to edit a PHP file. Apache cannot make
# that conditional on whether the software is installed without knowing
# where config/config.php sits on this particular host, so the lock is
# in install.php itself: once there is a configuration, a schema and an
# administrator, it answers 403 and says only "already installed,
# delete this file".
#
# Delete install.php and public/install.php after installing anyway.
# A guard you can remove is better than a guard you rely on.

<FilesMatch "^(composer\.(json|lock|phar)|deploy-manifest\.json|version\.php)$">
    Require all denied
</FilesMatch>

# Dotfiles, dumps and backups, anywhere in the tree. No "php" and no
# "json" — the application needs both.
<FilesMatch "^\.|\.(sql|log|lock|bak|old|dist|ini|env|sample|md)$">
    Require all denied
</FilesMatch>

<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header unset X-Powered-By

    # X-Frame-Options deliberately absent here. PHP sets it (bootstrap),
    # because the embed widgets must be framable on other people's sites
    # and only PHP knows which request is a widget. An "always set" here
    # cannot be undone by header_remove() — mod_headers runs after PHP —
    # which is exactly how the widgets got silently blocked before.
</IfModule>

<IfModule mod_rewrite.c>
    RewriteEngine On

    # ── Version-control metadata, by path ────────────────────────────
    #
    # This has to be a rewrite and it has to be here. <FilesMatch "^\.">
    # above matches the *basename*, and the basename of .git/config is
    # "config" — no leading dot, so it never matched and .git/config,
    # .git/HEAD and the object files all answered 200 while every other
    # sensitive path answered 403. That is enough to reconstruct the
    # entire source tree from a live site with git clone.
    #
    # It must also sit above the "-f is served as-is" rule below: those
    # are real files on disk, so that rule ends the round and hands them
    # straight to Apache.
    RewriteRule (^|/)\.(git|svn|hg|bzr)(/|$) - [F,L]

    # Assets and uploads still live under public/, and are served from
    # there without appearing in the URL. This is what keeps /assets/…
    # and /uploads/… working while public/ is no longer the web root —
    # and what means 64 MB of uploads did not have to move.
    RewriteRule ^(assets|uploads)/(.*)$ public/$1/$2 [L]

    # A real file or directory is served as-is.
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]

    # Everything else is the application's problem.
    RewriteRule ^(.*)$ index.php?_route=$1 [QSA,L]
</IfModule>

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript
    AddOutputFilterByType DEFLATE application/javascript application/json
    AddOutputFilterByType DEFLATE image/svg+xml
</IfModule>
