Header Location after file_put_contents - php

I try to read a constant from a file and be able to change this constant on demand.
So when this constant need to be written (for this example through a GET), right after I would like to reload the page to have the correct value.
But after the reload, even if my file contains the new value, it seems that the constant is still defined to the old one.
If I put a sleep before the header(Location) everything works fine. Is there a solution without the sleep, and why?
Here is the example file:
<?php
include_once 'toto.php';
if (isset($_GET['test'])) {
$file = "<?php const TOTO = '$_GET[test]'; ?>";
file_put_contents('toto.php', $file);
// sleep(3);
header('Location: index.php');
exit;
}
echo TOTO;
?>
I tried to replace the file_put_contents by fopen+fwrite+fflush+fclose without more success.

The above code working fine for me.
What your index.php contains?

Concept breaking
The concept of a constant is that throughout the application it doesn't change its value. You're breaking the principle of a constant.
Insecure
Also, since the constant is defined with user input, and written to a file, we can very easily hijack your server with any malicious code we want. Ie:
http://localhost/index.php?test=42%27;eval($_GET[%27hack%27]);%3F>
Then we can append to the query string anything we want executing.
http://localhost/index.php?hack=echo%20shell_exec(%27cat%20%2Fetc%2Fpasswd%27)
And viola, we have your /etc/passwd file. From there, we could get your /etc/shadow file and hijack your entire server. We could create more backdoors to your server - pretty much do anything to your server by passing our commands to the hack query string parameter.
The fix
To modify your script so that it doesn't break this concept, or you have no race condition on writing the new value to the file and reading, consider using a cookie or a session (both are unique to the client; cookies are editable by the client, sessions generally aren't (the session ID is, but the value bound to that session ID isn't)).
<?php
session_start();
include_once 'toto.php'; //or put session_start(); at the top of this file
if (isset($_GET['test'])) {
$_SESSION['TOTO'] = $_GET['test']; //Do some sanitation here since it's user input.
header('Location: index.php');
exit;
}
Now to read this, simply use $_SESSION['TOTO'];.
Though, since you've mentioned this should be a global configuration (ie: throughout the entire application and for all users), then use an ini file or database.

You can try putting this code -
<?php
include_once 'toto.php';
if (isset($_GET['test'])) {
$file = "<?php const TOTO = '$_GET[test]'; ?>";
if (file_put_contents('toto.php', $file)) {
// sleep(3);
header('Location: index.php');
exit;
}
}
echo TOTO;
?>
With this code the header function will be called only if the constant is written to your file properly.
Also your issue may be occurring because the page is redirected before the write to toto.php is in progress.

Related

How should I make variable global for all the pages in PHP

Question
I want to make $associate_name and $app_key global variable so I can access them on any page I want. Below is the code from my header file and the get variables are coming to index page. It works fine on index page as the $_GET data is available but when a user moves onto next page but with the same header file included it throws an error saying Undefined index. Please let me know how can I make this variable available on all pages. Thanks!
Code
$associate_name = $_REQUEST['an'];
$app_key = $_REQUEST['key'];
define('associate_name',$associate_name);
define('app_key',$app_key);
//echo "Sorry but there seems to be a problem in your code. We can't find one of the following: App name or App key";
$select_associate = "SELECT * FROM associate_account WHERE associate_name='".associate_name."' and app_key='".app_key."'";
$assoc_result = mysql_query($select_associate) or die($select_associate.mysql_error());
if(mysql_num_rows($assoc_result)<=0){
echo "Oops there seems to be a problem in your iFrame code. Please login into your Associate panel and copy/paste the link again.";
}else{
$row_assoc = mysql_fetch_assoc($assoc_result);
$associate_name=ucwords($row_assoc['associate_name']);
$app_logo=$row_assoc['app_logo'];
$app_intro_content=$row_assoc['app_intro_content'];
$bg_color=$row_assoc['bg_color'];
}
Put those variables you want as session or cookie data. Otherwise, you would have to resort to the global keyword, which is a very bad way of doing things in modern PHP applications.
It would be like this (for session):
$_SESSION["myvar"] = <value>;
It's a bit more complicated with cookies, but this should get you going ;)
Have all your variables/constants in a separate file may be constants.php
Include that constants.php wherever you want to access that variable.
Use $_SESSION
Sessions are your choice in case the value is modified. Otherwise (the value is constant from your configuration and not from user's modification, go for Constants

How to disable direct entry to a html?

Say I have two html files called html1 and html2. html1 contains an embedded swf file.
Now what I want is that the user can not go to html2 directly via url. He has to click it through the link in the swf in html1. Is there a way to achieve this?
If not possible in html, is it possible with php?
Thanks
EDIT:
After answer from John, I went ahead and tried his advice, but I can never access the file2.php, even if I have been to file1.php before. It keeps redirecting me back to file1.php, even when it should not.
My code from file1.php
//file1.php
<?php
session_start();
$_SESSION['enableAccessTill']=strtotime("+5 minutes");
?>
Here is file2.php
//file2.php
<?php
session_start();
if(!isset($_SESSION['enableAccessTil'])||$_SESSION['enableAccessTil']<time())
{
header("Location: indexFLA.php");
exit;
}
?>
what am I possibly doing wrong?
found it, it was due to a misspelling - "enableAccessTil" and "enableAccessTill"
professional solution:
create protected directory and make .htaccess file in directory and copy all embedded and partial files into directory.
this directory not accessible whit get url.
but you can include file whit php include and require method.
.htaccess content:
deny from all
This wont be possible in just plain html.
An easy way to do this is php is by setting a session variable in file 1, and test in file 2 it the users has been to file 1.
file1:
<?php
session_start();
$_SESSION['enableAccessTill'] = strtotime("+5 minutes"); //set the time here till when the user has access
[...]
file2
<?php
session_start();
if(!isset( $_SESSION['enableAccessTill'] ) || $_SESSION['enableAccessTill'] < time() ){ //If time is expired
header("Location: file1.php"); //redirect user to the first file
exit;
}
[...] //continue your script here.
Things with referrer check do usually fail (some browsers/firewalls blocking that variable).
Based on the options you described, it would sound most reasonable to make the html2 a php script and check that the referrer is the html1 file. The script should display the normal html1 content if that is the case, or an error message otherwise.
A sneaky user could still get around this if they knew what was going on, but it should be fine for the majority of your audience.
Possible with php.
At index.php you must write
<?php
define('START', true);
include 'file.php';
At file.php need write
<?php defined('START) or die('Direct access!!'); ?>
<embed> your swf file embed
This way you will prevent direct access
You could do it with PHP by using session variables. Start the session in html1. Check for the session in html2. If it exists, display html2. If it does not, don't display html2. In either case, destroy the session in html2.
well is posible with html you has two options one is cookies and the other is local storage in html5
localStorage.hasClick = true;
alert(localStorage.hasClick);
http://www.html5rocks.com/en/features/storage
but obviously the straightforward solution is php / c# / ruby / etc...
//when I said html i refer to use only client side html/javascript

Displaying a div if a PHP if statement is true

I have the following PHP script within a file named login.php
<?php
$ref = $_SERVER['HTTP_REFERER'];
if ($ref == 'http://example.com/dir/invalid.php' || $ref == 'http://www.example.com /dir/invalid.php') {
echo '
<div id="invalid">
TESTTESTTESTTESTTESTTESTTESTTEST
</div>
';
}
?>
I have deliberately went to the invalid.php page (which redirects using header() to login.php) and this div does not show up. Does it have something to do with the referrer not really being invalid.php or is there an issue with the script?
Thanks
I don't think the HTTP_REFERER is what you think it is. Namely, it is the page from which the user followed a link to the current page. However, it's very unreliable as we rely on the browser of the user to correctly report this value.
I would suggest the option I thought you needed, except that the only one I can think of you might doesn't really makes sense... (checking if the url matches a url that's not the current script)... so I do not see what you are trying to do.
As promised several ways to do what you want to achieve:
First off, I don't like this solution at all and really consider it ugly, but it's the one closest to what you where trying to do.
invalid.php
require 'login.php'; // we include the file instead of referring to it
login.php
if ($_SERVER['SCRIPT_NAME'] == 'invalid.php')
{
// do whatever
}
The main difference between what you did and what I did for the user will be that here the url bar will show that you're at invalid.php and not somewhere else. This also means that refreshing doesn't make the message go away.
A better solution in my opinion is the following:
In your script that logs a user in (checks the database and everything):
if (!valid_login()) // pseudo-code, obviously
{
$_SESSION['invalid_login'] = true;
header('Location: login.php');
// previously, we had something like this instead of the two lines above:
// header('Location: invalid.php');
}
in login.php
if (isset($_SESSION['invalid_login']) && $_SESSION['invalid_login'])
{
$_SESSION['invalid_login'] = false;
// do whatever
}
Of course, this should be done with proper session facilities like starting up the session in both those files. Instead of using session variables, you could include the file and use normal variables or send GET variables through the header request, but both those solutions share a problem: refreshing doesn't make the message disappear. However, if you were to move the code from the top file of the two above to login.php (if it's not already there, I don't know what file that actually is...) you could once again use normal variables instead of session variables and have a solution in which refreshing does make it go away. In this case, you might argue that you are cluttering your files with bussiness logic and presentation, but there are solutions to that (like keeping it in a separate file, and including it into login.php, moving the html to another file and including that one into login.php or both.

Setting PHP variables from AJAX/Json

At the moment I have this code:
index.php
var refreshId = setInterval(function() {
$.ajax({
url: ("http://www.example.co.uk/erc/user_data.php?imei="+inCallingNum),
dataType: "json", //the return type data is jsonn
success: function(data){ // <--- (data) is in json format
$('#right-side').html(data.rightside);
$('#caller').html(data.caller);
$('.location').html(data.location);
$('.battery-level').html(data.battery);
//parse the json data
}
});
});
user_data.php
$profile = array();
$profile['rightside'] = $rightside;
$profile['caller'] = $caller;
$profile['nextofkin'] = $nextofkin;
$profile['location'] = $location;
$profile['battery'] = $battery;
echo json_encode($profile);
This works fine to add the information into the div tags, but what I need to do now is take a PHP variable from the user_data.php file and use it in the index.php file. Is it possible to send/capture PHP variables in that way?
E.g. in user_data.php I have a variable $test and I want to use this $test variable in index.php
Thanks for any help
There are many ways you can do this, and the easiest (and most transparent way of doing so) is by setting a session cookie. This is a small file that sits on the client's computer, and is readable by all sites on your sub-domain (x.mydomain.com.), basically all files in that same folder as the file that set it. You can do this easily in PHP by doing the following things:
On EVERY page you want to set, get, or otherwise check for the variables... use this code
session_start(); // Put this at the TOP of your page, below <? or just before you check the variables.
On the page you want to SET the variables... use this code
$_SESSION['variable'] = "data";
session_write_close(); // Use this after you are done setting the session data, to save it before the page execution is finished. This is a good habit to get in to, it's kind of like when you fclose a file instead of waiting for the script to do it.
On the page you want to GET the variables.. use this code
$test = $_SESSION['variable'];
You can basically use the $_SESSION array to store variables you want to be seen as "global" on your site. Forums use this to store the User ID and session hash, for later authentication on passwords. Other sites use session cookies to limit user activity within a given timeframe.
--
There is also another way you can do this, have a link from your page that generates the value of $test send a GET request to index.php (for example, if the user clicks a link format the link like:
index.php?test=value
Then on index.php simply do:
$test = $_GET{'test'];
This method is good for users who may not have cookie support, or may have cookies disabled; but is very obvious, and users can easily change the value of the cookie (which can have unseen results.)
What you are asking for cannot really be done since index.php is executed before user_data.php. However, since you are sending the result from user_data.php to index.php maybe you can look at consuming the variable with JavaScript. Why not tell us more about what you would like to accomplish so we can suggest how it can be done.
two ways:
either set $test into $_SESSION['test'] and get it on index.php
alternative:
did u try with json_decode()
You have the answer to your question in the question!
Even though you are creating and array to encode as JSON you are in fact just passing values from php to javascript.
You could equally do
$profile['test'] = $test;
and then in your javascript use
data.test
to get your value.
The question is when are you wanting to get the varaible value? Is it before the page is served or during your ajax call?
You should create your JavaScript code dynamically, with PHP:
alert("server name: <?php
echo $_SERVER['SERVER_NAME'];
?>");
Use it with caution, just in rare cases.

providing login check, page redirect in all pages in php

I am making a simple Dynamic Website using PHP, where i allow the user to login and then access specific pages. So here's what i have done so far.
The logged in values are taken though $_POST variables in a php script where it fetches values from database for registered users. If the user is found i do the following:
session_register('userid');
$_SESSION['userid'] = $username;//this is taken from $_POST
$_SESSION['accesslevel'] = $access;
at the beginning of the php script i have put session_start();
Now here comes my problem.
At every page now i have to check if the user is allowed to view that page or not, if he ain't then he must be redirected to login.php, if he is then the page load must continue.
Now so far what i have learnt is that only way to maintain values across php pages is to use $_SESSION variables, and which ever page i am using Session Variables i must write session_start() on each page as the first line, else i will be getting Headers Already Sent error..
Strangely i exactly have done that but still get erros with the "headers already sent".
SO i want to what is the best way to design a website, where i have to use Session variables across most of the pages, and keep these common checks at a common place..
Can i use include() feature some how?
Are sessions only way to communicate data across php pages.
What is a better way?
I have the following code :
<?php
session_start();
if(!isset($_SESSION['user']))
{
$_SESSION['loc'] = "adminhome.php";
header("location:ettschoollogin.php");
exit();
}
?>
Which resides on top of every page which wants to check if the user has logged in.
And this is teh script to check for login
<?php
session_start();
include("connection.php");
$userid =$_POST['userid'];
$userpwd =$_POST['userpwd'];
$query="Select UNAME,UPASSWORD,SCHOOL,uaccess from schooluser where uname = '$userid'";
$result=mysql_query($query) or die("couldn't execute the query");
$row=mysql_fetch_array($result);
$useraccess = $row["uaccess"];
$school =$row[2];
if(($row[0]==$userid)&&($row[1]==$userpwd))
{
session_register('userid');
$_SESSION['userid']=$userid;
$_SESSION['school']=$school;
if($useraccess =="admin")
{
header("Location:adminhome.php");
}
if($useraccess !="admin")
{
header("Location:school_main.php");
}
}
else
{
header("Location:ettschoollogin.php?err=1");
}
?>
i was aware of the common error of having extra spaces after "?>", BUT I STILL GET IT.
Thanks guys, i missed out and the "connection.php" file actually had extra spaces after "?>" i had removed it before, but some how the file got rewritten again.Thanks a lot.
Yes, you can use include. Put all your common functions in a separate php file and "include" it at the top of each file.
You can use cookies to store information (typically just an id that you use to look up additional information in the PHP page). Normally, PHP sessions are handled using cookies though. See setcookie in the docs.
You are probably getting the error messages due to stray characters outside of a <?php ?> block. A common error is to have an extra blank line at the end of an include file, after the ?>. That blank line will be output and your headers will have been sent. If that isn't the problem, you will just need to make sure you move the session related code above any code that might generate some output (eg by using print or echo).
•Can i use include() feature some how?
Yes. You can do whatever you want before your session_start() call, only, you must not have outputted anything, not even a single space or character. Probably you have already outputted something, maybe on an automatic inclusion or apache prepend.
•Are sessions only way to communicate data across php pages.
•What is a better way?
Other ways are cookies, post and get parameters. But sessions are the only way to securely pass data among pages without sending them to the client and back (which may pose security risks)
Write ob_start(); at the top of your code and then you dont get the error of "headers already send"

Categories