# ---------------------------
# BASIC AUTH
# ---------------------------
# Satisfy Any
# AuthType Basic
# AuthName "Input your ID and Password."
# AuthUserFile /var/www/html/.htpasswd
# Require valid-user

# ---------------------------
# php 設定
# ---------------------------
# php_value max_input_vars 99999
# php_value memory_limit 512M
# php_value post_max_size 64M
# php_value upload_max_filesize 16M

# ---------------------------
# 全体のIPアドレス制限
# ---------------------------
# <RequireAll>
#   Require not ip xxx.xxx.xxx.xxx
#   Require not ip yyy.yyy.yyy.yyy
#   Require all granted
# </RequireAll>

# ---------------------------------------
# index.php以外のPHPスクリプトを実行禁止
# ---------------------------------------
<FilesMatch "\.php$">
  Require all denied
</FilesMatch>
<Files "index.php">
  Require all granted
</Files>

# ---------------------------------------
# 隠しファイル（ドットファイル）へのアクセス禁止
# ---------------------------------------
<Files ~ "^\.">
  Require all denied
</Files>

# ---------------------------------------
# config.server.php へのアクセス禁止
# ---------------------------------------
<Files config.server.php>
  Require all denied
</Files>

# ---------------------------------------
# ビルドツールへのアクセス禁止
# ---------------------------------------
<FilesMatch "^webpack\..*\.(js|mjs|cjs|ts|mts|cts)$">
  Deny from all
</FilesMatch>

<FilesMatch "^vite\..*\.(js|mjs|cjs|ts|mts|cts)$">
  Deny from all
</FilesMatch>

<FilesMatch "^tsconfig\.jsonc?$">
  Deny from all
</FilesMatch>

<FilesMatch "^.*\.config\.(js|mjs|cjs|ts|mts|cts|json)$">
  Deny from all
</FilesMatch>

# ---------------------------------------
# ライブラリ情報ファイルへのアクセス禁止
# ---------------------------------------
<Files "package*.json">
  Deny from all
</Files>

<Files "composer.json">
  Deny from all
</Files>

<Files "composer.lock">
  Deny from all
</Files>

<Files "yarn.lock">
  Deny from all
</Files>

<Files "pnpm-lock.yaml">
  Deny from all
</Files>

# ---------------------------------
# 静的アセットのセキュリティ設定
# ---------------------------------
<FilesMatch "\.(js|css|jpg|jpeg|png|gif|webp|svg|woff|woff2|ttf|eot|ico)$">
  Header set X-Content-Type-Options "nosniff"
  Header set X-Frame-Options "SAMEORIGIN"
  Header set Referrer-Policy "strict-origin-when-cross-origin"
  Header set X-XSS-Protection "1; mode=block"
  Header set Content-Security-Policy "default-src 'self';"
  Header set Strict-Transport-Security "max-age=63072000; includeSubDomains;"
</FilesMatch>

# ---------------------------------
# 静的アセットのキャッシュ設定
# ---------------------------------
<Files ~ "\.(css|js)$">
  <IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 365 days"
  </IfModule>
  <IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE application/javascript
  </IfModule>
  <IfModule mod_headers.c>
    Header set Cache-Control "public, max-age=31536000, immutable"
  </IfModule>
  FileETag None
</Files>
<Files ~ "\.(jpg|jpeg|png|gif|webp|svg|woff|woff2|ttf|eot|ico)$">
  <IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 365 days"
  </IfModule>
  <IfModule mod_headers.c>
    Header unset ETag
    Header set Cache-Control "public, max-age=31536000, immutable"
  </IfModule>
  FileETag None
</Files>

# ---------------------------
# Contents Security Policy
# ---------------------------
# <IfModule mod_headers.c>
#   Header set Content-Security-Policy " \
#     default-src \
#       'self'; \
#     style-src \
#       'self' \
#       'unsafe-inline' \
#       *.googleapis.com \
#       *.google.com; \
#     script-src \
#       'self' \
#       'unsafe-inline' \
#       'unsafe-eval' \
#       *.google.com \
#       *.googletagmanager.com \
#       *.google-analytics.com \
#       *.googleapis.com \
#       *.googleadservices.com; \
#     img-src \
#       'self' \
#       data: \
#       *.google.com; \
#     frame-src \
#       'self' \
#       *.google.com; \
#     frame-ancestors \
#       'self'; \
#     block-all-mixed-content; \
#   "
# </IfModule>

# ---------------------------
# URL書き換え設定
# ---------------------------
RewriteEngine on
# RewriteBase /
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

# ------------------------------------------------------------------
# リクエストがURLエンコードされていたらフラグ
# %3f = ?, %26 = &, %3d = =, %25 = %, %2e = ., %2f = /, %5c = \
# 攻撃者がURLエンコードを使ってパス変換や偽装を試みた場合を検出を立てる
# ------------------------------------------------------------------
RewriteCond %{THE_REQUEST} (%3[fF]|%26|%3[dD]|%25|%2e|%2f|%5c) [NC]
RewriteRule .* - [E=has_encoded_query:1]

