I have a php file which I will be using as exclusively as an include. Therefore I would like to throw an error instead of executing it when it\'s accessed directly by typing
If more precisely, you should use this condition:
if (array_search(__FILE__, get_included_files()) === 0) {
echo 'direct access';
}
else {
echo 'included';
}
get_included_files() returns indexed array containing names of all included files (if file is beign executed then it was included and its name is in the array). So, when the file is directly accessed, its name is the first in the array, all other files in the array were included.
i suggest that don't use of $_SERVER
for security reasons .
You can use a variable like $root=true;
in first file that included another one.
and use isset($root)
in begin of second file that be included.
Earlier mentioned solution with PHP version check added:
$max_includes = version_compare(PHP_VERSION, '5', '<') ? 0 : 1;
if (count(get_included_files()) <= $max_includes)
{
exit('Direct access is not allowed.');
}
The easiest way is to store your includes outside of the web directory. That way the server has access to them but no outside machine. The only down side is you need to be able to access this part of your server. The upside is it requires no set up, configuration, or additional code/server stress.
My answer is somewhat different in approach but includes many of the answers provided here. I would recommend a multipronged approach:
defined('_SOMECONSTANT') or die('Hackers! Be gone!');
HOWEVER the defined or die
approach has a number of failings. Firstly, it is a real pain in the assumptions to test and debug with. Secondly, it involves horrifyingly, mind-numbingly boring refactoring if you change your mind. "Find and replace!" you say. Yes, but how sure are you that it is written exactly the same everywhere, hmmm? Now multiply that with thousands of files... o.O
And then there's .htaccess. What happens if your code is distributed onto sites where the administrator is not so scrupulous? If you rely only on .htaccess to secure your files you're also going to need a) a backup, b) a box of tissues to dry your tears, c) a fire extinguisher to put out the flames in all the hatemail from people using your code.
So I know the question asks for the "easiest", but I think what this calls for is more "defensive coding".
What I suggest is:
require('ifyoulieyougonnadie.php');
(not include()
and as a replacement for defined or die
)In ifyoulieyougonnadie.php
, do some logic stuff - check for different constants, calling script, localhost testing and such - and then implement your die(), throw new Exception, 403
, etc.
I am creating my own framework with two possible entry points - the main index.php (Joomla framework) and ajaxrouter.php (my framework) - so depending on the point of entry, I check for different things. If the request to ifyoulieyougonnadie.php
doesn't come from one of those two files, I know shenanigans are being undertaken!
But what if I add a new entry point? No worries. I just change ifyoulieyougonnadie.php
and I'm sorted, plus no 'find and replace'. Hooray!
What if I decided to move some of my scripts to do a different framework that doesn't have the same constants defined()
? ... Hooray! ^_^
I found this strategy makes development a lot more fun and a lot less:
/**
* Hmmm... why is my netbeans debugger only showing a blank white page
* for this script (that is being tested outside the framework)?
* Later... I just don't understand why my code is not working...
* Much later... There are no error messages or anything!
* Why is it not working!?!
* I HATE PHP!!!
*
* Scroll back to the top of my 100s of lines of code...
* U_U
*
* Sorry PHP. I didn't mean what I said. I was just upset.
*/
// defined('_JEXEC') or die();
class perfectlyWorkingCode {}
perfectlyWorkingCode::nowDoingStuffBecauseIRememberedToCommentOutTheDie();
The following code is used in the Flatnux CMS (http://flatnux.altervista.org):
if ( strpos(strtolower($_SERVER['SCRIPT_NAME']),strtolower(basename(__FILE__))) )
{
header("Location: ../../index.php");
die("...");
}