# Holiday Expert CRM — web server rules

# The database and any backups must never be downloadable. -wal and -shm are
# the two files SQLite keeps beside the database now that it runs in WAL mode;
# the -wal one holds recently written rows, so it matters as much as the
# database itself.
<FilesMatch "\.(sqlite|sqlite3|db|sql|log|bak)$|-(wal|shm)$">
  Require all denied
</FilesMatch>

# release notes, build and update scripts are for us, not for visitors (v6.56)
<FilesMatch "\.(md|sh|command)$|^(config|config\.platform|platform\.config)\.example\.php$|^platform\.config\.php$|^build_manifest\.php$">
  Require all denied
</FilesMatch>

# hide dot files
<FilesMatch "^\.">
  Require all denied
</FilesMatch>

# nothing in the upload folders may ever execute
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteRule ^(db|includes)/ - [F,L]
  RewriteRule ^uploads/.*\.(php|phtml|phar|cgi|pl|py|sh)$ - [F,L]
</IfModule>

# Room for a package file.
#
# A package carries its own images, so one exported from the itinerary maker
# is routinely tens of megabytes — far past PHP's 2 MB default, which refuses
# the upload before a single line of this CRM runs. These two lines raise it
# where the server lets them: php_value works under Apache's mod_php, and the
# .user.ini beside this file does the same job under FastCGI and PHP-FPM.
#
# If neither takes (some shared hosts ignore both), raise upload_max_filesize
# and post_max_size in php.ini. The CRM says which number stopped it.
<IfModule mod_php.c>
  php_value upload_max_filesize 128M
  php_value post_max_size 132M
</IfModule>
<IfModule mod_php7.c>
  php_value upload_max_filesize 128M
  php_value post_max_size 132M
</IfModule>
<IfModule mod_php8.c>
  php_value upload_max_filesize 128M
  php_value post_max_size 132M
</IfModule>

# The passport reader's training data (assets/vendor/tesseract). It is a plain
# binary file the browser downloads once and then keeps, so it is named here
# for two reasons: to be sure it is served as a file rather than guessed at,
# and to let it be cached hard — it is the same file in every release. (v6.85)
<FilesMatch "\.traineddata$">
  ForceType application/octet-stream
  <IfModule mod_headers.c>
    Header set Cache-Control "public, max-age=31536000"
  </IfModule>
</FilesMatch>

# sensible defaults
Options -Indexes
DirectoryIndex login.php index.php

<IfModule mod_headers.c>
  Header set X-Content-Type-Options "nosniff"
  Header set X-Frame-Options "SAMEORIGIN"
  Header set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
