mirror of
https://github.com/slawkens/myaac.git
synced 2025-09-14 04:23:34 +02:00
Compare commits
97 Commits
v1.6
...
feature/2f
Author | SHA1 | Date | |
---|---|---|---|
![]() |
03c7dd0002 | ||
![]() |
20f99903ae | ||
![]() |
b6e1620f14 | ||
![]() |
9cb7792623 | ||
![]() |
0db908be18 | ||
![]() |
785d38312b | ||
![]() |
e1c04ed28e | ||
![]() |
c836308601 | ||
![]() |
0efe47ce71 | ||
![]() |
3b47e9df2f | ||
![]() |
43415cf35d | ||
![]() |
cf7fd20452 | ||
![]() |
080cc2781f | ||
![]() |
20d69a641c | ||
![]() |
2d4be327b2 | ||
![]() |
bb097b69ce | ||
![]() |
6e5a4ff8c7 | ||
![]() |
caf326a658 | ||
![]() |
bccf8e056d | ||
![]() |
7d27e5a0ba | ||
![]() |
9b6f410459 | ||
![]() |
c06b0017f1 | ||
![]() |
d8132d4d76 | ||
![]() |
1566deb84a | ||
![]() |
536b29be95 | ||
![]() |
5271633bdb | ||
![]() |
ce5b1cf2a6 | ||
![]() |
83f84172e0 | ||
![]() |
34fead906e | ||
![]() |
ec11c14024 | ||
![]() |
2fe9924437 | ||
![]() |
f0f2e3785f | ||
![]() |
36ca755243 | ||
![]() |
f17269e44c | ||
![]() |
dcb96f4ce1 | ||
![]() |
a89f9a8484 | ||
![]() |
45d6047031 | ||
![]() |
e435062025 | ||
![]() |
ecc9bd4042 | ||
![]() |
c92148d467 | ||
![]() |
b4b62442fe | ||
![]() |
047742848b | ||
![]() |
fe8281594e | ||
![]() |
0bff910a05 | ||
![]() |
6d43fc181f | ||
![]() |
13d33822b5 | ||
![]() |
f78ebad136 | ||
![]() |
d90fa323d7 | ||
![]() |
181131f7f3 | ||
![]() |
0da524fefe | ||
![]() |
797377e428 | ||
![]() |
96b5df9d74 | ||
![]() |
6cf4b9dac5 | ||
![]() |
b3dfc56c96 | ||
![]() |
96d6e04bd2 | ||
![]() |
9146eee327 | ||
![]() |
3d97fa0719 | ||
![]() |
5cfa3a697f | ||
![]() |
bb830bce44 | ||
![]() |
566c2a9151 | ||
![]() |
a66cafceab | ||
![]() |
0f48f12e2e | ||
![]() |
0ea247ce7e | ||
![]() |
b329da52aa | ||
![]() |
c720ccc451 | ||
![]() |
8dc42b6544 | ||
![]() |
dca904e61d | ||
![]() |
29faa4f695 | ||
![]() |
4767120043 | ||
![]() |
9a90e4aae2 | ||
![]() |
ba4ed6a04b | ||
![]() |
a7efacdbac | ||
![]() |
577037becc | ||
![]() |
b8abc11b96 | ||
![]() |
4def6a6cae | ||
![]() |
e6100a1b72 | ||
![]() |
522f6c11d8 | ||
![]() |
00c3635c5f | ||
![]() |
c074a48f24 | ||
![]() |
e222957893 | ||
![]() |
d423ddd07a | ||
![]() |
4d4f7759d3 | ||
![]() |
9510640ba9 | ||
![]() |
98b13c91a4 | ||
![]() |
0c95bcfd06 | ||
![]() |
524e982a0e | ||
![]() |
fffb427eae | ||
![]() |
10cd71a663 | ||
![]() |
0812fe025d | ||
![]() |
309c1fb715 | ||
![]() |
8d29fdb98b | ||
![]() |
f782850307 | ||
![]() |
835dda9659 | ||
![]() |
dcc703b1eb | ||
![]() |
9d8e9d27bd | ||
![]() |
db09980de1 | ||
![]() |
2dba778167 |
@@ -1,5 +1,79 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [1.8 - 02.08.2025]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* Templates - Kathrine: Possibility to add custom menu categories (https://github.com/slawkens/myaac/commit/ec11c1402417c25980582467546d1c1e9bb8267f)
|
||||||
|
* Admin Panel - Accounts Editor: Add Coins Transferable (https://github.com/slawkens/myaac/commit/45d6047031c9c3a0e7e512dc5d15c75629aec5a2, https://github.com/slawkens/myaac/commit/bb097b69ce106500a49686d6f4fe604348eaa310)
|
||||||
|
* Highscores:
|
||||||
|
* Revamped: (https://github.com/slawkens/myaac/commit/d8132d4d76e03d5aa0c042be426320655a601392)
|
||||||
|
* Show real rank, if 2 or more players have the same skill, show them with same rank
|
||||||
|
* New setting: highscores_online_status
|
||||||
|
* Additional fields passed to twig: updatedAt, totalResults, page, baseLink
|
||||||
|
* Add new Setting: Display Skills Box (https://github.com/slawkens/myaac/commit/36ca755243ef1c83f6ac87465b426d4d8d3b0bb9)
|
||||||
|
* Functions: Add getExperienceForLevel (level) (https://github.com/slawkens/myaac/commit/1566deb84a082176b8c683fda205d828bc38fbcc)
|
||||||
|
* Commands - cache:clear : Add warning about APCu clear in CLI (https://github.com/slawkens/myaac/commit/83f84172e02e8ea2ccb6dca29bc033e44c35aebc)
|
||||||
|
* Models - PlayerOnline: Add missing $fillable into model (https://github.com/slawkens/myaac/commit/43415cf35db1c1307f2684c1728693d65065ffff)
|
||||||
|
* Twig: add cache variable (https://github.com/slawkens/myaac/commit/0efe47ce71c4b364a9e96bc5a55b1655326ae6da)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* pages/online: add cache, resulting in 20x performance boost
|
||||||
|
* (for an example server with 2k players) (https://github.com/slawkens/myaac/commit/c8363086015cbb6e8786c398c7b9ac3959a26ec4)
|
||||||
|
* Admin Bar: Move admin bar code into body_start place_holder (https://github.com/slawkens/myaac/commit/f17269e44ce9dd38447bd2e2a8e1bdb065d4161f)
|
||||||
|
* Cache::remember: $ttl = 0 means no cache (https://github.com/slawkens/myaac/commit/3b47e9df2f4051807c5ff87892f7fa3d348f9c55)
|
||||||
|
* Templates: Load config.ini with $process_sections set to true (https://github.com/slawkens/myaac/commit/a89f9a84847630eb75b4890fdcc8b7a7bfa6b8ac)
|
||||||
|
* Twig: Allow for timestamp as integer in the timeago twig function
|
||||||
|
(https://github.com/slawkens/myaac/commit/34fead906ea13b9f09d7a3c41ed88109d34d386c)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* Settings: Fixed two exceptions (https://github.com/slawkens/myaac/commit/6e5a4ff8c78ff5373aba091baa66cae029557643, https://github.com/slawkens/myaac/commit/20d69a641c0a933d14889a89da6d32f6a4bc6c7d)
|
||||||
|
* Models\Account + OTS_Account -> isPremium -> ignore config.freePremium (https://github.com/slawkens/myaac/commit/5271633bdbfbbfed0b1d59c403093ce6fc2b7d20)
|
||||||
|
* Admin Panel - Mailer:
|
||||||
|
* Fix send to email link redirecting from accounts page (https://github.com/slawkens/myaac/commit/080cc2781f034c844af658229e495e9a47fd2298)
|
||||||
|
* Option to send only to verified accounts - only if setting('core.account_mail_verify') enabled (https://github.com/slawkens/myaac/commit/cf7fd20452e863980045bb5d6012ec86c6e8e01f)
|
||||||
|
|
||||||
|
### Internal
|
||||||
|
* Rewrite to use constants (account transferable coins) (https://github.com/slawkens/myaac/commit/bccf8e056df985bbe1bab5f7ab5492f714d6b62b)
|
||||||
|
* Refactor to use HAS_ACCOUNT_COINS (https://github.com/slawkens/myaac/commit/caf326a6584a234775ebc6c8000ea02b3fecd160)
|
||||||
|
|
||||||
|
## [1.7.1 - 27.06.2025]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* Rename plugin:install:install to plugin:setup, also add alias to previous command (https://github.com/slawkens/myaac/commit/13d33822b59df349199e885a78a3d6beb0863d0b)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* Fix commands: setup + cache:clear (https://github.com/slawkens/myaac/commit/0da524fefe93b3028392e9014550eea3324d3a22, https://github.com/slawkens/myaac/commit/fe8281594e989f00280ba1adc734a9198c6b5cc1)
|
||||||
|
* Fix polls link in tibiacom template (https://github.com/slawkens/myaac/commit/d90fa323d7c77d81768df60feeb1c374b1650a0c)
|
||||||
|
|
||||||
|
## [1.7 - 22.06.2025]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* Feature: plugins versions check (#310)
|
||||||
|
* New hooks: HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS, HOOK_GUILDS_AFTER_MANAGE_BUTTON (https://github.com/slawkens/myaac/commit/c074a48f245df55646b6705737f667b6a84149b2, https://github.com/slawkens/myaac/commit/e6100a1b72de8695bba1dae9ba4e28bfdce47b10)
|
||||||
|
* Add OTS_Toolbox::getVocationName(id, promotion) + OTS_Player->isNameLocked() (https://github.com/slawkens/myaac/commit/e222957893c4a1de0dc8dbba55bce1a43418d275, https://github.com/slawkens/myaac/commit/522f6c11d835afd36fd07a07074d96d7e219b488)
|
||||||
|
* Add missing csrf in more places, causing white page with error about Request (https://github.com/slawkens/myaac/commit/dca904e61d21d856bf809070e7652803a2df0f58, https://github.com/slawkens/myaac/commit/c720ccc451ff90ef40b2a1595468d061ffd7e1e4)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* Revamped online page (https://github.com/slawkens/myaac/commit/9a90e4aae280e607430511c6727d9a714b11f4c5, https://github.com/slawkens/myaac/commit/4767120043b09141870383e249f3729638d53dc2)
|
||||||
|
* Better $title inventing (https://github.com/slawkens/myaac/commit/0c95bcfd06b68b21512e477646ef7bd3a0d4912b)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* Use apcu cache clear (https://github.com/slawkens/myaac/commit/b329da52aae9d0e21120a6444d3caf442420ce50, https://github.com/slawkens/myaac/commit/566c2a9151ab6392286f74e26853faa19a1b4f24)
|
||||||
|
* fix: boostedcreatures for 13.40 (by @GooseWithAKnife) (#307)
|
||||||
|
|
||||||
|
## [1.6.1 - 11.06.2025]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* Fixed "Request has been cancelled due to security reasons", cause of missing csrf() in twig files (https://github.com/slawkens/myaac/commit/10cd71a6630ffec91b43a26a6d685b66c5836a6a)
|
||||||
|
* Fix: Ignore duplicated route exception (https://github.com/slawkens/myaac/commit/9d8e9d27bd87167d8d4005942a6af62bfe4c0892)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* Move counter & visitors code before router (In case someone wants to include that info on page) (https://github.com/slawkens/myaac/commit/f78285030708ad3c74ab048711f73bbf3ee5281e)
|
||||||
|
* Set TinyMCE license key to gpl (Avoid warning message in browser console) (https://github.com/slawkens/myaac/commit/8d29fdb98b92dbc3d2853ef88a185c67036b4a77)
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
* Remove deprecated TinyMCE plugin - template (https://github.com/slawkens/myaac/commit/309c1fb715b882e67cb673b1544a03befbf64a22)
|
||||||
|
|
||||||
## [1.6 - 03.06.2025]
|
## [1.6 - 03.06.2025]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@@ -26,7 +26,6 @@ if (setting('core.account_country'))
|
|||||||
$nameOrNumberColumn = getAccountIdentityColumn();
|
$nameOrNumberColumn = getAccountIdentityColumn();
|
||||||
|
|
||||||
$hasSecretColumn = $db->hasColumn('accounts', 'secret');
|
$hasSecretColumn = $db->hasColumn('accounts', 'secret');
|
||||||
$hasCoinsColumn = $db->hasColumn('accounts', 'coins');
|
|
||||||
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
|
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
|
||||||
$hasTypeColumn = $db->hasColumn('accounts', 'type');
|
$hasTypeColumn = $db->hasColumn('accounts', 'type');
|
||||||
$hasGroupColumn = $db->hasColumn('accounts', 'group_id');
|
$hasGroupColumn = $db->hasColumn('accounts', 'group_id');
|
||||||
@@ -136,11 +135,18 @@ else if (isset($_REQUEST['search'])) {
|
|||||||
if (!Validator::email($email))
|
if (!Validator::email($email))
|
||||||
$errors['email'] = Validator::getLastError();
|
$errors['email'] = Validator::getLastError();
|
||||||
|
|
||||||
//tibia coins
|
// tibia coins
|
||||||
if ($hasCoinsColumn) {
|
if (HAS_ACCOUNT_COINS) {
|
||||||
$t_coins = $_POST['t_coins'];
|
$t_coins = $_POST['t_coins'];
|
||||||
verify_number($t_coins, 'Tibia coins', 12);
|
verify_number($t_coins, 'Tibia coins', 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// transferable tibia coins
|
||||||
|
if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) {
|
||||||
|
$t_coins_transferable = $_POST['t_coins_transferable'];
|
||||||
|
verify_number($t_coins_transferable, 'Transferable Tibia coins', 12);
|
||||||
|
}
|
||||||
|
|
||||||
// prem days
|
// prem days
|
||||||
$p_days = (int)$_POST['p_days'];
|
$p_days = (int)$_POST['p_days'];
|
||||||
verify_number($p_days, 'Prem days', 11);
|
verify_number($p_days, 'Prem days', 11);
|
||||||
@@ -185,12 +191,18 @@ else if (isset($_REQUEST['search'])) {
|
|||||||
if ($hasSecretColumn) {
|
if ($hasSecretColumn) {
|
||||||
$account->setCustomField('secret', $secret);
|
$account->setCustomField('secret', $secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
$account->setCustomField('key', $key);
|
$account->setCustomField('key', $key);
|
||||||
$account->setEMail($email);
|
$account->setEMail($email);
|
||||||
if ($hasCoinsColumn) {
|
|
||||||
|
if (HAS_ACCOUNT_COINS) {
|
||||||
$account->setCustomField('coins', $t_coins);
|
$account->setCustomField('coins', $t_coins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) {
|
||||||
|
$account->setCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN, $t_coins_transferable);
|
||||||
|
}
|
||||||
|
|
||||||
$lastDay = 0;
|
$lastDay = 0;
|
||||||
if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) {
|
if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) {
|
||||||
$lastDay = time();
|
$lastDay = time();
|
||||||
@@ -223,9 +235,6 @@ else if (isset($_REQUEST['search'])) {
|
|||||||
|
|
||||||
$password = encrypt($password);
|
$password = encrypt($password);
|
||||||
$account->setPassword($password);
|
$account->setPassword($password);
|
||||||
|
|
||||||
if (USE_ACCOUNT_SALT)
|
|
||||||
$account->setCustomField('salt', $salt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$account->save();
|
$account->save();
|
||||||
@@ -395,12 +404,18 @@ else if (isset($_REQUEST['search'])) {
|
|||||||
<label for="email">Email:</label><?php echo (setting('core.mail_enabled') ? ' (<a href="' . ADMIN_URL . '?p=mailer&mail_to=' . $account->getEMail() . '">Send Mail</a>)' : ''); ?>
|
<label for="email">Email:</label><?php echo (setting('core.mail_enabled') ? ' (<a href="' . ADMIN_URL . '?p=mailer&mail_to=' . $account->getEMail() . '">Send Mail</a>)' : ''); ?>
|
||||||
<input type="text" class="form-control" id="email" name="email" autocomplete="off" value="<?php echo $account->getEMail(); ?>"/>
|
<input type="text" class="form-control" id="email" name="email" autocomplete="off" value="<?php echo $account->getEMail(); ?>"/>
|
||||||
</div>
|
</div>
|
||||||
<?php if ($hasCoinsColumn): ?>
|
<?php if (HAS_ACCOUNT_COINS): ?>
|
||||||
<div class="col-12 col-sm-12 col-lg-6">
|
<div class="col-12 col-sm-12 col-lg-6">
|
||||||
<label for="t_coins">Tibia Coins:</label>
|
<label for="t_coins">Tibia Coins:</label>
|
||||||
<input type="text" class="form-control" id="t_coins" name="t_coins" autocomplete="off" maxlength="11" value="<?php echo $account->getCustomField('coins') ?>"/>
|
<input type="text" class="form-control" id="t_coins" name="t_coins" autocomplete="off" maxlength="11" value="<?php echo $account->getCustomField('coins') ?>"/>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
<?php if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS): ?>
|
||||||
|
<div class="col-12 col-sm-12 col-lg-6">
|
||||||
|
<label for="t_coins_transferable">Transferable Tibia Coins:</label>
|
||||||
|
<input type="text" class="form-control" id="t_coins_transferable" name="t_coins_transferable" autocomplete="off" maxlength="11" value="<?php echo $account->getCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN) ?>"/>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
<div class="col-12 col-sm-12 col-lg-6">
|
<div class="col-12 col-sm-12 col-lg-6">
|
||||||
<label for="p_days">Premium Days:</label>
|
<label for="p_days">Premium Days:</label>
|
||||||
<input type="text" class="form-control" id="p_days" name="p_days" autocomplete="off" maxlength="11" value="<?php echo $account->getPremDays(); ?>"/>
|
<input type="text" class="form-control" id="p_days" name="p_days" autocomplete="off" maxlength="11" value="<?php echo $account->getPremDays(); ?>"/>
|
||||||
|
@@ -25,9 +25,10 @@ if (!setting('core.mail_enabled')) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$mail_to = isset($_POST['mail_to']) ? stripslashes(trim($_POST['mail_to'])) : null;
|
$mail_to = isset($_REQUEST['mail_to']) ? stripslashes(trim($_REQUEST['mail_to'])) : null;
|
||||||
$mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : null;
|
$mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : null;
|
||||||
$mail_content = isset($_POST['mail_content']) ? stripslashes($_POST['mail_content']) : null;
|
$mail_content = isset($_POST['mail_content']) ? stripslashes($_POST['mail_content']) : null;
|
||||||
|
$mail_verified_only = $_POST['mail_verified_only'] ?? false;
|
||||||
|
|
||||||
if (isset($_POST['submit'])) {
|
if (isset($_POST['submit'])) {
|
||||||
if (empty($mail_subject)) {
|
if (empty($mail_subject)) {
|
||||||
@@ -58,14 +59,14 @@ if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) {
|
|||||||
$success = 0;
|
$success = 0;
|
||||||
$failed = 0;
|
$failed = 0;
|
||||||
|
|
||||||
$add = '';
|
$query = Account::where('email', '!=', '');
|
||||||
if (setting('core.account_mail_verify')) {
|
|
||||||
note('Note: Sending only to users with verified E-Mail.');
|
if ($mail_verified_only) {
|
||||||
$add = ' AND `email_verified` = 1';
|
info('Note: Sending only to users with verified E-Mail.');
|
||||||
|
$query->where('email_verified', 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = Account::where('email', '!=', '')->get(['email']);
|
foreach ($query->get(['email']) as $email) {
|
||||||
foreach ($query as $email) {
|
|
||||||
if (_mail($email->email, $mail_subject, $mail_content)) {
|
if (_mail($email->email, $mail_subject, $mail_content)) {
|
||||||
$success++;
|
$success++;
|
||||||
}
|
}
|
||||||
@@ -84,5 +85,6 @@ if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) {
|
|||||||
$twig->display('admin.mailer.html.twig', [
|
$twig->display('admin.mailer.html.twig', [
|
||||||
'mail_to' => $mail_to,
|
'mail_to' => $mail_to,
|
||||||
'mail_subject' => $mail_subject,
|
'mail_subject' => $mail_subject,
|
||||||
'mail_content' => $mail_content
|
'mail_content' => $mail_content,
|
||||||
|
'mail_verified_only' => $mail_verified_only,
|
||||||
]);
|
]);
|
||||||
|
@@ -18,7 +18,6 @@ $title = 'Mass Account Actions';
|
|||||||
|
|
||||||
csrfProtect();
|
csrfProtect();
|
||||||
|
|
||||||
$hasCoinsColumn = $db->hasColumn('accounts', 'coins');
|
|
||||||
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
|
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
|
||||||
$freePremium = $config['lua']['freePremium'];
|
$freePremium = $config['lua']['freePremium'];
|
||||||
|
|
||||||
@@ -40,9 +39,7 @@ function admin_give_points($points)
|
|||||||
|
|
||||||
function admin_give_coins($coins)
|
function admin_give_coins($coins)
|
||||||
{
|
{
|
||||||
global $hasCoinsColumn;
|
if (!HAS_ACCOUNT_COINS) {
|
||||||
|
|
||||||
if (!$hasCoinsColumn) {
|
|
||||||
displayMessage('Coins not supported.');
|
displayMessage('Coins not supported.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -167,19 +164,19 @@ if (!empty(ACTION) && isRequestMethod('post')) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$twig->display('admin.tools.account.html.twig', array(
|
$twig->display('admin.tools.account.html.twig', array(
|
||||||
'hasCoinsColumn' => $hasCoinsColumn,
|
'hasCoinsColumn' => HAS_ACCOUNT_COINS,
|
||||||
'hasPointsColumn' => $hasPointsColumn,
|
'hasPointsColumn' => $hasPointsColumn,
|
||||||
'freePremium' => $freePremium,
|
'freePremium' => $freePremium,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayMessage($message, $success = false) {
|
function displayMessage($message, $success = false) {
|
||||||
global $twig, $hasCoinsColumn, $hasPointsColumn, $freePremium;
|
global $twig, $hasPointsColumn, $freePremium;
|
||||||
|
|
||||||
$success ? success($message): error($message);
|
$success ? success($message): error($message);
|
||||||
|
|
||||||
$twig->display('admin.tools.account.html.twig', array(
|
$twig->display('admin.tools.account.html.twig', array(
|
||||||
'hasCoinsColumn' => $hasCoinsColumn,
|
'hasCoinsColumn' => HAS_ACCOUNT_COINS,
|
||||||
'hasPointsColumn' => $hasPointsColumn,
|
'hasPointsColumn' => $hasPointsColumn,
|
||||||
'freePremium' => $freePremium,
|
'freePremium' => $freePremium,
|
||||||
));
|
));
|
||||||
|
@@ -6,7 +6,7 @@ defined('MYAAC') or die('Direct access not allowed!');
|
|||||||
|
|
||||||
$coins = 0;
|
$coins = 0;
|
||||||
|
|
||||||
if ($db->hasColumn('accounts', 'coins')) {
|
if (HAS_ACCOUNT_COINS) {
|
||||||
$whatToGet = ['id', 'coins'];
|
$whatToGet = ['id', 'coins'];
|
||||||
if (USE_ACCOUNT_NAME) {
|
if (USE_ACCOUNT_NAME) {
|
||||||
$whatToGet[] = 'name';
|
$whatToGet[] = 'name';
|
||||||
|
@@ -51,6 +51,56 @@ else {
|
|||||||
} else {
|
} else {
|
||||||
error('Error while disabling plugin ' . $disable . ': ' . Plugins::getError());
|
error('Error while disabling plugin ' . $disable . ': ' . Plugins::getError());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (isset($_GET['check-updates'])) {
|
||||||
|
$repoUri = $config['admin_plugins_api_uri'] ?? 'https://plugins.my-aac.org/api/';
|
||||||
|
success("Fetching latest info from $repoUri..");
|
||||||
|
|
||||||
|
$adminPlugins = new \MyAAC\Admin\Plugins();
|
||||||
|
|
||||||
|
$adminPlugins->setApiBaseUri($repoUri);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$plugins = $adminPlugins->getLatestVersions();
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
error($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($plugins) && count($plugins) > 0) {
|
||||||
|
$outdated = [];
|
||||||
|
|
||||||
|
foreach (get_plugins(true) as $plugin) {
|
||||||
|
$string = file_get_contents(BASE . 'plugins/' . $plugin . '.json');
|
||||||
|
$plugin_info = json_decode($string, true);
|
||||||
|
|
||||||
|
if (!$plugin_info) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$disabled = (str_contains($plugin, 'disabled.'));
|
||||||
|
$pluginOriginal = ($disabled ? str_replace('disabled.', '', $plugin) : $plugin);
|
||||||
|
|
||||||
|
$info = $plugins[$pluginOriginal] ?? false;
|
||||||
|
if ($info && version_compare($info['version'], $plugin_info['version'], '>')) {
|
||||||
|
$outdated[] = [
|
||||||
|
'name' => $pluginOriginal,
|
||||||
|
'yourVersion' => $plugin_info['version'],
|
||||||
|
'latestVersion' => $info['version'],
|
||||||
|
'link' => $info['link'] ?? 'Unknown',
|
||||||
|
'download_link' => $info['download_link'] ?? 'Unknown',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($outdated) > 0) {
|
||||||
|
info('Following updates have been found for your plugins:');
|
||||||
|
$twig->display('admin.plugins.outdated.html.twig', ['plugins' => $outdated]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
success('All plugins up to date!');
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (isset($_FILES['plugin']['name'])) {
|
} else if (isset($_FILES['plugin']['name'])) {
|
||||||
$file = $_FILES['plugin'];
|
$file = $_FILES['plugin'];
|
||||||
$filename = $file['name'];
|
$filename = $file['name'];
|
||||||
|
@@ -19,8 +19,7 @@ $use_datatable = true;
|
|||||||
|
|
||||||
if (!setting('core.visitors_counter')): ?>
|
if (!setting('core.visitors_counter')): ?>
|
||||||
Visitors counter is disabled.<br/>
|
Visitors counter is disabled.<br/>
|
||||||
You can enable it by editing this configurable in <b>config.local.php</b> file:<br/>
|
You can enable it in Settings -> General -> Visitors Counter.<br/>
|
||||||
<p style="margin-left: 3em;"><b>$config['visitors_counter'] = true;</b></p>
|
|
||||||
<?php
|
<?php
|
||||||
return;
|
return;
|
||||||
endif;
|
endif;
|
||||||
@@ -46,7 +45,7 @@ foreach ($tmp as &$visitor) {
|
|||||||
if ($dd->isBot()) {
|
if ($dd->isBot()) {
|
||||||
$bot = $dd->getBot();
|
$bot = $dd->getBot();
|
||||||
$message = '(Bot) %s, <a href="%s" target="_blank">%s</a>';
|
$message = '(Bot) %s, <a href="%s" target="_blank">%s</a>';
|
||||||
$browser = sprintf($message, $bot['category'], $bot['url'], $bot['name']);
|
$browser = sprintf($message, $bot['category'] ?? 'Unknown', $bot['url'] ?? '', $bot['name'] ?? 'Unknown name');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$osFamily = OperatingSystem::getOsFamily($dd->getOs('name'));
|
$osFamily = OperatingSystem::getOsFamily($dd->getOs('name'));
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use MyAAC\Hooks;
|
|
||||||
use MyAAC\Settings;
|
use MyAAC\Settings;
|
||||||
|
|
||||||
const MYAAC_ADMIN = true;
|
const MYAAC_ADMIN = true;
|
||||||
|
@@ -26,8 +26,8 @@
|
|||||||
if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.');
|
if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.');
|
||||||
|
|
||||||
const MYAAC = true;
|
const MYAAC = true;
|
||||||
const MYAAC_VERSION = '1.6';
|
const MYAAC_VERSION = '1.8.1-dev';
|
||||||
const DATABASE_VERSION = 45;
|
const DATABASE_VERSION = 46;
|
||||||
const TABLE_PREFIX = 'myaac_';
|
const TABLE_PREFIX = 'myaac_';
|
||||||
define('START_TIME', microtime(true));
|
define('START_TIME', microtime(true));
|
||||||
define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));
|
define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));
|
||||||
|
@@ -18,7 +18,8 @@
|
|||||||
"symfony/string": "^6.4",
|
"symfony/string": "^6.4",
|
||||||
"symfony/var-dumper": "^6.4",
|
"symfony/var-dumper": "^6.4",
|
||||||
"filp/whoops": "^2.15",
|
"filp/whoops": "^2.15",
|
||||||
"maximebf/debugbar": "1.*"
|
"maximebf/debugbar": "1.*",
|
||||||
|
"guzzlehttp/guzzle": "7.9.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpstan/phpstan": "^1.10"
|
"phpstan/phpstan": "^1.10"
|
||||||
|
537
composer.lock
generated
537
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "be4d1489a53a9cd8eec6bcaa7a096f30",
|
"content-hash": "5317e97a5025ebc2a977214bd3fa964c",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
@@ -493,6 +493,331 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-09-25T12:00:00+00:00"
|
"time": "2024-09-25T12:00:00+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "guzzlehttp/guzzle",
|
||||||
|
"version": "7.9.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/guzzle/guzzle.git",
|
||||||
|
"reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77",
|
||||||
|
"reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-json": "*",
|
||||||
|
"guzzlehttp/promises": "^1.5.3 || ^2.0.3",
|
||||||
|
"guzzlehttp/psr7": "^2.7.0",
|
||||||
|
"php": "^7.2.5 || ^8.0",
|
||||||
|
"psr/http-client": "^1.0",
|
||||||
|
"symfony/deprecation-contracts": "^2.2 || ^3.0"
|
||||||
|
},
|
||||||
|
"provide": {
|
||||||
|
"psr/http-client-implementation": "1.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"bamarni/composer-bin-plugin": "^1.8.2",
|
||||||
|
"ext-curl": "*",
|
||||||
|
"guzzle/client-integration-tests": "3.0.2",
|
||||||
|
"php-http/message-factory": "^1.1",
|
||||||
|
"phpunit/phpunit": "^8.5.39 || ^9.6.20",
|
||||||
|
"psr/log": "^1.1 || ^2.0 || ^3.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-curl": "Required for CURL handler support",
|
||||||
|
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
|
||||||
|
"psr/log": "Required for using the Log middleware"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"bamarni-bin": {
|
||||||
|
"bin-links": true,
|
||||||
|
"forward-command": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/functions_include.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"GuzzleHttp\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Graham Campbell",
|
||||||
|
"email": "hello@gjcampbell.co.uk",
|
||||||
|
"homepage": "https://github.com/GrahamCampbell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Michael Dowling",
|
||||||
|
"email": "mtdowling@gmail.com",
|
||||||
|
"homepage": "https://github.com/mtdowling"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jeremy Lindblom",
|
||||||
|
"email": "jeremeamia@gmail.com",
|
||||||
|
"homepage": "https://github.com/jeremeamia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "George Mponos",
|
||||||
|
"email": "gmponos@gmail.com",
|
||||||
|
"homepage": "https://github.com/gmponos"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tobias Nyholm",
|
||||||
|
"email": "tobias.nyholm@gmail.com",
|
||||||
|
"homepage": "https://github.com/Nyholm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Márk Sági-Kazár",
|
||||||
|
"email": "mark.sagikazar@gmail.com",
|
||||||
|
"homepage": "https://github.com/sagikazarmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tobias Schultze",
|
||||||
|
"email": "webmaster@tubo-world.de",
|
||||||
|
"homepage": "https://github.com/Tobion"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Guzzle is a PHP HTTP client library",
|
||||||
|
"keywords": [
|
||||||
|
"client",
|
||||||
|
"curl",
|
||||||
|
"framework",
|
||||||
|
"http",
|
||||||
|
"http client",
|
||||||
|
"psr-18",
|
||||||
|
"psr-7",
|
||||||
|
"rest",
|
||||||
|
"web service"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/guzzle/guzzle/issues",
|
||||||
|
"source": "https://github.com/guzzle/guzzle/tree/7.9.3"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/GrahamCampbell",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/Nyholm",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-03-27T13:37:11+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "guzzlehttp/promises",
|
||||||
|
"version": "2.2.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/guzzle/promises.git",
|
||||||
|
"reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c",
|
||||||
|
"reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.2.5 || ^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"bamarni/composer-bin-plugin": "^1.8.2",
|
||||||
|
"phpunit/phpunit": "^8.5.39 || ^9.6.20"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"bamarni-bin": {
|
||||||
|
"bin-links": true,
|
||||||
|
"forward-command": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"GuzzleHttp\\Promise\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Graham Campbell",
|
||||||
|
"email": "hello@gjcampbell.co.uk",
|
||||||
|
"homepage": "https://github.com/GrahamCampbell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Michael Dowling",
|
||||||
|
"email": "mtdowling@gmail.com",
|
||||||
|
"homepage": "https://github.com/mtdowling"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tobias Nyholm",
|
||||||
|
"email": "tobias.nyholm@gmail.com",
|
||||||
|
"homepage": "https://github.com/Nyholm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tobias Schultze",
|
||||||
|
"email": "webmaster@tubo-world.de",
|
||||||
|
"homepage": "https://github.com/Tobion"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Guzzle promises library",
|
||||||
|
"keywords": [
|
||||||
|
"promise"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/guzzle/promises/issues",
|
||||||
|
"source": "https://github.com/guzzle/promises/tree/2.2.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/GrahamCampbell",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/Nyholm",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-03-27T13:27:01+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "guzzlehttp/psr7",
|
||||||
|
"version": "2.7.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/guzzle/psr7.git",
|
||||||
|
"reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16",
|
||||||
|
"reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.2.5 || ^8.0",
|
||||||
|
"psr/http-factory": "^1.0",
|
||||||
|
"psr/http-message": "^1.1 || ^2.0",
|
||||||
|
"ralouphie/getallheaders": "^3.0"
|
||||||
|
},
|
||||||
|
"provide": {
|
||||||
|
"psr/http-factory-implementation": "1.0",
|
||||||
|
"psr/http-message-implementation": "1.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"bamarni/composer-bin-plugin": "^1.8.2",
|
||||||
|
"http-interop/http-factory-tests": "0.9.0",
|
||||||
|
"phpunit/phpunit": "^8.5.39 || ^9.6.20"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"bamarni-bin": {
|
||||||
|
"bin-links": true,
|
||||||
|
"forward-command": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"GuzzleHttp\\Psr7\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Graham Campbell",
|
||||||
|
"email": "hello@gjcampbell.co.uk",
|
||||||
|
"homepage": "https://github.com/GrahamCampbell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Michael Dowling",
|
||||||
|
"email": "mtdowling@gmail.com",
|
||||||
|
"homepage": "https://github.com/mtdowling"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "George Mponos",
|
||||||
|
"email": "gmponos@gmail.com",
|
||||||
|
"homepage": "https://github.com/gmponos"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tobias Nyholm",
|
||||||
|
"email": "tobias.nyholm@gmail.com",
|
||||||
|
"homepage": "https://github.com/Nyholm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Márk Sági-Kazár",
|
||||||
|
"email": "mark.sagikazar@gmail.com",
|
||||||
|
"homepage": "https://github.com/sagikazarmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tobias Schultze",
|
||||||
|
"email": "webmaster@tubo-world.de",
|
||||||
|
"homepage": "https://github.com/Tobion"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Márk Sági-Kazár",
|
||||||
|
"email": "mark.sagikazar@gmail.com",
|
||||||
|
"homepage": "https://sagikazarmark.hu"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PSR-7 message implementation that also provides common utility methods",
|
||||||
|
"keywords": [
|
||||||
|
"http",
|
||||||
|
"message",
|
||||||
|
"psr-7",
|
||||||
|
"request",
|
||||||
|
"response",
|
||||||
|
"stream",
|
||||||
|
"uri",
|
||||||
|
"url"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/guzzle/psr7/issues",
|
||||||
|
"source": "https://github.com/guzzle/psr7/tree/2.7.1"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/GrahamCampbell",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/Nyholm",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-03-27T12:30:47+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "illuminate/collections",
|
"name": "illuminate/collections",
|
||||||
"version": "v10.48.25",
|
"version": "v10.48.25",
|
||||||
@@ -1472,6 +1797,166 @@
|
|||||||
},
|
},
|
||||||
"time": "2021-11-05T16:47:00+00:00"
|
"time": "2021-11-05T16:47:00+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "psr/http-client",
|
||||||
|
"version": "1.0.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/php-fig/http-client.git",
|
||||||
|
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
|
||||||
|
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.0 || ^8.0",
|
||||||
|
"psr/http-message": "^1.0 || ^2.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.0.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Psr\\Http\\Client\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "PHP-FIG",
|
||||||
|
"homepage": "https://www.php-fig.org/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Common interface for HTTP clients",
|
||||||
|
"homepage": "https://github.com/php-fig/http-client",
|
||||||
|
"keywords": [
|
||||||
|
"http",
|
||||||
|
"http-client",
|
||||||
|
"psr",
|
||||||
|
"psr-18"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/php-fig/http-client"
|
||||||
|
},
|
||||||
|
"time": "2023-09-23T14:17:50+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "psr/http-factory",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/php-fig/http-factory.git",
|
||||||
|
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
|
||||||
|
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1",
|
||||||
|
"psr/http-message": "^1.0 || ^2.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.0.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Psr\\Http\\Message\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "PHP-FIG",
|
||||||
|
"homepage": "https://www.php-fig.org/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
|
||||||
|
"keywords": [
|
||||||
|
"factory",
|
||||||
|
"http",
|
||||||
|
"message",
|
||||||
|
"psr",
|
||||||
|
"psr-17",
|
||||||
|
"psr-7",
|
||||||
|
"request",
|
||||||
|
"response"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/php-fig/http-factory"
|
||||||
|
},
|
||||||
|
"time": "2024-04-15T12:06:14+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "psr/http-message",
|
||||||
|
"version": "2.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/php-fig/http-message.git",
|
||||||
|
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
|
||||||
|
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.2 || ^8.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "2.0.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Psr\\Http\\Message\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "PHP-FIG",
|
||||||
|
"homepage": "https://www.php-fig.org/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Common interface for HTTP messages",
|
||||||
|
"homepage": "https://github.com/php-fig/http-message",
|
||||||
|
"keywords": [
|
||||||
|
"http",
|
||||||
|
"http-message",
|
||||||
|
"psr",
|
||||||
|
"psr-7",
|
||||||
|
"request",
|
||||||
|
"response"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/php-fig/http-message/tree/2.0"
|
||||||
|
},
|
||||||
|
"time": "2023-04-04T09:54:51+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/log",
|
"name": "psr/log",
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
@@ -1573,6 +2058,50 @@
|
|||||||
},
|
},
|
||||||
"time": "2021-10-29T13:26:27+00:00"
|
"time": "2021-10-29T13:26:27+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "ralouphie/getallheaders",
|
||||||
|
"version": "3.0.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/ralouphie/getallheaders.git",
|
||||||
|
"reference": "120b605dfeb996808c31b6477290a714d356e822"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
|
||||||
|
"reference": "120b605dfeb996808c31b6477290a714d356e822",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.6"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"php-coveralls/php-coveralls": "^2.1",
|
||||||
|
"phpunit/phpunit": "^5 || ^6.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/getallheaders.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Ralph Khattar",
|
||||||
|
"email": "ralph.khattar@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A polyfill for getallheaders.",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/ralouphie/getallheaders/issues",
|
||||||
|
"source": "https://github.com/ralouphie/getallheaders/tree/develop"
|
||||||
|
},
|
||||||
|
"time": "2019-03-08T08:55:37+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v6.4.17",
|
"version": "v6.4.17",
|
||||||
@@ -2910,7 +3439,7 @@
|
|||||||
],
|
],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"stability-flags": [],
|
"stability-flags": {},
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
@@ -2921,6 +3450,6 @@
|
|||||||
"ext-xml": "*",
|
"ext-xml": "*",
|
||||||
"ext-dom": "*"
|
"ext-dom": "*"
|
||||||
},
|
},
|
||||||
"platform-dev": [],
|
"platform-dev": {},
|
||||||
"plugin-api-version": "2.3.0"
|
"plugin-api-version": "2.6.0"
|
||||||
}
|
}
|
||||||
|
BIN
images/order_asc.gif
Normal file
BIN
images/order_asc.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 B |
BIN
images/order_desc.gif
Normal file
BIN
images/order_desc.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 B |
25
index.php
25
index.php
@@ -93,6 +93,7 @@ if(setting('core.backward_support')) {
|
|||||||
if($logged && $account_logged)
|
if($logged && $account_logged)
|
||||||
$group_id_of_acc_logged = $account_logged->getGroupId();
|
$group_id_of_acc_logged = $account_logged->getGroupId();
|
||||||
|
|
||||||
|
$config['serverPath'] = $config['server_path'];
|
||||||
$config['site'] = &$config;
|
$config['site'] = &$config;
|
||||||
$config['server'] = &$config['lua'];
|
$config['server'] = &$config['lua'];
|
||||||
$config['site']['shop_system'] = setting('core.gifts_system');
|
$config['site']['shop_system'] = setting('core.gifts_system');
|
||||||
@@ -117,6 +118,14 @@ if(setting('core.backward_support')) {
|
|||||||
$config['status']['serverStatus_' . $key] = $value;
|
$config['status']['serverStatus_' . $key] = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(setting('core.views_counter')) {
|
||||||
|
require_once SYSTEM . 'counter.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(setting('core.visitors_counter')) {
|
||||||
|
$visitors = new Visitors(setting('core.visitors_counter_ttl'));
|
||||||
|
}
|
||||||
|
|
||||||
require_once SYSTEM . 'router.php';
|
require_once SYSTEM . 'router.php';
|
||||||
|
|
||||||
// anonymous usage statistics
|
// anonymous usage statistics
|
||||||
@@ -153,22 +162,6 @@ if(setting('core.anonymous_usage_statistics')) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(setting('core.views_counter'))
|
|
||||||
require_once SYSTEM . 'counter.php';
|
|
||||||
|
|
||||||
if(setting('core.visitors_counter')) {
|
|
||||||
$visitors = new Visitors(setting('core.visitors_counter_ttl'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var OTS_Account $account_logged
|
|
||||||
*/
|
|
||||||
if ($logged && admin()) {
|
|
||||||
$content .= $twig->render('admin-bar.html.twig', [
|
|
||||||
'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$title_full = (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];
|
$title_full = (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];
|
||||||
require $template_path . '/' . $template_index;
|
require $template_path . '/' . $template_index;
|
||||||
|
|
||||||
|
@@ -10,6 +10,15 @@ CREATE TABLE `myaac_account_actions`
|
|||||||
KEY (`account_id`)
|
KEY (`account_id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||||
|
|
||||||
|
CREATE TABLE `myaac_account_email_codes`
|
||||||
|
(
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`account_id` int NOT NULL,
|
||||||
|
`code` varchar(6) NOT NULL,
|
||||||
|
`created_at` int NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||||
|
|
||||||
CREATE TABLE `myaac_admin_menu`
|
CREATE TABLE `myaac_admin_menu`
|
||||||
(
|
(
|
||||||
`id` int NOT NULL AUTO_INCREMENT,
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
@@ -88,8 +88,8 @@ switch ($action) {
|
|||||||
case 'boostedcreature':
|
case 'boostedcreature':
|
||||||
$clientVersion = (int)setting('core.client');
|
$clientVersion = (int)setting('core.client');
|
||||||
|
|
||||||
// 14.00 and up
|
// 13.40 and up
|
||||||
if ($clientVersion >= 1400) {
|
if ($clientVersion >= 1340) {
|
||||||
$creatureBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_creature'))->fetchAll();
|
$creatureBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_creature'))->fetchAll();
|
||||||
$bossBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_boss'))->fetchAll();
|
$bossBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_boss'))->fetchAll();
|
||||||
die(json_encode([
|
die(json_encode([
|
||||||
|
13
package-lock.json
generated
13
package-lock.json
generated
@@ -976,15 +976,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/form-data": {
|
"node_modules/form-data": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
||||||
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
|
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
"es-set-tostringtag": "^2.1.0",
|
"es-set-tostringtag": "^2.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
"mime-types": "^2.1.12"
|
"mime-types": "^2.1.12"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -2084,9 +2085,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/tmp": {
|
"node_modules/tmp": {
|
||||||
"version": "0.2.3",
|
"version": "0.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.4.tgz",
|
||||||
"integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
|
"integrity": "sha512-UdiSoX6ypifLmrfQ/XfiawN6hkjSBpCjhKxxZcWlUUmoXLaCKQU0bx4HF/tdDK2uzRuchf1txGvrWBzYREssoQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@@ -28,10 +28,9 @@ parameters:
|
|||||||
- '#Variable \$guild might not be defined#'
|
- '#Variable \$guild might not be defined#'
|
||||||
- '#Variable \$[a-zA-Z0-9\\_]+ might not be defined#'
|
- '#Variable \$[a-zA-Z0-9\\_]+ might not be defined#'
|
||||||
# Eloquent models
|
# Eloquent models
|
||||||
|
- '#Call to an undefined 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 static method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\)#'
|
||||||
- '#Call to an undefined method object::toArray\(\)#'
|
|
||||||
# system/pages/highscores.php
|
# system/pages/highscores.php
|
||||||
- '#Call to an undefined method Illuminate\\Database\\Query\\Builder::withOnlineStatus\(\)#'
|
|
||||||
- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$online_status#'
|
- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$online_status#'
|
||||||
- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$vocation_name#'
|
- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$vocation_name#'
|
||||||
-
|
-
|
||||||
|
@@ -51,5 +51,8 @@
|
|||||||
"themes": true,
|
"themes": true,
|
||||||
"admin-pages": true,
|
"admin-pages": true,
|
||||||
"admin-pages-sub-folders": true,
|
"admin-pages-sub-folders": true,
|
||||||
|
"settings": true,
|
||||||
|
"install": true,
|
||||||
|
"init": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -512,6 +512,13 @@ function template_place_holder($type): string
|
|||||||
}
|
}
|
||||||
elseif ($type === 'body_start') {
|
elseif ($type === 'body_start') {
|
||||||
$ret .= $twig->render('browsehappy.html.twig');
|
$ret .= $twig->render('browsehappy.html.twig');
|
||||||
|
|
||||||
|
if (admin()) {
|
||||||
|
global $account_logged;
|
||||||
|
$ret .= $twig->render('admin-bar.html.twig', [
|
||||||
|
'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
elseif($type === 'body_end') {
|
elseif($type === 'body_end') {
|
||||||
$ret .= template_ga_code();
|
$ret .= template_ga_code();
|
||||||
@@ -767,6 +774,10 @@ function formatExperience($exp, $color = true)
|
|||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getExperienceForLevel($level): float|int {
|
||||||
|
return ( 50 / 3 ) * pow( $level, 3 ) - ( 100 * pow( $level, 2 ) ) + ( ( 850 / 3 ) * $level ) - 200;
|
||||||
|
}
|
||||||
|
|
||||||
function get_locales()
|
function get_locales()
|
||||||
{
|
{
|
||||||
$ret = array();
|
$ret = array();
|
||||||
@@ -982,11 +993,12 @@ function load_config_lua($filename)
|
|||||||
foreach($lines as $ln => $line)
|
foreach($lines as $ln => $line)
|
||||||
{
|
{
|
||||||
$line = trim($line);
|
$line = trim($line);
|
||||||
if(@$line[0] === '{' || @$line[0] === '}') {
|
if(isset($line[0]) && ($line[0] === '{' || $line[0] === '}')) {
|
||||||
// arrays are not supported yet
|
// arrays are not supported yet
|
||||||
// just ignore the error
|
// just ignore the error
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$tmp_exp = explode('=', $line, 2);
|
$tmp_exp = explode('=', $line, 2);
|
||||||
if(str_contains($line, 'dofile')) {
|
if(str_contains($line, 'dofile')) {
|
||||||
$delimiter = '"';
|
$delimiter = '"';
|
||||||
@@ -1216,7 +1228,8 @@ function setting($key)
|
|||||||
return $settings[$key[0]] = $key[1];
|
return $settings[$key[0]] = $key[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $settings[$key]['value'];
|
$ret = $settings[$key];
|
||||||
|
return isset($ret) ? $ret['value'] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearCache()
|
function clearCache()
|
||||||
@@ -1265,14 +1278,15 @@ function clearCache()
|
|||||||
$db->setClearCacheAfter(true);
|
$db->setClearCacheAfter(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (function_exists('apcu_clear_cache')) {
|
||||||
|
apcu_clear_cache();
|
||||||
|
}
|
||||||
|
|
||||||
deleteDirectory(CACHE . 'signatures', ['index.html'], true);
|
deleteDirectory(CACHE . 'signatures', ['index.html'], true);
|
||||||
deleteDirectory(CACHE . 'twig', ['index.html'], true);
|
deleteDirectory(CACHE . 'twig', ['index.html'], true);
|
||||||
deleteDirectory(CACHE . 'plugins', ['index.html'], true);
|
deleteDirectory(CACHE . 'plugins', ['index.html'], true);
|
||||||
deleteDirectory(CACHE, ['signatures', 'twig', 'plugins', 'index.html', 'persistent'], true);
|
deleteDirectory(CACHE, ['signatures', 'twig', 'plugins', 'index.html', 'persistent'], true);
|
||||||
|
|
||||||
// routes cache
|
|
||||||
clearRouteCache();
|
|
||||||
|
|
||||||
global $hooks;
|
global $hooks;
|
||||||
$hooks->trigger(HOOK_CACHE_CLEAR, ['cache' => Cache::getInstance()]);
|
$hooks->trigger(HOOK_CACHE_CLEAR, ['cache' => Cache::getInstance()]);
|
||||||
|
|
||||||
|
@@ -144,6 +144,15 @@ $ots = POT::getInstance();
|
|||||||
$eloquentConnection = null;
|
$eloquentConnection = null;
|
||||||
require_once SYSTEM . 'database.php';
|
require_once SYSTEM . 'database.php';
|
||||||
|
|
||||||
|
define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name'));
|
||||||
|
define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number'));
|
||||||
|
define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt'));
|
||||||
|
|
||||||
|
define('HAS_ACCOUNT_COINS', $db->hasColumn('accounts', 'coins'));
|
||||||
|
define('HAS_ACCOUNT_COINS_TRANSFERABLE', $db->hasColumn('accounts', 'coins_transferable'));
|
||||||
|
define('HAS_ACCOUNT_TRANSFERABLE_COINS', $db->hasColumn('accounts', 'transferable_coins'));
|
||||||
|
const ACCOUNT_COINS_TRANSFERABLE_COLUMN = (HAS_ACCOUNT_COINS_TRANSFERABLE ? 'coins_transferable' : 'transferable_coins');
|
||||||
|
|
||||||
$twig->addGlobal('logged', false);
|
$twig->addGlobal('logged', false);
|
||||||
$twig->addGlobal('account_logged', new \OTS_Account());
|
$twig->addGlobal('account_logged', new \OTS_Account());
|
||||||
|
|
||||||
@@ -188,10 +197,6 @@ if($settingsItemImagesURL[strlen($settingsItemImagesURL) - 1] !== '/') {
|
|||||||
setting(['core.item_images_url', $settingsItemImagesURL . '/']);
|
setting(['core.item_images_url', $settingsItemImagesURL . '/']);
|
||||||
}
|
}
|
||||||
|
|
||||||
define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name'));
|
|
||||||
define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number'));
|
|
||||||
define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt'));
|
|
||||||
|
|
||||||
$towns = Cache::remember('towns', 10 * 60, function () use ($db) {
|
$towns = Cache::remember('towns', 10 * 60, function () use ($db) {
|
||||||
if ($db->hasTable('towns') && Town::count() > 0) {
|
if ($db->hasTable('towns') && Town::count() > 0) {
|
||||||
return Town::orderBy('id', 'ASC')->pluck('name', 'id')->toArray();
|
return Town::orderBy('id', 'ASC')->pluck('name', 'id')->toArray();
|
||||||
|
@@ -473,12 +473,9 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
|
|||||||
|
|
||||||
public function isPremium()
|
public function isPremium()
|
||||||
{
|
{
|
||||||
global $config;
|
if(isset($this->data['premium_ends_at'])) {
|
||||||
if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return true;
|
return $this->data['premium_ends_at'] > time();
|
||||||
|
}
|
||||||
if(isset($this->data['premium_ends_at'])) {
|
|
||||||
return $this->data['premium_ends_at'] > time();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($this->data['premend'])) {
|
if(isset($this->data['premend'])) {
|
||||||
return $this->data['premend'] > time();
|
return $this->data['premend'] > time();
|
||||||
|
@@ -2919,6 +2919,32 @@ class OTS_Player extends OTS_Row_DAO
|
|||||||
$this->data['banned'] = $ban['active'];
|
$this->data['banned'] = $ban['active'];
|
||||||
$this->data['banned_time'] = $ban['expires'];
|
$this->data['banned_time'] = $ban['expires'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isNameLocked(): bool
|
||||||
|
{
|
||||||
|
// nothing can't be banned
|
||||||
|
if( !$this->isLoaded() ) {
|
||||||
|
throw new E_OTS_NotLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->db->hasTable('player_namelocks')) {
|
||||||
|
$ban = $this->db->query('SELECT 1 FROM `player_namelocks` WHERE `player_id` = ' . $this->data['id'])->fetch(PDO::FETCH_ASSOC);
|
||||||
|
return (isset($ban['1']));
|
||||||
|
}
|
||||||
|
else if($this->db->hasTable('bans')) {
|
||||||
|
if($this->db->hasColumn('bans', 'active')) {
|
||||||
|
$ban = $this->db->query('SELECT `active`, `expires` FROM `bans` WHERE `type` = 2 AND `active` = 1 AND `value` = ' . $this->data['id'] . ' AND (`expires` > ' . time() .' OR `expires` = -1) ORDER BY `expires` DESC')->fetch();
|
||||||
|
return isset($ban['active']);
|
||||||
|
}
|
||||||
|
else { // tfs 0.2
|
||||||
|
$ban = $this->db->query('SELECT `time` FROM `bans` WHERE `type` = 2 AND `account` = ' . $this->data['account_id'] . ' AND (`time` > ' . time() .' OR `time` = -1) ORDER BY `time` DESC')->fetch();
|
||||||
|
|
||||||
|
return isset($ban['time']) && ($ban['time'] == -1 || $ban['time'] > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Deletes player.
|
* Deletes player.
|
||||||
*
|
*
|
||||||
@@ -2953,21 +2979,14 @@ class OTS_Player extends OTS_Row_DAO
|
|||||||
* @return string Player proffesion name.
|
* @return string Player proffesion name.
|
||||||
* @throws E_OTS_NotLoaded If player is not loaded or global vocations list is not loaded.
|
* @throws E_OTS_NotLoaded If player is not loaded or global vocations list is not loaded.
|
||||||
*/
|
*/
|
||||||
public function getVocationName()
|
public function getVocationName(): string
|
||||||
{
|
{
|
||||||
if( !isset($this->data['vocation']) )
|
if( !isset($this->data['vocation']) )
|
||||||
{
|
{
|
||||||
throw new E_OTS_NotLoaded();
|
throw new E_OTS_NotLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
global $config;
|
return OTS_Toolbox::getVocationName($this->data['vocation'], $this->data['promotion'] ?? 0);
|
||||||
$voc = $this->getVocation();
|
|
||||||
if(!isset($config['vocations'][$voc])) {
|
|
||||||
return 'Unknown';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $config['vocations'][$voc];
|
|
||||||
//return POT::getInstance()->getVocationsList()->getVocationName($this->data['vocation']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -29,11 +29,11 @@ class OTS_Toolbox
|
|||||||
* @return int Experience points for level.
|
* @return int Experience points for level.
|
||||||
*/
|
*/
|
||||||
public static function experienceForLevel($level, $experience = 0)
|
public static function experienceForLevel($level, $experience = 0)
|
||||||
{
|
{
|
||||||
//return 50 * ($level - 1) * ($level * $level - 5 * $level + 12) / 3 - $experience;
|
//return 50 * ($level - 1) * ($level * $level - 5 * $level + 12) / 3 - $experience;
|
||||||
$level = $level - 1;
|
$level = $level - 1;
|
||||||
return ((50 * $level * $level * $level) - (150 * $level * $level) + (400 * $level)) / 3;
|
return ((50 * $level * $level * $level) - (150 * $level * $level) + (400 * $level)) / 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds out which level user have basing on his/her experience.
|
* Finds out which level user have basing on his/her experience.
|
||||||
@@ -45,19 +45,19 @@ class OTS_Toolbox
|
|||||||
* @param int $experience Current experience points.
|
* @param int $experience Current experience points.
|
||||||
* @return int Experience level.
|
* @return int Experience level.
|
||||||
*/
|
*/
|
||||||
public static function levelForExperience($experience)
|
public static function levelForExperience($experience)
|
||||||
{
|
{
|
||||||
// default level
|
// default level
|
||||||
$level = 1;
|
$level = 1;
|
||||||
|
|
||||||
// until we will find level which requires more experience then we have we will step to next
|
// until we will find level which requires more experience then we have we will step to next
|
||||||
while( self::experienceForLevel($level + 1) <= $experience)
|
while( self::experienceForLevel($level + 1) <= $experience)
|
||||||
{
|
{
|
||||||
$level++;
|
$level++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $level;
|
return $level;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @version 0.1.5
|
* @version 0.1.5
|
||||||
@@ -65,25 +65,25 @@ class OTS_Toolbox
|
|||||||
* @return OTS_Players_List Filtered list.
|
* @return OTS_Players_List Filtered list.
|
||||||
* @deprecated 0.1.5 Use OTS_PlayerBans_List.
|
* @deprecated 0.1.5 Use OTS_PlayerBans_List.
|
||||||
*/
|
*/
|
||||||
public static function bannedPlayers()
|
public static function bannedPlayers()
|
||||||
{
|
{
|
||||||
// creates filter
|
// creates filter
|
||||||
$filter = new OTS_SQLFilter();
|
$filter = new OTS_SQLFilter();
|
||||||
$filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_PLAYER);
|
$filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_PLAYER);
|
||||||
$filter->addFilter( new OTS_SQLField('active', 'bans'), 1);
|
$filter->addFilter( new OTS_SQLField('active', 'bans'), 1);
|
||||||
$filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'players') );
|
$filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'players') );
|
||||||
|
|
||||||
// selects only active bans
|
// selects only active bans
|
||||||
$actives = new OTS_SQLFilter();
|
$actives = new OTS_SQLFilter();
|
||||||
$actives->addFilter( new OTS_SQLField('expires', 'bans'), 0);
|
$actives->addFilter( new OTS_SQLField('expires', 'bans'), 0);
|
||||||
$actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR);
|
$actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR);
|
||||||
$filter->addFilter($actives);
|
$filter->addFilter($actives);
|
||||||
|
|
||||||
// creates list and aplies filter
|
// creates list and aplies filter
|
||||||
$list = new OTS_Players_List();
|
$list = new OTS_Players_List();
|
||||||
$list->setFilter($filter);
|
$list->setFilter($filter);
|
||||||
return $list;
|
return $list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @version 0.1.5
|
* @version 0.1.5
|
||||||
@@ -91,25 +91,34 @@ class OTS_Toolbox
|
|||||||
* @return OTS_Accounts_List Filtered list.
|
* @return OTS_Accounts_List Filtered list.
|
||||||
* @deprecated 0.1.5 Use OTS_AccountBans_List.
|
* @deprecated 0.1.5 Use OTS_AccountBans_List.
|
||||||
*/
|
*/
|
||||||
public static function bannedAccounts()
|
public static function bannedAccounts()
|
||||||
{
|
{
|
||||||
// creates filter
|
// creates filter
|
||||||
$filter = new OTS_SQLFilter();
|
$filter = new OTS_SQLFilter();
|
||||||
$filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_ACCOUNT);
|
$filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_ACCOUNT);
|
||||||
$filter->addFilter( new OTS_SQLField('active', 'bans'), 1);
|
$filter->addFilter( new OTS_SQLField('active', 'bans'), 1);
|
||||||
$filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'accounts') );
|
$filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'accounts') );
|
||||||
|
|
||||||
// selects only active bans
|
// selects only active bans
|
||||||
$actives = new OTS_SQLFilter();
|
$actives = new OTS_SQLFilter();
|
||||||
$actives->addFilter( new OTS_SQLField('expires', 'bans'), 0);
|
$actives->addFilter( new OTS_SQLField('expires', 'bans'), 0);
|
||||||
$actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR);
|
$actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR);
|
||||||
$filter->addFilter($actives);
|
$filter->addFilter($actives);
|
||||||
|
|
||||||
// creates list and aplies filter
|
// creates list and aplies filter
|
||||||
$list = new OTS_Accounts_List();
|
$list = new OTS_Accounts_List();
|
||||||
$list->setFilter($filter);
|
$list->setFilter($filter);
|
||||||
return $list;
|
return $list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getVocationName($id, $promotion = 0): string
|
||||||
|
{
|
||||||
|
if($promotion > 0) {
|
||||||
|
$id = ($id + ($promotion * config('vocations_amount')));
|
||||||
|
}
|
||||||
|
|
||||||
|
return config('vocations')[$id] ?? 'Unknown';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
8
system/migrations/46-account_email_codes.sql
Normal file
8
system/migrations/46-account_email_codes.sql
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
CREATE TABLE `myaac_account_email_codes`
|
||||||
|
(
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`account_id` int NOT NULL,
|
||||||
|
`code` varchar(6) NOT NULL,
|
||||||
|
`created_at` int NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
27
system/migrations/46.php
Normal file
27
system/migrations/46.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
// add the myaac_account_email_codes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var OTS_DB_MySQL $db
|
||||||
|
*/
|
||||||
|
|
||||||
|
$up = function () use ($db) {
|
||||||
|
if (!$db->hasColumn('accounts', '2fa_type')) {
|
||||||
|
$db->addColumn('accounts', '2fa_type', "tinyint NOT NULL DEFAULT 0 AFTER `web_flags`");
|
||||||
|
}
|
||||||
|
|
||||||
|
// add myaac_account_email_codes table
|
||||||
|
if (!$db->hasTable(TABLE_PREFIX . 'account_email_codes')) {
|
||||||
|
$db->exec(file_get_contents(__DIR__ . '/46-account_email_codes.sql'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$down = function () use ($db) {
|
||||||
|
if ($db->hasColumn('accounts', '2fa_type')) {
|
||||||
|
$db->dropColumn('accounts', '2fa_type');
|
||||||
|
}
|
||||||
|
|
||||||
|
//if ($db->hasTable(TABLE_PREFIX . 'account_email_codes')) {
|
||||||
|
// $db->dropTable(TABLE_PREFIX . 'account_email_codes');
|
||||||
|
//}
|
||||||
|
};
|
@@ -8,7 +8,7 @@
|
|||||||
* @link https://my-aac.org
|
* @link https://my-aac.org
|
||||||
*/
|
*/
|
||||||
defined('MYAAC') or die('Direct access not allowed!');
|
defined('MYAAC') or die('Direct access not allowed!');
|
||||||
$title = '404 Not Found';
|
$title = 'Not Found';
|
||||||
|
|
||||||
header('HTTP/1.0 404 Not Found');
|
header('HTTP/1.0 404 Not Found');
|
||||||
?>
|
?>
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
* @link https://my-aac.org
|
* @link https://my-aac.org
|
||||||
*/
|
*/
|
||||||
defined('MYAAC') or die('Direct access not allowed!');
|
defined('MYAAC') or die('Direct access not allowed!');
|
||||||
$title = '405 Method Not Allowed';
|
$title = 'Method Not Allowed';
|
||||||
|
|
||||||
header('HTTP/1.0 405 Method Not Allowed');
|
header('HTTP/1.0 405 Method Not Allowed');
|
||||||
?>
|
?>
|
||||||
|
121
system/pages/account/2fa.php
Normal file
121
system/pages/account/2fa.php
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* 2-factor authentication
|
||||||
|
*
|
||||||
|
* @package MyAAC
|
||||||
|
* @author Slawkens <slawkens@gmail.com>
|
||||||
|
* @copyright 2019 MyAAC
|
||||||
|
* @link https://my-aac.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
use MyAAC\TwoFactorAuth\TwoFactorAuth;
|
||||||
|
|
||||||
|
defined('MYAAC') or die('Direct access not allowed!');
|
||||||
|
|
||||||
|
$title = 'Two Factor Authentication';
|
||||||
|
require __DIR__ . '/base.php';
|
||||||
|
|
||||||
|
csrfProtect();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var OTS_Account $account_logged
|
||||||
|
*/
|
||||||
|
$step = $_REQUEST['step'] ?? '';
|
||||||
|
$code = $_REQUEST['email-code'] ?? '';
|
||||||
|
|
||||||
|
if ((!setting('core.mail_enabled')) && ACTION == 'email-code') {
|
||||||
|
$twig->display('error_box.html.twig', ['errors' => ['Account two-factor e-mail authentication disabled.']]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($account_logged) || !$account_logged->isLoaded()) {
|
||||||
|
$current_session = getSession('account');
|
||||||
|
if($current_session) {
|
||||||
|
$account_logged->load($current_session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$twoFactorAuth = TwoFactorAuth::getInstance($account_logged);
|
||||||
|
|
||||||
|
if (ACTION == 'email-code') {
|
||||||
|
if ($step == 'resend') {
|
||||||
|
if ($twoFactorAuth->hasRecentEmailCode(15 * 60)) {
|
||||||
|
$errors = ['Sorry, one email per 15 minutes'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$twoFactorAuth->resendEmailCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($errors)) {
|
||||||
|
$twig->display('error_box.html.twig', ['errors' => $errors]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$twig->display('account.2fa.email.login.html.twig');
|
||||||
|
}
|
||||||
|
else if ($step == 'activate') {
|
||||||
|
if (!$twoFactorAuth->hasRecentEmailCode(15 * 60)) {
|
||||||
|
$twoFactorAuth->resendEmailCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_POST['save'])) {
|
||||||
|
if (!empty($code)) {
|
||||||
|
$twoFactorAuth->setAuthGateway(TwoFactorAuth::TYPE_EMAIL);
|
||||||
|
if ($twoFactorAuth->getAuthGateway()->verifyCode($code)) {
|
||||||
|
$serverName = configLua('serverName');
|
||||||
|
|
||||||
|
$twoFactorAuth->enable(TwoFactorAuth::TYPE_EMAIL);
|
||||||
|
$twoFactorAuth->deleteOldCodes();
|
||||||
|
|
||||||
|
$twig->display('success.html.twig', [
|
||||||
|
'title' => 'Email Code Authentication Activated',
|
||||||
|
'description' => sprintf('You have successfully activated <b>email code authentication</b> for your account. This means an <b>email code</b> will be sent to the email address assigned to your account whenever you try to log in to the %s client or the %s website. In order to log in, you will need to enter the <b>most recent email code</b> you have received.', $serverName, $serverName)
|
||||||
|
]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$errors[] = 'Invalid email code!';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($errors)) {
|
||||||
|
$twig->display('error_box.html.twig', ['errors' => $errors]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$twig->display('account.2fa.email_code.html.twig', ['wrongCode' => count($errors) > 0]);
|
||||||
|
}
|
||||||
|
else if ($step == 'deactivate') {
|
||||||
|
if (!$twoFactorAuth->hasRecentEmailCode(15 * 60)) {
|
||||||
|
$twoFactorAuth->resendEmailCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_POST['save'])) {
|
||||||
|
if (!empty($code)) {
|
||||||
|
if ($twoFactorAuth->getAuthGateway()->verifyCode($code)) {
|
||||||
|
|
||||||
|
$twoFactorAuth->disable();
|
||||||
|
$twoFactorAuth->deleteOldCodes();
|
||||||
|
|
||||||
|
$twig->display('success.html.twig',
|
||||||
|
[
|
||||||
|
'title' => 'Email Code Authentication Deactivated',
|
||||||
|
'description' => 'You have successfully <b>deactivated</b> the <b>Email Code Authentication</b> for your account.'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$errors[] = 'Invalid email code!';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($errors)) {
|
||||||
|
$twig->display('error_box.html.twig', ['errors' => $errors]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$twig->display('account.2fa.email.deactivate.html.twig', ['wrongCode' => count($errors) > 0]);
|
||||||
|
}
|
||||||
|
}
|
@@ -17,6 +17,10 @@ if(!$logged)
|
|||||||
if(!empty($errors))
|
if(!empty($errors))
|
||||||
$twig->display('error_box.html.twig', array('errors' => $errors));
|
$twig->display('error_box.html.twig', array('errors' => $errors));
|
||||||
|
|
||||||
|
if (defined('HIDE_LOGIN_BOX') && HIDE_LOGIN_BOX) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$twig->display('account.login.html.twig', array(
|
$twig->display('account.login.html.twig', array(
|
||||||
'redirect' => $_REQUEST['redirect'] ?? null,
|
'redirect' => $_REQUEST['redirect'] ?? null,
|
||||||
'account' => USE_ACCOUNT_NAME ? 'Name' : 'Number',
|
'account' => USE_ACCOUNT_NAME ? 'Name' : 'Number',
|
||||||
|
@@ -166,7 +166,7 @@ if(isset($_POST['emailchangecancel']) && $_POST['emailchangecancel'] == 1) {
|
|||||||
$account_logged->setCustomField("email_new", "");
|
$account_logged->setCustomField("email_new", "");
|
||||||
$account_logged->setCustomField("email_new_time", 0);
|
$account_logged->setCustomField("email_new_time", 0);
|
||||||
|
|
||||||
$custom_buttons = '<div style="text-align:center"><table border="0" cellspacing="0" cellpadding="0" ><form action="' . getLink('account/manage') . '" method="post" ><tr><td style="border:0px;" >' . $twig->render('buttons.back.html.twig') . '</td></tr></form></table></div>';
|
$custom_buttons = '<div style="text-align:center"><table border="0" cellspacing="0" cellpadding="0" ><form action="' . getLink('account/manage') . '" method="post" >' . csrf(true) . '<tr><td style="border:0px;" >' . $twig->render('buttons.back.html.twig') . '</td></tr></form></table></div>';
|
||||||
|
|
||||||
$twig->display('success.html.twig', array(
|
$twig->display('success.html.twig', array(
|
||||||
'title' => 'Email Address Change Cancelled',
|
'title' => 'Email Address Change Cancelled',
|
||||||
|
@@ -227,10 +227,15 @@ if($save)
|
|||||||
}
|
}
|
||||||
|
|
||||||
$accountDefaultCoins = setting('core.account_coins');
|
$accountDefaultCoins = setting('core.account_coins');
|
||||||
if($db->hasColumn('accounts', 'coins') && $accountDefaultCoins > 0) {
|
if(HAS_ACCOUNT_COINS && $accountDefaultCoins > 0) {
|
||||||
$new_account->setCustomField('coins', $accountDefaultCoins);
|
$new_account->setCustomField('coins', $accountDefaultCoins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$accountDefaultCoinsTransferable = setting('core.account_coins_transferable');
|
||||||
|
if((HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) && $accountDefaultCoinsTransferable > 0) {
|
||||||
|
$new_account->setCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN, $accountDefaultCoinsTransferable);
|
||||||
|
}
|
||||||
|
|
||||||
$tmp_account = $email;
|
$tmp_account = $email;
|
||||||
if (!config('account_login_by_email')) {
|
if (!config('account_login_by_email')) {
|
||||||
$tmp_account = (USE_ACCOUNT_NAME ? $account_name : $account_id);
|
$tmp_account = (USE_ACCOUNT_NAME ? $account_name : $account_id);
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use MyAAC\RateLimit;
|
use MyAAC\RateLimit;
|
||||||
|
use MyAAC\TwoFactorAuth\TwoFactorAuth;
|
||||||
|
|
||||||
defined('MYAAC') or die('Direct access not allowed!');
|
defined('MYAAC') or die('Direct access not allowed!');
|
||||||
|
|
||||||
@@ -50,6 +51,11 @@ if(!empty($login_account) && !empty($login_password))
|
|||||||
if (setting('core.account_mail_verify') && (int)$account_logged->getCustomField('email_verified') !== 1) {
|
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.';
|
$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 {
|
||||||
|
$twoFactorAuth = TwoFactorAuth::getInstance($account_logged);
|
||||||
|
if (!$twoFactorAuth->process($login_account, $login_password, $_POST['email-code'] ?? '')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
session_regenerate_id();
|
session_regenerate_id();
|
||||||
setSession('account', $account_logged->getId());
|
setSession('account', $account_logged->getId());
|
||||||
setSession('password', encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $login_password));
|
setSession('password', encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $login_password));
|
||||||
|
@@ -8,6 +8,9 @@
|
|||||||
* @copyright 2019 MyAAC
|
* @copyright 2019 MyAAC
|
||||||
* @link https://my-aac.org
|
* @link https://my-aac.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use MyAAC\TwoFactorAuth\TwoFactorAuth;
|
||||||
|
|
||||||
defined('MYAAC') or die('Direct access not allowed!');
|
defined('MYAAC') or die('Direct access not allowed!');
|
||||||
|
|
||||||
$title = 'Account Management';
|
$title = 'Account Management';
|
||||||
@@ -111,6 +114,8 @@ $twig->display('account.management.html.twig', array(
|
|||||||
'account_registered' => $account_registered,
|
'account_registered' => $account_registered,
|
||||||
'account_rlname' => $account_rlname,
|
'account_rlname' => $account_rlname,
|
||||||
'account_location' => $account_location,
|
'account_location' => $account_location,
|
||||||
|
'twoFactorViews' => TwoFactorAuth::getInstance($account_logged)->getAccountManageViews(),
|
||||||
|
|
||||||
'actions' => $actions,
|
'actions' => $actions,
|
||||||
'players' => $account_players
|
'players' => $account_players,
|
||||||
));
|
));
|
||||||
|
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Change comment
|
|
||||||
*
|
|
||||||
* @package MyAAC
|
|
||||||
* @author Gesior <jerzyskalski@wp.pl>
|
|
||||||
* @author Slawkens <slawkens@gmail.com>
|
|
||||||
* @copyright 2019 MyAAC
|
|
||||||
* @link https://my-aac.org
|
|
||||||
*/
|
|
||||||
defined('MYAAC') or die('Direct access not allowed!');
|
|
||||||
|
|
||||||
$redirect = urldecode($_REQUEST['redirect']);
|
|
||||||
|
|
||||||
// should never happen, unless hacker modify the URL
|
|
||||||
if (!str_contains($redirect, BASE_URL)) {
|
|
||||||
error('Fatal error: Cannot redirect outside the website.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$twig->display('account.redirect.html.twig', array(
|
|
||||||
'redirect' => $redirect
|
|
||||||
));
|
|
@@ -36,10 +36,9 @@ if(count($guilds_list) > 0) {
|
|||||||
$guildName = $guild->getName();
|
$guildName = $guild->getName();
|
||||||
$guilds[] = array('name' => $guildName, 'logo' => $guild_logo, 'link' => getGuildLink($guildName, false), 'description' => $description);
|
$guilds[] = array('name' => $guildName, 'logo' => $guild_logo, 'link' => getGuildLink($guildName, false), 'description' => $description);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
$twig->display('guilds.list.html.twig', array(
|
$twig->display('guilds.list.html.twig', array(
|
||||||
'guilds' => $guilds,
|
'guilds' => $guilds,
|
||||||
'logged' => $logged ?? false,
|
|
||||||
'isAdmin' => admin(),
|
'isAdmin' => admin(),
|
||||||
));
|
));
|
||||||
|
@@ -123,16 +123,10 @@ if($db->hasColumn('players', 'promotion'))
|
|||||||
$promotion = ',players.promotion';
|
$promotion = ',players.promotion';
|
||||||
|
|
||||||
$outfit_addons = false;
|
$outfit_addons = false;
|
||||||
$outfit = '';
|
$outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype';
|
||||||
|
if($db->hasColumn('players', 'lookaddons')) {
|
||||||
$settingHighscoresOutfit = setting('core.highscores_outfit');
|
$outfit .= ', lookaddons';
|
||||||
|
$outfit_addons = true;
|
||||||
if($settingHighscoresOutfit) {
|
|
||||||
$outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype';
|
|
||||||
if($db->hasColumn('players', 'lookaddons')) {
|
|
||||||
$outfit .= ', lookaddons';
|
|
||||||
$outfit_addons = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$configHighscoresPerPage = setting('core.highscores_per_page');
|
$configHighscoresPerPage = setting('core.highscores_per_page');
|
||||||
@@ -146,17 +140,24 @@ $cache = Cache::getInstance();
|
|||||||
if ($cache->enabled() && $highscoresTTL > 0) {
|
if ($cache->enabled() && $highscoresTTL > 0) {
|
||||||
$tmp = '';
|
$tmp = '';
|
||||||
if ($cache->fetch($cacheKey, $tmp)) {
|
if ($cache->fetch($cacheKey, $tmp)) {
|
||||||
$highscores = unserialize($tmp);
|
$data = unserialize($tmp);
|
||||||
|
$totalResults = $data['totalResults'];
|
||||||
|
$highscores = $data['highscores'];
|
||||||
|
$updatedAt = $data['updatedAt'];
|
||||||
$needReCache = false;
|
$needReCache = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$offset = ($page - 1) * $configHighscoresPerPage;
|
$offset = ($page - 1) * $configHighscoresPerPage;
|
||||||
$query->join('accounts', 'accounts.id', '=', 'players.account_id')
|
$query->withOnlineStatus()
|
||||||
->withOnlineStatus()
|
|
||||||
->whereNotIn('players.id', setting('core.highscores_ids_hidden'))
|
->whereNotIn('players.id', setting('core.highscores_ids_hidden'))
|
||||||
->notDeleted()
|
->notDeleted()
|
||||||
->where('players.group_id', '<', setting('core.highscores_groups_hidden'))
|
->where('players.group_id', '<', setting('core.highscores_groups_hidden'));
|
||||||
|
|
||||||
|
$totalResultsQuery = clone $query;
|
||||||
|
|
||||||
|
$query
|
||||||
|
->join('accounts', 'accounts.id', '=', 'players.account_id')
|
||||||
->limit($limit)
|
->limit($limit)
|
||||||
->offset($offset)
|
->offset($offset)
|
||||||
->selectRaw('accounts.country, players.id, players.name, players.account_id, players.level, players.vocation' . $outfit . $promotion)
|
->selectRaw('accounts.country, players.id, players.name, players.account_id, players.level, players.vocation' . $outfit . $promotion)
|
||||||
@@ -215,17 +216,24 @@ if (empty($highscores)) {
|
|||||||
|
|
||||||
return $tmp;
|
return $tmp;
|
||||||
})->toArray();
|
})->toArray();
|
||||||
|
|
||||||
|
$updatedAt = time();
|
||||||
|
$totalResults = $totalResultsQuery->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($highscoresTTL > 0 && $cache->enabled() && $needReCache) {
|
if ($highscoresTTL > 0 && $cache->enabled() && $needReCache) {
|
||||||
$cache->set($cacheKey, serialize($highscores), $highscoresTTL * 60);
|
$cache->set($cacheKey, serialize(
|
||||||
|
[
|
||||||
|
'totalResults' => $totalResults,
|
||||||
|
'highscores' => $highscores,
|
||||||
|
'updatedAt' => $updatedAt,
|
||||||
|
]
|
||||||
|
), $highscoresTTL * 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
$show_link_to_next_page = false;
|
$show_link_to_next_page = false;
|
||||||
$i = 0;
|
$i = 0;
|
||||||
|
|
||||||
$settingHighscoresVocation = setting('core.highscores_vocation');
|
|
||||||
|
|
||||||
foreach($highscores as $id => &$player)
|
foreach($highscores as $id => &$player)
|
||||||
{
|
{
|
||||||
if(++$i <= $configHighscoresPerPage)
|
if(++$i <= $configHighscoresPerPage)
|
||||||
@@ -239,10 +247,22 @@ foreach($highscores as $id => &$player)
|
|||||||
|
|
||||||
$player['link'] = getPlayerLink($player['name'], false);
|
$player['link'] = getPlayerLink($player['name'], false);
|
||||||
$player['flag'] = getFlagImage($player['country']);
|
$player['flag'] = getFlagImage($player['country']);
|
||||||
if($settingHighscoresOutfit) {
|
$player['outfit'] = '<img style="position:absolute;margin-top:' . (in_array($player['looktype'], setting('core.outfit_images_wrong_looktypes')) ? '-15px;margin-left:5px' : '-45px;margin-left:-25px') . ';" src="' . $player['outfit_url'] . '" alt="" />';
|
||||||
$player['outfit'] = '<img style="position:absolute;margin-top:' . (in_array($player['looktype'], setting('core.outfit_images_wrong_looktypes')) ? '-15px;margin-left:5px' : '-45px;margin-left:-25px') . ';" src="' . $player['outfit_url'] . '" alt="" />';
|
|
||||||
|
if ($skill != POT::SKILL__LEVEL) {
|
||||||
|
if (isset($lastValue) && $lastValue == $player['value']) {
|
||||||
|
$player['rank'] = $lastRank;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$player['rank'] = $offset + $i;
|
||||||
|
}
|
||||||
|
|
||||||
|
$lastRank = $player['rank'] ;
|
||||||
|
$lastValue = $player['value'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$player['rank'] = $offset + $i;
|
||||||
}
|
}
|
||||||
$player['rank'] = $offset + $i;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
unset($highscores[$id]);
|
unset($highscores[$id]);
|
||||||
@@ -263,6 +283,8 @@ if($show_link_to_next_page) {
|
|||||||
$linkNextPage = getLink('highscores') . '/' . $list . ($vocation !== 'all' ? '/' . $vocation : '') . '/' . ($page + 1);
|
$linkNextPage = getLink('highscores') . '/' . $list . ($vocation !== 'all' ? '/' . $vocation : '') . '/' . ($page + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$baseLink = getLink('highscores') . '/' . $list . ($vocation !== 'all' ? '/' . $vocation : '') . '/';
|
||||||
|
|
||||||
$types = array(
|
$types = array(
|
||||||
'experience' => 'Experience',
|
'experience' => 'Experience',
|
||||||
'magic' => 'Magic',
|
'magic' => 'Magic',
|
||||||
@@ -297,4 +319,8 @@ $twig->display('highscores.html.twig', [
|
|||||||
'types' => $types,
|
'types' => $types,
|
||||||
'linkPreviousPage' => $linkPreviousPage,
|
'linkPreviousPage' => $linkPreviousPage,
|
||||||
'linkNextPage' => $linkNextPage,
|
'linkNextPage' => $linkNextPage,
|
||||||
|
'totalResults' => $totalResults,
|
||||||
|
'page' => $page,
|
||||||
|
'baseLink' => $baseLink,
|
||||||
|
'updatedAt' => $updatedAt,
|
||||||
]);
|
]);
|
||||||
|
@@ -9,123 +9,140 @@
|
|||||||
* @link https://my-aac.org
|
* @link https://my-aac.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use MyAAC\Cache\Cache;
|
||||||
use MyAAC\Models\ServerConfig;
|
use MyAAC\Models\ServerConfig;
|
||||||
use MyAAC\Models\ServerRecord;
|
use MyAAC\Models\ServerRecord;
|
||||||
|
|
||||||
defined('MYAAC') or die('Direct access not allowed!');
|
defined('MYAAC') or die('Direct access not allowed!');
|
||||||
$title = 'Who is online?';
|
$title = 'Who is online?';
|
||||||
|
|
||||||
if (setting('core.account_country'))
|
if (setting('core.account_country')) {
|
||||||
require SYSTEM . 'countries.conf.php';
|
require SYSTEM . 'countries.conf.php';
|
||||||
|
}
|
||||||
|
|
||||||
$promotion = '';
|
$promotion = '';
|
||||||
if($db->hasColumn('players', 'promotion'))
|
if($db->hasColumn('players', 'promotion')) {
|
||||||
$promotion = '`promotion`,';
|
$promotion = '`promotion`,';
|
||||||
|
|
||||||
$order = $_GET['order'] ?? 'name';
|
|
||||||
if(!in_array($order, array('country', 'name', 'level', 'vocation')))
|
|
||||||
$order = $db->fieldName('name');
|
|
||||||
else if($order == 'country')
|
|
||||||
$order = $db->tableName('accounts') . '.' . $db->fieldName('country');
|
|
||||||
else if($order == 'vocation')
|
|
||||||
$order = $promotion . 'vocation ASC';
|
|
||||||
|
|
||||||
$skull_type = 'skull';
|
|
||||||
if($db->hasColumn('players', 'skull_type')) {
|
|
||||||
$skull_type = 'skull_type';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$skull_time = 'skulltime';
|
$order = $_GET['order'] ?? 'name_asc';
|
||||||
if($db->hasColumn('players', 'skull_time')) {
|
if(!in_array($order, ['country_asc', 'country_desc', 'name_asc', 'name_desc', 'level_asc', 'level_desc', 'vocation_asc', 'vocation_desc'])) {
|
||||||
$skull_time = 'skull_time';
|
$order = 'name_asc';
|
||||||
|
}
|
||||||
|
else if($order == 'vocation_asc' || $order == 'vocation_desc') {
|
||||||
|
$order = $promotion . 'vocation_' . (str_contains($order, 'asc') ? 'asc' : 'desc');
|
||||||
}
|
}
|
||||||
|
|
||||||
$outfit_addons = false;
|
$cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60, function() use($db, $promotion, $order) {
|
||||||
$outfit = '';
|
$orderExplode = explode('_', $order);
|
||||||
if (setting('core.online_outfit')) {
|
$orderSql = $orderExplode[0] . ' ' . $orderExplode[1];
|
||||||
|
|
||||||
|
$skull_type = 'skull';
|
||||||
|
if($db->hasColumn('players', 'skull_type')) {
|
||||||
|
$skull_type = 'skull_type';
|
||||||
|
}
|
||||||
|
|
||||||
|
$skull_time = 'skulltime';
|
||||||
|
if($db->hasColumn('players', 'skull_time')) {
|
||||||
|
$skull_time = 'skull_time';
|
||||||
|
}
|
||||||
|
|
||||||
|
$outfit_addons = false;
|
||||||
$outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype';
|
$outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype';
|
||||||
if($db->hasColumn('players', 'lookaddons')) {
|
if($db->hasColumn('players', 'lookaddons')) {
|
||||||
$outfit .= ', lookaddons';
|
$outfit .= ', lookaddons';
|
||||||
$outfit_addons = true;
|
$outfit_addons = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$vocs = [];
|
$vocations = array_map(function ($name) {
|
||||||
if (setting('core.online_vocations')) {
|
return 0;
|
||||||
foreach($config['vocations'] as $id => $name) {
|
}, setting('core.vocations'));
|
||||||
$vocs[$id] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($db->hasTable('players_online')) // tfs 1.0
|
if($db->hasTable('players_online')) // tfs 1.0
|
||||||
$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $order);
|
$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql);
|
||||||
else
|
else
|
||||||
$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $order);
|
$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql);
|
||||||
|
|
||||||
$players_data = array();
|
$settingVocations = setting('core.vocations');
|
||||||
$players = 0;
|
$settingVocationsAmount = setting('core.vocations_amount');
|
||||||
$data = '';
|
|
||||||
foreach($playersOnline as $player) {
|
$players = [];
|
||||||
$skull = '';
|
foreach($playersOnline as $player) {
|
||||||
if (setting('core.online_skulls'))
|
$skull = '';
|
||||||
{
|
if($player['skulltime'] > 0) {
|
||||||
if($player['skulltime'] > 0)
|
if($player['skull'] == 3) {
|
||||||
{
|
|
||||||
if($player['skull'] == 3)
|
|
||||||
$skull = ' <img style="border: 0;" src="images/white_skull.gif"/>';
|
$skull = ' <img style="border: 0;" src="images/white_skull.gif"/>';
|
||||||
elseif($player['skull'] == 4)
|
}
|
||||||
|
elseif($player['skull'] == 4) {
|
||||||
$skull = ' <img style="border: 0;" src="images/red_skull.gif"/>';
|
$skull = ' <img style="border: 0;" src="images/red_skull.gif"/>';
|
||||||
elseif($player['skull'] == 5)
|
}
|
||||||
|
elseif($player['skull'] == 5) {
|
||||||
$skull = ' <img style="border: 0;" src="images/black_skull.gif"/>';
|
$skull = ' <img style="border: 0;" src="images/black_skull.gif"/>';
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($player['promotion'])) {
|
|
||||||
if((int)$player['promotion'] > 0)
|
|
||||||
$player['vocation'] += ($player['promotion'] * $config['vocations_amount']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$players_data[] = array(
|
|
||||||
'name' => getPlayerLink($player['name']),
|
|
||||||
'player' => $player,
|
|
||||||
'level' => $player['level'],
|
|
||||||
'vocation' => $config['vocations'][$player['vocation']],
|
|
||||||
'country_image' => setting('core.account_country') ? getFlagImage($player['country']) : null,
|
|
||||||
'outfit' => setting('core.online_outfit') ? setting('core.outfit_images_url') . '?id=' . $player['looktype'] . ($outfit_addons ? '&addons=' . $player['lookaddons'] : '') . '&head=' . $player['lookhead'] . '&body=' . $player['lookbody'] . '&legs=' . $player['looklegs'] . '&feet=' . $player['lookfeet'] : null
|
|
||||||
);
|
|
||||||
|
|
||||||
if (setting('core.online_vocations')) {
|
|
||||||
$vocs[($player['vocation'] > $config['vocations_amount'] ? $player['vocation'] - $config['vocations_amount'] : $player['vocation'])]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$record = '';
|
|
||||||
if(count($players_data) > 0) {
|
|
||||||
if( setting('core.online_record')) {
|
|
||||||
$result = null;
|
|
||||||
$timestamp = false;
|
|
||||||
if($db->hasTable('server_record')) {
|
|
||||||
$timestamp = true;
|
|
||||||
$result = ServerRecord::where('world_id', $config['lua']['worldId'])->orderByDesc('record')->first()->toArray();
|
|
||||||
} else if($db->hasTable('server_config')) { // tfs 1.0
|
|
||||||
$row = ServerConfig::where('config', 'players_record')->first();
|
|
||||||
if ($row) {
|
|
||||||
$result = ['record' => $row->value];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($result) {
|
if(isset($player['promotion'])) {
|
||||||
$record = 'The maximum on this game world was ' . $result['record'] . ' players' . ($timestamp ? ' on ' . date("M d Y, H:i:s", $result['timestamp']) . '.' : '.');
|
if((int)$player['promotion'] > 0)
|
||||||
|
$player['vocation'] += ($player['promotion'] * $settingVocationsAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
$players[] = array(
|
||||||
|
'name' => getPlayerLink($player['name']),
|
||||||
|
'player' => $player,
|
||||||
|
'level' => $player['level'],
|
||||||
|
'vocation' => $settingVocations[$player['vocation']],
|
||||||
|
'skull' => $skull,
|
||||||
|
'country_image' => getFlagImage($player['country']),
|
||||||
|
'outfit' => setting('core.outfit_images_url') . '?id=' . $player['looktype'] . ($outfit_addons ? '&addons=' . $player['lookaddons'] : '') . '&head=' . $player['lookhead'] . '&body=' . $player['lookbody'] . '&legs=' . $player['looklegs'] . '&feet=' . $player['lookfeet'],
|
||||||
|
);
|
||||||
|
|
||||||
|
$vocations[($player['vocation'] > $settingVocationsAmount ? $player['vocation'] - $settingVocationsAmount : $player['vocation'])]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$record = '';
|
||||||
|
if(count($players) > 0) {
|
||||||
|
if( setting('core.online_record')) {
|
||||||
|
$result = null;
|
||||||
|
$timestamp = false;
|
||||||
|
if($db->hasTable('server_record')) {
|
||||||
|
$timestamp = $db->hasColumn('server_record', 'timestamp');
|
||||||
|
$serverRecordQuery = ServerRecord::query();
|
||||||
|
|
||||||
|
if ($db->hasColumn('server_record', 'world_id')) {
|
||||||
|
$serverRecordQuery->where('world_id', configLua('worldId'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $serverRecordQuery->orderByDesc('record')->first();
|
||||||
|
if ($result) {
|
||||||
|
$result = $result->toArray();
|
||||||
|
}
|
||||||
|
} else if($db->hasTable('server_config')) { // tfs 1.0
|
||||||
|
$row = ServerConfig::where('config', 'players_record')->first();
|
||||||
|
if ($row) {
|
||||||
|
$result = ['record' => $row->value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($result) {
|
||||||
|
$record = $result['record'] . ' player' . ($result['record'] > 1 ? 's' : '') . ($timestamp ? ' (on ' . date("M d Y, H:i:s", $result['timestamp']) . ')' : '');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return [
|
||||||
|
'players' => $players,
|
||||||
|
'record' => $record,
|
||||||
|
'vocations' => $vocations,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
$twig->display('online.html.twig', array(
|
$twig->display('online.html.twig', array(
|
||||||
'players' => $players_data,
|
'players' => $cached['players'],
|
||||||
'record' => $record,
|
'record' => $cached['record'],
|
||||||
'vocs' => $vocs,
|
'vocations' => $cached['vocations'],
|
||||||
|
'vocs' => $cached['vocations'], // deprecated, to be removed
|
||||||
|
'order' => $order,
|
||||||
));
|
));
|
||||||
|
|
||||||
//search bar
|
// search bar
|
||||||
$twig->display('online.form.html.twig');
|
$twig->display('characters.form.html.twig');
|
||||||
?>
|
|
||||||
|
@@ -174,7 +174,12 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r)
|
|||||||
// apply aliases
|
// apply aliases
|
||||||
$route[1] = str_replace($aliases[0], $aliases[1], $route[1]);
|
$route[1] = str_replace($aliases[0], $aliases[1], $route[1]);
|
||||||
|
|
||||||
$r->addRoute($route[0], $route[1], $route[2]);
|
try {
|
||||||
|
$r->addRoute($route[0], $route[1], $route[2]);
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// duplicated route, just ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config('env') === 'dev') {
|
if (config('env') === 'dev') {
|
||||||
@@ -321,7 +326,9 @@ if (isset($_REQUEST['_page_only'])) {
|
|||||||
|
|
||||||
if(!isset($title)) {
|
if(!isset($title)) {
|
||||||
$title = str_replace('index.php/', '', $page);
|
$title = str_replace('index.php/', '', $page);
|
||||||
$title = ucfirst($title);
|
$title = str_replace(['_', '-', '/'], ' ', $page);
|
||||||
|
|
||||||
|
$title = ucwords($title);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(setting('core.backward_support')) {
|
if(setting('core.backward_support')) {
|
||||||
|
@@ -22,11 +22,11 @@ return [
|
|||||||
['GET', 'account/confirm-email/{hash:alphanum}', 'account/confirm-email.php'],
|
['GET', 'account/confirm-email/{hash:alphanum}', 'account/confirm-email.php'],
|
||||||
|
|
||||||
['GET', 'bans/{page:int}', 'bans.php'],
|
['GET', 'bans/{page:int}', 'bans.php'],
|
||||||
[['GET', 'POST'], 'characters[/{name:[A-Za-z0-9-_%+\' \[\]]+}]', 'characters.php'],
|
[['GET', 'POST'], 'characters/{name:[A-Za-z0-9-_%+\' \[\]]+}', 'characters.php'],
|
||||||
['GET', 'changelog[/{page:int}]', 'changelog.php'],
|
['GET', 'changelog/{page:int}', 'changelog.php'],
|
||||||
[['GET', 'POST'], 'monsters[/{name:string}]', 'monsters.php'],
|
[['GET', 'POST'], 'monsters/{name:string}', 'monsters.php'],
|
||||||
|
|
||||||
[['GET', 'POST'], 'faq[/{action:string}]', 'faq.php'],
|
[['GET', 'POST'], 'faq/{action:string}', 'faq.php'],
|
||||||
|
|
||||||
[['GET', 'POST'], 'forum/{action:string}', 'forum.php'],
|
[['GET', 'POST'], 'forum/{action:string}', 'forum.php'],
|
||||||
['GET', 'forum/board/{id:int}', 'forum/show_board.php'],
|
['GET', 'forum/board/{id:int}', 'forum/show_board.php'],
|
||||||
|
@@ -694,7 +694,14 @@ Sent by MyAAC,<br/>
|
|||||||
'name' => 'Default Account Coins',
|
'name' => 'Default Account Coins',
|
||||||
'type' => 'number',
|
'type' => 'number',
|
||||||
'desc' => 'Default coins on new account',
|
'desc' => 'Default coins on new account',
|
||||||
'hidden' => ($db && !$db->hasColumn('accounts', 'coins')),
|
'hidden' => ($db && !HAS_ACCOUNT_COINS),
|
||||||
|
'default' => 0,
|
||||||
|
],
|
||||||
|
'account_coins_transferable' => [
|
||||||
|
'name' => 'Default Account Transferable Coins',
|
||||||
|
'type' => 'number',
|
||||||
|
'desc' => 'Default transferable coins on new account',
|
||||||
|
'hidden' => ($db && !HAS_ACCOUNT_COINS_TRANSFERABLE && !HAS_ACCOUNT_TRANSFERABLE_COINS),
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
],
|
],
|
||||||
'account_mail_change' => [
|
'account_mail_change' => [
|
||||||
@@ -1062,6 +1069,12 @@ Sent by MyAAC,<br/>
|
|||||||
'desc' => 'How often to update highscores from database in minutes. Too low may slow down your website.<br/>0 to disable.',
|
'desc' => 'How often to update highscores from database in minutes. Too low may slow down your website.<br/>0 to disable.',
|
||||||
'default' => 15,
|
'default' => 15,
|
||||||
],
|
],
|
||||||
|
'highscores_skills_box' => [
|
||||||
|
'name' => 'Display Skills Box',
|
||||||
|
'type' => 'boolean',
|
||||||
|
'desc' => 'show "Choose a skill" box on the highscores (allowing peoples to sort highscores by skill)?',
|
||||||
|
'default' => true,
|
||||||
|
],
|
||||||
'highscores_vocation_box' => [
|
'highscores_vocation_box' => [
|
||||||
'name' => 'Display Vocation Box',
|
'name' => 'Display Vocation Box',
|
||||||
'type' => 'boolean',
|
'type' => 'boolean',
|
||||||
@@ -1074,6 +1087,12 @@ Sent by MyAAC,<br/>
|
|||||||
'desc' => 'Show player vocation under his nickname?',
|
'desc' => 'Show player vocation under his nickname?',
|
||||||
'default' => true,
|
'default' => true,
|
||||||
],
|
],
|
||||||
|
'highscores_online_status' => [
|
||||||
|
'name' => 'Display Online Status',
|
||||||
|
'type' => 'boolean',
|
||||||
|
'desc' => 'Show player status as red (offline) or green (online)',
|
||||||
|
'default' => false,
|
||||||
|
],
|
||||||
'highscores_frags' => [
|
'highscores_frags' => [
|
||||||
'name' => 'Display Top Frags',
|
'name' => 'Display Top Frags',
|
||||||
'type' => 'boolean',
|
'type' => 'boolean',
|
||||||
@@ -1228,6 +1247,14 @@ Sent by MyAAC,<br/>
|
|||||||
'type' => 'section',
|
'type' => 'section',
|
||||||
'title' => 'Online Page'
|
'title' => 'Online Page'
|
||||||
],
|
],
|
||||||
|
'online_cache_ttl' => [
|
||||||
|
'name' => 'Online Cache TTL (in minutes)',
|
||||||
|
'type' => 'number',
|
||||||
|
'min' => 0,
|
||||||
|
'desc' => 'How often to update online list from database in minutes. Too low may slow down your website.' . PHP_EOL .
|
||||||
|
'0 to disable.',
|
||||||
|
'default' => 15,
|
||||||
|
],
|
||||||
'online_record' => [
|
'online_record' => [
|
||||||
'name' => 'Display Players Record',
|
'name' => 'Display Players Record',
|
||||||
'type' => 'boolean',
|
'type' => 'boolean',
|
||||||
@@ -1264,6 +1291,12 @@ Sent by MyAAC,<br/>
|
|||||||
'desc' => '',
|
'desc' => '',
|
||||||
'default' => false,
|
'default' => false,
|
||||||
],
|
],
|
||||||
|
'online_datacenter' => [
|
||||||
|
'name' => 'Data Center',
|
||||||
|
'type' => 'text',
|
||||||
|
'desc' => 'Server Location, will be shown on online page',
|
||||||
|
'default' => 'Frankfurt - Germany',
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'type' => 'section',
|
'type' => 'section',
|
||||||
'title' => 'Team Page'
|
'title' => 'Team Page'
|
||||||
@@ -1570,7 +1603,7 @@ Sent by MyAAC,<br/>
|
|||||||
'callbacks' => [
|
'callbacks' => [
|
||||||
'beforeSave' => function($key, $value, &$errorMessage) {
|
'beforeSave' => function($key, $value, &$errorMessage) {
|
||||||
global $db;
|
global $db;
|
||||||
if ($value == 'coins' && !$db->hasColumn('accounts', 'coins')) {
|
if ($value == 'coins' && !HAS_ACCOUNT_COINS) {
|
||||||
$errorMessage = "Shop: Donate Column: Cannot set column to coins, because it doesn't exist in database.";
|
$errorMessage = "Shop: Donate Column: Cannot set column to coins, because it doesn't exist in database.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
49
system/src/Admin/Plugins.php
Normal file
49
system/src/Admin/Plugins.php
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MyAAC\Admin;
|
||||||
|
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
|
||||||
|
class Plugins
|
||||||
|
{
|
||||||
|
private string $api_base_uri = 'https://plugins.my-aac.org/api/';
|
||||||
|
|
||||||
|
public function getLatestVersions(): array
|
||||||
|
{
|
||||||
|
$client = new Client([
|
||||||
|
// Base URI is used with relative requests
|
||||||
|
'base_uri' => $this->api_base_uri,
|
||||||
|
// You can set any number of default request options.
|
||||||
|
'timeout' => 3.0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$plugins = get_plugins(true);
|
||||||
|
foreach ($plugins as &$plugin) {
|
||||||
|
if (str_contains($plugin, 'disabled.')) {
|
||||||
|
$plugin = str_replace('disabled.', '', $plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $client->get('get-latest-versions', [
|
||||||
|
'json' => ['plugins' => $plugins],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
error('API Error. Please try again later.');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$statusCode = $response->getStatusCode();
|
||||||
|
if ($statusCode != 200) {
|
||||||
|
throw new \Exception('Error getting info from plugins repository. Please try again later.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $response->getBody();
|
||||||
|
return json_decode($data, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setApiBaseUri(string $uri): void {
|
||||||
|
$this->api_base_uri = $uri;
|
||||||
|
}
|
||||||
|
}
|
@@ -106,7 +106,7 @@ class Cache
|
|||||||
public static function remember($key, $ttl, $callback)
|
public static function remember($key, $ttl, $callback)
|
||||||
{
|
{
|
||||||
$cache = self::getInstance();
|
$cache = self::getInstance();
|
||||||
if (!$cache->enabled()) {
|
if (!$cache->enabled() || $ttl == 0) {
|
||||||
return $callback();
|
return $callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace MyAAC\Commands;
|
namespace MyAAC\Commands;
|
||||||
|
|
||||||
|
use MyAAC\Cache\Cache;
|
||||||
use MyAAC\Hooks;
|
use MyAAC\Hooks;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
@@ -17,10 +18,7 @@ class CacheClearCommand extends Command
|
|||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
global $hooks;
|
require SYSTEM . 'init.php';
|
||||||
$hooks = new Hooks();
|
|
||||||
$hooks->load();
|
|
||||||
$hooks->trigger(HOOK_INIT);
|
|
||||||
|
|
||||||
$io = new SymfonyStyle($input, $output);
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
@@ -29,6 +27,13 @@ class CacheClearCommand extends Command
|
|||||||
return Command::FAILURE;
|
return Command::FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$cacheEngine = config('cache_engine') == 'auto' ?
|
||||||
|
Cache::detect() : config('cache_engine');
|
||||||
|
|
||||||
|
if (config('env') !== 'dev' && $cacheEngine == 'apcu') {
|
||||||
|
$io->warning('APCu cache cannot be cleared in CLI. Please visit the Admin Panel and clear there.');
|
||||||
|
}
|
||||||
|
|
||||||
$io->success('Cache cleared');
|
$io->success('Cache cleared');
|
||||||
return Command::SUCCESS;
|
return Command::SUCCESS;
|
||||||
}
|
}
|
||||||
|
@@ -12,9 +12,10 @@ class MailSendCommand extends Command
|
|||||||
{
|
{
|
||||||
protected function configure(): void
|
protected function configure(): void
|
||||||
{
|
{
|
||||||
$this->setName('mail:send')
|
$this->setName('email:send')
|
||||||
|
->setAliases(['mail:send'])
|
||||||
->setDescription('This command sends E-Mail to single user. Message can be provided as follows: ' . PHP_EOL
|
->setDescription('This command sends E-Mail to single user. Message can be provided as follows: ' . PHP_EOL
|
||||||
. ' echo "Hello World" | php sa email:send --subject="This is the subject" test@test.com')
|
. ' echo "Hello World" | php aac email:send --subject="This is the subject" test@test.com')
|
||||||
->addArgument('recipient', InputArgument::REQUIRED, 'Email, Account Name, Account id or Player Name')
|
->addArgument('recipient', InputArgument::REQUIRED, 'Email, Account Name, Account id or Player Name')
|
||||||
->addOption('subject', 's', InputOption::VALUE_REQUIRED, 'Subject');
|
->addOption('subject', 's', InputOption::VALUE_REQUIRED, 'Subject');
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,8 @@ class PluginInstallInstallCommand extends Command
|
|||||||
{
|
{
|
||||||
protected function configure(): void
|
protected function configure(): void
|
||||||
{
|
{
|
||||||
$this->setName('plugin:install:install')
|
$this->setName('plugin:setup')
|
||||||
|
->setAliases(['plugin:install:install'])
|
||||||
->setDescription('This command executes the "install" part of the plugin')
|
->setDescription('This command executes the "install" part of the plugin')
|
||||||
->addArgument('plugin', InputArgument::REQUIRED, 'Plugin name');
|
->addArgument('plugin', InputArgument::REQUIRED, 'Plugin name');
|
||||||
}
|
}
|
||||||
|
@@ -53,12 +53,9 @@ class Account extends Model {
|
|||||||
|
|
||||||
public function getIsPremiumAttribute()
|
public function getIsPremiumAttribute()
|
||||||
{
|
{
|
||||||
global $config;
|
if(isset($this->premium_ends_at)) {
|
||||||
if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return true;
|
return $this->premium_ends_at > time();
|
||||||
|
}
|
||||||
if(isset($this->premium_ends_at)) {
|
|
||||||
return $this->premium_ends_at > time();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($this->premend)) {
|
if(isset($this->premend)) {
|
||||||
return $this->premend > time();
|
return $this->premend > time();
|
||||||
|
14
system/src/Models/AccountEMailCode.php
Normal file
14
system/src/Models/AccountEMailCode.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MyAAC\Models;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class AccountEMailCode extends Model {
|
||||||
|
|
||||||
|
protected $table = TABLE_PREFIX . 'account_email_codes';
|
||||||
|
|
||||||
|
public $timestamps = false;
|
||||||
|
|
||||||
|
protected $fillable = ['account_id', 'code', 'created_at'];
|
||||||
|
|
||||||
|
}
|
@@ -9,6 +9,10 @@ class PlayerOnline extends Model {
|
|||||||
|
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'player_id',
|
||||||
|
];
|
||||||
|
|
||||||
public function player()
|
public function player()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Player::class);
|
return $this->belongsTo(Player::class);
|
||||||
|
@@ -532,193 +532,192 @@ class Plugins {
|
|||||||
self::$plugin_json = $plugin_json;
|
self::$plugin_json = $plugin_json;
|
||||||
if ($plugin_json == null) {
|
if ($plugin_json == null) {
|
||||||
self::$warnings[] = 'Cannot load ' . $file_name . '. File might be not a valid json code.';
|
self::$warnings[] = 'Cannot load ' . $file_name . '. File might be not a valid json code.';
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
$continue = true;
|
|
||||||
|
|
||||||
if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) {
|
$continue = true;
|
||||||
self::$error = 'Plugin "name" tag is not set.';
|
|
||||||
|
if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) {
|
||||||
|
self::$error = 'Plugin "name" tag is not set.';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isset($plugin_json['version']) || empty(trim($plugin_json['version']))) {
|
||||||
|
self::$warnings[] = 'Plugin "version" tag is not set.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($plugin_json['require'])) {
|
||||||
|
$require = $plugin_json['require'];
|
||||||
|
|
||||||
|
$myaac_satified = true;
|
||||||
|
if(isset($require['myaac_'])) {
|
||||||
|
$require_myaac = $require['myaac_'];
|
||||||
|
if(!Semver::satisfies(MYAAC_VERSION, $require_myaac)) {
|
||||||
|
$myaac_satified = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(isset($require['myaac'])) {
|
||||||
|
$require_myaac = $require['myaac'];
|
||||||
|
if(version_compare(MYAAC_VERSION, $require_myaac, '<')) {
|
||||||
|
$myaac_satified = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$myaac_satified) {
|
||||||
|
self::$error = "Your AAC version doesn't meet the requirement of this plugin. Required version is: " . $require_myaac . ", and you're using version " . MYAAC_VERSION . ".";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isset($plugin_json['version']) || empty(trim($plugin_json['version']))) {
|
$php_satisfied = true;
|
||||||
self::$warnings[] = 'Plugin "version" tag is not set.';
|
if(isset($require['php_'])) {
|
||||||
|
$require_php = $require['php_'];
|
||||||
|
if(!Semver::satisfies(phpversion(), $require_php)) {
|
||||||
|
$php_satisfied = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(isset($require['php'])) {
|
||||||
|
$require_php = $require['php'];
|
||||||
|
if(version_compare(phpversion(), $require_php, '<')) {
|
||||||
|
$php_satisfied = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isset($plugin_json['require'])) {
|
if(!$php_satisfied) {
|
||||||
$require = $plugin_json['require'];
|
self::$error = "Your PHP version doesn't meet the requirement of this plugin. Required version is: " . $require_php . ", and you're using version " . phpversion() . ".";
|
||||||
|
$continue = false;
|
||||||
|
}
|
||||||
|
|
||||||
$myaac_satified = true;
|
$database_satisfied = true;
|
||||||
if(isset($require['myaac_'])) {
|
if(isset($require['database_'])) {
|
||||||
$require_myaac = $require['myaac_'];
|
$require_database = $require['database_'];
|
||||||
if(!Semver::satisfies(MYAAC_VERSION, $require_myaac)) {
|
if(!Semver::satisfies(DATABASE_VERSION, $require_database)) {
|
||||||
$myaac_satified = false;
|
$database_satisfied = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(isset($require['database'])) {
|
||||||
|
$require_database = $require['database'];
|
||||||
|
if(version_compare(DATABASE_VERSION, $require_database, '<')) {
|
||||||
|
$database_satisfied = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$database_satisfied) {
|
||||||
|
self::$error = "Your database version doesn't meet the requirement of this plugin. Required version is: " . $require_database . ", and you're using version " . DATABASE_VERSION . ".";
|
||||||
|
$continue = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($continue) {
|
||||||
|
foreach($require as $req => $version) {
|
||||||
|
$req = strtolower(trim($req));
|
||||||
|
$version = trim($version);
|
||||||
|
|
||||||
|
if(in_array($req, array('myaac', 'myaac_', 'php', 'php_', 'database', 'database_'))) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if(isset($require['myaac'])) {
|
|
||||||
$require_myaac = $require['myaac'];
|
|
||||||
if(version_compare(MYAAC_VERSION, $require_myaac, '<')) {
|
|
||||||
$myaac_satified = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$myaac_satified) {
|
if(in_array($req, array('php-ext', 'php-extension'))) { // require php extension
|
||||||
self::$error = "Your AAC version doesn't meet the requirement of this plugin. Required version is: " . $require_myaac . ", and you're using version " . MYAAC_VERSION . ".";
|
$tmpDisplayError = false;
|
||||||
return false;
|
$explode = explode(',', $version);
|
||||||
}
|
|
||||||
|
|
||||||
$php_satisfied = true;
|
foreach ($explode as $item) {
|
||||||
if(isset($require['php_'])) {
|
if(!extension_loaded($item)) {
|
||||||
$require_php = $require['php_'];
|
$errors[] = "This plugin requires php extension: " . $item . " to be installed.";
|
||||||
if(!Semver::satisfies(phpversion(), $require_php)) {
|
$tmpDisplayError = true;
|
||||||
$php_satisfied = false;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(isset($require['php'])) {
|
|
||||||
$require_php = $require['php'];
|
|
||||||
if(version_compare(phpversion(), $require_php, '<')) {
|
|
||||||
$php_satisfied = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$php_satisfied) {
|
|
||||||
self::$error = "Your PHP version doesn't meet the requirement of this plugin. Required version is: " . $require_php . ", and you're using version " . phpversion() . ".";
|
|
||||||
$continue = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$database_satisfied = true;
|
|
||||||
if(isset($require['database_'])) {
|
|
||||||
$require_database = $require['database_'];
|
|
||||||
if(!Semver::satisfies(DATABASE_VERSION, $require_database)) {
|
|
||||||
$database_satisfied = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(isset($require['database'])) {
|
|
||||||
$require_database = $require['database'];
|
|
||||||
if(version_compare(DATABASE_VERSION, $require_database, '<')) {
|
|
||||||
$database_satisfied = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$database_satisfied) {
|
|
||||||
self::$error = "Your database version doesn't meet the requirement of this plugin. Required version is: " . $require_database . ", and you're using version " . DATABASE_VERSION . ".";
|
|
||||||
$continue = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($continue) {
|
|
||||||
foreach($require as $req => $version) {
|
|
||||||
$req = strtolower(trim($req));
|
|
||||||
$version = trim($version);
|
|
||||||
|
|
||||||
if(in_array($req, array('myaac', 'myaac_', 'php', 'php_', 'database', 'database_'))) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(in_array($req, array('php-ext', 'php-extension'))) { // require php extension
|
if ($tmpDisplayError) {
|
||||||
$tmpDisplayError = false;
|
self::$error = implode('<br/>', $errors);
|
||||||
$explode = explode(',', $version);
|
|
||||||
|
|
||||||
foreach ($explode as $item) {
|
|
||||||
if(!extension_loaded($item)) {
|
|
||||||
$errors[] = "This plugin requires php extension: " . $item . " to be installed.";
|
|
||||||
$tmpDisplayError = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($tmpDisplayError) {
|
|
||||||
self::$error = implode('<br/>', $errors);
|
|
||||||
$continue = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if($req == 'table') {
|
|
||||||
$tmpDisplayError = false;
|
|
||||||
$explode = explode(',', $version);
|
|
||||||
foreach ($explode as $item) {
|
|
||||||
if(!$db->hasTable($item)) {
|
|
||||||
$errors[] = "This plugin requires table: " . $item . " to exist in the database.";
|
|
||||||
$tmpDisplayError = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($tmpDisplayError) {
|
|
||||||
self::$error = implode('<br/>', $errors);
|
|
||||||
$continue = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if($req == 'column') {
|
|
||||||
$tmpDisplayError = false;
|
|
||||||
$explode = explode(',', $version);
|
|
||||||
foreach ($explode as $item) {
|
|
||||||
$tmp = explode('.', $item);
|
|
||||||
|
|
||||||
if(count($tmp) == 2) {
|
|
||||||
if(!$db->hasColumn($tmp[0], $tmp[1])) {
|
|
||||||
$errors[] = "This plugin requires database column: " . $tmp[0] . "." . $tmp[1] . " to exist in database.";
|
|
||||||
$tmpDisplayError = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self::$warnings[] = "Invalid plugin require column: " . $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($tmpDisplayError) {
|
|
||||||
self::$error = implode('<br/>', $errors);
|
|
||||||
$continue = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(strpos($req, 'ext-') !== false) {
|
|
||||||
$tmp = explode('-', $req);
|
|
||||||
if(count($tmp) == 2) {
|
|
||||||
if(!extension_loaded($tmp[1]) || !Semver::satisfies(phpversion($tmp[1]), $version)) {
|
|
||||||
self::$error = "This plugin requires php extension: " . $tmp[1] . ", version " . $version . " to be installed.";
|
|
||||||
$continue = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(!self::is_installed($req, $version)) {
|
|
||||||
self::$error = "This plugin requires another plugin to run correctly. The another plugin is: " . $req . ", with version " . $version . ".";
|
|
||||||
$continue = false;
|
$continue = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else if($req == 'table') {
|
||||||
}
|
$tmpDisplayError = false;
|
||||||
|
$explode = explode(',', $version);
|
||||||
|
foreach ($explode as $item) {
|
||||||
|
if(!$db->hasTable($item)) {
|
||||||
|
$errors[] = "This plugin requires table: " . $item . " to exist in the database.";
|
||||||
|
$tmpDisplayError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if($continue) {
|
if ($tmpDisplayError) {
|
||||||
if(!$zip->extractTo(BASE)) { // "Real" Install
|
self::$error = implode('<br/>', $errors);
|
||||||
self::$error = 'There was a problem with extracting zip archive to base directory.';
|
$continue = false;
|
||||||
$zip->close();
|
break;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$install = $plugin_json['install'] ?? '';
|
|
||||||
if (self::getAutoLoadOption($plugin_json, 'install', true) && is_file(PLUGINS . $pluginFilename . '/install.php')) {
|
|
||||||
$install = 'plugins/' . $pluginFilename . '/install.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($install)) {
|
|
||||||
if (file_exists(BASE . $install)) {
|
|
||||||
$db->revalidateCache();
|
|
||||||
require BASE . $install;
|
|
||||||
$db->revalidateCache();
|
|
||||||
}
|
}
|
||||||
else {
|
else if($req == 'column') {
|
||||||
self::$warnings[] = 'Cannot load install script. Your plugin might be not working correctly.';
|
$tmpDisplayError = false;
|
||||||
|
$explode = explode(',', $version);
|
||||||
|
foreach ($explode as $item) {
|
||||||
|
$tmp = explode('.', $item);
|
||||||
|
|
||||||
|
if(count($tmp) == 2) {
|
||||||
|
if(!$db->hasColumn($tmp[0], $tmp[1])) {
|
||||||
|
$errors[] = "This plugin requires database column: " . $tmp[0] . "." . $tmp[1] . " to exist in database.";
|
||||||
|
$tmpDisplayError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self::$warnings[] = "Invalid plugin require column: " . $item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($tmpDisplayError) {
|
||||||
|
self::$error = implode('<br/>', $errors);
|
||||||
|
$continue = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(strpos($req, 'ext-') !== false) {
|
||||||
|
$tmp = explode('-', $req);
|
||||||
|
if(count($tmp) == 2) {
|
||||||
|
if(!extension_loaded($tmp[1]) || !Semver::satisfies(phpversion($tmp[1]), $version)) {
|
||||||
|
self::$error = "This plugin requires php extension: " . $tmp[1] . ", version " . $version . " to be installed.";
|
||||||
|
$continue = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(!self::is_installed($req, $version)) {
|
||||||
|
self::$error = "This plugin requires another plugin to run correctly. The another plugin is: " . $req . ", with version " . $version . ".";
|
||||||
|
$continue = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clearCache();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if(!$continue) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$zip->extractTo(BASE)) { // "Real" Install
|
||||||
|
self::$error = 'There was a problem with extracting zip archive to base directory.';
|
||||||
|
$zip->close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$install = $plugin_json['install'] ?? '';
|
||||||
|
if (self::getAutoLoadOption($plugin_json, 'install', true) && is_file(PLUGINS . $pluginFilename . '/install.php')) {
|
||||||
|
$install = 'plugins/' . $pluginFilename . '/install.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($install)) {
|
||||||
|
if (file_exists(BASE . $install)) {
|
||||||
|
$db->revalidateCache();
|
||||||
|
require BASE . $install;
|
||||||
|
$db->revalidateCache();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self::$warnings[] = 'Cannot load install script. Your plugin might be not working correctly.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearCache();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isEnabled($pluginFileName): bool
|
public static function isEnabled($pluginFileName): bool
|
||||||
@@ -781,15 +780,20 @@ class Plugins {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isset($plugin_json['install'])) {
|
$install = $plugin_json['install'] ?? '';
|
||||||
self::$error = "Plugin doesn't have install options defined. Skipping...";
|
if (self::getAutoLoadOption($plugin_json, 'install', true) && is_file(PLUGINS . $plugin_name . '/install.php')) {
|
||||||
|
$install = 'plugins/' . $plugin_name . '/install.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($install)) {
|
||||||
|
self::$error = "This plugin doesn't seem to have install script defined.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
global $db;
|
global $db;
|
||||||
if (file_exists(BASE . $plugin_json['install'])) {
|
if (file_exists(BASE . $install)) {
|
||||||
$db->revalidateCache();
|
$db->revalidateCache();
|
||||||
require BASE . $plugin_json['install'];
|
require BASE . $install;
|
||||||
$db->revalidateCache();
|
$db->revalidateCache();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@@ -472,24 +472,22 @@ class Settings implements \ArrayAccess
|
|||||||
if (!isset($this->settingsFile[$pluginKeyName]['settings'])) {
|
if (!isset($this->settingsFile[$pluginKeyName]['settings'])) {
|
||||||
throw new \RuntimeException('Unknown plugin settings: ' . $pluginKeyName);
|
throw new \RuntimeException('Unknown plugin settings: ' . $pluginKeyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->settingsFile[$pluginKeyName]['settings'];
|
return $this->settingsFile[$pluginKeyName]['settings'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$ret = [];
|
if (!isset($this->settingsFile[$pluginKeyName]['settings'][$key])) {
|
||||||
if(isset($this->settingsFile[$pluginKeyName]['settings'][$key])) {
|
return null;
|
||||||
$ret = $this->settingsFile[$pluginKeyName]['settings'][$key];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$ret = $this->settingsFile[$pluginKeyName]['settings'][$key];
|
||||||
|
|
||||||
if(isset($this->settingsDatabase[$pluginKeyName][$key])) {
|
if(isset($this->settingsDatabase[$pluginKeyName][$key])) {
|
||||||
$value = $this->settingsDatabase[$pluginKeyName][$key];
|
$value = $this->settingsDatabase[$pluginKeyName][$key];
|
||||||
|
|
||||||
$ret['value'] = $value;
|
$ret['value'] = $value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!isset($this->settingsFile[$pluginKeyName]['settings'][$key])) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$ret['value'] = $this->settingsFile[$pluginKeyName]['settings'][$key]['default'];
|
$ret['value'] = $this->settingsFile[$pluginKeyName]['settings'][$key]['default'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
13
system/src/TwoFactorAuth/Gateway/AppAuthGateway.php
Normal file
13
system/src/TwoFactorAuth/Gateway/AppAuthGateway.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MyAAC\TwoFactorAuth\Gateway;
|
||||||
|
|
||||||
|
use MyAAC\TwoFactorAuth\Interface\AuthGatewayInterface;
|
||||||
|
|
||||||
|
class AppAuthGateway extends BaseAuthGateway implements AuthGatewayInterface
|
||||||
|
{
|
||||||
|
public function verifyCode(string $code): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
12
system/src/TwoFactorAuth/Gateway/BaseAuthGateway.php
Normal file
12
system/src/TwoFactorAuth/Gateway/BaseAuthGateway.php
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MyAAC\TwoFactorAuth\Gateway;
|
||||||
|
|
||||||
|
class BaseAuthGateway
|
||||||
|
{
|
||||||
|
protected \OTS_Account $account;
|
||||||
|
|
||||||
|
public function __construct(\OTS_Account $account) {
|
||||||
|
$this->account = $account;
|
||||||
|
}
|
||||||
|
}
|
16
system/src/TwoFactorAuth/Gateway/EmailAuthGateway.php
Normal file
16
system/src/TwoFactorAuth/Gateway/EmailAuthGateway.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MyAAC\TwoFactorAuth\Gateway;
|
||||||
|
|
||||||
|
use MyAAC\Models\AccountEMailCode;
|
||||||
|
use MyAAC\TwoFactorAuth\Interface\AuthGatewayInterface;
|
||||||
|
use MyAAC\TwoFactorAuth\TwoFactorAuth;
|
||||||
|
|
||||||
|
class EmailAuthGateway extends BaseAuthGateway implements AuthGatewayInterface
|
||||||
|
{
|
||||||
|
public function verifyCode(string $code): bool
|
||||||
|
{
|
||||||
|
return AccountEMailCode::where('account_id', '=', $this->account->getId())->where('code', $code)->where('created_at', '>', time() - TwoFactorAuth::EMAIL_CODE_VALID_UNTIL)->first() !== null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MyAAC\TwoFactorAuth\Interface;
|
||||||
|
|
||||||
|
interface AuthGatewayInterface
|
||||||
|
{
|
||||||
|
public function __construct(\OTS_Account $account);
|
||||||
|
public function verifyCode(string $code): bool;
|
||||||
|
}
|
173
system/src/TwoFactorAuth/TwoFactorAuth.php
Normal file
173
system/src/TwoFactorAuth/TwoFactorAuth.php
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MyAAC\TwoFactorAuth;
|
||||||
|
|
||||||
|
use MyAAC\Models\AccountEMailCode;
|
||||||
|
use MyAAC\TwoFactorAuth\Gateway\AppAuthGateway;
|
||||||
|
use MyAAC\TwoFactorAuth\Gateway\EmailAuthGateway;
|
||||||
|
|
||||||
|
class TwoFactorAuth
|
||||||
|
{
|
||||||
|
const TYPE_NONE = 0;
|
||||||
|
const TYPE_EMAIL = 1;
|
||||||
|
const TYPE_APP = 2;
|
||||||
|
// maybe later
|
||||||
|
//const TYPE_SMS = 3;
|
||||||
|
|
||||||
|
const EMAIL_CODE_VALID_UNTIL = 24 * 60 * 60;
|
||||||
|
|
||||||
|
private static self $instance;
|
||||||
|
|
||||||
|
private \OTS_Account $account;
|
||||||
|
private int $authType;
|
||||||
|
private EmailAuthGateway|AppAuthGateway $authGateway;
|
||||||
|
|
||||||
|
public function __construct(\OTS_Account|int $account) {
|
||||||
|
if (is_int($account)) {
|
||||||
|
$this->account = new \OTS_Account();
|
||||||
|
$this->account->load($account);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->account = $account;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authType = (int)$this->account->getCustomField('2fa_type');
|
||||||
|
$this->setAuthGateway($this->authType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getInstance($account = null): self
|
||||||
|
{
|
||||||
|
if (!isset(self::$instance)) {
|
||||||
|
self::$instance = new self($account);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function process($login_account, $login_password, $code): bool
|
||||||
|
{
|
||||||
|
global $twig;
|
||||||
|
|
||||||
|
if (!$this->isActive()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($code)) {
|
||||||
|
if ($this->authType == self::TYPE_EMAIL) {
|
||||||
|
if (!$this->hasRecentEmailCode(15 * 60)) {
|
||||||
|
$this->resendEmailCode();
|
||||||
|
//success('Resent email.');
|
||||||
|
}
|
||||||
|
|
||||||
|
define('HIDE_LOGIN_BOX', true);
|
||||||
|
$twig->display('account.2fa.email.login.html.twig');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo 'Two Factor App Auth';
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->getAuthGateway()->verifyCode($code)) {
|
||||||
|
if ($this->authType === self::TYPE_EMAIL) {
|
||||||
|
$this->deleteOldCodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: account/manage');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setting('core.mail_enabled')) {
|
||||||
|
$mailBody = $twig->render('mail.account.2fa.email-code.wrong-attempt.html.twig');
|
||||||
|
|
||||||
|
if (!_mail($this->account->getEMail(), configLua('serverName') . ' - Failed Two-Factor Authentication Attempt', $mailBody)) {
|
||||||
|
error('An error occurred while sending email. For Admin: More info can be found in system/logs/mailer-error.log');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define('HIDE_LOGIN_BOX', true);
|
||||||
|
|
||||||
|
$errors[] = 'Invalid email code!';
|
||||||
|
$twig->display('error_box.html.twig', ['errors' => $errors]);
|
||||||
|
|
||||||
|
$twig->display('account.2fa.email.login.html.twig', ['wrongCode' => true]);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAuthGateway(int $authType): void
|
||||||
|
{
|
||||||
|
if ($authType === self::TYPE_EMAIL) {
|
||||||
|
$this->authGateway = new EmailAuthGateway($this->account);
|
||||||
|
}
|
||||||
|
else if ($authType === self::TYPE_APP) {
|
||||||
|
$this->authGateway = new AppAuthGateway($this->account);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAccountManageViews(): array
|
||||||
|
{
|
||||||
|
$twoFactorView = 'account.2fa.protected.html.twig';
|
||||||
|
if ($this->authType == self::TYPE_EMAIL) {
|
||||||
|
$twoFactorView2 = 'account.2fa.email.activated.html.twig';
|
||||||
|
}
|
||||||
|
elseif ($this->authType == self::TYPE_APP) {
|
||||||
|
$twoFactorView2 = 'account.2fa.app.activated.html.twig';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$twoFactorView = 'account.2fa.connect.html.twig';
|
||||||
|
$twoFactorView2 = 'account.2fa.email.activate.html.twig';
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$twoFactorView, $twoFactorView2];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function enable(int $type): void {
|
||||||
|
$this->account->setCustomField('2fa_type', $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function disable(): void {
|
||||||
|
$this->account->setCustomField('2fa_type', self::TYPE_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isActive(): bool {
|
||||||
|
return $this->authType != self::TYPE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAuthType(): int {
|
||||||
|
return $this->authType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAuthGateway(): AppAuthGateway|EmailAuthGateway {
|
||||||
|
return $this->authGateway;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasRecentEmailCode($since = self::EMAIL_CODE_VALID_UNTIL): bool {
|
||||||
|
return AccountEMailCode::where('account_id', '=', $this->account->getId())->where('created_at', '>', time() - $since)->first() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteOldCodes(): void {
|
||||||
|
AccountEMailCode::where('account_id', '=', $this->account->getId())->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resendEmailCode(): void
|
||||||
|
{
|
||||||
|
global $twig;
|
||||||
|
|
||||||
|
$newCode = generateRandomString(6, true, false, true);
|
||||||
|
AccountEMailCode::create([
|
||||||
|
'account_id' => $this->account->getId(),
|
||||||
|
'code' => $newCode,
|
||||||
|
'created_at' => time(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$mailBody = $twig->render('mail.account.2fa.email-code.html.twig', [
|
||||||
|
'code' => $newCode,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!_mail($this->account->getEMail(), configLua('serverName') . ' - Requested Authentication Email Code', $mailBody)) {
|
||||||
|
error('An error occurred while sending email. For Admin: More info can be found in system/logs/mailer-error.log');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -54,6 +54,7 @@ define('HOOK_ACCOUNT_MANAGE_BEFORE_GENERAL_INFORMATION', ++$i);
|
|||||||
define('HOOK_ACCOUNT_MANAGE_BEFORE_PUBLIC_INFORMATION', ++$i);
|
define('HOOK_ACCOUNT_MANAGE_BEFORE_PUBLIC_INFORMATION', ++$i);
|
||||||
define('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS', ++$i);
|
define('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS', ++$i);
|
||||||
define('HOOK_ACCOUNT_MANAGE_BEFORE_CHARACTERS', ++$i);
|
define('HOOK_ACCOUNT_MANAGE_BEFORE_CHARACTERS', ++$i);
|
||||||
|
define('HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS', ++$i);
|
||||||
define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i);
|
define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i);
|
||||||
define('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT', ++$i);
|
define('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT', ++$i);
|
||||||
define('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT', ++$i);
|
define('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT', ++$i);
|
||||||
@@ -92,6 +93,7 @@ define('HOOK_EMAIL_CONFIRMED', ++$i);
|
|||||||
define('HOOK_GUILDS_BEFORE_GUILD_HEADER', ++$i);
|
define('HOOK_GUILDS_BEFORE_GUILD_HEADER', ++$i);
|
||||||
define('HOOK_GUILDS_AFTER_GUILD_HEADER', ++$i);
|
define('HOOK_GUILDS_AFTER_GUILD_HEADER', ++$i);
|
||||||
define('HOOK_GUILDS_AFTER_GUILD_INFORMATION', ++$i);
|
define('HOOK_GUILDS_AFTER_GUILD_INFORMATION', ++$i);
|
||||||
|
define('HOOK_GUILDS_AFTER_MANAGE_BUTTON', ++$i);
|
||||||
define('HOOK_GUILDS_AFTER_GUILD_MEMBERS', ++$i);
|
define('HOOK_GUILDS_AFTER_GUILD_MEMBERS', ++$i);
|
||||||
define('HOOK_GUILDS_AFTER_INVITED_CHARACTERS', ++$i);
|
define('HOOK_GUILDS_AFTER_INVITED_CHARACTERS', ++$i);
|
||||||
define('HOOK_TWIG', ++$i);
|
define('HOOK_TWIG', ++$i);
|
||||||
|
@@ -91,7 +91,7 @@ else {
|
|||||||
$file = BASE . $template_path . '/layout_config.ini';
|
$file = BASE . $template_path . '/layout_config.ini';
|
||||||
}
|
}
|
||||||
|
|
||||||
$template_ini = parse_ini_file($file);
|
$template_ini = parse_ini_file($file, true);
|
||||||
unset($file);
|
unset($file);
|
||||||
|
|
||||||
if ($cache->enabled()) {
|
if ($cache->enabled()) {
|
||||||
|
36
system/templates/account.2fa.connect.html.twig
Normal file
36
system/templates/account.2fa.connect.html.twig
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="TableShadowContainerRightTop">
|
||||||
|
<div class="TableShadowRightTop" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rt.gif);"></div>
|
||||||
|
</div>
|
||||||
|
<div class="TableContentAndRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rm.gif);">
|
||||||
|
<div class="TableContentContainer">
|
||||||
|
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
|
||||||
|
<tbody><tr>
|
||||||
|
<td class="LabelV"><b>Connect your {{ config.lua.serverName }} account to an authenticator app!</b>
|
||||||
|
<div style="float: right; font-size: 1px;">
|
||||||
|
<form action="{{ getLink('account/2fa') }}?action=email-code" method="post" style="margin: 0px; padding: 0px;">
|
||||||
|
{{ csrf() }}
|
||||||
|
{% set button_name = 'Request' %}
|
||||||
|
{% include('buttons.base.html.twig') %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p>As a first step to connect an <b>authenticator app</b> to your account, click on "Request"! An email with a confirmation key will be sent to the email address assigned to your account.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="TableShadowContainer">
|
||||||
|
<div class="TableBottomShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-bm.gif);">
|
||||||
|
<div class="TableBottomLeftShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-bl.gif);"></div>
|
||||||
|
<div class="TableBottomRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-br.gif);"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
37
system/templates/account.2fa.email.activate.html.twig
Normal file
37
system/templates/account.2fa.email.activate.html.twig
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="TableShadowContainerRightTop">
|
||||||
|
<div class="TableShadowRightTop" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rt.gif);"></div>
|
||||||
|
</div>
|
||||||
|
<div class="TableContentAndRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rm.gif);">
|
||||||
|
<div class="TableContentContainer">
|
||||||
|
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="LabelV"><b>Activate email code authentication for your account!</b>
|
||||||
|
<div style="float: right; font-size: 1px;">
|
||||||
|
<form action="{{ getLink('account/2fa') }}?action=email-code&step=activate" method="post" style="margin: 0; padding: 0;">
|
||||||
|
{{ csrf() }}
|
||||||
|
{% set button_name = 'Request' %}
|
||||||
|
{% include('buttons.base.html.twig') %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p>As a first step to activate <b>email code authentication</b> for your account, click on "Request"! An <b>email code</b> will be sent to the email address assigned to your account. You will be asked to enter this <b>email code</b> on the next page within 24 hours.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="TableShadowContainer">
|
||||||
|
<div class="TableBottomShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-bm.gif);">
|
||||||
|
<div class="TableBottomLeftShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-bl.gif);"></div>
|
||||||
|
<div class="TableBottomRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-br.gif);"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
26
system/templates/account.2fa.email.activated.html.twig
Normal file
26
system/templates/account.2fa.email.activated.html.twig
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="TableContentContainer ">
|
||||||
|
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div style="float: right; width: 135px;">
|
||||||
|
<form action="{{ getLink('account/2fa') }}?action=email-code" method="post" style="padding:0;margin:0;">
|
||||||
|
{{ csrf() }}
|
||||||
|
<input type="hidden" name="step" value="deactivate">
|
||||||
|
{% set button_name = 'Deactivate' %}
|
||||||
|
{{ include('buttons.base.html.twig') }}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<b>Two-Factor Email Code Authentication <span style="color: green">Activated</span>!</b>
|
||||||
|
<p>To deactivate <b>email code authentication</b>, click on the "Deactivate" button.</p>
|
||||||
|
<p>You will have to confirm the deactivation by entering an <b>email code</b> which will be sent
|
||||||
|
to the email address assigned to your account.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
109
system/templates/account.2fa.email.deactivate.html.twig
Normal file
109
system/templates/account.2fa.email.deactivate.html.twig
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
{% set title = 'Deactivate Email Code Authentication' %}
|
||||||
|
{% set content %}
|
||||||
|
<table style="width:100%;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="TableContentContainer ">
|
||||||
|
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>To deactivate <b>two-factor email code authentication</b> for your account, enter the
|
||||||
|
received <b>email code</b> below. Note, however, that <b>email code authentication</b>
|
||||||
|
is an important security feature which helps to prevent any unauthorised access to your
|
||||||
|
Tibia account.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="TableContentContainer">
|
||||||
|
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div style="float: right;">
|
||||||
|
<form
|
||||||
|
action="{{ getLink('account/2fa') }}?action=email-code&step=resend"
|
||||||
|
method="post"
|
||||||
|
style="padding:0;margin:0;"
|
||||||
|
>
|
||||||
|
{{ csrf() }}
|
||||||
|
|
||||||
|
{% set button_name = 'Resend Email Code' %}
|
||||||
|
{{ include('buttons.base.html.twig') }}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
An <b>email code</b> has already been sent to the email address assigned to your
|
||||||
|
account.
|
||||||
|
Please check your email account's spam/junk filter and make sure that your mailbox is
|
||||||
|
not
|
||||||
|
full.<br>In case you need a new email code, you can request one by clicking on "Resend
|
||||||
|
Email
|
||||||
|
Code".
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="TableContentContainer">
|
||||||
|
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>To complete the deactivation of <b>email code authentication</b>, please enter the <b>email
|
||||||
|
code</b> you received at the email address assigned to your account.
|
||||||
|
<div style="margin-top: 15px; margin-bottom: 15px;">
|
||||||
|
<div class="LabelV150 {{ wrongCode ? 'red' : '' }}" style="float:left;"><label
|
||||||
|
for="email-code">Email Code:</label></div>
|
||||||
|
<input form="form-code" id="email-code" name="email-code" maxlength="15"
|
||||||
|
autocomplete="off">
|
||||||
|
{% if wrongCode %}
|
||||||
|
<br/>
|
||||||
|
<div class="LabelV150" style="float:left;"> </div>
|
||||||
|
<div class="FormFieldError">Invalid email code!</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endset %}
|
||||||
|
{% include 'tables.headline.html.twig' %}
|
||||||
|
<table style="width: 100%;">
|
||||||
|
<tbody>
|
||||||
|
<tr align="center" valign="top">
|
||||||
|
<td>
|
||||||
|
<form id="form-code" method="post" action="{{ getLink('account/2fa') }}?action=email-code">
|
||||||
|
{{ csrf() }}
|
||||||
|
|
||||||
|
<input type="hidden" name="step" value="deactivate">
|
||||||
|
<input type="hidden" name="save" value="1">
|
||||||
|
|
||||||
|
{% set button_name = 'Continue' %}
|
||||||
|
{% set button_color = 'green' %}
|
||||||
|
{{ include('buttons.submit.html.twig') }}
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<form action="{{ getLink('account/manage') }}" method="post" style="padding:0;margin:0;">
|
||||||
|
{{ csrf() }}
|
||||||
|
{% set button_color = 'blue' %}
|
||||||
|
{{ include('buttons.back.html.twig') }}
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
85
system/templates/account.2fa.email.login.html.twig
Normal file
85
system/templates/account.2fa.email.login.html.twig
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{% set title = 'Enter Email Code' %}
|
||||||
|
{% set content %}
|
||||||
|
<table style="width:100%;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="TableContentContainer">
|
||||||
|
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div style="float: right;">
|
||||||
|
<form
|
||||||
|
action="{{ getLink('account/2fa') }}?action=email-code&step=resend"
|
||||||
|
method="post"
|
||||||
|
style="padding:0;margin:0;"
|
||||||
|
>
|
||||||
|
{{ csrf() }}
|
||||||
|
|
||||||
|
{% set button_name = 'Resend Email Code' %}
|
||||||
|
{{ include('buttons.base.html.twig') }}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
An <b>email code</b> has already been sent to the email address assigned to your account.
|
||||||
|
Please check your email account's spam/junk filter and make sure that your mailbox is not
|
||||||
|
full.<br>In case you need a new email code, you can request one by clicking on "Resend Email
|
||||||
|
Code".
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="TableContentContainer">
|
||||||
|
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><b>Email code authentication is activated for your account.</b><br><br>Please enter the <b>most
|
||||||
|
recent email code</b> you have received in order to log in.<br>
|
||||||
|
<div style="margin-top: 15px; margin-bottom: 15px;">
|
||||||
|
<div class="LabelV150 {{ wrongCode ? 'red' : '' }}" style="float:left;"><label for="email-code">Email Code:</label></div>
|
||||||
|
<input form="form-code" id="email-code" name="email-code" maxlength="15" autocomplete="off">
|
||||||
|
{% if wrongCode %}
|
||||||
|
<br/>
|
||||||
|
<div class="LabelV150" style="float:left;"> </div>
|
||||||
|
<div class="FormFieldError">Invalid email code!</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endset %}
|
||||||
|
{% include 'tables.headline.html.twig' %}
|
||||||
|
<table style="width: 100%;">
|
||||||
|
<tbody>
|
||||||
|
<tr align="center" valign="top">
|
||||||
|
<td>
|
||||||
|
<form id="form-code" method="post" action="{{ getLink('account/manage') }}">
|
||||||
|
{{ csrf() }}
|
||||||
|
|
||||||
|
<input type="hidden" name="step" value="verify">
|
||||||
|
{% set button_name = 'Continue' %}
|
||||||
|
{% set button_color = 'green' %}
|
||||||
|
{{ include('buttons.submit.html.twig') }}
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<form action="{{ getLink('account/manage') }}" method="post" style="padding:0;margin:0;">
|
||||||
|
{{ csrf() }}
|
||||||
|
{% set button_color = 'blue' %}
|
||||||
|
{{ include('buttons.back.html.twig') }}
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
105
system/templates/account.2fa.email_code.html.twig
Normal file
105
system/templates/account.2fa.email_code.html.twig
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
{% set title = 'Activate Email Code Authentication' %}
|
||||||
|
|
||||||
|
{% set content %}
|
||||||
|
<table style="width:100%;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="TableContentContainer">
|
||||||
|
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Enter the email code below to activate <b>two-factor email code authentication</b>. Note
|
||||||
|
that this code is only valid for 24 hours.<br><br>
|
||||||
|
<div class="AttentionSign"><img src="{{ template_path }}/images/global/content/attentionsign.gif"></div>
|
||||||
|
<b>Note:</b> Once you have email code authentication activated, an <b>email code</b> will be
|
||||||
|
sent to the email address assigned to your account whenever you try to log in to the Tibia
|
||||||
|
client or the {{ config.lua.serverName }} website. In order to log in, you will need to enter the <b>most recent
|
||||||
|
email code</b> you have received.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="TableContentContainer">
|
||||||
|
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div style="float: right;">
|
||||||
|
<form action="{{ getLink('account/2fa') }}?action=email-code"
|
||||||
|
method="post" style="padding:0;margin:0;">
|
||||||
|
{{ csrf() }}
|
||||||
|
|
||||||
|
<input type="hidden" name="step" value="resend">
|
||||||
|
|
||||||
|
{% set button_name = 'Resend Email Code' %}
|
||||||
|
{% include('buttons.base.html.twig') %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
An <b>email code</b> has already been sent to the email address assigned to your account.
|
||||||
|
Please check your email account's spam/junk filter and make sure that your mailbox is not
|
||||||
|
full.<br>In case you need a new email code, you can request one by clicking on "Resend Email
|
||||||
|
Code".
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="TableContentContainer">
|
||||||
|
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>To complete the activation of email code authentication for your Tibia account, please enter
|
||||||
|
the email code you received at the email address assigned to your account.
|
||||||
|
<div style="margin-top: 15px; margin-bottom: 15px;">
|
||||||
|
<div class="LabelV150 {{ wrongCode ? 'red' : '' }}" style="float:left;">Email Code:</div>
|
||||||
|
<input form="confirmActivateForm" name="email-code" maxlength="6">
|
||||||
|
{% if wrongCode %}
|
||||||
|
<br/>
|
||||||
|
<div class="LabelV150" style="float:left;"> </div>
|
||||||
|
<div class="FormFieldError">Invalid email code!</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endset %}
|
||||||
|
{% include 'tables.headline.html.twig' %}
|
||||||
|
<table style="width: 100%;">
|
||||||
|
<tbody>
|
||||||
|
<tr align="center" valign="top">
|
||||||
|
<td>
|
||||||
|
<form id="confirmActivateForm" action="{{ getLink('account/2fa') }}?action=email-code" method="post" style="padding:0;margin:0;">
|
||||||
|
{{ csrf() }}
|
||||||
|
|
||||||
|
<input type="hidden" name="step" value="activate">
|
||||||
|
<input type="hidden" name="save" value="1">
|
||||||
|
|
||||||
|
{% set button_color = 'green' %}
|
||||||
|
{{ include('buttons.submit.html.twig') }}
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<form action="{{ getLink('account/manage') }}" method="post" style="padding:0;margin:0;">
|
||||||
|
{{ csrf() }}
|
||||||
|
{{ include('buttons.back.html.twig') }}
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
12
system/templates/account.2fa.main.html.twig
Normal file
12
system/templates/account.2fa.main.html.twig
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{% set title = 'Two-Factor Authentication' %}
|
||||||
|
|
||||||
|
{% set content %}
|
||||||
|
<table style="width:100%;">
|
||||||
|
<tbody>
|
||||||
|
{{ include(twoFactorViews[0]) }}
|
||||||
|
{{ include(twoFactorViews[1]) }}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endset %}
|
||||||
|
{% include('tables.headline.html.twig') %}
|
||||||
|
<br/>
|
18
system/templates/account.2fa.protected.html.twig
Normal file
18
system/templates/account.2fa.protected.html.twig
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="TableContentContainer ">
|
||||||
|
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="InTableRightButtonContainer"></div>
|
||||||
|
<b>Two-Factor Authenticator App</b>
|
||||||
|
<p>Your account is currently protected by email code authentication. If you prefer to use a <b>two-factor
|
||||||
|
authentication app</b>, you have to "Deactivate" email code authentication first.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
@@ -28,7 +28,7 @@ Please enter your password and the new email address. Make sure that you enter a
|
|||||||
<td>
|
<td>
|
||||||
<table border="0" cellspacing="0" cellpadding="0">
|
<table border="0" cellspacing="0" cellpadding="0">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="border:0px;">
|
<td style="border:0;">
|
||||||
<form id="form" action="{{ getLink('account/change-email') }}" method="post">
|
<form id="form" action="{{ getLink('account/change-email') }}" method="post">
|
||||||
{{ csrf() }}
|
{{ csrf() }}
|
||||||
<input type="hidden" name="changeemailsave" value="1"/>
|
<input type="hidden" name="changeemailsave" value="1"/>
|
||||||
@@ -40,14 +40,14 @@ Please enter your password and the new email address. Make sure that you enter a
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<table border="0" cellspacing="0" cellpadding="0">
|
<table border="0" cellspacing="0" cellpadding="0">
|
||||||
<form action="{{ getLink('account/manage') }}" method="post">
|
<tr>
|
||||||
{{ csrf() }}
|
<td style="border:0;">
|
||||||
<tr>
|
<form action="{{ getLink('account/manage') }}" method="post">
|
||||||
<td style="border:0px;">
|
{{ csrf() }}
|
||||||
{{ include('buttons.back.html.twig') }}
|
{{ include('buttons.back.html.twig') }}
|
||||||
</td>
|
</form>
|
||||||
</tr>
|
</td>
|
||||||
</form>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@@ -88,7 +88,7 @@ If you do not want to specify a certain field, just leave it blank.<br/><br/>
|
|||||||
<td>
|
<td>
|
||||||
<table border="0" cellspacing="0" cellpadding="0">
|
<table border="0" cellspacing="0" cellpadding="0">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="border:0px;">
|
<td style="border:0;">
|
||||||
<input type="hidden" name="name" value="{{ player.name }}">
|
<input type="hidden" name="name" value="{{ player.name }}">
|
||||||
<input type="hidden" name="changecommentsave" value="1">
|
<input type="hidden" name="changecommentsave" value="1">
|
||||||
{{ include('buttons.submit.html.twig') }}
|
{{ include('buttons.submit.html.twig') }}
|
||||||
@@ -99,15 +99,15 @@ If you do not want to specify a certain field, just leave it blank.<br/><br/>
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<table border="0" cellspacing="0" cellpadding="0">
|
<table border="0" cellspacing="0" cellpadding="0">
|
||||||
<form action="{{ getLink('account/manage') }}" method="post">
|
<tr>
|
||||||
{{ csrf() }}
|
<td style="border:0;">
|
||||||
<tr>
|
<form action="{{ getLink('account/manage') }}" method="post">
|
||||||
<td style="border:0px;">
|
{{ csrf() }}
|
||||||
{{ include('buttons.back.html.twig') }}
|
{{ include('buttons.back.html.twig') }}
|
||||||
</td>
|
</form>
|
||||||
</tr>
|
</td>
|
||||||
</form>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -24,7 +24,7 @@ To delete a character enter the name of the character and your password.<br/><br
|
|||||||
<td>
|
<td>
|
||||||
<table border="0" cellspacing="0" cellpadding="0">
|
<table border="0" cellspacing="0" cellpadding="0">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="border:0px;">
|
<td style="border:0;">
|
||||||
<form id="form" action="{{ getLink('account/characters/delete') }}" method="post">
|
<form id="form" action="{{ getLink('account/characters/delete') }}" method="post">
|
||||||
{{ csrf() }}
|
{{ csrf() }}
|
||||||
<input type="hidden" name="deletecharactersave" value="1"/>
|
<input type="hidden" name="deletecharactersave" value="1"/>
|
||||||
@@ -36,14 +36,14 @@ To delete a character enter the name of the character and your password.<br/><br
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<table border="0" cellspacing="0" cellpadding="0">
|
<table border="0" cellspacing="0" cellpadding="0">
|
||||||
<form action="{{ getLink('account/manage') }}" method="post">
|
<tr>
|
||||||
{{ csrf() }}
|
<td style="border:0;">
|
||||||
<tr>
|
<form action="{{ getLink('account/manage') }}" method="post">
|
||||||
<td style="border:0px;">
|
{{ csrf() }}
|
||||||
{{ include('buttons.back.html.twig') }}
|
{{ include('buttons.back.html.twig') }}
|
||||||
</td>
|
</form>
|
||||||
</tr>
|
</td>
|
||||||
</form>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@@ -32,14 +32,14 @@ To generate recovery key for your account please enter your password.<br/><br/>
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<table border="0" cellspacing="0" cellpadding="0">
|
<table border="0" cellspacing="0" cellpadding="0">
|
||||||
<form action="{{ getLink('account/manage') }}" method="post">
|
<tr>
|
||||||
{{ csrf() }}
|
<td style="border: 0;">
|
||||||
<tr>
|
<form action="{{ getLink('account/manage') }}" method="post">
|
||||||
<td style="border: 0;">
|
{{ csrf() }}
|
||||||
{{ include('buttons.back.html.twig') }}
|
{{ include('buttons.back.html.twig') }}
|
||||||
</td>
|
</form>
|
||||||
</tr>
|
</td>
|
||||||
</form>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@@ -147,6 +147,9 @@
|
|||||||
{% include('buttons.base.html.twig') %}
|
{% include('buttons.base.html.twig') %}
|
||||||
</form>
|
</form>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
{{ include('account.2fa.main.html.twig') }}
|
||||||
|
|
||||||
{{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS') }}
|
{{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS') }}
|
||||||
<a name="Account+Logs" ></a>
|
<a name="Account+Logs" ></a>
|
||||||
<h2>Account Logs</h2>
|
<h2>Account Logs</h2>
|
||||||
@@ -228,5 +231,7 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
<br/>
|
||||||
|
{{ hook('HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -16,6 +16,13 @@
|
|||||||
<input class="form-control" type="text" id="mail_to" name="mail_to" value="{{ mail_to }}"/>
|
<input class="form-control" type="text" id="mail_to" name="mail_to" value="{{ mail_to }}"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if setting('core.account_mail_verify') %}
|
||||||
|
<div class="form-check">
|
||||||
|
<input type="checkbox" class="form-check-input" id="mail_verified_only" name="mail_verified_only" {% if mail_verified_only %}checked{% endif %}>
|
||||||
|
<label class="form-check-label" for="mail_verified_only">Mail only verified users</label>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="mail_subject">Subject:</label>
|
<label for="mail_subject">Subject:</label>
|
||||||
<input class="form-control" type="text" id="mail_subject" name="mail_subject" value="{{ mail_subject }}" maxlength="30"/>
|
<input class="form-control" type="text" id="mail_subject" name="mail_subject" value="{{ mail_subject }}" maxlength="30"/>
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
<div id="install_plugin">
|
<div id="install_plugin">
|
||||||
<div class="card card-info card-outline">
|
<div class="card card-info card-outline">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h5 class="m-0">Install plugin</h5>
|
<h5 class="m-0">Install plugin
|
||||||
|
<a href="?p=plugins&check-updates" class="btn btn-primary float-right">Check for updates</a>
|
||||||
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<form enctype="multipart/form-data" method="post" action="{{ constant('ADMIN_URL') }}?p=plugins">
|
<form enctype="multipart/form-data" method="post" action="{{ constant('ADMIN_URL') }}?p=plugins">
|
||||||
{{ csrf() }}
|
{{ csrf() }}
|
||||||
|
18
system/templates/admin.plugins.outdated.html.twig
Normal file
18
system/templates/admin.plugins.outdated.html.twig
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<table class="table table-bordered table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Plugin Name</th>
|
||||||
|
<th>Your Version</th>
|
||||||
|
<th>Latest Version</th>
|
||||||
|
<th>Download Link</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{% for plugin in plugins %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ plugin.name }}</td>
|
||||||
|
<td>{{ plugin.yourVersion }}</td>
|
||||||
|
<td>{{ plugin.latestVersion }}</td>
|
||||||
|
<td><a href="{{ plugin.download_link }}" target="_blank">{{ plugin.download_link }}</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
@@ -1,17 +1,23 @@
|
|||||||
<form action="{{ link }}" method="post">
|
<br/>
|
||||||
<table width="100%" border="0" cellspacing="1" cellpadding="4">
|
<form action="{{ getLink('characters') }}" method="post">
|
||||||
<tr><td bgcolor="{{ config.vdarkborder }}" class="white"><B>Search Character</B></TD></TR>
|
{% set title = 'Search Character' %}
|
||||||
<tr>
|
{% set tableClass = 'Table1' %}
|
||||||
<td bgcolor="{{ config.darkborder }}">
|
{% set background = config('darkborder') %}
|
||||||
<table border="0" cellpadding="1">
|
{% set content %}
|
||||||
<tr>
|
<table width="100%">
|
||||||
<td>Name:</td><td><input name="name" value="" size="29" maxlength="29"{% if autofocus %} autofocus{% endif %}></TD>
|
<tr>
|
||||||
<td>
|
<td style="vertical-align:middle" class="LabelV150">
|
||||||
{{ include('buttons.submit.html.twig') }}
|
Character Name:
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
<td style="width:170px">
|
||||||
</table>
|
<input style="width:165px" name="name" value="" size="29" maxlength="29"/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
<td>
|
||||||
</table>
|
{% set button_name = 'Submit' %}
|
||||||
|
{{ include('buttons.base.html.twig') }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
{% endset %}
|
||||||
|
{{ include('tables.headline.html.twig') }}
|
||||||
</form>
|
</form>
|
@@ -49,6 +49,7 @@
|
|||||||
{% include('buttons.base.html.twig') %}
|
{% include('buttons.base.html.twig') %}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{{ hook('HOOK_GUILDS_AFTER_MANAGE_BUTTON') }}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -61,6 +62,7 @@
|
|||||||
{{ hook('HOOK_GUILDS_AFTER_GUILD_INFORMATION') }}
|
{{ hook('HOOK_GUILDS_AFTER_GUILD_INFORMATION') }}
|
||||||
|
|
||||||
{% set title = 'Guild Members' %}
|
{% set title = 'Guild Members' %}
|
||||||
|
{% set background = config('lightborder') %}
|
||||||
{% set content %}
|
{% set content %}
|
||||||
<table style="width:100%;">
|
<table style="width:100%;">
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -151,6 +153,7 @@
|
|||||||
|
|
||||||
{{ hook('HOOK_GUILDS_AFTER_GUILD_MEMBERS') }}
|
{{ hook('HOOK_GUILDS_AFTER_GUILD_MEMBERS') }}
|
||||||
{% set title = 'Invited Characters' %}
|
{% set title = 'Invited Characters' %}
|
||||||
|
{% set background = config('lightborder') %}
|
||||||
{% set content %}
|
{% set content %}
|
||||||
<table style="width:100%;">
|
<table style="width:100%;">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@@ -66,7 +66,7 @@
|
|||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ player.link }}">
|
<a href="{{ player.link }}">
|
||||||
<span style="color: {% if player.online > 0 %}green{% else %}red{% endif %}">{{ player.name }}</span>
|
<span {% if setting('core.highscores_online_status') %}style="color: {% if player.online > 0 %}green{% else %}red{% endif %}"{% endif %}>{{ player.name }}</span>
|
||||||
</a>
|
</a>
|
||||||
{% if setting('core.highscores_vocation') %}
|
{% if setting('core.highscores_vocation') %}
|
||||||
<br/><small>{{ player.vocation }}</small>
|
<br/><small>{{ player.vocation }}</small>
|
||||||
@@ -94,8 +94,10 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
|
{% if setting('core.highscores_skills_box') or setting('core.highscores_vocation_box') %}
|
||||||
<td width="5%"></td>
|
<td width="5%"></td>
|
||||||
<td width="15%" valign="top" align="right">
|
<td width="15%" valign="top" align="right">
|
||||||
|
{% if setting('core.highscores_skills_box') %}
|
||||||
<table style="border: 0; width: 100%" cellpadding="4" cellspacing="1">
|
<table style="border: 0; width: 100%" cellpadding="4" cellspacing="1">
|
||||||
<tr bgcolor="{{ config.vdarkborder }}">
|
<tr bgcolor="{{ config.vdarkborder }}">
|
||||||
<td class="white"><B>Choose a skill</B></TD>
|
<td class="white"><B>Choose a skill</B></TD>
|
||||||
@@ -109,7 +111,8 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<br/>
|
<br/>
|
||||||
{% if config.highscores_vocation_box %}
|
{% endif %}
|
||||||
|
{% if setting('core.highscores_vocation_box') %}
|
||||||
<table border="0" width="100%" cellpadding="4" cellspacing="1">
|
<table border="0" width="100%" cellpadding="4" cellspacing="1">
|
||||||
<tr bgcolor="{{ config.vdarkborder }}">
|
<tr bgcolor="{{ config.vdarkborder }}">
|
||||||
<td class="white"><b>Choose a vocation</b></td>
|
<td class="white"><b>Choose a vocation</b></td>
|
||||||
@@ -126,5 +129,6 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 18px"></td>
|
<td style="width: 18px"></td>
|
||||||
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
9
system/templates/mail.account.2fa.email-code.html.twig
Normal file
9
system/templates/mail.account.2fa.email-code.html.twig
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Dear {{ config.lua.serverName}} player,
|
||||||
|
<br/><br/>
|
||||||
|
Your account is protected by email code authentication, and you requested a new email code:
|
||||||
|
<br/><br/>
|
||||||
|
<p>{{ code }}</p>
|
||||||
|
<br/>
|
||||||
|
Note that the code is only valid for 24 hours.
|
||||||
|
<br/><br/>
|
||||||
|
Kind Regards,
|
@@ -0,0 +1,5 @@
|
|||||||
|
Dear {{ config.lua.serverName}} player,<br/>
|
||||||
|
<br/>
|
||||||
|
A <strong>wrong two-factor authentication code</strong> was entered for your {{ config.lua.serverName}} account. If you simply mistyped the code, please try again.<br/>
|
||||||
|
<br/>
|
||||||
|
However, if this was <strong>not you</strong>, someone else may be trying to access your account. Since they already know your password, we strongly recommend that you <strong>change your password immediately</strong>.
|
@@ -1,25 +0,0 @@
|
|||||||
<br/>
|
|
||||||
<form action="{{ getLink('characters') }}" method=post>
|
|
||||||
<table width="100%" border="0" cellspacing="1" cellpadding="4">
|
|
||||||
<tr>
|
|
||||||
<td bgcolor="{{ config.vdarkborder }}" class="white">
|
|
||||||
<b>Search Character</b>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td bgcolor="{{ config.darkborder }}">
|
|
||||||
<table border="0" cellpadding="1">
|
|
||||||
<tr>
|
|
||||||
<td>Name:</td>
|
|
||||||
<td>
|
|
||||||
<input name="name" value=""size=29 maxlength=29>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ include('buttons.submit.html.twig') }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
@@ -1,39 +1,13 @@
|
|||||||
<table border="0" cellspacing="1" cellpadding="4" width="100%">
|
{% set onlineTTL = setting('core.online_cache_ttl') %}
|
||||||
<tr bgcolor="{{ config.vdarkborder }}">
|
{% if onlineTTL > 0 and cache.enabled() %}
|
||||||
<td class="white"><b>Server Status</b></td>
|
<small>*Note: Online List is updated every {{ onlineTTL > 1 ? ' ' ~ onlineTTL : '' }} minute{{ onlineTTL > 1 ? 's' : '' }}.</small>
|
||||||
</tr>
|
|
||||||
{% if players|length == 0 %}
|
|
||||||
<tr bgcolor="{{ config.darkborder }}"><td>Currently no one is playing on {{ config.lua.serverName }}.</td></tr></table>
|
|
||||||
{% else %}
|
|
||||||
<tr bgcolor="{{ config.darkborder }}">
|
|
||||||
<td>
|
|
||||||
{% if not status.online %}
|
|
||||||
Server is offline.<br/>
|
|
||||||
{% else %}
|
|
||||||
{% if setting('core.online_afk') %}
|
|
||||||
{% set players_count = players|length %}
|
|
||||||
{% set afk = players_count - status.players %}
|
|
||||||
{% if afk < 0 %}
|
|
||||||
{% set players_count = players_count + afk|abs %}
|
|
||||||
{% set afk = 0 %}
|
|
||||||
{% endif %}
|
|
||||||
Currently there are <b>{{ status.players }}</b> active and <b>{{ afk }}</b> AFK players.<br/>
|
|
||||||
Total number of players: <b>{{ players_count }}</b>.<br/>
|
|
||||||
{% else %}
|
|
||||||
Currently {{ players|length }} players are online.<br/>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
{% if setting('core.online_record') %}
|
|
||||||
{{ record }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<br/>
|
<br/>
|
||||||
{# vocation statistics #}
|
{% endif %}
|
||||||
{% if setting('core.online_vocations') %}
|
|
||||||
|
{# vocation statistics #}
|
||||||
|
{% if setting('core.online_vocations') %}
|
||||||
<br/>
|
<br/>
|
||||||
{% if setting('core.online_vocations_images') %}
|
{% if setting('core.online_vocations_images') %}
|
||||||
<table width="200" cellspacing="1" cellpadding="0" border="0" align="center">
|
<table width="200" cellspacing="1" cellpadding="0" border="0" align="center">
|
||||||
<tr bgcolor="{{ config.darkborder }}">
|
<tr bgcolor="{{ config.darkborder }}">
|
||||||
<td><img src="images/sorcerer.png" /></td>
|
<td><img src="images/sorcerer.png" /></td>
|
||||||
@@ -69,11 +43,13 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
<br/>
|
<br/>
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{# show skulls #}
|
<br/>
|
||||||
{% if setting('core.online_skulls') %}
|
|
||||||
|
{# show skulls #}
|
||||||
|
{% if setting('core.online_skulls') %}
|
||||||
<table width="100%" cellspacing="1">
|
<table width="100%" cellspacing="1">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="background: {{ config.darkborder }};" align="center">
|
<td style="background: {{ config.darkborder }};" align="center">
|
||||||
@@ -83,34 +59,114 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
{% set title = 'World Information' %}
|
||||||
|
{% set tableClass = 'Table3' %}
|
||||||
|
{% set background = config('darkborder') %}
|
||||||
|
{% set content %}
|
||||||
|
<table width="100%">
|
||||||
|
<tr>
|
||||||
|
<td class="LabelV150"><b>Status:</b></td>
|
||||||
|
<td>{% if not status.online %}Offline{% else %}Online{% endif %}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="LabelV150"><b>Players Online:</b></td>
|
||||||
|
<td>
|
||||||
|
{% if setting('core.online_afk') %}
|
||||||
|
{% set players_count = players|length %}
|
||||||
|
{% set afk = players_count - status.players %}
|
||||||
|
{% if afk < 0 %}
|
||||||
|
{% set players_count = players_count + afk|abs %}
|
||||||
|
{% set afk = 0 %}
|
||||||
|
{% endif %}
|
||||||
|
Currently there are <b>{{ status.players }}</b> active and <b>{{ afk }}</b> AFK players.<br/>
|
||||||
|
Total number of players: <b>{{ players_count }}</b>.<br/>
|
||||||
|
{% else %}
|
||||||
|
{{ players|length }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% if setting('core.online_record') and record|length > 0 %}
|
||||||
|
<tr>
|
||||||
|
<td class="LabelV150"><b>Online Record:</b></td>
|
||||||
|
<td>
|
||||||
|
{{ record }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<table border="0" cellspacing="1" cellpadding="4" width="100%">
|
<tr>
|
||||||
<tr bgcolor="{{ config.vdarkborder }}">
|
<td class="LabelV150"><b>Location Datacenter:</b></td>
|
||||||
|
<td>{{ setting('core.online_datacenter') }} <small>(Server date & time: - {{ "now"|date("d/m/Y H:i:s") }})</small></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="LabelV150"><b>PvP Type:</b></td>
|
||||||
|
<td>
|
||||||
|
{% set worldType = config('lua')['worldType']|lower %}
|
||||||
|
{% if worldType in ['pvp','2','normal','open','openpvp'] %}
|
||||||
|
Open PvP
|
||||||
|
{% elseif worldType in ['no-pvp','nopvp','non-pvp','nonpvp','1','safe','optional','optionalpvp'] %}
|
||||||
|
Optional PvP
|
||||||
|
{% elseif worldType in ['pvp-enforced','pvpenforced','pvp-enfo','pvpenfo','pvpe','enforced','enfo','3','war','hardcore','hardcorepvp'] %}
|
||||||
|
Hardcore PvP
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
{% endset %}
|
||||||
|
{% include 'tables.headline.html.twig' %}
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
{% set title = 'Players Online' %}
|
||||||
|
{% set tableClass = 'Table2' %}
|
||||||
|
{% set content %}
|
||||||
|
<table width="100%">
|
||||||
|
<tr class="LabelH" style="position: relative; z-index: 20;">
|
||||||
{% if setting('core.account_country') %}
|
{% if setting('core.account_country') %}
|
||||||
<td width="11px"><a href="{{ getLink('online?order=country') }}" class="white">#</A></td>
|
<td width="11px"><a href="{{ getLink('online')}}?order=country_{{ order == 'country_asc' ? 'desc' : 'asc' }}">#  </a>
|
||||||
|
</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if setting('core.online_outfit') %}
|
{% if setting('core.online_outfit') %}
|
||||||
<td class="white"><b>Outfit</b></td>
|
<td><b>Outfit</b></td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<td width="60%"><a href="{{ getLink('online?order=name') }}" class="white">Name</A></td>
|
<td style="text-align:left; width:50%">Name  
|
||||||
<td width="20%"><a href="{{ getLink('online?order=level') }}" class="white">Level</A></td>
|
<small style="font-weight:normal">[<a href="{{ getLink('online')}}?order=name_{{ order == 'name_asc' ? 'desc' : 'asc' }}">sort</a>]</small>
|
||||||
<td width="20%"><a href="{{ getLink('online?order=vocation') }}" class="white">Vocation</td>
|
<img class="sortarrow" src="images/{{ order == 'name_asc' ? 'order_desc' : (order == 'name_desc' ? 'order_asc' : 'news/blank') }}.gif"/></td>
|
||||||
|
<td style="text-align:left;width:30%">Level  
|
||||||
|
<small style="font-weight:normal">[<a href="{{ getLink('online')}}?order=level_{{ order == 'level_asc' ? 'desc' : 'asc' }}">sort</a>]</small>
|
||||||
|
<img class="sortarrow" src="images/{{ order == 'level_asc' ? 'order_desc' : (order == 'level_desc' ? 'order_asc' : 'news/blank') }}.gif"/>
|
||||||
|
</td>
|
||||||
|
<td style="text-align:left;width:50%">Vocation  
|
||||||
|
<small style="font-weight:normal">[<a href="{{ getLink('online')}}?order=vocation_{{ order == 'vocation_asc' ? 'desc' : 'asc' }}">sort</a>]</small>
|
||||||
|
<img class="sortarrow" src="images/{{ order == 'vocation_asc' ? 'order_desc' : (order == 'vocation_desc' ? 'order_asc' : 'news/blank') }}.gif"/>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% set i = 0 %}
|
{% set i = 0 %}
|
||||||
{% for player in players %}
|
{% for player in players %}
|
||||||
{% set i = i + 1 %}
|
{% set i = i + 1 %}
|
||||||
<tr bgcolor="{{ getStyle(i) }}">
|
|
||||||
{% if setting('core.account_country') %}
|
<tr style="background: {{ getStyle(i) }}; text-align: right; height: 40px;">
|
||||||
<td>{{ player.country_image|raw }}</td>
|
{% if setting('core.account_country') %}
|
||||||
{% endif %}
|
<td>{{ player.country_image|raw }}</td>
|
||||||
{% if setting('core.online_outfit') %}
|
{% endif %}
|
||||||
<td width="5%"><img style="position:absolute;margin-top:{% if player.player.looktype in setting('core.outfit_images_wrong_looktypes') %}-20px;margin-left:-0px;{% else %}-45px;margin-left:-25px;{% endif %}" src="{{ player.outfit }}" alt="player outfit"/></td>
|
|
||||||
{% endif %}
|
{% if setting('core.online_outfit') %}
|
||||||
<td>{{ player.name|raw }}{{ player.skull }}</td>
|
<td width="5%"><img style="position:absolute;margin-top:-48px;margin-left:-70px;" src="{{ player.outfit }}" alt="player outfit"/></td>
|
||||||
<td>{{ player.level }}</td>
|
{% endif %}
|
||||||
<td>{{ player.vocation }}</td>
|
|
||||||
|
<td style="width:70%; text-align:left">
|
||||||
|
{{ player.name|raw }}{{ player.skull }}
|
||||||
|
</td>
|
||||||
|
<td style="width:10%">{{ player.level }}</td>
|
||||||
|
<td style="width:20%">{{ player.vocation }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
{% endif %}
|
{% endset %}
|
||||||
|
{{ include('tables.headline.html.twig') }}
|
||||||
|
@@ -18,13 +18,14 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<div style="text-align:center">
|
<div style="text-align:center">
|
||||||
<table border="0" cellspacing="0" cellpadding="0">
|
<table border="0" cellspacing="0" cellpadding="0">
|
||||||
<form action="{{ getLink('account/manage') }}" method="post">
|
<tr>
|
||||||
<tr>
|
<td style="border:0;">
|
||||||
<td style="border:0px;">
|
<form action="{{ getLink('account/manage') }}" method="post">
|
||||||
|
{{ csrf() }}
|
||||||
{{ include('buttons.back.html.twig') }}
|
{{ include('buttons.back.html.twig') }}
|
||||||
</td>
|
</form>
|
||||||
</tr>
|
</td>
|
||||||
</form>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
selector: "#editor",
|
selector: "#editor",
|
||||||
content_css: '{{ constant('ADMIN_URL') }}template/style.css',
|
content_css: '{{ constant('ADMIN_URL') }}template/style.css',
|
||||||
theme: "silver",
|
theme: "silver",
|
||||||
plugins: 'preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help code emoticons',
|
plugins: 'preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help code emoticons',
|
||||||
toolbar1: 'formatselect | bold italic strikethrough forecolor backcolor | emoticons link | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat code',
|
toolbar1: 'formatselect | bold italic strikethrough forecolor backcolor | emoticons link | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat code',
|
||||||
resize: 'both',
|
resize: 'both',
|
||||||
image_advtab: true,
|
image_advtab: true,
|
||||||
@@ -23,6 +23,8 @@
|
|||||||
{title: 'Colored Table', value: 'myaac-table'},
|
{title: 'Colored Table', value: 'myaac-table'},
|
||||||
],
|
],
|
||||||
|
|
||||||
|
license_key: 'gpl',
|
||||||
|
|
||||||
setup: function (ed) {
|
setup: function (ed) {
|
||||||
ed.on('NodeChange', function (e) {
|
ed.on('NodeChange', function (e) {
|
||||||
if (ed.getContent() !== lastContent) {
|
if (ed.getContent() !== lastContent) {
|
||||||
|
@@ -36,7 +36,11 @@ $twig->addExtension(new MyAAC\Twig\Extension\TypeCastingExtension());
|
|||||||
|
|
||||||
$filter = new TwigFilter('timeago', function ($datetime) {
|
$filter = new TwigFilter('timeago', function ($datetime) {
|
||||||
|
|
||||||
$time = time() - strtotime($datetime);
|
if (!is_int($datetime)) {
|
||||||
|
$datetime = strtotime($datetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
$time = time() - $datetime;
|
||||||
|
|
||||||
$units = array (
|
$units = array (
|
||||||
31536000 => 'year',
|
31536000 => 'year',
|
||||||
@@ -152,3 +156,5 @@ $twig->addFilter($filter);
|
|||||||
unset($function, $filter);
|
unset($function, $filter);
|
||||||
|
|
||||||
$hooks->trigger(HOOK_TWIG, ['twig' => $twig, 'twig_loader' => $twig_loader]);
|
$hooks->trigger(HOOK_TWIG, ['twig' => $twig, 'twig_loader' => $twig_loader]);
|
||||||
|
|
||||||
|
$twig->addGlobal('cache', $cache);
|
||||||
|
@@ -1,12 +1,18 @@
|
|||||||
<?php
|
<?php
|
||||||
$config['menu_default_links_color'] = '#ffffff';
|
$config['menu_default_links_color'] = '#ffffff';
|
||||||
|
|
||||||
$config['menu_categories'] = array(
|
// max 7 menus for kathrine
|
||||||
MENU_CATEGORY_NEWS => array('id' => 'news', 'name' => 'Latest News'),
|
$config['menu_categories'] = [
|
||||||
MENU_CATEGORY_ACCOUNT => array('id' => 'account', 'name' => 'Account'),
|
MENU_CATEGORY_NEWS => ['id' => 'news', 'name' => 'Latest News'],
|
||||||
MENU_CATEGORY_COMMUNITY => array('id' => 'community', 'name' => 'Community'),
|
// you can add custom menu by uncommenting this
|
||||||
MENU_CATEGORY_LIBRARY => array('id' => 'library', 'name' => 'Library'),
|
// after doing it, go to admin panel -> Menus and add your entries for this category
|
||||||
MENU_CATEGORY_SHOP => array('id' => 'shops', 'name' => 'Shop')
|
// tip: you can move it up/down to show it on specific position
|
||||||
);
|
//7 => array('id' => 'testing', 'name' => 'Test Menu 1'),
|
||||||
|
//8 => array('id' => 'testing2', 'name' => 'Test Menu 2'),
|
||||||
|
MENU_CATEGORY_ACCOUNT => ['id' => 'account', 'name' => 'Account'],
|
||||||
|
MENU_CATEGORY_COMMUNITY => ['id' => 'community', 'name' => 'Community'],
|
||||||
|
MENU_CATEGORY_LIBRARY => ['id' => 'library', 'name' => 'Library'],
|
||||||
|
MENU_CATEGORY_SHOP => ['id' => 'shops', 'name' => 'Shop']
|
||||||
|
];
|
||||||
|
|
||||||
$config['menus'] = require __DIR__ . '/menus.php';
|
$config['menus'] = require __DIR__ . '/menus.php';
|
||||||
|
@@ -1,42 +1,40 @@
|
|||||||
<?php
|
<?php
|
||||||
$menus = get_template_menus();
|
function get_template_pages($category): array
|
||||||
|
{
|
||||||
function get_template_pages($category) {
|
|
||||||
global $menus;
|
global $menus;
|
||||||
|
|
||||||
$ret = array();
|
$ret = array();
|
||||||
foreach($menus[$category] as $menu) {
|
foreach($menus[$category] ?? [] as $menu) {
|
||||||
$ret[] = $menu['link'];
|
$ret[] = $menu['link'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
var category = '<?php
|
let category = '<?php
|
||||||
if(strpos(URI, 'subtopic=') !== false) {
|
if(str_contains(URI, 'subtopic=')) {
|
||||||
$tmp = array($_REQUEST['subtopic']);
|
$tmp = [$_REQUEST['subtopic']];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$tmp = URI;
|
$tmp = URI;
|
||||||
if(empty($tmp)) {
|
if(empty($tmp)) {
|
||||||
$tmp = array('news');
|
$tmp = ['news'];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$tmp = explode('/', URI);
|
$tmp = explode('/', URI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(in_array($tmp[0], get_template_pages(MENU_CATEGORY_NEWS)))
|
foreach (config('menu_categories') as $id => $info) {
|
||||||
echo 'news';
|
$templatePages = get_template_pages($id);
|
||||||
elseif(in_array($tmp[0], get_template_pages(MENU_CATEGORY_LIBRARY)))
|
|
||||||
echo 'library';
|
if ($id == MENU_CATEGORY_ACCOUNT) {
|
||||||
elseif(in_array($tmp[0], get_template_pages(MENU_CATEGORY_COMMUNITY)))
|
$templatePages = array_merge($templatePages, ['account']);
|
||||||
echo 'community';
|
}
|
||||||
elseif(in_array($tmp[0], array_merge(get_template_pages(MENU_CATEGORY_ACCOUNT), array('account'))))
|
|
||||||
echo 'account';
|
if (in_array($tmp[0], $templatePages)) {
|
||||||
elseif(in_array($tmp[0], get_template_pages(MENU_CATEGORY_SHOP)))
|
echo $info['id'];
|
||||||
echo 'shops';
|
break;
|
||||||
else {
|
}
|
||||||
echo 'news';
|
|
||||||
}
|
}
|
||||||
?>';
|
?>';
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
var list = new Array();
|
var list = new Array();
|
||||||
{% set i = 0 %}
|
{% set i = 0 %}
|
||||||
{% for cat in categories %}
|
{% for id, cat in config('menu_categories') %}
|
||||||
{% if cat.id != 'shops' or setting('core.gifts_system') %}
|
{% if (cat.id != 'shops' or setting('core.gifts_system')) and menus[id]|length > 0 %}
|
||||||
list[{{ i }}] = '{{ cat.id }}';
|
list[{{ i }}] = '{{ cat.id }}';
|
||||||
|
{% set i = i + 1 %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% set i = i + 1 %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
function initMenu()
|
function initMenu()
|
||||||
|
@@ -27,11 +27,13 @@ body
|
|||||||
|
|
||||||
#tabs
|
#tabs
|
||||||
{
|
{
|
||||||
width: 580px;
|
width: 99%;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
background: url('images/tabs-bg.png') no-repeat;
|
background: url('images/tabs-bg.png') no-repeat;
|
||||||
float: left;
|
|
||||||
padding-left: 200px;
|
padding-left: 200px;
|
||||||
|
position: relative;
|
||||||
|
display: inline-flex;
|
||||||
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#tabs .tab
|
#tabs .tab
|
||||||
@@ -453,6 +455,27 @@ a:hover
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
.LabelV120 {
|
||||||
|
font-weight: bold;
|
||||||
|
padding-right: 10px;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: top;
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
.LabelV150 {
|
||||||
|
font-weight: bold;
|
||||||
|
padding-right: 10px;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: top;
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
.LabelV200 {
|
||||||
|
font-weight: bold;
|
||||||
|
padding-right: 10px;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: top;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
.LabelH {
|
.LabelH {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
|
@@ -8,7 +8,9 @@ defined('MYAAC') or die('Direct access not allowed!');
|
|||||||
<link rel="stylesheet" href="<?php echo $template_path; ?>/style.css" type="text/css" />
|
<link rel="stylesheet" href="<?php echo $template_path; ?>/style.css" type="text/css" />
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
<?php
|
<?php
|
||||||
$twig->display('menu.js.html.twig', array('categories' => $config['menu_categories']));
|
$menus = get_template_menus();
|
||||||
|
|
||||||
|
$twig->display('menu.js.html.twig', ['menus' => $menus]);
|
||||||
?>
|
?>
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="tools/basic.js"></script>
|
<script type="text/javascript" src="tools/basic.js"></script>
|
||||||
@@ -28,11 +30,24 @@ defined('MYAAC') or die('Direct access not allowed!');
|
|||||||
<div id="header"></div>
|
<div id="header"></div>
|
||||||
<!-- End -->
|
<!-- End -->
|
||||||
|
|
||||||
|
<!-- Custom Style for #tabs -->
|
||||||
|
<?php
|
||||||
|
$menusCount = count($menus);
|
||||||
|
$tabsStyle = '';
|
||||||
|
if ($menusCount > 6) {
|
||||||
|
$tabsStyle .= 'padding-left: 4px;';
|
||||||
|
$tabsStyle .= 'padding-right: 12px;';
|
||||||
|
}
|
||||||
|
elseif ($menusCount > 5) {
|
||||||
|
$tabsStyle .= 'padding-left: 90px;';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
<!-- Menu Section -->
|
<!-- Menu Section -->
|
||||||
<div id="tabs">
|
<div id="tabs" style="<?= $tabsStyle; ?>">
|
||||||
<?php
|
<?php
|
||||||
foreach($config['menu_categories'] as $id => $cat) {
|
foreach($config['menu_categories'] as $id => $cat) {
|
||||||
if($id != MENU_CATEGORY_SHOP || $config['gifts_system']) { ?>
|
if (($id != MENU_CATEGORY_SHOP || $config['gifts_system']) && isset($menus[$id])) { ?>
|
||||||
<span id="<?php echo $cat['id']; ?>" onclick="menuSwitch('<?php echo $cat['id']; ?>');"><?php echo $cat['name']; ?></span>
|
<span id="<?php echo $cat['id']; ?>" onclick="menuSwitch('<?php echo $cat['id']; ?>');"><?php echo $cat['name']; ?></span>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
|
@@ -11,13 +11,14 @@
|
|||||||
<td width="100%"></td>
|
<td width="100%"></td>
|
||||||
<td>
|
<td>
|
||||||
<table border="0" cellspacing="0" cellpadding="0" >
|
<table border="0" cellspacing="0" cellpadding="0" >
|
||||||
<form action="{{ getLink('account/logout') }}" method="post" >
|
<tr>
|
||||||
<tr>
|
<td style="border:0;">
|
||||||
<td style="border:0px;">
|
<form action="{{ getLink('account/logout') }}" method="post" >
|
||||||
|
{{ csrf() }}
|
||||||
{{ include('buttons.logout.html.twig') }}
|
{{ include('buttons.logout.html.twig') }}
|
||||||
</td>
|
</form>
|
||||||
</tr>
|
</td>
|
||||||
</form>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -59,13 +60,14 @@
|
|||||||
</table>
|
</table>
|
||||||
<div style="text-align:center">
|
<div style="text-align:center">
|
||||||
<table border="0" cellspacing="0" cellpadding="0" style="margin-left: auto; margin-right: auto;">
|
<table border="0" cellspacing="0" cellpadding="0" style="margin-left: auto; margin-right: auto;">
|
||||||
<form action="{{ getLink('account/register') }}" method="post">
|
<tr>
|
||||||
<tr>
|
<td style="border:0;">
|
||||||
<td style="border:0;">
|
<form action="{{ getLink('account/register') }}" method="post">
|
||||||
|
{{ csrf() }}
|
||||||
{{ include('buttons.register_account.html.twig') }}
|
{{ include('buttons.register_account.html.twig') }}
|
||||||
</td>
|
</form>
|
||||||
</tr>
|
</td>
|
||||||
</form>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -94,13 +96,14 @@
|
|||||||
</table>
|
</table>
|
||||||
<div style="text-align:center">
|
<div style="text-align:center">
|
||||||
<table border="0" cellspacing="0" cellpadding="0">
|
<table border="0" cellspacing="0" cellpadding="0">
|
||||||
<form action="{{ getLink('account/change-email') }}" method="post">
|
<tr>
|
||||||
<tr>
|
<td style="border:0;">
|
||||||
<td style="border:0px;">
|
<form action="{{ getLink('account/change-email') }}" method="post">
|
||||||
|
{{ csrf() }}
|
||||||
{{ include('buttons.edit.html.twig') }}
|
{{ include('buttons.edit.html.twig') }}
|
||||||
</td>
|
</form>
|
||||||
</tr>
|
</td>
|
||||||
</form>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -177,26 +180,29 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<table border="0" cellspacing="0" cellpadding="0">
|
<table border="0" cellspacing="0" cellpadding="0">
|
||||||
<form action="{{ getLink('account/change-password') }}" method="post">
|
<tr>
|
||||||
<tr>
|
<td style="border:0;" >
|
||||||
<td style="border:0px;" >
|
<form action="{{ getLink('account/change-password') }}" method="post">
|
||||||
|
{{ csrf() }}
|
||||||
{{ include('buttons.change_password.html.twig') }}
|
{{ include('buttons.change_password.html.twig') }}
|
||||||
</td>
|
</form>
|
||||||
</tr>
|
</td>
|
||||||
</form>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<table border="0" cellspacing="0" cellpadding="0">
|
<table border="0" cellspacing="0" cellpadding="0">
|
||||||
<form action="{{ getLink('account/change-email') }}" method="post">
|
<tr>
|
||||||
<tr>
|
<td style="border:0;">
|
||||||
<td style="border:0px;">
|
<form action="{{ getLink('account/change-email') }}" method="post">
|
||||||
|
{{ csrf() }}
|
||||||
|
|
||||||
<input type="hidden" name="newemail" value=""/>
|
<input type="hidden" name="newemail" value=""/>
|
||||||
<input type="hidden" name="newemaildate" value="0">
|
<input type="hidden" name="newemaildate" value="0">
|
||||||
{{ include('buttons.change_email.html.twig') }}
|
{{ include('buttons.change_email.html.twig') }}
|
||||||
</td>
|
</form>
|
||||||
</tr>
|
</td>
|
||||||
</form>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
<td width="100%"></td>
|
<td width="100%"></td>
|
||||||
@@ -204,13 +210,14 @@
|
|||||||
{% if recovery_key is empty %}
|
{% if recovery_key is empty %}
|
||||||
<td>
|
<td>
|
||||||
<table border="0" cellspacing="0" cellpadding="0">
|
<table border="0" cellspacing="0" cellpadding="0">
|
||||||
<form action="{{ getLink('account/register') }}" method="post">
|
<tr>
|
||||||
<tr>
|
<td style="border:0;">
|
||||||
<td style="border:0px;">
|
<form action="{{ getLink('account/register') }}" method="post">
|
||||||
|
{{ csrf() }}
|
||||||
{{ include('buttons.register_account.html.twig') }}
|
{{ include('buttons.register_account.html.twig') }}
|
||||||
</td>
|
</form>
|
||||||
</tr>
|
</td>
|
||||||
</form>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -258,13 +265,14 @@
|
|||||||
</td>
|
</td>
|
||||||
<td align=right>
|
<td align=right>
|
||||||
<table border="0" cellspacing="0" cellpadding="0">
|
<table border="0" cellspacing="0" cellpadding="0">
|
||||||
<form action="{{ getLink('account/change-info') }}" method="post">
|
<tr>
|
||||||
<tr>
|
<td style="border:0;">
|
||||||
<td style="border:0px;">
|
<form action="{{ getLink('account/change-info') }}" method="post">
|
||||||
|
{{ csrf() }}
|
||||||
{{ include('buttons.edit.html.twig') }}
|
{{ include('buttons.edit.html.twig') }}
|
||||||
</td>
|
</form>
|
||||||
</tr>
|
</td>
|
||||||
</form>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -282,6 +290,9 @@
|
|||||||
{% endset %}
|
{% endset %}
|
||||||
{% include 'tables.headline.html.twig' %}
|
{% include 'tables.headline.html.twig' %}
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
{{ include('account.2fa.main.html.twig') }}
|
||||||
|
|
||||||
{{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS') }}
|
{{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS') }}
|
||||||
<a name="Account+Logs" ></a>
|
<a name="Account+Logs" ></a>
|
||||||
<div class="TopButtonContainer">
|
<div class="TopButtonContainer">
|
||||||
@@ -398,8 +409,9 @@
|
|||||||
<td>
|
<td>
|
||||||
<table border="0" cellspacing="0" cellpadding="0" >
|
<table border="0" cellspacing="0" cellpadding="0" >
|
||||||
<tr>
|
<tr>
|
||||||
<td style="border:0px;">
|
<td style="border:0;">
|
||||||
<form action="{{ getLink('account/characters/create') }}" method="post" >
|
<form action="{{ getLink('account/characters/create') }}" method="post" >
|
||||||
|
{{ csrf() }}
|
||||||
{{ include('buttons.create_character.html.twig') }}
|
{{ include('buttons.create_character.html.twig') }}
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
@@ -410,8 +422,9 @@
|
|||||||
<td>
|
<td>
|
||||||
<table border="0" cellspacing="0" cellpadding="0" >
|
<table border="0" cellspacing="0" cellpadding="0" >
|
||||||
<tr>
|
<tr>
|
||||||
<td style="border:0px;">
|
<td style="border:0;">
|
||||||
<form action="{{ getLink('account/characters/change-name') }}" method="post" >
|
<form action="{{ getLink('account/characters/change-name') }}" method="post" >
|
||||||
|
{{ csrf() }}
|
||||||
{{ include('buttons.change_name.html.twig') }}
|
{{ include('buttons.change_name.html.twig') }}
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
@@ -423,8 +436,9 @@
|
|||||||
<td>
|
<td>
|
||||||
<table border="0" cellspacing="0" cellpadding="0" >
|
<table border="0" cellspacing="0" cellpadding="0" >
|
||||||
<tr>
|
<tr>
|
||||||
<td style="border:0px;">
|
<td style="border:0;">
|
||||||
<form action="{{ getLink('account/characters/change-sex') }}" method="post">
|
<form action="{{ getLink('account/characters/change-sex') }}" method="post">
|
||||||
|
{{ csrf() }}
|
||||||
{{ include('buttons.change_sex.html.twig') }}
|
{{ include('buttons.change_sex.html.twig') }}
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
@@ -436,8 +450,9 @@
|
|||||||
<td>
|
<td>
|
||||||
<table border="0" cellspacing="0" cellpadding="0">
|
<table border="0" cellspacing="0" cellpadding="0">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="border: 0px;">
|
<td style="border: 0;">
|
||||||
<form action="{{ getLink('account/characters/delete') }}" method="post">
|
<form action="{{ getLink('account/characters/delete') }}" method="post">
|
||||||
|
{{ csrf() }}
|
||||||
{{ include('buttons.delete_character.html.twig') }}
|
{{ include('buttons.delete_character.html.twig') }}
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
@@ -451,4 +466,7 @@
|
|||||||
</table>
|
</table>
|
||||||
{% endset %}
|
{% endset %}
|
||||||
{% include 'tables.headline.html.twig' %}
|
{% include 'tables.headline.html.twig' %}
|
||||||
<br/><br/>
|
<br/>
|
||||||
|
{{ hook('HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS') }}
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
@@ -1446,6 +1446,27 @@ img {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
.LabelV120 {
|
||||||
|
font-weight: bold;
|
||||||
|
padding-right: 10px;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: top;
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
.LabelV150 {
|
||||||
|
font-weight: bold;
|
||||||
|
padding-right: 10px;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: top;
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
.LabelV200 {
|
||||||
|
font-weight: bold;
|
||||||
|
padding-right: 10px;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: top;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
.LabelH {
|
.LabelH {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<div id="CurrentPollBox" class="Themebox" style="background-image:url({{ template_path }}/images/themeboxes/current-poll/currentpollbox.gif);">
|
<div id="CurrentPollBox" class="Themebox" style="background-image:url({{ template_path }}/images/themeboxes/current-poll/currentpollbox.gif);">
|
||||||
<div id="CurrentPollText">{{ poll.question }}</div>
|
<div id="CurrentPollText">{{ poll.question }}</div>
|
||||||
<a class="ThemeboxButton" href="{{ getLink('polls') }}/{{ poll.id }}" onMouseOver="MouseOverBigButton(this);" onMouseOut="MouseOutBigButton(this);" style="background-image:url({{ template_path }}/images/global/buttons/sbutton.gif);"><div class="BigButtonOver" style="background-image:url({{ template_path }}/images/global/buttons/sbutton_over.gif);"></div><div class="ButtonText" style="background-image:url({{ template_path }}/images/global/buttons/_sbutton_votenow.gif);"></div>
|
<a class="ThemeboxButton" href="{{ getLink('polls') }}?ìd={{ poll.id }}" onMouseOver="MouseOverBigButton(this);" onMouseOut="MouseOutBigButton(this);" style="background-image:url({{ template_path }}/images/global/buttons/sbutton.gif);"><div class="BigButtonOver" style="background-image:url({{ template_path }}/images/global/buttons/sbutton_over.gif);"></div><div class="ButtonText" style="background-image:url({{ template_path }}/images/global/buttons/_sbutton_votenow.gif);"></div>
|
||||||
</a>
|
</a>
|
||||||
<div class="Bottom" style="background-image:url({{ template_path }}/images/general/box-bottom.gif);"></div>
|
<div class="Bottom" style="background-image:url({{ template_path }}/images/general/box-bottom.gif);"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -164,6 +164,10 @@ if(isset($config['boxes']))
|
|||||||
function InitializeMenu()
|
function InitializeMenu()
|
||||||
{
|
{
|
||||||
for(menuItemName in menu[0]) {
|
for(menuItemName in menu[0]) {
|
||||||
|
if (!document.getElementById(menuItemName+"_Submenu")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(menu[0][menuItemName] == "0") {
|
if(menu[0][menuItemName] == "0") {
|
||||||
document.getElementById(menuItemName+"_Submenu").style.visibility = "hidden";
|
document.getElementById(menuItemName+"_Submenu").style.visibility = "hidden";
|
||||||
document.getElementById(menuItemName+"_Submenu").style.display = "none";
|
document.getElementById(menuItemName+"_Submenu").style.display = "none";
|
||||||
@@ -454,7 +458,7 @@ foreach($config['menu_categories'] as $id => $cat) {
|
|||||||
|
|
||||||
foreach($config['boxes'] as $box) {
|
foreach($config['boxes'] as $box) {
|
||||||
/** @var string $template_name */
|
/** @var string $template_name */
|
||||||
$file = TEMPLATES . $template_name . '/boxes/' . $box . '.php';
|
$file = __DIR__ . '/boxes/' . $box . '.php';
|
||||||
if(file_exists($file)) {
|
if(file_exists($file)) {
|
||||||
include($file); ?>
|
include($file); ?>
|
||||||
<?php
|
<?php
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td style="border:0;">
|
<td style="border:0;">
|
||||||
<form action="{{ getLink('account/manage') }}" method="post">
|
<form action="{{ getLink('account/manage') }}" method="post">
|
||||||
|
{{ csrf() }}
|
||||||
{{ include('buttons.back.html.twig') }}
|
{{ include('buttons.back.html.twig') }}
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
|
Reference in New Issue
Block a user