diff --git a/includes/components/foot.php b/includes/components/foot.php index b605728..62c2875 100755 --- a/includes/components/foot.php +++ b/includes/components/foot.php @@ -1,2 +1,5 @@ - + +'; diff --git a/includes/components/form.php b/includes/components/form.php new file mode 100644 index 0000000..9235bbf --- /dev/null +++ b/includes/components/form.php @@ -0,0 +1,46 @@ + +
+ '; + + foreach ($fields as $field => $metadata) { + if ($field == 'method' || $field == 'action') + continue; + + $form .= ' +
+ + +
+ '; + } + + $form .= ' + +
+ '; + + if (!empty($error)) { + $form .= ' +
+

' . ucwords($error) . ' information!

+
+ '; + } + + $form .= ' + + '; + + return $form; +} diff --git a/includes/components/head.php b/includes/components/head.php index ca671b6..9c59133 100755 --- a/includes/components/head.php +++ b/includes/components/head.php @@ -1,10 +1,14 @@ + - - Dummy Title - - - + + Vintage Coding + + + - + +'; +include_once('nav.php'); diff --git a/includes/components/nav.php b/includes/components/nav.php index 8a3383d..8289406 100755 --- a/includes/components/nav.php +++ b/includes/components/nav.php @@ -1,14 +1,14 @@ - - + '; echo $nav; diff --git a/includes/fields/login_fields.php b/includes/fields/login_fields.php new file mode 100644 index 0000000..5f796b1 --- /dev/null +++ b/includes/fields/login_fields.php @@ -0,0 +1,25 @@ + 'post', + 'action' => 'process.php?action=login', + 'login_username' => [ + 'label' => 'username', + 'type' => 'text', + 'placeholder' => 'e.g., jsmith', + 'validators' => [ + 'no_spaces', + // 'check_sql', + ], + ], + 'login_password' => [ + 'label' => 'password', + 'type' => 'password', + 'placeholder' => '', + 'validators' => [ + 'no_spaces', + // 'pw_strength', + // 'no_backslash', + // 'check_sql', + ], + ], +]; diff --git a/includes/functions.php b/includes/functions.php index cd07e55..79515a2 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -1,4 +1,30 @@ + ' . print_r($input) . ' + + '; +} diff --git a/includes/input_validation.php b/includes/input_validation.php new file mode 100755 index 0000000..7331ca7 --- /dev/null +++ b/includes/input_validation.php @@ -0,0 +1,239 @@ + [ + * // Placeholder text + * 'e.g., jsmith', + * + * // Validation requirements + * [ + * 'no_spaces', + * 'checkSQL', + * ], + * ], + * ]; + * + * EXAMPLE CLIENT IMPLEMENTATION + * + * function validate($standard_fields, $admin_fields) { + * include('includes/input_validation.php'); + * $error = ''; + * foreach($standard_fields as $field => $arr) { + * // Get the requirements from the associative array. + * $validationRequirements = $arr[1]; + * + * foreach($validationRequirements as $validReq) { + * switch($validReq) { + * case 'no_spaces': + * if(no_spaces($_POST[$field])) { + * $error .= '

' . $field . ' does not allow spaces.

'; + * } + * break; + * default: + * $error .= '

Something went wrong...

'; + * break; + * } + * } + * } + * } + */ + +function no_spaces($input) +{ + return !str_contains($input, ' '); +} + +function no_digits($input) +{ + for ($i = 0; $i < strlen($input); $i++) + if (is_numeric($input[$i])) + return false; + return true; +} + +function no_backslash($input) +{ + for ($i = 0; $i < strlen($input); $i++) + if ($input[$i] === '\\') + return false; + return true; +} + +/* + * This checks for the following characters: + * ' ' ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ + * \ ] ^ _ ` { | } ~ + * + * TODO: Add support for additional special characters available through + * other means. + */ +function no_special($input) +{ + $special = [ + '!', + '"', + '#', + '$', + '%', + '&', + "'", + '(', + ')', + '*', + '+', + ',', + '-', + '.', + '/', + ':', + ';', + '<', + '=', + '>', + '?', + '@', + '[', + '\\', + ']', + '^', + '_', + '`', + '{', + '|', + '}', + '~', + ]; + + for ($i = 0; $i < strlen($input); $i++) + if (in_array($input[$i], $special)) + return false; + + return true; +} + +function only_digits($input) +{ + for ($i = 0; $i < strlen($input); $i++) + if (!is_numeric($input[$i])) + return false; + + return true; +} + +function only_digits_x($input, $x) +{ + if (strlen($input) != $x) + return false; + + for ($i = 0; $i < strlen($input); $i++) + if (!is_numeric($input[$i])) + return false; + + return true; +} + +function only_letters($input) +{ + return (preg_match('/[^A-Za-z]*/', $input) == 1 ? true : false); +} + +function only_letters_x($input, $x) +{ + if (strlen($input) != $x) + return false; + + return (preg_match('/[^A-Za-z]*/', $input) ? true : false); +} + +// TODO: Add additional step which tests if the email exists. +function valid_email($input) +{ + if (!str_contains($input, '@')) + return false; + + $email = explode('@', $input); + if (count($email) != 2) + return false; + + return true; +} + +/* + * Note: While this function handles the most common variations of a phone + * number (and potential missed or inconsistent entry), it does not apply + * any formatting. The client must handle data consistency themselves. + */ +function valid_phone($input) +{ + $formats = [ + '/^\d{10}$/', // xxxxxxxxxx + '/^\d{3}-\d{7}$/', // xxx-xxxxxxx + '/^\d{6}-\d{4}$/', // xxxxxx-xxxx + '/^\d{3}-\d{3}-\d{4}$/', // xxx-xxx-xxxx + '/^\(\d{3}\)\d{7}$/', // (xxx)xxxxxxx + '/^\(\d{3}\)\d{3}-\d{4}$/', // (xxx)xxx-xxxx + '/^\(\d{3}\) \d{3}-\d{4}$/', // (xxx) xxx-xxxx + '/^\(\d{3}\)\d{3} -\d{4}$/', // (xxx)xxx -xxxx + '/^\(\d{3}\)\d{3}- \d{4}$/', // (xxx)xxx- xxxx + '/^\(\d{3}\)\d{3} - \d{4}$/', // (xxx)xxx - xxxx + '/^\(\d{3}\) \d{3} -\d{4}$/', // (xxx) xxx -xxxx + '/^\(\d{3}\) \d{3}- \d{4}$/', // (xxx) xxx- xxxx + '/^\(\d{3}\) \d{3} - \d{4}$/', // (xxx) xxx - xxxx + '/^\d{3} \d{7}$/', // xxx xxxxxxx + '/^\d{6} \d{4}$/', // xxxxxx xxxx + '/^\d{3} \d{3} \d{4}$/', // xxx xxx xxxx + '/^\d{3} \d{3}-\d{4}$/', // xxx xxx-xxxx + '/^\d{3}-\d{3} \d{4}$/', // xxx-xxx xxxx + '/^\d{3}\.\d{7}$/', // xxx.xxxxxxx + '/^\d{6}\.\d{4}$/', // xxxxxx.xxxx + '/^\d{3}\.\d{3}\.\d{4}$/', // xxx.xxx.xxxx + ]; + + foreach ($formats as $regex) + if (preg_match($regex, $input)) + return true; + + return false; +} + +/* + * TODO: This should ensure the user's password consists of the following: + * - length > 8, + * - 1+ uppercase letters, + * - 1+ lowercase letters, + * - 1+ digits, + * - 1+ special characters + */ +function pw_strength($input) +{ + return true; +} + +/* + * TODO: Need to implement SQL Injection prevention. + * + * Note: This should have the additional step of blacklisting a user who + * attempts SQL Injection. At least adding any valid submitted information + * to a DB table in case they attempt to create a 'valid' account, or + * flagging a 'valid' account that attempts SQL Injection. This will require + * a lot of research and therefore time. For now, since this isn't public + * facing, I'll operate with some trust in the user. + * + * Also, this might be better in a database functions file instead. + */ +function check_sql($input) +{ + return false; +} diff --git a/includes/sql.php b/includes/sql.php index 65eb236..fbe262e 100755 --- a/includes/sql.php +++ b/includes/sql.php @@ -26,6 +26,30 @@ function get_all_accounts() return $results; } +function get_account_login($username) +{ + $conn = mysqli_connect(HOST, USER, PASS, DB); + $query = 'SELECT password_hash FROM accounts WHERE username = "' . $username . '";'; + $results = mysqli_query($conn, $query); + return $results; +} + +function get_account_info($username) +{ + $conn = mysqli_connect(HOST, USER, PASS, DB); + $query = 'SELECT * FROM accounts WHERE username = "' . $username . '";'; + $results = mysqli_query($conn, $query); + return $results; +} + +function get_account_role($username) +{ + $conn = mysqli_connect(HOST, USER, PASS, DB); + $query = 'SELECT * FROM accounts WHERE username = "' . $username . '";'; + $results = mysqli_query($conn, $query); + return $results; +} + function get_all_article_cards() { $conn = mysqli_connect(HOST, USER, PASS, DB); diff --git a/index.php b/index.php index 879cdcf..5836aeb 100755 --- a/index.php +++ b/index.php @@ -1,7 +1,6 @@ Home'; + +include_once('../includes/components/foot.php'); diff --git a/process.php b/process.php new file mode 100644 index 0000000..7c59050 --- /dev/null +++ b/process.php @@ -0,0 +1,114 @@ + $value) { + if (!validate($value, $login_fields[$field]['validators'])) + header('Location: ' . $error_location . 'invalid'); + } + + $username = $_POST['login_username']; + $password_hash = hash('sha256', $_POST['login_password']); + + // If username/password hash are incorrect, redirect to login with error state. + if (!authorize($username, $password_hash)) + header('Location: ' . $error_location . 'incorrect'); + + unset($_POST['login_username']); + unset($_POST['login_password']); + + // auth() handles setting $_SESSION variables, user is now OK to proceed to home.php. + // header('Location: ' . $success_location); + default: + // code... + break; +} + +function validate($input, $validators) +{ + include_once('includes/input_validation.php'); + + foreach ($validators as $v) { + switch ($v) { + case 'no_spaces': + if (!no_spaces($input)) + return false; + break; + + case 'no_digits': + if (!no_digits($input)) + return false; + break; + + case 'no_backslash': + if (!no_backslash($input)) + return false; + break; + + case 'no_special': + if (!no_special($input)) + return false; + break; + + case 'only_digits': + if (!only_digits($input)) + return false; + break; + + // TODO: Need to get x. + case 'only_digits_x': + if (!only_digits_x($input, 5)) + return false; + break; + + case 'only_letters': + if (!only_letters($input)) + return false; + break; + + // TODO: Need to get x. + case 'only_letters_x': + if (!only_letters_x($input, 5)) + return false; + break; + + case 'valid_email': + if (!valid_email($input)) + return false; + break; + + case 'valid_phone': + if (!valid_phone($input)) + return false; + break; + + case 'pw_strength': + if (!pw_strength($input)) + return false; + break; + + case 'check_sql': + if (check_sql($input)) + return false; + break; + } + } + + return true; +}