diff --git a/README.md b/README.md index 44bea61d..cc69e630 100644 --- a/README.md +++ b/README.md @@ -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) + [Multibyte String](https://www.php.net/manual/en/book.mbstring.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) + 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) diff --git a/endpoints/account/account.php b/endpoints/account/account.php index cd57c720..e560a55e 100644 --- a/endpoints/account/account.php +++ b/endpoints/account/account.php @@ -28,6 +28,7 @@ class AccountBaseResponse extends TemplateResponse public string $curEmail = ''; public string $curName = ''; public string $renameCD = ''; + public string $activeCD = ''; public array $description = []; public array $signature = []; public int $avMode = 0; @@ -51,7 +52,7 @@ class AccountBaseResponse extends TemplateResponse { 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'); @@ -108,10 +109,13 @@ class AccountBaseResponse extends TemplateResponse $this->curEmail = $user['email'] ?? ''; // Username - $this->curName = User::$username; - - // todo localize date format; store time - // $this->renameCD = date('F j, o', time() + 7 * DAY); + $this->curName = User::$username; + $this->renameCD = Util::formatTime(Cfg::get('ACC_RENAME_DECAY') * 1000); + if ($user['renameCooldown'] > time()) + { + $locCode = implode('_', str_split(Lang::getLocale()->json(), 2)); // ._. + $this->activeCD = (new \IntlDateFormatter($locCode, pattern: Lang::main('dateFmtIntl')))->format($user['renameCooldown']); + } /* COMMUNITY */ diff --git a/endpoints/account/confirm-email-address.php b/endpoints/account/confirm-email-address.php new file mode 100644 index 00000000..eb11801c --- /dev/null +++ b/endpoints/account/confirm-email-address.php @@ -0,0 +1,62 @@ + ['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'); + } +} + +?> diff --git a/endpoints/account/confirm-password.php b/endpoints/account/confirm-password.php new file mode 100644 index 00000000..4eec91f0 --- /dev/null +++ b/endpoints/account/confirm-password.php @@ -0,0 +1,60 @@ + ['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'); + } +} + +?> diff --git a/endpoints/account/revert-email-address.php b/endpoints/account/revert-email-address.php new file mode 100644 index 00000000..37475082 --- /dev/null +++ b/endpoints/account/revert-email-address.php @@ -0,0 +1,62 @@ + ['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'); + } +} + +?> diff --git a/endpoints/account/update-email.php b/endpoints/account/update-email.php new file mode 100644 index 00000000..104e18a5 --- /dev/null +++ b/endpoints/account/update-email.php @@ -0,0 +1,80 @@ + ['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']]); + } +} + +?> diff --git a/endpoints/account/update-password.php b/endpoints/account/update-password.php new file mode 100644 index 00000000..cc4151d6 --- /dev/null +++ b/endpoints/account/update-password.php @@ -0,0 +1,86 @@ + ['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]); + } +} + +?> diff --git a/endpoints/account/update-username.php b/endpoints/account/update-username.php new file mode 100644 index 00000000..d301fb6a --- /dev/null +++ b/endpoints/account/update-username.php @@ -0,0 +1,61 @@ + ['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']]); + } +} + +?> diff --git a/includes/kernel.php b/includes/kernel.php index 4d444d5a..7145501d 100644 --- a/includes/kernel.php +++ b/includes/kernel.php @@ -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)))); -$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring', 'fileinfo'/*, 'gmp'*/]; +$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring', 'fileinfo', 'intl'/*, 'gmp'*/]; $badExt = []; $error = ''; if ($ext = array_filter($reqExt, fn($x) => !extension_loaded($x))) diff --git a/localization/locale_dede.php b/localization/locale_dede.php index 71e46780..23ff084b 100644 --- a/localization/locale_dede.php +++ b/localization/locale_dede.php @@ -133,7 +133,7 @@ $lang = array( 'colon' => ': ', 'dateFmtShort' => "d.m.Y", 'dateFmtLong' => "d.m.Y \u\m H:i", - 'dateFmtUntil' => "j. F Y", + 'dateFmtIntl' => "d. MMMM y", 'timeAgo' => 'vor %s', 'nfSeparators' => ['.', ','], diff --git a/localization/locale_enus.php b/localization/locale_enus.php index 812c3606..670ec5e9 100644 --- a/localization/locale_enus.php +++ b/localization/locale_enus.php @@ -133,7 +133,7 @@ $lang = array( 'colon' => ': ', 'dateFmtShort' => "Y/m/d", 'dateFmtLong' => "Y/m/d \a\\t g:i A", - 'dateFmtUntil' => "F j, Y", + 'dateFmtIntl' => "MMMM d, y", 'timeAgo' => "%s ago", 'nfSeparators' => [',', '.'], diff --git a/localization/locale_eses.php b/localization/locale_eses.php index 385861b1..9e5af257 100644 --- a/localization/locale_eses.php +++ b/localization/locale_eses.php @@ -133,7 +133,7 @@ $lang = array( 'colon' => ': ', 'dateFmtShort' => "d/m/Y", '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', 'nfSeparators' => ['.', ','], diff --git a/localization/locale_frfr.php b/localization/locale_frfr.php index 1974541e..cd982692 100644 --- a/localization/locale_frfr.php +++ b/localization/locale_frfr.php @@ -133,7 +133,7 @@ $lang = array( 'colon' => ' : ', 'dateFmtShort' => "Y-m-d", 'dateFmtLong' => "Y-m-d à g:i A", - 'dateFmtUntil' => "j F Y", + 'dateFmtIntl' => "d MMMM y", 'timeAgo' => 'il y a %s', 'nfSeparators' => [' ', ','], diff --git a/localization/locale_ruru.php b/localization/locale_ruru.php index 64a925d9..5f702169 100644 --- a/localization/locale_ruru.php +++ b/localization/locale_ruru.php @@ -133,7 +133,7 @@ $lang = array( 'colon' => ": ", 'dateFmtShort' => "Y-m-d", 'dateFmtLong' => "Y-m-d в g:i A", - 'dateFmtUntil' => "j F Y г.", + 'dateFmtIntl' => "d MMMM y г.", 'timeAgo' => '%s назад', 'nfSeparators' => [' ', ','], diff --git a/localization/locale_zhcn.php b/localization/locale_zhcn.php index 4d710049..e184e6dd 100644 --- a/localization/locale_zhcn.php +++ b/localization/locale_zhcn.php @@ -133,7 +133,7 @@ $lang = array( 'colon' => ':', 'dateFmtShort' => "Y/m/d", 'dateFmtLong' => "Y/m/d \a\\t g:i A", - 'dateFmtUntil' => "Y年n月j日", + 'dateFmtIntl' => "y年M月d日", 'timeAgo' => '%s之前', 'nfSeparators' => [',', '.'], diff --git a/setup/updates/1758578400_13.sql b/setup/updates/1758578400_13.sql new file mode 100644 index 00000000..c055f944 --- /dev/null +++ b/setup/updates/1758578400_13.sql @@ -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`; diff --git a/setup/updates/1758578400_14.sql b/setup/updates/1758578400_14.sql new file mode 100644 index 00000000..3445704e --- /dev/null +++ b/setup/updates/1758578400_14.sql @@ -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'); diff --git a/template/mails/change-email_0.tpl b/template/mails/change-email_0.tpl new file mode 100644 index 00000000..58a92f10 --- /dev/null +++ b/template/mails/change-email_0.tpl @@ -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 diff --git a/template/mails/change-email_2.tpl b/template/mails/change-email_2.tpl new file mode 100644 index 00000000..c9743068 --- /dev/null +++ b/template/mails/change-email_2.tpl @@ -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 diff --git a/template/mails/change-email_3.tpl b/template/mails/change-email_3.tpl new file mode 100644 index 00000000..8abae027 --- /dev/null +++ b/template/mails/change-email_3.tpl @@ -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 diff --git a/template/mails/change-email_4.tpl b/template/mails/change-email_4.tpl new file mode 100644 index 00000000..9fbd9efa --- /dev/null +++ b/template/mails/change-email_4.tpl @@ -0,0 +1,11 @@ +# GPTed from 2025 source +确认更改电子邮件地址 +您好, + +我们收到了一项更改您账户电子邮件地址的请求。如果是您本人操作,请点击下方链接以确认更改。 + +HOST_URL?account=confirm-email-address&key=%1$s + +如果您未曾发起此更改,请忽略此邮件。如果链接无法使用或您对此有任何疑问,请联系 CONTACT_EMAIL。此链接将在本邮件发送后 %10$s 失效。 + +NAME_SHORT 团队敬上 diff --git a/template/mails/change-email_6.tpl b/template/mails/change-email_6.tpl new file mode 100644 index 00000000..16aabc7b --- /dev/null +++ b/template/mails/change-email_6.tpl @@ -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 diff --git a/template/mails/change-email_8.tpl b/template/mails/change-email_8.tpl new file mode 100644 index 00000000..aaeeed88 --- /dev/null +++ b/template/mails/change-email_8.tpl @@ -0,0 +1,12 @@ +# GPTed from 2025 source +Подтверждение изменения адреса электронной почты +Здравствуйте, + +Мы получили запрос на изменение адреса электронной почты, связанного с вашим аккаунтом. Если вы отправили этот запрос, пожалуйста, перейдите по ссылке ниже для подтверждения изменения. + +HOST_URL?account=confirm-email-address&key=%1$s + +Если вы не запрашивали это изменение, просто проигнорируйте это письмо. Если ссылка не работает или у вас есть дополнительные вопросы, пожалуйста, свяжитесь с CONTACT_EMAIL. Ссылка станет недействительной через %10$s после отправки этого письма. + +Команда NAME_SHORT +Пожалуйста, перейдите по ссылке ниже, чтобы подтвердить ваш новый адрес электронной почты. diff --git a/template/mails/revert-email_0.tpl b/template/mails/revert-email_0.tpl new file mode 100644 index 00000000..881c02f9 --- /dev/null +++ b/template/mails/revert-email_0.tpl @@ -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 diff --git a/template/mails/revert-email_2.tpl b/template/mails/revert-email_2.tpl new file mode 100644 index 00000000..b9b37958 --- /dev/null +++ b/template/mails/revert-email_2.tpl @@ -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 diff --git a/template/mails/revert-email_3.tpl b/template/mails/revert-email_3.tpl new file mode 100644 index 00000000..4ccc7af9 --- /dev/null +++ b/template/mails/revert-email_3.tpl @@ -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 diff --git a/template/mails/revert-email_4.tpl b/template/mails/revert-email_4.tpl new file mode 100644 index 00000000..ecc86e88 --- /dev/null +++ b/template/mails/revert-email_4.tpl @@ -0,0 +1,11 @@ +# GPTed from 2025 source +请求更改电子邮件地址 +您好, + +我们收到了一项更改您账户电子邮件地址的请求。如果是您本人操作,请按照发送到指定地址的确认邮件中的说明进行操作。如果不是您本人操作,请点击下方链接以阻止电子邮件地址的更改。 + +HOST_URL?account=revert-email-address&key=%1$s + +如果链接无法使用或您对此有任何疑问,请联系 CONTACT_EMAIL。此链接将在 %10$s 后自动失效。 + +NAME_SHORT 团队敬上 diff --git a/template/mails/revert-email_6.tpl b/template/mails/revert-email_6.tpl new file mode 100644 index 00000000..2fbf927b --- /dev/null +++ b/template/mails/revert-email_6.tpl @@ -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 diff --git a/template/mails/revert-email_8.tpl b/template/mails/revert-email_8.tpl new file mode 100644 index 00000000..b257ad2a --- /dev/null +++ b/template/mails/revert-email_8.tpl @@ -0,0 +1,11 @@ +# GPTed from 2025 source +Запрос на изменение адреса электронной почты +Здравствуйте, + +Мы получили запрос на изменение адреса электронной почты, связанного с вашим аккаунтом. Если вы отправили этот запрос, пожалуйста, следуйте инструкциям в письме с подтверждением, отправленном на указанный адрес. Если вы не отправляли такой запрос, пожалуйста, перейдите по ссылке ниже, чтобы предотвратить изменение адреса электронной почты. + +HOST_URL?account=revert-email-address&key=%1$s + +Если ссылка не работает или у вас есть дополнительные вопросы, пожалуйста, свяжитесь с CONTACT_EMAIL. Эта ссылка автоматически станет недействительной через %10$s. + +Команда NAME_SHORT diff --git a/template/mails/update-password_0.tpl b/template/mails/update-password_0.tpl new file mode 100644 index 00000000..d55404cb --- /dev/null +++ b/template/mails/update-password_0.tpl @@ -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 diff --git a/template/mails/update-password_2.tpl b/template/mails/update-password_2.tpl new file mode 100644 index 00000000..e971a03a --- /dev/null +++ b/template/mails/update-password_2.tpl @@ -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 diff --git a/template/mails/update-password_3.tpl b/template/mails/update-password_3.tpl new file mode 100644 index 00000000..348a7abb --- /dev/null +++ b/template/mails/update-password_3.tpl @@ -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 diff --git a/template/mails/update-password_4.tpl b/template/mails/update-password_4.tpl new file mode 100644 index 00000000..affa20f4 --- /dev/null +++ b/template/mails/update-password_4.tpl @@ -0,0 +1,10 @@ +# Created by ChatGPT from May 2025 base; locale 0 +密码确认 +你好! + +请点击下面的链接以确认你的新密码。 +HOST_URL?account=confirm-password&key=%1$s + +如果你有任何问题,请告诉我们! + +NAME_SHORT 团队敬上 diff --git a/template/mails/update-password_6.tpl b/template/mails/update-password_6.tpl new file mode 100644 index 00000000..b46dd849 --- /dev/null +++ b/template/mails/update-password_6.tpl @@ -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 diff --git a/template/mails/update-password_8.tpl b/template/mails/update-password_8.tpl new file mode 100644 index 00000000..9266fa1d --- /dev/null +++ b/template/mails/update-password_8.tpl @@ -0,0 +1,10 @@ +# Created: May 2025 +Подтверждение пароля +Здравствуйте! + +Пожалуйста, перейдите по ссылке ниже, чтобы подтвердить ваш новый пароль. +HOST_URL?account=confirm-password&key=%1$s + +Сообщите нам, если у вас возникнут какие-либо проблемы! + +Команда NAME_SHORT diff --git a/template/pages/account.tpl.php b/template/pages/account.tpl.php index ca64947c..fe9b076b 100644 --- a/template/pages/account.tpl.php +++ b/template/pages/account.tpl.php @@ -110,9 +110,9 @@ if ($this->bans):
-
-renameCD): ?> -

renameCD]);?>
+
renameCD]);?>
+activeCD): ?> +

activeCD]);?>