Jim Westergren
About me, my projects, SEO, Web Development and Personal Development since 2005
"If we did all the things we are capable of, we would literally astound ourselves." - Thomas A. Edison

Challenge In Building a CMS: Different Hosting Setups

This is the first article in a serie about the Clesto CMS - my first PHP project (I am still a kind of noob, feedback appreciated).

There is a huge difference in building something for yourself and something that you release for a lot of people to download. The Clesto CMS has now been tested in many various shared hosting companies, many having their own custom setups. It did at first not work in some of them and had to be corrected. On the way of testing and correcting I learned a great deal which I will outline in this article as I think others might also have use for it.

PHP 4 versus PHP 5

Many hosts are still running PHP 4 and so you have to make sure that your script is working as intended. The PHP Manual usually have notices on functions in what PHP version it was introduced. For example instead of file_put_contents() the functions of fopen(), fwrite() and fclose() has to be used. Or just make your own such as this one simple:

<?php
function write_to_file($file, $text, $method) {
	$fh = fopen($file, $method);
	fwrite($fh, $text);
	fclose($fh);
}
?>

PHP able to write to files?

Around half of the cases yes and half no. My CMS is flat file based and would not work if it cannot write to files so this is crucial. And it would be really stupid to tell the user to CHMOD some directories to 777 if it is not needed.

So I came up with this:

<?php
if ($fh = @fopen("../createdfiles/test.txt", 'w')) {
	$test = "pass";
	unlink("../createdfiles/test.txt");
	fclose($fh);
} else {
    $test = "fail";
}
?>

Then I can just use the $test variable to know if I should display a notice or not.

A word of warning! Having directories with permissions of 777 can be a security risk. In my CMS I have many protections in place, more about that later.

Safe Mode on or off

Your script has to work in both. See the article Functions restricted/disabled by safe mode from PHP.net.

cURL function turned off

Certain hosts such as Hostgator has this turned off. The solution is to not depend on it and check if it exist with a simple if:

<?php
if(function_exists("curl_init")) {
	// Do the cURL stuff here
}
?>

Hosts that run PHP in CGI mode

Hostgator and the Swedish Binero does this for example. What this means is that any mention of php_flag or php_value in any .htaccess file will break the site completely and making all pages have an internal server error (500). This means that you cannot have things like php_flag display_errors off, php_flag register_globals off and php_flag magic_quotes_gpc off.

A solution for php_flag display_errors off (displaying errors on screen is a security risk) is to do it with PHP instead. My current set up looks like this:

<?php
error_reporting(E_ERROR | E_WARNING | E_PARSE);
ini_set("display_errors", "off");
ini_set("log_errors", "on");
ini_set("error_log", $path."createdfiles/error_log.txt");
?>

Hosts that have Magic Quotes (magic_quotes_gpc) ON

When on, all ' (single-quote), " (double quote), (backslash) and NULL characters are escaped with a backslash automatically. This is identical to what addslashes() does. (source)

As we now don't have a possibility of turning off Magic Quotes (see previous point) we just have to accept the possibility that it can be on. It will affect all GET, POST and COOKIE.

You can use this if:

<?php
if (get_magic_quotes_gpc()) {
	// Do stuff like stripslashes() here
}
?>

Apache mod_rewrite module

Contrary as it may seem there has not been a single incident of the Apache mod_rewrite module missing. All hosts had it installed and ready - so this is not an issue. But in any case it can be tested like this:

<?php
if (function_exists('apache_get_modules') ) {
	if(!in_array('mod_rewrite',apache_get_modules())) {
	    echo "Apache mod_rewrite module is missing";
	} 
}
?>

Foreign users

You will have users that write a foreign language with special characters. Those characters can be scrambled and it can be a pain in the ass trying to figure out what the problem is. The problem is a conflict with UTF-8 versus for example ISO-8859-1. I recommend using UTF-8 so make sure of the following:

  1. The physical files of your script is saved in the UTF-8 coding and not for example ANSI.
  2. You are sending the UTF-8 header on all pages of your script.
    header("Content-Type: text/html; charset=utf-8");
  3. You are displaying the Content Type meta tag with UTF-8:
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Installation in subfolder

If you are using mod_rewrite as I do then the RewriteBase is very important. If the user is installing in a sub folder the RewriteBase have to change in the .htaccess.

As for the moment I am during the installation checking the $_SERVER["SCRIPT_NAME"] to see if the user is installing in a sub folder and if so I display a message saying that RewriteBase / have to be changed to RewriteBase /currentfolder/.

I know it is not an optimal solution and I cannot even make a check that the user has done it but it works. If someone know a better method then please comment below.

The reason I don't want to make it dynamically is for security reasons. I even have the following in the root .htaccess:


## Protect all the .htaccess files
<Files .htaccess>
deny from all
</Files>

Feedback on this article is greatly appreciated.

11 Nov 2009

About the Author Jim Westergren Jim Westergren is a Swedish web entrepreneur currently living in Spain. He is happily married and has three lovely children. Some of his interests are web development, SEO and writing.
He is the Founder of DomainStats and N.nu. Read his .