views:

251

answers:

5

Possible Duplicate:
Best redirect methods?

Hello

I am working with some legacy code that includes a module for user registration / login. There is a block that queries the DB to see if the user is logged in, then re-directs to the login page.

The re-direct is handled by <meta http-equiv='refresh' content='=2;index.php' /> but I have since learnt this is depreciated, and doesn't work in all browsers.

Is there an alternative way to put a re-direct within the code below?

    $username = mysql_real_escape_string($_POST['username']);
    $password = md5(mysql_real_escape_string($_POST['password']));

    $checklogin = mysql_query("SELECT * FROM users WHERE username = '".$username."' AND password = '".$password."'");

    if(mysql_num_rows($checklogin) == 1)
    {
        $row = mysql_fetch_array($checklogin);
        $email = $row['email'];

        $_SESSION['username'] = $username;
        $_SESSION['email'] = $email;
        $_SESSION['LoggedIn'] = 1;

        echo "<h1>Success</h1>";
        echo "<p>We are now redirecting you</p>";
        echo "<meta http-equiv='refresh' content='=2;index.php' />";
    }
    else
    {
        echo "<h2>Error</h2>";
        echo "<p>Sorry, your account could not be found. Please <a href=\"index.php\">click here to try again</a>.</p>";
    }

Many thanks for any pointers.

+3  A: 

You can use header() before any content is sent to the server:

header("Location: index.php");
die();

this will send the browser a 302 response and cause it to open the other page instead.

