Location: PHPKode > projects > Informium > class/user-class.php
<?

//
// Copyright (c) 2002, Cameron McKay
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions 
// are met:

// * Redistributions of source code must retain the above copyright 
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright 
//   notice, this list of conditions and the following disclaimer in the 
//   documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

//
// Informium -- Advanced News Script
//
// User Class (user-class.php)
//
// Author: Cameron McKay
// Note:   This contains all the functions Informium needs retrieve and
//         set use: detail.
//

class user
{
	//
	// Function: add ( $username, $password, $cipher, $email, $access )
	//
	// Purpose:  Adds an user to the Informium database.
	//
	// Arguments:
	//   $username -> The user's username (automatically stripped of illegal characters).
	//   $password -> The user's password.
	//   $cipher   -> The user's password cipher (Currently either MD5 or DES).
	//   $email    -> The user's e-mail address (automatically checked for correct format).
	//   $access   -> The user's access level (Currently 0-4).
	//	
	// Returns:  The user's new user_id, or -1 for empty field.
	//

	function add ($username, $password, $cipher, $email, $access)
	{
		// Call the insert() function to insert the article.
		return $this->insert(0, $username, $password, $cipher, $email, $access);
	}

	//
	// Function: edit ( $user_id, $username, $password, $cipher, $email, $access )
	//
	// Purpose:  Edits an user in the Informium database.
	//
	// Arguments:
	//   $user_id  -> The user's user_id.
	//   $username -> The user's username (automatically stripped of illegal characters).
	//   $password -> The user's password.
	//   $cipher   -> The user's password cipher (Currently either MD5 or DES).
	//   $email    -> The user's e-mail address (automatically checked for correct format).
	//   $access   -> The user's access level (Currently 0-4).
	//
	// Returns:  The user_id, or -1 for empty field.
	//

	function edit ($user_id, $username, $password, $cipher, $email, $access)
	{
		// Call the insert() function to update the article.
		return $this->insert($user_id, $username, $password, $cipher, $email, $access);
	}

	//
	// Function: delete ( $user_id )
	//
	// Purpose:  Deletes an user in the Informium database.
	//
	// Arguments:
	//   $user_id -> The user's user_id.
	//
	// Returns:  Nothing.
	//

	function delete ($user_id)
	{
		// Import CONF.
		global $CONF;

		// Import the MYSQL class, if needed.
		require_once("$CONF[local_path]/class/mysql-class.php");

		// Create a new MYSQL object.
		$db = new mysql();

		// Connect to the DB.
		$db->pconnect();

		// Check if the user has any posts or comments.
		$query1  = "SELECT * FROM news WHERE user_id='$user_id'";
		$query2  = "SELECT * FROM comments WHERE user_id='$user_id'";
		$result1 = $db->query($query1);
		$result2 = $db->query($query2);

		// If they do, then we only 'fake' delete them.
		if ($db->num_rows($result1) || $db->num_rows($result2)) {

			// Free the results.
			$db->free($result1);
			$db->free($result2);

			// Prepare and execute the query.
			$query  = "SELECT * FROM user WHERE user_id='$user_id'";
			$result = $db->query($query);

			// Read the data into an array.
			$list = $db->fetch_array($result);

			// Use the edit command to change the access level to -1 (deleted).
			$this->edit($list[user_id], $list[username], $list[password], $list[cipher], $list[email], -$list[access]);

		// Otherwise we really delete them.
		} else {

			// Prepare and execute the query.
			$query  = "DELETE FROM user WHERE user_id='$user_id'";
			$db->query($query);

		}
	}

	//
	// Function: restore ( $user_id )
	//
	// Purpose:  Restores a deleted user in the Informium database.
	//
	// Arguments:
	//   $user_id -> The user's user_id.
	//
	// Returns:  Nothing.
	//

	function restore ($user_id)
	{
		// Merely running the delete method on a deleted user restores him... cool eh? :)
		$this->delete($user_id);
	}

	//
	// Function: insert ( $user_id, $username, $password, $cipher, $email, $access);
	//
	// Purpose:  Adds or edits an user in the database.
	//
	// Arguments:
	//   $user_id  -> The user's user_id.  If '0', then the user is new.
	//   $username -> The user's username.
	//   $password -> The user's encrypted password.
	//   $cipher   -> The user's password cipher.
	//   $email    -> The user's e-mail address.
	//   $access   -> The user's access level.
	//
	// Returns:  The new user_id, or error number.
	//
	