# ------------------------------------------------------------------
# 実行可能なスクリプト (PHP, CGI, Perl, Python, Shell, EXE) をブロック
# ------------------------------------------------------------------
# RewriteCond %{REQUEST_URI} !^/index\.php$ [NC]
# RewriteCond %{REQUEST_URI} !^/_setup/.*\.php$ [NC]
# RewriteCond %{REQUEST_URI} !^/other2/index\.php$ [NC]
# RewriteCond %{REQUEST_URI} \.(php|cgi|pl|py|sh|exe|bin|dll|bat|cmd|msi|jar)$ [NC]
# RewriteRule ^.*$ - [F,L]

# ---------------------------
# ログインページをIPアドレス制限
# ---------------------------
# RewriteCond %{REQUEST_URI} ^/login(/.*)?$ [NC]
# RewriteCond %{REMOTE_ADDR} !^xxx\.xxx\.xxx\.xxx$
# RewriteRule ^.*$ - [F,L]

# ---------------------------
# メンテナンス表示
# ---------------------------
# ErrorDocument 503 /503.html
# RewriteCond %{REQUEST_URI} !=/503.html
# RewriteCond %{REMOTE_ADDR} !=xxx.xxx.xxx.xxx
# RewriteCond %{REMOTE_ADDR} !=xxx.xxx.xxx.xxx
# RewriteRule ^.*$ - [R=503,L]

# ---------------------------
# webpフォーマット画像対応
# ---------------------------
RewriteCond %{ENV:has_encoded_query} !1
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_FILENAME} (.*)\.(jpe?g|png)$
RewriteCond %{REQUEST_FILENAME}\.webp -f
RewriteCond %{QUERY_STRING} !type=original
RewriteRule (.+)\.(jpe?g|png)$ %{REQUEST_FILENAME}.webp [T=image/webp,E=accept:1]
<IfModule mod_headers.c>
    Header append Vary Accept env=REDIRECT_accept
</IfModule>
<IfModule mod_mime.c>
    AddType image/webp .webp
</IfModule>

# ---------------------------
# wwwあり、なし正規化
# ---------------------------
# RewriteCond %{ENV:has_encoded_query} !1
# RewriteCond %{HTTP_HOST} ^(example\.com)(:80)?
# RewriteRule ^(.*)$ %{REQUEST_SCHEME}://www.example.com/$1 [R=301,NE,L]

# ---------------------------
# 特定ドメイン以外でのアクセスを拒否
# ---------------------------
# RewriteCond %{HTTP_HOST} !^www\.example\.com$
# RewriteRule .* - [F]

# -----------------------------------------
# 存在するファイルへの直指定の場合、CMSを通さない
# -----------------------------------------
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .* - [L]

# ---------------------------
# index.html なしへの正規化
# ---------------------------
RewriteCond %{ENV:has_encoded_query} !1
RewriteCond %{REQUEST_URI} ^(.*)/index.html/?$
RewriteRule .* %{REQUEST_SCHEME}://%{HTTP_HOST}%1/ [R=301,NE,L]

# ---------------------------
# 最後にスラッシュをつける
# ---------------------------
RewriteCond %{ENV:has_encoded_query} !1
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{REQUEST_URI} !\.[^/\.]+$
RewriteRule ^.+[^/]$ %{REQUEST_SCHEME}://%{HTTP_HOST}%{REQUEST_URI}/ [R=301,L]

# -----------------------------------
# 拡張子がある場合、最後のスラッシュをとる
# -----------------------------------
# RewriteCond %{ENV:has_encoded_query} !1
# RewriteCond %{REQUEST_URI} \.[^/\.]+/$
# RewriteRule ^(.*)/$ %{REQUEST_SCHEME}://%{HTTP_HOST}/$1 [L,NE,R=301]

# ------------------------------------------------------------------
# メンテナンスモード時に503ページを出力 (setup_は環境に合わせて変更して下さい)
# ------------------------------------------------------------------
# RewriteCond %{ENV:has_encoded_query} !1
# RewriteRule ^setup_/ - [L]
# RewriteRule ^(.*)$ setup_/503.php [L]

# ------------------------------------------------------------------
# a-blog cms以外のコンテンツ（a-blog cmsを動作させないコンテンツ）
# ------------------------------------------------------------------
# RewriteCond %{REQUEST_URI} !^/?other/
# RewriteCond %{REQUEST_URI} !^/?other2/
RewriteCond %{REQUEST_URI} !/js/locales/(.*)/translation.json

# ---------------------------
# CMSを実行
# ---------------------------
RewriteRule . index.php [L]
