I've got quite a large.. and secure PHP registration form, however when I fill it in, I'm being provided with the error Registration Failed, which is only meant to display if there's an error signing up, and I can't work out what the error is..
MYSQL Code
CREATE TABLE IF NOT EXISTS `users` (
`username` varchar(30) NOT NULL,
`password` varchar(32) DEFAULT NULL,
`userid` varchar(32) DEFAULT NULL,
`userlevel` tinyint(1) unsigned NOT NULL,
`email` varchar(50) DEFAULT NULL,
`timestamp` int(11) unsigned NOT NULL,
`valid` tinyint(1) unsigned NOT NULL DEFAULT '0',
`name` varchar(50) DEFAULT NULL,
`hash` varchar(32) NOT NULL,
`hash_generated` int(11) NOT NULL,
PRIMARY KEY (`username`)
Register.php
<?php
include("include/session.php");
/**
* The user is already logged in, not allowed to register.
*/
if($session->logged_in){
echo "<h1>Registered</h1>";
echo "<p>We're sorry <b>$session->username</b>, but you've already registered. "
."<a href=\"main.php\">Main</a>.</p>";
}
/**
* The user has submitted the registration form and the
* results have been processed.
*/
else if(isset($_SESSION['regsuccess'])){
/* Registration was successful */
if($_SESSION['regsuccess']){
echo "<h1>Registered!</h1>";
if(EMAIL_WELCOME){
echo "<p>Thankyou <b>".$_SESSION['reguname']."</b>, you have been sent a confirmation email which should be arriving shortly. Please confirm your registration before you continue.<br />Back to <a href='main.php'>Main</a></p>";
}else{
echo "<p>Thank you <b>".$_SESSION['reguname']."</b>, your information has been added to the database, "
."you may now <a href=\"main.php\">log in</a>.</p>";
}
}
/* Registration failed */
else{
echo "<h1>Registration Failed</h1>";
echo "<p>We're sorry, but an error has occurred and your registration for the username <b>".$_SESSION['reguname']."</b>, "
."could not be completed.<br>Please try again at a later time.</p>";
}
unset($_SESSION['regsuccess']);
unset($_SESSION['reguname']);
}
/**
* The user has not filled out the registration form yet.
* Below is the page with the sign-up form, the names
* of the input fields are important and should not
* be changed.
*/
else{
?>
<h1>Register</h1>
<form action="process.php" method="POST">
<p>Username:</p>
<?php echo $form->error("user"); ?>
<input type="text" name="user" maxlength="18" value="<?php echo $form->value("user"); ?>">
<p>Password:</p>
<?php echo $form->error("pass"); ?>
<input type="password" name="pass" value="<?php echo $form->value("pass"); ?>">
<p>Email:</p>
<?php echo $form->error("email"); ?>
<input type="text" name="email" value="<?php echo $form->value("email"); ?>">
<input type="hidden" name="fav_continent" value="Default">
<input type="hidden" name="fav_colour" value="Default">
<input type="hidden" name="subjoin" value="1">
<input type="submit" value="Register">
</form>
<?php
}
?>
Process.php
<?php
include("include/session.php");
class Process
{
/* Class constructor */
function Process(){
global $session;
/* User submitted login form */
if(isset($_POST['sublogin'])){
$this->procLogin();
}
/* User submitted registration form */
else if(isset($_POST['subjoin'])){
$this->procRegister();
}
/* User submitted edit account form */
else if(isset($_POST['subedit'])){
$this->procEditAccount();
}
else if(isset($_POST['subConfirm'])){
$this->procSendConfirm();
}
else if(isset($_POST['login_with_hash'])){
$this->procHashLogin($_POST['hash']);
}
/**
* The only other reason user should be directed here
* is if he wants to logout, which means user is
* logged in currently.
*/
else if($session->logged_in){
$this->procLogout();
}
}
/**
* procRegister - Processes the user submitted registration form,
* if errors are found, the user is redirected to correct the
* information, if not, the user is effectively registered with
* the system and an email is (optionally) sent to the newly
* created user.
*/
function procRegister(){
global $session, $form;
$_POST = $session->cleanInput($_POST);
/* Registration attempt */
$retval = $session->register($_POST['user'], $_POST['pass'], $_POST['email'], $_POST['fav_continent'], $_POST['fav_colour']);
/* Registration Successful */
if($retval == 0){
$_SESSION['reguname'] = $_POST['user'];
$_SESSION['regsuccess'] = true;
header("Location: ".$session->referrer);
}
/* Error found with form */
else if($retval == 1){
$_SESSION['value_array'] = $_POST;
$_SESSION['error_array'] = $form->getErrorArray();
header("Location: ".$session->referrer);
}
/* Registration attempt failed */
else if($retval == 2){
$_SESSION['reguname'] = $_POST['user'];
$_SESSION['regsuccess'] = false;
header("Location: ".$session->referrer);
}
}
};
/* Initialize process */
$process = new Process;
?>
Database.php
<?php
include("constants.php");
define("DB_SERVER", "localhost");
define("DB_USER", "questers_dbuser1");
define("DB_PASS", "mallz123");
define("DB_NAME", "questers_db1");
class MySQLDB
{
var $connection; //The MySQL database connection
var $num_active_users; //Number of active users viewing site
var $num_active_guests; //Number of active guests viewing site
var $num_members; //Number of signed-up users
/* Note: call getNumMembers() to access $num_members! */
/* Class constructor */
function MySQLDB(){
/* Make connection to database */
$this->connection = mysql_connect(DB_SERVER, DB_USER, DB_PASS) or die(mysql_error());
mysql_select_db(DB_NAME, $this->connection) or die(mysql_error());
/**
* Only query database to find out number of members
* when getNumMembers() is called for the first time,
* until then, default value set.
*/
$this->num_members = -1;
if(TRACK_VISITORS){
/* Calculate number of users at site */
$this->calcNumActiveUsers();
/* Calculate number of guests at site */
$this->calcNumActiveGuests();
}
}
/**
* confirmUserPass - Checks whether or not the given
* username is in the database, if so it checks if the
* given password is the same password in the database
* for that user. If the user doesn't exist or if the
* passwords don't match up, it returns an error code
* (1 or 2). On success it returns 0.
*/
function confirmUserPass($username, $password){
/* Add slashes if necessary (for query) */
if(!get_magic_quotes_gpc()) {
$username = addslashes($username);
}
/* Verify that user is in database */
$q = sprintf("SELECT password FROM ".TBL_USERS." where username = '%s'",
mysql_real_escape_string($username));
$result = mysql_query($q, $this->connection);
if(!$result || (mysql_numrows($result) < 1)){
return 1; //Indicates username failure
}
/* Retrieve password from result, strip slashes */
$dbarray = mysql_fetch_array($result);
$dbarray['password'] = stripslashes($dbarray['password']);
$password = stripslashes($password);
/* Validate that password is correct */
if($password == $dbarray['password']){
return 0; //Success! Username and password confirmed
}
else{
return 2; //Indicates password failure
}
}
/**
* confirmUserID - Checks whether or not the given
* username is in the database, if so it checks if the
* given userid is the same userid in the database
* for that user. If the user doesn't exist or if the
* userids don't match up, it returns an error code
* (1 or 2). On success it returns 0.
*/
function confirmUserID($username, $userid){
/* Add slashes if necessary (for query) */
if(!get_magic_quotes_gpc()) {
$username = addslashes($username);
}
/* Verify that user is in database */
$q = sprintf("SELECT userid FROM ".TBL_USERS." WHERE username= '%s'",
mysql_real_escape_string($username));
$result = mysql_query($q, $this->connection);
if(!$result || (mysql_numrows($result) < 1)){
return 1; //Indicates username failure
}
/* Retrieve userid from result, strip slashes */
$dbarray = mysql_fetch_array($result);
$dbarray['userid'] = stripslashes($dbarray['userid']);
$userid = stripslashes($userid);
/* Validate that userid is correct */
if($userid == $dbarray['userid']){
return 0; //Success! Username and userid confirmed
}
else{
return 2; //Indicates userid invalid
}
}
/**
* usernameTaken - Returns true if the username has
* been taken by another user, false otherwise.
*/
function usernameTaken($username){
if(!get_magic_quotes_gpc()){
$username = addslashes($username);
}
$q = sprintf("SELECT username FROM ".TBL_USERS." WHERE username = '%s'",
mysql_real_escape_string($username));
$result = mysql_query($q, $this->connection);
return (mysql_numrows($result) > 0);
}
/**
* emailTaken - Returns true if the email has
* been taken by another user, false otherwise.
*/
function emailTaken($email){
if(!get_magic_quotes_gpc()){
$email = addslashes($email);
}
$q = sprintf("SELECT email FROM ".TBL_USERS." WHERE email = '%s'",
mysql_real_escape_string($email));
$result = mysql_query($q, $this->connection);
return (mysql_num_rows($result) > 0);
}
/**
* addNewUser - Inserts the given (username, password, email)
* info into the database. Appropriate user level is set.
* Returns true on success, false otherwise.
*/
function addNewUser($username, $password, $email, $userid, $fav_continent, $fav_colour){
$time = time();
/* If admin sign up, give admin user level */
if(strcasecmp($username, ADMIN_NAME) == 0){
$ulevel = ADMIN_LEVEL;
}else{
$ulevel = USER_LEVEL;
}
$q = sprintf("INSERT INTO ".TBL_USERS." VALUES ('%s', '%s', '%s', '%s', '%s', $time, '0', '%s', '%s', '%s', '0', '0')",
mysql_real_escape_string($username),
mysql_real_escape_string($password),
mysql_real_escape_string($userid),
mysql_real_escape_string($ulevel),
mysql_real_escape_string($email),
mysql_real_escape_string($fav_continent),
mysql_real_escape_string($fav_colour));
return mysql_query($q, $this->connection);
}
/**
* updateUserField - Updates a field, specified by the field
* parameter, in the user's row of the database.
*/
function updateUserField($username, $field, $value){
$q = sprintf("UPDATE ".TBL_USERS." SET %s = '%s' WHERE username = '%s'",
mysql_real_escape_string($field),
mysql_real_escape_string($value),
mysql_real_escape_string($username));
return mysql_query($q, $this->connection);
}
/**
* getUserInfo - Returns the result array from a mysql
* query asking for all information stored regarding
* the given username. If query fails, NULL is returned.
*/
function getUserInfo($username){
$q = sprintf("SELECT * FROM ".TBL_USERS." WHERE username = '%s'",
mysql_real_escape_string($username));
$result = mysql_query($q, $this->connection);
/* Error occurred, return given name by default */
if(!$result || (mysql_numrows($result) < 1)){
return NULL;
}
/* Return result array */
$dbarray = mysql_fetch_array($result);
return $dbarray;
}
function getUserInfoFromHash($hash){
$q = sprintf("SELECT * FROM ".TBL_USERS." WHERE hash = '%s'",
mysql_real_escape_string($hash));
$result = mysql_query($q, $this->connection);
if(!$result || (mysql_num_rows($result) < 1)){
return NULL;
}
$dbarray = mysql_fetch_array($result);
return $dbarray;
}
/**
* query - Performs the given query on the database and
* returns the result, which may be false, true or a
* resource identifier.
*/
function query($query){
return mysql_query($query, $this->connection);
}
};
/* Create database connection */
$database = new MySQLDB;
?>
Form.php
Session.php
<?php
include("database.php");
include("form.php");
class Session
{
var $username; //Username given on sign-up
var $userid; //Random value generated on current login
var $userlevel; //The level to which the user pertains
var $time; //Time user was last active (page loaded)
var $logged_in; //True if user is logged in, false otherwise
var $userinfo = array(); //The array holding all user info
var $url; //The page url current being viewed
var $referrer; //Last recorded site page viewed
function Session(){
$this->time = time();
$this->startSession();
}
function startSession(){
global $database; //The database connection
session_start(); //Tell PHP to start the session
/**
* Set guest value to users not logged in, and update
* active guests table accordingly.
*/
if(!$this->logged_in){
$this->username = $_SESSION['username'] = GUEST_NAME;
$this->userlevel = GUEST_LEVEL;
$database->addActiveGuest($_SERVER['REMOTE_ADDR'], $this->time);
}
/* Update users last active timestamp */
else{
$database->addActiveUser($this->username, $this->time);
}
/* Remove inactive visitors from database */
$database->removeInactiveUsers();
$database->removeInactiveGuests();
/* Set referrer page */
if(isset($_SESSION['url'])){
$this->referrer = $_SESSION['url'];
}else{
$this->referrer = "/";
}
/* Set current url */
$this->url = $_SESSION['url'] = $_SERVER['PHP_SELF'];
}
function register($subuser, $subpass, $subemail, $subfav_continent, $subfav_colour){
global $database, $form, $mailer; //The database, form and mailer object
/* Username error checking */
$field = "user"; //Use field name for username
if(!$subuser || strlen($subuser = trim($subuser)) == 0){
$form->setError($field, "* Username not entered");
}
else{
/* Check if username is already in use */
else if($database->usernameTaken($subuser)){
$form->setError($field, "* Username already in use");
}
}
/* Password error checking */
$field = "pass"; //Use field name for password
if(!$subpass){
$form->setError($field, "* Password not entered");
}
else{
/* Spruce up password and check length*/
$subpass = stripslashes($subpass);
if(strlen($subpass) < 4){
$form->setError($field, "* Password too short");
}
}
/* Email error checking */
$field = "email"; //Use field name for email
if(!$subemail || strlen($subemail = trim($subemail)) == 0){
$form->setError($field, "* Email not entered");
}
else{
/* Check if valid email address */
if(filter_var($subemail, FILTER_VALIDATE_EMAIL) == FALSE){
$form->setError($field, "* Email invalid");
}
/* Check if email is already in use */
if($database->emailTaken($subemail)){
$form->setError($field, "* Email already in use");
}
$subemail = stripslashes($subemail);
}
$randid = $this->generateRandID();
/* Errors exist, have user correct them */
if($form->num_errors > 0){
return 1; //Errors with form
}
/* No errors, add the new account to the */
else{
if($database->addNewUser($subuser, md5($subpass), $subemail, $randid, $subfav_continent, $subfav_colour)){
if(EMAIL_WELCOME){
$mailer->sendWelcome($subuser,$subemail,$subpass,$randid);
}
return 0; //New user added succesfully
}else{
return 2; //Registration attempt failed
}
}
}
/**
* generateRandID - Generates a string made up of randomized
* letters (lower and upper case) and digits and returns
* the md5 hash of it to be used as a userid.
*/
function generateRandID(){
return md5($this->generateRandStr(16));
}
/**
* generateRandStr - Generates a string made up of randomized
* letters (lower and upper case) and digits, the length
* is a specified parameter.
*/
function generateRandStr($length){
$randstr = "";
for($i=0; $i<$length; $i++){
$randnum = mt_rand(0,61);
if($randnum < 10){
$randstr .= chr($randnum+48);
}else if($randnum < 36){
$randstr .= chr($randnum+55);
}else{
$randstr .= chr($randnum+61);
}
}
return $randstr;
}
function cleanInput($post = array()) {
foreach($post as $k => $v){
$post[$k] = trim(htmlspecialchars($v));
}
return $post;
}
};
/**
* Initialize session object - This must be initialized before
* the form object because the form uses session variables,
* which cannot be accessed unless the session has started.
*/
$session = new Session;
/* Initialize form object */
$form = new Form;
?>