	function insert ($user_id, $username, $password, $cipher, $email, $access)
	{
		// Import CONF and COOKIE.
		global $CONF, $COOKIE_ADMIN;

		// Import COOKIE, MYSQL and SYSTEM classes, if needed.
		require_once("$CONF[local_path]/class/cookie-class.php");
		require_once("$CONF[local_path]/class/mysql-class.php");
		require_once("$CONF[local_path]/class/system-class.php");
 
		// Make new COOKIE, MYSQL and SYSTEM objects.
		$cookie = new cookie();
		$db     = new mysql();
		$system = new system();

		// Connect to the DB.
		$db->pconnect();

		// Check the username for illegal characters.
		if (preg_match("/[^A-Za-z-_ ]/i", $username)) {
			return -1;

		}

		// Make sure there are no empty fields.
		if (!strcmp($username, '') || !strcmp($password, '') || !strcmp($email, '')) {
			return -2;
		
		}

		// Check if we have a user_id that's greater than 0.  If we do, then
		// we're merely updating a user.
		if ($user_id > 0) {

			// Get the original create_date (since UPDATE automatically changes the timestamp...
			$create_date = $this->info($user_id, 'create_date');

			// Prepare the update.
			$query = "UPDATE user SET
					username='$username',
					password='$password',
					cipher='$cipher',
					email='$email',
					access='$access',
					create_date='$create_date' 
					WHERE user_id=$user_id"; 

		// Otherwise we're adding a new one.
		} else { 

			// Make sure there are no user's with that name already.
			$query  = "SELECT * FROM user WHERE username='$username'";
			$result = $db->query($query);

			if ($db->num_rows($result)) {

				// Free the result.
				$db->free($result);

				// Return -3 (duplicate user).
				return -3;

			}

			// Prepare the addition.
			$query = "INSERT user VALUES('', '$username', '$password', '$cipher', '$email', '$access', now())";

		}

		// Execute the query.
		$db->query($query);

		// Fetch the post_id for return, if needed.
		if ($user_id < 1)
			$user_id = $db->insert_id();

		// Return the values that were added.
		return $user_id;
	}

	//
	// Function: form ( [$user_id] )
	//
	// Purpose:  Creates a form used for adding and editing
	//           users.
	//
	// Arguments:
	//   $user_id -> If user_id is provided, then use those values.
	//
	// Returns:  Nothing.
	//

