php - track down premature headers leak - php

I'm using set_cookie() on a site. After adding some functionality, I'm getting Warning: Cannot modify header information - headers already sent by... error. The line number it references as to where the headers initiated from is the very line where set_cookie() is! And I checked, it's not being called twice.
How can I track down these premature headers? I looked at the source code and didn't see any stray characters or anything before the error message starts ( I'm using xdebug, so the first thing is a , which I thought was me, but is actually the beginning of the xdebug message ). I've grepped my code for extra echo and so forth -- nothing.
Can PHP tell me when and where the headers are starting? Or are they really starting on the set_cookie line, and if so, how have I gotten myself into this situation, and how do I get out?
edit: I'm not sure I can paste the code -- do you want just the set_cookie() line? I thought the headers were coming out before that. And there's a lot going on before that with different classes being instantiated. And also I don't think I can post all the classes and stuff -- you know, proprietary information ;)
Edit: I've gotten rid of all terminating delimiters ( all ?>s) and made sure that the first characters of every included file is <?. This is frustrating! It was working before I did these recent changes :(((
Also, why doesn't headers_sent() work?
if ( headers_sent($filename, $linenum) ) {
echo "headers sent: $filename:$linenum.";
}
set_cookie(...);
gives
headers sent: :0.

You can use headers_sent():
if (!headers_sent($filename, $linenum)) {
set_cookie(/*...*/);
} else {
echo "Headers already sent in $filename on line $linenum\n";
exit;
}

One approach would be to run your script from the command line with STDERR redirected to null.
This will show you everything that is being sent to STDOUT, i.e. everything that the server would send to a client.
Hopefully, once you see this, it will be clear where your headers are coming from.

Besides using headers_sent to detect if the HTTP header has already been sent, you could use the PHP’s output control to buffer the output. That allows you to change the header even if you’ve already done some output.
Here’s some example using the explicit output buffering by calling ob_start:
ob_start();
echo 'foobar';
header('Content-Type: text/plain;charset=utf-8');
But make sure you call ob_start before any output was done. Otherwise the HTTP header probably has already been sent.

Can you paste the code?
If its saying headers already sent by [line where set_cookie is], then the error is further on in the script.

Are you sure that you don't have any include files being called prior to your set_cookie() initialization? Do you have sessions running, because if you do, you could just set the cookie at that same point in your script as you started the session.

If there is even a single white space before your set_cookie() initialization it will cause the headers to not be sent correctly. Maybe try using a different editor and checking your results.

I found it! It was a flush(); that I had left lying around all by itself in one of the pages. Surprisingly, it doesn't correctly bind $filename and $linenumber to headers_sent().

Related

Header function not working for the log out and log in

Well I have have already read the cannot modify header
But still I'm getting the error
Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\xampp\web\librarian_menu.php:582)
This is my code , I don't know what i am doing wrong
<body>
<?php
#session_start();
require 'connect.php';
if(isset($_SESSION['lib']))
{
echo '<strong style="position:relative;top:25px; left:940px;">'.$_SESSION['lib'].'</strong>';
}
else
{
echo "<script>alert('You need to login first')</script>";
header('Location: quote.php');
}
if(isset($_POST['log_out']))
{
unset($_SESSION['lib']);
header('Location: quote.php');
}
?>
.
.
.
If what you posted above really is your code, then it is pretty obvious where the problem comes from. Just look at the first line of code right before your opening php tag:
<body>
<?php
#session_start();
require 'connect.php';
See the <body> tag? You output it before anything else. A similar issue exists within the else branch of the first conditional: first you echo some string, then you call the header() function. You simply must not output / echo anything prior to calling that header() function.
Note that such code might work, when the http server caches the preliminary output. But you have no guarantee for that. So you cannot rely on it. Apparently in your case that output is not cached, but sent before you cann the header() function.
The reason for this behaviour of php, for this issue is a simple one: http headers are preceding an http reply. Per definition there cannot be any content contained in a reply before the headers. So once php start to send any content it must close the headers and sent them first. If you try to add any additional headers afterwards php has no choice but to raise an error: sending simply is impossible within that reply.
You have to restructure your code to sent the headers prior to anything else. If that really is not possible, then you might want to take a look at "output buffering". It allows you to hold back any output and release it to the client only later, after having done whatever is required, for example defining additional http headers.
Any maybe a side note, just to make things crystal clear: with the message "Warning: Cannot modify header information..." php refers to the http headers, not to any html header tag you might use.
Before header function (such as session_start, header) you cannot output anything to the browser - remove echos and html tags like <body> from the code before session_start() or header().
Read the first few lines of this : http://php.net/manual/en/function.header.php

how to ignore redirection errors in php

