Session variable won't echo if cleared on same page? - php

I am having a strange issue of a session variable being empty when I clear it on the same page that I attempt to echo it. Here is a quick type-up of what I am trying to do.
Take this example;
Page A:
$_SESSION['referer'] = 'abc123';
header('Location: http://www.test.com/pageb.php');
exit();
Page B:
function get_referer() {
$referer = '';
if (isset($_SESSION['referer'])) {
$referer = $_SESSION['referer'];
$_SESSION['referer'] = null;
unset($_SESSION['referer']);
}
echo $referer;
}
Now when I do this on page B with the functions...
If I run it all by itself it works:
get_referer();
When I run the echo inside the value attribute of the input (making sure to only run the function once on the page due to it being erased after being called), it didn't echo anything when I view source the page.
<input type="hidden" name="referer" value="<?php get_referer(); ?>" />
However, funny enough, if I make the input type="text" it works fine.
<input type="text" name="referer" value="<?php get_referer(); ?>" />
The issue only occurs on the value attribute for input type="hidden"

You're outputting the content with
<input type="hidden" name="referer" value="<?php get_referer(); ?>" />
you're not viewing it on the same page as you would have if you were using type="text". When using type="hidden", you're most likely right-clicking the window and choosing View Source in your browser. The problem is that same browsers (like Chrome) refresh the page when you do so. This means, that once you load the page, the value attribute actually contains abc123, but when you attempt to see it, the page is refreshed, and therefore the session no longer exists, hence value is empty.

Maybe you are calling the get_referer() twice?
In the first it will echo the referer and unset. When you call in the input, the referer don't exists anymore in the session, so prints nothing.

Related

Redirect to current page value for input value in form

In my html I currently have:
<input type="hidden" name="redirect" value="example.com" />
Is it possible to change the value to redirect to the current page (basically refreshing the page) without having to manually put the url in for each page?
Yes, you could add this function to your code. I use it in some of my application
create a function like :
function getPageUrlNoQuery()
{
$pageUrl = ($_SERVER['PHP_SELF']);
return $pageUrl;
}
include the function file, and call.
<input type="hidden" name="redirect" value="<?php echo getPageUrlNoQuery() ?>" />
Have edited, and i think this should work in most architecture as long as
you can call the function, or class. whichever you use.
Well, in PHP you should know what page you are loading anyways and then put that value in. (I don't know your architecture, but either set a variable in your controller manually or if you don't use Controllers, then simply extract the URL from the get request.)
Alternatively you can use Javascript:
document.getElementById('YourLink').value = window.location.href;

PHP session data changes in Internet Explorer

