mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
Template/Update (Part 46 - IV)
* account management rework: Personal Settings functionality * email, password, username update * email updates now also mails the old address for confirmation
This commit is contained in:
@@ -24,6 +24,7 @@ Also, this project is not meant to be used for commercial purposes of any kind!
|
|||||||
+ [MySQL Improved](https://www.php.net/manual/en/book.mysqli.php)
|
+ [MySQL Improved](https://www.php.net/manual/en/book.mysqli.php)
|
||||||
+ [Multibyte String](https://www.php.net/manual/en/book.mbstring.php)
|
+ [Multibyte String](https://www.php.net/manual/en/book.mbstring.php)
|
||||||
+ [File Information](https://www.php.net/manual/en/book.fileinfo.php)
|
+ [File Information](https://www.php.net/manual/en/book.fileinfo.php)
|
||||||
|
+ [Internationalization](https://www.php.net/manual/en/book.intl.php)
|
||||||
+ [GNU Multiple Precision](https://www.php.net/manual/en/book.gmp.php) (When using TrinityCore as auth source)
|
+ [GNU Multiple Precision](https://www.php.net/manual/en/book.gmp.php) (When using TrinityCore as auth source)
|
||||||
+ MySQL ≥ 5.7.0 OR MariaDB ≥ 10.6.4 OR similar
|
+ MySQL ≥ 5.7.0 OR MariaDB ≥ 10.6.4 OR similar
|
||||||
+ [TDB 335.21101](https://github.com/TrinityCore/TrinityCore/releases/tag/TDB335.21101) (no other other providers are supported at this time)
|
+ [TDB 335.21101](https://github.com/TrinityCore/TrinityCore/releases/tag/TDB335.21101) (no other other providers are supported at this time)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class AccountBaseResponse extends TemplateResponse
|
|||||||
public string $curEmail = '';
|
public string $curEmail = '';
|
||||||
public string $curName = '';
|
public string $curName = '';
|
||||||
public string $renameCD = '';
|
public string $renameCD = '';
|
||||||
|
public string $activeCD = '';
|
||||||
public array $description = [];
|
public array $description = [];
|
||||||
public array $signature = [];
|
public array $signature = [];
|
||||||
public int $avMode = 0;
|
public int $avMode = 0;
|
||||||
@@ -51,7 +52,7 @@ class AccountBaseResponse extends TemplateResponse
|
|||||||
{
|
{
|
||||||
array_unshift($this->title, Lang::account('settings'));
|
array_unshift($this->title, Lang::account('settings'));
|
||||||
|
|
||||||
$user = DB::Aowow()->selectRow('SELECT `debug`, `email`, `description`, `avatar`, `wowicon` FROM ?_account WHERE `id` = ?d', User::$id);
|
$user = DB::Aowow()->selectRow('SELECT `debug`, `email`, `description`, `avatar`, `wowicon`, `renameCooldown` FROM ?_account WHERE `id` = ?d', User::$id);
|
||||||
|
|
||||||
Lang::sort('game', 'ra');
|
Lang::sort('game', 'ra');
|
||||||
|
|
||||||
@@ -109,9 +110,12 @@ class AccountBaseResponse extends TemplateResponse
|
|||||||
|
|
||||||
// Username
|
// Username
|
||||||
$this->curName = User::$username;
|
$this->curName = User::$username;
|
||||||
|
$this->renameCD = Util::formatTime(Cfg::get('ACC_RENAME_DECAY') * 1000);
|
||||||
// todo localize date format; store time
|
if ($user['renameCooldown'] > time())
|
||||||
// $this->renameCD = date('F j, o', time() + 7 * DAY);
|
{
|
||||||
|
$locCode = implode('_', str_split(Lang::getLocale()->json(), 2)); // ._.
|
||||||
|
$this->activeCD = (new \IntlDateFormatter($locCode, pattern: Lang::main('dateFmtIntl')))->format($user['renameCooldown']);
|
||||||
|
}
|
||||||
|
|
||||||
/* COMMUNITY */
|
/* COMMUNITY */
|
||||||
|
|
||||||
|
|||||||
62
endpoints/account/confirm-email-address.php
Normal file
62
endpoints/account/confirm-email-address.php
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aowow;
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* accessed via confirmation email link
|
||||||
|
* write status to session and redirect to account settings
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ?auth=email-change
|
||||||
|
class AccountConfirmemailaddressResponse extends TemplateResponse
|
||||||
|
{
|
||||||
|
protected string $template = 'text-page-generic';
|
||||||
|
protected string $pageName = 'confirm-email-address';
|
||||||
|
|
||||||
|
protected array $expectedGET = array(
|
||||||
|
'key' => ['filter' => FILTER_VALIDATE_REGEXP, 'options' => ['regexp' => '/^[a-zA-Z0-9]{40}$/']]
|
||||||
|
);
|
||||||
|
|
||||||
|
private bool $success = false;
|
||||||
|
|
||||||
|
protected function generate() : void
|
||||||
|
{
|
||||||
|
parent::generate();
|
||||||
|
|
||||||
|
if (User::isBanned())
|
||||||
|
return;
|
||||||
|
|
||||||
|
$msg = $this->change();
|
||||||
|
|
||||||
|
$this->inputbox = ['inputbox-status', array(
|
||||||
|
'head' => Lang::account('inputbox', 'head', $this->success ? 'success' : 'error'),
|
||||||
|
'message' => $this->success ? $msg : '',
|
||||||
|
'error' => $this->success ? '' : $msg,
|
||||||
|
)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// this should probably leave change info intact for revert
|
||||||
|
// todo - move personal settings changes to separate table
|
||||||
|
private function change() : string
|
||||||
|
{
|
||||||
|
if (!$this->assertGET('key'))
|
||||||
|
return Lang::main('intError');
|
||||||
|
|
||||||
|
$acc = DB::Aowow()->selectRow('SELECT `updateValue`, `status`, `statusTimer` FROM ?_account WHERE `token` = ?', $this->_get['key']);
|
||||||
|
if (!$acc || $acc['status'] != ACC_STATUS_CHANGE_EMAIL || $acc['statusTimer'] < time())
|
||||||
|
return Lang::account('inputbox', 'error', 'mailTokenUsed');
|
||||||
|
|
||||||
|
// 0 changes == error
|
||||||
|
if (!DB::Aowow()->query('UPDATE ?_account SET `email` = `updateValue`, `status` = ?d, `statusTimer` = 0, `token` = "", `updateValue` = "" WHERE `token` = ?', ACC_STATUS_NONE, $this->_get['key']))
|
||||||
|
return Lang::main('intError');
|
||||||
|
|
||||||
|
$this->success = true;
|
||||||
|
return Lang::account('inputbox', 'message', 'mailChangeOk');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
60
endpoints/account/confirm-password.php
Normal file
60
endpoints/account/confirm-password.php
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aowow;
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* accessed via confirmation email link
|
||||||
|
* write status to session and redirect to account settings
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 2025 - no longer in use?
|
||||||
|
class AccountConfirmpasswordResponse extends TemplateResponse
|
||||||
|
{
|
||||||
|
protected string $template = 'text-page-generic';
|
||||||
|
protected string $pageName = 'confirm-password';
|
||||||
|
|
||||||
|
protected array $expectedGET = array(
|
||||||
|
'key' => ['filter' => FILTER_VALIDATE_REGEXP, 'options' => ['regexp' => '/^[a-zA-Z0-9]{40}$/']]
|
||||||
|
);
|
||||||
|
|
||||||
|
private bool $success = false;
|
||||||
|
|
||||||
|
protected function generate() : void
|
||||||
|
{
|
||||||
|
parent::generate();
|
||||||
|
|
||||||
|
if (User::isBanned())
|
||||||
|
return;
|
||||||
|
|
||||||
|
$msg = $this->confirm();
|
||||||
|
|
||||||
|
$this->inputbox = ['inputbox-status', array(
|
||||||
|
'head' => Lang::account('inputbox', 'head', $this->success ? 'success' : 'error'),
|
||||||
|
'message' => $this->success ? $msg : '',
|
||||||
|
'error' => $this->success ? '' : $msg,
|
||||||
|
)];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function confirm() : string
|
||||||
|
{
|
||||||
|
if (!$this->assertGET('key'))
|
||||||
|
return Lang::main('intError');
|
||||||
|
|
||||||
|
$acc = DB::Aowow()->selectRow('SELECT `updateValue`, `status`, `statusTimer` FROM ?_account WHERE `token` = ?', $this->_get['key']);
|
||||||
|
if (!$acc || $acc['status'] != ACC_STATUS_CHANGE_PASS || $acc['statusTimer'] < time())
|
||||||
|
return Lang::account('inputbox', 'error', 'passTokenUsed');
|
||||||
|
|
||||||
|
// 0 changes == error
|
||||||
|
if (!DB::Aowow()->query('UPDATE ?_account SET `passHash` = `updateValue`, `status` = ?d, `statusTimer` = 0, `token` = "", `updateValue` = "" WHERE `token` = ?', ACC_STATUS_NONE, $this->_get['key']))
|
||||||
|
return Lang::main('intError');
|
||||||
|
|
||||||
|
$this->success = true;
|
||||||
|
return Lang::account('inputbox', 'message', 'passChangeOk');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
62
endpoints/account/revert-email-address.php
Normal file
62
endpoints/account/revert-email-address.php
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aowow;
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* accessed via revert email link
|
||||||
|
* write status to session and redirect to account settings
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ?auth=email-revert
|
||||||
|
class AccountRevertemailaddressResponse extends TemplateResponse
|
||||||
|
{
|
||||||
|
protected string $template = 'text-page-generic';
|
||||||
|
protected string $pageName = 'revert-email-address';
|
||||||
|
|
||||||
|
protected array $expectedGET = array(
|
||||||
|
'key' => ['filter' => FILTER_VALIDATE_REGEXP, 'options' => ['regexp' => '/^[a-zA-Z0-9]{40}$/']]
|
||||||
|
);
|
||||||
|
|
||||||
|
private bool $success = false;
|
||||||
|
|
||||||
|
protected function generate() : void
|
||||||
|
{
|
||||||
|
parent::generate();
|
||||||
|
|
||||||
|
if (User::isBanned())
|
||||||
|
return;
|
||||||
|
|
||||||
|
$msg = $this->revert();
|
||||||
|
|
||||||
|
$this->inputbox = ['inputbox-status', array(
|
||||||
|
'head' => Lang::account('inputbox', 'head', $this->success ? 'success' : 'error'),
|
||||||
|
'message' => $this->success ? $msg : '',
|
||||||
|
'error' => $this->success ? '' : $msg,
|
||||||
|
)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// this should probably take precedence over email-change
|
||||||
|
// todo - move personal settings changes to separate table
|
||||||
|
private function revert() : string
|
||||||
|
{
|
||||||
|
if (!$this->assertGET('key'))
|
||||||
|
return Lang::main('intError');
|
||||||
|
|
||||||
|
$acc = DB::Aowow()->selectRow('SELECT `updateValue`, `status`, `statusTimer` FROM ?_account WHERE `token` = ?', $this->_get['key']);
|
||||||
|
if (!$acc || $acc['status'] != ACC_STATUS_CHANGE_EMAIL || $acc['statusTimer'] < time())
|
||||||
|
return Lang::account('inputbox', 'error', 'mailTokenUsed');
|
||||||
|
|
||||||
|
// 0 changes == error
|
||||||
|
if (!DB::Aowow()->query('UPDATE ?_account SET `status` = ?d, `statusTimer` = 0, `token` = "", `updateValue` = "" WHERE `token` = ?', ACC_STATUS_NONE, $this->_get['key']))
|
||||||
|
return Lang::main('intError');
|
||||||
|
|
||||||
|
$this->success = true;
|
||||||
|
return Lang::account('inputbox', 'message', 'mailRevertOk');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
80
endpoints/account/update-email.php
Normal file
80
endpoints/account/update-email.php
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aowow;
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* accessed via account settings form submit
|
||||||
|
* write status to session and redirect to account settings
|
||||||
|
*/
|
||||||
|
|
||||||
|
class AccountUpdateemailResponse extends TextResponse
|
||||||
|
{
|
||||||
|
protected ?string $redirectTo = '?account#personal';
|
||||||
|
protected bool $requiresLogin = true;
|
||||||
|
|
||||||
|
protected array $expectedPOST = array(
|
||||||
|
'newemail' => ['filter' => FILTER_VALIDATE_EMAIL, 'flags' => FILTER_FLAG_STRIP_AOWOW]
|
||||||
|
);
|
||||||
|
|
||||||
|
private bool $success = false;
|
||||||
|
|
||||||
|
public function __construct(string $pageParam)
|
||||||
|
{
|
||||||
|
if (Cfg::get('ACC_AUTH_MODE') != AUTH_MODE_SELF)
|
||||||
|
(new TemplateResponse())->generateError();
|
||||||
|
|
||||||
|
parent::__construct($pageParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generate() : void
|
||||||
|
{
|
||||||
|
if (User::isBanned())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ($msg = $this->updateMail())
|
||||||
|
$_SESSION['msg'] = ['email', $this->success, $msg];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updateMail() : string
|
||||||
|
{
|
||||||
|
// no input yet
|
||||||
|
if (is_null($this->_post['newemail']))
|
||||||
|
return Lang::main('intError');
|
||||||
|
// truncated due to validation fail
|
||||||
|
if (!$this->_post['newemail'])
|
||||||
|
return Lang::account('emailInvalid');
|
||||||
|
|
||||||
|
if (DB::Aowow()->selectCell('SELECT 1 FROM ?_account WHERE `email` = ? AND `id` <> ?d', $this->_post['newemail'], User::$id))
|
||||||
|
return Lang::account('mailInUse');
|
||||||
|
|
||||||
|
$status = DB::Aowow()->selectCell('SELECT `status` FROM ?_account WHERE `statusTimer` > UNIX_TIMESTAMP() AND `id` = ?d', User::$id);
|
||||||
|
if ($status != ACC_STATUS_NONE && $status != ACC_STATUS_CHANGE_EMAIL)
|
||||||
|
return Lang::account('isRecovering', [Util::formatTime(Cfg::get('ACC_RECOVERY_DECAY') * 1000)]);
|
||||||
|
|
||||||
|
$oldEmail = DB::Aowow()->selectCell('SELECT `email` FROM ?_account WHERE `id` = ?d', User::$id);
|
||||||
|
if ($this->_post['newemail'] == $oldEmail)
|
||||||
|
return Lang::account('newMailDiff');
|
||||||
|
|
||||||
|
$token = Util::createHash();
|
||||||
|
|
||||||
|
// store new mail in updateValue field, exchange when confirmation mail gets confirmed
|
||||||
|
if (!DB::Aowow()->query('UPDATE ?_account SET `updateValue` = ?, `status` = ?d, `statusTimer` = UNIX_TIMESTAMP() + ?d, `token` = ? WHERE `id` = ?d',
|
||||||
|
$this->_post['newemail'], ACC_STATUS_CHANGE_EMAIL, Cfg::get('ACC_RECOVERY_DECAY'), $token, User::$id))
|
||||||
|
return Lang::main('intError');
|
||||||
|
|
||||||
|
if (!Util::sendMail($this->_post['newemail'], 'change-email', [$token, $this->_post['newemail']], Cfg::get('ACC_RECOVERY_DECAY')))
|
||||||
|
return Lang::main('intError2', ['send mail']);
|
||||||
|
|
||||||
|
if (!Util::sendMail($oldEmail, 'revert-email', [$token, $oldEmail], Cfg::get('ACC_RECOVERY_DECAY')))
|
||||||
|
return Lang::main('intError2', ['send mail']);
|
||||||
|
|
||||||
|
$this->success = true;
|
||||||
|
return Lang::account('updateMessage', 'personal', [$this->_post['newemail']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
86
endpoints/account/update-password.php
Normal file
86
endpoints/account/update-password.php
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aowow;
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* accessed via account settings form submit
|
||||||
|
* write status to session and redirect to account settings
|
||||||
|
*/
|
||||||
|
|
||||||
|
class AccountUpdatepasswordResponse extends TextResponse
|
||||||
|
{
|
||||||
|
protected ?string $redirectTo = '?account#personal';
|
||||||
|
protected bool $requiresLogin = true;
|
||||||
|
|
||||||
|
protected array $expectedPOST = array(
|
||||||
|
'currentPassword' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkTextLine']],
|
||||||
|
'newPassword' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkTextLine']],
|
||||||
|
'confirmPassword' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkTextLine']],
|
||||||
|
'globalLogout' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkCheckbox']]
|
||||||
|
);
|
||||||
|
|
||||||
|
private bool $success = false;
|
||||||
|
|
||||||
|
public function __construct(string $pageParam)
|
||||||
|
{
|
||||||
|
if (Cfg::get('ACC_AUTH_MODE') != AUTH_MODE_SELF)
|
||||||
|
(new TemplateResponse())->generateError();
|
||||||
|
|
||||||
|
parent::__construct($pageParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generate() : void
|
||||||
|
{
|
||||||
|
if (User::isBanned())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ($msg = $this->updatePassword())
|
||||||
|
$_SESSION['msg'] = ['password', $this->success, $msg];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updatePassword() : string
|
||||||
|
{
|
||||||
|
if (!$this->assertPOST('currentPassword', 'newPassword', 'confirmPassword'))
|
||||||
|
return Lang::main('intError');
|
||||||
|
|
||||||
|
if (!Util::validatePassword($this->_post['newPassword'], $e))
|
||||||
|
return Lang::account($e == 1 ? 'errPassLength' : 'errPassChars');
|
||||||
|
|
||||||
|
if ($this->_post['newPassword'] !== $this->_post['confirmPassword'])
|
||||||
|
return Lang::account('passMismatch');
|
||||||
|
|
||||||
|
$userData = DB::Aowow()->selectRow('SELECT `status`, `passHash`, `statusTimer` FROM ?_account WHERE `id` = ?d', User::$id);
|
||||||
|
if ($userData['status'] != ACC_STATUS_NONE && $userData['status'] != ACC_STATUS_CHANGE_PASS && $userData['statusTimer'] > time())
|
||||||
|
return Lang::account('isRecovering', [Util::formatTime(Cfg::get('ACC_RECOVERY_DECAY') * 1000)]);
|
||||||
|
|
||||||
|
if (!User::verifyCrypt($this->_post['currentPassword'], $userData['passHash']))
|
||||||
|
return Lang::account('wrongPass');
|
||||||
|
|
||||||
|
if (User::verifyCrypt($this->_post['newPassword'], $userData['passHash']))
|
||||||
|
return Lang::account('newPassDiff');
|
||||||
|
|
||||||
|
$token = Util::createHash();
|
||||||
|
|
||||||
|
// store new hash in updateValue field, exchange when confirmation mail gets confirmed
|
||||||
|
if (!DB::Aowow()->query('UPDATE ?_account SET `updateValue` = ?, `status` = ?d, `statusTimer` = UNIX_TIMESTAMP() + ?d, `token` = ? WHERE `id` = ?d',
|
||||||
|
User::hashCrypt($this->_post['newPassword']), ACC_STATUS_CHANGE_PASS, Cfg::get('ACC_RECOVERY_DECAY'), $token, User::$id))
|
||||||
|
return Lang::main('intError');
|
||||||
|
|
||||||
|
$email = DB::Aowow()->selectCell('SELECT `email` FROM ?_account WHERE `id` = ?d', User::$id);
|
||||||
|
if (!Util::sendMail($email, 'update-password', [$token, $email], Cfg::get('ACC_RECOVERY_DECAY')))
|
||||||
|
return Lang::main('intError2', ['send mail']);
|
||||||
|
|
||||||
|
// logout all other active sessions
|
||||||
|
if ($this->_post['globalLogout'])
|
||||||
|
DB::Aowow()->query('UPDATE ?_account_sessions SET `status` = ?d, `touched` = ?d WHERE `userId` = ?d AND `sessionId` <> ? AND `status` = ?d', SESSION_FORCED_LOGOUT, time(), User::$id, session_id(), SESSION_ACTIVE);
|
||||||
|
|
||||||
|
$this->success = true;
|
||||||
|
return Lang::account('updateMessage', 'personal', [User::$email]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
61
endpoints/account/update-username.php
Normal file
61
endpoints/account/update-username.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aowow;
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* accessed via account settings form submit
|
||||||
|
* write status to session and redirect to account settings
|
||||||
|
*/
|
||||||
|
|
||||||
|
class AccountUpdateusernameResponse extends TextResponse
|
||||||
|
{
|
||||||
|
protected ?string $redirectTo = '?account#personal';
|
||||||
|
protected bool $requiresLogin = true;
|
||||||
|
|
||||||
|
protected array $expectedPOST = array(
|
||||||
|
'newUsername' => ['filter' => FILTER_CALLBACK, 'options' => [Util::class, 'validateUsername']]
|
||||||
|
);
|
||||||
|
|
||||||
|
private bool $success = false;
|
||||||
|
|
||||||
|
public function __construct(string $pageParam)
|
||||||
|
{
|
||||||
|
if (Cfg::get('ACC_AUTH_MODE') != AUTH_MODE_SELF)
|
||||||
|
(new TemplateResponse())->generateError();
|
||||||
|
|
||||||
|
parent::__construct($pageParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generate() : void
|
||||||
|
{
|
||||||
|
if (User::isBanned())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ($msg = $this->updateUsername())
|
||||||
|
$_SESSION['msg'] = ['username', $this->success, $msg];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updateUsername() : string
|
||||||
|
{
|
||||||
|
if (!$this->assertPOST('newUsername'))
|
||||||
|
return Lang::main('intError');
|
||||||
|
|
||||||
|
if (DB::Aowow()->selectCell('SELECT `renameCooldown` FROM ?_account WHERE `id` = ?d', User::$id) > time())
|
||||||
|
return Lang::main('intError'); // should have grabbed the error response..
|
||||||
|
|
||||||
|
// yes, including your current name. you don't want to change into your current name, right?
|
||||||
|
if (DB::Aowow()->selectCell('SELECT 1 FROM ?_account WHERE LOWER(`username`) = LOWER(?)', $this->_post['newUsername']))
|
||||||
|
return Lang::account('nameInUse');
|
||||||
|
|
||||||
|
DB::Aowow()->query('UPDATE ?_account SET `username` = ?, `renameCooldown` = ?d WHERE `id` = ?d', $this->_post['newUsername'], time() + Cfg::get('acc_rename_decay'), User::$id);
|
||||||
|
|
||||||
|
$this->success = true;
|
||||||
|
return Lang::account('updateMessage', 'username', [User::$username, $this->_post['newUsername']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -13,7 +13,7 @@ define('CLI_HAS_E', CLI && // WIN10 and later u
|
|||||||
(!OS_WIN || (function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(STDOUT))));
|
(!OS_WIN || (function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(STDOUT))));
|
||||||
|
|
||||||
|
|
||||||
$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring', 'fileinfo'/*, 'gmp'*/];
|
$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring', 'fileinfo', 'intl'/*, 'gmp'*/];
|
||||||
$badExt = [];
|
$badExt = [];
|
||||||
$error = '';
|
$error = '';
|
||||||
if ($ext = array_filter($reqExt, fn($x) => !extension_loaded($x)))
|
if ($ext = array_filter($reqExt, fn($x) => !extension_loaded($x)))
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ $lang = array(
|
|||||||
'colon' => ': ',
|
'colon' => ': ',
|
||||||
'dateFmtShort' => "d.m.Y",
|
'dateFmtShort' => "d.m.Y",
|
||||||
'dateFmtLong' => "d.m.Y \u\m H:i",
|
'dateFmtLong' => "d.m.Y \u\m H:i",
|
||||||
'dateFmtUntil' => "j. F Y",
|
'dateFmtIntl' => "d. MMMM y",
|
||||||
'timeAgo' => 'vor %s',
|
'timeAgo' => 'vor %s',
|
||||||
'nfSeparators' => ['.', ','],
|
'nfSeparators' => ['.', ','],
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ $lang = array(
|
|||||||
'colon' => ': ',
|
'colon' => ': ',
|
||||||
'dateFmtShort' => "Y/m/d",
|
'dateFmtShort' => "Y/m/d",
|
||||||
'dateFmtLong' => "Y/m/d \a\\t g:i A",
|
'dateFmtLong' => "Y/m/d \a\\t g:i A",
|
||||||
'dateFmtUntil' => "F j, Y",
|
'dateFmtIntl' => "MMMM d, y",
|
||||||
'timeAgo' => "%s ago",
|
'timeAgo' => "%s ago",
|
||||||
'nfSeparators' => [',', '.'],
|
'nfSeparators' => [',', '.'],
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ $lang = array(
|
|||||||
'colon' => ': ',
|
'colon' => ': ',
|
||||||
'dateFmtShort' => "d/m/Y",
|
'dateFmtShort' => "d/m/Y",
|
||||||
'dateFmtLong' => "d/m/Y \a \l\a\s g:i A",
|
'dateFmtLong' => "d/m/Y \a \l\a\s g:i A",
|
||||||
'dateFmtUntil' => "j \d\\e F \d\\e Y",
|
'dateFmtIntl' => "d 'de' MMMM 'de' y",
|
||||||
'timeAgo' => 'hace %s',
|
'timeAgo' => 'hace %s',
|
||||||
'nfSeparators' => ['.', ','],
|
'nfSeparators' => ['.', ','],
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ $lang = array(
|
|||||||
'colon' => ' : ',
|
'colon' => ' : ',
|
||||||
'dateFmtShort' => "Y-m-d",
|
'dateFmtShort' => "Y-m-d",
|
||||||
'dateFmtLong' => "Y-m-d à g:i A",
|
'dateFmtLong' => "Y-m-d à g:i A",
|
||||||
'dateFmtUntil' => "j F Y",
|
'dateFmtIntl' => "d MMMM y",
|
||||||
'timeAgo' => 'il y a %s',
|
'timeAgo' => 'il y a %s',
|
||||||
'nfSeparators' => [' ', ','],
|
'nfSeparators' => [' ', ','],
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ $lang = array(
|
|||||||
'colon' => ": ",
|
'colon' => ": ",
|
||||||
'dateFmtShort' => "Y-m-d",
|
'dateFmtShort' => "Y-m-d",
|
||||||
'dateFmtLong' => "Y-m-d в g:i A",
|
'dateFmtLong' => "Y-m-d в g:i A",
|
||||||
'dateFmtUntil' => "j F Y г.",
|
'dateFmtIntl' => "d MMMM y г.",
|
||||||
'timeAgo' => '%s назад',
|
'timeAgo' => '%s назад',
|
||||||
'nfSeparators' => [' ', ','],
|
'nfSeparators' => [' ', ','],
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ $lang = array(
|
|||||||
'colon' => ':',
|
'colon' => ':',
|
||||||
'dateFmtShort' => "Y/m/d",
|
'dateFmtShort' => "Y/m/d",
|
||||||
'dateFmtLong' => "Y/m/d \a\\t g:i A",
|
'dateFmtLong' => "Y/m/d \a\\t g:i A",
|
||||||
'dateFmtUntil' => "Y年n月j日",
|
'dateFmtIntl' => "y年M月d日",
|
||||||
'timeAgo' => '%s之前',
|
'timeAgo' => '%s之前',
|
||||||
'nfSeparators' => [',', '.'],
|
'nfSeparators' => [',', '.'],
|
||||||
|
|
||||||
|
|||||||
2
setup/updates/1758578400_13.sql
Normal file
2
setup/updates/1758578400_13.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE `aowow_account`
|
||||||
|
ADD COLUMN `renameCooldown` int unsigned NOT NULL DEFAULT 0 COMMENT 'timestamp when rename is available again' AFTER `updateValue`;
|
||||||
2
setup/updates/1758578400_14.sql
Normal file
2
setup/updates/1758578400_14.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
DELETE FROM `aowow_config` WHERE `key` = 'acc_rename_decay';
|
||||||
|
INSERT INTO `aowow_config` VALUES ('acc_rename_decay', 30 * 24 * 60 * 60, '30 * 24 * 60 * 60', 3, 129, 'delay between username changes');
|
||||||
11
template/mails/change-email_0.tpl
Normal file
11
template/mails/change-email_0.tpl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Created: 2025
|
||||||
|
Email Change Confirm
|
||||||
|
Greetings,
|
||||||
|
|
||||||
|
We received a request to change your account's email address. If you made this request, please follow the link below to confirm the change.
|
||||||
|
|
||||||
|
HOST_URL?account=confirm-email-address&key=%1$s
|
||||||
|
|
||||||
|
If you didn't request this change please feel free to disregard this email. If the link did not work or you have any further concerns about this, please contact CONTACT_EMAIL. The link will become invalid %10$s after this email was sent.
|
||||||
|
|
||||||
|
The NAME_SHORT team
|
||||||
11
template/mails/change-email_2.tpl
Normal file
11
template/mails/change-email_2.tpl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# GPTed from 2025 source
|
||||||
|
Demande de confirmation de changement d'adresse e-mail
|
||||||
|
Bonjour,
|
||||||
|
|
||||||
|
Nous avons reçu une demande de modification de l'adresse e-mail associée à votre compte. Si vous êtes à l'origine de cette demande, veuillez suivre le lien ci-dessous pour confirmer le changement.
|
||||||
|
|
||||||
|
HOST_URL?account=confirm-email-address&key=%1$s
|
||||||
|
|
||||||
|
Si vous n'avez pas demandé ce changement, vous pouvez ignorer cet e-mail. Si le lien ne fonctionne pas ou si vous avez d'autres préoccupations à ce sujet, veuillez contacter CONTACT_EMAIL. Ce lien deviendra invalide %10$s après l'envoi de cet e-mail.
|
||||||
|
|
||||||
|
L'équipe NAME_SHORT
|
||||||
11
template/mails/change-email_3.tpl
Normal file
11
template/mails/change-email_3.tpl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# GPTed from 2025 source
|
||||||
|
Bestätigung der E-Mail-Änderung angefordert
|
||||||
|
Hallo,
|
||||||
|
|
||||||
|
Wir haben eine Anfrage zur Änderung Ihrer E-Mail-Adresse erhalten. Wenn Sie diese Anfrage gestellt haben, folgen Sie bitte dem untenstehenden Link, um die Änderung zu bestätigen.
|
||||||
|
|
||||||
|
HOST_URL?account=confirm-email-address&key=%1$s
|
||||||
|
|
||||||
|
Falls Sie diese Änderung nicht angefordert haben, können Sie diese E-Mail ignorieren. Falls der Link nicht funktioniert oder Sie weitere Fragen haben, wenden Sie sich bitte an CONTACT_EMAIL. Der Link wird %10$s nach Versand dieser E-Mail ungültig.
|
||||||
|
|
||||||
|
Das Team von NAME_SHORT
|
||||||
11
template/mails/change-email_4.tpl
Normal file
11
template/mails/change-email_4.tpl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# GPTed from 2025 source
|
||||||
|
确认更改电子邮件地址
|
||||||
|
您好,
|
||||||
|
|
||||||
|
我们收到了一项更改您账户电子邮件地址的请求。如果是您本人操作,请点击下方链接以确认更改。
|
||||||
|
|
||||||
|
HOST_URL?account=confirm-email-address&key=%1$s
|
||||||
|
|
||||||
|
如果您未曾发起此更改,请忽略此邮件。如果链接无法使用或您对此有任何疑问,请联系 CONTACT_EMAIL。此链接将在本邮件发送后 %10$s 失效。
|
||||||
|
|
||||||
|
NAME_SHORT 团队敬上
|
||||||
11
template/mails/change-email_6.tpl
Normal file
11
template/mails/change-email_6.tpl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# GPTed from 2025 source
|
||||||
|
Confirmación de cambio de correo electrónico
|
||||||
|
Saludos,
|
||||||
|
|
||||||
|
Hemos recibido una solicitud para cambiar la dirección de correo electrónico de su cuenta. Si usted realizó esta solicitud, siga el enlace de abajo para confirmar el cambio.
|
||||||
|
|
||||||
|
HOST_URL?account=confirm-email-address&key=%1$s
|
||||||
|
|
||||||
|
Si usted no solicitó este cambio, puede ignorar este correo. Si el enlace no funciona o tiene alguna inquietud, por favor contacte a CONTACT_EMAIL. El enlace se invalidará %10$s después de que este correo haya sido enviado.
|
||||||
|
|
||||||
|
El equipo de NAME_SHORT
|
||||||
12
template/mails/change-email_8.tpl
Normal file
12
template/mails/change-email_8.tpl
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# GPTed from 2025 source
|
||||||
|
Подтверждение изменения адреса электронной почты
|
||||||
|
Здравствуйте,
|
||||||
|
|
||||||
|
Мы получили запрос на изменение адреса электронной почты, связанного с вашим аккаунтом. Если вы отправили этот запрос, пожалуйста, перейдите по ссылке ниже для подтверждения изменения.
|
||||||
|
|
||||||
|
HOST_URL?account=confirm-email-address&key=%1$s
|
||||||
|
|
||||||
|
Если вы не запрашивали это изменение, просто проигнорируйте это письмо. Если ссылка не работает или у вас есть дополнительные вопросы, пожалуйста, свяжитесь с CONTACT_EMAIL. Ссылка станет недействительной через %10$s после отправки этого письма.
|
||||||
|
|
||||||
|
Команда NAME_SHORT
|
||||||
|
Пожалуйста, перейдите по ссылке ниже, чтобы подтвердить ваш новый адрес электронной почты.
|
||||||
11
template/mails/revert-email_0.tpl
Normal file
11
template/mails/revert-email_0.tpl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Created: 2025
|
||||||
|
Email Change Requested
|
||||||
|
Greetings,
|
||||||
|
|
||||||
|
We received a request to change your account's email address. If you made this request, please follow the instructions in the confirmation email sent to the address indicated. If you didn't make such a request, please click the link below to prevent the email from being changed.
|
||||||
|
|
||||||
|
HOST_URL?account=revert-email-address&key=%1$s
|
||||||
|
|
||||||
|
If the link did not work or you have any further concerns about this, please contact CONTACT_EMAIL. This link will automatically become invalid %10$s from now.
|
||||||
|
|
||||||
|
The NAME_SHORT team
|
||||||
11
template/mails/revert-email_2.tpl
Normal file
11
template/mails/revert-email_2.tpl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# GPTed from 2025 source
|
||||||
|
Demande de modification d'adresse e-mail
|
||||||
|
Bonjour,
|
||||||
|
|
||||||
|
Nous avons reçu une demande de modification de l'adresse e-mail associée à votre compte. Si vous êtes à l'origine de cette demande, veuillez suivre les instructions contenues dans l'e-mail de confirmation envoyé à l'adresse indiquée. Si vous n'êtes pas à l'origine de cette demande, veuillez cliquer sur le lien ci-dessous pour empêcher la modification de l'adresse e-mail.
|
||||||
|
|
||||||
|
HOST_URL?account=revert-email-address&key=%1$s
|
||||||
|
|
||||||
|
Si le lien ne fonctionne pas ou si vous avez d'autres préoccupations à ce sujet, veuillez contacter CONTACT_EMAIL. Ce lien deviendra automatiquement invalide dans %10$s.
|
||||||
|
|
||||||
|
L'équipe NAME_SHORT
|
||||||
11
template/mails/revert-email_3.tpl
Normal file
11
template/mails/revert-email_3.tpl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# GPTed from 2025 source
|
||||||
|
E-Mail-Änderung angefordert
|
||||||
|
Hallo,
|
||||||
|
|
||||||
|
Wir haben eine Anfrage zur Änderung Ihrer E-Mail-Adresse erhalten. Wenn Sie diese Anfrage gestellt haben, folgen Sie bitte den Anweisungen in der Bestätigungs-E-Mail, die an die angegebene Adresse gesendet wurde. Falls Sie diese Anfrage nicht gestellt haben, klicken Sie bitte auf den untenstehenden Link, um die Änderung der E-Mail-Adresse zu verhindern.
|
||||||
|
|
||||||
|
HOST_URL?account=revert-email-address&key=%1$s
|
||||||
|
|
||||||
|
Falls der Link nicht funktioniert oder Sie weitere Fragen haben, wenden Sie sich bitte an CONTACT_EMAIL. Dieser Link wird automatisch nach %%10$s ungültig.
|
||||||
|
|
||||||
|
Ihr NAME_SHORT-Team
|
||||||
11
template/mails/revert-email_4.tpl
Normal file
11
template/mails/revert-email_4.tpl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# GPTed from 2025 source
|
||||||
|
请求更改电子邮件地址
|
||||||
|
您好,
|
||||||
|
|
||||||
|
我们收到了一项更改您账户电子邮件地址的请求。如果是您本人操作,请按照发送到指定地址的确认邮件中的说明进行操作。如果不是您本人操作,请点击下方链接以阻止电子邮件地址的更改。
|
||||||
|
|
||||||
|
HOST_URL?account=revert-email-address&key=%1$s
|
||||||
|
|
||||||
|
如果链接无法使用或您对此有任何疑问,请联系 CONTACT_EMAIL。此链接将在 %10$s 后自动失效。
|
||||||
|
|
||||||
|
NAME_SHORT 团队敬上
|
||||||
11
template/mails/revert-email_6.tpl
Normal file
11
template/mails/revert-email_6.tpl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# GPTed from 2025 source
|
||||||
|
Solicitud de cambio de correo electrónico
|
||||||
|
Saludos,
|
||||||
|
|
||||||
|
Hemos recibido una solicitud para cambiar la dirección de correo electrónico de su cuenta. Si usted realizó esta solicitud, siga las instrucciones en el correo de confirmación enviado a la dirección indicada. Si no realizó esta solicitud, haga clic en el enlace de abajo para evitar el cambio de correo electrónico.
|
||||||
|
|
||||||
|
HOST_URL?account=revert-email-address&key=%1$s
|
||||||
|
|
||||||
|
Si el enlace no funciona o tiene alguna inquietud, por favor contacte a CONTACT_EMAIL. Este enlace se invalidará automáticamente en %10$s.
|
||||||
|
|
||||||
|
El equipo de NAME_SHORT
|
||||||
11
template/mails/revert-email_8.tpl
Normal file
11
template/mails/revert-email_8.tpl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# GPTed from 2025 source
|
||||||
|
Запрос на изменение адреса электронной почты
|
||||||
|
Здравствуйте,
|
||||||
|
|
||||||
|
Мы получили запрос на изменение адреса электронной почты, связанного с вашим аккаунтом. Если вы отправили этот запрос, пожалуйста, следуйте инструкциям в письме с подтверждением, отправленном на указанный адрес. Если вы не отправляли такой запрос, пожалуйста, перейдите по ссылке ниже, чтобы предотвратить изменение адреса электронной почты.
|
||||||
|
|
||||||
|
HOST_URL?account=revert-email-address&key=%1$s
|
||||||
|
|
||||||
|
Если ссылка не работает или у вас есть дополнительные вопросы, пожалуйста, свяжитесь с CONTACT_EMAIL. Эта ссылка автоматически станет недействительной через %10$s.
|
||||||
|
|
||||||
|
Команда NAME_SHORT
|
||||||
10
template/mails/update-password_0.tpl
Normal file
10
template/mails/update-password_0.tpl
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Created: May 2025
|
||||||
|
Password Confirmation
|
||||||
|
Hey!
|
||||||
|
|
||||||
|
Please click the link below to confirm your new password.
|
||||||
|
HOST_URL?account=confirm-password&key=%1$s
|
||||||
|
|
||||||
|
Let us know if you have any problems!
|
||||||
|
|
||||||
|
The NAME_SHORT team
|
||||||
10
template/mails/update-password_2.tpl
Normal file
10
template/mails/update-password_2.tpl
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Created: May 2025
|
||||||
|
Confirmation du mot de passe
|
||||||
|
Bonjour !
|
||||||
|
|
||||||
|
Veuillez cliquer sur le lien ci-dessous pour confirmer votre nouveau mot de passe.
|
||||||
|
HOST_URL?account=confirm-password&key=%1$s
|
||||||
|
|
||||||
|
Faites-nous savoir si vous rencontrez des problèmes !
|
||||||
|
|
||||||
|
L'équipe NAME_SHORT
|
||||||
10
template/mails/update-password_3.tpl
Normal file
10
template/mails/update-password_3.tpl
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Created: May 2025
|
||||||
|
Passwortbestätigung
|
||||||
|
Hallo!
|
||||||
|
|
||||||
|
Bitte klicke auf den untenstehenden Link, um dein neues Passwort zu bestätigen.
|
||||||
|
HOST_URL?account=confirm-password&key=%1$s
|
||||||
|
|
||||||
|
Lass uns wissen, falls du Probleme hast!
|
||||||
|
|
||||||
|
Das NAME_SHORT Team
|
||||||
10
template/mails/update-password_4.tpl
Normal file
10
template/mails/update-password_4.tpl
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Created by ChatGPT from May 2025 base; locale 0
|
||||||
|
密码确认
|
||||||
|
你好!
|
||||||
|
|
||||||
|
请点击下面的链接以确认你的新密码。
|
||||||
|
HOST_URL?account=confirm-password&key=%1$s
|
||||||
|
|
||||||
|
如果你有任何问题,请告诉我们!
|
||||||
|
|
||||||
|
NAME_SHORT 团队敬上
|
||||||
10
template/mails/update-password_6.tpl
Normal file
10
template/mails/update-password_6.tpl
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Created: May 2025
|
||||||
|
Confirmación de contraseña
|
||||||
|
¡Hola!
|
||||||
|
|
||||||
|
Por favor, haz clic en el siguiente enlace para confirmar tu nueva contraseña.
|
||||||
|
HOST_URL?account=confirm-password&key=%1$s
|
||||||
|
|
||||||
|
¡Avísanos si tienes algún problema!
|
||||||
|
|
||||||
|
El equipo de NAME_SHORT
|
||||||
10
template/mails/update-password_8.tpl
Normal file
10
template/mails/update-password_8.tpl
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Created: May 2025
|
||||||
|
Подтверждение пароля
|
||||||
|
Здравствуйте!
|
||||||
|
|
||||||
|
Пожалуйста, перейдите по ссылке ниже, чтобы подтвердить ваш новый пароль.
|
||||||
|
HOST_URL?account=confirm-password&key=%1$s
|
||||||
|
|
||||||
|
Сообщите нам, если у вас возникнут какие-либо проблемы!
|
||||||
|
|
||||||
|
Команда NAME_SHORT
|
||||||
@@ -110,9 +110,9 @@ if ($this->bans):
|
|||||||
<div class="box"><div class="msg-<?=($type ? 'success' : 'failure');?>"><?=$msg;?></div></div>
|
<div class="box"><div class="msg-<?=($type ? 'success' : 'failure');?>"><?=$msg;?></div></div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div><?=Lang::account('usernameNote');?></div>
|
<div><?=Lang::account('usernameNote', [$this->renameCD]);?></div>
|
||||||
<?php if ($this->renameCD): ?>
|
<?php if ($this->activeCD): ?>
|
||||||
<div class="msg-failure pad3"><br /><?=Lang::account('renameCD', [$this->renameCD]);?></div>
|
<div class="msg-failure pad3"><br /><?=Lang::account('activeCD', [$this->activeCD]);?></div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<form action="?account=update-username" name="ce" method="post" id="change-username">
|
<form action="?account=update-username" name="ce" method="post" id="change-username">
|
||||||
<table cellspacing="5" cellpadding="0" border="0">
|
<table cellspacing="5" cellpadding="0" border="0">
|
||||||
|
|||||||
Reference in New Issue
Block a user