I have a front controller in my PHP project. Here is the code;
.htaccess
file
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [PT,L]
</IfModule>
index.php
file
<?php
list($url) = explode('?', $_SERVER['REQUEST_URI']);
$url = trim(trim($url), '/');
if(!file_exists('pages/'.$url.'.php')
header('Location: 404.html');
require_once 'inc/head.php';
require_once 'pages/'.$url.'.php';
require_once 'inc/foot.php';
?>
I assumed every requested URL must go through index.php file. But if there is a \
(as %5C) in URL server answer is "Not Found".
Questions;
\
character? Is there any characters like that?\
character to make Apache search for a file? Why not just ignore?Note: My system is Windows with Apache 2.2.21 and PHP 5.3.10. Note2: This is just an example code, so do not offer a better way.
Comment above said it already:
On Windows \
is the path separator So requesting 'http://localhost/\'
on a windows system will be caught by the RewriteCond %{REQUEST_FILENAME} -d
, simply your document root, which is a directory.
You have inverted the condition, d (!-d
) so apache does not execute the rewrite rule but looks for the default index file, which does not exist, you get a 404
Remove the condition "not a existing directory" or add the index.php to the list of defaults
EDIT:
The story I wrote had such a plausible character that I believed it by myself :) Indeed, this is not even Windows but Apache specific.
Because of a security leak in CGI
Apache introduced this as a fix many years ago. Instead of processing the request, it immediately returns a 404 Not Found
, when you pass either %5C (backslash)
or %2F (slash)
in the request URL.
I was able to reproduce this on a Apache 2.2.14
.
If you do not use CGI
( e.g. Perl website ) you can safely disable this "security fix":
AllowEncodedSlashes On
This was introduced in Apache 2.0.46, see documentation, setting this variable didn't work in my .htaccess
, I had to put it into the vhost config
and restart the apache
server.