# OG Shortlink - Production .htaccess Configuration
# PHP 8.3 + Apache 2.4+
# Security-first configuration with best practices

# ============================================================================
# 1. SECURITY HEADERS
# ============================================================================

<IfModule mod_headers.c>
    # Prevent MIME sniffing
    Header always set X-Content-Type-Options "nosniff"

    # Prevent clickjacking
    Header always set X-Frame-Options "DENY"

    # XSS Protection (legacy browsers)
    Header always set X-XSS-Protection "1; mode=block"

    # Referrer Policy
    Header always set Referrer-Policy "no-referrer-when-downgrade"

    # Permissions Policy (disable unnecessary features)
    Header always set Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=(), usb=(), magnetometer=(), gyroscope=(), accelerometer=()"

    # Content Security Policy (strict, adjust if needed)
    # Note: Managed via bootstrap/headers.php for dynamic nonce support
    # Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; form-action 'self'"

    # HSTS (HTTP Strict Transport Security) - Enable only if HTTPS is configured
    # Uncomment after SSL setup:
    # Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS

    # Remove server signature
    Header always unset X-Powered-By
    Header always unset Server
</IfModule>

# ============================================================================
# 2. PHP SECURITY SETTINGS
# ============================================================================

<IfModule mod_php.c>
    # Disable dangerous functions (if not in php.ini)
    php_flag display_errors Off
    php_flag log_errors On
    php_value error_log /var/log/php-errors.log

    # Hide PHP version
    php_flag expose_php Off

    # Session security
    php_value session.cookie_httponly 1
    php_value session.cookie_secure 1
    php_value session.cookie_samesite Strict
    php_value session.use_strict_mode 1
    php_value session.sid_length 48

    # File upload limits
    php_value upload_max_filesize 5M
    php_value post_max_size 6M

    # Execution limits
    php_value max_execution_time 30
    php_value max_input_time 30
    php_value memory_limit 128M
</IfModule>

# ============================================================================
# 3. DIRECTORY PROTECTION
# ============================================================================

# Disable directory listing
Options -Indexes

# Deny access to hidden files and directories (except .well-known for ACME)
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_URI} "!(^|/)\.well-known/([^./]+\./?)+$" [NC]
    RewriteCond %{SCRIPT_FILENAME} -d [OR]
    RewriteCond %{SCRIPT_FILENAME} -f
    RewriteRule "(^|/)\." - [F]
</IfModule>

# Protect sensitive files
<FilesMatch "^(\.env|\.git|\.gitignore|composer\.(json|lock)|package(-lock)?\.json|phpunit\.xml|phpstan\.neon|phpcs\.xml|README\.md|INSTALL\.md|\.installed)$">
    Require all denied
</FilesMatch>

# Deny access to PHP files in sensitive directories
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule ^(data|logs|var|vendor|bin|tests|docs|database|app|bootstrap)/.*\.php$ - [F,L]
</IfModule>

# ============================================================================
# 4. FILE TYPE RESTRICTIONS
# ============================================================================

# Allow only specific file types
<FilesMatch "\.(php|html|htm|js|css|json|xml|txt|ico|png|jpg|jpeg|gif|svg|webp|woff|woff2|ttf|eot)$">
    # Files are allowed
</FilesMatch>

# Deny execution of scripts in upload directories
<Directory "*/data/*">
    <FilesMatch "\.(php|php3|php4|php5|php7|phtml|pl|py|jsp|asp|sh|cgi)$">
        Require all denied
    </FilesMatch>
    php_flag engine off
</Directory>