	function form()
	{
		// Import CONF and INF.
		global $CONF, $INF;

		// Import SYSTEM and XHTML classes, if needed.
		require_once("$CONF[local_path]/class/system-class.php");
		require_once("$CONF[local_path]/class/xhtml-class.php");	

		// Make new SYSTEM and XHTML objects.
		$system = new system();
		$xhtml  = new xhtml();

		// Determine access level.
		$access = $this->info(0, 'access');

		// Disabled certain fields if access is below 4.
		if ($access > 3) {
			$att_disabled = "";

		} else {
			$att_disabled = "disabled='disabled'";

		}

		// Check if we're editing.
		if (func_num_args() > 0) {

			// If we're editing, define the type.
			$type = 'edit';

			// Get the user_id.
			$user_id = func_get_arg(0);

			// Fetch details about that user.
			$list = $this->info($user_id);

			// Make the creation date look nice.
			$list[create_date] = $system->date_format($user_id, 'create_date', 'user'); 

		// Otherwise we're adding.
		} else {

			// If we're adding, define the type.
			$type = 'add';

			// Fill in the values we can.
			$list[create_date] = $system->date_format(0, 'now', 'user');
			
		}

		// Start a new table.
		$xhtml->table_start('normal', $CONF[table_size]);

		// Escape PHP.
		?>
<br />
<form action='user.php?exec=<? echo $type; ?>&user_id=<? echo $user_id; ?>' method='post'>

<table class='normal' width='100%' cellpadding='5' cellspacing='0' border='0' align='center'>

<tr>
<td>Username:</td>
<td>
<input type='text' name='username' value='<? echo $list[username]; ?>' size='40' <? echo $att_disabled; ?>' />
</td>
</tr>

<tr>
<td>E-Mail:</td>
<td><input type='text' name='email' value='<? echo $list[email]; ?>' size='40' /></td>
</tr>

<tr><td><br /></td><td><br /></td></tr>

<tr>
<td>Password:</td>
<td><input type='password' name='password' size='40' /></td>
</tr>

<tr>
<td>Re-type Password:</td>
<td><input type='password' name='password_check' size='40' /></td>
</tr>

<?
// If we're editing, then give the option to use the old password.
if (!strcmp($type, 'edit')) {
	
	echo "<tr>\n";
	echo "<td>Use Old Password:</td>\n";
	echo "<td>\n";
	echo "<select name='password_old'>\n";
	echo "<option value='1'>Yes</option>\n";
	echo "<option value='0'>No</option>\n";
	echo "</select>\n";
	echo "</td>\n";
	echo "</tr>\n";

}
?>

<tr>
<td>Password Cipher:</td>
<td>
<?
// If we're editing, then the cipher cannot be changed.
if (!strcmp($type, 'edit')) {

	echo "<input type='hidden' name='cipher' value='$list[cipher]' />\n";
	echo "<select name='cipher' disabled='disabled'>\n";
	echo "<option value='$list[cipher]' selected='selected'>$list[cipher]</option>\n";

// Otherwise, it's business as usual.
} else {

	echo "<select name='cipher'>\n";
	for ($i = 0; $i < count($CONF[cipher_list]); ++$i)
		echo "<option value='{$CONF[cipher_list][$i]}'>{$CONF[cipher_list][$i]}</option>\n";

}

// End the list.
echo "</select>\n";
?>
</td>
</tr>

<tr><td><br /></td><td><br /></td></tr>

<tr>
<td>Access Level:</td>
<td>
<?
// If we're editing, and the user's access level < 4, then the
// access level cannot be changed.
if (!strcmp($type, 'edit') && ($this->info(0, 'access') < 4))
	echo "<select name='access' disabled='disabled'>\n";

// Otherwise, ti's business as usual.
else
	echo "<select name='access'>\n";

// List the possible access levels.
for ($i = 1; $i <= ($CONF[access_count]); ++$i) {

	// If we're editing, set it to the current users access level.
	if (!strcmp($type, 'edit')) {

		// Determine access level.
		$access = $this->info($user_id, 'access');

		// If they match, then we make the match the default selected.
		if ($access == $i) {
			echo "<option value='$i' selected='selected'>$i - {$CONF[access_list][$i]}</option>\n";
			continue;
		}

	}	
	
	echo "<option value='$i'>$i - {$CONF[access_list][$i]}</option>\n";

}

// End the list.
echo "</select>\n";
?>
</td>
</tr>

<tr><td><br /></td><td><br /></td></tr>

<tr>
<td>Creation Date:</td>
<td><? echo $list[create_date]; ?></td>
</tr>

<tr>
<td>Current Date:</td>
<td><? echo $system->date_format(0, 'now', 'user'); ?></td>
</tr>

<tr><td><br /></td><td><br /></td></tr>

<tr>
<td><input type='submit' value='<? echo ucfirst($type); ?> User'> <input type='reset' value='Reset' /></td>
<td>&nbsp;</td>
</tr>

</table>

</form>
		<?
		// Re-enter PHP.

		// End the table.
		$xhtml->table_end();

	}

	//
	// Function: dropdown ( $type, $limit )
	//
	// Purpose:  Displays a dropdown menu of users so the user may choose one.
	//
	// Arguments:
	//   $type  -> Type of dropdown (i.e. edit or delete).
	//   $limit -> Number of items in the dropdown.
	//
	// Returns:  Nothing.
	//
	
	function dropdown ($type, $limit, $real_user = TRUE)
	{
		// Import CONF and COOKIE.
		global $CONF, $COOKIE_ADMIN;

		// Import COOKIE, MYSQL, USER and XHTML classes, if needed.
		require_once("$CONF[local_path]/class/cookie-class.php");
		require_once("$CONF[local_path]/class/mysql-class.php");
		require_once("$CONF[local_path]/class/xhtml-class.php");

		// Make COOKIE, MYSQL and USER objects.
		$cookie = new cookie();
		$db     = new mysql();
		$xhtml  = new xhtml();

		// Make a new MYSQL object.
		$db = new mysql();
 
		// Connect to the database to check the access.
		$db->pconnect();

		// If real_user is TRUE then we user any number > 0,
		// If real_user is FALSE then we user any numer < 0.
		if ($real_user == TRUE) {

			$compare = '>';

		} else {

			$compare = '<';
		}

		// Prepare the query.
		// If the limit is greater than 0, than we have a limit.
		if ($limit > 0)
			$query  = "SELECT * FROM user WHERE access $compare 0 ORDER BY access DESC, username ASC LIMIT $limit";

		// If the limit is lees than 0, than we have no limit.
		else if ($limit < 0)
			$query  = "SELECT * FROM user WHERE access $compare 0 ORDER BY access DESC, username ASC";

		// Execute the query.
		$result = $db->query($query);

		// Make the argument string for the form.
		if (!strcmp($type, 'edit')) {
			$argument = 'form=edit';

		// If we're restoring, restore the user.
		} else if (!strcmp($type, 'restore')) {
			$argument = 'exec=restore';

		// Otherwise we're deleting.
		} else if (!strcmp($type, 'delete')) {
			$argument = 'exec=delete';

		}

		// Start the table.
		$xhtml->table_start('normal', $CONF[table_size]);

		// Start the form.
		echo "<br />\n";
		echo "<form action='user.php?$argument' method='post'>\n";
		echo "<select name='user_id'>\n";

		// Display the user list.
		while ($list = $db->fetch_array($result))
		{
			// Determine the username.
			$list[username] = $this->to_name($list[user_id]);

			// Print the information.
			echo "<option value='$list[user_id]'>$list[username] - Level $list[access] ({$CONF[access_list][$list[access]]})</option>\n";
		}

		// End the form and list.
		echo "</select><br />\n";
		echo "<br />\n";
		echo "<input type='submit' value='" . ucfirst($type) . " User'>\n";
		echo "</form>\n";

		// End the table.
		$xhtml->table_end();

		// Free the result.
		$db->free($result);
	}

