# Apache 2.4: protect secrets, installers and diagnostic scripts.
Options -Indexes
<FilesMatch "(?i)^(i18n\.php|improvements(?:_view)?\.php|improvement_form\.php|improvement_board\.php|project_history\.php|updater(?:_view)?\.php|site_features\.php|publication(?:_view)?\.php|system_check(?:_view)?\.php|setup-proof-[a-f0-9]{24}\.txt|site_config\.php|setup-config(?:\.example)?\.php|.*\.lock|db(?:_test)?\.php|auth\.php|functions\.php|security\.php|theme\.php|project_release\.php|admin_accounts\.php|admin_passkeys\.php|webauthn_bundle\.php|admin_account_view\.php|installation_registry\.php|installations_view\.php|download_requests\.php|download_requests_view\.php|followers\.php|followers_view\.php|info\.php|hash\.php|test_(?:thumb|write)\.php|production-upload\.zip|photography-portfolio-.*\.zip|.*\.(?:md|bak|sql|log|env))$">
    Require all denied
</FilesMatch>

# Never serve executable files from any pictures subtree.
RewriteEngine On
RewriteRule ^webauthn-lib(?:/|$) - [F,L,NC]
RewriteRule ^\.photography-updates(?:/|$) - [F,L,NC]
ErrorDocument 404 /not_found.php
RewriteRule ^(pictures/all/[^/]+\.(?:jpe?g|png|gif|webp|mp4|webm|ogg|mov)|cache/[a-f0-9]{64}\.(?:webp|jpg|png))$ media_asset.php?asset=$1 [B,L,NC]
RewriteRule ^(?:develop|archive|dev|setup|tests|tools)(/|$) - [F,NC]
RewriteRule (^|/)pictures/.*\.(php[0-9]*|phtml|pht|phar|cgi|pl|py|sh|shtml)([./]|$) - [F,NC]

# Compress text responses. Images/videos are already compressed.
<IfModule mod_deflate.c>
    <IfModule mod_filter.c>
        AddOutputFilterByType DEFLATE text/html text/plain text/css text/javascript application/javascript application/json application/xml text/xml image/svg+xml
    </IfModule>
</IfModule>

<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
    Header always set Strict-Transport-Security "max-age=15552000"
    # Script restrictions need a separate migration of existing inline handlers.
    Header always set Content-Security-Policy "frame-ancestors 'self'; base-uri 'self'; object-src 'none'; form-action 'self'"
    <FilesMatch "^(?:download|download_media|download_zip|request_download|follower|follower_subscribe|follower_admin|admin_access|admin_passkey|installation_register|improvement|improvement_push)\.php$">
        Header always set Referrer-Policy "no-referrer"
        Header always set Cache-Control "no-store"
        Header always set X-Robots-Tag "noindex, nofollow, noarchive"
    </FilesMatch>
    Header unset X-Powered-By
    Header always unset X-Powered-By
    <FilesMatch "\.(?:css|js)$">
        Header set Cache-Control "public, max-age=86400, must-revalidate"
    </FilesMatch>
</IfModule>

<FilesMatch "^geo-country-v[46]\.bin$">
    Require all denied
</FilesMatch>
