Picture of Chad
Let's face it, web pages aren't designed for interaction with users. At one time or another, you've probably found yourself needing to know what user you are dealing with, and some information about that user. But how do you do it on the web? There are many ways, but most of them are either error prone, or serious security risks. Passing around form data from page to page can easily be sniffed, and even more easily forged. What is a webmaster to do?
The simple answer is PHPLIB. PHPLIB is a set of PHP classes that are designed to make is easier to develop web based applications - things that need interaction. This is provided by many classes, the most essential being authentication, session management, permissions, and database abstraction.

What You'll Need

To use phplib, you need php installed on your server. Unlike basic authentication, phplib works with either the cgi or the module. You will probably need at least version 3.0.5 of php. Earlier cgi versions may work if you compiled them with --enable-foce-cgi-redirect option. Otherwise, you will get nothing but security errors. PHP also needs to be configured with track_vars enabled. You will also need a database. PHPLIB currently supports MySQL, Orace, ODBC, PostgreSQL, and Sybase.

How it Works

First and foremost, the classes need to be configured for your system. The only file that has to be modified is the local.inc file included in the distribution. It is filled in with a sample setup which can be used almost as is, or can be modified as you want. Before setting it up though, it's a good idea to understand what is going on.
Each page that uses PHPLIB must first import all of the needed files. You can do this with php's auto_prepend feature if you have access to your php.ini and you want the files included on EVERY page. If not, you can specify an include directory in the php.ini, or just use the absolute path to require the PHPLIB files. A sample file called prepend.php3 is included in the distribution, which can be required at the top of each file to include all of the other needed files.
At the top of each phplib page, you must make a call to the page_open function. This initializes the features that you plan on using, more on this later. A typical page_open call that gives authentication, session, and permission capabilities looks like:

<?php

page_open
(array("sess" => "Cms_Session""auth" => "Cms_Auth""perm" => "Cms_Perm"));

