Developer

Build Your Skills: Dynamic Web site configuration tutorial

Fine-tune options for PHP to help you get the most out of your Web site.


In the second Daily Drill Down of this series, I showed you how to install Apache, MySQL, PHP4, and some Apache modules to interface with PHP4 and Perl. I gave a very cursory glance at some configuration directives for Apache, primarily to get it to use the modules you installed.

In this Daily Drill Down, I’ll show you some specific fine-tuning options for these programs to help you get the most out of your applications.

PHP configuration: The php.ini file
The php.ini file provides system-wide configuration options for PHP4 (which we will refer to as just PHP from this point on). The default location for php.ini is in the /usr/local/lib directory; however, the location may differ depending on how you installed PHP. For instance, many RPM packages will place it in the /etc/httpd/conf directory, along with the rest of your Apache configuration files.

For the most part, the default directives should work fine. However, you may want to fine-tune a few options, just to make life a little easier. Let’s take a look at some of these options.

short_open_tag
The short_open_tag is the first directive you want to look at. The short_open_tag directive determines how to begin a block of code. Traditionally, you begin PHP code with the <’php symbol and close it with the ‘> symbol. This directive can be set to either Off, False, or No to keep the traditional method of starting PHP code segments. However, you can change this setting to On, True, or Yes for the short method, namely using <’ and ‘> to begin and end PHP code. To save a few keystrokes, set this directive to On by using the following:
short_open_tag = On

track_vars
Since you compiled PHP with the –-enable-track-vars configuration option, you want to enable this feature in the php.ini file, as well. This feature allows PHP to make certain variables available as a result of GET or POST requests in Web forms, or via cookies. The track_vars directive creates associative arrays that contain elements generated by an HTTP request. This means that GET variables are stored in the $HTTP_GET_VARS[] array, POST variables are stored in the $HTTP_POST_VARS[] array, and cookie variables are stored in the $HTTP_COOKIE_VARS[] array. Since this directive is invaluable to any Web designer, you want to enable it with the following:
track_vars = On

register_globals
Another similar directive you want to enable is the register_globals variable. This directive determines whether or not values resulting from an HTTP request should be made available as global variables. Since this is the easiest way of dealing with variables coming from a Web form or cookie, you should enable it by using:
register_globals = On

gpc_globals
You also want to set gpc_globals to On. Instead of accessing HTTP-generated variables through the $HTTP_GET_VARS[] array, you can access the variable directly. I’ll give an example for this one. Suppose you have a Web form with an entry item called name. The piece of HTML code might look like this:
<input type=”text” name=”name” size=”20" maxlength=”20">

Normally, you would need to retrieve the information via $HTTP_GET_VARS[‘name’]. In order to use a smaller variable name, you might reassign the value to another variable, like this:
$name = $HTTP_GET_VARS[‘name’];

By having gpc_globals enabled, you can skip this unnecessary step. You will be able to directly use the $name variable without reassigning it first. Since this makes life easier, you want to enable it like so:
gpc_globals = On

display_errors
Another option you’ll want to enable, especially if you’re new to PHP, is the display_errors directive. This directive determines whether or not PHP will display error messages to the Web browser if it comes across any syntax problems or other problems with your PHP code. You can enable this directive by using:
display_errors = On

error_reporting
You can also control how much information to generate on errors with the error_reporting directive. There are a few different classes of errors for which you can set error_reporting. The following are valid values for this directive:
  • E_ALL displays all error messages, regardless of the type of error.
  • E_ERROR displays only fatal error messages (like memory allocation problems).
  • E_WARNING displays non-fatal errors (like badly written function arguments).
  • E_PARSE displays parser errors, namely when the parser does not understand the syntax you’ve used.
  • E_NOTICE displays notices or potential problems (like uninitialized variables).
  • E_CORE_ERROR displays fatal startup errors.
  • E_CORE_WARNING displays non-fatal startup errors.

The error-reporting type that you use simply determines which error information is sent to the Web browser. It is used for nothing else. The nice thing about this directive is that you can combine or exclude specific directives depending upon your needs. For instance,
error_reporting = E_ERROR | E_PARSE

will display error messages and parser error messages. By using the pipe (|) symbol, you can tell the directive to use one error-reporting type and another error-reporting type. If you wanted to display all errors except for warning messages, you could do it using:
error_reporting = E_ALL & ~E_WARNING

This will display all error messages except for warning messages. You can provide many different combinations of error reporting by using binary arithmetic (which we won’t get into here). Suffice to say, a value of:
error_reporting = E_ERROR | E_WARNING | E_PARSE

