headers_sent() issue with plugins and instant website

By ITI - August 15, 2011 - edited: August 16, 2011

This issue relates to writing plugins and users who use Interactive Tools Instant Website.

This error is hard to reproduce and I haven't been able to do it internally. I can however with the assistance of a site visitor in the Toronto area. I can not explain why only some site visitors are affected so its a bit of a mystery.

To explain I'll have to use the Instant Website initialization file "website_init.php" which contains the line:
// error checking
if (headers_sent()) {
die("You must load " .basename(__FILE__).
" at top of file! Make sure there are no spaces before it!\n");
}
// Note: this is written on a single line (line 11) in website_init.php


Some website visitors will see the error message and the web page will not be displayed.

The reason in my case was that there were active plugins that contained white space (blank lines) after the closing php tag (?>)

To ensure that the page is always displayed in your "Instant website" you can simply comment out the line with 2 forward slashes.
//if (headers_sent()) { die("You must load " .basename(__FILE__). .....

What I did to test this issue was to change the "die" to sending an email instead.
if(headers_sent($file,$line)) {
$to = $SETTINGS['adminEmail'];
$headers = "From: $to";
$subject = "Headers Sent on ".$_SERVER['SERVER_NAME'];
$msg = "Headers already sent accessing: ".$_SERVER['SERVER_NAME'].
"\nIn $file, on line $line, from IP: ".$_SERVER['REMOTE_ADDR'];
mail($to,$subject,$msg,$headers);
}

The email contains the line number in the file causing the problem. In Instant website the page still displays so there is no need to "exit". I received several emails from different IP address which indicates that this isn't isolated to just a single visitor.

Note to New Plugin developers:
Be sure you do not have any more than 1 blank line after the closing php tag in any of your plugin files.

I suspect that the use of headers_sent() in any custom code you create could also trigger this error.

I've also include information on this issue on my plugins tutorial page:
http://www.canadiandomainregistry.ca/cmsDocs/cmsPublic/
Glen







http://www.CanadianDomainRegistry.ca







ITI Internetworking Technologies Inc.

Re: [ITI] headers_sent() issue with plugins and instant website

By ross - August 16, 2011

Hi Glenn

Thanks for looking into this! Spaces in plugins can defintiely be a problem when headers are being sent. This is something I've run into myself a few times so I am quite familiar with how frustrating that can be.

If you are still having trouble with sporadic error messages, could you shoot us over a full support ticket? I'd like to take a closer look myself :).

Thanks!
-----------------------------------------------------------
Cheers,
Ross Fairbairn - Consulting
consulting@interactivetools.com

Hire me! Save time by getting our experts to help with your project.
Template changes, advanced features, full integration, whatever you
need. Whether you need one hour or fifty, get it done fast with
Priority Consulting: http://www.interactivetools.com/consulting/

Re: [ITI] headers_sent() issue with plugins and instant website

By Dave - August 17, 2011

Hi Glen,

I've updated the error message to show the source of the whitespace as so:

if (headers_sent($file, $line)) {
die("You must load " .basename(__FILE__). " at top of file! Make sure there are no extra spaces before
it (or at the end of any plugins)! Output started in $file line $line.\n");
}


>Now, if you could tell me/us why some site visitors
>trigger the error while others do not, I would be most
>interested in knowing.

I'm curious about that too, because I would imagine if there was extra whitespace sent it would affect all users. What was the file and line that was reported when you received errors by mail?

Thanks!
Dave Edis - Senior Developer
interactivetools.com

Re: [Dave] headers_sent() issue with plugins and instant website

By ITI - August 17, 2011 - edited: August 17, 2011

Hi Dave.

The problem with using "die(...)" is that the its the site visitor that is seeing error message. The site owner or developer will never know about. Unless the site visitor knows the site owner they are just going to move on to the next site.

I only became aware of the problem because the site visitor called me.

What's weird is that the page will still display even if the headers_sent() was triggered which reinforces the point that there is no need to stop execution of the script.

The initial error was a result of a plugin I had written. I have a tendency to add white space to the bottom so that I'm look at the code in the middle of the screen.

During my testing I added various amounts of new lines to different plugins at different times and my email error message always identified the last line of the file I was testing. Only active plugins generated the error. So basically the error can be caused by any plugin that has "more than one line" after the closing php tag.

I tried generating the errors by accessing the site from my neighbors cable connection, my buddies satellite connection and via W3C's validation scripts which was another form on external access. I could not generate the error.

However, during the testing stage I did receive access errors from other IP addresses other than the person who was assisting me from Toronto. This tells us that it isn't an isolated situation.

I'm still of the belief that it has to do with establishing the communication protocols during the request/response/ack stage via their ISP's satellite or possibly some weird ISP's DHCP configuration between them and their clients.
After all Telus thinks they know it all and yes they are down east as well.

I think you should consider not using die(). Even echo or print would at least allow the page to display.
As for me, I'm going to leave the email notification in place since I do have that tendency to add white space while developing.

ps. To help determine whether or not this is a real issue maybe other users of IW could use the email notification and deliberately add a few extra lines to one of their active plugins.

pps. I have created and activated a plugin with extra line feeds. Click to see if your connection displays the error.
http://www.canadiandomainregistry.ca/cmsDemo/index.php
The page will either display normally or die() and send me an email.
Glen







http://www.CanadianDomainRegistry.ca







ITI Internetworking Technologies Inc.

Re: [ITI] headers_sent() issue with plugins and instant website

By Dave - August 17, 2011

Hi Glen,

If you send headers after you've sent content you'll get a warning from PHP regardless, so the idea with the die call is it shows just that one error and nothing else so it's more noticable instead of PHPs default warning somewhere in the page content, which looks like this: "Warning: Cannot modify header information - headers already sent by ...".

The problem with removing that line (or sending content before headers such as with whitespace in plugins) is that if header have already been sent (which means page content or whitespace has been sent) no more HTTP headers can be sent (and you can't set cookies or, session values either). So, for example, this would produce a "headers already sent" error:

print " ";
ob_flush();
header("HTTP/1.0 404 Not Found");
print "<h1>404 Not Found</h1>";
print "done";


I'm thinking it may be a server-side caching issue. That IIS sometimes hasn't yet sent the content to PHP so PHP doesn't know headers have been sent. Can you try adding this line and let me know if you get the error all the time?

ob_flush();
if (headers_sent($file, $line)) {
die("You must load " .basename(__FILE__). " at top of file! Make sure there are no extra spaces before
it (or at the end of any plugins)! Output started in $file line $line.\n");
}


Anyways, with Instant Website I don't think it's matters much and it's pretty safe to remove that line. All it does is prevent you from getting a different error when the 404 code is called. So if it's not proving helpful removing it is probably the way to go.

Also, it gives me an idea that maybe we could auto-detect the whitespace at the end of plugins in CMSB init and warn developers about it.

Let me know if ob_flush() gives you different results (and if you have any extensions that automatically gzencode/compress output or anything like that.

Thanks!
Dave Edis - Senior Developer
interactivetools.com

Re: [Dave] headers_sent() issue with plugins and instant website

By ITI - August 17, 2011

Hi Dave

I added a link to the previous post to have people test to see if they get the error.

I did as you requested and added ob_flush().
The page failed with the error message. I refreshed a half dozen times and the error message displayed every time.

I've now commented out ob_flush() and reactivated the faulty plugin to see if users from the forums will see the page or the error.
http://www.canadiandomainregistry.ca/cmsDemo/index.php
Glen







http://www.CanadianDomainRegistry.ca







ITI Internetworking Technologies Inc.

Re: [ITI] headers_sent() issue with plugins and instant website

By Toledoh - August 17, 2011

I see the page...
Cheers,

Tim (toledoh.com.au)

Re: [ITI] headers_sent() issue with plugins and instant website

By Dave - August 18, 2011

Hmm, I did some more testing and headers_sent() seems pretty inconsistent and problematic.

I've removed it from website_init.php. Thanks for the tip! :)
Dave Edis - Senior Developer
interactivetools.com