I've defined a session to storing token using PHP like below:
$_SESSION['token'] = sha1(uniqid(mt_rand(), true));
when I want to read this session, I have not any problem in Chrome or Firefox. But in IE, it changes to something else before regenerating. For example if I store its value in a hidden field of form and submit it like this:
<input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>" />
I will get this result in IE in the next page:
echo $_SESSION['token']; // shows 1b05fab5ec11f1d50713aea6e74f84727d29b4a3
echo $_POST['token']; // shows e8fac6d55b04d1752f37ecde953f7f08b112ccca
Whereas if I print $_SESSION['token'] immediately after creation or even in end of its creation page, it shows the content exactly and with no problem.
What is this problem for ?
Edit:
This is my form :
<form action="process/login.php" method="post">
<input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>" />
<label>Email: </label><input type="text" name="email" />
<div class="space"></div>
<label>Password: </label><input type="password" name="password" />
<div class="space"></div>
<input type="submit" value="Login" class="button" />
</form>
Since PHP and session storage are server side and IE is obviously a client, the problem does not reside in your session code.
Sessions are usually kept track of by a cookie (session cookie) or though a POST/GET variable. By default in PHP this value is named PHPSESSID.
Probably, in your case either the session cookie or POST/GET variable that is linked to your server side session is not coming over okay in IE. In case of a cookie, it might have to do with cookie settings and whether or not cookies are allowed at all. In case of a POST/GET it could be that your HTML is malformed in a way that IE doesn't like, but other browser do understand.
Now once that value is lost in IE, PHP assigns that browser a new session on each request, and the session token is regenerated on each request. But your hidden field remembers the old token as well...
If you show us more code (you can edit your question), I can edit my answer to give you more details.
edit
You can start by showing us the relevant php.ini settings lines that concern sessions and session cookies. And by double checking your IE cookie settings. In specific I would like to know if you have set a cookie_path, making cookies only available in the same directory.
Maybe you even have an IE security setting or add-on installed preventing cookies. So try checking your IE settings and disable all add-ons and test it again.
Also check if the first page (that sets the session) and the second page (that reads the session) have EXACTLY the same domain name.
So for example www.yourdomain.com in the first page, should not be yourdomain.com on the second page (without the www) or www.yourdomain.com. (with an extra dot at the end).
I think after your form submits you might be creating another token value.
use
if(!isset($_POST['token'])){
$_SESSION['token'] = sha1(uniqid(mt_rand(), true));
}
I would try changing the name of the input to something else, maybe IE is doing some weird stuff with the token name. Searched the net, but nothing mentions this, but just to be on safe side, and remove this option I would do it.
<input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>" />
to:
<input type="hidden" name="my_session_token" value="<?php echo $_SESSION['token']; ?>" />
And try changing $_SESSION['token'] to $_SESSION['my_session_token'] as stated above in a comment
I'm almost certain that you are assigning the $_SESSION['token'] twice. It might be the same line of code being executed twice or you've assigned the variable somewhere else too. In order to find the problem you need to define a function as a wrapper for assigning the session entry. Then call the function instead of assigning the variable directly. Here's the sample code:
function assign_token()
{
$_SESSION['token'] = sha1(uniqid(mt_rand(), true));
}
But you need to make sure never assign the token directly anywhere within your code. And call this function instead. Once you've done this, if you have a debugger, all you need to do is to set a break point within this function and see how many times it is called and from where.
But in case you don't have a debugger installed, or even worse, in case the assignment happens not within a single request but in two, you need to modify your function like this:
function assign_token()
{
file_put_contents('/tmp/assign_token.txt', time() ."\n". print_r(debug_backtrace(), true), FILE_APPEND);
$_SESSION['token'] = sha1(uniqid(mt_rand(), true));
}
The line added will help you track each time the function is called. Even if it's called twice within two separate requests, you can identify them thanks to FILE_APPEND and time(). The first one appends to the file (obviously) so log entries won't overwrite each other and second one helps knowing if two entries of your log are made in the same request.
That's all I've got. At the end, you may want to style the log entries making them more readable.
I would do something more along the lines of this:
md5(uniqid($_SERVER['REMOTE_ADDR'], true))
Assuring that the token will always be unique.
Correct me if i'm wrong but i've tested already code below in Chrome FF and IE 7 and it doesn't seems that there is any issue with IE.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form method="POST" action="/">
<?php
session_start();
if(!$_SESSION['token']){
$_SESSION['token'] = sha1(uniqid(mt_rand(), true));
}
?>
<input type="hidden" value="<?php echo $_SESSION['token']; ?>" name="token"/>
<button type="submit" name="send">Send</button>
<?php
if(!empty($_POST)){
var_dump($_POST);
var_dump($_SESSION['token']);
}
?>
</form>
</body>
</html>
If You have php version >= 5.4 try to set builtin server in php with this command ():
php -S localhost:88 -t /path/to/your/app
Assume that You are testing in your local computer. Mayby something is wrong with apache+php stack on your server.
Check the value of the sha1(uniqid(mt_rand(), true)). IE has problems with names that contain '-' or '_' - they cannot maintain a session! I've had this problem twice in the past, and it always takes me weeks to figure out, and I'm shocked IE hasn't fixed it.
Just make sure you don't have such characters!

Page redirect to previous page after authentication

