Forum Moderators: coopster
I just want to get the script working. Here is the original I started from with a simply copy and past...
Original Working Script
<?
if ($_POST) {
// submit changes
$file = fopen($uploaddir . 'efb.txt', 'w', 1);
fwrite($file, $_POST['textarea']);
fclose($file);
?>
<b><font color="#FF0000">The changes have been saved and will show as follows.</font></b>
<textarea name="textarea2" cols="91" rows="50"><? include("efb.txt");?></textarea>
<?
} else {
// display text and wait for changes
?>
<form name="efb" method="post" action="?ac=efb">
<textarea name="textarea" cols="91" rows="50"><? include("efb.txt");?></textarea>
<br><input type="submit" name="Submit" value="Submit"></form>
<?
}
?>
I wanted to use this so I can click on an edit anchor on any page and the template editing page would detect the referer and let me edit that page. (The edit anchor would require being logged in as an admin in example.) Here are a couple pages I used for test purposes only.
test1.html
<h1>test page 1</h1>
<span>Page 1</span>
<br />
<a href="test2.html">Page 2</a>
<br />
<a href="edit2.php">edit this page</a>
test2.html
<h1>test page 2</h1>
<a href="test1.html">Page 1</a>
<br />
<span>Page 2</span>
<br />
<a href="edit2.php">edit this page</a>
Ok the last part is the script I modified and the errors I encountered. First the errors...
failed to open stream: HTTP wrapper does not support writeable connections. in edit.php on line 6
Warning: fwrite(): supplied argument is not a valid stream resource on line 7
Warning: fclose(): supplied argument is not a valid stream resource on line 8
Keep in mind I've only modified the script so it's not a problem with my local Apache install. Here is the modified script that I'm trying to learn off of.
Current Not-Working Script
<?php
$template = $_SERVER['HTTP_REFERER'];if ($_POST) {
// submit changes
$file = fopen($uploaddir . $template, 'w', 1);
fwrite($file, $_POST['textarea']);
fclose($file);
?>
<span style="#f00">The changes have been saved and will show as follows.</span>
<form>
<textarea name="textarea2" cols="64" rows="16"><?php readfile($_SERVER['HTTP_REFERER']);?></textarea>
</form><?
} else {
// display text and wait for changes
?>
<form name="efb" method="post" action="?ac=efb">
<textarea name="textarea" cols="64" rows="16"><?php readfile($_SERVER['HTTP_REFERER']);?></textarea>
<br><input type="submit" name="Submit" value="Submit"></form>
<?
}
?>
Remember I don't care about security at this moment as I'm trying to learn by cutting down the pieces to as small as I can get them. It's makes things more modular anyway to boot. I want to talk about security but not before the script doesn't even work! Anyway I should have posted here first.
- John
$template = [url=http://us2.php.net/manual/en/function.basename.php]basename[/url]($_SERVER['HTTP_REFERER']);
$template = basename($_SERVER['HTTP_REFERER']);
echo $uploaddir.$template;
You may have forgotten the slash:
$uploaddir = '/templates/';
I don't see any other reason why it wouldn't work....unless you don't have the referrer set, which you should be checking for ;)
if(!isset($_SERVER['HTTP_REFERER'])) {
echo 'No referrer set!';
exit;
}
If the referer looks like "file.php" it worked just fine. However if there is any path like "http://localhost/..." it does not work.
How could I strip $_SERVER['HTTP_REFERER']; so...
[localhost...]
changes to...
test1.html
...as the referer? I think that would do the trick for now at least on the basic level. Thanks!
- John
$template = basename($_SERVER['HTTP_REFERER']);
If the referrer looked like this (which it IS in this format):
http://localhost/test.html
Then using basename would give the following output:
test.html
Edit: some how this script is only able to write to itself?
1.) When I did have the pages saving themselves PHP would add double quotes. That plus somehow the edit page would sometimes overwrite itself! Here is that version of the script with your referer modification...
<?php
$template = basename($_SERVER['HTTP_REFERER']);echo 'The referer page is: <b>' . $template .'</b> <br />';
if ($_POST) {
// submit changes
$file = fopen($uploaddir . $template, 'w', 1);
fwrite($file, $_POST['textarea']);
fclose($file);
?>
<span style="#f00">The changes have been saved and will show as follows.</span>
<form>
<textarea name="textarea2" cols="64" rows="16"><?php readfile($_SERVER['HTTP_REFERER']);?></textarea>
</form><?
} else {
// display text and wait for changes
?>
<form method="post" action="edit.php">
<textarea name="textarea" cols="64" rows="16"><?php readfile($_SERVER['HTTP_REFERER']);?></textarea>
<br><input type="submit" name="Submit" value="Submit"></form>
<?
}
?>
<br />
<a href="test1.html">Page 1</a>
<br />
<a href="test2.html">Page 2</a>
After that I attempted to stop the editor from overwriting itself. I am guessing this is because the edit page was becoming it's own referer! What I'm trying to do now is figure out how to have the edit page not display the form but only the output in plain text (and not rendered)...I'm guessing I should use a pre element.
Also I'm looking to to potentially using this in a live environment if I can get it to work securely. The only step before securing the script would be my intent to edit templates for content instead of entire PHP files. I can keep the template files in the same directory as the PHP files and they would have the same names only a different extension (*.tpl in example).
Lastly I would want to get in to authentication and setup at least some form with registration, account type (normal/admin/etc), and store password. I'm also looking to add other basic values but thats getting way ahead of myself here.
Right now I want to work on keeping the edit page from editing itself (which I'll be attempting to do on my own though suggestions welcome). I also want to take the referer and change it's extension so the editor only edits the template and not the entire page with other PHP information. Lastly I really need to figure out how to get rid of those double quotes which is most important since all my own is done as application/xhtml+xml. Thanks for your help!
Oh a last minute thought...is there a way to make PHP unable to write to the edit page itself?
- John
[edited by: JAB_Creations at 6:24 pm (utc) on Mar. 5, 2007]
<?php
if(!isset($_SERVER['HTTP_REFERER'])) {
echo 'No referrer set!';
exit;
}
$dir = "path/to/the/files/";
if (isset($_POST)) {
// submit changes
$template = $_POST['template'];
$file = fopen($dir . $template, 'w', 1);
fwrite($file, $_POST['textarea']);
fclose($file);
?>
<span style="#f00">The changes have been saved and will show as follows.</span>
<form>
<textarea name="textarea2" cols="64" rows="16"><?php readfile($dir.$template);?></textarea>
</form>
<?
} else {
$template = basename($_SERVER['HTTP_REFERER']);
if($template == "edit.php") exit; //checks to see if referrer is itself
?>
<form method="post" action="edit.php">
<textarea name="textarea" cols="64" rows="16"><?php readfile($dir.$template);?></textarea>
<input type="hidden" name="template" value="<?php echo $template;?>" />
<br><input type="submit" name="Submit" value="Submit"></form>
<?
}
?>
<br />
<a href="test1.html">Page 1</a>
<br />
<a href="test2.html">Page 2</a>
Warning: fclose(): supplied argument is not a valid stream resource in edit.php on line 13
Also I'm getting the "your changes have been made" when I simply click on a referer page's link so I'm not seeing the input. I'm off to work for a few hours and I'll be back to continue working on the script. Thanks for your continued help!
- John
Edited to remove unintended smiley.
[edited by: JAB_Creations at 8:33 pm (utc) on Mar. 5, 2007]
<?php
if(!isset($_SERVER['HTTP_REFERER'])) {
echo 'No referrer set!';
exit;
}
if (isset($_POST['template']) && isset($_POST['textarea'])) {
$template = $_POST['template'];
$file = fopen($template, 'w');
fwrite($file, $_POST['textarea']);
fclose($file);
?>
<span style="#f00">The changes have been saved and will show as follows.</span>
<form>
<textarea name="textarea2" cols="64" rows="16" disabled="disabled"><?php readfile($template);?></textarea>
</form>
<?php
} else {
$template = basename($_SERVER['HTTP_REFERER']);
?>
<form method="post" action="index.php">
<textarea name="textarea" cols="64" rows="16"><?php readfile($template);?></textarea>
<input type="hidden" name="template" value="<?php echo $template;?>" />
<br><input type="submit" name="Submit" value="Submit"></form>
<?php
}
?>
When you get back from work try it out and see what happens :)
Good luck
I've modded the script a little, here it is...
Thanks for getting it to work!
- John
<?php
$template = basename($_SERVER['HTTP_REFERER']);if(isset($_SERVER['HTTP_REFERER'])) {
echo 'The referer page is: <b>' . $template .'</b> <br />';
}
else if(!isset($_SERVER['HTTP_REFERER'])) {
echo 'No referrer set!';
echo '<br />php dies';
die();
}if (isset($_POST['template']) && isset($_POST['textarea'])) {
$template = $_POST['template'];
$file = fopen($template, 'w');
fwrite($file, $_POST['textarea']);
fclose($file);
?>
<span style="#f00">The changes have been saved and will show as follows.</span>
<form>
<textarea name="textarea2" cols="64" rows="16" disabled="disabled"><?php readfile($template);?></textarea>
</form><?php
} else {
$template = basename($_SERVER['HTTP_REFERER']);
if(isset($_SERVER['HTTP_REFERER'])) {
echo 'The referer page is: <b>' . $template .'</b> <br />';
}?>
<form method="post" action="<?php echo 'edit.php';?>">
<textarea name="textarea" cols="64" rows="16"><?php readfile($template);?></textarea>
<input type="hidden" name="template" value="<?php echo $template;?>" />
<br><input type="submit" name="Submit" value="Submit"></form>
<?php
}
?>
if (get_magic_quotes_gpc()) {fwrite ($file, stripslashes($_POST['textarea']));}
The full working script...
<?php
$template = basename($_SERVER['HTTP_REFERER']);if(isset($_SERVER['HTTP_REFERER'])) {
echo 'The referer page is: <b>' . $template .'</b> <br />';
}
else if(!isset($_SERVER['HTTP_REFERER'])) {
echo 'No referrer set!';
echo '<br />php dies';
die();
}if (isset($_POST['template']) && isset($_POST['textarea'])) {
$template = $_POST['template'];
$file = fopen($template, 'w');
if (get_magic_quotes_gpc()) {fwrite ($file, stripslashes($_POST['textarea']));}
else fwrite($file, $_POST['textarea']);
fclose($file);
?>
<span style="#f00">The changes have been saved and will show as follows.</span>
<form>
<textarea name="textarea2" cols="64" rows="16" disabled="disabled"><?php readfile($template);?></textarea>
</form><?php
} else {
$template = basename($_SERVER['HTTP_REFERER']);
if(isset($_SERVER['HTTP_REFERER'])) {
echo 'The referer page is: <b>' . $template .'</b> <br />';
}?>
<form method="post" action="<?php echo 'edit.php';?>">
<textarea name="textarea" cols="64" rows="16"><?php readfile($template);?></textarea>
<input type="hidden" name="template" value="<?php echo $template;?>" />
<br><input type="submit" name="Submit" value="Submit"></form>
<?php
}
?>
I'll be figuring out registration, MySQL, and authentication to of course make this more secure. That means I'll need to figure out types of users as well.
- John
page1.php --> edit.php --> page1.tpl
So I click the edit anchor on page1.php which lets me edit the included template which is opened and saved from page1.tpl.
So page1.php includes all the PHP. The page1.tpl contains the HTML content in the creamy middle. The user clicks page1.php but the str_replace function changes the referer url's file extension! Here is the modified working code (just in case I misplace it.) ;)
- John
<?php
$template = basename($_SERVER['HTTP_REFERER']);
$file = str_replace('.php','.tpl',$template);echo '<span style="color: #0ff;">' . $file . '</span><br />';
if(isset($_SERVER['HTTP_REFERER'])) {
echo 'The referer page is: <b>' . $file .'</b> <br />';
}
else if(!isset($_SERVER['HTTP_REFERER'])) {
echo 'No referrer set!';
echo '<br />php dies';
die();
}if (isset($_POST['template']) && isset($_POST['textarea'])) {
$file = $_POST['template'];
$file = fopen($file, 'w');
if (get_magic_quotes_gpc()) {fwrite ($file, stripslashes($_POST['textarea']));}
else fwrite($file, $_POST['textarea']);
fclose($file);
?>
<span style="#f00">The changes have been saved and will show as follows.</span>
<form>
<textarea name="textarea2" cols="64" rows="16" disabled="disabled"><?php readfile($file);?></textarea>
</form><?php
} else {
$template = basename($_SERVER['HTTP_REFERER']);
$file = str_replace('.php','.tpl',$template);if(isset($_SERVER['HTTP_REFERER'])) {
echo 'The referer page is: <b>' . $file .'</b> <br />';
}?>
<form method="post" action="<?php echo 'edit.php';?>">
<textarea name="textarea" cols="64" rows="16"><?php readfile($file);?></textarea>
<input type="hidden" name="template" value="<?php echo $file;?>" />
<br><input type="submit" name="Submit" value="Submit"></form>
<?php
}
?>
$self = basename($_SERVER['PHP_SELF']);
if ($self == $template) {echo 'Can not edit editing page!'; die();}
Will protect the script from itself in the very least. Here is the full script...
- John
<?php
$template = basename($_SERVER['HTTP_REFERER']);
$file = str_replace('.php','.tpl',$template);echo basename($_SERVER['PHP_SELF']) . '<br />';
echo '<span style="color: #0ff;">' . $file . '</span><br />';if(isset($_SERVER['HTTP_REFERER'])) {
echo 'The referer page is: <b>' . $file .'</b> <br />';
}
else if(!isset($_SERVER['HTTP_REFERER'])) {
echo 'No referrer set!';
echo '<br />php dies';
die();
}if (isset($_POST['template']) && isset($_POST['textarea'])) {
$file = $_POST['template'];
$file = fopen($file, 'w');
if (get_magic_quotes_gpc()) {fwrite ($file, stripslashes($_POST['textarea']));}
else fwrite($file, $_POST['textarea']);
fclose($file);
?>
<span style="#f00">The changes have been saved and will show as follows.</span>
<form>
<textarea name="textarea2" cols="64" rows="16" disabled="disabled"><?php readfile($file);?></textarea>
</form><?php
} else {
$template = basename($_SERVER['HTTP_REFERER']);
$self = basename($_SERVER['PHP_SELF']);
if ($self == $template) {echo 'Can not edit editing page!'; die();}
$file = str_replace('.php','.tpl',$template);if(isset($_SERVER['HTTP_REFERER'])) {
echo 'The referer page is: <b>' . $file .'</b> <br />';
}?>
<form method="post" action="<?php echo 'edit.php';?>">
<textarea name="textarea" cols="64" rows="16"><?php readfile($file);?></textarea>
<input type="hidden" name="template" value="<?php echo $file;?>" />
<br><input type="submit" name="Submit" value="Submit"></form>
<?php
}
?>
<a href="edit.php">edit edit page</a>
With the edit page's protection against editing itself while the file still saves the "this is what you submitted textarea" spits out...
<b>Warning</b>: readfile() expects parameter 1 to be string, resource given in edit.php on line 36
This is after changing the beginning to this...
<?php $template = basename($_SERVER['HTTP_REFERER']);
$self = basename($_SERVER['PHP_SELF']);
if (!$_POST['Submit'])
{
if ($self == $template) {header('HTTP/1.0 405'); echo 'Error 405: Can not edit editing page!'; die();}
}
Line 36
<textarea name="textarea2" cols="64" rows="16" disabled="disabled"><?php readfile($file);?></textarea>
Everything works except I get that error! Gah...I was on a roll to!
- John
First a couple test case files...
main1.php
<?php echo '<?xml version="1.0" encoding="UTF-8"?>';?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Main 1</title>
<link href="style.css" media="screen" rel="stylesheet" title="default" type="text/css" />
<!-- saved from url=(0014)about:internet -->
</head><body>
<?php include("main1.tpl");?>
</body>
</html>
main2.php
<?php echo '<?xml version="1.0" encoding="UTF-8"?>';?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Main 2</title>
<link href="style.css" media="screen" rel="stylesheet" title="default" type="text/css" />
<!-- saved from url=(0014)about:internet -->
</head><body>
<?php include("main2.tpl");?>
</body>
</html>
Next their included template files...
main1.tpl
<h1>Main page 1</h1>
<span>Page 1</span>
<br />
<a href="main2.php">Page 2</a>
<br />
<a href="edit.php">edit this page</a>
main2.tpl
<h1>Main page 2</h1>
<a href="main1.php">Page 1</a>
<br />
<span>Page 2</span>
<br />
<a href="edit.php">edit this page</a>
edit.php
<?php
$referer = basename($_SERVER['HTTP_REFERER']);
$template = str_replace('.php','.tpl',$referer);if(isset($_SERVER['HTTP_REFERER'])) {
echo 'The referer page is: <b>' . $referer .'</b> and it\'s template page is <b>' . $template . '</b> <br />';}
else if(!isset($_SERVER['HTTP_REFERER'])) {
echo 'No referrer set!';
echo '<br />php dies';
die();
}if (isset($_POST['referer']) && isset($_POST['textarea'])) {
$template = $_POST['referer'];
$file = fopen($template, 'w');
if (get_magic_quotes_gpc()) {fwrite ($file, stripslashes($_POST['textarea']));}
else fwrite($file, $_POST['textarea']);
fclose($file);
?>
<span style="color: #f00;">The changes have been saved and will show as follows.</span>
<form>
<textarea name="textarea2" cols="64" rows="16" disabled="disabled"><?php readfile($template);?></textarea>
</form><?php
} else {
$referer = basename($_SERVER['HTTP_REFERER']);
$template = str_replace('.php','.tpl',$referer);?>
<form method="post" action="<?php echo 'edit.php';?>">
<textarea name="textarea" cols="64" rows="16"><?php readfile($template);?></textarea>
<input type="hidden" name="referer" value="<?php echo $template;?>" />
<br><input type="submit" name="Submit" value="Submit"></form>
<?php
}
?>
That is my entire test case at the moment. I've changed a couple of the variables which I think were creating conflicts so all the code in this post works perfectly! I can now concentrate on protecting the edit file from overwriting itself!
I changed $template to $referer and $file to $template because there was already a $file variable.
$referer = referer page.
$template = refer page with template extension instead of original extension.
Now I'm going to try and reintroduce the self-protection code which I don't think will be as difficult this time around! :)
PS - Thanks for sticking around while I become engulfed in my first moderately complex PHP script! :)
PS2 - dreamcatcher, thanks for your post, though I realized I screwed up the variables. Ops!
- John
[edited by: JAB_Creations at 6:37 pm (utc) on Mar. 6, 2007]
I ran in to another problem which I fixed rather quickly!
I test using XAMPP locally but I wanted to see what would happen when I tested the script on my live server. Turns out it couldn't write to the file!
All I had to do was change the permissions on edit.php and it worked. I changed it from 644 to 646 which means I gave it public write permissions. A security issue of course unless I have authentication in place in order to access it though I've deleted the files immediately after until I'm able to implement obvious security choke points.
Now that it works in the necessary environments I'll try to add the self-protecting code and then on to authentication for the first time!
- John
<?php
$referer = basename($_SERVER['HTTP_REFERER']);
$template = str_replace('.php','.tpl',$referer);if (isset($_POST['referer']) && isset($_POST['textarea'])) {
if(isset($_SERVER['HTTP_REFERER'])) {
echo 'The referer page is: <b>' . $referer .'</b> and it\'s template page is <b>' . $template . '</b> <br />';}
else if(!isset($_SERVER['HTTP_REFERER'])) {
echo 'No referrer set!';
echo '<br />php dies';
die();
}$template = $_POST['referer'];
$file = fopen($template, 'w');
if (get_magic_quotes_gpc()) {fwrite ($file, stripslashes($_POST['textarea']));}
else fwrite($file, $_POST['textarea']);
fclose($file);
?>
<span style="color: #f00;">The changes have been saved and will show as follows.</span>
<form>
<textarea name="textarea2" cols="64" rows="16" disabled="disabled"><?php readfile($template);?></textarea>
</form><?php
} else {
$referer = basename($_SERVER['HTTP_REFERER']);
$template = str_replace('.php','.tpl',$referer);$self = basename($_SERVER['PHP_SELF']);
if ($self == $template) {echo 'Can not edit editing page!'; die();}?>
<form method="post" action="<?php echo 'edit.php';?>">
<textarea name="textarea" cols="64" rows="16"><?php readfile($template);?></textarea>
<input type="hidden" name="referer" value="<?php echo $template;?>" />
<br><input type="submit" name="Submit" value="Submit"></form>
<?php
}
?>
I moved a chunk of code to only execute when the file is posted to. Then I copied my earlier code. It still writes to all refers, I get no errors, and hitting the go button when viewing edit.php triggers a self-referer and the script kills itself before the person using the editor can do any harm.
When I get the authentication system working I'll have it require being logged in and as an admin (type). Any other security suggestions are welcomed at this point now that it's actually working! :)
- John
You might want to check to see if the referrer exists before you set
$referer:
if(!isset($_SERVER['HTTP_REFERER'])) {
echo 'No referrer set!';
echo '<br />php dies';
die();
}
$referer = basename($_SERVER['HTTP_REFERER']);
$template = str_replace('.php','.tpl',$referer);
echo 'The referer page is: <b>' . $referer .'</b> and it\'s template page is <b>' . $template . '</b> <br />';
#etc...
Otherwise, nice job :)