performMinimumRequirementsCheck()) {
$this->runApplication();
}
}
/**
* Performs a check for minimum requirements to run this application.
* Does not run the further application when PHP version is lower than 5.3.7
* Does include the PHP password compatibility library when PHP version lower than 5.5.0
* (this library adds the PHP 5.5 password hashing functions to older versions of PHP)
* @return bool Success status of minimum requirements check, default is false
*/
private function performMinimumRequirementsCheck()
{
if (version_compare(PHP_VERSION, '5.3.7', '<')) {
echo "Sorry, Simple PHP Login does not run on a PHP version older than 5.3.7 !";
} elseif (version_compare(PHP_VERSION, '5.5.0', '<')) {
require_once("_tools/_php_login/libraries/password_compatibility_library.php");
return true;
} elseif (version_compare(PHP_VERSION, '5.5.0', '>=')) {
return true;
}
// default return
return false;
}
/**
* This is basically the controller that handles the entire flow of the application.
*/
public function runApplication()
{
// check is user wants to see register page (etc.)
$this->doRegistration();
$this->showPageRegistration();
}
/**
* Creates a PDO database connection (in this case to a SQLite flat-file database)
* @return bool Database creation success status, false by default
*/
private function createDatabaseConnection()
{
try {
$this->db_connection = new PDO($this->db_type . ':' . $this->db_sqlite_path);
return true;
} catch (PDOException $e) {
$this->feedback = "PDO database connection problem: " . $e->getMessage();
} catch (Exception $e) {
$this->feedback = "General problem: " . $e->getMessage();
}
return false;
}
/**
* The registration flow
* @return bool
*/
private function doRegistration()
{
if ($this->checkRegistrationData()) {
if ($this->createDatabaseConnection()) {
$this->createNewUser();
}
}
// default return
return false;
}
/**
* Validates the user's registration input
* @return bool Success status of user's registration data validation
*/
private function checkRegistrationData()
{
// if no registration form submitted: exit the method
if (!isset($_POST["register"])) {
return false;
}
// validating the input
if (!empty($_POST['user_name'])
&& strlen($_POST['user_name']) <= 64
&& strlen($_POST['user_name']) >= 2
&& preg_match('/^[a-z\d]{2,64}$/i', $_POST['user_name'])
&& !empty($_POST['user_email'])
&& strlen($_POST['user_email']) <= 64
&& filter_var($_POST['user_email'], FILTER_VALIDATE_EMAIL)
&& !empty($_POST['user_password_new'])
&& !empty($_POST['user_password_repeat'])
&& ($_POST['user_password_new'] === $_POST['user_password_repeat'])
) {
// only this case return true, only this case is valid
return true;
} elseif (empty($_POST['user_name'])) {
$this->feedback = "Empty Username";
} elseif (empty($_POST['user_password_new']) || empty($_POST['user_password_repeat'])) {
$this->feedback = "Empty Password";
} elseif ($_POST['user_password_new'] !== $_POST['user_password_repeat']) {
$this->feedback = "Password and password repeat are not the same";
} elseif (strlen($_POST['user_password_new']) < 6) {
$this->feedback = "Password has a minimum length of 6 characters";
} elseif (strlen($_POST['user_name']) > 64 || strlen($_POST['user_name']) < 2) {
$this->feedback = "Username cannot be shorter than 2 or longer than 64 characters";
} elseif (!preg_match('/^[a-z\d]{2,64}$/i', $_POST['user_name'])) {
$this->feedback = "Username does not fit the name scheme: only a-Z and numbers are allowed, 2 to 64 characters";
} elseif (empty($_POST['user_email'])) {
$this->feedback = "Email cannot be empty";
} elseif (strlen($_POST['user_email']) > 64) {
$this->feedback = "Email cannot be longer than 64 characters";
} elseif (!filter_var($_POST['user_email'], FILTER_VALIDATE_EMAIL)) {
$this->feedback = "Your email address is not in a valid email format";
} else {
$this->feedback = "An unknown error occurred.";
}
// default return
return false;
}
/**
* Creates a new user.
* @return bool Success status of user registration
*/
private function createNewUser()
{
// remove html code etc. from username and email
$user_name = htmlentities($_POST['user_name'], ENT_QUOTES);
$user_email = htmlentities($_POST['user_email'], ENT_QUOTES);
$user_password = $_POST['user_password_new'];
// crypt the user's password with the PHP 5.5's password_hash() function, results in a 60 char hash string.
// the constant PASSWORD_DEFAULT comes from PHP 5.5 or the password_compatibility_library
$user_password_hash = password_hash($user_password, PASSWORD_DEFAULT);
$sql = 'SELECT * FROM users WHERE user_name = :user_name OR user_email = :user_email';
$query = $this->db_connection->prepare($sql);
$query->bindValue(':user_name', $user_name);
$query->bindValue(':user_email', $user_email);
$query->execute();
// As there is no numRows() in SQLite/PDO (!!) we have to do it this way:
// If you meet the inventor of PDO, punch him. Seriously.
$result_row = $query->fetchObject();
if ($result_row) {
$this->feedback = "Sorry, that username / email is already taken. Please choose another one.";
} else {
$sql = 'INSERT INTO users (user_name, user_password_hash, user_email)
VALUES(:user_name, :user_password_hash, :user_email)';
$query = $this->db_connection->prepare($sql);
$query->bindValue(':user_name', $user_name);
$query->bindValue(':user_password_hash', $user_password_hash);
$query->bindValue(':user_email', $user_email);
// PDO's execute() gives back TRUE when successful, FALSE when not
// @link http://stackoverflow.com/q/1661863/1114320
$registration_success_state = $query->execute();
if ($registration_success_state) {
$this->feedback = "Your account has been created successfully. You can now log in.";
return true;
} else {
$this->feedback = "Sorry, your registration failed. Please go back and try again.";
}
}
// default return
return false;
}
/**
* Simple demo-"page" with the registration form.
* In a real application you would probably include an html-template here, but for this extremely simple
* demo the "echo" statements are totally okay.
*/
private function showPageRegistration()
{
if ($this->feedback) {
echo $this->feedback . "
";
}
echo '