2

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.

Community
  • 1
  • 1
Dave
  • 686
  • 2
  • 13
  • 31
  • 1
    doing escaping before md5 is nonsense. escaping should be the very last thing done to the data going into query. and escaping may spoil some passwords, making them not working – Your Common Sense Aug 03 '10 at 12:31
  • 1
    Symbolic +1 for @Gordon for being the only one bothering to look for dupes. Not for the first time :) – Pekka Aug 03 '10 at 12:31

5 Answers5

8

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
  • 5,399
  • 27
  • 29
5

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
  • 442,112
  • 142
  • 972
  • 1,088
  • 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 Aug 03 '10 at 12:26
  • @Mvan die is obligatory here. – Your Common Sense Aug 03 '10 at 12:28
  • @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 Aug 03 '10 at 12:28
  • @Pekka - it actually sends a REDIRECT (302) status code to the browser unless the 201 or a 3xx status code has already been set – robjmills Aug 03 '10 at 12:31
  • What if you DO want to send output to the browser (clearly, he does) – defines Aug 03 '10 at 12:31
  • @seengee cheers, corrected. @Dustin it should be easy enough to change the position of the script inside the document. – Pekka Aug 03 '10 at 12:32
  • 1
    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... – defines Aug 03 '10 at 12:32
  • How does location of the script affect anything? If you want to show "Success! redirecting..." then the `header` function isn't a solution. – defines Aug 03 '10 at 12:33
  • @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 Aug 03 '10 at 12:33
  • @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. – bcosca Aug 03 '10 at 12:34
  • @Dustin if one wants to show "Success! redirecting..." then one needs to use a different solution, e.g. yours. – Pekka Aug 03 '10 at 12:35
  • @Dustin I suspect you have misunderstood the question. There is no output in this script. – Your Common Sense Aug 03 '10 at 12:36
  • Lol no output? Did you read the question? Fail! – defines Aug 03 '10 at 12:40
  • 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 Aug 03 '10 at 12:42
  • 1
    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. – defines Aug 03 '10 at 12:42
  • 1
    @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 Aug 03 '10 at 12:44
  • @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 – Your Common Sense Aug 03 '10 at 12:45
  • 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. – defines Aug 03 '10 at 12:50
  • 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". – defines Aug 03 '10 at 12:54
  • (says the man who doesn't know the difference between GOTO and THROW lmfao) – defines Aug 03 '10 at 12:57
  • 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 – Your Common Sense Aug 03 '10 at 13:09
  • @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 Aug 03 '10 at 13:20
  • @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 Aug 03 '10 at 13:24
  • 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 Aug 03 '10 at 13:32
  • If you say so, but anyone is free to do their own research. – defines Aug 03 '10 at 16:25
4

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.

defines
  • 10,229
  • 4
  • 40
  • 56
  • 1
    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 Aug 03 '10 at 12:34
  • 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. – defines Aug 03 '10 at 12:43
  • 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. – defines Aug 03 '10 at 12:46
  • 1
    @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 Aug 03 '10 at 13:03
  • @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 Aug 03 '10 at 13:34
  • 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. – defines Aug 27 '10 at 20:42
0
header ("Location: index.php?success=1");
exit;

and in index.php

if (!empty ($_GET['success'])) {
    echo "<h1>Success</h1>";
}
Piotr Pankowski
  • 2,396
  • 1
  • 15
  • 18
0

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 Hoth
  • 2,675
  • 3
  • 22
  • 33
  • Sorry, sometimes stackoverflow doesn't give notice when new answers have been given while you type yours. – Stefan Hoth Aug 03 '10 at 12:37
  • I don't really see why this got downvoted... Upvoting to even it up, even though I wouldn't use a JS redirect. – Pekka Aug 03 '10 at 13:30
  • @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 Hoth Aug 03 '10 at 14:00