Run PHP Script Only When Called From Certain Page [duplicate] - php

This question already has answers here:
PHP: Check if a file is loaded directly instead of including?
(15 answers)
Closed 4 years ago.
I have a script in PHP that's included on pageX.php through include_once. Let's call it script A.php.
One could call this script by navigating directly to it from the browser: www.whatever.com/scripts/A.php.
What I want however is for script A.php to only be accessible through inclusion (on pageX.php) as it contains info that I want displayed on pageX.php only.
Besides using $_SESSION, are there different approaches?

You can define a constant within your index.php, that would not exist had the included script been called directly. In your included script you check if this constant is set and stop execution if it isn't.
Your original script (index.php):
define('PROPERLY_STARTED', true);
include_once 'a.php';
Your a.php:
if (!defined('PROPERLY_STARTED')) return;
Because my comment was deleted for some reason: While this works, it's error prone as you need to add that code to every single file. The established way of dealing with this issue is to only expose the index.php in your web root and have the files that should remain inaccessible in a directory outside of your web root so they aren't even reachable via HTTP (see e.g. the accepted answer on the question this is marked as duplicate of)

Simply don't let A.php output anything and use a
function/method based approach
a PHP script won't do anything if you have just functions defined in it.
Limit the access to your pageX.php only (via chmod / htaccess)

Related

Why does 'include' not include a defined constant in a separate file?

