PDA

View Full Version : Warning: Cannot modify header information; php help needed


junkybrewster
12-26-2007, 08:58 PM
Hi All :)

I am running a rich text editor on my webpage using a (heavily) modified version of abitwhizzy/whizzywig. It works perfectly on my midPhase hosting package but here on bluehost, when I make my changes in the editor and click save, I get the following warning:


Warning: Cannot modify header information - headers already sent by (output started at /home/public_html/.../editor.html:7) in /home/public_html/.../abitwhizzy.php on line 52.


I have searched for that problem but a) didn't understand all the answers and b) I've tried what people seemed to suggest and I'm still broken hehe.

I am using include files to allow user to edit only a section of a page. The include files are still updated/saved, it's just my editor page will not redirect back to where it is supposed to (line 52 - header: "location...).

I have removed everything I think is whitespace from any tags.. I did have editor.html under a login screen, but I removed my set sessions include file to test, and I still get the error. I've gone through the php file looking for whitespace or anything that would send html to the browser before the header location call... but I just can't see it.

Now, editor.html is just a plain html page, with my call to include the editor in the middle of the page <?php include("abitwhizzy.php")?> (oh yeah, I allowed html parsing of php in .htaccess). It really needs to go there, because that's where the editor will render! I can't see how I could have it anywhere else. Again, works fine at midPhase.

What confuses me more is the error message referring to editor.html:7. Does that mean line 7? If so, that is my <title> tag.

I am on PHP 4 here. I even converted over to PHP 5 in the settings (as midphase is 5.2.4) but that didn't do anything.

Here is the code I am using in abitwhizzy.php:


<?
//abitwhizzy.php - whizzywig web page editor, demonstrating whizzywig.js
//Copyright 2005, John Goodman - john.goodman(at)unverse.net (i removed some of the comments here for ease of reading)

if (!isset($_SERVER))
{
$_GET = &$HTTP_GET_VARS;
$_POST = &$HTTP_POST_VARS;
$_ENV = &$HTTP_ENV_VARS;
$_SERVER = &$HTTP_SERVER_VARS;
$_COOKIE = &$HTTP_COOKIE_VARS;
$_REQUEST = array_merge($_GET, $_POST, $_COOKIE);
}
$f = $_REQUEST['f'];
$t = $_REQUEST['t'];

//CONFIGURE HERE ================================================== ==================
if (!$password) $password= ""; //can leave password as "" if you are using .htaccess to protect abitwhizzy
if (!$whizzywig) $whizzywig = "whizzery/whizzywig.js"; //path to whizzywig.js required
if (!$cssFile) $cssFile= "css/editor.css"; //choose your stylesheet, or set to ""
if (!$buttonPath) $buttonPath = "whizzery/buttons/"; //toolbar images live here. "" for text buttons
if (!$imageBrowse) $imageBrowse = ""; // "" for no image browser
if (!$linkBrowse) $linkBrowse = ""; // "" for no link browser
if (!$toolbar) $toolbar = "bold italic underline left center right bullet number"; //try "all" if you need more
if (!$editarea) $editarea = "width:90%; height:250px";
if (!$xhtml) $xhtml = "whizzery/xhtml.js"; //path to xhtml converter, or set to "" for HTML 4.01. Use appropriate header in $top.
if (!$extensions) $extensions = "/(html)$/"; //file extensions to consider for edit (in the brackets|to separate)
//LEAVE THESE
if ($xhtml) $doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';
else $doctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>';
//HTML TEMPLATE: Use these 2 variables ($top and $tail) to wrap the generated HTML in your own template.
if (!$top) $top = "";
if (!$tail) $tail = "";
//END CONFIG ================================================== ======================
if (preg_match("#^\.|\.\.\/|^\/#",$f)) die ("Not allowed!");
if ($_REQUEST['save']) { //write page and go there
if ($_REQUEST['p'] != $password) die ("<h1>Wrong password: not saved.</h1>Click the Back button to try again. ");
$edited = $_REQUEST['edited'];
if ($f == "top.shtml" || $f == "tail.shtml") $html = stripslashes($edited);
else {
$html = $top."";
$html .= stripslashes($edited);
$html .= "".$tail;
}
$fsave = fopen($f, 'w'); //save the edited file
fwrite($fsave, $html);
fclose($fsave);
header("Location: editlinks.html");
} else if (file_exists($f)) {
$fedit = fopen($f, 'r'); //open the file for edit
$content = fread($fedit, filesize($f));
$start = strpos($content,"<!--#include virtual='top.shtml'-->") ? "/.*<!--#include virtual='top.shtml'-->/" : "|.*<body[^>]*>|iU";
$stop = strpos($content,"<!--#include virtual='tail.shtml'-->") ? "/<!--#include virtual='tail.shtml'-->.*/" : "|</body>.*$|iU";
$content = preg_replace($start,'',$content);
$content = preg_replace($stop,'',$content);
fclose($fedit);
preg_match('|<title>(.*)</title>|i',$content, $match);
$t = $match[1]; //grab the title
}
?>


