Compare commits

..

16 Commits

Author SHA1 Message Date
slawkens
c6ddcf829e Change message 2025-10-12 10:14:43 +02:00
slawkens
cbb88413d9 Nothing important: change variable name 2025-10-12 10:14:35 +02:00
slawkens
2a2512f5d0 Merge branch 'main' into feature/resend-email-verify 2025-10-12 00:15:18 +02:00
slawkens
9acad15451 Allow links in error_box 2025-10-12 00:15:04 +02:00
slawkens
9a0ec33f6d feat: Resend Email Verify
+ rework the whole concept, based on new table for email hashes
This make it possible that every email will work, not matter if first or last
2025-10-12 00:14:41 +02:00
slawkens
8c3cb0e06f New configurable: hooks_debug
To view where hooks are located in .twig files
2025-10-11 18:34:15 +02:00
slawkens
2eae44e075 Add missing compat config: email_lai_sec_interval 2025-10-08 14:39:23 +02:00
slawkens
8272f1373c Fix database column info cache 2025-10-03 16:24:02 +02:00
slawkens
901df48d13 Add promotion into getTopPlayers 2025-10-03 00:31:03 +02:00
slawkens
2da0024c68 Add lookmount into getTopPlayers 2025-10-03 00:25:41 +02:00
slawkens
0d8f68a48e Fix menus for ?subtopic= 2025-10-02 22:31:16 +02:00
slawkens
0cb9d3a208 Fix routes_final cache 2025-10-02 22:31:02 +02:00
slawkens
d8b73f55a3 Fix routes_final for prod env 2025-10-02 22:16:29 +02:00
slawkens
3bb272ebbb Allow for img in online_datacenter 2025-10-02 22:13:33 +02:00
slawkens
64acf70d38 Cache::remember -1 = infinite 2025-10-02 22:13:15 +02:00
slawkens
97f9d3d6f6 Add option to use ?subtopic=x for plugins pages 2025-10-02 15:06:57 +02:00
46 changed files with 892 additions and 975 deletions

View File

@@ -27,7 +27,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is
const MYAAC = true;
const MYAAC_VERSION = '1.8.3-dev';
const DATABASE_VERSION = 45;
const DATABASE_VERSION = 46;
const TABLE_PREFIX = 'myaac_';
define('START_TIME', microtime(true));
define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));

View File