	//
	// Function: i_list ( $field )
	//
	// Purpose:  Retrieves a list array of any given field name.
	//
	// Arguments:
	//   $field -> Can be any of the values written below.
	//
	// Returns:  An array with one of the following list of values.
	//   user_id     -> The uesr's id number.
	//   username    -> The user's username.
	//   password    -> The user's password.
	//   email       -> The user's email address.
	//   access      -> The user's access level.
	//   create_date -> The user's creation date.
	//

	function i_list ($field)
	{
		// Import CONF.
		global $CONF;

		// Import MYSQL class, if needed.
		require_once("$CONF[local_path]/class/mysql-class.php");

		// Make a new MYSQL object.
		$db = new mysql();

		// Connect to the database to check the access.
		$db->pconnect();

		// Prepare the query.
		$query  = "SELECT ($field) FROM user WHERE access > 0";
		$result = $db->query($query);

		// Cycle through the results, making them into a list.
		while ($list = $db->fetch_array($result))
			$return[] = $list[$field];

		// Free the result.
		$db->free($result);

		// Return the answer.
		return $return;
	}

	//
	// Function: info ( $user_id, $type )
	//
	// Purpose:  Retrieves important user values by decoding the cookie and looking
	//           their name up in the database (depending on what needs to be found).
	//
	// Arguments:
	//   $type -> Can be any of the values written below or blank.
	//
	// Returns:  An associative array with all of the following values (if argument is blank).
	//   user_id     -> The uesr's id number.
	//   username    -> The user's username.
	//   password    -> The user's password.
	//   email       -> The user's email address.
	//   access      -> The user's access level.
	//   create_date -> The user's creation date.
	//
	//   Otherwise it returns the requested value.
	//

	function info()
	{
		// Load the INF array and cookie.
		global $CONF, $INF, $COOKIE_ADMIN;

		// Import COOKIE class, if needed.
		require_once("$CONF[local_path]/class/cookie-class.php");

		// Make a new COOKIE object.
		$cookie = new cookie();

		// If the user_id is '0', then we get the information from the cookie.
		if (($user_id = func_get_arg(0)) == 0) {

			// Decode and check the cookie.
			if(!(list($user_id, $username, $password, $ip) = $cookie->decode($COOKIE_ADMIN)))
				die("INFORMIUM: Cookie values illegally changed.<br />\n");
 
		}

		// Import MYSQL class, if needed.
		require_once("$CONF[local_path]/class/mysql-class.php");

		// Make a new MYSQL object.
		$db = new mysql();

		// Connect to the database to check the access.
		$db->pconnect();

		// If we have no arguments, then get them all.
		if (func_num_args() < 2) {

			$query  = "SELECT * FROM user WHERE user_id='$user_id'";
			$result = $db->query($query);
			$return = $db->fetch_array($result);

		} else {

			$field   = func_get_arg(1);
			$query   = "SELECT ($field) FROM user WHERE user_id='$user_id'";
			$result  = $db->query($query);
			$return  = $db->result($result);

		}

		// Free the result.
		$db->free($result);

		// Return what they want.
		return $return;
	}