I even tried adding php to the opening <? tag of that script above (NB: I left out the second part of the script, the one that renders the form for the editor.. I didn't think it relevant). I also tried deleting all the comments too in case of whitespace...

Do you think my editlinks page could do it? This is still under login. This parses the include file name into the editor (and opens the editor). This is also where I want to redirect to after save.. anyway, basically I don't know what I'm talking about in this area hehe.

Happy holidays! - Junky

areidmtm
12-26-2007, 09:16 PM
Remember that header() must be called before any actual output is sent, either by normal HTML tags, blank lines in a file, or from PHP. It is a very common error to read code with include(), or require(), functions, or another file access function, and have spaces or empty lines that are output before header() is called. The same problem exists when using a single PHP/HTML file.

Basil
12-26-2007, 09:26 PM
You have header("Location: editlinks.html"); in this file, you're including this file in another file which is outputting something before the include.

We need to see editor.html to say exactly what the problem is.

edit: I think I kind of sort of know what you're trying to do, and I'm wondering why you don't use a frame for this?

junkybrewster
12-26-2007, 10:27 PM
Thanks for your help guys,

Here is the code for editor.html:


<?php include("library/session.php")?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="EN" />
<title>Page Editor</title>
<meta name="Robots" content="noindex, nofollow" />
<link rel="shortcut icon" href="images/favicon.ico" type="image/x-icon" />
<meta name="description" content="Online content editor/word processor to change pages" />

<style type="text/css" media="all">
@import "css/non-ie.css";
</style>

<!--[if IE]>
<style type="text/css" media="all">
@import "css/ie.css";
</style>
<![endif]-->

<script type="text/javascript">

var language = new Array();
language['Color'] = "Colour";
language['Color name'] = "Colour name";
language['Hilite'] = "Highlight colour";

</script>

</head>

<body>

<!--Entire Page Wrapper Div Container -->
<div id="wrapper">

<!--Page content Div Container -->
<div id="content">

<!--header banners, image replacement -->
<h1 id="pagetitle">PAGE TITLE</h1>
<p id="topnavigation">
| <a href="userguide.html" title="view help/user guide" accesskey="L" tabindex="1"> Help</a> |
</p>


<h2>EDIT PAGES </h2>

<div id="editor">
<?php include("abitwhizzy.php")?>
</div>

<!-- footer stone bar -->
<p id="footernavigation">| <a href="editlinks.html"
title="return to the list of pages you can edit" accesskey="E" tabindex="4">Edit Options</a>
| <a href="logout.php" title="click to log out" accesskey="O" tabindex="5">Log Out</a> |
</p>

<!-- footer -->
<p id="footer">
some text I deleted
</p>

<!--End Content Div Container -->
</div>

<!-- End Page Wrapper Div Container -->
</div>

</body>
</html>


Note, I have tried WITHOUT the include for library/session, I've also removed the javascript array in the header (this was a new addition) and reverted to simple DOCTYPE (shooting in the dark am I hehe).

This is not my page (though I wrote it..) - it's some work for a friend so I've had to change the <title> tag and my <h1> PAGE TITLE.. for privacy sort of thing. His title is a monster (long long long), but I have also changed that to a simple title for testing... just in case and that didn't help hehe.

It's a bit hard to let you see it "in action" because it's a friends bluehost web server and client's site... and I don't know if he'd want people looking at it "live" and freaking the clients out.. I COULD upload it onto my bluehost I suppose (and remove branding) if you need because my test site is on my midphase space and that works teehee.

Thank you!!!

junkybrewster
12-26-2007, 10:47 PM
Hi Basil,

Just saw your edit. I'm not sure I know that much about frames... normally abitwhizzy is meant for accessing as a URL... you link to www.example.com/abitwhizzy.php and then the editor (buttons, textarea) opens. you can pick the html file on your server you want edited from a drop down list.

I've cut all that out (I want to control what pages they load; that's what my editlinks page is for). The documentation at unverse.net for abitwhizzy does say you can include the editor in your own page so you can design it to suit. However, the example given I could not get to work.. so this was my way of making it work...

