# --------------------------------
# FileRise portable .htaccess
# --------------------------------
Options -Indexes -Multiviews
DirectoryIndex index.php index.html

# Allow PATH_INFO for routes like /webdav.php/foo/bar
AcceptPathInfo On

# ---------------- Security: dotfiles ----------------
<IfModule mod_authz_core.c>
  # Block direct access to dotfiles like .env, .gitignore, etc.
  <FilesMatch "^\..*">
    Require all denied
  </FilesMatch>
</IfModule>

# ---------------- Rewrites ----------------
<IfModule mod_rewrite.c>
RewriteEngine On

# 0) Let ACME http-01 pass BEFORE any other rule (needed for auto-renew)
RewriteCond %{REQUEST_URI} ^/.well-known/acme-challenge/
RewriteRule - - [L]

# 1) Block hidden files/dirs anywhere EXCEPT .well-known (path-aware)
#    Prevents requests like /.env, /.git/config, /.ssh/id_rsa, etc.
#    Allow dotpaths only through WebDAV (scoped to /webdav.php).
RewriteCond %{REQUEST_URI} !^/webdav\.php/ [NC]
RewriteRule "(^|/)\.(?!well-known/)" - [F]
RewriteRule ^portal/([A-Za-z0-9_-]+)$ portal.html?slug=$1 [L,QSA]
# Keep entrypoint consistent: serve /index.html through index.php.
RewriteRule ^index\.html$ index.php [L,QSA]

# 2) Deny direct access to PHP except the API endpoints and WebDAV front controller
#    - allow /api/*.php (API endpoints)
#    - allow /api.php     (ReDoc/spec page)
#    - allow /webdav.php  (SabreDAV front)
RewriteCond %{REQUEST_URI} !^/api/ [NC]
RewriteCond %{REQUEST_URI} !^/api\.php$ [NC]
RewriteCond %{REQUEST_URI} !^/webdav\.php$ [NC]
RewriteCond %{REQUEST_URI} !^/index\.php$ [NC]
RewriteRule \.php$ - [F,L]

# 3) Never redirect local/dev hosts
RewriteCond %{HTTP_HOST} ^(localhost|127\.0\.0\.1|fr\.local|192\.168\.[0-9]+\.[0-9]+)$ [NC]
RewriteRule ^ - [L]

# 4) HTTPS redirect (enable ONE of these, comment the other)

# A) Direct TLS on this server
#RewriteCond %{HTTPS} !=on
#RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# B) Behind reverse proxy that sets X-Forwarded-Proto
#RewriteCond %{HTTP:X-Forwarded-Proto} =http [OR]
#RewriteCond %{HTTP:X-Forwarded-Proto} ^$
#RewriteCond %{HTTPS} !=on
#RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# 5) Mark versioned assets (?v=...) with env flag for caching rules below
RewriteCond %{QUERY_STRING} (^|&)v= [NC]
RewriteRule ^ - [E=IS_VER:1]
</IfModule>

# ---------------- MIME types ----------------
<IfModule mod_mime.c>
  AddType font/woff2 .woff2
  AddType font/woff  .woff
  AddType image/svg+xml .svg
  AddType application/javascript .mjs
</IfModule>

# ---------------- Security headers ----------------
<IfModule mod_headers.c>
  Header always set X-Frame-Options "SAMEORIGIN"
  Header always set X-XSS-Protection "1; mode=block"
  Header always set X-Content-Type-Options "nosniff"
  Header always set Referrer-Policy "strict-origin-when-cross-origin"
  Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
  Header always set X-Download-Options "noopen"
  Header always set Expect-CT "max-age=86400, enforce"
  Header always set Cross-Origin-Resource-Policy "same-origin"
  Header always set X-Permitted-Cross-Domain-Policies "none"

  # HSTS only when HTTPS (safe for .htaccess)
  Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS

  # CSP baseline (pretheme bootstrap is external JS, so no inline script hash is required).
  Header always set Content-Security-Policy "default-src 'self'; base-uri 'self'; frame-ancestors 'self'; object-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self'; connect-src 'self'; media-src 'self' blob:; worker-src 'self' blob:; form-action 'self'"
</IfModule>

# ---------------- Caching ----------------
<IfModule mod_headers.c>
  # HTML/PHP: no cache
  <FilesMatch "\.(html?|php)$">
    Header setifempty Cache-Control "no-cache, no-store, must-revalidate"
    Header setifempty Pragma "no-cache"
    Header setifempty Expires "0"
  </FilesMatch>

  # version.js: never cache
  <FilesMatch "^js/version\.js$">
    Header set Cache-Control "no-cache, no-store, must-revalidate"
    Header set Pragma "no-cache"
    Header set Expires "0"
  </FilesMatch>

  # JS/CSS: long cache if ?v= present, else 1h
  <FilesMatch "\.(?:m?js|css)$">
    Header set Cache-Control "public, max-age=31536000, immutable" env=IS_VER
    Header set Cache-Control "public, max-age=3600, must-revalidate" env=!IS_VER
  </FilesMatch>

  # Images/fonts: long cache if ?v= present, else 7d
  <FilesMatch "\.(?:png|jpe?g|gif|webp|svg|ico|woff2?|ttf|otf)$">
    Header set Cache-Control "public, max-age=31536000, immutable" env=IS_VER
    Header set Cache-Control "public, max-age=604800" env=!IS_VER
  </FilesMatch>
</IfModule>

# ---------------- Compression ----------------
<IfModule mod_brotli.c>
  AddOutputFilterByType BROTLI_COMPRESS text/html text/css application/javascript application/json image/svg+xml
</IfModule>
<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/css application/javascript application/json image/svg+xml
</IfModule>

# ---------------- Disable TRACE ----------------
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_METHOD} ^TRACE
RewriteRule .* - [F]
</IfModule>
