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).
Related
Most of my website is in my root directory. And In that directory there is "css", "functions", "images" folder. Everything works fine when I include php files within index.php or any other root file. It includes it fine and executes it fine.
But problem occurres when I made folder "blog". So this is totally new and separate root folder with CMS and its own "root" files. And I try to include css from main root directory or some php files from "functions" folder in main root directory, Everything breaks down. I know I have to include it as ../functions/myfile.com. But this files includes some other files so it just wont work properly and won't be able to include other files properly.
Is there any idea how to fix this problem?
You can get to the root from within each site using $_SERVER['DOCUMENT_ROOT']. For testing ONLY you can echo out the path to make sure it's working, if you do it the right way. You NEVER want to show the local server paths for things like includes and requires.
Site 1
echo $_SERVER['DOCUMENT_ROOT']; //should be '/main_web_folder/';
Includes under site one would be at:
echo $_SERVER['DOCUMENT_ROOT'].'/includes/'; // should be '/main_web_folder/includes/';
Site 2
echo $_SERVER['DOCUMENT_ROOT']; //should be '/main_web_folder/blog/';
The actual code to access includes from site1 inside of site2 you would say:
include($_SERVER['DOCUMENT_ROOT'].'/../includes/file_from_site_1.php');
It will only use the relative path of the file executing the query if you try to access it by excluding the document root and the root slash:
//(not as fool-proof or non-platform specific)
include('../includes/file_from_site_1.php');
Included paths have no place in code on the front end (live) of the site anywhere, and should be secured and used in production environments only.
Additionally for URLs on the site itself you can make them relative to the domain. Browsers will automatically fill in the rest because they know which page they are looking at. So instead of:
<a href='http://www.__domain__name__here__.com/contact/'>Contact</a>
You should use:
<a href='/contact/'>Contact</a>
For good SEO you'll want to make sure that the URLs for the blog do not exist in the other domain, otherwise it may be marked as a duplicate site. With that being said you might also want to add a line to your robots.txt file for ONLY site1:
User-agent: *
Disallow: /blog/
Other possibilities:
Look up your IP address and include this snippet of code:
function is_dev(){
//use the external IP from Google.
//If you're hosting locally it's 127.0.01 unless you've changed it.
$ip_address='xxx.xxx.xxx.xxx';
if ($_SERVER['REMOTE_ADDR']==$ip_address){
return true;
} else {
return false;
}
}
if(is_dev()){
echo $_SERVER['DOCUMENT_ROOT'];
}
Remember if your ISP changes your IP, as in you have a DCHP Dynamic IP, you'll need to change the IP in that file to see the results. I would put that file in an include, then require it on pages for debugging.
If you're okay with modern methods like using the browser console log you could do this instead and view it in the browser's debugging interface:
if(is_dev()){
echo "<script>".PHP_EOL;
echo "console.log('".$_SERVER['DOCUMENT_ROOT']."');".PHP_EOL;
echo "</script>".PHP_EOL;
}
If I understand you correctly, You have two folders, one houses your php script that you want to include into a file that is in another folder?
If this is the case, you just have to follow the trail the right way.
Let's assume your folders are set up like this:
root
includes
php_scripts
script.php
blog
content
index.php
If this is the proposed folder structure, and you are trying to include the "Script.php" file into your "index.php" folder, you need to include it this way:
include("../../../includes/php_scripts/script.php");
The way I do it is visual. I put my mouse pointer on the index.php (looking at the file structure), then every time I go UP a folder, I type another "../" Then you have to make sure you go UP the folder structure ABOVE the folders that you want to start going DOWN into. After that, it's just normal folder hierarchy.
i had the same issue and found a code on https://css-tricks.com/php-include-from-root/ that fixed it
<?php
$path = $_SERVER['DOCUMENT_ROOT'];
$path .= "/common/header.php";
include_once($path);
?>
None of the above answers fixed this issue for me.
I did it as following (Laravel with Ubuntu server):
<?php
$footerFile = '/var/www/website/main/resources/views/emails/elements/emailfooter.blade.php';
include($footerFile);
?>
Try to never use relative paths. Use a generic include where you assign the DocumentRoot server variable to a global variable, and construct absolute paths from there. Alternatively, for larger projects, consider implementing a PSR-0 SPL autoloader.
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';
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')
I have a php applicaiton and i'm planning to keep critical settings in a .ini file. However, i think that file can be accessed from over the web, so where is a "standard place" for it to be placed?
You can store it above the document/web root or specifically block access to it. For example, a common structure for PHP applications is:
application/
public/
Where public is the web root - so I usually store application configuration in application/config where I know it can't be accessed.
An alternative would be to block it using Apache:
<!-- Block access to all .ini files -->
<Files ~ "\.ini">
Order deny,allow
Deny from all
</Files>
The "standard place" is anywhere not affected by the directory root of the apache. For example you can place it under /home/someuser/, or somewhere else.
Place the .ini file outside the web root or protect it with .htaccess if you really want to keep it under the web root.
It can be accessed if you place your INI file in your webroot/docroot.
Making sure the file is not accessible via the docroot is the first step.
I would use a database to be honest.
However, if you really want to use a flat file (e.g. .ini), you can place it in a directory, and use .htaccess to stop people from accessing it via their browser. That way, you can still access the file via php file functions.
To do this, make a file called .htaccess in the folder you want to protect (e.g. ini/)
Then, in this file put:
deny from all
The folder is now not accessible by going to the url in the browser.
Place the configuration in a directory that isn't readable by the webserver, yet is readable for the application. Generally, you have a specific directory that's readable by the webserver, such as "web", "www", "public" or "public_html". Make sure you put it in the directory below that one.
That way, your application can read the file:
$cfg = parse_ini_file(
realpath( dirname( __FILE__ ) . '/../' ) . '/config.php'
);
Your webserver doesn't know how to reach it though, so it's secure.
a good example is Zend FW or any other php frameworks. directory structue is:
application/config/config.ini
library/Zend/
public/index.php
where public is accesible from web
I'm just starting with CodeIgniter, and I am not sure where things such as css, js, and images should go. Outside the whole system folder seems ok, but that means everything is seperate. Inside means the filepaths are longer, and I'm worried that it might mess things up. What's the best practice on this issue?
I usually put separate folders at the root level, so I end up with a directory structure like this:
/system
/css
/js
/img
Seems to work for me - when you use site_url(url), the URL it generates is from the root, so you can use site_url('css/file.css') to generate URLs to your stylesheets etc.
Personally, I rip the application directory out of the system directory and make it a sibling to system. I then create a project directory in public_html (www) where I move index.php and store my public assets.
Let's assume the project you're working on is called projekt. In the parent directory to public_html (www) create a directory called CISYSTEM, and inside that directory create a directory from the version you're using, 202, 210 etc.
/CISYSTEM
/202
/210
/another_CI_version
/projekt_application
/models
/views
/controllers
/private_assets
/public_html
/projekt
index.php
.htaccess
css
img
js
lib
The beauty of this directory structure is it adds another layer of security and makes it dead-easy to upgrade/swap out your CI core. Plus, you're not supposed to make changes to the core - having a single directory where your core is stored and having all projects reference it keeps things DRY.
All this directory shuffling requires you to reroute a few things though. Luckily, CodeIgniter makes it easy -- all changes can be made in the index.php file.
Open index.php and reroute a couple things:
Change: $system_path = 'system';
To: $system_path = '../../CISYSTEM/210';
Change: $application_folder = 'application';
To: $application_folder = '../../projekt_application';
Also, I see a lot of people talking about using site_url() in the other answers. I recommend a less verbose way of using site_url()... you don't have to call it every time if you make use of HTML's <base> element:
<base href="<?= site_url();?>">
Just include that in your application's <head> and you can call your controllers directly... as in:
<a href='controllername/functionname'>Some Action</a>
Cheers
I hate having so many directories at the root level, so I use /public and use htaccess to rewrite /scripts to /public/scripts and so on.
I find it best to keep the assets on the root level. You can use <?=base_url()?> to echo the full root of the site. In the config file, you set up the root of the website. This statement just echoes that out.
Because of this, you can use includes like this:
<link href="<?=base_url()?>/css/style.css" rel="stylesheet" type="text/css" />
anywhere in your code, and it will still get http://example.com/css/style.css.
base_url()/css/name.css
In order to use the site_url(url) helper in this way you MUST first configure Apache mod_rewrite (or equivalent) to remove the index.php segment from the URI.
Otherwise the site_url method adds index.php to the URL which will likely screw up the paths to your assets if you've got them in the base directory like above.
Here's the CodeIgniter documentation on removing index.php from the URI:
http://codeigniter.com/wiki/mod_rewrite/