Always make sure you DO NOT output any content after issuing a `header("Location"). Anything you output will still be sent to the browser!

The easiest way to achieve that is usually issuing a die() after the header("Location:") call.

Pekka
You might not want to `die` since some resources might have to be freed or disconnected. The Joomla! framework yells at me horribly each time I make a page die.
MvanGeest
@Mvan die is obligatory here.
Col. Shrapnel
@Mvan possibly, but it's important to shut down the page somehow, because otherwise, the response body still gets sent - that's especially dangerous when you're redirecting away from a protected resource.
Pekka
@Pekka - it actually sends a REDIRECT (302) status code to the browser unless the 201 or a 3xx status code has already been set
seengee
What if you DO want to send output to the browser (clearly, he does)
Dustin Fineout
@seengee cheers, corrected. @Dustin it should be easy enough to change the position of the script inside the document.
Pekka
die is not obligatory! In fact it is often not even desired. Just because you're done sending output doesn't mean you're finished scripting...
Dustin Fineout
How does location of the script affect anything? If you want to show "Success! redirecting..." then the `header` function isn't a solution.
Dustin Fineout
@Dustin it is obligatory to terminate the "normal" processing of the script and the outputting of any content. If you need to shut down things before die()ing, that is perfectly fine of course.
Pekka
@mvan joomla is an old fart claiming to be a framework. 301 or 303 is appropriate here. after issuance of the header, code must be terminated immediately.
stillstanding
@Dustin if one wants to show "Success! redirecting..." then one needs to use a different solution, e.g. yours.
Pekka
@Dustin I suspect you have misunderstood the question. There is no output in this script.
Col. Shrapnel
Lol no output? Did you read the question? Fail!
Dustin Fineout
Showing "Success! redirecting..." is not a requirement, I am just trying to replace the deprecated "meta http-equiv='refresh'" with something that will work cross browser and ensure a fast re-direct.
Dave
You don't need to terminate the "normal processing" of the script if your normal processing is to be finished. But then if you are in the habit of using a single PHP file for all the pages in your application, yes you might use a die statement. I tend to code atomically so using die at such a time would be erroneous.
Dustin Fineout
@Dustin this has nothing to do with how atomic your application is. When a `Location` header is issued, the response is not to have any output in its body, period. If you use `header:location()` to redirect a user away from a protected resource, it is good practice to terminate processing after the `header` statement to prevent anything protected from making it through into the response body.
Pekka
@Dustin `What if you DO want to send output to the browser` HTTP protocol forbids this. Location: header should be response to POST method request. This is very basic rule, known to all experienced developers. And others should learn it too. You'd better ask your own question instead of arguing here in comments
Col. Shrapnel
Yes it does have to do with atomicity. If I know a location header was sent, my app isn't going to then spit output. It won't happen. I don't need to die to prevent it because the function is going to return and the script is going to terminate. I knew what I was doing when I wrote the location header, and I don't need to erroneously use die.Col quick Google search shows that is just incorrect, go reread the HTTP protocol specs.
Dustin Fineout
Lol and seriously "This is a basic rule, known to all experienced developers" you are going to imply that every basic rule is known to every experienced developer? I'm sorry sir but such an arrogant statement implies lack of exposure to the depth and breadth of "development".
Dustin Fineout
(says the man who doesn't know the difference between GOTO and THROW lmfao)
Dustin Fineout
he is probably talking of application structure where it goes directly to it's natural end without using die. same thing other words. that's the only explanation I can find
Col. Shrapnel
@Dustin bad example - @Col's question you are referring to is actually questioning the concept of exceptions, a view with which he is not alone. http://www.joelonsoftware.com/items/2003/10/13.html Whether you agree with the view or not, this is not a beginner's question. I think you must have given that question only a very shallow read to reach a judgement like that.
Pekka
@Dustin re request bodies after header redirects: You are right, the protocol does not *prohibit* content in the response body, but it says this: `The temporary URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s). ` (from http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
Pekka
And @Dustin look, if your app structure handles this well, then good for you - that's the way it should be. However, I will continue to recommend `die()` in these cases because in many, many scripts, especially from newbies, flow control is *not* as good. I agree though that the wording should be different: "Make sure you DO NOT output any content after issuing a `header("Location")`" - rather than "make sure you die()". Updated my answer accordingly.
Pekka
If you say so, but anyone is free to do their own research.
Dustin Fineout
A: 
header ("Location: index.php?success=1");
exit;

and in index.php

if (!empty ($_GET['success'])) {
    echo "<h1>Success</h1>";
}
Piotr Pankowski
A: 

In addition to the header function mentioned by Pekka, you could alternatively use javascript - this is the behavior intended to replace the meta refresh which has been deprecated.

<script>top.location = 'index.php';</script>

Simply replace your meta line with the above.

You can even add a timeout as follows:

<script>setTimeout('top.location = \'index.php\'', 2000);</script>

The above will wait 2 seconds before redirecting.

Dustin Fineout
It's not the method I would use, but I don't think it deserves a downvote, it's a valid way and the only way to do it after the page is done rendering (provided JavaScript is active). +1 to even it out.
Pekka
If anyone downvoted this its out of spite and I have no idea why. Go read W3C specs it explicitly gives this as the replacement for the meta refresh. Try commenting if you're going to downvote.
Dustin Fineout
This solution is client-side like the meta is, it doesn't rely on you using PHP it will work regardless of your language and is the most generally applicable solution.
Dustin Fineout
@Dustin I disagree with that. JavaScript can be turned off, and the likelihood of that is much bigger than the Meta redirect not working. Header() is the most reliable variant of all, and should be used if possible. It works even for command line HTTP clients.
Pekka
Miss the point.
Dustin Fineout
@Dustin why? A Javascript redirect is crap if the client has Javascript turned off. If you want to make *sure* the redirect happens, issuing a header is the only reliable way.
Pekka
There are innumerable reasons why. This is the solution Google uses. If you want an instant redirect that sends no body to the client, then yes by all means use the http header. The OP was sending a body, and wanted a timeout. Neither of those are possible with a header redirect.
Dustin Fineout
A: 

First of all: Meta is only allowed in the head-section of a HTML-document so putting it out after h1 and p in the body is wrong and won't work at all in most browsers.

For showing a message for 2 seconds and redirect afterwards you'd have to use javascript, php can't do that for you.

Plain javascript would be using setTimeout (value in milliseconds)

setTimeout("location.href = 'index.php';",2000);

If you want to use jQuery you could use the delay()-function.

stefan
Sorry, sometimes stackoverflow doesn't give notice when new answers have been given while you type yours.
stefan
I don't really see why this got downvoted... Upvoting to even it up, even though I wouldn't use a JS redirect.
Pekka
@pekka: Thanks. I'm not a big fan of JS-redirects either but thinking the success message on the same page is a must I couldn't think of another way. Of course you are right to redirect by using header() if the message-part is optional.
stefan
A: 

META refresh is not deprecated. Your refresh tag has an extra =. It should be

<meta http-equiv='refresh' content='2;index.php' />

You can do a refresh with a header too:

header("Refresh: 2;index.php");

Or use 302 redirection:

header("Location: /index.php");

Or do it in Javascript.

And the best method? Use a META refresh tag in the <head> section. Rationale for this is that IE does not save headers when it uses cached version of a page.

jmz
I don't know who downvotes valid answers. Must be a troll. +1 for even it out.
stefan