0

My project directory structure:

project_root/
|- src/
|  |- model/
|  |- view/
|  |- controller/
|  -- ...others
-- resources/
   |- css/
   |- js/
   -- images/

Ok, somewhere in src there is a file responsible for redirecting controllers, views and so on, let us say it is the src/url_mapping.php, it is prepared to solve any kind of url, such as /{controller}/{action}/{id}?{query}, there is no problem here, the big deal is I do not want the user realize this folder structure exists, I want to hide it from them and let the flow as simples as RoR and other based systems.

I want allow only http://host/{css,js,images}/* from resources without allowing http://host/resources/* itself, and http://host/{controller}/{action}/{id}?{query} to the src/url_mapping.php file denying direct access to http://host/src.

For now, the closest I managed is the following .htaccess file:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /

    RewriteCond %{DOCUMENT_ROOT}/resources/$1 !-f
    RewriteCond %{DOCUMENT_ROOT}/resources/$1 !-d
    RewriteCond %{DOCUMENT_ROOT}/resources/$1 !-l
    RewriteRule (?!^resources/|^src/url_mapping.php/)^(.*)$ src/url_mapping.php/$1 [L,PT]

    RewriteCond %{DOCUMENT_ROOT}/resources/$1 -f [OR]
    RewriteCond %{DOCUMENT_ROOT}/resources/$1 -d [OR]
    RewriteCond %{DOCUMENT_ROOT}/resources/$1 -l
    RewriteRule (?!^resources/)^(.*)$ /resources/$1 [L,PT]
</IfModule>

In that case my first intention was: If users tries to get /resources or /src folder it will be filtered by src/url_mapping.php as well, although I am trying several combinations with no success over and over again.

I noted mod_rewrite are in loop such a way I can not block resources directory as well as src/url_mapping.php, I am limited to .htaccess file with my hands tied, but if there is another way to do that I will accept the solution.

The last choice is do only one redirect and treating even files in resources by src/url_mapping.php, but it will kill the cache, I am avoiding reinvent the wheel.

Tiago Pimenta
  • 736
  • 7
  • 20

1 Answers1

0

Well, I realised apache is not so smart, so an acceptable solution I found was changing the directory tree to hide the non-resources content such a way apache cannot access.

Imagine the DocumentRoot is /home/user/www, so if you browse to http://hostname/somefile will point to /home/user/www/somefile, this way files in /home/user/somedir/somefile is not accessible by apache, but could be accessible by your PHP script if it has ownership/permission over that directory.

So, everything in resources I put on /home/user/www and the src was on /home/user/private_html, only my url_mapping.php stayed on /home/user/www/index.php, this way I can fool the user if I throw 404 Not Found when direct accessing it.

The final tree:

project_root
|- private_html
|  |- model
|  |- view
|  |- controller
|  -- ...others
-- public_html
   |- css
   |- js
   |- images
   -- index.php

Where my .htaccess file is:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase / # Change it if there are a subdirectory

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-l
    RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>

And my index.php is:

<?php

if (!array_key_exists('REDIRECT_URL', $_SERVER) && substr($_SERVER['REQUEST_URI'], 0, strlen($_SERVER['SCRIPT_NAME'])) == $_SERVER['SCRIPT_NAME']) {
    header('HTTP/1.0 404 Not Found');
    exit;
}

define('VALID_KERNEL', true);

require '../private_html/core/core.php';

$server = new Server();
$server->request(array_key_exists('PATH_INFO', $_SERVER) ? $_SERVER['PATH_INFO'] : '/', $_REQUEST);

?>

This way it permits to access index.php only if it is the DirectoryIndex, I mean, http://hostname/ is allowed but http://hostname/index.php is 404 Not Found because this file should not exist, as well as http://hostname/index.php/anything and http://hostname/index.php?anything, although http://hostname/anything will redirect to http://hostname/index.php/anything but with REDIRECT_URL so it is allowed.

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
Tiago Pimenta
  • 736
  • 7
  • 20