	//
	// Function: check ( $username | $user_id )
	//
	// Purpose:  Checks if the username or user_id exists.
	//
	// Arguments:
	//   $username -> The user's username.
	//   $user_id  -> The user's user_id.
	//
	// Returns:  1 if the user exists, 0 if they do not exist, -1 if it contains illegal characters.
	//

	function check ($data)
	{
		// Import CONF.
		global $CONF;

		// Import MYSQL class, if needed.
		require_once("$CONF[local_path]/class/mysql-class.php");

		// Make a new MYSQL object.
		$db = new mysql();
		
		// Check username illegal characters.
		if (preg_match("/[^A-Za-z-_ ]/i", $username)) {
			return -1;
		}

		// If it's numerical, then it's a user_id.
		if (is_int($data)) {
			$data_type = 'user_id';

		// Otherwise, it's a username.
		} else {
			$data_type = 'username';

		}

		// Connect to the DB.
		$db->pconnect();

		// Prepare and execute the query.
		$query  = "SELECT * FROM user WHERE $data_type='$data'";
		$result = $db->query($query);

		// Check if we got a result.
		$return = $db->num_rows($result);

		// Free the result.
		$db->free($result);

		// Return the answer.
		return $return;
	}

	//
	// Function: to_name ( $user_id )
	//
	// Purpose:  Translates a user_id to a username.
	//
	// Returns:  Username for given user_id.
	//

	function to_name($user_id)
	{
		// Import CONF.
		global $CONF;

		// Import MYSQL class, if needed.
		require_once("$CONF[local_path]/class/mysql-class.php");

		// Make a new MYSQL object.
		$db = new mysql();

		// Connect to the database.
		$db->pconnect();

		// Execute query.
		$query  = "SELECT username FROM user WHERE user_id='$user_id'";
		$result = $db->query($query);
		$return = $db->result($result);

		// Free result.
		$db->free($result);

		// Return username.
		return $return;
	}

	//
	// Function: to_id ($username OR $user_id)
	//
	// Purpose:  Translates a username (or user_id) to a user_id.
	//
	// Return:   The user_id for given username.
	//

	function to_id ( $userdata )
	{
		// Import CONF.
		global $CONF;

		// If it's an integer than we assume it's already a user_id.
		if (is_numeric($userdata)) { 
		
			// So we return the value untouched.
			return $userdata;

		} else {

			// Rename it for aesthetics.
			$username = $userdata;

		}

		// Import MYSQL class, if needed.
		require_once("$CONF[local_path]/class/mysql-class.php");

		// Make a new MYSQL object.
		$db = new mysql();

		// Connect to the database.
		$db->pconnect();

		// Execute query.
		$query  = "SELECT user_id FROM user WHERE username='$username'";
		$result = $db->query($query);
		$return = $db->result($result);

		// Free result.
		$db->free($result);

		// Return user_id.
		return $return;
	}

	//
	// Function: encrypt_password ( $username OR user_id, $password )
	//
	// Purpose:  Encrypts the user's password with the proper cipher.
	//
	// Arguments:
	//   $userdata -> The user's username or user_id.
	//   $password -> The user's plaintext password.
	//
	// Returns:  The user's properly encrypted password.
	//

	function encrypt_password ( $userdata, $password )
	{
		// Import CONF & INF.
		global $CONF, $INF;

		// Import SYSTEM class, if needed.
		require_once("$CONF[local_path]/class/system-class.php");

		// Make a new SYSTEM object.
		$system = new system();

		// Make sure it's a user_id.
		$user_id = $this->to_id($userdata);

		// Find out the user's cipher.
		$cipher = $this->info($user_id, 'cipher');

		// Return the encrypted password.
		return $system->do_encrypt($password, $cipher);
	}

	//
	// Function: authenticate ( $username OR $user_id , $password )
	//
	// Purpose:  Determines whether or not a user is allowed access onto the system.
	//
	// Arguments:
	//   $userdata -> The user's username or user_id.
	//   $password -> The plaintext version of the password to check against.
	//
	// Returns:  1 if the password is valid, 0 if it is not.
	//
	
	function authenticate ( $userdata, $password )
	{
		// Import CONF.
		global $CONF;

		// Make sure it's a user_id.
		$user_id = $this->to_id($userdata);

		// Deny user if their access is less than 1.
		if ($this->info($user_id, 'access') < 1) {
			return 0;

		// Otherwise check the passwords.
		} else if (!strcmp($this->encrypt_password($user_id, $password), $this->info($user_id, 'password'))) {
			// The user is authenticated.
			return 1;

		// Otherwise .... the user is not authenticated.
		} else {
			return 0;

		}

	}

}

?>
Return current item: Informium