is probably good enough for your needs. If you need to change this value for one specific page you may be debugging, you can use the error_reporting() function in the PHP code itself. That function uses the same values as the error_reporting directive.

Syntax highlighting
Another nice directive to enable is the ability to view PHP source code with syntax highlighting. This will make debugging PHP code much easier. The first thing you need to do is add the following line to your httpd.conf file so that Apache has something to associate PHP source files with.
AddType application/x-httpd-php-source .phps

Before this change will take effect, you must restart Apache. Then, you must edit your php.ini file and add the following directives:
highlight.string = Red
highlight.comment = Cyan
highlight.keyword = Magenta
highlight.default = Blue
highlight.html = Black


The colors you select for any of these directives can be a word or HTML color code. Basically, anything that will work in the HTML <font color=???> code will work here. The above directives are used to break up the displayed PHP source code into sections. The highlight.string directive displays quotation marks and quoted text. The highlight.comment directive displays comments in the PHP code. The highlight.keyword directive highlights many of the built-in functions, operators, and language constructs. The highlight.default directive highlights all other PHP code. Finally, the highlight.html directive indicates which color to use when displaying regular HTML code.

That should be enough to get you going with your PHP configuration. We’ve spent quite a bit of time fine-tuning PHP, which is important. Although you’re also using other tools to create and maintain your dynamic Web site, PHP will be one of the most important aspects of your site. Because it is such a powerful tool, you will find it much easier to learn and use than Perl, which will likely mean that you’ll use PHP on your site far more than you’ll use Perl. In addition, Perl doesn’t require the same initial configuration as PHP does. Beyond using Perl modules, there is no global way to configure Perl.

Apache is also very simple to maintain. It is well configured out of the box, and doesn’t require very much fine-tuning other than the little I described earlier in this and the previous part of this series.

One more note on PHP configuration that doesn’t involve the php.ini file directly: There’s a handy function in PHP called phpinfo() that will display configuration information for your server. It will show you the properties of your PHP configuration on the Web site and is useful not only for debugging, but also to see what options you have enabled, without requiring you to dig into the php.ini file.

Create the back-end site
Let’s write a second PHP page that will use the phpinfo() function exclusively. Fire up your favorite text editor and create a file called phpinfo.php with the following contents:
<html>
<body>
<’ phpinfo(); ‘>
</body>
</html>


Save the file in a directory that you will be using for administration. For the sake of example, let’s put it in the /home/httpd/html/admin directory. You’ll make this your administrator’s back-end directory. I’ll show you how to secure it in a moment.

Now if you go to www.yourdomain.com/admin/phpinfo.php or localhost/admin/phpinfo.php, you will see the output of the phpinfo() function. This will give you an abundance of information on your current PHP configuration.

Next, let’s create another page that we can use to view the source code for any file with colored syntax highlighting. Fire up your favorite editor and create a file called phpview.php, which we will also save in our administrator’s directory. The contents of phpview.php should be
<html>
<head>
<title>View PHP Source Files</title>
</head>
<body>
<form method=”GET” action=”phpview.php”>
Enter local file name:
<input type=”text” name=”file” value=”<’ echo $file; ‘>”>
<input type=”Submit” value=”View it!”>
</form>
<br /><hr /><br />
<’
if ($file) {
  show_source($file);
}
‘>
</body>
</html>


Now, if you go to localhost/admin/phpview.php, you’ll see a page that prompts you for a local filename. If you enter the name phpview.php, you’ll see the source code displayed with color syntax highlighting.

Securing Web pages
Since the nice thing about PHP is the fact that it parses the PHP code locally and then sends the resulting page to the remote Web browser, you don’t want your phpview.php file to be accessible by just anyone. When PHP sends the page to the browser, all of the PHP code is interpreted and removed from the output. This means that the remote user, even if they run a View Source command on the page, will never see the PHP code. This is a definite asset to Web programmers who may not want to share their source code with others, or better yet, embed passwords for accessing MySQL databases in PHP source code. The last thing you want is for a remote user to see the username and/or password used to connect to your MySQL server.

Because PHP does remove the actual PHP code before serving the page, you’re relatively safe from prying eyes. However, with your phpview.php page, you’ve just opened up another hole. If someone found the location to your administrator’s back-end directory without it being secured, all of your source code would be available to anyone who wanted to look at it.

Because of this, use Apache’s .htaccess method of securing pages. Using .htaccess will allow you to restrict who gets to load the pages in your administrator’s back-end directory. One quick note on .htaccess, however: This method of securing Web pages is not supported by Internet Explorer (go figure). Because I always used IE exclusively on my Windows computer, I was never able to view my own secured pages. I had to install Netscape Communicator in order to view those pages. I don’t think IE can handle the password authentication that Apache uses, which is odd.

