Code Review - Registration Page in PDO

Hello again.

I need a 2nd pair of eyes on some code that I’ve written. It’s nearly finished, but since I’m still a beginner it would be nice to have others take a look at it to ensure that it’s faultless. If you’re wondering what I’m asking, it’s for suggestions on how the code could be structured (written) better, if there are issues, etc.

Goal:
Create a user registration page that creates a new user for a web application.

Data to Collect:

[ul][li]Desired Username[/li]
[li]Desired Password[/li]
[li]First Name[/li]
[li]Last Name[/li]
[li]Preferred Email Address[/li][/ul]

Features:

[ul][li]Checks the form for invalid or missing data[/li]
[li]Connects to a database to check for conflicts with existing data[/li]
[li]Rudimentary Data Escape and Sanitation for user data[/li]
[li]Enters user provided information into a database to create the account.[/li][/ul]

Constraints

[ul][li]Usernames and Passwords must be 6 chars long[/li]
[li]All textual input must be less than 127 chars long, with the exception of the eMail input which is 255 chars maximum[/li]
[li]No HTML is allowed in the user’s input[/li][/ul]

The Code: HTML (Bare Essentials)

<div id="content">
        <h2 id='pageSubTitle'>One Step Registration</h2>
	    <small class='formInst'>Fields marked <em>*</em> are required</small>
	    <form action="/users/register.php" method="post" id="register" name="register">
		<fieldset>
            <fieldset>
            <!-- Person's Name -->
            <p class="float name">
                <label for="firstName">First</label>
				<input type="text"
				       name="firstName"
				       id="firstName"
				       placeholder="Anderson"/>
            </p>
            <p class="float name">
                <label for="lastName">Last</label>
				<input type="text"
				       name="lastName"
				       id="lastName"
				       placeholder="Smith"/>
            </p>
            </fieldset>
            <fieldset>
            <!-- Person's Account Details -->
            <p class="float">
                <label for="username"><em>*</em>Username</label>
                <input type="text"
                       name="username"
                       id="username"
                       placeholder="asmith13"
                       required="required"/>
            </p>
            <p class='float'>
                <label for="password"><em>*</em>Password</label>
                <input type="password"
                       name="password"
                       id="password"
                       placeholder="letters, numbers, symbols please"
                       required="required"/>
            </p>
            </fieldset>
            <fieldset>
            <!-- Person's Contact Information -->
            <p class='clearfix'>
                <label for="eMail"><em>*</em>Email</label>
                <input type="text"
                       name="eMail"
                       id="eMail"
                       placeholder="[email protected]"
                       required="required"/>
            </p>
            </fieldset>
            <p class='clearfix'>
                <input type="submit"
                    name="createUser"
                    id="createUser"
                    value="Register"/>
            </p>
		</fieldset>
	    </form>
	</div>

The Code: PHP

[php]

<?php // If the user has pressed submit, and the user is not already signed onto an account if ( isset($_POST['createUser']) && ( !isset($_SESSION['signedOn']) || isset($_SESSION['signedOn']) && $_SESSION['signedOn'] == false) ) { // Default Status for Account Creation $commit = false; // User Information $firstName = $_POST['firstName']; $lastName = $_POST['lastName']; $username = $_POST['userName']; $password = $_POST['password']; $eMail = $_POST['eMail']; // Constants define('MIN_LENGTH_USERNAME', 6); define('MIN_LENGTH_PASSWORD', 6); define('MAX_LENGTH_USERNAME', 127); define('MAX_LENGTH_PASSWORD', 127); define('MAX_LENGTH_FIRSTNAME', 127); define('MAX_LENGTH_LASTNAME', 127); // Simple eMail Validator { NOTE: NOT RFC 822 OR RFC 5321 COMPLIANT } $profileEmail = "/^[a-z0-9]+([_\\.-][a-z0-9]+)*@([a-z0-9]+([\.-][a-z0-9]+)*)+\\.[a-z]{2,}$/i"; // TO DO: Password Complexity Enforcement // PART A: 1A, 2A, 3A - Worry about checking to see if any required information is missing first if (!$username || !is_string($username)) { $errMessage = "You must enter a valid username for your account."; exit(); } else if (!$password || !is_string($firstName)) { $errMessage = "Your account must be secured with a password."; exit(); } else if (!$eMail || !is_string($eMail)) { $errMessage = "To verify your account, we need your eMail address."; exit(); } // PART A: 4A - 12A Now check all form information for consistency. # OPTIONAL if (isset($firstName)) { if(!is_string($firstName)) { $errMessage = "Your first name must contain alphanumeric characters."; } else if(strlen($firstName) > MAX_LENGTH_FIRSTNAME) { $errMessage = "Your first name is too large to fit in our table."; } } if (isset($lastName)) { if(!is_string($lastName)) { $errMessage = "Your last name must contain alphanumeric characters."; } else if (strlen($lastName) > MAX_LENGTH_LASTNAME) { $errMessage = "Your last name is too large to fit in our table."; } } # MANDATORY else if (strlen($username) < MIN_LENGTH_USERNAME || strlen($username) > MAX_LENGTH_USERNAME) { $errMessage = "Your username must be between " . MIN_LENGTH_USERNAME . " and " . MAX_LENGTH_USERNAME . " characters long."; } else if (strlen($password) < MIN_LENGTH_PASSWORD || strlen($password) > MAX_LENGTH_PASSWORD) { $errMessage = "Your password must be between " . MIN_LENGTH_PASSWORD . " and " . MAX_LENGTH_PASSWORD . " characters long."; } else if (!preg_match($profileEmail, $eMail)) { $errMessage = "The eMail you've provided seems to be invalid."; $errLegal = "If this is not the case, please contact our webmaster."; } // No HTML tags allowed in input; Ensure Quotes are Escaped for MySQL $sanUsername = addslashes(strip_tags($username)); $sanPassword = addslashes(strip_tags($password)); $sanFirstName = addslashes(strip_tags($firstName)); $sanLastName = addslashes(strip_tags($lastName)); $sanEmail = addslashes(strip_tags($eMail)); /* PART B: Make a connection to the database (dbConn.php) last to conserve * : network resources. */ include_once ("{$_SERVER['DOCUMENT_ROOT']}/inc/auth/dbConn.php"); #Ensure there is a working database connection if(isset($dbObject)) { // 1B. Find existing usernames in the database matching the chosen username $queryUsernameConflict = 'SELECT * FROM `users` WHERE `username` = :username'; try { $stmtUserConflict = $dbObject->prepare($queryUsernameConflict); $stmtUserConflict->bindValue(':username', $sanUsername); $stmtUserConflict->execute(); $userMatches = $stmtUserConflict->fetchAll(); $stmtUserConflict->closeCursor(); return $userMatches; } catch (PDOException $errorData) { $errorMessage = $errorData->getMessage(); $dbDebugMsg = <<<DEBUG_USER_CHECK