# ============================================================================
# 5. URL REWRITING (Main Application Logic)
# ============================================================================

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Force HTTPS (uncomment after SSL setup)
    # RewriteCond %{HTTPS} off
    # RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

    # Block suspicious request methods
    RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK|OPTIONS|CONNECT)
    RewriteRule .* - [F]

    # Block SQL injection patterns in URL
    RewriteCond %{QUERY_STRING} ([a-z0-9]{2000,}) [NC,OR]
    RewriteCond %{QUERY_STRING} (union.*select.*\() [NC,OR]
    RewriteCond %{QUERY_STRING} (concat.*\() [NC,OR]
    RewriteCond %{QUERY_STRING} (eval\(.*\)) [NC,OR]
    RewriteCond %{QUERY_STRING} (base64_(en|de)code.*\() [NC,OR]
    RewriteCond %{QUERY_STRING} (<script.*>.*</script>) [NC]
    RewriteRule .* - [F,L]

    # Block common attack patterns
    RewriteCond %{REQUEST_URI} (\.\.\/|\.\.\\) [NC,OR]
    RewriteCond %{REQUEST_URI} (\/\~) [NC,OR]
    RewriteCond %{REQUEST_URI} (\<script) [NC,OR]
    RewriteCond %{REQUEST_URI} (javascript\:) [NC,OR]
    RewriteCond %{REQUEST_URI} (etc\/passwd|usr\/bin) [NC]
    RewriteRule .* - [F,L]

    # Don't rewrite existing files and directories
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]

    # API routes
    RewriteRule ^api/shortlinks$ api/shortlinks.php [L,NC]

    # Shortcode redirect: /Abc_123 or /x-y_z (3-32 chars)
    # Supports: alphanumeric, underscore, hyphen
    RewriteRule ^([A-Za-z0-9_-]{3,32})$ index.php?code=$1 [L,QSA]
</IfModule>

# ============================================================================
# 6. COMPRESSION & CACHING
# ============================================================================

# Enable GZIP compression
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript
    AddOutputFilterByType DEFLATE application/javascript application/x-javascript application/json application/xml
    AddOutputFilterByType DEFLATE image/svg+xml

    # Don't compress images/binaries
    SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|ico)$ no-gzip
</IfModule>

# Browser caching for static assets
<IfModule mod_expires.c>
    ExpiresActive On

    # Images
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/webp "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 year"
    ExpiresByType image/x-icon "access plus 1 year"

    # Fonts
    ExpiresByType font/woff "access plus 1 year"
    ExpiresByType font/woff2 "access plus 1 year"
    ExpiresByType font/ttf "access plus 1 year"
    ExpiresByType font/eot "access plus 1 year"

    # CSS, JavaScript
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType text/javascript "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
    ExpiresByType application/x-javascript "access plus 1 month"

    # HTML, JSON (don't cache)
    ExpiresByType text/html "access plus 0 seconds"
    ExpiresByType application/json "access plus 0 seconds"
</IfModule>

# Cache-Control headers
<IfModule mod_headers.c>
    # Cache static assets
    <FilesMatch "\.(ico|jpg|jpeg|png|gif|svg|webp|css|js|woff|woff2|ttf|eot)$">
        Header set Cache-Control "public, max-age=31536000, immutable"
    </FilesMatch>

    # Don't cache dynamic content
    <FilesMatch "\.(php|html|htm|json)$">
        Header set Cache-Control "no-store, no-cache, must-revalidate, max-age=0"
        Header set Pragma "no-cache"
    </FilesMatch>
</IfModule>

# ============================================================================
# 7. ERROR HANDLING
# ============================================================================

# Custom error pages (create these in public/ directory)
# ErrorDocument 400 /errors/400.html
# ErrorDocument 401 /errors/401.html
# ErrorDocument 403 /errors/403.html
# ErrorDocument 404 /errors/404.html
# ErrorDocument 500 /errors/500.html
# ErrorDocument 503 /errors/503.html

# ============================================================================
# 8. ADDITIONAL SECURITY
# ============================================================================

# Limit request size (prevent DoS)
LimitRequestBody 10485760

# Disable server-side includes
<IfModule mod_include.c>
    Options -Includes
</IfModule>

# Disable CGI execution
<IfModule mod_cgi.c>
    Options -ExecCGI
</IfModule>

# Prevent access to backup and temporary files
<FilesMatch "(\.(bak|config|dist|fla|inc|ini|log|psd|sh|sql|swp)|~)$">
    Require all denied
</FilesMatch>

# ============================================================================
# 9. PERFORMANCE TUNING
# ============================================================================

# Enable Keep-Alive
<IfModule mod_headers.c>
    Header set Connection keep-alive
</IfModule>

# ETags for better caching
FileETag MTime Size

# ============================================================================
# END OF CONFIGURATION
# ============================================================================

# NOTE: After deploying to production:
# 1. Uncomment HSTS header after SSL is configured
# 2. Uncomment HTTPS redirect after SSL is configured
# 3. Create custom error pages in public/errors/
# 4. Test all security headers: securityheaders.com
# 5. Verify CSP doesn't block legitimate resources
# 6. Monitor error logs for blocked requests

# BEGIN cPanel-generated php ini directives, do not edit
# Manual editing of this file may result in unexpected behavior.
# To make changes to this file, use the cPanel MultiPHP INI Editor (Home >> Software >> MultiPHP INI Editor)
# For more information, read our documentation (https://go.cpanel.net/EA4ModifyINI)
<IfModule php8_module>

</IfModule>
<IfModule lsapi_module>

</IfModule>
# END cPanel-generated php ini directives, do not edit

# php -- BEGIN cPanel-generated handler, do not edit
# Set the “ea-php81” package as the default “PHP” programming language.
<IfModule mime_module>
  AddHandler application/x-httpd-ea-php81 .php .php8 .phtml
</IfModule>
# php -- END cPanel-generated handler, do not edit