?>
The keys of the array (sess, auth, perm) are the variable names you will use to address the objects, and must be the standard variable names phplib uses (sess, auth, perm...). The values are the names of the classes you create in your local.inc. The page_open call must be before any output to the browser, and you only need to put in the features that you are going to use (if you're not using authentication on the page, just leave that part out). The script must end with a call to the page_close() function, which writes all changes back to the database. If you forget the page_close() call, you may find some things not working quite as expected...
Because phplib uses cookies to store information, your page_open() call must be issued before ANY output is sent to the browser. Output can be anything from html to blank lines. If you find yourself getting errors which say something along the lines of "Oops - SetCookie called after header has been sent" this means that there was some output before the page_open was called. The typical culprits, and the hardest to find, are blank lines outside of the <? and ?> tags in the included files. Check your local.inc or prepend.php3 for blank lines at the end with vi, or another editor which will show you these.
Now let's take a look at what the features do.

Authentication

PHP uses an authentication mechanism that is more flexible than basic authentication, as well as being reasonably secure. Here's how it works. At the top of your protected page, you have a page_open call which contains the statement "auth" => "auth_class" where auth_class is the name of your authentication class. The page_open function evaluates this, and initializes the authentication component. Authentication first checks to see if the user is already authenticated.

Let's assume that our user just arrived, and is not yet authenticated. PHPLIB will present the user with a login form (no popup windows!!!), which you may design yourself or use the included one. The user enters their username and password, and clicks submit. Simple, eh? What goes on behind the scenes is a bit more complicated...

If the user does not have a JavaScript capable browser, then authentication works much like you would suspect. The username and password are sent to the server, and compared against the values stored in the database. If the user does have a JavaScript capable browser, it's a bit different. PHPLIB will put a string in the form called a "challenge". When the user submits the form, their username, password, and the challenge are encrypted using an md5 encryption algorithm. The only thing that is passed back to the server is the username, and this encrypted hash (password is NOT transmitted). The server then takes the same challenge string, the username submitted, and the password associated with that username in the database. These values are also encrypted with md5. The two encrypted strings are then compared. If they match, the user submitted the correct password, and is allowed to proceed. So, the user is authenticated with the password never having been transmitted, so it cannot be sniffed. Very slick.

Session Management

Authentication ties in very closely with session management. Once the user is authenticated, their session begins. If the user has a browser that supports cookies, a session id is created by making an md5 hash of a php uniquid (a random id based on system time) and an arbitrary string. The cookie is a session cookie, meaning that it is never written to the user's hard disk, and it is removed once the session ends. If they do not support cookies, the same session id is stored as a get parameter in the URL.The md5 hash is done so that the session id is random, and it is not possible to guess one session id based on knowledge of another one. The session id is used to store information about the user in the system. This information can include if the user is authenticated, when their authentication exprires (Yep, you can do expiration!), what permissions they have (coming later), and any other information you want.

Aside: PHP and Object Oriented Programming

PHPLIB uses PHP's OOP feature extensively. This may be the first time you've seen it in use, so it's going to help a lot if you have an idea of what it all means. The first step is to not really think of it as object oriented. Rather, it's a way to group together data and functions for convenient access. It does not follow many OO conventions, and it is not truly object oriented. With that said, let's look at the database class to see what it means.
<?php $db = new MyDBClass?>
This line creates a new database object. Think of it as initializing all the functions in MyDBClass so that you can use them. $db is then a link to this database object. In a real OO language, creating this object would simply allocate memory for the data and functions. With PHP, what it does is essentially set up the object (in this case, basically set up the database connection, and select the database). To do anything useful with this object, you evoke methods on it. Methods are simply functions that manipulate an object's data. For example,
<?php $db->query($query); ?>
means to evoke the function query on the database object $db. The query method takes the string you pass it, and uses the data in the database object to execute that query. The -> symbol may confuse you a bit. In C, -> means to access the data of a pointer to a structure. In PHP, it means that the method on the right is called on the object on the left. Here, query is just one of the functions in the database class. All the other functions in that class can be accessed in the same way.
Now, when you set up your local.inc file, you do so by extending classes. Extending is an OO word for adding functionality to things. When you extend a class, all the functions and data in the class you are extending (called the super class) is available to the extending class (called the sub class). Your subclass can add functionality to the superclass, and it can also overwrite data and methods in the superclass. Let's take the database example. Here is a subclass of a database class:


class MyDBClass extends DB_Sql {
    $Host     = "localhost";
    $Database = "some_database";
    $User     = "some_db_user";
    $Password = "db_user_password";
}

Here we are creating a class called MyDBClass. This class can do everything that the database class can do. However, it has replaced some of the data of the database class with some of it's own. If you look in DB_Sql, you'll see the variables above are empty. The subclass provides these values, and it is the subclass you will use to create your database objects. You can call all the methods of DB_Sql on MyDBClass, because it is merely an extension. Think of it as MyDBClass IS a DB_Sql object with added functionality and/or data.
Session Management is not just for authentication purposes though, it can even be used without authentication at all. You may use it to store any information you want, and this information will be available to all other pages the user visits which you have enabled with phplib session management. To use it, you simply register the variable you want to become persistent to other pages. This is done with a simple call like:
<?php $sess->register("variable_name"); ?>
Note that you do not use the $variable notation, simply a string containing the name of the variable you want to register. This is because when you register a variable, you are making that variable (as in the variable name) persistent, NOT the contents of that variable (it's value). Thus, if you change the value of a persistent variable on subsequent pages, the value of the session variable will change as well.That's all! That variable (be it a string, number, array, even an object) will be available to you on all further session pages. For example, let's say page1.php3 is passed some user info from a form. Let's say it get's the variable $firstname. You can then do:

<?php

$sess
->register("first");
if (
check($firstname)) {
    
$first $firstname;
}

?>
A few important things here. Notice that we can register the variable before it exists. This is perfectly valid, as long as the variable we are registering is defined before the end of the script. You'll also notice that we did not simply store the variable passed by the form. For security reasons, you should never blindly store form data. As shown above, you should always check the form variable to make sure it is what you expect (in this example a user function "check" was used to do this). Finally, if the data checks out to be okay, then you copy it to your registered variable.
After registering the variable, it is written to the database by the page_close() call. If you forget your page_close() call, your session data will not be saved, giving you some possible surprising results. On subsequent pages, the page_open() call will restore the session variables out of the database. In the example above, the registered variable $first will be available as $first automatically. If you no longer need them, session variables can also be deleted by calling

<?php

$sess
->unregister("variable_name");

?>
With PHPLIB 6.1 (the current release), session data must be stored in a database. With the upcoming 7.0 release, PHPLIB uses a storage container mechanism, which allows you to store it in a database, shared memory, or even LDAP. PHPLIB uses a database class which makes your choice of which database arbitrary, we'll see more on that later.

Permissions

Permissions tie in closely with authentication. Once a user is authenticated, you can then have the option of checking their permissions to prevent them from accessing certain data. To do this, you must set up your permissions class in the page_open call. There are two main functions to check permissions.

<?php

$perm
->check("permission_level");

?>
This function will check to see that the user has the permission level you specify. The permission levels are defined in your local setup ( in the local.inc file ) and thus can be anything you like. For the check function, if the user does not have the permission level specified, the function perm_invalid() is automatically called. You may create your own perm_invalid function, or use the specified on which simply reports that the person does not have appropriate permissions, and then exits.

<?php

$perm
->have_perm("permission_level");

?>
Unlike check, have_perm returns true or false, and does not exit the script. You can use this for conditional testing, such as:

<?php

if ($perm->have_perm("guest")) {
    
//do something;
} elseif ($perm->have_perm("admin")) {
    
//do something else;
} else {
    
//yet something else;
}

?>

Database Abstraction

As mentioned earlier, PHPLIB uses a database abstraction layer. This is required for use with the other classes (authentication, session), but is also extremely handy to use on your own. It allows you to use a set of arbitrary database commands which will then be mapped to the database you are using. The benefit of this is that your apps can work with any database simply by changing your local configuration. Here's a simple example to query a database.

<?php

$db 
= new DB_MyDBClass;
$query "select name from sometable";
$db->query($query);
while (
$db->next_record()) {
    
$db->p("name");
}

?>
The first line creates a new database object. The username, password, host, and database are set in your local configuration. The third line then queries the database, and stores the result set in the database object. The $db->next_record() advances result set to the next row. The $db->p("name") prints out the value of the field name. You can also say $db->f("name") which simply returns the value rather than printing it out. The above is equivalent to this chunk of mysql specific code, and also automatically provides error handling and centralized storage of connection data:

<?php

mysql_connect
("localhost","username","password");
mysql_select_db("some_db");
$query "select name from sometable";
$result mysql_query($query);
while (
$row mysql_fetch_array($result)) {
    
$row["name"];
}

?>

 

Conclusion

There is a lot more to what PHPLIB can do, this is just an introduction. There are more functions and classes you'll want to look at, so head over to http://phplib.netuse.de and check out the docs. Check out the showroom to get an idea of how to put together a system.
--Chad