@@ -1,4 +1,4 @@
SET @myaac_database_version = 45;
SET @myaac_database_version = 46;
CREATE TABLE `myaac_account_actions`
(
@@ -10,6 +10,15 @@ CREATE TABLE `myaac_account_actions`
KEY (`account_id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_account_emails_verify`
(
`id` int NOT NULL AUTO_INCREMENT,
`account_id` int NOT NULL,
`hash` varchar(32) NOT NULL,
`sent_at` int NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_admin_menu`
(
`id` int NOT NULL AUTO_INCREMENT,

View File

@@ -102,18 +102,13 @@ if(!$db->hasColumn('accounts', 'web_flags')) {
success($locale['step_database_adding_field'] . ' accounts.web_flags...');
}
if(!$db->hasColumn('accounts', 'email_hash')) {
if(query("ALTER TABLE `accounts` ADD `email_hash` VARCHAR(32) NOT NULL DEFAULT '' AFTER `web_flags`;"))
success($locale['step_database_adding_field'] . ' accounts.email_hash...');
}
if(!$db->hasColumn('accounts', 'email_verified')) {
if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `email_hash`;"))
if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `web_flags`;"))
success($locale['step_database_adding_field'] . ' accounts.email_verified...');
}
if(!$db->hasColumn('accounts', 'email_new')) {
if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_hash`;"))
if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_verified`;"))
success($locale['step_database_adding_field'] . ' accounts.email_new...');
}

View File

@@ -81,6 +81,7 @@ $deprecatedConfig = [
'account_change_character_name_points' => 'account_change_character_name_price',
'account_change_character_sex',
'account_change_character_sex_points' => 'account_change_character_name_price',
'email_lai_sec_interval' => 'mail_lost_account_interval',
];
foreach ($deprecatedConfig as $key => $value) {

View File

@@ -1142,10 +1142,18 @@ function getTopPlayers($limit = 5, $skill = 'level') {
'looktype', 'lookhead', 'lookbody', 'looklegs', 'lookfeet'
];
if ($db->hasColumn('players', 'promotion')) {
$columns[] = 'promotion';
}
if ($db->hasColumn('players', 'lookaddons')) {
$columns[] = 'lookaddons';
}
if ($db->hasColumn('players', 'lookmount')) {
$columns[] = 'lookmount';
}
return Player::query()
->select($columns)
->withOnlineStatus()

View File

@@ -120,6 +120,11 @@ class OTS_DB_MySQL extends OTS_Base_DB
if($cache->fetch('database_columns', $tmp) && $tmp) {
$this->has_column_cache = unserialize($tmp);
}
$tmp = null;
if($cache->fetch('database_columns_info', $tmp) && $tmp) {
$this->get_column_info_cache = unserialize($tmp);
}
}
}
@@ -156,11 +161,13 @@ class OTS_DB_MySQL extends OTS_Base_DB
if ($this->clearCacheAfter) {
$cache->delete('database_tables');
$cache->delete('database_columns');
$cache->delete('database_columns_info');
$cache->delete('database_checksum');
}
else {
$cache->set('database_tables', serialize($this->has_table_cache), 3600);
$cache->set('database_columns', serialize($this->has_column_cache), 3600);
$cache->set('database_columns_info', serialize($this->get_column_info_cache), 3600);
$cache->set('database_checksum', serialize(sha1($config['database_host'] . '.' . $config['database_name'])), 3600);
}
}
@@ -295,7 +302,8 @@ class OTS_DB_MySQL extends OTS_Base_DB
return [];
}
public function revalidateCache() {
public function revalidateCache(): void
{
foreach($this->has_table_cache as $key => $value) {
$this->hasTableInternal($key);
}
@@ -310,6 +318,21 @@ class OTS_DB_MySQL extends OTS_Base_DB
$this->hasColumnInternal($explode[0], $explode[1]);
}
}
foreach($this->get_column_info_cache as $key => $value) {
$explode = explode('.', $key);
if(!isset($this->has_table_cache[$explode[0]])) { // first check if table exist
$this->hasTableInternal($explode[0]);
}
if($this->has_table_cache[$explode[0]]) {
$this->hasColumnInternal($explode[0], $explode[1]);
}
if($this->has_table_cache[$explode[0]]) {
$this->getColumnInfoInternal($explode[0], $explode[1]);
}
}
}
public function setClearCacheAfter($clearCache)

View File

@@ -0,0 +1,8 @@
CREATE TABLE `myaac_account_emails_verify`
(
`id` int NOT NULL AUTO_INCREMENT,
`account_id` int NOT NULL,
`hash` varchar(32) NOT NULL,
`sent_at` int NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;

24
system/migrations/46.php Normal file
View File

@@ -0,0 +1,24 @@
<?php
/**
* @var OTS_DB_MySQL $db
*/
$up = function () use ($db) {
if ($db->hasColumn('accounts', 'email_hash')) {
$db->dropColumn('accounts', 'email_hash');
}
if (!$db->hasTable(TABLE_PREFIX . 'account_emails_verify')) {
$db->query(file_get_contents(__DIR__ . '/46-account_emails_verify.sql'));
}
};
$down = function () use ($db) {
if (!$db->hasColumn('accounts', 'email_hash')) {
$db->addColumn('accounts', 'email_hash', "varchar(32) NOT NULL DEFAULT ''");
}
if ($db->hasTable(TABLE_PREFIX . 'account_emails_verify')) {
$db->dropTable(TABLE_PREFIX . 'account_emails_verify');
}
};

View File

@@ -9,6 +9,7 @@
*/
use MyAAC\Models\Account;
use MyAAC\Models\AccountEmailVerify;
defined('MYAAC') or die('Direct access not allowed!');
@@ -20,16 +21,20 @@ if(empty($hash)) {
return;
}
if(!Account::where('email_hash', $hash)->exists()) {
note("Your email couldn't be verified. Please contact staff to do it manually.");
// by default link is valid for 30 days
$accountEmailVerify = AccountEmailVerify::where('hash', $hash)->where('sent_at', '>', time() - 30 * 24 * 60 * 60)->first();
if(!$accountEmailVerify) {
note("Wrong link or link has expired.");
}
else
{
$accountModel = Account::where('email_hash', $hash)->where('email_verified', 0)->first();
$accountModel = Account::where('id', $accountEmailVerify->account_id)->where('email_verified', 0)->first();
if ($accountModel) {
$accountModel->email_verified = 1;
$accountModel->save();
AccountEmailVerify::where('account_id', $accountModel->id)->delete();
success('You have now verified your e-mail, this will increase the security of your account. Thank you for doing this. You can now <a href=' . getLink('account/manage') . '>log in</a>.');
$account = new OTS_Account();
@@ -39,6 +44,6 @@ else
}
}
else {
error('Link has expired.');
error('Your account is already verified.');
}
}

View File

@@ -10,6 +10,7 @@
*/
use MyAAC\CreateCharacter;
use MyAAC\Models\AccountEmailVerify;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Create Account';
@@ -244,7 +245,12 @@ if($save)
if(setting('core.mail_enabled') && setting('core.account_mail_verify'))
{
$hash = md5(generateRandomString(16, true, true) . $email);
$new_account->setCustomField('email_hash', $hash);
AccountEmailVerify::create([
'account_id' => $new_account->getId(),
'hash' => $hash,
'sent_at' => time(),
]);
$verify_url = getLink('account/confirm-email/' . $hash);
$body_html = $twig->render('mail.account.verify.html.twig', array(

View File

@@ -48,7 +48,9 @@ if(!empty($login_account) && !empty($login_password))
)
{
if (setting('core.account_mail_verify') && (int)$account_logged->getCustomField('email_verified') !== 1) {
$errors[] = 'Your account is not verified. Please verify your email address. If the message is not coming check the SPAM folder in your E-Mail client.';
$link = getLink('account/resend-email-verify');
$errors[] = 'Your account is not verified. Please verify your email address. If the message is not coming check the SPAM folder in your E-Mail client.<br/>' .
'You can resend the Email here: <a href="' . $link . '">' . $link . '</a>';
} else {
session_regenerate_id();
setSession('account', $account_logged->getId());

View File

@@ -9,11 +9,540 @@
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Lost Account';
$title = 'Lost Account Interface';
if(!setting('core.mail_enabled')) {
echo "<b>Account maker is not configured to send e-mails, you can't use Lost Account Interface. Contact with admin to get help.</b>";
if(!setting('core.mail_enabled'))
{
echo '<b>Account maker is not configured to send e-mails, you can\'t use Lost Account Interface. Contact with admin to get help.</b>';
return;
}
$twig->display('account/lost/form.html.twig');
$action_type = isset($_REQUEST['action_type']) ? $_REQUEST['action_type'] : '';
if($action == '')
{
$twig->display('account.lost.form.html.twig');
}
else if($action == 'step1' && $action_type == '') {
$twig->display('account.lost.noaction.html.twig');
}
elseif($action == 'step1' && $action_type == 'email')
{
$nick = stripslashes($_REQUEST['nick']);
if(Validator::characterName($nick))
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded())
$account = $player->getAccount();
if($account->isLoaded())
{
if($account->getCustomField('email_next') < time())
echo 'Please enter e-mail to account with this character.<BR>
<form action="' . getLink('account/lost') . '?action=sendcode" method=post>
<input type=hidden name="character">
<table cellspacing=1 cellpadding=4 border=0 width=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Please enter e-mail to account</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
Character: <INPUT TYPE=text NAME="nick" VALUE="'.$nick.'" SIZE="40" readonly="readonly"><BR>
E-mail to account:<INPUT TYPE=text NAME="email" VALUE="" SIZE="40"><BR>
</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
' . $twig->render('buttons.submit.html.twig') . '</div>
</TD></TR></FORM></TABLE></TABLE>';
else
{
$insec = (int)$account->getCustomField('email_next') - time();
$minutesleft = floor($insec / 60);
$secondsleft = $insec - ($minutesleft * 60);
$timeleft = $minutesleft.' minutes '.$secondsleft.' seconds';
echo 'Account of selected character (<b>'.$nick.'</b>) received e-mail in last '.ceil(setting('core.mail_lost_account_interval') / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.';
}
}
else
echo 'Player or account of player <b>' . $nick . '</b> doesn\'t exist.';
}
else
echo 'Invalid player name format. If you have other characters on account try with other name.';
echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<a href="' . getLink('account/lost') . '" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
</TD></TR></FORM></TABLE></TABLE>';
}
elseif($action == 'sendcode')
{
$email = $_REQUEST['email'];
$nick = stripslashes($_REQUEST['nick']);
if(Validator::characterName($nick))
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded())
$account = $player->getAccount();
if($account->isLoaded())
{
if($account->getCustomField('email_next') < time())
{
if($account->getEMail() == $email)
{
$newcode = generateRandomString(30, true, false, true);
$mailBody = '
You asked to reset your ' . $config['lua']['serverName'] . ' password.<br/>
<p>Account name: '.$account->getName().'</p>
<br />
To do so, please click this link:
<p><a href="' . getLink('account/lost') . '?action=checkcode&code='.$newcode.'&character='.urlencode($nick).'">' . getLink('account/lost') . '?action=checkcode&code='.$newcode.'&character='.urlencode($nick).'</a></p>
<p>or open page: <i>' . getLink('account/lost') . '?action=checkcode</i> and in field "code" write <b>'.$newcode.'</b></p>
<br/>
<p>If you did not request a password change, you may ignore this message and your password will remain unchanged.';
$account_mail = $account->getCustomField('email');
if(_mail($account_mail, $config['lua']['serverName'].' - Recover your account', $mailBody))
{
$account->setCustomField('email_code', $newcode);
$account->setCustomField('email_next', (time() + setting('core.mail_lost_account_interval')));
echo '<br />Details about steps required to recover your account has been sent to <b>' . $account_mail . '</b>. You should receive this email within 15 minutes. Please check your inbox/spam directory.';
}
else
{
$account->setCustomField('email_next', (time() + 60));
echo '<br /><p class="error">An error occurred while sending email! Try again later or contact with admin. For Admin: More info can be found in system/logs/mailer-error.log</p>';
}
}
else
echo 'Invalid e-mail to account of character <b>'.$nick.'</b>. Try again.';
}
else
{
$insec = (int)$account->getCustomField('email_next') - time();
$minutesleft = floor($insec / 60);
$secondsleft = $insec - ($minutesleft * 60);
$timeleft = $minutesleft.' minutes '.$secondsleft.' seconds';
echo 'Account of selected character (<b>'.$nick.'</b>) received e-mail in last '.ceil(setting('core.mail_lost_account_interval') / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.';
}
}
else
echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
}
else
echo 'Invalid player name format. If you have other characters on account try with other name.';
echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<a href="' . getLink('account/lost') . '?action=step1&action_type=email&nick='.urlencode($nick).'" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
</TD></TR></FORM></TABLE></TABLE>';
}
elseif($action == 'step1' && $action_type == 'reckey')
{
$nick = stripslashes($_REQUEST['nick']);
if(Validator::characterName($nick))
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded())
$account = $player->getAccount();
if($account->isLoaded())
{
$account_key = $account->getCustomField('key');
if(!empty($account_key))
{
echo 'If you enter right recovery key you will see form to set new e-mail and password to account. To this e-mail will be send your new password and account name.<BR>
<FORM ACTION="' . getLink('account/lost') . '?action=step2" METHOD=post>
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Please enter your recovery key</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
Character name:&nbsp;<INPUT TYPE=text NAME="nick" VALUE="'.$nick.'" SIZE="40" readonly="readonly"><BR />
Recovery key:&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE=text NAME="key" VALUE="" SIZE="40"><BR>
</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
' . $twig->render('buttons.submit.html.twig') . '</div>
</TD></TR></FORM></TABLE></TABLE>';
}
else
echo 'Account of this character has no recovery key!';
}
else
echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
}
else
echo 'Invalid player name format. If you have other characters on account try with other name.';
echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<a href="' . getLink('account/lost') . '" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
</TD></TR></FORM></TABLE></TABLE>';
}
elseif($action == 'step2')
{
$rec_key = trim($_REQUEST['key']);
$nick = stripslashes($_REQUEST['nick']);
if(Validator::characterName($nick))
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded())
$account = $player->getAccount();
if($account->isLoaded())
{
$account_key = $account->getCustomField('key');
if(!empty($account_key))
{
if($account_key == $rec_key)
{
echo '<script type="text/javascript">
function validate_required(field,alerttxt)
{
with (field)
{
if (value==null||value==""||value==" ")
{alert(alerttxt);return false;}
else {return true}
}
}
function validate_email(field,alerttxt)
{
with (field)
{
apos=value.indexOf("@");
dotpos=value.lastIndexOf(".");
if (apos<1||dotpos-apos<2)
{alert(alerttxt);return false;}
else {return true;}
}
}
function validate_form(thisform)
{
with (thisform)
{
if (validate_required(email,"Please enter your e-mail!")==false)
{email.focus();return false;}
if (validate_email(email,"Invalid e-mail format!")==false)
{email.focus();return false;}
if (validate_required(passor,"Please enter password!")==false)
{passor.focus();return false;}
if (validate_required(passor2,"Please repeat password!")==false)
{passor2.focus();return false;}
if (passor2.value!=passor.value)
{alert(\'Repeated password is not equal to password!\');return false;}
}
}
</script>';
echo 'Set new password and e-mail to your account.<BR>
<FORM ACTION="' . getLink('account/lost') . '?action=step3" onsubmit="return validate_form(this)" METHOD=post>
<INPUT TYPE=hidden NAME="character" VALUE="">
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Please enter new password and e-mail</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
Account of character:&nbsp;&nbsp;<INPUT TYPE=text NAME="nick" VALUE="'.$nick.'" SIZE="40" readonly="readonly"><BR />
New password:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT id="passor" TYPE=password NAME="passor" VALUE="" SIZE="40"><BR>
Repeat new password:&nbsp;&nbsp;<INPUT id="passor2" TYPE=password NAME="passor" VALUE="" SIZE="40"><BR>
New e-mail address:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT id="email" TYPE=text NAME="email" VALUE="" SIZE="40"><BR>
<INPUT TYPE=hidden NAME="key" VALUE="'.$rec_key.'">
</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
' . $twig->render('buttons.submit.html.twig') . '</div>
</TD></TR></FORM></TABLE></TABLE>';
}
else
echo 'Wrong recovery key!';
}
else
echo 'Account of this character has no recovery key!';
}
else
echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
}
else
echo 'Invalid player name format. If you have other characters on account try with other name.';
echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<a href="' . getLink('account/lost') . '?action=step1&action_type=reckey&nick='.urlencode($nick).'" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
</TD></TR></FORM></TABLE></TABLE>';
}
elseif($action == 'step3')
{
$rec_key = trim($_REQUEST['key']);
$nick = stripslashes($_REQUEST['nick']);
$new_pass = trim($_REQUEST['passor']);
$new_email = trim($_REQUEST['email']);
if(Validator::characterName($nick))
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded())
$account = $player->getAccount();
if($account->isLoaded())
{
$account_key = $account->getCustomField('key');
if(!empty($account_key))
{
if($account_key == $rec_key)
{
if(Validator::password($new_pass))
{
if(Validator::email($new_email))
{
$account->setEMail($new_email);
$tmp_new_pass = $new_pass;
if(USE_ACCOUNT_SALT)
{
$salt = generateRandomString(10, false, true, true);
$tmp_new_pass = $salt . $new_pass;
}
$account->setPassword(encrypt($tmp_new_pass));
$account->save();
if(USE_ACCOUNT_SALT)
$account->setCustomField('salt', $salt);
echo 'Your account name, new password and new e-mail.<BR>
<FORM ACTION="' . getLink('account/manage') . '" onsubmit="return validate_form(this)" METHOD=post>
<INPUT TYPE=hidden NAME="character" VALUE="">
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Your account name, new password and new e-mail</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
Account name:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>'.$account->getName().'</b><BR>
New password:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>'.$new_pass.'</b><BR>
New e-mail address:&nbsp;<b>'.$new_email.'</b><BR>';
if($account->getCustomField('email_next') < time())
{
$mailBody = '
<h3>Your account name and new password!</h3>
<p>Changed password and e-mail to your account in Lost Account Interface on server <a href="'.BASE_URL.'"><b>'.$config['lua']['serverName'].'</b></a></p>
<p>Account name: <b>'.$account->getName().'</b></p>
<p>New password: <b>'.$new_pass.'</b></p>
<p>E-mail: <b>'.$new_email.'</b> (this e-mail)</p>
<br />
<p><u>It\'s automatic e-mail from OTS Lost Account System. Do not reply!</u></p>';
if(_mail($account->getCustomField('email'), $config['lua']['serverName']." - New password to your account", $mailBody))
{
echo '<br /><small>Sent e-mail with your account name and password to new e-mail. You should receive this e-mail in 15 minutes. You can login now with new password!</small>';
}
else
{
echo '<br /><p class="error">An error occurred while sending email! You will not receive e-mail with this informations. For Admin: More info can be found in system/logs/mailer-error.log</p>';
}
}
else
{
echo '<br /><small>You will not receive e-mail with this informations.</small>';
}
echo '<INPUT TYPE=hidden NAME="account_login" VALUE="'.$account->getId().'">
<INPUT TYPE=hidden NAME="password_login" VALUE="'.$new_pass.'">
</TD></TR></TABLE><BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<INPUT TYPE=image NAME="Login" ALT="Login" SRC="'.$template_path.'/images/global/buttons/sbutton_login.gif" BORDER=0 WIDTH=120 HEIGHT=18></div>
</TD></TR></FORM></TABLE></TABLE>';
}
else
echo Validator::getLastError();
}
else
echo Validator::getLastError();
}
else
echo 'Wrong recovery key!';
}
else
echo 'Account of this character has no recovery key!';
}
else
echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
}
else
echo 'Invalid player name format. If you have other characters on account try with other name.';
echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<a href="' . getLink('account/lost') . '?action=step1&action_type=reckey&nick='.urlencode($nick).'" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
</TD></TR></FORM></TABLE></TABLE>';
}
elseif($action == 'checkcode')
{
$code = trim($_REQUEST['code']);
$character = stripslashes(trim($_REQUEST['character']));
if(empty($code) || empty($character))
echo 'Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
<FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & character name</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
Your code:&nbsp;<INPUT TYPE=text NAME="code" VALUE="" SIZE="40")><BR />
Character:&nbsp;<INPUT TYPE=text NAME="character" VALUE="" SIZE="40")><BR />
</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
' . $twig->render('buttons.submit.html.twig') . '</div>
</TD></TR></FORM></TABLE></TABLE>';
else
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($character);
if($player->isLoaded())
$account = $player->getAccount();
if($account->isLoaded())
{
if($account->getCustomField('email_code') == $code)
{
echo '<script type="text/javascript">
function validate_required(field,alerttxt)
{
with (field)
{
if (value==null||value==""||value==" ")
{alert(alerttxt);return false;}
else {return true}
}
}
function validate_form(thisform)
{
with (thisform)
{
if (validate_required(passor,"Please enter password!")==false)
{passor.focus();return false;}
if (validate_required(passor2,"Please repeat password!")==false)
{passor2.focus();return false;}
if (passor2.value!=passor.value)
{alert(\'Repeated password is not equal to password!\');return false;}
}
}
</script>
Please enter new password to your account and repeat to make sure you remember password.<BR>
<FORM ACTION="' . getLink('account/lost') . '?action=setnewpassword" onsubmit="return validate_form(this)" METHOD=post>
<INPUT TYPE=hidden NAME="character" VALUE="'.$character.'">
<INPUT TYPE=hidden NAME="code" VALUE="'.$code.'">
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & account name</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
New password:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE=password ID="passor" NAME="passor" VALUE="" SIZE="40")><BR />
Repeat new password:&nbsp;<INPUT TYPE=password ID="passor2" NAME="passor2" VALUE="" SIZE="40")><BR />
</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
' . $twig->render('buttons.submit.html.twig') . '</div>
</TD></TR></FORM></TABLE></TABLE>';
}
else
$error= 'Wrong code to change password.';
}
else
$error = 'Account of this character or this character doesn\'t exist.';
}
if(!empty($error))
echo '<span style="color: red"><b>'.$error.'</b></span><br />Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
<FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & character name</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
Your code:&nbsp;<INPUT TYPE=text NAME="code" VALUE="" SIZE="40")><BR />
Character:&nbsp;<INPUT TYPE=text NAME="character" VALUE="" SIZE="40")><BR />
</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
' . $twig->render('buttons.submit.html.twig') . '</div>
</TD></TR></FORM></TABLE></TABLE>';
}
elseif($action == 'setnewpassword')
{
$newpassword = $_REQUEST['passor'];
$code = $_REQUEST['code'];
$character = stripslashes($_REQUEST['character']);
echo '';
if(empty($code) || empty($character) || empty($newpassword))
echo '<span style="color: red"><b>Error. Try again.</b></span><br />Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
<BR><FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<INPUT TYPE=image NAME="Back" ALT="Back" SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" BORDER=0 WIDTH=120 HEIGHT=18></div>
</TD></TR></FORM></TABLE></TABLE>';
else
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($character);
if($player->isLoaded())
$account = $player->getAccount();
if($account->isLoaded())
{
if($account->getCustomField('email_code') == $code)
{
if(Validator::password($newpassword))
{
$tmp_new_pass = $newpassword;
if(USE_ACCOUNT_SALT)
{
$salt = generateRandomString(10, false, true, true);
$tmp_new_pass = $salt . $newpassword;
$account->setCustomField('salt', $salt);
}
$account->setPassword(encrypt($tmp_new_pass ));
$account->save();
$account->setCustomField('email_code', '');
echo 'New password to your account is below. Now you can login.<BR>
<INPUT TYPE=hidden NAME="character" VALUE="'.$character.'">
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Changed password</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
New password:&nbsp;<b>'.$newpassword.'</b><BR />
Account name:&nbsp;&nbsp;&nbsp;<i>(Already on your e-mail)</i><BR />';
$mailBody = '
<h3>Your account name and password!</h3>
<p>Changed password to your account in Lost Account Interface on server <a href="'.BASE_URL.'"><b>'.$config['lua']['serverName'].'</b></a></p>
<p>Account name: <b>'.$account->getName().'</b></p>
<p>New password: <b>'.$newpassword.'</b></p>
<br />
<p><u>It\'s automatic e-mail from OTS Lost Account System. Do not reply!</u></p>';
if(_mail($account->getCustomField('email'), $config['lua']['serverName']." - Your new password", $mailBody))
{
echo '<br /><small>New password work! Sent e-mail with your password and account name. You should receive this e-mail in 15 minutes. You can login now with new password!';
}
else
{
echo '<br /><p class="error">New password work! An error occurred while sending email! You will not receive e-mail with new password. For Admin: More info can be found in system/logs/mailer-error.log';
}
echo '</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<FORM ACTION="' . getLink('account/manage') . '" METHOD=post>
<INPUT TYPE=image NAME="Login" ALT="Login" SRC="'.$template_path.'/images/global/buttons/sbutton_login.gif" BORDER=0 WIDTH=120 HEIGHT=18></div>
</TD></TR></FORM></TABLE></TABLE>';
}
else
$error= Validator::getLastError();
}
else
$error= 'Wrong code to change password.';
}
else
$error = 'Account of this character or this character doesn\'t exist.';
}
if(!empty($error))
echo '<span style="color: red"><b>'.$error.'</b></span><br />Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
<FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & character name</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
Your code:&nbsp;<INPUT TYPE=text NAME="code" VALUE="" SIZE="40")><BR />
Character:&nbsp;<INPUT TYPE=text NAME="character" VALUE="" SIZE="40")><BR />
</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
' . $twig->render('buttons.submit.html.twig') . '</div>
</TD></TR></FORM></TABLE></TABLE>';
}

View File

@@ -1,18 +0,0 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
function lostAccountWriteCooldown(string $nick, int $time): void
{
global $twig;
$inSec = $time - time();
$minutesLeft = floor($inSec / 60);
$secondsLeft = $inSec - ($minutesLeft * 60);
$timeLeft = $minutesLeft.' minutes '.$secondsLeft.' seconds';
$timeRounded = ceil(setting('core.mail_lost_account_interval') / 60);
$twig->display('error_box.html.twig', [
'errors' => ["Account of selected character (<b>" . escapeHtml($nick) . "</b>) received e-mail in last $timeRounded minutes. You must wait $timeLeft before you can use Lost Account Interface again."]
]);
}

View File

@@ -1,51 +0,0 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
csrfProtect();
$title = 'Lost Account';
$code = isset($_REQUEST['code']) ? trim($_REQUEST['code']) : '';
$character = isset($_REQUEST['character']) ? stripslashes(trim($_REQUEST['character'])) : '';
if(empty($code) || empty($character))
$twig->display('account/lost/check-code.html.twig', [
'code' => $code,
'characters' => $character,
]);
else
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($character);
if($player->isLoaded()) {
$account = $player->getAccount();
}
if($account->isLoaded()) {
if($account->getCustomField('email_code') == $code) {
$twig->display('account/lost/check-code.finish.html.twig', [
'character' => $character,
'code' => $code,
]);
}
else {
$error = 'Wrong code to change password.';
}
}
else {
$error = "Account of this character or this character doesn't exist.";
}
}
if(!empty($error)) {
$twig->display('error_box.html.twig', [
'errors' => [$error],
]);
echo '<br/>';
$twig->display('account/lost/check-code.html.twig', [
]);
}

View File

@@ -1,68 +0,0 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
csrfProtect();
require __DIR__ . '/../base.php';
$title = 'Lost Account';
$email = $_REQUEST['email'];
$nick = stripslashes($_REQUEST['nick']);
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded()) {
$account = $player->getAccount();
}
if($account->isLoaded()) {
if($account->getCustomField('email_next') < time()) {
if($account->getEMail() == $email) {
$newCode = generateRandomString(30, true, false, true);
$mailBody = $twig->render('mail.account.lost.code.html.twig', [
'newCode' => $newCode,
'account' => $account,
'nick' => $nick,
]);
$accountEMail = $account->getCustomField('email');
if(_mail($accountEMail, configLua('serverName') . ' - Recover your account', $mailBody)) {
$account->setCustomField('email_code', $newCode);
$account->setCustomField('email_next', (time() + setting('core.mail_lost_account_interval')));
$twig->display('success.html.twig', [
'title' => 'Email has been sent',
'description' => 'Details about steps required to recover your account has been sent to <b>' . $accountEMail . '</b>. You should receive this email within 15 minutes. Please check your inbox/spam directory.',
'custom_buttons' => '',
]);
}
else {
$account->setCustomField('email_next', (time() + 60));
error('An error occurred while sending email! Try again later or contact with admin. For Admin: More info can be found in system/logs/mailer-error.log</p>');
}
}
else {
$errors[] = 'Invalid e-mail to account of character <b>' . escapeHtml($nick) . '</b>. Try again.';
}
}
else {
lostAccountWriteCooldown($nick, (int)$account->getCustomField('email_next'));
}
}
else {
$errors[] = "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
}
if (!empty($errors)) {
$twig->display('error_box.html.twig', [
'errors' => $errors,
]);
}
$twig->display('account.back_button.html.twig', [
'new_line' => true,
'center' => true,
'action' => getLink('account/lost/step-1') . '?action=email&nick=' . urlencode($nick),
]);

View File

@@ -1,94 +0,0 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
csrfProtect();
$title = 'Lost Account';
$newPassword = $_REQUEST['password'];
$passwordRepeat = $_REQUEST['password_repeat'];
$code = $_REQUEST['code'];
$character = stripslashes($_REQUEST['character']);
if(empty($code) || empty($character) || empty($newPassword) || empty($passwordRepeat)) {
$errors[] = 'Please enter code from e-mail and name of one character from account. Then press Submit.';
$twig->display('error_box.html.twig', [
'errors' => $errors,
]);
$twig->display('account.back_button.html.twig', [
'new_line' => true,
'center' => true,
'action' => getLink('account/lost/check-code')
]);
return;
}
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($character);
if($player->isLoaded()) {
$account = $player->getAccount();
}
if($account->isLoaded()) {
if($account->getCustomField('email_code') == $code) {
if ($newPassword == $passwordRepeat) {
if (Validator::password($newPassword)) {
$tmp_new_pass = $newPassword;
if (USE_ACCOUNT_SALT) {
$salt = generateRandomString(10, false, true, true);
$tmp_new_pass = $salt . $newPassword;
$account->setCustomField('salt', $salt);
}
$account->setPassword(encrypt($tmp_new_pass));
$account->save();
$account->setCustomField('email_code', '');
$mailBody = $twig->render('mail.account.lost.new-password.html.twig', [
'account' => $account,
'newPassword' => $newPassword,
]);
$statusMsg = '';
if (_mail($account->getCustomField('email'), configLua('serverName') . ' - Your new password', $mailBody)) {
$statusMsg = '<br /><small>New password work! Sent e-mail with your password and account name. You should receive this e-mail in 15 minutes. You can login now with new password!';
} else {
$statusMsg = '<br /><p class="error">New password work! An error occurred while sending email! You will not receive e-mail with new password. For Admin: More info can be found in system/logs/mailer-error.log';
}
$twig->display('account/lost/finish.new-password.html.twig', [
'statusMsg' => $statusMsg,
'newPassword' => $newPassword,
]);
} else {
$error = Validator::getLastError();
}
}
else {
$error = 'Passwords are not the same!';
}
}
else {
$error = 'Wrong code to change password.';
}
}
else {
$error = "Account of this character or this character doesn't exist.";
}
if(!empty($error)) {
$twig->display('error_box.html.twig', [
'errors' => [$error],
]);
echo '<br/>';
$twig->display('account/lost/check-code.html.twig', [
'code' => $code,
'character' => $character,
]);
}

View File

@@ -1,34 +0,0 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
require __DIR__ . '/../base.php';
csrfProtect();
$title = 'Lost Account';
if($account->isLoaded()) {
if($account->getCustomField('email_next') < time()) {
$twig->display('account/lost/email.html.twig', [
'nick' => $nick,
]);
}
else {
lostAccountWriteCooldown($nick, (int)$account->getCustomField('email_next'));
}
}
else {
$errors[] = "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
}
if (!empty($errors)) {
$twig->display('error_box.html.twig', [
'errors' => $errors,
]);
}
$twig->display('account.back_button.html.twig', [
'new_line' => true,
'center' => true,
'action' => getLink('account/lost'),
]);

View File

@@ -1,34 +0,0 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
csrfProtect();
$title = 'Lost Account';
if($account->isLoaded()) {
$account_key = $account->getCustomField('key');
if(!empty($account_key)) {
$twig->display('account/lost/recovery-key.step-1.html.twig', [
'nick' => $nick,
]);
}
else {
$errors[] = 'Account of this character has no recovery key!';
}
}
else {
$errors[] = "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
}
if (!empty($errors)) {
$twig->display('error_box.html.twig', [
'errors' => $errors,
]);
}
$twig->display('account.back_button.html.twig', [
'new_line' => true,
'center' => true,
'action' => getLink('account/lost'),
]);

View File

@@ -1,48 +0,0 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
csrfProtect();
$title = 'Lost Account';
$key = trim($_REQUEST['key']);
$nick = stripslashes($_REQUEST['nick']);
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded()) {
$account = $player->getAccount();
}
if($account->isLoaded()) {
$accountKey = $account->getCustomField('key');
if(!empty($accountKey)) {
if($accountKey == $key) {
$twig->display('account/lost/recovery-key.step-2.html.twig', [
'nick' => $nick,
'key' => $key,
]);
}
else {
$errors[] = 'Wrong recovery key!';
}
}
else {
$errors[] = 'Account of this character has no recovery key!';
}
}
else
$errors[] = "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
if (!empty($errors)) {
$twig->display('error_box.html.twig', [
'errors' => $errors,
]);
}
$twig->display('account.back_button.html.twig', [
'new_line' => true,
'center' => true,
'action' => getLink('account/lost/step-1') . '?action=recovery-key&nick=' . urlencode($nick),
]);

View File

@@ -1,101 +0,0 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
csrfProtect();
$title = 'Lost Account';
$key = trim($_REQUEST['key']);
$nick = stripslashes($_REQUEST['nick']);
$newPassword = trim($_REQUEST['password']);
$passwordRepeat = trim($_REQUEST['password_repeat']);
$newEmail = trim($_REQUEST['email']);
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded()) {
$account = $player->getAccount();
}
if($account->isLoaded()) {
$accountKey = $account->getCustomField('key');
if(!empty($accountKey)) {
if($accountKey == $key) {
if(Validator::password($newPassword)) {
if ($newPassword == $passwordRepeat) {
if (Validator::email($newEmail)) {
$account->setEMail($newEmail);
$tmp_new_pass = $newPassword;
if (USE_ACCOUNT_SALT) {
$salt = generateRandomString(10, false, true, true);
$tmp_new_pass = $salt . $newPassword;
}
$account->setPassword(encrypt($tmp_new_pass));
$account->save();
if (USE_ACCOUNT_SALT) {
$account->setCustomField('salt', $salt);
}
$statusMsg = '';
if ($account->getCustomField('email_next') < time()) {
$mailBody = $twig->render('mail.account.lost.new-email.html.twig', [
'account' => $account,
'newPassword' => $newPassword,
'newEmail' => $newEmail,
]);
if (_mail($account->getCustomField('email'), configLua('serverName') . ' - New password to your account', $mailBody)) {
$statusMsg = '<br /><small>Sent e-mail with your account name and password to new e-mail. You should receive this e-mail in 15 minutes. You can login now with new password!</small>';
} else {
$statusMsg = '<br /><p class="error">An error occurred while sending email! You will not receive e-mail with this informations. For Admin: More info can be found in system/logs/mailer-error.log</p>';
}
} else {
$statusMsg = '<br /><small>You will not receive e-mail with this informations.</small>';
}
$twig->display('account/lost/finish.new-email.html.twig', [
'statusMsg' => $statusMsg,
'account' => $account,
'newPassword' => $newPassword,
'newEmail' => $newEmail,
]);
} else {
$errors[] = Validator::getLastError();
}
}
else {
$errors[] = 'Passwords are not the same!';
}
}
else {
$errors[] = Validator::getLastError();
}
}
else {
$errors[] = 'Wrong recovery key!';
}
}
else {
$errors[] = 'Account of this character has no recovery key!';
}
}
else {
$errors[] = "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
}
if (!empty($errors)) {
$twig->display('error_box.html.twig', [
'errors' => $errors,
]);
}
$twig->display('account.back_button.html.twig', [
'new_line' => true,
'center' => true,
'action' => getLink('account/lost/step-1') . '?action=recovery-key&nick=' . urlencode($nick),
]);

View File

@@ -1,26 +0,0 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
csrfProtect();
$title = 'Lost Account';
$nick = stripslashes($_REQUEST['nick']);
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded()) {
$account = $player->getAccount();
}
if (ACTION == 'email') {
require __DIR__ . '/email/step-1.php';
}
else if (ACTION == 'recovery-key') {
require __DIR__ . '/recovery-key/step-1.php';
}
else {
$twig->display('account/lost/no-action.html.twig');
}

View File

@@ -0,0 +1,94 @@
<?php
use MyAAC\Models\AccountEmailVerify;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Resend Email';
$errorWithBackButton = function ($msg) use ($twig) {
$errors = [$msg];
$twig->display('error_box.html.twig', ['errors' => $errors]);
$twig->display('account.back_button.html.twig', [
'action' => getLink('account/resend-email-verify'),
]);
};
if (!setting('core.mail_enabled') || !setting('core.account_mail_verify')) {
$errorWithBackButton('Resending email is not possible on this server.');
return;
}
$showForm = true;
if (isset($_POST['submit']) && $_POST['submit'] == '1') {
$email = $_REQUEST['email'];
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errorWithBackButton('Please enter valid Email.');
return;
}
$account = new OTS_Account();
$account->findByEMail($email);
if ($account->isLoaded()) {
if ($account->getCustomField('email_verified') == '1') {
$errorWithBackButton('This account is already verified! You can <a href=' . getLink('account/manage') . '>log in</a> on the website.');
return;
}
$accountEmailVerify = AccountEmailVerify::where('account_id', $account->getId())->orderBy('sent_at', 'DESC')->first();
if ($accountEmailVerify && time() - $accountEmailVerify->sent_at < 60) {
$errorWithBackButton('Only one Email per minute is allowed. Please try again later.');
return;
}
$tmp_account = $email;
if (!config('account_login_by_email')) {
$tmp_account = (USE_ACCOUNT_NAME ? $account->getName() : $account->getId());
}
$hash = md5(generateRandomString(16, true, true) . $email);
AccountEmailVerify::create([
'account_id' => $account->getId(),
'hash' => $hash,
'sent_at' => time(),
]);
$verify_url = getLink('account/confirm-email/' . $hash);
$body_html = $twig->render('mail.account.resend-email-verify.html.twig', array(
'account' => $tmp_account,
'verify_url' => generateLink($verify_url, $verify_url, true)
));
if (_mail($account->getEMail(), configLua('serverName') . ' - Verify Account', $body_html)) {
$message = "If account with this email exists - you will become an email with verification link.";
$showForm = false;
} else {
$message = "<p class='error'>An error occurred while sending email (<b>{$email}</b> )! Try again later. For Admin: More info can be found in system/logs/mailer-error.log</p>";
}
}
else {
$message = "<br />If account with this email exists - you will become an email with verification link.";
$showForm = false;
}
$twig->display('success.html.twig', array(
'title' => 'Verify Email Sent',
'description' => $message,
));
}
//show errors if not empty
if (!empty($errors)) {
$twig->display('error_box.html.twig', ['errors' => $errors]);
$twig->display('account.back_button.html.twig', [
'action' => getLink('account/resend-email-verify'),
]);
}
if ($showForm) {
$twig->display('account.resend-email-verify.html.twig');
}

View File

@@ -88,8 +88,10 @@ if($logged && $account_logged && $account_logged->isLoaded()) {
/**
* Routes loading
*/
$routesFinal = [];
$dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) {
$routesFinal = [];
global $cache, $routesFinal;
foreach(getDatabasePages() as $page) {
$routesFinal[] = ['*', $page, '__database__/' . $page, 100];
}
@@ -165,7 +167,7 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r)
echo '</pre>';
die;
*/
foreach ($routesFinal as $route) {
foreach ($routesFinal as &$route) {
if ($route[0] === '*') {
$route[0] = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD'];
}
@@ -198,6 +200,10 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r)
log_append('router.log', $warning);
}
}
if ($cache->enabled()) {
$cache->set('routes_final', serialize($routesFinal), 10 * 365 * 24 * 60 * 60); // 10 years / infinite
}
},
[
'cacheFile' => CACHE . 'route.cache',
@@ -212,7 +218,7 @@ $found = true;
// old support for pages like /?subtopic=accountmanagement
$page = $_REQUEST['p'] ?? ($_REQUEST['subtopic'] ?? '');
if(!empty($page) && preg_match('/^[A-z0-9\-]+$/', $page)) {
if(!empty($page) && preg_match('/^[A-z0-9\/\-]+$/', $page)) {
if (isset($_REQUEST['p'])) { // some plugins may require this
$_REQUEST['subtopic'] = $_REQUEST['p'];
}
@@ -221,9 +227,26 @@ if(!empty($page) && preg_match('/^[A-z0-9\-]+$/', $page)) {
require SYSTEM . 'compat/pages.php';
}
$file = loadPageFromFileSystem($page, $found);
if(!$found) {
$file = false;
$foundRoute = false;
$tmp = null;
if ($cache->enabled() && $cache->fetch('routes_final', $tmp)) {
$routesFinal = unserialize($tmp);
}
foreach ($routesFinal as $route) {
if ($page === $route[1]) {
$file = $route[2];
$foundRoute = true;
break;
}
}
if (!$foundRoute) {
$file = loadPageFromFileSystem($page, $found);
if(!$found) {
$file = false;
}
}
}
else {

View File

@@ -115,6 +115,11 @@ class Cache
return unserialize($value);
}
// -1 for infinite cache
if ($ttl == -1) {
$ttl = 10 * 365 * 24 * 60 * 60; // 10 years should be enough
}
$value = $callback();
$cache->set($key, serialize($value), $ttl);
return $value;

View File

@@ -0,0 +1,15 @@
<?php
namespace MyAAC\Models;
use Illuminate\Database\Eloquent\Model;
class AccountEmailVerify extends Model
{
protected $table = TABLE_PREFIX . 'account_emails_verify';
public $timestamps = false;
protected $fillable = ['account_id', 'hash', 'sent_at'];
}

View File

@@ -1,26 +1,7 @@
{% if new_line is defined and new_line %}
<br/>
{% endif %}
{% set _center = false %}
{% if center is defined and center %}
{% set _center = true %}
{% endif %}
{% if _center %}
<table border="0" cellspacing="1" cellpadding="4" width="100%">
<tbody>
<tr>
<td align="center">
{% endif %}
<form action="{% if action is not defined %}{{ getLink('account/manage') }}{% else %}{{ action }}{% endif %}" method="post">
{{ csrf() }}
{{ include('buttons.back.html.twig') }}
</form>
{% if _center %}
</td>
</tr>
</tbody>
</table>
{% endif %}
<form action="{% if action is not defined %}{{ getLink('account/manage') }}{% else %}{{ action }}{% endif %}" method="post">
{{ csrf() }}
{{ include('buttons.back.html.twig') }}
</form>

View File

@@ -0,0 +1,36 @@
The Lost Account Interface can help you to get back your account name and password. Please enter your character name and select what you want to do.<br/>
<form action="{{ getLink('account/lost') }}?action=step1" method="post">
{{ csrf() }}
<input type="hidden" name="character" value="">
<table cellspacing="1" cellpadding="4" border="0" width="100%">
<tr>
<td bgcolor="{{ config.vdarkborder }}" class="white"><b>Please enter your character name</b></td>
</tr>
<tr>
<td bgcolor="{{ config.darkborder }}">
<input type="text" name="nick" size="40" autofocus/><br>
</td>
</tr>
</table>
<table cellspacing="1" cellpadding="4" border="0" width="100%">
<tr>
<td bgcolor="{{ config.vdarkborder }}" class="white"><b>What do you want?</b></td>
</tr>
<tr>
<td bgcolor="{{ config.darkborder }}">
<input type="radio" name="action_type" id="action_type_email" value="email">
<label for="action_type_email"> Send me new password and my account name to account e-mail adress.</label><br/>
<input type=radio name="action_type" id="action_type_key" value="reckey">
<label for="action_type_key"> I got <b>recovery key</b> and want set new password and e-mail adress to my account.</label><br/>
</td>
</tr>
</table>
<br/>
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td align="center">
{{ include('buttons.submit.html.twig') }}
</td>
</tr>
</table>
</form>

View File

@@ -0,0 +1,10 @@
Please select action.<br/>
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td align="center">
<a href="{{ getLink('account/lost') }}" border="0">
{{ include('buttons.back.html.twig') }}
</a>
</td>
</tr>
</table>

View File

@@ -0,0 +1,45 @@
Please enter your account Email address.<br/><br/>
{% set title = 'Resend Email' %}
{% set background = config('darkborder') %}
{% set content %}
<table style="width:100%;">
<tr>
<td class="LabelV" >
<span><label for="email">Email Address:</label></span>
</td>
<td style="width:90%;">
<input type="email" form="form" id="email" name="email" size="30" maxlength="50" autofocus/>
</td>
</tr>
</table>
{% endset %}
{% include 'tables.headline.html.twig' %}
<br/>
<table style="width:100%;">
<tr align="center">
<td>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td style="border:0;">
<form id="form" action="{{ getLink('account/resend-email-verify') }}" method="post">
{{ csrf() }}
<input type="hidden" name="submit" value="1"/>
{{ include('buttons.submit.html.twig') }}
</form>
</td>
<tr>
</table>
</td>
<td>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td style="border:0;">
<form action="{{ getLink('news') }}" method="post">
{{ include('buttons.back.html.twig') }}
</form>
</td>
</tr>
</table>
</td>
</tr>
</table>

View File

@@ -1,54 +0,0 @@
Please enter new password to your account and repeat to make sure you remember password.<BR>
<form action="{{ getLink('account/lost/email/set-new-password') }}" method="post">
{{ csrf() }}
<input type="hidden" name="character" value="{{ character }}">
<input type="hidden" name="code" value="{{ code }}">
<table class="myaac-table" style="width: 100%;">
<thead>
<tr>
<th class="white"><b>Passwords</b></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<table>
<tr>
<td>
<label for="password">New password:</label>
</td>
<td>
<input type="password" id="password" name="password" value="" size="40">
</td>
</tr>
<tr>
<td>
<label for="password_repeat">Repeat new password:</label>
</td>
<td>
<input type="password" id="password_repeat" name="password_repeat" value="" size="40">
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
<br/>
<table style="width: 100%">
<tr>
<td>
<div style="text-align: center">
{% set button_name = 'Submit' %}
{% include('buttons.base.html.twig') %}
</div>
</td>
</tr>
</table>
</form>

View File

@@ -1,33 +0,0 @@
Please enter code from e-mail and name of one character from account. Then press Submit.<br/>
<form action="{{ getLink('account/lost/check-code') }}" method="post">
{{ csrf() }}
<table class="myaac-table" style="width: 100%;">
<thead>
<tr>
<th class="white">
<b>Code & character name</b>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Your code:&nbsp;<input type="text" name="code" value="{{ code }}" size="40"><br/>
Character:&nbsp;<input type="text" name="character" value="{{ character }}" size="40"><br/>
</td>
</tr>
</tbody>
</table>
<br>
<table style="width: 100%">
<tr>
<td align="center">
{% set button_name = 'Submit' %}
{% include('buttons.base.html.twig') %}
</td>
</tr>
</table>
</form>

View File

@@ -1,54 +0,0 @@
Please enter e-mail to account with this character.<br/>
<form action="{{ getLink('account/lost/email/send-code') }}" method="post">
{{ csrf() }}
<input type=hidden name="character">
<table class="myaac-table" style="width: 100%;">
<thead>
<tr>
<th class="white"><b>Please enter e-mail to account</b></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<table>
<tr>
<td>
<label for="nick">Character:</label>
</td>
<td>
<input type=text id="nick" name="nick" value="{{ nick }}" size="40" readonly="readonly">
</td>
</tr>
<tr>
<td>
<label for="name">E-mail to account:</label>
</td>
<td>
<input type=text id="name" name="email" value="" size="40">
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
<br>
<table style="width: 100%">
<tr>
<td>
<div style="text-align:center">
{% set button_name = 'Submit' %}
{% include('buttons.base.html.twig') %}
</div>
</td>
</tr>
</table>
</form>

View File

@@ -1,58 +0,0 @@
Your account name, new password and new e-mail.<br/>
<table class="myaac-table" style="width: 100%;">
<thead>
<tr>
<th class="white">
<b>Your account name, new password and new e-mail</b>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<table>
<tr>
<td>
Account name:
</td>
<td>
<b>{{ account.getName() }}</b>
</td>
</tr>
<tr>
<td>
New password:
</td>
<td>
<b>{{ newPassword }}</b>
</td>
</tr>
<tr>
<td>
New e-mail address:
</td>
<td>
<b>{{ newEmail }}</b>
</td>
</tr>
</table>
{{ statusMsg|raw }}
</td>
</tr>
</tbody>
</table>
<br>
<table style="width: 100%">
<tr>
<td align="center">
<form action="{{ getLink('account/manage') }}" method="post">
{{ include('buttons.login.html.twig') }}
</form>
</td>
</tr>
</table>

View File

@@ -1,30 +0,0 @@
New password to your account is below. Now you can log in.<BR>
<table class="myaac-table" style="width: 100%;">
<thead>
<tr>
<th class="white"><b>Changed password</b></th>
</tr>
</thead>
<tbody>
<tr>
<td>
New password:&nbsp;<b>{{ newPassword }}</b><br/>
Account name:&nbsp;&nbsp;&nbsp;<i>(Already on your e-mail)</i><br/>
{{ statusMsg|raw }}
</td>
</tr>
</tbody>
</table>
<br/>
<table style="width: 100%">
<tr>
<td align="center">
<form action="{{ getLink('account/manage') }}">
{% set button_name = 'Login' %}
{% include('buttons.base.html.twig') %}
</form>
</td>
</tr>
</table>

View File

@@ -1,43 +0,0 @@
The Lost Account Interface can help you to get back your account name and password. Please enter your character name and select what you want to do.<br/>
<form action="{{ getLink('account/lost/step-1') }}" method="post">
{{ csrf() }}
<input type="hidden" name="character" value="">
<table class="myaac-table" style="width: 100%">
<thead>
<tr>
<th class="white"><b>Please enter your character name</b></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="text" name="nick" size="40" autofocus/><br>
</td>
</tr>
</tbody>
</table>
<table style="width: 100%; border-spacing: 1px">
<tr>
<td style="padding: 4px; background: {{ config('vdarkborder') }}" class="white"><b>What do you want?</b></td>
</tr>
<tr>
<td style="padding: 4px; background: {{ config('darkborder') }}">
<input type="radio" name="action" id="action_type_email" value="email">
<label for="action_type_email"> Send me new password and my account name to account e-mail address.</label><br/>
<input type=radio name="action" id="action_type_key" value="recovery-key">
<label for="action_type_key"> I got <b>recovery key</b> and want set new password and e-mail address to my account.</label><br/>
</td>
</tr>
</table>
<br/>
<table style="width: 100%">
<tr>
<td align="center">
{% set button_name = 'Submit' %}
{% include('buttons.base.html.twig') %}
</td>
</tr>
</table>
</form>

View File

@@ -1,10 +0,0 @@
Please select action.<br/>
<table style="width: 100%">
<tr>
<td align="center">
<a href="{{ getLink('account/lost') }}">
{{ include('buttons.back.html.twig') }}
</a>
</td>
</tr>
</table>

View File

@@ -1,53 +0,0 @@
If you enter right recovery key you will see form to set new e-mail and password to account. To this e-mail will be send your new password and account name.<BR>
<form action="{{ getLink('account/lost/recovery-key/step-2') }}" method="post">
{{ csrf() }}
<table class="myaac-table" style="width: 100%;">
<thead>
<tr>
<th class="white">
<b>Please enter your recovery key</b>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<table>
<tr>
<td>
<label for="nick">Character name:</label>
</td>
<td>
<input type=text id="nick" name="nick" value="{{ nick }}" size="40" readonly="readonly">
</td>
</tr>
<tr>
<td>
<label for="key">Recovery key:</label>
</td>
<td>
<input type="text" id="key" name="key" value="" size="40">
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
<br>
<table style="width: 100%">
<tr>
<td>
<div style="text-align:center">
{% set button_name = 'Submit' %}
{% include('buttons.base.html.twig') %}
</div>
</td>
</tr>
</table>
</form>

View File

@@ -1,71 +0,0 @@
Set new password and e-mail to your account.<br>
<form action="{{ getLink('account/lost/recovery-key/step-3') }}" method="post">
{{ csrf() }}
<input type="hidden" name="key" VALUE="{{ key }}">
<input type="hidden" name="character" value="">
<table class="myaac-table" style="width: 100%">
<thead>
<tr>
<th class="white">
<b>Please enter new password and e-mail</b>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<table>
<tr>
<td>
<label for="nick">Account of character:</label>
</td>
<td>
<input type="text" id="nick" name="nick" value="{{ nick }}" size="40" readonly="readonly">
</td>
</tr>
<tr>
<td>
<label for="password">New password:</label>
</td>
<td>
<input type="password" id="password" name="password" value="" size="40">
</td>
</tr>
<tr>
<td>
<label for="password_repeat">Repeat new password:</label>
</td>
<td>
<input type="password" id="password_repeat" name="password_repeat" value="" size="40">
</td>
</tr>
<tr>
<td>
<label for="email">New e-mail address:</label>
</td>
<td>
<input type="text" id="email" name="email" value="" size="40">
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
<br>
<table style="width: 100%">
<tr>
<td align="center">
{% set button_name = 'Submit' %}
{% include('buttons.base.html.twig') %}
</td>
</tr>
</table>
</form>

View File

@@ -9,7 +9,7 @@
<div class="AttentionSign" style="background-image:url({{ template_path }}/images/content/attentionsign.gif);"></div>
<b>The Following Errors Have Occurred:</b><br/>
{% for error in errors %}
<li>{{ error|striptags('<b>')|raw }}</li>
<li>{{ error|striptags('<b><a>')|raw }}</li>
{% endfor %}
</div>
<div class="BoxFrameHorizontal" style="background-image:url({{ template_path }}/images/content/box-frame-horizontal.gif);"></div>
@@ -17,4 +17,4 @@
<div class="BoxFrameEdgeLeftBottom" style="background-image:url({{ template_path }}/images/content/box-frame-edge.gif);"></div>
</div>
</div>
<br/>
<br/>

View File

@@ -1,10 +0,0 @@
You asked to reset your {{ config('lua')['serverName'] }} password.<br/>
<p>Account name: {{ account.getName() }}</p>
<br/>
To do so, please click this link:
<p>
<a href="{{ getLink('account/lost/check-code') }}?code={{ newCode }}&character={{ nick|urlencode }}">{{ getLink('account/lost/check-code') }}?code={{ newCode }}&character={{ nick|urlencode }}</a>
</p>
<p>or open page: <i>{{ getLink('account/lost/check-code') }}</i> and in field "code" write <b>{{ newCode }}</b></p>
<br/>
<p>If you did not request a password change, you may ignore this message and your password will remain unchanged.

View File

@@ -1,7 +0,0 @@
<h3>Your account name and new password!</h3>
<p>Changed password and e-mail to your account in Lost Account Interface on server <a href="{{ constant('BASE_URL') }}"><b>{{ config('lua')['serverName'] }}</b></a></p>
<p>Account name: <b>{{ account.getName() }}</b></p>
<p>New password: <b>{{ newPassword }}</b></p>
<p>E-mail: <b>{{ newEmail }}</b> (this e-mail)</p>
<br/>
<p><u>It's automatic e-mail from OTS Lost Account System. Do not reply!</u></p>

View File

@@ -1,6 +0,0 @@
<h3>Your account name and password!</h3>
<p>Changed password to your account in Lost Account Interface on server <a href="{{ constant('BASE_URL') }}"><b>{{ config('lua')['serverName'] }}</b></a></p>
<p>Account name: <b>{{ account.getName() }}</b></p>
<p>New password: <b>{{ newPassword }}</b></p>
<br/>
<p><u>It's automatic e-mail from OTS Lost Account System. Do not reply!</u></p>

View File

@@ -0,0 +1,7 @@
Hello {{ account }}!<br/>
<br/>
You requested to resend the verify Email on {{ config.lua.serverName }}!<br/>
<br/>
To verify your email address please click the link below:<br/>
{{ verify_url|raw }}

View File

@@ -101,7 +101,7 @@
<tr>
<td class="LabelV150"><b>Location Datacenter:</b></td>
<td>{{ setting('core.online_datacenter') }} <small>(Server date & time: - {{ "now"|date("d/m/Y H:i:s") }})</small></td>
<td>{{ setting('core.online_datacenter')|raw }} <small>(Server date & time: - {{ "now"|date("d/m/Y H:i:s") }})</small></td>
</tr>
<tr>
<td class="LabelV150"><b>PvP Type:</b></td>

View File

@@ -101,7 +101,9 @@ $twig->addFunction($function);
$function = new TwigFunction('hook', function ($context, $hook, array $params = []) {
global $hooks;
//note($hook);
if (config('hooks_debug')) {
note($hook);
}
if(is_string($hook)) {
if (defined($hook)) {

View File

@@ -27,26 +27,18 @@ if(isset($config['boxes']))
var loginStatus="<?php echo ($logged ? 'true' : 'false'); ?>";
<?php
if(PAGE !== 'news') {
if(isset($_REQUEST['subtopic'])) {
$tmp = escapeHtml($_REQUEST['subtopic']);
if($tmp === 'accountmanagement') {
$tmp = 'accountmanage';
$tmp = str_replace('/', '_', isset($_REQUEST['subtopic']) ? escapeHtml($_REQUEST['subtopic']) : PAGE);
$exp = explode('/', PAGE);
if(PAGE !== 'account/create' && PAGE !== 'account/lost' && isset($exp[1])) {
if ($exp[0] === 'account' && $exp[1] === 'lost') {
$tmp = 'account_lost';
} elseif ($exp[0] === 'account') {
$tmp = 'account_manage';
} else if ($exp[0] === 'news' && $exp[1] === 'archive') {
$tmp = 'news_archive';
}
}
else {
$tmp = str_replace('/', '_', PAGE);
$exp = explode('/', PAGE);
if(PAGE !== 'account/create' && PAGE !== 'account/lost' && isset($exp[1])) {
if ($exp[0] === 'account' && $exp[1] === 'lost') {
$tmp = 'account_lost';
} elseif ($exp[0] === 'account') {
$tmp = 'account_manage';
} else if ($exp[0] === 'news' && $exp[1] === 'archive') {
$tmp = 'news_archive';
}
else if (in_array($exp[0], ['characters', 'highscores', 'guilds', 'forum'])) {
$tmp = $exp[0];
}
else if (in_array($exp[0], ['characters', 'highscores', 'guilds', 'forum'])) {
$tmp = $exp[0];
}
}
}