i have a problem with included file in php.
I have 2 file "settings.php" and "test.php" (hosted in localhost with all xampp's default settings and "allow_url_include=1").
Now. This is the content of file "settings.php":
<?
define("TEST_INFO","Lorem ipsum");
?>
And this is the file that include "setting.php":
"test.php":
<?
include("http://127.0.0.1/projectFolder/settings.php");
echo(TEST_INFO);
?>
The result of "test.php" is:
Notice: Use of undefined constant TEST_INFO - assumed 'TEST_INFO' in
C:\xampp\htdocs\projectFolder\test.php on line 4 TEST_INFO
The "include" function not make any error or warning as if it were performed correctly, but the constant (or any variable) defined in the included file not work.
If i try to include file "setting.php" without all url, it work correctly. include("settings.php");
But i need that it work so as: include("http://127.0.0.1/projectFolder/settings.php");
Thanks.
You are including a resource from a URL.
The PHP in the first script makes an HTTP request to the URL
The PHP that runs the define (in the second script) is executed on the server
The output is sent over HTTP to the include()
The output is included in the first page
The define statement is executed in a completely different script (possibly on a different server!).
If you want to execute PHP in the context of the current script, then you must include a local file and not an HTTP URL.

Prevent direct access using the define and defined function in PHP

I'm trying to use the define function and the defined function in order to avoid hotlinking / direct accessing a PHP script but for some reason it will not work.
The issue I'm having is that it simply will not work and i recieve the "Hotlinking is not allowed" message even if i visit index.php first and follow the link and / or the post form.
Here is an example of what i'm trying to do:
index.php
<?php
define("ACCEPT",TRUE);
?>
<html>
...
core.php
<?php
if (defined('ACCEPT'))
{
// ACCEPT is defined which means the user came here via index.php
}
else
{
// The user is most likely direct accessing core.php, abort.
echo "Hotlinking is not allowed";
exit;
}
Please note that the post "Preventing Direct Access, is it possible to spoof a php define?" does not answer my question nor does the post "define and defined for disallow direct access".
This is what a fair amount of programs do. Just create a header that checks for the definition and redirect/exit if it isn't defined. There is nothing wrong with doing it this way, but it just adds to the amount of lines/code each page will need. This can be confusing because the DEFINE needs to be in one place, then the page requested has to either be included, or needs to include the page that has the define. It is all about structure.
Here is something you can do:
.htaccess - redirects every request to index.php
index.php - Defines a variable, acts as a router that fetches/includes the page to be shown based on request data.
childpage.php - checks if variable exists (meaning it was included) and then does whatever needs to be done.
The other option is to place the sensitive code in am htaccess protected directory.
You can use a framework as well that does a lot of this.
Or, if your host allows you to edit your vhost config, which they probably won't if you only have access to a public directory, you can change the document root to a higher directory.

If an include() is conditional, will PHP include the file even if the condition is not met?

This has been on my mind for quite some time and I figured I should seek an answer from experts.
I want to know if it is a poor programming technique to funnel all PHP requests through a single file. I have been working on a website and not sure if it will scale with growth because I am not 100% certain of how PHP handles the include() function.
To better explain how I have build my quasi framework here is a snippet of my root .htaccess file:
# > Standard Settings
RewriteEngine On
# Ignore all media requests
RewriteRule ^media/ - [L]
# Funnel all requests into model
RewriteRule ^(.*)$ _model.php [QSA]
So everything except content within the media directory is passed into this single script.
Inside _model.php I have all my input sanitisation, user authentication, session data gets pulled from the database, any global variables (commonly used variables like $longTime, $longIP etc...) are set. Requests are routed via interpreting the $_SERVER["REQUEST_URI"] variable.
Essentially I have a switch() statement which chooses which module to include(). What I don't understand is: when PHP executes, will it execute every single include() regardless of whether or not the case directive is true?
I am concerned that after time I will have a lot of these modules - and if PHP does at runtime include all the modules it will end up occupying too much processing power and RAM...
--
Edit:
I am really just asking if PHP will 'read' all those files that it potentially might have to include. I know that it shouldn't actually execute the code.
If one of my include() is a 2GB file which takes a long time to process, will PHP always read over that file before executing?
--
Edit:
I have found another similar question (I did search a lot before posting this one)
PHP behavior of include/require inside conditional
I think I can close this off.
No, PHP will execute include in the moment the code fragment is reached.
This is quite important, because you can have php include file with code directly. E.g.
File1:
<?php echo "Foo"; ?>
File2:
<?php
echo "Before";
include("File1");
echo "After";
?>
Sometimes your PHP processor won't even know at compiletime which file to include. Imagine something like include("File".mt_rand(1,10));. PHP won't know the filename to include up to the very moment it reaches the include statement.
will PHP include the file even if the condition is not met?
No, include and require statements are interpreted and evaluated in the same way as other PHP statements. PHP does not scan the script for includes prior to executing.
This can be verified with a simple test:
if(false)
{
include('does_not_exist.php');
}
The above produces no error or warnings. If the include was read before execution, you would see a warning like:
Warning: include(does_not_exist.php): failed to open stream: No such file or directory ...
Warning: include(): Failed opening 'does_not_exist.php' for inclusion ...

$GLOBALS being cleared in URL included page

When I include a page using it's full URL (like include 'http://mysite.tld/mypage.php'), I can't use the $GLOBALS in mypage.php, it returns Undefined index error.
But when I include it using it's relative path (like include 'mypage.php'), then it's OK.
The reason why am I using URL instead of relative path is that I want to include $_GET parameters to mypage.php
Is there any logical explanation of this strange behaviour?
Note that both files are on the same server, in the same directory.
Including files with a URL means the code is run as a separate process, which means it runs under a different variable scope. This is as opposed to if you include the file via a relative path, in which case it is pretty much equivalent to cut and pasting the code into the script.
Essentially this means that the only variables available from your starting script are those that you explicitly pass (as you are in this case using the $_GET variables). This includes the $_SESSION variables, since the caller is your own server rather than the client.
This behaviour is noted in the PHP manual's include page:
If the target server interprets the target file as PHP code, variables
may be passed to the included file using a URL request string as used
with HTTP GET. This is not strictly speaking the same thing as
including the file and having it inherit the parent file's variable
scope; the script is actually being run on the remote server and the
result is then being included into the local script.

PHP add constant on load before scripts

I was wondering if it possible to add constants to php before any scripts are ran, thus on startup. If this is possible, could it be done with classes etc aswell?
I was thinking in the direction of creating a plugin for php but maybe there is a way simpler way.
I don't mean including a file in every script.
thanks in advance
Not constants as far as I'm aware, but this is ok:
.htaccess
SetEnv MYVAR "hello"
somefile.php
echo $_SERVER['MYVAR'];
See the Apache docs on SetEnv for more.
To directly answer the question, there are two approaches:
Use auto_prepend_file to auto include a PHP file that has define calls.
Configure your web server to set server variables.
I think the second is a better approach. However, I don't see how either of them are very useful in the context of a plugin. Usually a class autoloader of some sort is the way to go there, or to require a single include file.
If I understand your question correctly, what I do is to include a file before all else on my index.php. That same file contains tons of constants, control verifications, initialization for the DB object, etc...
e.g.,
INSIDE index.php
<?php
$moduleRoot = dirname(__FILE__);
require_once($moduleRoot."/components/inc/inc.php");
// continue to render the web page and perform as usual
?>
INSIDE THE inc.php
// When in development, all errors should be presented
// Comment this two lines when in production
error_reporting(E_ALL);
ini_set('display_errors', '1');
// Website id for this project
// the website must be present in the table site in order to get
// the configurations and records that belong to this website
define("CONF_SITE_ID",1);
// Domain path where the project is located
// Should be like the access used on the browser
$serverDomain = $_SERVER["HTTP_HOST"];
$serverAccess = (!empty($_SERVER['HTTPS'])) ? ('https://') : ('http://');
$serverRoot = dirname(__FILE__);
define("CONF_DOMAIN", $serverAccess.$serverDomain);
// etc ...
EDITED
Since you have multiple "startup" files and you need all of them to call inc.php, the best choise seems to be .user.ini as of PHP 5.3.0, you can read about it here!.
And an article on the subject.

Categories