Do you mean, that instead of using an include call in editor.html, I could simply load it using frames?

Thanks

junkybrewster
12-27-2007, 05:54 AM
Just posting an update - I've had a breakthrough and gotten rid of the warning and successfully redirected back to the page I want after save... I ended up putting the HTML for my editor page INSIDE the .php file, and calling the php file to parse the include files instead. The reason I didn't want to do that is because using the include (when it works) I can call the editor multiple times for different things.. now I'm sort of stuck with the same page design. Still! It's an advancement.

HOWEVER, when I try to put session code in, to put the editor under my login, I get the same headers already sent warning, both pointing back to editor.php (the new name) to the line where my session code begins.

I have tried to include it above my DOCTYPE in two ways:


<?php include("library/session.php")?>


and by putting the code fully in (without include):


<?php
session_start();

if (!isset($_SESSION['db_is_logged_in'])
|| $_SESSION['db_is_logged_in'] !== true) {

// not logged in, move to login page
header('Location: login.html');
exit;
}
?>


Here's the bulk of editor.php if that helps (missing is only the end of my html design). Note: if some of the php doesn't make sense, I HAVE hacked bits out I don't want, and I've changed the <form> part a lot to make it XHTML valid and a cut down version..but the full a full clean install makes no difference to my error.



<?
if (!isset($_SERVER))
{
$_GET = &$HTTP_GET_VARS;
$_POST = &$HTTP_POST_VARS;
$_ENV = &$HTTP_ENV_VARS;
$_SERVER = &$HTTP_SERVER_VARS;
$_COOKIE = &$HTTP_COOKIE_VARS;
$_REQUEST = array_merge($_GET, $_POST, $_COOKIE);
}
$f = $_REQUEST['f'];
$t = $_REQUEST['t'];

//CONFIGURE HERE ================================================== ==================
if (!$password) $password= ""; //can leave password as "" if you are using .htaccess to protect abitwhizzy
if (!$whizzywig) $whizzywig = "whizzery/whizzywig.js"; //path to whizzywig.js required
if (!$cssFile) $cssFile= "css/editor.css"; //choose your stylesheet, or set to ""
if (!$buttonPath) $buttonPath = "whizzery/buttons/"; //toolbar images live here. "" for text buttons
if (!$imageBrowse) $imageBrowse = ""; // "" for no image browser
if (!$linkBrowse) $linkBrowse = ""; // "" for no link browser
if (!$toolbar) $toolbar = "bold italic underline left center right bullet number undo"; //try "all"
if (!$editarea) $editarea = "width:90%; height:250px";
if (!$xhtml) $xhtml = "editor/xhtml.js"; //path to xhtml converter
if (!$extensions) $extensions = "/(html)$/"; //file extensions
//HTML TEMPLATE: Use these 2 variables ($top and $tail) to wrap the generated HTML in your own template.
if (!$top) $top = "";
if (!$tail) $tail = "";
//END CONFIG ================================================== ======================
if (preg_match("#^\.|\.\.\/|^\/#",$f)) die ("Not allowed!");
if ($_REQUEST['save']) { //write page and go there
if ($_REQUEST['p'] != $password) die ("<h1>Wrong password: not saved.</h1>Click the Back button to try again. ");
$edited = $_REQUEST['edited'];
if ($f == "top.shtml" || $f == "tail.shtml") $html = stripslashes($edited);
else {
$html = $top."";
$html .= stripslashes($edited);
$html .= "".$tail;
}
$fsave = fopen($f, 'w'); //save the edited file
fwrite($fsave, $html);
fclose($fsave);
header("Location: editlinks.html");
} else if (file_exists($f)) {
$fedit = fopen($f, 'r'); //open the file for edit
$content = fread($fedit, filesize($f));
$start = strpos($content,"<!--#include virtual='top.shtml'-->") ? "/.*<!--#include virtual='top.shtml'-->/" : "|.*<body[^>]*>|iU";
$stop = strpos($content,"<!--#include virtual='tail.shtml'-->") ? "/<!--#include virtual='tail.shtml'-->.*/" : "|</body>.*$|iU";
$content = preg_replace($start,'',$content);
$content = preg_replace($stop,'',$content);
fclose($fedit);
preg_match('|<title>(.*)</title>|i',$content, $match);
$t = $match[1]; //grab the title
}?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="EN" />
<title>Page Editor</title>
<meta name="Robots" content="noindex, nofollow" /> <!-- leave -->
<link rel="shortcut icon" href="images/favicon.ico" type="image/x-icon" />
<meta name="description" content="Online content editor/word processor to change pages" />