Okay. Change to your /home/httpd/html/admin directory. Now, create a new file called .htaccess in this directory and have it consist of the following:
AuthUserFile /etc/.htpasswd
AuthGroupFile /dev/null
AuthName joe
AuthType basic


<Files phpinfo.php>
Order Deny,Allow
Deny From All
Allow From localhost
Require user joe
Satisfy any
</Files>


<Files phpview.php>
Order Deny,Allow
Deny From All
Allow From localhost
Require user joe
Satisfy any
</Files>


Let’s examine what you’ve done here. You’ve defined your user password file to be /etc/.htpasswd. This contains the encrypted password for the users you define. You’ve decided not to use groups, so your AuthGroupFile is the magical device /dev/null. You’ve authorized the user joe in this instance, so this username will have to appear in our AuthUserFile (more about that in a moment). Finally, you’ve defined the authorization type to be Basic.

The next thing you’ve done is secure the file phpinfo.php in the current directory. The way the page’s authorization is granted is to deny before allowing, so then you explicitly tell Apache to deny everyone. Then, begin to grant access to the page, first to connections from localhost and then from the user joe specifically. Next, tell Apache that any of the requirements can be matched, meaning that joe can connect from anywhere, not just from localhost. Finally, do the same thing for phpview.php so that it is also secured.

There are more directives that you can use in the .htaccess file. The directives used above are the basics necessary to secure the page, but you can make the access rules as elaborate as you need to. For more information on .htaccess, take a look at the Apache manual or any book that discusses Apache.

Creating the password database
The next thing you need to do prior to making this page usable by joe or any other user is to create the AuthUserFile. This is the password database that stores usernames and encrypted password pairs. The default filename is .htpasswd, but you can use any name you like. You can also have more than one such file if you want separate password files for different Web sites and so forth.

To initialize the password database, run the program htpasswd like this:
htpasswd -c /etc/.htpasswd joe

This command tells htpasswd to create a new password database in the file /etc/.htpasswd with a user entry for joe. When this command is run, htpasswd will prompt you for a password for the user joe and, once it is entered, prompt you again to verify that it is correct.

Now, give it a try. Visit www.yourdomain.com/admin/phpinfo.php. You should be asked for a username and password before the browser displays anything on the page. Enter the username you used in your .htaccess file and with the htpasswd program (the example user joe), and enter the password you supplied. The page should now load.

If you were to enter an incorrect password or username, the browser would ask you again for the proper username and password. After three incorrect attempts, the browser would inform you that you did not have access permission to the page.

The only thing to keep in mind is that you should explicitly secure every page you want secured. If you add another page to the admin directory in the future (and we will in a later part of this series), you’ll need to add the page to your .htaccess file in order to secure it. Securing sensitive administration pages is an excellent idea since the last thing you want is other people tampering with your site.

In a future installment of this series, you will also learn how to use PHP to provide user authentication. While .htaccess is an excellent method to secure pages, using it in conjunction with a PHP-based authentication system will provide you with extra security and flexibility.

Conclusion
In this third part of my series of Daily Drill Downs, we learned how to fine-tune PHP and we also looked at a few simple PHP Web pages to help us keep an eye on our system. This is important for any Web programmer because it offers you a little more flexibility and makes administering the system easier as well. We also learned how to secure important pages, which is essential information for any Web administrator.

In the next part of this series of Daily Drill Downs, we will begin designing our first interactive Web page. I’ll illustrate how to use MySQL to create a new database and provide the code you’ll need in order to access that information. Then, in another installment, we’ll look at balancing dynamic pages by creating one page to view information and another to administer the contents of the database that page displays.

Vincent Danen, a native Canadian in Edmonton, Alberta, has been computing since the age of 10, and he’s been using Linux for nearly two years. Prior to that, he used OS/2 exclusively for approximately four years. Vincent is a firm believer in the philosophy behind the Linux "revolution,” and heattempts to contribute to the Linux causein as many ways as possible—from his FreezerBurn Web site to building and submitting custom RPMs for the Linux Mandrake project. Vincent also has obtained his Linux Administrator certification from Brainbench .He hopes to tackle the RHCE once it can be taken in Canada.

The authors and editors have taken care in preparation of the content contained herein, but make no expressed or implied warranty of any kind and assume no responsibility for errors or omissions. No liability is assumed for any damages. Always have a verified backup before making any changes.

About

Vincent Danen works on the Red Hat Security Response Team and lives in Canada. He has been writing about and developing on Linux for over 10 years and is a veteran Mac user.

Editor's Picks