.htaccess deny/allow specific folder within the current rules

.htaccessapache-2.2

I am using a .htaccess rule similar to the below:

# BEGIN Disable access to all files EXCEPT
Order deny,allow
Deny from all

# Files
<Files ~ ".(doc|xlsx|xlsm|xls|pdf|docx|txt|rtf|rdf|odf)$">
    Allow from all
</Files>
# Page Content
<Files ~ ".(css|js)$">
    Allow from all
</Files>
# Images
<Files ~ ".(jpe?g|png|gif|bmp|cur|ico|webp)$">
    Allow from all
</Files>
# Fonts
<Files ~ ".(svgz?|eot|otf|tt[cf]|woff2?)$">
    Allow from all
</Files>

However, I also want to allow one specific .php file, I don't want to have to put a .htaccess rule in the folder where the specific .php file exists so I've been trying to do it with FilesMatch

Here are some examples:

<FilesMatch "\/folder1\/folder2\/folder3\/folder4\/\.(php)">
    Allow from all
    Satisfy Any   
</FilesMatch>

<FilesMatch "\folder1\folder2\folder3\folder4\file1.php">
    Allow from all
    Satisfy Any   
</FilesMatch>

I've even tried them with /home/hostaccount/public_html/ at the start of the location and also just /public_html/ at the start of the location.

I've tried adding ^ to the start of the location and finished it off with $ at the end.

Anyone know what I am doing wrong and more importantly how to fix it?

Best Answer

There's not much difference between <Files ~ "..."> or <FilesMatch "..."> (or <Files "..."> in this context) since they all just match against the file basename, excluding the directory path.

So, if the files basename is unique within this directory tree then you can simply do:

<Files "file-to-allow.php">
    Allow from all
</Files>

However, this will match file-to-allow.php anywhere within this directory tree, if the same file basename occurs in multiple directories.

If you needed to match the full filesystem path (or strictly speaking the URL-path), without using a .htaccess file in the target subdirectory and without access to the server config (which would allow you to use a <Directory> container), then you could perhaps do something like the following, with the help of mod_setenvif:

SetEnvIf Request_URI "^/path/to/file-to-allow\.php$" letmein

Allow from env=letmein

The SetEnvIf directive sets the environment variable letmein if the Request_URI matches the specific URL (regex). This is then used in the following Allow directive to only allow if the environment variable is set.