I was trying to redirect users to the previous page after authentication. It works well with the below codes.
The file login_page.php (the page where users enter login credentials) contains the below code which stores the SOURCE URL and passes it to next page.
<input type="hidden" name="url" value=<?php echo $_SERVER['HTTP_REFERER'] ; ?> />
File do_authentication.php (page which does the authentication) has the code echo "<meta http-equiv='Refresh' content=0;url='$_POST[url]'>"; which redirects to SOURCE URL
In the normal situation it works, but in situations when user enters wrong credentials, the page is redirected to login_page.php and it asks the user to try again with correct credentials. At that time, 'url' value changes to login_page.php.
What is the correct/better logic to solve this?
I've always used the session to retain the original page when doing login. This will not work if the session isn't supported. Then I just send the user to the home page.
A Stack Overflow post discussing this is Redirect to previous page after logging in using PHP.
You should consider using session variables to store the value of the page you want to redirect to. HTTP_REFERRER is not right option.
Just try below:
<input type="hidden" name="url" value=<?php echo pathinfo(__FILE__,PATHINFO_FILENAME ).".".pathinfo(__FILE__,PATHINFO_EXTENSION); ?> />
Use:
header("location: ".$_POST['url']); // Redirects to posted page
exit; // Prevents execution of other code after this
In login_page.php, you could check if you already passed a URL; if so, pass this one instead of the HTTP_REFERER.
<?php if(isset($_POST['url']) ?>
<input type="hidden" name="url" value=<?php echo $_POST['url'] ; ?> />
<?php else ?>
<input type="hidden" name="url" value=<?php echo $_SERVER['HTTP_REFERER'] ; ?> />
Or in a more concise way
<?php $url= (isset($_POST['url'])) ? $_POST['url'] : $_SERVER['HTTP_REFERER']; ?>
<input type="hidden" name="url" value=<?php echo $url; ?> />

Writing PHP variable value to another variable in HTML form

I would like to understand why the below is not working. It is code that I have inherited and it did work on the previous webmaster's hosting.
The page has a $service variable in the URL hence the echo $_GET['service'] below in order to display the value of the variable on the page. However, we want to use that same variable value on the next page also.
At the moment I cannot use echo $_POST or I even tried echo $_GET on the next page to display this
value. There must be something out of date or wrong with <input type="hidden" name="service" value="<? echo $service; ?>" />.
I tried value= echo $_GET['service']; but this did not appear to change anything,
Grateful for all help.
Thanks.
<?php echo $_GET['service']; ?>
<form action="send-order.php" method="post">
Email<br /><input name="email" value="<?echo $email;?>" type="text" style="width: 350px;" />
<input type="hidden" name="service" value="<? echo $service; ?>" />
<input type="submit" value="Order now" /></p>
</form>
Uhm, first of all I'm seeing your form action is POST (instead of GET), so it's natural you don't appen the service input to the url...
Another thing, you're saying that the code worked previously: it might be for the use of register_globals (turned ON; in darker times that was the usual setting, now it's disabled by default) on the previous server's settings, which automatically made available to the var $service what should have been called with $_GET['service'] (or $_POST['service'], for what that matters).
I still don't understand where the "p" param comes in the URL from your comment, though. If you change the form action to action="get", you will have something like "email=something&service=somethig", but 'p' ?
$service is a variable.
http://example.com?service=foo is a GET parameter.
$service is not the same as $_GET['service']
$_POST['service'] is not the same as $_GET['service']
That said, the form's method is "post". If you're posting to the same page where the form is located, then use $_POST['service'] instead. Or change the form method to "get" and use $_GET['service'].

Post data again after authorization

I have a CakePHP application where there is a form that is visible to visitors who haven't even logged in. If they submit the form without logging in, they are redirected to a login page from where I want them to go back to the add controller with all the submitted form data.
Is this possible? If yes, how?
Off the top of my head, something like this should work:
function beforeFilter() {
// be sure to do this before any Auth or security checks
if ($this->RequestHandler->isPost() && $this->data) {
$this->Session->write('last_post_data', $this->data);
}
}
function add() {
if (!$this->data && $this->Session->check('last_post_data')) {
$this->data = $this->Session->read('last_post_data');
}
$this->Session->delete('last_post_data');
if ($this->data) {
// save as usual
}
}
Just make sure to properly dispose of the POST data saved in the Session, or it could wreck havoc later on. In fact, you should not only save the data in the Session, but also which action it was intended for ($this->action and $this->controller) and check for that before reusing the data in the action. Possibly also put a very tight timeout on the data.
I think you will have to use the SESSION or do something like to this:
<input type="text" name="user" value="<?php echo $_POST['user'];?>">
<input type="password" name="password" value="<?php echo $_POST['password'];?>">
Note that above i have used the POST array but you can also use Cake's array for this if there is one.
Assign a session to the users before logging in, and store the data in the session. That session might have an attribute loggedIn which is default false.
Don't store the session data in a cookie though, keep it server side :)
Put session_start(); on the top of the form, and login page. On the form's action page set session variables:
$_SESSION['name'] = $_POST['name'];
$_SESSION['address'] = $_POST['address'];
etc...
On the form page, set values by saying the following:
<input type="text" name="name" id="name" value="<?php echo $_SESSION['name']; ?>" />
<input type="text" name="address" id="address" value="<?php echo $_SESSION['address']; ?>" />
etc...
If you only allow logged in users to access the form, you could also add a periodic AJAX request to the page with the form that keeps the session alive.
window.setInterval(function(){
jQuery.get("/url/to_page_that_does_nothing");
}, 600000);
You could also set it up so that the timer is acticated only when the user starts filling out the form.
Disclaimers: 1) this uses jQuery 2) not as secure as logging in again, but faster/easier to implement.

Categories