Methods for accessing files outside root - php

Hi all :D My file structure is as follow:
/site
/public_html
/1
/2
/3
read.php
/file
file.doc
For security reasons, I moved my docs outside public_html folder.
Inside read.php, I am accessing file.doc via code "../../../../file/file.doc"
Are there other methods (shortcuts?) to access the doc? I call on a lot of files from many locations. This code is too long and easy to lose track on how many ../ I need.

If your virtual host is rooted on /site/public_html you can shorten it a little by using $_SERVER['DOCUMENT_ROOT']; this should work for all scripts underneath the document root in the same manner.
$file = $_SERVER['DOCUMENT_ROOT']. '/../file/file.doc';

You can set a ROOT constant that points to the root:
# on read.php
define('ROOT', dirname(dirname(dirname(dirname(dirname(__FILE__))))).DIRECTORY_SEPARATOR;
and then just call:
# anywhere else
include ROOT.'file/file.doc';

Related

How can I make the php files inside an includes/ folder readable by the website but not downloadable by file download managers?

I have a small PHP/MySQL project I would like to upload to our subdomain. The project has an includes/ folder that contains some PHP files that have information about the database name, username, password and login function.
How can I make the files of this directory readable by the website (so when someone comes to the website, they can log in and do other stuff) but not accessible to the public? I can use a file downloader to download the content of the folder which is something I want to block.
Is the solution using a .htaccess file?
EDIT:
Thank you all for the answer. After some reading, I switched my folder structure to be like this:
includes/
- initiate.php
- login.inc.php
- functions.inc.php
public/
- index.php
- login.php
templates/
- header.php
- footer.php
I'm now having issues setting up relative and absolute path constants though
The initiate.php has my constant variables:
define('INITIATE_FOLDER', dirname(__FILE__));
define('ROOT_FOLDER', dirname(INITIATE_FOLDER));
define('TEMPLATES', ROOT_FOLDER . '/templates');
define('INCLUDES', ROOT_FOLDER . '/includes');
define('WWW_ROOT', ROOT_FOLDER . '/public');
When I echo out the constants, I get the followings:
echo INITIATE_FOLDER; C:\wamp64\www\project\includes
echo ROOT_FOLDER; C:\wamp64\www\project
echo INCLUDES; C:\wamp64\www\project/includes
echo TEMPLATES; C:\wamp64\www\project/templates
echo WWW_ROOT; C:\wamp64\www\project/public
Can you please tell me what I'm doing wrong and how to correct it?
If your server setup is correct, no PHP file will get downlaoded, only executed.
Basically, you have PHP extension installed nad if the file starts with <?php then it will be executable.
As others have said, all content between <?php ?> tags will be removed from the page before it's served by your server, so long as your file ends in .php.
If you are trying to keep a non-php file from being served, your best bet is to put your includes folder where it is not publicly available.
Generally, when you FTP into your server, the layout is something like this:
www/
public_html/
... etc, other folders
The files you want to make publicly available should go inside of the public_html/www folder (www is usually just a shortcut/symlink for public_html).
You includes directory should go next to the public_html folder, rather than within it.
www/
public_html/
includes/
... etc, other folders
Then, in the files where you were including those files, include them from the new location.
<?php
require_once "includes/databaseSettings.php";
becomes
<?php
require_once "../includes/databaseSettings.php";
Now your files are outside of the directory being served by your HTTP server, but still available to be included in the rest of your code.
This has usually been my experience, but can vary from vendor to vendor. If, when you FTP into your server, you don't see a www or public_html folder, try navigating up one directory.

Getting the absolute pathname in php

Consider the following scenario: I have a vhost defined to some paths on my home folder.
say ~/web/project-name/ is my root. such that when i point to http://some-name/ it points to the index.php inside ~/web/project-name.
I've a Model-View-Controller framework (self-made/minimal) and my views contains different client side links (js, or css, or a href) Since I made my working folder root, i used absoulte path names (for instance /client/css/my.css ).
Now a friends comes in takes my projects. Copies it to /var/www/ So, now the contents of my website is not root, so my links in the views does not work?
What is the best way to mitigate the above problem?
I tried defining a constant ROOT as define('ROOT', dirname(__FILE__)) in my index.php, but it returns the absolute path like /home/cipher/...
I want to make a function such that it returns the path of my index.php relative to the web root!
Thanks in advance!
You might want to try a $_SERVER['DOCUMENT_ROOT'].

Accessing PHP script files outside site directory using path relative to root

I'm using apahce server and I have files that I want to keep private. I've read that they should be put in a directory outside of the document root.
I could access them from the root directory using:
<?php include('../includes/somefile.php');?>
To simplify navigation I want to use paths relative to the root. This works fine for directories within the site such as:
define('ROOT_PATH', $_SERVER['DOCUMENT_ROOT']);
include(ROOT_PATH.'/path/file.php');
but I get errors when I try going up the directory tree like this:
include(ROOT_PATH.'../includes/somefile.php');
Am I doing something wrong here?
This is because .. is taking to the previous directory of the DOCUMENT_ROOT which you do not have permission to access.

php declaring application root

I have a little problem: I began a project as a subdirectory in a larger web project. Thus the web file path is something like /../myProject. But things have progressed and I've realized that this should be its own project. However, I'd like to be able to keep it where it (as a sub-directory) also make it a sub-domain wherein myProject becomes the root. (There is also the possibility that my project will be mirrored at a library site, where it will once be in a sub-directory).
The problem I having with all this is that in some cases I have html_partial files, (for instance for the header or footer). But the relative path of these partials differs depending on where you are in the file tree. I originally solved this by always going back to the root.
But now, you see, depending on where my project lives, the root will be different. What I'd like to do is declare myProject as the "application root" and then be able to use relative paths based on this application root rather the than the web root'. This way, all of the relative paths within 'myProject' will work no matter wheremyProject` lives in the web path.
Does PHP have a way to declare something like an Application Root if so, can you explain it me or direct me to its documentation. Thanks!
You could simply have a PHP file in your application root directory which would define the directory it is in as the application root. The file could be as simple as this:
<?php
define('APPLICATION_ROOT', __DIR__);
?>
You could then include this file as needed and base all of your file paths off of APPLICATION_ROOT. Note that APPLICATION_ROOT would not have a trailing slash as defined here (unless your file happened to be on in the machines root directory, which is unlikely).
I usually do something lile this in the front controller:
define('APPLICATION_PATH', realpath(__DIR__));
Then you can do things like:
set_include_path(APPLICATION_PATH . '/include');
Or:
$fp = fopen(APPLICATION_PATH . '/path/to/some/file', 'r');
If your app doesn't make use of a front controller, you could define an environment variable in your vhost config or .htaccess:
SetEnv APPLICATION_PATH /full/path/to/my/app
And then use:
getenv('APPLICATION_PATH')

Why are CodeIgniter application files in the public_html folder?

Isn't having all of the files in public view a bad thing?
Surely things such as /system/application/config/database.php should not be publicly visible!
The developers of CodeIgniter, EllisLabs, have set up the framework in this way for ease of use. It means that people wishing to try out the framework don't have to fiddle with any permissions settings on their server.
Of course on a production server, you are absolutely right, putting your PHP files in the public HTML folder is not a good idea.
A better way to organise your folders would be:
root
code_igniter
application_folder
config
controllers
models
...
system_folder
public_html
css
js
images
index.php
.htaccess
The only other change to be made here would be to change line 26 of index.php to read:
$system_folder = "../../code_igniter/system-folder";
You can add the following rule to your .htaccess file to further protect the system and application directories from being viewed (sends a 403 Forbidden error):
# Protect application and system files from being viewed
RewriteRule ^(application|system) - [F,L]
With this structure:
/application
/system
/public
index.php
You can change in public/index.php these two settings and you are done
$application_folder = '../application';
$system_path = '../system';
Jon Winstanley's answer is perfect,
also don't forget to secure file uploads folder, if you have one. I did that by also moving it outside public root, and get the images using below code:
<?php
// $details = getimagesize($_GET["path"] . '/' . $_GET["image"]);
$details = getimagesize($_GET["path"] . strip_tags($_GET["image"]));
header ('Content-Type: ' . $details['mime']);
readfile($_GET["path"] . strip_tags($_GET["image"]));
exit;
?>
Accessing the files within /system/ from a browser will not reveal any sensitive information, because the PHP will be parsed and nothing is output from those files (CI system files may even check to see if a variable has been defined that indicates the file wasn't accessed directly).
That being said, however, you should probably install your entire system folder above web root anyway.
You can always place the system directory outside the public directory. Don't forget to update paths inside the the front controller (index.php).

Categories