I got this warning in php:
Cannot modify header information - headers already sent by (output started at
When I installed mysql, apache, and php separately but when I'm using Wamp the warning does not exist and the page redirects gracefully.
I have already tried setting the error reporting to only display errors and not warnings and what happened is that the warning didn't show up but the page also didn't redirect.
I know this is already considered bad practice but my code base has a lot of these codes and modifying them all might introduce new bugs to the code.
Is there any way to completely ignore this warning in php?
The classic way to avoid - and not ignore - this problem is with output buffering, ob_start() and ob_flush(). Start the buffering before any output, and finish with the flush explicitly, or it may do so automatically. This captures any output rather than printing it, and so any headers that are output are done so before any visible content.
Fixing the bug of things being output, from the filename you had in the error message is the best way to fix this though. Removing the closing '?>' from files when it's not needed might help.
This is an horrible practice but just set
error_reporting(0);
at the beginning of your script. Otherwise setit in php.ini
display_errors = Off
EDIT - probably you are outputting something before the redirect. I once spent three days debugging this and the reason sometimes is whitespace at the end of files or the fact that you output some HTML to the browser before the redirect.
I usually never close the php tag to avoid this
Even when you don't show your error your application will not work. This is because like the error said the headers are already sent. What this means is the following:
A browser requests your php file at the server. The server then executes this and sends back the resulting html. This error tells you that you are sending something back to the browser after you already sent the result of your php file. So I'd suggest you try to fix the error your getting instead of just not showing it.
You can't "ignore" this warning and redirect. The warning says so clearly:
Can't send headers! Headers already send by output!
This means that the header (the Location header cannot be sent because output was already sent. (Headers may only be sent before any and all output).
Please RTM, you need to fix your bugs, not ignore them.
The error is caused by you sending some sort of output before the header() function is called, the reason for that may be a lot of things, when unexpected, the immediate suspect is a whitespace at the beginning or ending of some file.
<?php //Note the space before the opening tag!
header("Location: this-will-fail.html");
?>
Please note that this error specifies exactly where in your code you've started to output data to the browser (see the output started at ...1, look for trailing white space \r, \n, tabs & spaces).
In theory, turning off the error reporting will not cause the page to redirect because the headers were already sent and therefore cannot be changed or added to.
What you should do if you need to redirect with data already sent is something like this:
if ( headers_sent() ) // Check if the headers were already sent
{
echo( "<script>document.location.href='$url';</script>" ); // Use client side redirect
die(); // Stop here
}
else
{
header( "Location: $url" ); // Use server side redirect
}
But the best thing would be to find out where the output started and fixing that (if possible).

alternate php redirection method that works with output preceding it

so apparently if you do this:
<?php
echo 'something';
header("Location: http://something/");
?>
it will not work because there is an output preceding the header...
is there any other alternative php redirection method that works straight from php without installing anything and in which it will still work even if there's an output preceding it so that I don't have to worry about making sure that there is no output before, etc...
not, unless you do something in javascript or html tags in the page that you output itself
if preceding output is a problem
you can also use output buffering, see ob_start, ob_get
to get around that
There is no other way to do a php redirect, but you can fool it to still work even with code prior. You would buffer the content and only output it if there is no redirect or reaches the end of the script. Note: this may be resource heavy in some cases.
ob_start()
....CONTENT...
ob_end_flush();
There are no ways in PHP except using header()... before output is sent (headers be already sent)...
You can either use meta refresh in HTML that is set at zero seconds, or javascript.
But I wouldn't recommend javascript as some will have it disabled.
You could use a meta refresh tag.
You understand why this is impossible, right?
As soon as you echo "something" you have sent content to the client, and as part of that client headers were already sent. You can't retroactively modify headers you already sent, and you can't make two responses to one HTTP request.
ob_start() and ob_end_flush() will buffer the output instead of sending it to the client, which will allow you to get around this problem, BUT
a better solution would be to:
separate your logic code from your template so that you don't write anything to the screen until you already know you aren't going to redirect.

PHP Forward to next Page

I have a form that, on submit, is going to a PHP file.
Here the form is processed and sent to a MySQL database for storage.
After this is done I want the page to, automatically, send me to the next page wich contains another form that has to be filled in (this continues a few times).
I know that you can use
header('Location: HERE YOURE LINK ');
for sending you to the next page, but it doesn't work.
In my PHP file I have some basic stuff:
Request form, process data, INSERT INTO database....
When I put the "header....."-code after these PHP commands it returns an error, and the same thing happens when I place it in front of the PHP commands.
It keeps returning the error:
Cannot modify header information - headers already sent by .... on line 17
I hope someone can help me, and that I have given you all the information you need to help me. I've been searching all day but still haven't found the solution.
Thanks in advance!
Milaan
You need to make sure the header(...); line is called before any other text or headers are sent.
The "headers already sent" error is usually caused by having white space before or after the opening and closing PHP tags (<?php . . . ?>).
Use of ob_start() also helps.
This function will turn output buffering on. While output buffering is active no output is sent from the script (other than headers), instead the output is stored in an internal buffer.
A detailed description of your very common problem may be found at the following link:
http://www.phpbuilder.com/board/showthread.php?t=10262775
Putting the html tag before the header() blocks it. Please check.

how does the header work in php?

Going through the php.net site, it had an example for header, which says would give me error. I copied it, and executed on on WAMP, but it didn't showed me any error, but did redirect to the site.
<html>
<?php
/* This should give an error (but it doesn't!). Note the output
* above, which is before the header() call */
header('Location: http://www.example.com/');
?>
Just wanted to know, if its a right behavior on my WAMP, or its an error, or if I have any particular settings active in php.ini file which is making this work!!!. Let me know if anyone needs my php.ini to be copied here!!
Thanks,
Tanmay
It sounds like you have output_buffering enabled.
http://php.net/manual/en/outcontrol.configuration.php
Standard configuration would be to error because data has already been output, and headers need to come first. Output buffering would allow headers to appear in code after other output, but it would still output the headers first due to the buffer.
Headers are sent as soon as any text is sent to the browser, and can only be sent once. once the is sent, headers are sent along with it, so trying the header function after that wll throw a headers already sent error.

Categories