Skip to content
Open
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 = '';
99 changes: 99 additions & 0 deletions Trinity Account Creator/php/compat_random.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?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('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;
}
}
} else if (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 = ($rand !== false) ? str_pad($rand, $b, chr(0)) : false;
return ($rand !== false && bytelen($rand) == $b) ? $rand : null;
}
}
} catch (Exception $e) { }
}

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('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;
}
}
}
}

if (!is_callable('random_int')) {
if (is_callable('gmp_random_range')) {
function random_int($min, $max) {
return gmp_intval(gmp_random_range($min, $max));
}
} elseif (is_callable('mt_rand')) {
function random_int($min, $max) {
mt_srand(random_bytes(3));
return mt_rand($min, $max);
}
} elseif (is_callable('rand')) {
function random_int($min, $max) {
srand(random_bytes(3));
return rand($min, $max);
}
}
}

?>
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