Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements for account creation script #6

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,15 @@
Projects created for use with the TrinityCore World of Warcraft emulator: https://www.trinitycore.org/

# Requirements
gmp module is required to be enabled in PHP. On linux this means either `sudo apt install php-gmp` or editing the default php.ini and uncomment the `extension=gmp` line

#### PHP Version >= 5.0.0

[gmp](https://www.php.net/manual/en/book.gmp.php) module is required to be enabled in PHP.
* On Linux do `sudo apt install php-gmp`
* On Windows you should have `php_gmp.dll` in your extensions folder of your PHP installation
* Edit the default php.ini and uncomment the `extension=gmp` line.

[pdo_mysql](https://www.php.net/manual/en/ref.pdo-mysql.php) module is required to be enabled in PHP.
* On Linux do `sudo apt install php-mysql`
* On Windows you should have `php_pdo_mysql.dll` in your extensions folder of your PHP installation
* Edit the default php.ini and uncomment the `extension=pdo_mysql` line.
7 changes: 7 additions & 0 deletions Trinity Account Creator/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@
/>
</form>
</div>
<!--
<div class="container formContainer">
<div>
<p>Realmlist: 127.0.0.1</p>
</div>
</div>
-->
</main>

<!-- Footer -->
Expand Down
66 changes: 46 additions & 20 deletions Trinity Account Creator/js/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,49 @@ function submitForm() {

// Create a callback function.
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
// Transaction was successful.
if (xhr.responseText == '0') {
// Reset the form first.
document.getElementById('accountForm').reset();

// Update the status message.
document.getElementById('statusMessage').value =
'Account created successfully!';
document.getElementById('statusMessage').style.color = 'green';
} else if (xhr.responseText == '1') {
document.getElementById('statusMessage').value = 'Email is invalid.';
document.getElementById('statusMessage').style.color = 'yellow';
} else if (xhr.responseText == '2') {
document.getElementById('statusMessage').value =
'Account already exists.';
document.getElementById('statusMessage').style.color = 'red';
} else if (xhr.responseText == '3') {
document.getElementById('statusMessage').value =
'Unknown error occurred.<br>Please try again.';
if (xhr.readyState == 4) {
if (xhr.status == 200) {
// Transaction was successful.
if (xhr.responseText == '0') {
// Reset the form first.
document.getElementById('accountForm').reset();

// Update the status message.
document.getElementById('statusMessage').value = 'Account created successfully!';
document.getElementById('statusMessage').style.color = 'green';
} else if (xhr.responseText == '1') {
document.getElementById('statusMessage').value = 'Account already exists.';
document.getElementById('statusMessage').style.color = 'red';
} else if (xhr.responseText == '2') {
document.getElementById('statusMessage').value = 'Connection failed.';
document.getElementById('statusMessage').style.color = 'red';
} else if (xhr.responseText == '3') {
document.getElementById('statusMessage').value = 'Username is empty.';
document.getElementById('statusMessage').style.color = 'yellow';
} else if (xhr.responseText == '4') {
document.getElementById('statusMessage').value = 'Username is invalid.';
document.getElementById('statusMessage').style.color = 'yellow';
} else if (xhr.responseText == '5') {
document.getElementById('statusMessage').value = 'Username is too long.';
document.getElementById('statusMessage').style.color = 'yellow';
} else if (xhr.responseText == '6') {
document.getElementById('statusMessage').value = 'Password is empty.';
document.getElementById('statusMessage').style.color = 'yellow';
} else if (xhr.responseText == '7') {
document.getElementById('statusMessage').value = 'Password is too long.';
document.getElementById('statusMessage').style.color = 'yellow';
} else if (xhr.responseText == '8') {
document.getElementById('statusMessage').value = 'Email is empty.';
document.getElementById('statusMessage').style.color = 'yellow';
} else if (xhr.responseText == '9') {
document.getElementById('statusMessage').value = 'Email is invalid.';
document.getElementById('statusMessage').style.color = 'yellow';
} else {
document.getElementById('statusMessage').value = 'Unknown error occurred.';
document.getElementById('statusMessage').style.color = 'red';
}
} else {
document.getElementById('statusMessage').value = 'Unknown error occurred.';
document.getElementById('statusMessage').style.color = 'red';
}
}
Expand All @@ -59,3 +82,6 @@ $('#accountForm').submit(function(event) {
// Cancel the form submission, so we can use AJAX instead.
event.preventDefault();
});

// Reset status message on page reload
document.getElementById('statusMessage').value = '';
81 changes: 81 additions & 0 deletions Trinity Account Creator/php/compat_random.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

function bytelen($str) {
if (defined('MB_OVERLOAD_STRING') && (ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING) && extension_loaded('mbstring')) {
return mb_strlen($str, '8bit');
} else {
return strlen($str);
}
}

if (!is_callable('random_bytes')) {
if (is_callable('gmp_random_bits')) {
function random_bytes($b) {
$rand = '';
for ($i = 1; $i <= $b; $i++) {
$rand .= chr(gmp_intval(gmp_random_bits(8)));
}
return ($rand !== false && bytelen($rand) == $b) ? $rand : null;
}
} else if (is_callable('openssl_random_pseudo_bytes')) {
function random_bytes($b) {
$rand = openssl_random_pseudo_bytes($b);
return ($rand !== false && bytelen($rand) == $b) ? $rand : null;
}
} else if (is_callable('mcrypt_create_iv')) {
if (DIRECTORY_SEPARATOR === '/') {
function random_bytes($b) {
$rand = mcrypt_create_iv($b, MCRYPT_DEV_URANDOM);
return ($rand !== false && bytelen($rand) == $b) ? $rand : null;
}
} else {
function random_bytes($b) {
$rand = mcrypt_create_iv($b);
return ($rand !== false && bytelen($rand) == $b) ? $rand : null;
}
}
} else if (DIRECTORY_SEPARATOR === '/') {
$stat = @stat('/dev/urandom');
if ($stat !== false && ($stat['mode'] & 0170000) === 020000) {
function random_bytes($b) {
$rand = @file_get_contents('/dev/urandom', false, null, 0, $b);
return ($rand !== false && bytelen($rand) == $b) ? $rand : null;
}
}
} elseif (class_exists('\\COM')) {
try {
$util = new COM('CAPICOM.Utilities.1');
$method = array($util, 'GetRandom');
if (is_callable($method)) {
function random_bytes($b) {
$util = new \COM('CAPICOM.Utilities.1');
$rand = base64_decode($util->GetRandom($b,0));
$rand = str_pad($rand, $b, chr(0));
return ($rand !== false && bytelen($rand) == $b) ? $rand : null;
}
}
} catch (Exception $e) { }
}

if (!is_callable('random_bytes')) {
if (is_callable('mt_rand')) {
function random_bytes($b) {
$rand = '';
for ($i = 1; $i <= $b; $i++) {
$rand .= chr(mt_rand(0,255));
}
return ($rand !== false && bytelen($rand) == $b) ? $rand : null;
}
} else {
function random_bytes($b) {
$rand = '';
for ($i = 1; $i <= $b; $i++) {
$rand .= chr(rand(0,255));
}
return ($rand !== false && bytelen($rand) == $b) ? $rand : null;
}
}
}
}

?>
130 changes: 85 additions & 45 deletions Trinity Account Creator/php/createAccount.php
Original file line number Diff line number Diff line change
@@ -1,83 +1,123 @@
<?php

require_once(dirname(__FILE__) . '/vars.php');
require_once(dirname(__FILE__) . '/db.php');

$db = new db();

if (class_exists('db')) {
$db = new db();
}
else {
echo "-1"; // Unknown error occured.
error_log("Error: Class db() could not be initialized.");
return;
}

if (!$db->isOpen()) {
echo "2"; // Connection failed
return;
}

// Get POST data and validate.
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = validateInput($_POST['username']);
$email = validateInput($_POST['email']);
$password = validateInput($_POST['password']);
}

if (!isset($username) || !is_string($username))
throw new InvalidArgumentException("Username is invalid or empty.");

if (!isset($password) || !is_string($password))
throw new InvalidArgumentException("Password is invalid or empty.");

if (!isset($email))
throw new InvalidArgumentException("Email is empty.");

$username = trim($_POST['username']);
$email = trim($_POST['email']);
$password = $_POST['password'];
}

if (!isset($username) || !is_string($username) || empty($username)) {
echo "3"; // Username is empty.
return;
}
$username = validateInput($username);
if (!isset($username)) {
echo "4"; // Username is invalid.
return;
}

// username has 16 byte limit on TC server
if (strlen($username) > 16) {
echo "5"; // Username is too long.
return;
}

if (!isset($password) || !is_string($password) || empty($password)) {
echo "6"; // Password is empty.
return;
}

// password has a 16 character limit on 3.3.5.12340 client even when SRP6 does not have such limitation
if (strlen($password) > 64 || iconv_strlen($password, 'utf-8') > 16) {
echo "7"; // Password is too long.
return;
}

if (!isset($email)) {
echo "8"; // Email is empty.
return;
}
if (strlen($email) > 255) {
echo "9"; // Email is invalid.
return;
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo "1"; // Returns that email is invalid, to update status message.
echo "9"; // Email is invalid.
return;
}

$username = $db->strtoupper_az($username);
$email = $db->strtoupper_az($email);

try {

// First, we need to check if the account name already exists.
$accountCheckQuery = "SELECT * FROM account WHERE username = ?";
$accountCheckParams = array($username);

$results = $db->queryMultiRow($accountCheckQuery, $accountCheckParams);

if ($db->getRowCount($results) > 0) {

// Account already exists, inform user and stop transaction.
echo "2";
echo "1";

// Close connection to the database.
$db->close();

return;
}

// If no account exists, create a new one.
// Get the SHA1 encrypted password.

// Get the SRP6 salt and verifier tokens
list($salt, $verifier) = $db->getRegistrationData($username, $password);
$accountCreateQuery = "INSERT INTO account(username, salt, verifier, email) VALUES(?, ?, ?, ?)";
$accountCreateParams = array($username, $salt, $verifier, $email);

$accountCreateQuery = "INSERT INTO account(username, salt, verifier, reg_mail, email) VALUES(?, ?, ?, ?, ?)";
$accountCreateParams = array($username, $salt, $verifier, $email, $email);

// Execute the query.
$db->insertQuery($accountCreateQuery, $accountCreateParams);

// Close connection to the database.
$db->close();


//error_log("Account created: '" . $username . "' '". $email . "'");

// Return successful to AJAX call.
echo "0";

echo "0"; // Account created successfully!
}
catch(PDOException $e) {
echo "3"; // Update status message with unknown error occurred.
error_log("PDO Database error occurred: " . $e->getMessage());
echo "-1"; // Unknown error occured.
error_log("Database error: " . $e->getMessage());
}
catch (Exception $e) {
echo "3"; // Update status message with unknown error occurred.
error_log("Unknown error occurred: " . $e->getMessage());
echo "-1"; // Unknown error occured.
error_log("Unknown error: " . $e->getMessage());
}

// Validates POST input data.
function validateInput($param) {
$param = trim($param);
$param = stripslashes($param);
$param = htmlspecialchars($param);

return $param;
}
function validateInput($param) {
$valid = stripslashes($param);
$valid = htmlspecialchars($valid, ENT_QUOTES);
$valid = preg_replace('/\s+/', '', $valid);

return ($param == $valid) ? $param : null;
}
?>
Loading