Debug Message: An error was encountered while checking for duplicate users.

Details: $errorMessage

DEBUG_USER_CHECK; return $dbDebugMsg; } #TO DO: Figure out how to detect if a row contains a username that matches #the one chosen by the client. if($userMatches) { $errMessage = "The username $username has already been taken!"; } // 2B. Find an identical eMail in the database to prevent duplicate accounts $queryDuplicateAccounts = 'SELECT * FROM `users` WHERE `eMail` = :email'; try { $stmtDupeEmail = $dbObject->prepare($queryDuplicateAccounts); $stmtDupeEmail->bindValue(':email', $sanEmail); $stmtDupeEmail->execute(); $emailMatches = $stmtDupeEmail->fetchAll(); $stmtDupeEmail->closeCursor(); } catch (PDOException $errorData) { $errorMessage = $errorData->getMessage(); $dbDebugMsg = <<<DEBUG_EMAIL_CHECK

Debug Message: An error was encountered while checking for duplicate email accounts.

Details: $errorMessage

DEBUG_EMAIL_CHECK; return $dbDebugMsg; } #TO DO: Figure out how to detect if a row contains an email that matches #the one provided by the client. if($emailMatches) { $errMessage = "We already have an account with that email address; users are not allowed to have duplicate accounts. If this is in error, please contact our webmaster."; } // 3B. Insert Finalized Data into the database #Prepare the date information $salt = date('U'); $registerTime = date('Y-m-d'); $lastLoginTime = date('Y-m-d H:i:s'); #ENCRYPT PASSWORD AND 'SALT' IT $deliciousPassword = sha1($sanPassword) + $salt; $queryCreateUser = 'INSERT INTO `users` (userID, nameFirst, nameLast, gender, username, password, emailAddress, privilegeLevel, firstJoined, lastSeen, verified) VALUES (DEFAULT, :firstName, :lastName, NULL, :username, :password, :email, 0, :creationDateTime, :lastLogin, 0'; try { $stmtCreateUser = $dbObject->prepare($queryCreateUser); $stmtCreateUser->bindValue(':firstName', $sanFirstName); $stmtCreateUser->bindValue(':lastName', $sanLastName); $stmtCreateUser->bindValue(':username', $sanUsername); $stmtCreateUser->bindValue(':password', $deliciousPassword); $stmtCreateUser->bindValue(':email', $sanEmail); $stmtCreateUser->bindValue(':creationDateTime', $registerTime); $stmtCreateUser->bindValue(':lastLogin', $lastLoginTime); $commit = true; return $commit; } catch (PDOException $errorData) { $errorMessage = $errorData->getMessage(); $dbDebugMsg = <<<DEBUG_USER_CREATE

Debug Message: An error was encountered while checking for duplicate email accounts.

Details: $errorMessage

DEBUG_USER_CREATE; return $dbDebugMsg; } if($commit == true) { //Generate activation code $code = md5($username + $registerTime + $eMail); mail( $eMail, "$username, now a flavor at Test Site!", "Thank you for registering with us $username, \n If you did not register an account at test-site.com, please ignore this email message. Otherwise, continue reading the instructions below. \n The link below should automatically activate your account. If the link doesn't work, you may copy and paste it into your browser's address bar to activate it. \n \n http://www.test-site.com/users/activation.php?code=$code", 'From: [email protected]' ); } else { $errMessage = "A problem was encountered creating your account. We would like to apologize for this inconvenience, but please try again! In addition, an email has been sent to our webmaster and administrators regarding the issue, and should have it resolved within 48 hours."; $errorTime = date('d, m, Y @ h:m:s'); mail( '[email protected]; [email protected]', "An Error Has Been Encountered With A User's Registration", "The following error was encountered on $errorTime. \n $dbDebugMsg", 'From: [email protected]' ); } } // No Database Connection; Terminate Script !!! else { $errMessage = "We seem to be having database connection issues. Please try again later."; } } ?>

[/php]

Sponsor our Newsletter | Privacy Policy | Terms of Service