<style type="text/css" media="all">
@import "css/non-ie.css";
</style>

<!--[if IE]>
<style type="text/css" media="all">
@import "css/ie.css";
</style>
<![endif]-->

<script type="text/javascript">

var language = new Array();
language['Color'] = "Colour";
language['Color name'] = "Colour name";
language['Hilite'] = "Highlight colour";

</script>

</head>

<body>

<!--Entire Page Wrapper Div Container -->
<div id="wrapper">

<!--Page content Div Container -->
<div id="content">

<!--header banners -->
<h1 id="pagetitle">PAGE TITLE</h1>
<p id="topnavigation">
| <a href="userguide.html" title="view help/user guide" accesskey="L" tabindex="1"> Help</a> |
</p>


<h2>EDIT PAGES </h2>

<div id="editor">
<script language="JavaScript" type="text/javascript" src="editor/editor.js"></script>
<script language="JavaScript" type="text/javascript" src="editor/xhtml.js"></script>

<form name="Whizzy" action="<? $_SERVER['SCRIPT_NAME']; ?>" method="post" onsubmit= "cleanUp();" >
<input type="submit" name="save" title="save changes" accesskey="S" id="save" value="Save" tabindex="2"/>
<input type="button" value="Cancel" id="cancel" title="cancel edit" tabindex="3" accesskey="X" onClick="document.location.href='editlinks.html';" />
<div id="edited" style="<?=$editarea;?>" >
<?=$content;?>
</div>
<script language="JavaScript" type="text/javascript">
buttonPath = "<?=$buttonPath;?>";
cssFile = "<?=$cssFile;?>"
imageBrowse = "<?=$imageBrowse;?>";
linkBrowse = "<?=$linkBrowse;?>";
makeWhizzyWig("edited", "<?=$toolbar;?>");
</script>
</form>
</div>


So, I still can't see what is getting sent to the browser BEFORE my session code, if I put that above the doctype. I really need this page under my login.

Thanks for any input :)

Basil
12-27-2007, 12:15 PM
You want to basically embed the editor in other pages right?

The simple solution would be like this..

<iframe src="abitwhizzy.php" frameborder=0 id="editor"></iframe>

and maybe style it like this..

<style type="text/css">
#editor {
border: 1px solid #000;
height: 500px;
width: 750px;
}
</style>

Alternatively, if you really want to include it, you can comment out the header line and add a meta refresh like this..
//header("Location: $f");
echo '<meta http-equiv="refresh" content="0;url='.$f.'">';

The reason the header doesn't work is because it's being included after a bunch of text is already sent to the browser (all the html before the include). However, it works on my local server despite that, so I don't know about bluehost's configuration.

junkybrewster
12-27-2007, 07:34 PM
Hi Basil,

You're a genius!

I wanted to keep the include if I could (I am suspicious of iframes hehe), so I reverted back to editor.html with the include call, restored my sessions in the page and then put the meta refresh in the .php file like you said. It works a treat. Brilliant. I'm going to read some more about header() to try understand.

I also didn't thank you for helping me about a week ago (I went away for christmas the next morning). Thank you for the MySQL help, too! (Bluehost DO use a different password function than my other provider.. so I ended up going with MD5).

Thanks so much!