PHP header strange behaviour after processing URL - php

On my website i am using quite amount for GET parameters in url for loading specific page. And some of available actions involve calling another GET parameter in order to do something (..&act=something). PHP file with this actions is included at the top of the page. Below of this inclusion i have some code that checks if URL is valid, otherway header will head you to the correct one.
Lets say i have added a player as a friend.
Requested URL will be for example:
?id=3&request=clan&act=add&target=5.
So going by this url i am supposed to go in case: 'add' part and later being redirected by that header. However what i have is that this header is ignored. Instead, i am redirected by checking part. What is more odd, added friend appears in my friend list. Why does this happenes?
<?php
if (isset($_GET['act'])) //this code is included
{
switch ($_GET['act'])
{
case 'add':
//do something
header('Location: /index.php?id='.$cuid.'&request=clan&section=members');
break;
}
}
//some other code
if ($_GET['request'] == 'clan')
{
if ((!isset($_GET['section']) || ($_GET['section'] == '')) && ($c_guid != 0))
{
header('Location: /index.php?id='.$cuid.'&request=clan&section=info');
}
}
?>

Outputting a header does not actually stop your script! All the other code is running as well. You need to explicitly exit if you do not want any further code to be executed.

Related

Redirects & Non Browser created POSTS

I have a script which logs some stuff into a database. At the start of the script I have some code which tests a session to determine if a user is logged in - and if not - redirects them to the front page.
if (!$_SESSION['user']['loggedin'] || $_SESSION['user']['access_level'] < ACCESSLEVEL_ACOUNT_MANAGER) {
redirect('../index.php');
}
But - I'm getting odd entries into the database that are coming from this script. That I know for sure. I've set up a routine that emails me when an entry is made telling me the values of those sessions - and they're blank.
If a POST does not come from a browser - will the redirect be ignored and will the rest of the script be processed?
--
Edit - here's the redirect function (prior to me adding the exit) which was the culprit.
function redirect($url) {
session_write_close();
if (true || headers_sent()) {
print "<script langauge=\"JavaScript\">window.location='$url';</script>";
} else {
header("Location: $url");
}
header("Location: $url");
}
If a POST does not come from a browser
The type of client that makes an HTTP request is largely irrelevant.
The significant part here is that $_SESSION['user']['loggedin'] is empty, so the if passes and the redirect function is called.
will the redirect be ignored
The redirect function will be called.
The client may or may not follow the instruction from the server to request a different URL instead.
and will the rest of the script be processed?
The behaviour will be the same as for a browser.
There's nothing in the question to tell us what the redirect function does.
It might exit, in which case anything after the if statement will not be processed.
It might not.
… but the result will be the same for any kind of HTTP client. Browsers are not a special case.

redirection without reloading the whole page

I have a framework and I think I'm following something like the MVC pattern: A framework (the model) an index page that controls the input (the controller) and the views pages (that are included inside main.php/the main html)
I read a lot about structure and logics, to write a good application. I read many comments like "Why are you outputting anything if all you are going to do is try and redirect the user to another page?". Well the answer is, the most common case: redirect after the user successfully logged in. Do I need to print something? Of course, the whole main page with a login form/post. How I'm supposed to do that redirection??
So I'm a bit confused about logics and structure of the application. How do you store all the output and do the header redirection without printing anything?
I was thinking about using javascript to do the redirection but I also read comments saying; "if you write good code (following a good logic/structre), you won't need to use hacks like javascript redirection". How is that even possible?
Because the php output_buffering should not be enabled.
I have the output_buffering enabled, and I can use header (after output) without any problem. If I use the javascript redirection the whole page reloads, but using header it just loads the content (the views content that are included in main.php).
So how do you do this without output_buffering?
If you want to redirect to a success page AND pass messages - say, after a successful login - an easy solution is to use "flash" sessions, where you store a message in a SESSION and then, as soon as it's used, you discard it. You don't need to sore anything in the output buffer for this.
This is a very basic example, but should give you the gist of it.
login.php
if($login_successful) {
// put your message in the session
$_SESSION['message'] = 'Login Successful';
// redirect to the success page
header('location: success.php');
}
success.php
<?php
session_start();
// check if $_SESSION['message'] exists
if(isset($_SESSION['message'])) {
// print the message
echo $_SESSION['message'];
// clear the session
$_SESSION['message'] = null;
}
Looks like you are mixing up some things here. What you are talking about are actually two different requests. Either the user wants to view the main page, or he wants to log in using that form on your main page. In your index.php you would have something like this (pseudocode):
if (isLoginRequest) {
// user wants to log in
if( validateLogin($loginFormData) ) {
redirect('successful');
} else {
displayLoginError();
}
} else {
// user wants to view main page
echo main.html
}
Update to answer the question in the comments: The better alternative would be to leave your form validation stuff in login.php and refer to that in your login form <form action="login.php" .... Then in your login.php you would have something like this:
if (loginSuccessful) {
redirect('success.php');
// no need to call die() or whatever
} else {
setFlashMessage('Login failed'); // set a flash message like timgavin described
redirect('index.php')
// also no die() or whatever
}
index.php then is responsible to display your main page and, if set, rendering the flash message from a failed login attempt.
Simple solution: Move the login post script from login.php to another file (login_post.php). The same for other scripts using header() after dom output. (no need to change the form action="")
In index.php:
$url = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
//some more security checks like esc_url() (non-php function)
if ($url == '/login') {
include('header_pages/login_post.php');
}
// all these includes before including main.php
// where views pages are included and the DOM output starts
Since header() is inside the post script, no more headers already sent errors (And output_buffering off, of course).
Same for logout page that is currently being included inside main.php
Thanks to the other answers, they helped me finding this solution.

