diff --git a/CHANGELOG.md b/CHANGELOG.md index 66117c5d..98dc3f4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,35 @@ # Changelog +## [1.0-RC -23.07.2024] + +Changes since 1.0-beta: + +### Added +* Feat: Hooks priority (https://github.com/slawkens/myaac/commit/dc17b701da053e04bfa64e21be9247a4f07505e1) +* Make autoload of pages, commands and themes configurable (https://github.com/slawkens/myaac/commit/c1d4b4f80cd6bb85507ee9471e47013955a26a91) +* Fraggers in characters page for TFS 1.x and canary (https://github.com/slawkens/myaac/commit/42f99c3edc8de39cccc5632cb42e88b24579c5a6) +* New hooks: HOOK_INSTALL_FINISH, HOOK_ACCOUNT_CREATE_CHARACTER_* (https://github.com/slawkens/myaac/commit/08ac8ebade106521a5c7396faa5ce7006e629f7c, https://github.com/slawkens/myaac/commit/45dda5e834ff2059faea6ef9be2efa76f1723cbd) + +### Changed +* Allow account_create_character_create even if account_mail_verify is activated (https://github.com/slawkens/myaac/commit/203e411b626fe62401a4b74a48420769e512aa39) +* Create guild_rank entries, in case MySQL trigger not loaded (https://github.com/slawkens/myaac/commit/d9c1b2507c81f306970642b35e4bf5f7cc04a6f2, https://github.com/slawkens/myaac/commit/47a19e85dd84e9f3b39a1b29cfc2c04b004832b9) +* Set Admin Account verified by default (https://github.com/slawkens/myaac/commit/cd49dfc79942f3301ce9c0b8d899b9f39bda9a41) +* Refactor account routes into sub folders (https://github.com/slawkens/myaac/commit/bdc0c43d3fd3a51030c3e916bdb9f008468f5ecd) +* Order towns by id (https://github.com/slawkens/myaac/commit/9ea2a5067fc4b75de395f381577b18914132ad84) +* Do not create news about myaac, if any news already exist (on installation (https://github.com/slawkens/myaac/commit/504242fb846b73b56b87bc1e39d070687ad7f5b4) + +### Fixed +* Not working google recaptcha plugin (https://github.com/slawkens/myaac/commit/a1bcb217ecf4e21fd58da4ba491da1852029898a) +* Not working account create if account_country is disabled (https://github.com/slawkens/myaac/commit/933b681a9fcdbb6283e0469b3806d2ded492d232) +* Account verify - do not allow login without verified email (Thanks @anyeor, https://github.com/slawkens/myaac/commit/fcb13f3c0fb8ceafda0bd614a229a26a269432bd) +* Detect tools/ext exists on install to prevent broken installs (https://github.com/slawkens/myaac/commit/10a739773c4f2911876bc802a0ee0537c3e00a92) +* Cache reloading each time page refreshes (https://github.com/slawkens/myaac/commit/ec96985872057340112f65073efc0c4bf86dddb0) +* Highscores frags for TFS 1.x and canary (https://github.com/slawkens/myaac/commit/a04d186c22912915f0a7873dfe677ef3b5a23c79) +* Monsters page: monster not found exception (https://github.com/slawkens/myaac/commit/ef79b99b8acc179f14b8475547347d9daca27512) +* Fixed bug if \ are not present in monster.xml (https://github.com/slawkens/myaac/commit/57b47ab7983f625c7c0ef4f5303a4d07ef172786) +* fastRoute duplicate errors (https://github.com/slawkens/myaac/commit/4c0739d3e93812dff0c33849ea3f38e4e49113ac) +* useGuildNick displaying (https://github.com/slawkens/myaac/commit/0db0ec1aa47e044c26bc403ff5078a2115d086f8) + ## [1.0-beta - 18.05.2024] Minimum PHP version for this release is 8.1. diff --git a/admin/pages/accounts.php b/admin/pages/accounts.php index d42a2ee6..767b6e7f 100644 --- a/admin/pages/accounts.php +++ b/admin/pages/accounts.php @@ -8,6 +8,7 @@ * @link https://my-aac.org */ +use MyAAC\Models\Account as AccountModel; use MyAAC\Models\Player; defined('MYAAC') or die('Direct access not allowed!'); @@ -51,36 +52,51 @@ $acc_type = setting('core.account_types'); limit(11)->get(['email', 'id']); + if (count($accountModel) == 0) { + echo_error('No entries found.'); + } else if (count($accountModel) == 1) { + $id = $accountModel->first()->getKey(); + } else if (count($accountModel) > 10) { + echo_error('Specified e-mail resulted with too many accounts.'); + } +} else if (isset($_REQUEST['search'])) { $search_account = $_REQUEST['search']; - if (strlen($search_account) < 3 && !Validator::number($search_account)) { - echo_error('Player name is too short.'); + $min_size = 3; + if ($nameOrNumberColumn == 'number') { + $min_size = 1; + } + + if (strlen($search_account) < $min_size && !Validator::number($search_account)) { + echo_error('Account ' . $nameOrNumberColumn . ' is too short.'); } else { - $query = $db->query('SELECT `id` FROM `accounts` WHERE `' . $nameOrNumberColumn . '` = ' . $db->quote($search_account)); - if ($query->rowCount() == 1) { - $query = $query->fetch(); - $id = (int)$query['id']; + $query = AccountModel::where($nameOrNumberColumn, '=', $search_account)->limit(11)->get(['id', $nameOrNumberColumn]); + if (count($query) == 0) { + echo_error('No entries found.'); + } else if (count($query) == 1) { + $id = $query->first()->getKey(); + } else if (count($query) > 10) { + echo_error('Specified name resulted with too many accounts.'); } else { - $query = $db->query('SELECT `id`, `' . $nameOrNumberColumn . '` FROM `accounts` WHERE `' . $nameOrNumberColumn . '` LIKE ' . $db->quote('%' . $search_account . '%')); - if ($query->rowCount() > 0 && $query->rowCount() <= 10) { - $str_construct = 'Do you mean?'; - echo_error($str_construct); - } else if ($query->rowCount() > 10) - echo_error('Specified name resulted with too many accounts.'); - else - echo_error('No entries found.'); + $str_construct = 'Do you mean?'; + echo_error($str_construct); } } } ?>
0) { $account = new OTS_Account(); $account->load($id); @@ -143,7 +159,9 @@ else if (isset($_REQUEST['search'])) { $rl_loca = $_POST['rl_loca']; //country - $rl_country = $_POST['rl_country']; + if(setting('core.account_country')) { + $rl_country = $_POST['rl_country']; + } $web_flags = $_POST['web_flags']; verify_number($web_flags, 'Web Flags', 1); @@ -190,7 +208,11 @@ else if (isset($_REQUEST['search'])) { } $account->setRLName($rl_name); $account->setLocation($rl_loca); - $account->setCountry($rl_country); + + if(setting('core.account_country')) { + $account->setCountry($rl_country); + } + $account->setCustomField('created', $created); $account->setWebFlags($web_flags); $account->setCustomField('web_lastlogin', $web_lastlogin); @@ -214,7 +236,7 @@ else if (isset($_REQUEST['search'])) { } } } else if ($id == 0) { - $accounts_db = $db->query('SELECT `id`, `' . $nameOrNumberColumn . '`' . ($hasTypeColumn ? ',type' : ($hasGroupColumn ? ',group_id' : '')) . ' FROM `accounts` ORDER BY `id` ASC'); + $accounts_db = $db->query('SELECT `id`, `' . $nameOrNumberColumn . '`' . ($hasTypeColumn ? ',type' : ($hasGroupColumn ? ',group_id' : '')) . ', email FROM `accounts` ORDER BY `id` ASC'); ?>
@@ -228,6 +250,7 @@ else if (isset($_REQUEST['search'])) { ID + E-Mail Position Edit @@ -238,6 +261,7 @@ else if (isset($_REQUEST['search'])) { +
+
+
+ + +
+ + +
+
+
diff --git a/admin/pages/mailer.php b/admin/pages/mailer.php index d9cf8888..1f8d3188 100644 --- a/admin/pages/mailer.php +++ b/admin/pages/mailer.php @@ -7,6 +7,9 @@ * @copyright 2019 MyAAC * @link https://my-aac.org */ + +use MyAAC\Models\Account; + defined('MYAAC') or die('Direct access not allowed!'); $title = 'Mailer'; @@ -61,15 +64,15 @@ if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) { $add = ' AND `email_verified` = 1'; } - $query = $db->query('SELECT `email` FROM `accounts` WHERE `email` != ""' . $add); + $query = Account::where('email', '!=', '')->get(['email']); foreach ($query as $email) { - if (_mail($email['email'], $mail_subject, $mail_content)) { + if (_mail($email->email, $mail_subject, $mail_content)) { $success++; } else { $failed++; echo '
'; - error('An error occorred while sending email to ' . $email['email'] . '. For Admin: More info can be found in system/logs/mailer-error.log'); + error('An error occorred while sending email to ' . $email->email . '. For Admin: More info can be found in system/logs/mailer-error.log'); } } diff --git a/admin/pages/mass_account.php b/admin/pages/mass_account.php index dc921ac5..46c9bc9d 100644 --- a/admin/pages/mass_account.php +++ b/admin/pages/mass_account.php @@ -24,20 +24,13 @@ $freePremium = $config['lua']['freePremium']; function admin_give_points($points) { - global $db, $hasPointsColumn; + global $hasPointsColumn; if (!$hasPointsColumn) { displayMessage('Points not supported.'); return; } - - $statement = $db->prepare('UPDATE `accounts` SET `premium_points` = `premium_points` + :points'); - if (!$statement) { - displayMessage('Failed to prepare query statement.'); - return; - } - if (!Account::query()->increment('premium_points', $points)) { displayMessage('Failed to add points.'); return; @@ -47,7 +40,7 @@ function admin_give_points($points) function admin_give_coins($coins) { - global $db, $hasCoinsColumn; + global $hasCoinsColumn; if (!$hasCoinsColumn) { displayMessage('Coins not supported.'); @@ -62,24 +55,6 @@ function admin_give_coins($coins) displayMessage($coins . ' coins added to all accounts.', true); } -function query_add_premium($column, $value_query, $condition_query = '1=1', $params = []) -{ - global $db; - - $statement = $db->prepare("UPDATE `accounts` SET `{$column}` = $value_query WHERE $condition_query"); - if (!$statement) { - displayMessage('Failed to prepare query statement.'); - return false; - } - - if (!$statement->execute($params)) { - displayMessage('Failed to add premium days.'); - return false; - } - - return true; -} - function admin_give_premdays($days) { global $db, $freePremium; @@ -94,9 +69,9 @@ function admin_give_premdays($days) // othire if ($db->hasColumn('accounts', 'premend')) { // append premend - if (query_add_premium('premend', '`premend` + :value', '`premend` > :now', ['value' => $value, 'now' => $now])) { + if (Account::where('premend', '>', $now)->increment('premend', $value)) { // set premend - if (query_add_premium('premend', ':value', '`premend` <= :now', ['value' => $now + $value, 'now' => $now])) { + if (Account::where('premend', '<=', $now)->update(['premend' => $now + $value])) { displayMessage($days . ' premium days added to all accounts.', true); return; } else { @@ -114,11 +89,11 @@ function admin_give_premdays($days) // tfs 0.x if ($db->hasColumn('accounts', 'premdays')) { // append premdays - if (query_add_premium('premdays', '`premdays` + :value', '1=1', ['value' => $days])) { + if (Account::query()->update(['premdays' => $days])) { // append lastday - if (query_add_premium('lastday', '`lastday` + :value', '`lastday` > :now', ['value' => $value, 'now' => $now])) { + if (Account::where('lastday', '>', $now)->increment('lastday', $value)) { // set lastday - if (query_add_premium('lastday', ':value', '`lastday` <= :now', ['value' => $now + $value, 'now' => $now])) { + if (Account::where('lastday', '<=', $now)->update(['lastday' => $now + $value])) { displayMessage($days . ' premium days added to all accounts.', true); return; } else { @@ -142,9 +117,9 @@ function admin_give_premdays($days) // tfs 1.x if ($db->hasColumn('accounts', 'premium_ends_at')) { // append premium_ends_at - if (query_add_premium('premium_ends_at', '`premium_ends_at` + :value', '`premium_ends_at` > :now', ['value' => $value, 'now' => $now])) { + if (Account::where('premium_ends_at', '>', $now)->increment('premium_ends_at', $value)) { // set premium_ends_at - if (query_add_premium('premium_ends_at', ':value', '`premium_ends_at` <= :now', ['value' => $now + $value, 'now' => $now])) { + if (Account::where('premium_ends_at', '<=', $now)->update(['premium_ends_at' => $now + $value])) { displayMessage($days . ' premium days added to all accounts.', true); return; } else { diff --git a/admin/pages/players.php b/admin/pages/players.php index e8084afd..c44bc012 100644 --- a/admin/pages/players.php +++ b/admin/pages/players.php @@ -51,22 +51,20 @@ else if (isset($_REQUEST['search'])) { if (strlen($search_player) < 3 && !Validator::number($search_player)) { echo_error('Player name is too short.'); } else { - $query = $db->query('SELECT `id` FROM `players` WHERE `name` = ' . $db->quote($search_player)); - if ($query->rowCount() == 1) { - $query = $query->fetch(); - $id = (int)$query['id']; + $query = Player::where('name', 'like', '%' . $search_player . '%')->orderBy('name')->limit(11)->get(['id', 'name']); + if (count($query) == 0) { + echo_error('No entries found.'); + } else if (count($query) == 1) { + $id = $query->first()->getKey(); + } else if (count($query) > 10) { + echo_error('Specified name resulted with too many players.'); } else { - $query = $db->query('SELECT `id`, `name` FROM `players` WHERE `name` LIKE ' . $db->quote('%' . $search_player . '%')); - if ($query->rowCount() > 0 && $query->rowCount() <= 10) { - $str_construct = 'Do you mean?'; - echo_error($str_construct); - } else if ($query->rowCount() > 10) - echo_error('Specified name resulted with too many players.'); - else - echo_error('No entries found.'); + $str_construct = 'Do you mean?
    '; + foreach ($query as $row) { + $str_construct .= '
  • ' . $row->name . '
  • '; + } + $str_construct .= '
'; + echo_error($str_construct); } } } @@ -307,7 +305,7 @@ else if (isset($_REQUEST['search'])) { } } } else if ($id == 0) { - $players_db = $db->query('SELECT `id`, `name`, `level` FROM `players` ORDER BY `id` asc'); + $players_db = Player::orderBy('id')->get(['id','name', 'level']); ?>
@@ -327,11 +325,11 @@ else if (isset($_REQUEST['search'])) { - - - + id; ?> + name; ?> + level; ?> - + diff --git a/common.php b/common.php index 2057e972..a74a654b 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.0-beta.2'; +const MYAAC_VERSION = '1.0-RC'; const DATABASE_VERSION = 40; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); diff --git a/composer.lock b/composer.lock index ea12d783..b7a2e62e 100644 --- a/composer.lock +++ b/composer.lock @@ -137,16 +137,16 @@ }, { "name": "composer/semver", - "version": "3.4.0", + "version": "3.4.2", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "url": "https://api.github.com/repos/composer/semver/zipball/c51258e759afdb17f1fd1fe83bc12baaef6309d6", + "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6", "shasum": "" }, "require": { @@ -198,7 +198,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.0" + "source": "https://github.com/composer/semver/tree/3.4.2" }, "funding": [ { @@ -214,7 +214,7 @@ "type": "tidelift" } ], - "time": "2023-08-31T09:50:34+00:00" + "time": "2024-07-12T11:35:52+00:00" }, { "name": "doctrine/inflector", @@ -491,16 +491,16 @@ }, { "name": "illuminate/collections", - "version": "v10.48.10", + "version": "v10.48.16", "source": { "type": "git", "url": "https://github.com/illuminate/collections.git", - "reference": "f9589f1063a449111dcaa1d68285b507d9483a95" + "reference": "37c863cffb345869dd134eff8e646bc82a19cc96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/collections/zipball/f9589f1063a449111dcaa1d68285b507d9483a95", - "reference": "f9589f1063a449111dcaa1d68285b507d9483a95", + "url": "https://api.github.com/repos/illuminate/collections/zipball/37c863cffb345869dd134eff8e646bc82a19cc96", + "reference": "37c863cffb345869dd134eff8e646bc82a19cc96", "shasum": "" }, "require": { @@ -542,11 +542,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-03-20T20:09:13+00:00" + "time": "2024-06-19T14:25:05+00:00" }, { "name": "illuminate/conditionable", - "version": "v10.48.10", + "version": "v10.48.16", "source": { "type": "git", "url": "https://github.com/illuminate/conditionable.git", @@ -592,7 +592,7 @@ }, { "name": "illuminate/container", - "version": "v10.48.10", + "version": "v10.48.16", "source": { "type": "git", "url": "https://github.com/illuminate/container.git", @@ -643,7 +643,7 @@ }, { "name": "illuminate/contracts", - "version": "v10.48.10", + "version": "v10.48.16", "source": { "type": "git", "url": "https://github.com/illuminate/contracts.git", @@ -691,16 +691,16 @@ }, { "name": "illuminate/database", - "version": "v10.48.10", + "version": "v10.48.16", "source": { "type": "git", "url": "https://github.com/illuminate/database.git", - "reference": "eb8edf206d3a6eea8894bc6e21f53469e27dd5c9" + "reference": "ec00738a49e9fb0db4fc19b5d70310e214b32bff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/database/zipball/eb8edf206d3a6eea8894bc6e21f53469e27dd5c9", - "reference": "eb8edf206d3a6eea8894bc6e21f53469e27dd5c9", + "url": "https://api.github.com/repos/illuminate/database/zipball/ec00738a49e9fb0db4fc19b5d70310e214b32bff", + "reference": "ec00738a49e9fb0db4fc19b5d70310e214b32bff", "shasum": "" }, "require": { @@ -760,11 +760,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-04-29T13:23:17+00:00" + "time": "2024-07-03T21:35:00+00:00" }, { "name": "illuminate/macroable", - "version": "v10.48.10", + "version": "v10.48.16", "source": { "type": "git", "url": "https://github.com/illuminate/macroable.git", @@ -810,16 +810,16 @@ }, { "name": "illuminate/support", - "version": "v10.48.10", + "version": "v10.48.16", "source": { "type": "git", "url": "https://github.com/illuminate/support.git", - "reference": "ee3a1aaed36d916654ce0ae09dfbd38644a4f582" + "reference": "263f389d81488c237846b69469f91387ca2729f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/ee3a1aaed36d916654ce0ae09dfbd38644a4f582", - "reference": "ee3a1aaed36d916654ce0ae09dfbd38644a4f582", + "url": "https://api.github.com/repos/illuminate/support/zipball/263f389d81488c237846b69469f91387ca2729f3", + "reference": "263f389d81488c237846b69469f91387ca2729f3", "shasum": "" }, "require": { @@ -877,20 +877,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-04-07T17:47:33+00:00" + "time": "2024-05-16T21:33:51+00:00" }, { "name": "matomo/device-detector", - "version": "6.3.1", + "version": "6.3.2", "source": { "type": "git", "url": "https://github.com/matomo-org/device-detector.git", - "reference": "8096093346917ee2477d802ab3b00c4c091c5cee" + "reference": "fd4042cb6a7f3f985a81aedc075dd59e0b991a51" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/8096093346917ee2477d802ab3b00c4c091c5cee", - "reference": "8096093346917ee2477d802ab3b00c4c091c5cee", + "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/fd4042cb6a7f3f985a81aedc075dd59e0b991a51", + "reference": "fd4042cb6a7f3f985a81aedc075dd59e0b991a51", "shasum": "" }, "require": { @@ -946,7 +946,7 @@ "source": "https://github.com/matomo-org/matomo", "wiki": "https://dev.matomo.org/" }, - "time": "2024-04-12T12:16:21+00:00" + "time": "2024-05-28T10:16:19+00:00" }, { "name": "maximebf/debugbar", @@ -954,12 +954,12 @@ "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "40d2d7e986082287b47bb6f675541ba43db09398" + "reference": "c9cb28d5ee6f657fcc48440f38db8bbd140bef83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/40d2d7e986082287b47bb6f675541ba43db09398", - "reference": "40d2d7e986082287b47bb6f675541ba43db09398", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/c9cb28d5ee6f657fcc48440f38db8bbd140bef83", + "reference": "c9cb28d5ee6f657fcc48440f38db8bbd140bef83", "shasum": "" }, "require": { @@ -1015,7 +1015,7 @@ "issues": "https://github.com/maximebf/php-debugbar/issues", "source": "https://github.com/maximebf/php-debugbar/tree/master" }, - "time": "2024-04-15T10:55:03+00:00" + "time": "2024-07-02T07:24:16+00:00" }, { "name": "mustangostang/spyc", @@ -1073,16 +1073,16 @@ }, { "name": "nesbot/carbon", - "version": "2.72.3", + "version": "2.72.5", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "0c6fd108360c562f6e4fd1dedb8233b423e91c83" + "reference": "afd46589c216118ecd48ff2b95d77596af1e57ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/0c6fd108360c562f6e4fd1dedb8233b423e91c83", - "reference": "0c6fd108360c562f6e4fd1dedb8233b423e91c83", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/afd46589c216118ecd48ff2b95d77596af1e57ed", + "reference": "afd46589c216118ecd48ff2b95d77596af1e57ed", "shasum": "" }, "require": { @@ -1116,8 +1116,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-3.x": "3.x-dev", - "dev-master": "2.x-dev" + "dev-master": "3.x-dev", + "dev-2.x": "2.x-dev" }, "laravel": { "providers": [ @@ -1176,7 +1176,7 @@ "type": "tidelift" } ], - "time": "2024-01-25T10:35:09+00:00" + "time": "2024-06-03T19:18:41+00:00" }, { "name": "nikic/fast-route", @@ -1572,16 +1572,16 @@ }, { "name": "symfony/console", - "version": "v6.4.7", + "version": "v6.4.9", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "a170e64ae10d00ba89e2acbb590dc2e54da8ad8f" + "reference": "6edb5363ec0c78ad4d48c5128ebf4d083d89d3a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a170e64ae10d00ba89e2acbb590dc2e54da8ad8f", - "reference": "a170e64ae10d00ba89e2acbb590dc2e54da8ad8f", + "url": "https://api.github.com/repos/symfony/console/zipball/6edb5363ec0c78ad4d48c5128ebf4d083d89d3a9", + "reference": "6edb5363ec0c78ad4d48c5128ebf4d083d89d3a9", "shasum": "" }, "require": { @@ -1646,7 +1646,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.7" + "source": "https://github.com/symfony/console/tree/v6.4.9" }, "funding": [ { @@ -1662,7 +1662,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-06-28T09:49:33+00:00" }, { "name": "symfony/deprecation-contracts", @@ -1733,16 +1733,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + "reference": "0424dff1c58f028c451efff2045f5d92410bd540" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540", + "reference": "0424dff1c58f028c451efff2045f5d92410bd540", "shasum": "" }, "require": { @@ -1792,7 +1792,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0" }, "funding": [ { @@ -1808,20 +1808,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", "shasum": "" }, "require": { @@ -1870,7 +1870,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" }, "funding": [ { @@ -1886,20 +1886,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", "shasum": "" }, "require": { @@ -1951,7 +1951,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" }, "funding": [ { @@ -1967,20 +1967,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", "shasum": "" }, "require": { @@ -2031,7 +2031,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" }, "funding": [ { @@ -2047,20 +2047,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-06-19T12:30:46+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25" + "reference": "10112722600777e02d2745716b70c5db4ca70442" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/861391a8da9a04cbad2d232ddd9e4893220d6e25", - "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/10112722600777e02d2745716b70c5db4ca70442", + "reference": "10112722600777e02d2745716b70c5db4ca70442", "shasum": "" }, "require": { @@ -2104,7 +2104,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php72/tree/v1.30.0" }, "funding": [ { @@ -2120,20 +2120,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-06-19T12:30:46+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + "reference": "77fa7995ac1b21ab60769b7323d600a991a90433" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/77fa7995ac1b21ab60769b7323d600a991a90433", + "reference": "77fa7995ac1b21ab60769b7323d600a991a90433", "shasum": "" }, "require": { @@ -2184,7 +2184,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.30.0" }, "funding": [ { @@ -2200,7 +2200,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/service-contracts", @@ -2287,16 +2287,16 @@ }, { "name": "symfony/string", - "version": "v6.4.7", + "version": "v6.4.9", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "ffeb9591c61f65a68d47f77d12b83fa530227a69" + "reference": "76792dbd99690a5ebef8050d9206c60c59e681d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/ffeb9591c61f65a68d47f77d12b83fa530227a69", - "reference": "ffeb9591c61f65a68d47f77d12b83fa530227a69", + "url": "https://api.github.com/repos/symfony/string/zipball/76792dbd99690a5ebef8050d9206c60c59e681d7", + "reference": "76792dbd99690a5ebef8050d9206c60c59e681d7", "shasum": "" }, "require": { @@ -2353,7 +2353,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.7" + "source": "https://github.com/symfony/string/tree/v6.4.9" }, "funding": [ { @@ -2369,20 +2369,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-06-28T09:25:38+00:00" }, { "name": "symfony/translation", - "version": "v6.4.7", + "version": "v6.4.8", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "7495687c58bfd88b7883823747b0656d90679123" + "reference": "a002933b13989fc4bd0b58e04bf7eec5210e438a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/7495687c58bfd88b7883823747b0656d90679123", - "reference": "7495687c58bfd88b7883823747b0656d90679123", + "url": "https://api.github.com/repos/symfony/translation/zipball/a002933b13989fc4bd0b58e04bf7eec5210e438a", + "reference": "a002933b13989fc4bd0b58e04bf7eec5210e438a", "shasum": "" }, "require": { @@ -2448,7 +2448,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.4.7" + "source": "https://github.com/symfony/translation/tree/v6.4.8" }, "funding": [ { @@ -2464,7 +2464,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-05-31T14:49:08+00:00" }, { "name": "symfony/translation-contracts", @@ -2546,16 +2546,16 @@ }, { "name": "symfony/var-dumper", - "version": "v6.4.7", + "version": "v6.4.9", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "7a9cd977cd1c5fed3694bee52990866432af07d7" + "reference": "c31566e4ca944271cc8d8ac6887cbf31b8c6a172" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7a9cd977cd1c5fed3694bee52990866432af07d7", - "reference": "7a9cd977cd1c5fed3694bee52990866432af07d7", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c31566e4ca944271cc8d8ac6887cbf31b8c6a172", + "reference": "c31566e4ca944271cc8d8ac6887cbf31b8c6a172", "shasum": "" }, "require": { @@ -2611,7 +2611,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.7" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.9" }, "funding": [ { @@ -2627,7 +2627,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-06-27T13:23:14+00:00" }, { "name": "twig/twig", @@ -2845,16 +2845,16 @@ "packages-dev": [ { "name": "phpstan/phpstan", - "version": "1.11.1", + "version": "1.11.7", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "e524358f930e41a2b4cca1320e3b04fc26b39e0b" + "reference": "52d2bbfdcae7f895915629e4694e9497d0f8e28d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e524358f930e41a2b4cca1320e3b04fc26b39e0b", - "reference": "e524358f930e41a2b4cca1320e3b04fc26b39e0b", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/52d2bbfdcae7f895915629e4694e9497d0f8e28d", + "reference": "52d2bbfdcae7f895915629e4694e9497d0f8e28d", "shasum": "" }, "require": { @@ -2899,7 +2899,7 @@ "type": "github" } ], - "time": "2024-05-15T08:00:59+00:00" + "time": "2024-07-06T11:17:41+00:00" } ], "aliases": [], diff --git a/install/index.php b/install/index.php index 6536829e..1031a2b8 100644 --- a/install/index.php +++ b/install/index.php @@ -114,7 +114,7 @@ else if($step == 'finish') { $email = $_SESSION['var_email']; $password = $_SESSION['var_password']; $password_confirm = $_SESSION['var_password_confirm']; - $player_name = $_SESSION['var_player_name']; + $player_name = $_SESSION['var_player_name'] ?? null; // email check if(empty($email)) { @@ -159,12 +159,13 @@ else if($step == 'finish') { $errors[] = $locale['step_admin_password_confirm_error_not_same']; } - // player name check - if(empty($player_name)) { - $errors[] = $locale['step_admin_player_name_error_empty']; - } - else if(!Validator::characterName($player_name)) { - $errors[] = $locale['step_admin_player_name_error_format']; + if (isset($player_name)) { + // player name check + if (empty($player_name)) { + $errors[] = $locale['step_admin_player_name_error_empty']; + } else if (!Validator::characterName($player_name)) { + $errors[] = $locale['step_admin_player_name_error_format']; + } } if(!empty($errors)) { diff --git a/install/steps/5-database.php b/install/steps/5-database.php index ed8f82a1..4f87bc49 100644 --- a/install/steps/5-database.php +++ b/install/steps/5-database.php @@ -64,18 +64,6 @@ if(!$error) { $error = true; } - if (!$db->hasTable('players')) { - $tmp = str_replace('$TABLE$', 'players', $locale['step_database_error_table']); - error($tmp); - $error = true; - } - - if (!$db->hasTable('guilds')) { - $tmp = str_replace('$TABLE$', 'guilds', $locale['step_database_error_table']); - error($tmp); - $error = true; - } - if (!$error) { $twig->display('install.installer.html.twig', array( 'url' => 'tools/5-database.php', diff --git a/install/steps/6-admin.php b/install/steps/6-admin.php index e410fc93..ab30b477 100644 --- a/install/steps/6-admin.php +++ b/install/steps/6-admin.php @@ -18,6 +18,7 @@ if(!$error) { 'locale' => $locale, 'session' => $_SESSION, 'account' => $account, + 'hasTablePlayers' => $db->hasTable('players'), 'errors' => isset($errors) ? $errors : null, 'buttons' => next_buttons(true, $error ? false : true) )); diff --git a/install/steps/7-finish.php b/install/steps/7-finish.php index 84c2cce4..0ae302ea 100644 --- a/install/steps/7-finish.php +++ b/install/steps/7-finish.php @@ -42,23 +42,25 @@ if(isset($account)) else $account_db->load($account_id); -$player_name = $_SESSION['var_player_name']; -$player_db = new OTS_Player(); -$player_db->find($player_name); +if ($db->hasTable('players')) { + $player_name = $_SESSION['var_player_name']; + $player_db = new OTS_Player(); + $player_db->find($player_name); -if(!$player_db->isLoaded()) -{ - $player = new OTS_Player(); - $player->setName($player_name); + if(!$player_db->isLoaded()) + { + $player = new OTS_Player(); + $player->setName($player_name); - $player_used = &$player; + $player_used = &$player; + } + else { + $player_used = &$player_db; + } + + $groups = new OTS_Groups_List(); + $player_used->setGroupId($groups->getHighestId()); } -else { - $player_used = &$player_db; -} - -$groups = new OTS_Groups_List(); -$player_used->setGroupId($groups->getHighestId()); $email = $_SESSION['var_email']; if($account_db->isLoaded()) { @@ -100,10 +102,16 @@ if($db->hasColumn('accounts', 'group_id')) if($db->hasColumn('accounts', 'type')) $account_used->setCustomField('type', 6); -if(!$player_db->isLoaded()) - $player->setAccountId($account_used->getId()); -else - $player_db->setAccountId($account_used->getId()); +if ($db->hasTable('players')) { + if(!$player_db->isLoaded()) { + $player->setAccountId($account_used->getId()); + $player->save(); + } + else { + $player_db->setAccountId($account_used->getId()); + $player_db->save(); + } +} success($locale['step_database_created_account']); @@ -111,18 +119,14 @@ setSession('account', $account_used->getId()); setSession('password', encrypt($password)); setSession('remember_me', true); -if($player_db->isLoaded()) { - $player_db->save(); -} -else { - $player->save(); -} - if(!News::all()->count()) { $player_id = 0; - $tmpNewsPlayer = \MyAAC\Models\Player::where('name', $player_name)->first(); - if($tmpNewsPlayer) { - $player_id = $tmpNewsPlayer->id; + + if ($db->hasTable('players')) { + $tmpNewsPlayer = \MyAAC\Models\Player::where('name', $player_name)->first(); + if($tmpNewsPlayer) { + $player_id = $tmpNewsPlayer->id; + } } News::create([ diff --git a/install/tools/7-finish.php b/install/tools/7-finish.php index 37914a5f..8101b07d 100644 --- a/install/tools/7-finish.php +++ b/install/tools/7-finish.php @@ -25,30 +25,33 @@ if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['save require SYSTEM . 'init.php'; -$deleted = 'deleted'; -if($db->hasColumn('players', 'deletion')) - $deleted = 'deletion'; +if ($db->hasTable('players')) { + $deleted = 'deleted'; + if ($db->hasColumn('players', 'deletion')) + $deleted = 'deletion'; -$time = time(); -function insert_sample_if_not_exist($p) { - global $db, $success, $deleted, $time; + $time = time(); + function insert_sample_if_not_exist($p) + { + global $db, $success, $deleted, $time; - $query = $db->query('SELECT `id` FROM `players` WHERE `name` = ' . $db->quote($p['name'])); - if($query->rowCount() == 0) { - if(!query("INSERT INTO `players` (`id`, `name`, `group_id`, `account_id`, `level`, `vocation`, `health`, `healthmax`, `experience`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `maglevel`, `mana`, `manamax`, `manaspent`, `soul`, `town_id`, `posx`, `posy`, `posz`, `conditions`, `cap`, `sex`, `lastlogin`, `lastip`, `save`, `lastlogout`, `balance`, `$deleted`, `created`, `hide`, `comment`) VALUES (null, " . $db->quote($p['name']) . ", 1, " . getSession('account') . ", " . $p['level'] . ", " . $p['vocation_id'] . ", " . $p['health'] . ", " . $p['healthmax'] . ", " . $p['experience'] . ", 118, 114, 38, 57, " . $p['looktype'] . ", 0, " . $p['mana'] . ", " . $p['manamax'] . ", 0, " . $p['soul'] . ", 1, 1000, 1000, 7, '', " . $p['cap'] . ", 1, " . $time . ", 2130706433, 1, " . $time . ", 0, 0, " . $time . ", 1, '');")) - $success = false; + $query = $db->query('SELECT `id` FROM `players` WHERE `name` = ' . $db->quote($p['name'])); + if ($query->rowCount() == 0) { + if (!query("INSERT INTO `players` (`id`, `name`, `group_id`, `account_id`, `level`, `vocation`, `health`, `healthmax`, `experience`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `maglevel`, `mana`, `manamax`, `manaspent`, `soul`, `town_id`, `posx`, `posy`, `posz`, `conditions`, `cap`, `sex`, `lastlogin`, `lastip`, `save`, `lastlogout`, `balance`, `$deleted`, `created`, `hide`, `comment`) VALUES (null, " . $db->quote($p['name']) . ", 1, " . getSession('account') . ", " . $p['level'] . ", " . $p['vocation_id'] . ", " . $p['health'] . ", " . $p['healthmax'] . ", " . $p['experience'] . ", 118, 114, 38, 57, " . $p['looktype'] . ", 0, " . $p['mana'] . ", " . $p['manamax'] . ", 0, " . $p['soul'] . ", 1, 1000, 1000, 7, '', " . $p['cap'] . ", 1, " . $time . ", 2130706433, 1, " . $time . ", 0, 0, " . $time . ", 1, '');")) + $success = false; + } } -} -$success = true; -insert_sample_if_not_exist(array('name' => 'Rook Sample', 'level' => 1, 'vocation_id' => 0, 'health' => 150, 'healthmax' => 150, 'experience' => 0, 'looktype' => 130, 'mana' => 0, 'manamax' => 0, 'soul' => 100, 'cap' => 400)); -insert_sample_if_not_exist(array('name' => 'Sorcerer Sample', 'level' => 8, 'vocation_id' => 1, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470)); -insert_sample_if_not_exist(array('name' => 'Druid Sample', 'level' => 8, 'vocation_id' => 2, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470)); -insert_sample_if_not_exist(array('name' => 'Paladin Sample', 'level' => 8, 'vocation_id' => 3, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 129, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470)); -insert_sample_if_not_exist(array('name' => 'Knight Sample', 'level' => 8, 'vocation_id' => 4, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 131, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470)); + $success = true; + insert_sample_if_not_exist(array('name' => 'Rook Sample', 'level' => 1, 'vocation_id' => 0, 'health' => 150, 'healthmax' => 150, 'experience' => 0, 'looktype' => 130, 'mana' => 0, 'manamax' => 0, 'soul' => 100, 'cap' => 400)); + insert_sample_if_not_exist(array('name' => 'Sorcerer Sample', 'level' => 8, 'vocation_id' => 1, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470)); + insert_sample_if_not_exist(array('name' => 'Druid Sample', 'level' => 8, 'vocation_id' => 2, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470)); + insert_sample_if_not_exist(array('name' => 'Paladin Sample', 'level' => 8, 'vocation_id' => 3, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 129, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470)); + insert_sample_if_not_exist(array('name' => 'Knight Sample', 'level' => 8, 'vocation_id' => 4, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 131, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470)); -if($success) { - success($locale['step_database_imported_players']); + if ($success) { + success($locale['step_database_imported_players']); + } } Plugins::installMenus('kathrine', require TEMPLATES . 'kathrine/menus.php'); diff --git a/login.php b/login.php index 8be4d1f3..75aeed4d 100644 --- a/login.php +++ b/login.php @@ -4,6 +4,7 @@ use MyAAC\Models\BoostedCreature; use MyAAC\Models\PlayerOnline; use MyAAC\Models\Account; use MyAAC\Models\Player; +use MyAAC\RateLimit; require_once 'common.php'; require_once SYSTEM . 'functions.php'; @@ -130,12 +131,29 @@ switch ($action) { } $account = $account->first(); + + $ip = get_browser_real_ip(); + $limiter = new RateLimit('failed_logins', setting('core.account_login_attempts_limit'), setting('core.account_login_ban_time')); + $limiter->enabled = setting('core.account_login_ipban_protection'); + $limiter->load(); + + $ban_msg = 'A wrong account, password or secret has been entered ' . setting('core.account_login_attempts_limit') . ' times in a row. You are unable to log into your account for the next ' . setting('core.account_login_ban_time') . ' minutes. Please wait.'; if (!$account) { + $limiter->increment($ip); + if ($limiter->exceeded($ip)) { + sendError($ban_msg); + } + sendError(($inputEmail != false ? 'Email' : 'Account name') . ' or password is not correct.'); } $current_password = encrypt((USE_ACCOUNT_SALT ? $account->salt : '') . $request->password); if (!$account || $account->password != $current_password) { + $limiter->increment($ip); + if ($limiter->exceeded($ip)) { + sendError($ban_msg); + } + sendError(($inputEmail != false ? 'Email' : 'Account name') . ' or password is not correct.'); } @@ -145,16 +163,30 @@ switch ($action) { if ($accountSecret != null && $accountSecret != '') { $accountHasSecret = true; if ($inputToken === false) { + $limiter->increment($ip); + if ($limiter->exceeded($ip)) { + sendError($ban_msg); + } sendError('Submit a valid two-factor authentication token.', 6); } else { require_once LIBS . 'rfc6238.php'; if (TokenAuth6238::verify($accountSecret, $inputToken) !== true) { + $limiter->increment($ip); + if ($limiter->exceeded($ip)) { + sendError($ban_msg); + } + sendError('Two-factor authentication failed, token is wrong.', 6); } } } } + $limiter->reset($ip); + if (setting('core.account_mail_verify') && $account->email_verified !== 1) { + sendError('You need to verify your account, enter in our site and resend verify e-mail!'); + } + // common columns $columns = 'id, name, level, sex, vocation, looktype, lookhead, lookbody, looklegs, lookfeet, lookaddons'; diff --git a/phpstan.neon b/phpstan.neon index fda6a07c..020fa3a6 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -28,7 +28,7 @@ parameters: - '#Variable \$guild might not be defined#' - '#Variable \$[a-zA-Z0-9\\_]+ might not be defined#' # Eloquent models - - '#Call to an undefined static method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+()#' + - '#Call to an undefined static method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\)#' - '#Call to an undefined method object::toArray\(\)#' # system/pages/highscores.php - '#Call to an undefined method Illuminate\\Database\\Query\\Builder::withOnlineStatus\(\)#' diff --git a/system/clients.conf.php b/system/clients.conf.php index a7d2bf0c..fce41bb1 100644 --- a/system/clients.conf.php +++ b/system/clients.conf.php @@ -105,4 +105,8 @@ $config['clients'] = [ 1316, 1320, 1321, + 1322, + 1330, + 1332, + 1340, ]; diff --git a/system/functions.php b/system/functions.php index 70c0b93e..f177d997 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1041,7 +1041,7 @@ function load_config_lua($filename) return $result; } -function str_replace_first($search, $replace, $subject) { +function str_replace_first($search,$replace, $subject) { $pos = strpos($subject, $search); if ($pos !== false) { return substr_replace($subject, $replace, $pos, strlen($search)); diff --git a/system/libs/pot/OTS_Base_DB.php b/system/libs/pot/OTS_Base_DB.php index 21d6f756..6ef39bc5 100644 --- a/system/libs/pot/OTS_Base_DB.php +++ b/system/libs/pot/OTS_Base_DB.php @@ -184,8 +184,14 @@ abstract class OTS_Base_DB extends PDO implements IOTS_DB $query = 'UPDATE '.$this->tableName($table).' SET '; $count = count($fields); - for ($i = 0; $i < $count; $i++) - $query.= $this->fieldName($fields[$i]).' = '.$this->quote($values[$i]).', '; + for ($i = 0; $i < $count; $i++) { + $value = 'NULL'; + if ($values[$i] !== null) { + $value = $this->quote($values[$i]); + } + + $query.= $this->fieldName($fields[$i]).' = '.$value.', '; + } $query = substr($query, 0, -2); $query.=' WHERE ('; diff --git a/system/libs/pot/OTS_House.php b/system/libs/pot/OTS_House.php index 12a8f1cb..9ef0c149 100644 --- a/system/libs/pot/OTS_House.php +++ b/system/libs/pot/OTS_House.php @@ -60,12 +60,7 @@ class OTS_House extends OTS_Row_DAO private $tiles = array(); public function load($id) { - $this->data = $this->db->query('SELECT * FROM `houses` WHERE `id` = ' . $id )->fetch(); - foreach($this->data as $key => $value) { - if(is_numeric($key)) { - unset($this->data[$key]); - } - } + $this->data = $this->db->query('SELECT * FROM `houses` WHERE `id` = ' . $id )->fetch(PDO::FETCH_ASSOC); } public function find($name) diff --git a/system/migrations/20.php b/system/migrations/20.php index e7b5ee0a..1255fa14 100644 --- a/system/migrations/20.php +++ b/system/migrations/20.php @@ -2,6 +2,10 @@ use MyAAC\Settings; +if (!$db->hasTable('players')) { + return; +} + $query = $db->query("SELECT `id` FROM `players` WHERE (`name` = " . $db->quote("Rook Sample") . " OR `name` = " . $db->quote("Sorcerer Sample") . " OR `name` = " . $db->quote("Druid Sample") . " OR `name` = " . $db->quote("Paladin Sample") . " OR `name` = " . $db->quote("Knight Sample") . " OR `name` = " . $db->quote("Account Manager") . ") ORDER BY `id`;"); $highscores_ignored_ids = array(); diff --git a/system/pages/account/create.php b/system/pages/account/create.php index 0074f9e3..9fba8237 100644 --- a/system/pages/account/create.php +++ b/system/pages/account/create.php @@ -148,6 +148,10 @@ if($save) } } + /** + * two hooks for compatibility + */ + $hooks->trigger(HOOK_ACCOUNT_CREATE_AFTER_SUBMIT, $params); if (!$hooks->trigger(HOOK_ACCOUNT_CREATE_POST, $params)) { return; } @@ -187,6 +191,8 @@ if($save) $new_account->setEMail($email); $new_account->save(); + $hooks->trigger(HOOK_ACCOUNT_CREATE_AFTER_SAVED, ['account' => $new_account]); + if(USE_ACCOUNT_SALT) $new_account->setCustomField('salt', $salt); diff --git a/system/pages/account/login.php b/system/pages/account/login.php index 0fce795d..98e85b46 100644 --- a/system/pages/account/login.php +++ b/system/pages/account/login.php @@ -8,6 +8,9 @@ * @copyright 2023 MyAAC * @link https://my-aac.org */ + +use MyAAC\RateLimit; + defined('MYAAC') or die('Direct access not allowed!'); // new login with data from form @@ -18,30 +21,13 @@ if($logged || !isset($_POST['account_login']) || !isset($_POST['password_login'] $login_account = $_POST['account_login']; $login_password = $_POST['password_login']; $remember_me = isset($_POST['remember_me']); +$ip = get_browser_real_ip(); if(!empty($login_account) && !empty($login_password)) { - if($cache->enabled()) - { - $tmp = ''; - if($cache->fetch('failed_logins', $tmp)) - { - $tmp = unserialize($tmp); - $to_remove = array(); - foreach($tmp as $ip => $t) - { - if(time() - $t['last'] >= 5 * 60) - $to_remove[] = $ip; - } - foreach($to_remove as $ip) - unset($tmp[$ip]); - } - else - $tmp = array(); - - $ip = $_SERVER['REMOTE_ADDR']; - $t = $tmp[$ip] ?? null; - } + $limiter = new RateLimit('failed_logins', setting('core.account_login_attempts_limit'), setting('core.account_login_ban_time')); + $limiter->enabled = setting('core.account_login_ipban_protection'); + $limiter->load(); $account_logged = new OTS_Account(); if (config('account_login_by_email')) { @@ -56,14 +42,12 @@ if(!empty($login_account) && !empty($login_password)) } } - if($account_logged->isLoaded() && encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $login_password) == $account_logged->getPassword() - && (!isset($t) || $t['attempts'] < 5) + if($account_logged->isLoaded() && encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $login_password) == $account_logged->getPassword() && ($limiter->enabled && !$limiter->exceeded($ip)) ) { 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.'; - } - else { + } else { session_regenerate_id(); setSession('account', $account_logged->getId()); setSession('password', encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $login_password)); @@ -87,38 +71,21 @@ if(!empty($login_account) && !empty($login_password)) $hooks->trigger(HOOK_LOGIN, array('account' => $account_logged, 'password' => $login_password, 'remember_me' => $remember_me)); } + + $limiter->reset($ip); } else { $hooks->trigger(HOOK_LOGIN_ATTEMPT, array('account' => $login_account, 'password' => $login_password, 'remember_me' => $remember_me)); $errorMessage = getAccountLoginByLabel() . ' or password is not correct.'; + $limiter->increment($ip); + if ($limiter->exceeded($ip)) { + $errorMessage = 'A wrong password has been entered ' . $limiter->max_attempts . ' times in a row. You are unable to log into your account for the next ' . $limiter->ttl . ' minutes. Please wait.'; + } - // temporary solution for blocking failed login attempts - if($cache->enabled()) - { - if(isset($t)) - { - $t['attempts']++; - $t['last'] = time(); - - if($t['attempts'] >= 5) - $errors[] = 'A wrong password has been entered 5 times in a row. You are unable to log into your account for the next 5 minutes. Please wait.'; - else - $errors[] = $errorMessage; - } - else - { - $t = array('attempts' => 1, 'last' => time()); - $errors[] = $errorMessage; - } - - $tmp[$ip] = $t; - $cache->set('failed_logins', serialize($tmp), 60 * 60); // save for 1 hour - } - else { - $errors[] = $errorMessage; - } + $errors[] = $errorMessage; + } } else { diff --git a/system/pages/highscores.php b/system/pages/highscores.php index 0e5662e1..a1e2567f 100644 --- a/system/pages/highscores.php +++ b/system/pages/highscores.php @@ -180,7 +180,7 @@ if (empty($highscores)) { } else if ($skill == SKILL_FRAGS) // frags { if ($db->hasTable('player_killers')) { - $query->addSelect(['value' => PlayerKillers::where('player_killers.player_id', 'players.id')->selectRaw('COUNT(*)')]); + $query->addSelect(['value' => PlayerKillers::whereColumn('player_killers.player_id', 'players.id')->selectRaw('COUNT(*)')]); } else { $query->addSelect(['value' => PlayerDeath::unjustified()->whereColumn('player_deaths.killed_by', 'players.name')->selectRaw('COUNT(*)')]); } diff --git a/system/settings.php b/system/settings.php index a7f1b53c..1086f4d2 100644 --- a/system/settings.php +++ b/system/settings.php @@ -15,8 +15,7 @@ use MyAAC\Settings; return [ 'name' => 'MyAAC', - 'settings' => - [ + 'settings' => [ [ 'type' => 'category', 'title' => 'General' @@ -1374,7 +1373,7 @@ Sent by MyAAC,
'name' => 'Item Images URL', 'type' => 'text', 'desc' => 'Set to images/items if you host your own items in images folder', - 'default' => 'http://item-images.ots.me/1092/', + 'default' => 'https://item-images.ots.me/1092/', ], 'item_images_extension' => [ 'name' => 'Item Images File Extension', @@ -1390,7 +1389,7 @@ Sent by MyAAC,
'name' => 'Outfit Images URL', 'type' => 'text', 'desc' => 'Set to animoutfit.php for animated outfit', - 'default' => 'http://outfit-images.ots.me/outfit.php', + 'default' => 'https://outfit-images.ots.me/outfit.php', ], 'outfit_images_wrong_looktypes' => [ 'name' => 'Outfit Images Wrong Looktypes', @@ -1590,6 +1589,34 @@ Sent by MyAAC,
'account_change_character_sex', '=', 'true', ], ], + [ + 'type' => 'category', + 'title' => 'Security', + ], + [ + 'type' => 'section', + 'title' => 'IP Ban Protection', + ], + 'account_login_ipban_protection' => [ + 'name' => 'IP Ban Protection', + 'type' => 'boolean', + 'desc' => 'Activate IP ban protection after exceeding incorrect login attempts', + 'default' => true, + ], + + 'account_login_attempts_limit' => [ + 'name' => 'Login Attempts Limit', + 'type' => 'number', + 'desc' => 'Number of incorrect login attempts before banning the IP', + 'default' => 5, // Ajuste conforme necessário + ], + + 'account_login_ban_time' => [ + 'name' => 'Ban Time (Minutes)', + 'type' => 'number', + 'desc' => 'Time in minutes the IP will be banned after exceeding login attempts', + 'default' => 30, // Ajuste conforme necessário + ], ], 'callbacks' => [ 'beforeSave' => function(&$settings, &$values) { @@ -1658,6 +1685,6 @@ Sent by MyAAC,
return $success; }, - ], + ] ]; diff --git a/system/src/CreateCharacter.php b/system/src/CreateCharacter.php index ea0d2c6c..c54c515b 100644 --- a/system/src/CreateCharacter.php +++ b/system/src/CreateCharacter.php @@ -267,7 +267,7 @@ class CreateCharacter [ 'account' => $account, 'player' => $player, - 'samplePlayer' => $playerSample, + 'playerSample' => $playerSample, 'name' => $name, 'sex' => $sex, 'vocation' => $vocation, diff --git a/system/src/Models/PlayerKillers.php b/system/src/Models/PlayerKillers.php index 55abbfd8..d0bd9fdc 100644 --- a/system/src/Models/PlayerKillers.php +++ b/system/src/Models/PlayerKillers.php @@ -5,7 +5,7 @@ use Illuminate\Database\Eloquent\Model; class PlayerKillers extends Model { - protected $table = 'players_killers'; + protected $table = 'player_killers'; public $timestamps = false; diff --git a/system/src/RateLimit.php b/system/src/RateLimit.php new file mode 100644 index 00000000..fbb97369 --- /dev/null +++ b/system/src/RateLimit.php @@ -0,0 +1,120 @@ +key = $key; + $this->max_attempts = $max_attempts; + $this->ttl = $ttl; + } + + public function attempts(string $ip): int + { + if (!$this->enabled) { + return 0; + } + + if (isset($this->data[$ip]['attempts'])) { + return $this->data[$ip]['attempts']; + } + + return 0; + } + + public function exceeded(string $ip): bool { + if (!$this->enabled) { + return false; + } + + return $this->attempts($ip) >= $this->max_attempts; + } + + public function increment(string $ip): bool + { + global $cache; + if ($this->enabled && $cache->enabled()) { + if (isset($this->data[$ip]['attempts']) && isset($this->data[$ip]['last'])) { + $this->data[$ip]['attempts']++; + $this->data[$ip]['last'] = time(); + } else { + $this->data[$ip] = [ + 'attempts' => 1, + 'last' => time(), + ]; + } + + $this->save(); + } + + return false; + } + + public function reset(string $ip): void + { + if (!$this->enabled) { + return; + } + + if (isset($this->data[$ip])) { + unset($this->data[$ip]); + } + + $this->save(); + } + + public function save(): void + { + global $cache; + if (!$this->enabled) { + return; + } + + $data = $this->data; + $cache->set($this->key, serialize($data), $this->ttl * 60); + } + + public function load(): void + { + global $cache; + if (!$this->enabled) { + return; + } + + $data = []; + if ($this->enabled && $cache->enabled()) { + $tmp = ''; + if ($cache->fetch($this->key, $tmp)) { + $data = unserialize($tmp); + $to_remove = []; + foreach ($data as $ip => $t) { + if (time() - $t['last'] >= ($this->ttl * 60)) { + $to_remove[] = $ip; + } + } + + if (count($to_remove)) { + foreach ($to_remove as $ip) { + unset($data[$ip]); + } + + $this->save(); + } + } else { + $data = []; + } + } + + $this->data = $data; + } +} diff --git a/system/src/global.php b/system/src/global.php index d4bd0cc4..e106a57c 100644 --- a/system/src/global.php +++ b/system/src/global.php @@ -45,6 +45,12 @@ define('HOOK_ACCOUNT_CREATE_AFTER_TOWNS', ++$i); define('HOOK_ACCOUNT_CREATE_BEFORE_SUBMIT_BUTTON', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_FORM', ++$i); define('HOOK_ACCOUNT_CREATE_POST', ++$i); +define('HOOK_ACCOUNT_CREATE_AFTER_SUBMIT', ++$i); +define('HOOK_ACCOUNT_CREATE_AFTER_SAVED', ++$i); +define('HOOK_ACCOUNT_MANAGE_BEFORE_GENERAL_INFORMATION', ++$i); +define('HOOK_ACCOUNT_MANAGE_BEFORE_PUBLIC_INFORMATION', ++$i); +define('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS', ++$i); +define('HOOK_ACCOUNT_MANAGE_BEFORE_CHARACTERS', ++$i); define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i); define('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT', ++$i); define('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT', ++$i); diff --git a/system/status.php b/system/status.php index ee8b4317..835f204d 100644 --- a/system/status.php +++ b/system/status.php @@ -142,10 +142,14 @@ function updateStatus() { } } - $status['uptime'] = $serverStatus->getUptime(); - $h = floor($status['uptime'] / 3600); - $m = floor(($status['uptime'] - $h * 3600) / 60); - $status['uptimeReadable'] = $h . 'h ' . $m . 'm'; + $uptime = $status['uptime'] = $serverStatus->getUptime(); + $m = date('m', $uptime); + $m = $m > 1 ? "$m months, " : ($m == 1 ? 'month, ' : ''); + $d = date('d', $uptime); + $d = $d > 1 ? "$d days, " : ($d == 1 ? 'day, ' : ''); + $h = date('H', $uptime); + $min = date('i', $uptime); + $status['uptimeReadable'] = "{$m}{$d}{$h}h {$min}m"; $status['monsters'] = $serverStatus->getMonstersCount(); $status['motd'] = $serverStatus->getMOTD(); diff --git a/system/templates/account.management.html.twig b/system/templates/account.management.html.twig index db8c766f..87a33b6a 100644 --- a/system/templates/account.management.html.twig +++ b/system/templates/account.management.html.twig @@ -88,6 +88,7 @@


{% endif %} + {{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_GENERAL_INFORMATION') }}

General Information

@@ -127,6 +128,7 @@ {% endautoescape %}

+ {{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_PUBLIC_INFORMATION') }}

Public Information

@@ -145,6 +147,7 @@ {% include('buttons.base.html.twig') %}
+ {{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS') }}

Action Log

@@ -164,6 +167,7 @@ {% endautoescape %}

+ {{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_CHARACTERS') }}

Character list: {{ players|length }} characters.

diff --git a/system/templates/install.admin.html.twig b/system/templates/install.admin.html.twig index a3a306a8..1d64eea9 100644 --- a/system/templates/install.admin.html.twig +++ b/system/templates/install.admin.html.twig @@ -9,7 +9,13 @@ - {% for value in ['email', 'account', 'password', 'password_confirm', 'player_name'] %} + {% set values = ['email', 'account', 'password', 'password_confirm'] %} + + {% if hasTablePlayers %} + {% set values = values|merge(['player_name']) %} + {% endif %} + + {% for value in values %}
diff --git a/templates/tibiacom/account.management.html.twig b/templates/tibiacom/account.management.html.twig index 773ce6c9..6ce10274 100644 --- a/templates/tibiacom/account.management.html.twig +++ b/templates/tibiacom/account.management.html.twig @@ -111,6 +111,7 @@


{% endif %} +{{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_GENERAL_INFORMATION') }}
@@ -221,6 +222,7 @@ {% endset %} {% include 'tables.headline.html.twig' %}
+{{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_PUBLIC_INFORMATION') }}
@@ -280,6 +282,7 @@ {% endset %} {% include 'tables.headline.html.twig' %}
+{{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS') }}
@@ -333,6 +336,7 @@ {% endset %} {% include 'tables.headline.html.twig' %}
+{{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_CHARACTERS') }}