Allow PHP page only if set the correct url

I am trying to figure out how to allow PHP index only if it matches the URL I put in, something like this:
Example if you put in URL site.com/myfile.php I want to show message like 404 Error or something
But if you put site.com/myfile.php?=123 to show the page content.
I think it might be considered bad practice to send someone to a 404 when the page that they are accessing does actually exist, it's only a variable that they are missing.
Firstly, I'd expect to see something like
site.com/myfile.php?variablename=123
instead.
If you absolutely wanted to, you could at the top of your file then add a:
if(!isset($_GET['variablename']){
header('location:404.php');
}
Where 404.php is your 404 file that you'd like the user to see.
Hope that helps?
You could run a conditional looking for the request info, i would make it specific like using a ?page_id=123
<?php
if ( $_REQUEST AND isset($_REQUEST['page_id']) )
{
// SHOW PAGE CONTENT
}
else
{
// RETURN 404
}
?>
You would have to test the $_GET parameters.
if (!$_GET) {
echo "404 Error"; //or redirect using header();
} elseif ($_GET['key'] == 'value') {
//code here
}
I see you are using ?=123, I'm not 100% on if that will work, but it's easier (IMO) to have a key=>value association in the URL.
This should be enough for what you need. If there are other requirements let us know.
if(!isset($_GET)){
//do whatever you want to validate the get input provided.
} else {
header("HTTP/1.0 404 Not Found");
}
Well first of all this ?=123 might be an issue because when ?=123 is passed then it should be stored somewhere, it could be like this ?uid=123 and then you retrieve it in a variable through the get method and then check its value and accordingly redirect the user.
You can do something like this
if(isset($_GET['uid']))
{
refresh(to whatever location you want);
}
else
refresh(to some other location);
but if you want the error 404 something then its not possible according to me, because the values will be sent to a page that exists and if the page exists then the server cannot give a "not found" error.
By simply comparing a string.
if (#$_GET['secret'] != 'mysecret'){
header('location: noaccess.php'); //redirect the user to access denied page.
die(); // terminate the script. A
}
// The rest of the page
Or to keep everything in one file:
if ((isset($_GET['secret'])) && ($_GET['secret'] == 'mysecret')){
// Show the page
} else {
// Show an error message
}
site.com/myfile.php?secret=mysecret

Redirect Loop Error when using the Header function in PHP

I am having trouble with a redirecting a user to a certain page. I keep getting an error of "redirect loop". I know what this is, unfortunately, I do not know how to fix it. Here is my code $ setup.
//Check to see if the account is 'Active'
if (isset($_SESSION['inactive']) && $_SERVER['PHP_SELF'] != 'account-balance.php') {
if ($_SESSION['active'] != 'Yes') {
$_SESSION['inactive'] = TRUE;
header('Location: account-balance.php');
}
}
This code is in a "header.php" include file that is included on every page. What I am wanting to do is check whether or now a users account is active. If it is not active, redirect to the account-balance.php page. Any link they click on, I simply want it to redirect them back to the account-balance.php page until they make their payment. Is this possible to do?
I figured it out. It is suppose to be basename($_SERVER['PHP_SELF']) to get just the current page name.

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.

Categories