Compare commits

..

120 Commits

Author SHA1 Message Date
slawkens
8ec08b5a61 This is always true 2023-11-11 08:41:40 +01:00
slawkens
19346efc38 More info to confirm dialog 2023-11-11 08:38:15 +01:00
slawkens
c9d5c6cfd7 Add new changelog link 2023-11-11 08:37:32 +01:00
slawkens
4461c03d48 Fix changelog link 2023-11-11 08:33:44 +01:00
slawkens
60c7ef2391 Fix news type 2023-11-11 08:32:55 +01:00
slawkens
d6c35bcbb5 Formatting 2023-11-11 08:28:00 +01:00
slawkens
4e87e7e9dc clear_cache & maintenance csrf 2023-11-11 08:27:48 +01:00
slawkens
08a19158b3 Fix new page/news links 2023-11-11 08:12:02 +01:00
slawkens
9a306886fb Update mailer.php 2023-11-11 08:02:02 +01:00
slawkens
719c542757 add info function, same as note($message) 2023-11-11 08:01:58 +01:00
slawkens
1ed24afc7d Move definitions 2023-11-11 08:01:39 +01:00
slawkens
66479e64ed Plugins csrf 2023-11-11 07:53:24 +01:00
slawkens
4e26f07ab6 Menus: better csrf + add success message on reset colors 2023-11-11 07:41:43 +01:00
slawkens
13e6eb5666 Admin panel: Pages csrf 2023-11-11 07:37:21 +01:00
slawkens
56306dfb0a Use admin.links instead 2023-11-11 07:22:58 +01:00
slawkens
f27172691c Refactor admin newses + add csrf 2023-11-11 07:22:43 +01:00
slawkens
5578dbaa83 news/id route 2023-11-11 06:31:28 +01:00
slawkens
549c08c096 Admin Panel: changelogs csrf protection 2023-11-11 06:08:09 +01:00
slawkens
0127a4f417 Fix token generate 2023-11-11 06:07:33 +01:00
slawkens
08074d8d4f Merge branch 'develop' into feature/csrf 2023-11-11 05:40:17 +01:00
slawkens
a04fbde607 Fix highscores error 2023-11-09 20:32:20 +01:00
slawkens
9d119b6279 This is more error tolerant 2023-11-07 22:15:23 +01:00
slawkens
7dd9b7764a Update common.php 2023-11-07 22:01:47 +01:00
slawkens
3297a7c51a Better https detection 2023-11-07 22:01:43 +01:00
slawkens
4a430ae9db Fix display ban info on account page
https://otland.net/threads/myacc-bans-display-problem.286825/
2023-11-02 22:06:14 +01:00
Kamil Grzechulski
26a80e0741 fix: password2 variable refactor to correct name (#237) 2023-10-06 07:52:21 +02:00
slawkens
3b9feaf3bd My fault 2023-09-26 22:03:30 +02:00
slawkens
21bff97137 Add additional cache keys to clear function 2023-09-26 21:52:05 +02:00
slawkens
a2a273cde2 Twig_SimpleFilter is deprecated 2023-09-22 16:21:52 +02:00
slawkens
fc5635bad3 spaceless twig tag is deprecated as well 2023-09-22 16:19:56 +02:00
slawkens
e01a44f352 Update .editorconfig 2023-09-16 14:40:19 +02:00
slawkens
855b05b15f Fix class names 2023-09-16 11:45:40 +02:00
slawkens
198cc5a09d Cosmetics 2023-09-16 11:30:35 +02:00
slawkens
3e7cbbb63b Merge branch 'develop' into feature/csrf 2023-09-16 11:09:34 +02:00
slawkens
b3991a8e78 Add HOOK_TWIG. Also moved Hooks loading to init.php
For adding twig functions & filters by plugins
2023-09-16 11:07:38 +02:00
slawkens
8e3a71b36b Merge branch 'develop' into feature/csrf 2023-09-16 10:25:49 +02:00
slawkens
0ac0f4e7a8 Fixes 2023-09-16 10:22:10 +02:00
slawkens
e9f155fb49 Fix XSS in players editor 2023-09-16 10:21:18 +02:00
slawkens
55b5e3b600 Fix XSS in accounts editor 2023-09-16 10:21:18 +02:00
slawkens
08339fe8b6 Fix XSS in tibiacom template - subtopic 2023-09-16 10:21:17 +02:00
slawkens
89c2e84bff Fix alert class name 2023-09-16 09:24:10 +02:00
slawkens
0e33fd103c feature: csrf protection 2023-09-16 09:23:51 +02:00
slawkens
046c0b5cf4 Fix alert class name 2023-09-16 07:12:04 +02:00
slawkens
f76615e59b Fix getGuildLogoById 2023-09-16 05:54:41 +02:00
slawkens
4c4089a155 Quotes & const 2023-09-12 12:11:49 +02:00
slawkens
2d02d8d8b3 Fix news delete message part 2 2023-09-12 12:09:39 +02:00
slawkens
95b1460b13 Fix news delete message 2023-09-12 12:08:09 +02:00
slawkens
673e40350a Small adjustment to menus install 2023-09-12 11:42:03 +02:00
slawkens
f7cbe5170d set display quest default to false 2023-09-11 16:16:38 +02:00
slawkens
619b8ba4a0 Fix creatures datatable 2023-09-03 21:33:41 +02:00
slawkens
8c3b73ca9e Add account logs to admin panel accounts editor 2023-09-03 21:18:58 +02:00
slawkens
d90810cf84 Add latest clients versions 2023-08-31 14:20:24 +02:00
slawkens
fd25e6e881 Fix highscores country box to be hidden 2023-08-31 14:08:02 +02:00
slawkens
63e69c97b7 Fix login.php @gpedro <3 2023-08-31 14:01:30 +02:00
slawkens
574e35ba35 Fix: forgot to remove those menu items 2023-08-31 13:49:32 +02:00
slawkens
09627bdb1e Linux is case-sensitive! 2023-08-31 11:03:36 +02:00
Slawomir Boczek
5f10773189 feature: plugin cronjobs (#215) 2023-08-31 08:33:32 +02:00
slawkens
8a3986932d My fault was commenting this 2023-08-25 17:13:21 +02:00
slawkens
9e2a87f448 Add forgotten prefix for some settings 2023-08-25 17:09:31 +02:00
slawkens
0746708743 Reviewed some settings again, fixing many glitches 2023-08-24 17:20:32 +02:00
slawkens
3ef53aff6c Allow hooks to be prefixed with HOOK_ 2023-08-23 11:58:03 +02:00
slawkens
f43a5d1221 Option to disable settings saving with hooks
for next.my-aac.org
2023-08-23 11:57:37 +02:00
slawkens
43353b4f53 Update .gitattributes 2023-08-22 13:19:03 +02:00
Gabriel Pedro
a692607c5e feat: replace POT Query Builder to Eloquent ORM (#230)
* wip

* wip

* wip

* wip

* wip

* fix: reusing pdo connection from pot

* wip

* wip

* wip

* wip

* move files

In future, all classes will be in src/ folder

* Replace namespace name, for future

* Remove duplicated exception

* Fix towns from db

* Fix spells page

* Add default FAQ question + FAQ model

* feat: reset colors in menus

* Add confirm + save button at the top (menus)

* Do not insert duplicated FAQ on install

* Refactor install menus

* Fix changelogs showing

* Fix menu update, only with specified template name

* Fix account create -> missing compat

* Fix bans_per_page

* banned_by is player_id. type = 2 is namelock in tfs 0.3

* Add getPlayerNameById, fix getPlayerNameByAccount

* Change link name

* Order by lastlogin

* fix: query optimize

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Refactor notepad.php, class was useless

* This is showing error, if the updated rows = 0

* Fix success & error class (bootstrap)

* Uncomment require migrate.php

* Some distro have owner_id

* Update Player.php

---------

Co-authored-by: slawkens <slawkens@gmail.com>
2023-08-21 10:16:58 +02:00
slawkens
b72e7a3d96 Merge branch '0.9' into develop 2023-08-21 09:43:52 +02:00
slawkens
c3a161e2ee Merge branch '0.9' into develop 2023-08-21 09:38:31 +02:00
slawkens
627369bbde Add some variable to config.local.php on install 2023-08-21 09:01:50 +02:00
slawkens
7cea023965 Remove item.php include (was removed in last commits) 2023-08-15 22:33:37 +02:00
slawkens
eb416e18cc Add missing guild_ settings to config compat 2023-08-15 22:28:52 +02:00
slawkens
fc0d13437a Fix highscores show vocation 2023-08-15 22:17:34 +02:00
slawkens
14c8160020 Merge branch '0.9' into develop 2023-08-15 22:06:18 +02:00
slawkens
6c8961638e Merge branch '0.9' into develop 2023-08-12 13:28:07 +02:00
slawkens
b49c247162 Remove items generator, there are better ones made in JS
This one wasn't working with newer files anyways
2023-08-12 12:23:03 +02:00
slawkens
0f38a677b1 Require PHP min 8.0, older versions are EOL 2023-08-11 22:20:00 +02:00
slawkens
0835b69a93 Merge branch '0.9' into develop 2023-08-11 22:17:27 +02:00
slawkens
4f2e410a71 Merge branch '0.9' into develop 2023-08-11 22:11:47 +02:00
slawkens
ae600da28b Merge branch '0.9' into develop 2023-08-11 21:41:18 +02:00
slawkens
1a533388e7 Merge branch 'develop' of https://github.com/slawkens/myaac into develop 2023-08-11 06:40:20 +02:00
Gabriel Pedro
98335b8cc0 feat: add more tests (#229) 2023-08-11 06:39:17 +02:00
slawkens
16ebc1f577 Update functions.php 2023-08-10 13:05:17 +02:00
slawkens
7bab8f033c Allow hook file to be callable 2023-08-10 13:00:18 +02:00
slawkens
42d97721bf Merge branch '0.9' into develop 2023-08-10 12:02:54 +02:00
Slawomir Boczek
a72d1a3c9f Feature: settings (#216)
* New admin panel Pages: Options + Config [WIP]

* Forgot the plugin example of options

* Rename to settings.php

* Add Settings Class

* New myaac_settings table

* Add $limit parameter to $db->select method

* Add $member var annotation

* Remove useless title_separator from config

* Move $menus to menus.php

Also fix active link when menu item has subpage

* Settings [WIP]

New Settings class
New Plugins::load() method
Move config.php to settings.php
MyAAC Settings will have plugin_name = 'core'
Add compat_config.php

* Change options.php to settings.php

* Change name to settings

* Add Settings menu

* Add Sections + Add setting($key) function

Reorganisation

* Add email + password fields as type

* Update 33.php

* add settings migration

* php 8 compatibility

* add missing hook

* Add categories in tabs, move more settings, revert back getPluginSettings

Categories and sections are now not numbered
Remove example settings plugin

* fix typo

* Update .gitignore

* Add 36th migration for settings table

* Execute migrations just after db connect

* Update plugins.php

* [WIP] Some work on settings

Add hidden settings
New method: parse, to parse settings from array
Move base html to twig template
Remove vocation loading from .xml, instead use predefined voc names

* Rename

* Fix path

* [WIP] More work on settings

Move more config to settings (mainly mail_* + some other)
Remove mail_admin, wasnt used anywhere
Add return type to some functions
Add Twig settings(key) function
Possibility to save setting to db

* Add min, max, step to number field option

* Re-enable plugin if disabled and already installed

* Add Settings menu, including all plugins with settings

One change included in previous commit, due to missclick

* Nothing important

* Better boolean detection

* More detailed error message in settings

* Lets call it settings.name instead

* Add new function: only_if, to hide fields when they are not enabled [WIP]

Not fully finished yet

* guild_management: show_if

* Hide section title on show_if

* Fix: check on page load if radio button is checked

* Add: show_if - account_mail_verify

* nothing important

* Rename team_* variables + add to deprecated

* Change variable name

* Extract Settings:save function

* Add settings.callbacks.get

* Move forum config to settings

* Move status config to settings

* Remove whitespaces

* More config to settings: account_types, genders, highscores, admin

* Move signature config to settings

* Move news config to settings

* Rename variable

* Save config.php in Settings

Egg and hen problem solved :)
* Test database connection on save settings -> prevents from making website unusable if connection is wrong
* Test server_path -> same
There is no config.php anymore, just config.local.php, which can be edited manually and also from admin panel

* Remove configs from previous commit

* Fix create account, if account_create_character_create is enabled

* Add more deprecated configs

* Add more info into comment

* Update 5-database.php

* Fix menu highlighting & opening

* Update template.php

* Enable script option

* Reword email settings + move two new settings

* add last_kills_limit + move shop

* google_analytics_id

* add mail_lost_account_interval

* Create character blocked words (by @gpedro), just moved to settings

* Fix google_analytics

* create character name config moved to settings

* Fix for install warning - min/max length

* New create character checks configurable: block monsters & spells names

* fixes

* Improve character npc name check

* New setting: donate_column + move donate config to settings

* Add super fancy No Refresh saving with a toast

* Add new possibility: to deny saving setting if condition is not met

* Move database settings to separate category

* Fix default value displaying

* Add database_hash setting

* add last_kills_limit to compat config

* Move create character blocked names down

* Every setting needs to have default

* Move rest of config to settings

Remove config.php completely
Add new settings category: Game
Fix account_login_by_email
Min textarea size = 2 + adjusted automatically
2023-08-05 21:00:45 +02:00
slawkens
c802d427eb Merge branch '0.9' into develop 2023-08-05 20:52:26 +02:00
slawkens
b12c30982d Merge branch '0.9' into develop 2023-08-05 11:57:38 +02:00
slawkens
bb0e621308 Merge branch '0.9' into develop 2023-07-29 07:27:26 +02:00
slawkens
d3b15a0a3e Fix multiple redirects error in browser 2023-07-22 14:46:28 +02:00
slawkens
beff3e3aa6 Merge branch '0.9' into develop 2023-07-22 14:05:01 +02:00
Gabriel Pedro
3c3ddc4578 feat: custom words blocked (#190)
* Update config.php

* Update validator.php

* Update config.php
2023-07-22 09:54:03 +02:00
slawkens
0788dc8848 Merge branch '0.9' into develop 2023-07-21 21:22:41 +02:00
slawkens
eaa9d6be43 Merge branch '0.9' into develop 2023-07-21 16:38:22 +02:00
slawkens
712ca30293 Merge branch '0.9' into develop 2023-07-21 15:54:43 +02:00
slawkens
707aea18db Merge branch '0.9' into develop 2023-07-21 11:58:51 +02:00
slawkens
e14df529c0 Revert some change 2023-07-19 22:40:39 +02:00
slawkens
9f67cab503 Add twig context for twig hook() function
Allows to use variables from template inside the hook file with usage of $context variable
2023-07-19 22:40:11 +02:00
slawkens
99c53c75f2 New guild hooks, for some upcoming big feature ;) 2023-07-19 22:26:47 +02:00
slawkens
ddb093ec48 Fix highscores if there is only 1 record 2023-07-19 11:57:26 +02:00
slawkens
714476bf29 Merge branch '0.9' into develop 2023-07-13 11:08:30 +02:00
slawkens
a61cd43c3c Forum: nothing important, just formatting 2023-07-07 17:43:28 +02:00
slawkens
6d1b3235d2 Merge branch '0.9' into develop 2023-07-07 17:29:02 +02:00
slawkens
082884baa0 Fix guild description not shown 2023-07-02 00:26:44 +02:00
slawkens
2d561f267d Fix guild description not shown on guilds page 2023-06-30 19:52:20 +02:00
slawkens
5eafff737a Guilds & Characters: Use CSS word-break: break-all instead of PHP wordwrap
Suggested by @anyeor
2023-06-30 19:52:05 +02:00
slawkens
8cf4d0cb0f Add word-break on forum thread & reply
When someone inserts long word, is will break into multiple lines
2023-06-30 19:43:36 +02:00
slawkens
3a52f2c403 nothing important 2023-06-30 17:35:39 +02:00
slawkens
ac40922957 Merge branch '0.9' into develop 2023-06-30 17:32:40 +02:00
slawkens
a3bfdc1ec8 small adjustments 2023-06-25 08:54:36 +02:00
slawkens
74433303fb Better Gesior support 2023-06-23 21:52:23 +02:00
SRNT-GG
9d664d3577 WIP - Removing unneccessary closing tags to prevent potential issues. (#223)
* Part 1

Removing closing tags when no HTML or other output comes after the last PHP codeblock.

* Further removals

* nothing

---------

Co-authored-by: slawkens <slawkens@gmail.com>
2023-06-15 21:08:20 +02:00
slawkens
7d2fc48437 Fix links to edit/delete/hide directly from page 2023-06-11 18:57:57 +02:00
slawkens
aa1403480c Update to 0.10.0-dev 2023-06-03 18:50:14 +02:00
slawkens
91c8f1f5bc do not report if CI test 2 2023-06-03 18:41:16 +02:00
slawkens
b421bf3931 test dump env 2023-06-03 18:38:30 +02:00
slawkens
6e6f4679f4 Disable reporting on CI 2023-06-03 12:24:18 +02:00
slawkens
17221f5369 Rename to .htaccess.dist
Causes problems on default setup
2023-06-03 09:04:24 +02:00
slawkens
98d4d3fcf0 Install composer deps with --no-dev 2023-06-03 06:47:16 +02:00
slawkens
9868b41a61 <base> is not working properly, use full URL instead 2023-06-02 15:24:14 +02:00
slawkens
48822b6561 Use Whoops only if installed, otherwise use myaac exception handler 2023-06-02 15:20:13 +02:00
slawkens
0f30ebbcea change branch name in release.sh 2023-06-02 08:05:13 +02:00
slawkens
1a2e46f09b Ignore cypress in git-export + install composer deps on release 2023-06-02 08:04:17 +02:00
254 changed files with 6364 additions and 2945 deletions

View File

@@ -15,5 +15,5 @@ trim_trailing_whitespace = false
[{composer.json,package.json}]
indent_style = space
[package.json]
[{package.json, *.yml}]
indent_size = 2

1
.gitattributes vendored
View File

@@ -9,6 +9,5 @@ release.sh export-ignore
# cypress
cypress export-ignore
cypress.config.js export-ignore
cypress.env.json
*.sh text eol=lf

View File

@@ -1,9 +1,9 @@
name: Cypress
on:
pull_request:
branches: [0.9]
branches: [develop]
push:
branches: [0.9]
branches: [develop]
jobs:
cypress:

View File

@@ -19,7 +19,7 @@ Official website: https://my-aac.org
### Requirements
- PHP 7.2.5 or later
- PHP 8.0 or later
- MySQL database
- PDO PHP Extension
- XML PHP Extension

View File

@@ -0,0 +1,35 @@
<?php
$order = 10;
$settingsMenu = [];
$settingsMenu[] = [
'name' => 'MyAAC',
'link' => 'settings&plugin=core',
'icon' => 'list',
'order' => $order,
];
foreach (Plugins::getAllPluginsSettings() as $setting) {
$file = BASE . $setting['settingsFilename'];
if (!file_exists($file)) {
warning('Plugin setting: ' . $file . ' - cannot be loaded.');
continue;
}
$order += 10;
$settings = require $file;
$settingsMenu[] = [
'name' => $settings['name'],
'link' => 'settings&plugin=' . $setting['pluginFilename'],
'icon' => 'list',
'order' => $order,
];
}
unset($settings, $file, $order);
return $settingsMenu;

View File

@@ -6,10 +6,6 @@ require '../common.php';
const ADMIN_PANEL = true;
const MYAAC_ADMIN = true;
if(file_exists(BASE . 'config.local.php')) {
require_once BASE . 'config.local.php';
}
if(file_exists(BASE . 'install') && (!isset($config['installed']) || !$config['installed']))
{
header('Location: ' . BASE_URL . 'install/');
@@ -34,20 +30,8 @@ if(!$db->hasTable('myaac_account_actions')) {
throw new RuntimeException('Seems that the table <strong>myaac_account_actions</strong> of MyAAC doesn\'t exist in the database. This is a fatal error. You can try to reinstall MyAAC by visiting <a href="' . BASE_URL . 'install">this</a> url.');
}
if(config('env') === 'dev') {
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
}
// event system
require_once SYSTEM . 'hooks.php';
$hooks = new Hooks();
$hooks->load();
require SYSTEM . 'status.php';
require SYSTEM . 'login.php';
require SYSTEM . 'migrate.php';
require __DIR__ . '/includes/functions.php';
$twig->addGlobal('config', $config);

View File

@@ -7,13 +7,19 @@
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Player;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Account editor';
csrfProtect();
$admin_base = ADMIN_URL . '?p=accounts';
$use_datatable = true;
if ($config['account_country'])
if (setting('core.account_country'))
require SYSTEM . 'countries.conf.php';
$nameOrNumberColumn = 'name';
@@ -27,7 +33,7 @@ $hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
$hasTypeColumn = $db->hasColumn('accounts', 'type');
$hasGroupColumn = $db->hasColumn('accounts', 'group_id');
if ($config['account_country']) {
if (setting('core.account_country')) {
$countries = array();
foreach (array('pl', 'se', 'br', 'us', 'gb') as $c)
$countries[$c] = $config['countries'][$c];
@@ -37,7 +43,7 @@ if ($config['account_country']) {
$countries[$code] = $c;
}
$web_acc = ACCOUNT_WEB_FLAGS;
$acc_type = config('account_types');
$acc_type = setting('core.account_types');
?>
<link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ >
@@ -79,7 +85,7 @@ else if (isset($_REQUEST['search'])) {
$account = new OTS_Account();
$account->load($id);
if (isset($account, $_POST['save']) && $account->isLoaded()) {
if (isset($_POST['save']) && $account->isLoaded()) {
$error = false;
$_error = '';
@@ -263,6 +269,9 @@ else if (isset($_REQUEST['search'])) {
<li class="nav-item">
<a class="nav-link active" id="accounts-acc-tab" data-toggle="pill" href="#accounts-acc">Account</a>
</li>
<li class="nav-item">
<a class="nav-link" id="accounts-logs-tab" data-toggle="pill" href="#accounts-logs">Logs</a>
</li>
<li class="nav-item">
<a class="nav-link" id="accounts-chars-tab" data-toggle="pill" href="#accounts-chars">Characters</a>
</li>
@@ -283,6 +292,7 @@ else if (isset($_REQUEST['search'])) {
<div class="tab-content" id="accounts-tabContent">
<div class="tab-pane fade active show" id="accounts-acc">
<form action="<?php echo $admin_base . ((isset($id) && $id > 0) ? '&id=' . $id : ''); ?>" method="post">
<?php csrf(); ?>
<div class="form-group row">
<?php if (USE_ACCOUNT_NAME): ?>
<div class="col-12 col-sm-12 col-lg-4">
@@ -321,8 +331,8 @@ else if (isset($_REQUEST['search'])) {
<div class="col-12 col-sm-12 col-lg-6">
<label for="group">Account Type:</label>
<select name="group" id="group" class="form-control">
<?php foreach ($acc_type as $id => $a_type): ?>
<option value="<?php echo($id); ?>" <?php echo($acc_group == ($id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php foreach ($acc_type as $_id => $a_type): ?>
<option value="<?php echo($_id); ?>" <?php echo($acc_group == ($_id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php endforeach; ?>
</select>
</div>
@@ -332,8 +342,8 @@ else if (isset($_REQUEST['search'])) {
<div class="col-12 col-sm-12 col-lg-6">
<label for="group">Account Type:</label>
<select name="group" id="group" class="form-control">
<?php foreach ($groups->getGroups() as $id => $group): ?>
<option value="<?php echo $id; ?>" <?php echo($acc_group == $id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option>
<?php foreach ($groups->getGroups() as $_id => $group): ?>
<option value="<?php echo $_id; ?>" <?php echo($acc_group == $_id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option>
<?php endforeach; ?>
</select>
</div>
@@ -341,8 +351,8 @@ else if (isset($_REQUEST['search'])) {
<div class="col-12 col-sm-12 col-lg-6">
<label for="web_flags">Website Access:</label>
<select name="web_flags" id="web_flags" class="form-control">
<?php foreach ($web_acc as $id => $a_type): ?>
<option value="<?php echo($id); ?>" <?php echo($account->getWebFlags() == ($id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php foreach ($web_acc as $_id => $a_type): ?>
<option value="<?php echo($_id); ?>" <?php echo($account->getWebFlags() == ($_id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php endforeach; ?>
</select>
</div>
@@ -361,7 +371,7 @@ else if (isset($_REQUEST['search'])) {
</div>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<label for="email">Email:</label><?php echo (config('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(); ?>"/>
</div>
<?php if ($hasCoinsColumn): ?>
@@ -397,8 +407,8 @@ else if (isset($_REQUEST['search'])) {
<div class="col-12 col-sm-12 col-lg-4">
<label for="rl_country">Country:</label>
<select name="rl_country" id="rl_country" class="form-control">
<?php foreach ($countries as $id => $a_type): ?>
<option value="<?php echo($id); ?>" <?php echo($account->getCountry() == ($id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php foreach ($countries as $_id => $a_type): ?>
<option value="<?php echo($_id); ?>" <?php echo($account->getCountry() == ($_id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php endforeach; ?>
</select>
</div>
@@ -420,12 +430,39 @@ else if (isset($_REQUEST['search'])) {
<a href="<?php echo ADMIN_URL; ?>?p=accounts" class="btn btn-danger float-right"><i class="fas fa-cancel"></i> Cancel</a>
</form>
</div>
<div class="tab-pane fade" id="accounts-logs">
<div class="row">
<table class="table table-striped table-condensed table-responsive d-md-table">
<thead>
<tr>
<th>#</th>
<th>Date</th>
<th>Action</th>
<th>IP</th>
</tr>
</thead>
<tbody>
<?php
$accountActions = \MyAAC\Models\AccountAction::where('account_id', $account->getId())->orderByDesc('date')->get();
foreach ($accountActions as $i => $log):
$log->ip = ($log->ip != 0 ? long2ip($log->ip) : inet_ntop($log->ipv6));
?>
<tr>
<td><?php echo $i + 1; ?></td>
<td><?= date("M d Y, H:i:s", $log->date); ?></td>
<td><?= $log->action; ?></td>
<td><?= $log->ip; ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<div class="tab-pane fade" id="accounts-chars">
<div class="row">
<?php
if (isset($account) && $account->isLoaded()) {
$account_players = $account->getPlayersList();
$account_players->orderBy('id');
$account_players = Player::where('account_id', $account->getId())->orderBy('id')->get();
if (isset($account_players)) { ?>
<table class="table table-striped table-condensed table-responsive d-md-table">
<thead>
@@ -438,25 +475,13 @@ else if (isset($_REQUEST['search'])) {
</tr>
</thead>
<tbody>
<?php $i= 0;
foreach ($account_players as $i => $player):
$i++;
$player_vocation = $player->getVocation();
$player_promotion = $player->getPromotion();
if (isset($player_promotion)) {
if ((int)$player_promotion > 0)
$player_vocation += ($player_promotion * $config['vocations_amount']);
}
if (isset($config['vocations'][$player_vocation])) {
$vocation_name = $config['vocations'][$player_vocation];
} ?>
<?php foreach ($account_players as $i => $player): ?>
<tr>
<th><?php echo $i; ?></th>
<td><?php echo $player->getName(); ?></td>
<td><?php echo $player->getLevel(); ?></td>
<td><?php echo $vocation_name; ?></td>
<td><a href="?p=players&id=<?php echo $player->getId() ?>" class=" btn btn-success btn-sm" title="Edit"><i class="fas fa-pencil-alt"></i></a></td>
<th><?php echo $i + 1; ?></th>
<td><?php echo $player->name; ?></td>
<td><?php echo $player->level; ?></td>
<td><?php echo $player->vocation_name; ?></td>
<td><a href="?p=players&id=<?php echo $player->getKey() ?>" class=" btn btn-success btn-sm" title="Edit"><i class="fas fa-pencil-alt"></i></a></td>
</tr>
<?php endforeach ?>
</tbody>
@@ -560,18 +585,20 @@ else if (isset($_REQUEST['search'])) {
<div class="row">
<div class="col-6 col-lg-12">
<form action="<?php echo $admin_base; ?>" method="post">
<label for="name">Account Name:</label>
<?php csrf(); ?>
<label for="search">Account Name:</label>
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="search" value="<?php echo $search_account; ?>" maxlength="32" size="32">
<input type="text" class="form-control" id="search" name="search" value="<?= escapeHtml($search_account); ?>" maxlength="32" size="32">
<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span>
</div>
</form>
</div>
<div class="col-6 col-lg-12">
<form action="<?php echo $admin_base; ?>" method="post">
<label for="name">Account ID:</label>
<?php csrf(); ?>
<label for="id">Account ID:</label>
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="id" value="" maxlength="32" size="32">
<input type="text" class="form-control" id="id" name="id" value="<?= $id; ?>" maxlength="32" size="32">
<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span>
</div>
</form>

View File

@@ -8,32 +8,34 @@
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Changelog as ModelsChangelog;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Changelog';
csrfProtect();
if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) {
echo 'Access denied.';
return;
}
$title = 'Changelog';
$use_datatable = true;
const CL_LIMIT = 600; // maximum changelog body length
?>
<link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ >
<script src="<?php echo BASE_URL; ?>tools/js/jquery.datetimepicker.js"></script>
<?php
$id = $_GET['id'] ?? 0;
require_once LIBS . 'changelog.php';
if(!empty($action))
{
$id = $_REQUEST['id'] ?? null;
$body = isset($_REQUEST['body']) ? stripslashes($_REQUEST['body']) : null;
$create_date = isset($_REQUEST['createdate']) ? (int)strtotime($_REQUEST['createdate'] ): null;
$player_id = isset($_REQUEST['player_id']) ? (int)$_REQUEST['player_id'] : null;
$type = isset($_REQUEST['type']) ? (int)$_REQUEST['type'] : null;
$where = isset($_REQUEST['where']) ? (int)$_REQUEST['where'] : null;
$id = $_POST['id'] ?? null;
$body = isset($_POST['body']) ? stripslashes($_POST['body']) : null;
$create_date = isset($_POST['createdate']) ? (int)strtotime($_POST['createdate'] ): null;
$player_id = isset($_POST['player_id']) ? (int)$_POST['player_id'] : null;
$type = isset($_POST['type']) ? (int)$_POST['type'] : null;
$where = isset($_POST['where']) ? (int)$_POST['where'] : null;
$errors = array();
@@ -43,12 +45,13 @@ if(!empty($action))
$body = '';
$type = $where = $player_id = $create_date = 0;
success("Added successful.");
success('Added successful.');
}
}
else if($action == 'delete') {
Changelog::delete($id, $errors);
success("Deleted successful.");
if (Changelog::delete($id, $errors)) {
success('Deleted successful.');
}
}
else if($action == 'edit')
{
@@ -65,20 +68,21 @@ if(!empty($action))
$action = $body = '';
$type = $where = $player_id = $create_date = 0;
success("Updated successful.");
success('Updated successful.');
}
}
}
else if($action == 'hide') {
Changelog::toggleHidden($id, $errors, $status);
success(($status == 1 ? 'Show' : 'Hide') . " successful.");
if (Changelog::toggleHidden($id, $errors, $status)) {
success(($status == 1 ? 'Hide' : 'Show') . ' successful.');
}
}
if(!empty($errors))
error(implode(", ", $errors));
}
$changelogs = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'changelog' . '` ORDER BY `id` DESC')->fetchAll();
$changelogs = ModelsChangelog::orderBy('id')->get()->toArray();
$i = 0;
@@ -110,7 +114,7 @@ if($action == 'edit' || $action == 'new') {
$account_players->orderBy('group_id', POT::ORDER_DESC);
$twig->display('admin.changelog.form.html.twig', array(
'action' => $action,
'cl_link_form' => constant('ADMIN_URL').'?p=changelog&action=' . ($action == 'edit' ? 'edit' : 'new'),
'cl_link_form' => constant('ADMIN_URL').'?p=changelog',
'cl_id' => $id ?? null,
'body' => isset($body) ? escapeHtml($body) : '',
'create_date' => $create_date ?? '',
@@ -125,15 +129,3 @@ if($action == 'edit' || $action == 'new') {
$twig->display('admin.changelog.html.twig', array(
'changelogs' => $changelogs,
));
?>
<script>
$(document).ready(function () {
$('#createdate').datetimepicker({format: "M d Y, H:i:s",});
$('.tb_datatable').DataTable({
"order": [[0, "desc"]],
"columnDefs": [{targets: [1, 2,4,5],orderable: false}]
});
});
</script>

View File

@@ -10,7 +10,9 @@
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Dashboard';
if (isset($_GET['clear_cache'])) {
csrfProtect();
if (isset($_POST['clear_cache'])) {
if (clearCache()) {
success('Cache cleared.');
} else {
@@ -18,7 +20,7 @@ if (isset($_GET['clear_cache'])) {
}
}
if (isset($_GET['maintenance'])) {
if (isset($_POST['maintenance'])) {
$message = (!empty($_POST['message']) ? $_POST['message'] : null);
$_status = (isset($_POST['status']) && $_POST['status'] == 'true');
$_status = ($_status ? '0' : '1');
@@ -47,12 +49,11 @@ $tmp = '';
if (fetchDatabaseConfig('site_closed_message', $tmp))
$closed_message = $tmp;
$configAdminPanelModules = config('admin_panel_modules');
if (isset($configAdminPanelModules)) {
$settingAdminPanelModules = setting('core.admin_panel_modules');
if (count($settingAdminPanelModules) > 0) {
echo '<div class="row">';
$configAdminPanelModules = explode(',', $configAdminPanelModules);
$twig_loader->prependPath(__DIR__ . '/modules/templates');
foreach ($configAdminPanelModules as $box) {
foreach ($settingAdminPanelModules as $box) {
$file = __DIR__ . '/modules/' . $box . '.php';
if (file_exists($file)) {
include($file);

View File

@@ -10,6 +10,8 @@
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Login';
csrfProtect();
require PAGES . 'account/login.php';
if ($logged) {
header('Location: ' . (admin() ? ADMIN_URL : BASE_URL));

View File

@@ -10,17 +10,19 @@
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Mailer';
csrfProtect();
if (!hasFlag(FLAG_CONTENT_MAILER) && !superAdmin()) {
echo 'Access denied.';
return;
}
if (!config('mail_enabled')) {
if (!setting('core.mail_enabled')) {
echo 'Mail support disabled in config.';
return;
}
$mail_to = isset($_REQUEST['mail_to']) ? stripslashes(trim($_REQUEST['mail_to'])) : null;
$mail_to = isset($_POST['mail_to']) ? stripslashes(trim($_POST['mail_to'])) : null;
$mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : null;
$mail_content = isset($_POST['mail_content']) ? stripslashes($_POST['mail_content']) : null;
@@ -54,7 +56,7 @@ if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) {
$failed = 0;
$add = '';
if (config('account_mail_verify')) {
if (setting('core.account_mail_verify')) {
note('Note: Sending only to users with verified E-Mail.');
$add = ' AND `email_verified` = 1';
}

View File

@@ -9,10 +9,15 @@
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Account;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Mass Account Actions';
csrfProtect();
$hasCoinsColumn = $db->hasColumn('accounts', 'coins');
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
$freePremium = $config['lua']['freePremium'];
@@ -26,15 +31,14 @@ function admin_give_points($points)
return;
}
$statement = $db->prepare('UPDATE `accounts` SET `premium_points` = `premium_points` + :points');
if (!$statement) {
displayMessage('Failed to prepare query statement.');
return;
}
if (!$statement->execute([
'points' => $points
])) {
if (!Account::query()->increment('premium_points', $points)) {
displayMessage('Failed to add points.');
return;
}
@@ -50,15 +54,7 @@ function admin_give_coins($coins)
return;
}
$statement = $db->prepare('UPDATE `accounts` SET `coins` = `coins` + :coins');
if (!$statement) {
displayMessage('Failed to prepare query statement.');
return;
}
if (!$statement->execute([
'coins' => $coins
])) {
if (!Account::query()->increment('coins', $coins)) {
displayMessage('Failed to add coins.');
return;
}

View File

@@ -8,22 +8,21 @@
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Player;
use MyAAC\Models\PlayerOnline;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Mass Teleport Actions';
function admin_teleport_position($x, $y, $z) {
global $db;
$statement = $db->prepare('UPDATE `players` SET `posx` = :x, `posy` = :y, `posz` = :z');
if (!$statement) {
displayMessage('Failed to prepare query statement.');
return;
}
csrfProtect();
if (!$statement->execute([
'x' => $x, 'y' => $y, 'z' => $z
function admin_teleport_position($x, $y, $z) {
if (!Player::query()->update([
'posx' => $x, 'posy' => $y, 'posz' => $z
])) {
displayMessage('Failed to execute query.');
displayMessage('Failed to execute query. Probably already updated.');
return;
}
@@ -31,17 +30,10 @@ function admin_teleport_position($x, $y, $z) {
}
function admin_teleport_town($town_id) {
global $db;
$statement = $db->prepare('UPDATE `players` SET `town_id` = :town_id');
if (!$statement) {
displayMessage('Failed to prepare query statement.');
return;
}
if (!$statement->execute([
'town_id' => $town_id
if (!Player::query()->update([
'town_id' => $town_id,
])) {
displayMessage('Failed to execute query.');
displayMessage('Failed to execute query. Probably already updated.');
return;
}
@@ -58,13 +50,12 @@ if (isset($_POST['action']) && $_POST['action']) {
$playersOnline = 0;
if($db->hasTable('players_online')) {// tfs 1.0
$query = $db->query('SELECT count(*) AS `count` FROM `players_online`');
$playersOnline = PlayerOnline::count();
} else {
$query = $db->query('SELECT count(*) AS `count` FROM `players` WHERE `players`.`online` > 0');
$playersOnline = Player::online()->count();
}
$playersOnline = $query->fetch(PDO::FETCH_ASSOC);
if ($playersOnline['count'] > 0) {
if ($playersOnline > 0) {
displayMessage('Please, close the server before execute this action otherwise players will not be affected.');
return;
}

View File

@@ -7,35 +7,48 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Menu;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Menus';
csrfProtect();
if (!hasFlag(FLAG_CONTENT_MENUS) && !superAdmin()) {
echo 'Access denied.';
return;
}
if (isset($_REQUEST['template'])) {
$template = $_REQUEST['template'];
if (isset($_POST['template'])) {
$template = $_POST['template'];
if (isset($_REQUEST['menu'])) {
$post_menu = $_REQUEST['menu'];
$post_menu_link = $_REQUEST['menu_link'];
$post_menu_blank = $_REQUEST['menu_blank'];
$post_menu_color = $_REQUEST['menu_color'];
if (isset($_POST['menu'])) {
$post_menu = $_POST['menu'];
$post_menu_link = $_POST['menu_link'];
$post_menu_blank = $_POST['menu_blank'];
$post_menu_color = $_POST['menu_color'];
if (count($post_menu) != count($post_menu_link)) {
echo 'Menu count is not equal menu links. Something went wrong when sending form.';
return;
}
$db->query('DELETE FROM `' . TABLE_PREFIX . 'menu` WHERE `template` = ' . $db->quote($template));
Menu::where('template', $template)->delete();
foreach ($post_menu as $category => $menus) {
foreach ($menus as $i => $menu) {
if (empty($menu)) // don't save empty menu item
continue;
try {
$db->insert(TABLE_PREFIX . 'menu', array('template' => $template, 'name' => $menu, 'link' => $post_menu_link[$category][$i], 'blank' => $post_menu_blank[$category][$i] == 'on' ? 1 : 0, 'color' => str_replace('#', '', $post_menu_color[$category][$i]), 'category' => $category, 'ordering' => $i));
Menu::create([
'template' => $template,
'name' => $menu,
'link' => $post_menu_link[$category][$i],
'blank' => $post_menu_blank[$category][$i] == 'on' ? 1 : 0,
'color' => str_replace('#', '', $post_menu_color[$category][$i]),
'category' => $category,
'ordering' => $i
]);
} catch (PDOException $error) {
warning('Error while adding menu item (' . $menu . '): ' . $error->getMessage());
}
@@ -58,6 +71,16 @@ if (isset($_REQUEST['template'])) {
return;
}
if (isset($_GET['reset_colors'])) {
if (isset($config['menu_default_color'])) {
Menu::where('template', $template)->update(['color' => str_replace('#', '', $config['menu_default_color'])]);
success('Colors has been reset.');
}
else {
warning('There is no default color defined, cannot reset colors.');
}
}
if (!isset($config['menu_categories'])) {
echo "No menu categories set in template config.php.<br/>This template doesn't support dynamic menus.";
return;
@@ -71,17 +94,31 @@ if (isset($_REQUEST['template'])) {
Hint: Add links to external sites using: <b>http://</b> or <b>https://</b> prefix.<br/>
Not all templates support blank and colorful links.
</p>
<?php if (isset($config['menu_default_color'])) {?>
<form method="post" action="?p=menus&reset_colors" onsubmit="return confirm('Do you really want to reset colors?');">
<?php csrf(); ?>
<input type="hidden" name="template" value="<?php echo $template ?>"/>
<button type="submit" class="btn btn-danger">Reset Colors to default</button>
</form>
<br/>
<?php } ?>
</div>
<?php
$menus = array();
$menus_db = $db->query('SELECT `name`, `link`, `blank`, `color`, `category`, `ordering` FROM `' . TABLE_PREFIX . 'menu` WHERE `enabled` = 1 AND `template` = ' . $db->quote($template) . ' ORDER BY `ordering` ASC;')->fetchAll();
foreach ($menus_db as $menu) {
$menus[$menu['category']][] = array('name' => $menu['name'], 'link' => $menu['link'], 'blank' => $menu['blank'], 'color' => $menu['color'], 'ordering' => $menu['ordering']);
}
$menus = Menu::query()
->select('name', 'link', 'blank', 'color', 'category', 'ordering')
->where('enabled', 1)
->where('template', $template)
->orderBy('ordering')
->get()
->groupBy('category')
->toArray();
$last_id = array();
?>
<form method="post" id="menus-form" action="?p=menus">
<?php csrf(); ?>
<input type="hidden" name="template" value="<?php echo $template ?>"/>
<button type="submit" class="btn btn-info">Save</button><br/><br/>
<div class="row">
<?php foreach ($config['menu_categories'] as $id => $cat): ?>
<div class="col-md-12 col-lg-6">
@@ -113,7 +150,7 @@ if (isset($_REQUEST['template'])) {
</div>
<div class="row pb-2">
<div class="col-md-12">
<button type="submit" class="btn btn-info"><i class="fas fa-update"></i> Save</button>
<button type="submit" class="btn btn-info">Save</button>
<?php
echo '<button type="button" class="btn btn-danger float-right" value="Cancel" onclick="window.location = \'' . ADMIN_URL . '?p=menus\';"><i class="fas fa-cancel"></i> Cancel</button>';
?>
@@ -129,7 +166,7 @@ if (isset($_REQUEST['template'])) {
?>
<?php
} else {
$templates = $db->query('SELECT `template` FROM `' . TABLE_PREFIX . 'menu` GROUP BY `template`;')->fetchAll();
$templates = Menu::select('template')->distinct()->get()->toArray();
foreach ($templates as $key => $value) {
$file = TEMPLATES . $value['template'] . '/config.php';
if (!file_exists($file)) {

View File

@@ -1,7 +1,14 @@
<?php
use MyAAC\Models\Player;
defined('MYAAC') or die('Direct access not allowed!');
$balance = ($db->hasColumn('players', 'balance') ? $db->query('SELECT `balance`, `id`, `name`,`level` FROM `players` ORDER BY `balance` DESC LIMIT 10;') : 0);
$balance = 0;
if ($db->hasColumn('players', 'balance')) {
$balance = Player::orderByDesc('balance')->limit(10)->get(['balance', 'id','name', 'level'])->toArray();
}
$twig->display('balance.html.twig', array(
'balance' => $balance

View File

@@ -1,7 +1,14 @@
<?php
use MyAAC\Models\Account;
defined('MYAAC') or die('Direct access not allowed!');
$coins = ($db->hasColumn('accounts', 'coins') ? $db->query('SELECT `coins`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `coins` DESC LIMIT 10;') : 0);
$coins = 0;
if ($db->hasColumn('accounts', 'coins')) {
$coins = Account::orderByDesc('coins')->limit(10)->get(['coins', (USE_ACCOUNT_NAME ? 'name' : 'id')])->toArray();
}
$twig->display('coins.html.twig', array(
'coins' => $coins

View File

@@ -1,8 +1,15 @@
<?php
use MyAAC\Models\Account;
defined('MYAAC') or die('Direct access not allowed!');
$players = ($db->hasColumn('accounts', 'created') ? $db->query('SELECT `created`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `created` DESC LIMIT 10;') : 0);
$accounts = 0;
if ($db->hasColumn('accounts', 'created')) {
$accounts = Account::orderByDesc('created')->limit(10)->get(['created', (USE_ACCOUNT_NAME ? 'name' : 'id')])->toArray();
}
$twig->display('created.html.twig', array(
'players' => $players,
'accounts' => $accounts,
));

View File

@@ -1,7 +1,15 @@
<?php
use MyAAC\Models\Player;
defined('MYAAC') or die('Direct access not allowed!');
$players = ($db->hasColumn('players', 'lastlogin') ? $db->query('SELECT name, level, lastlogin FROM players ORDER BY lastlogin DESC LIMIT 10;') : 0);
$players = 0;
if ($db->hasColumn('players', 'lastlogin')) {
$players = Player::orderByDesc('lastlogin')->limit(10)->get(['name', 'level', 'lastlogin'])->toArray();
}
$twig->display('lastlogin.html.twig', array(
'players' => $players,
));

View File

@@ -1,7 +1,14 @@
<?php
use MyAAC\Models\Account;
defined('MYAAC') or die('Direct access not allowed!');
$points = ($db->hasColumn('accounts', 'premium_points') ? $db->query('SELECT `premium_points`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `premium_points` DESC LIMIT 10;') : 0);
$points = 0;
if ($db->hasColumn('accounts', 'premium_points')) {
$coins = Account::orderByDesc('premium_points')->limit(10)->get(['premium_points', (USE_ACCOUNT_NAME ? 'name' : 'id')])->toArray();
}
$twig->display('points.html.twig', array(
'points' => $points,

View File

@@ -1,11 +1,20 @@
<?php
use MyAAC\Models\Account;
use MyAAC\Models\Guild;
use MyAAC\Models\House;
use MyAAC\Models\Monster;
use MyAAC\Models\Player;
defined('MYAAC') or die('Direct access not allowed!');
$count = $db->query('SELECT
(SELECT COUNT(*) FROM `accounts`) as total_accounts,
(SELECT COUNT(*) FROM `players`) as total_players,
(SELECT COUNT(*) FROM `guilds`) as total_guilds,
(SELECT COUNT(*) FROM `' . TABLE_PREFIX . 'monsters`) as total_monsters,
(SELECT COUNT(*) FROM `houses`) as total_houses;')->fetch();
$count = $eloquentConnection->query()
->select([
'total_accounts' => Account::selectRaw('COUNT(id)'),
'total_players' => Player::selectRaw('COUNT(id)'),
'total_guilds' => Guild::selectRaw('COUNT(id)'),
'total_monsters' => Monster::selectRaw('COUNT(id)'),
'total_houses' => House::selectRaw('COUNT(id)'),
])->first();
$twig->display('statistics.html.twig', array(
'count' => $count,

View File

@@ -1,4 +1,4 @@
{% if players is iterable %}
{% if accounts is iterable %}
<div class=" col-md-6 col-lg-3">
<div class="card card-info card-outline">
<div class="card-header">
@@ -15,7 +15,7 @@
</thead>
<tbody>
{% set i = 0 %}
{% for result in players %}
{% for result in accounts %}
{% set i = i + 1 %}
<tr>
<th>{{ i }}</th>

View File

@@ -1,28 +1,32 @@
<div class="col-12 col-md-6">
<div class="card card-warning card-outline">
<form action="?p=dashboard&maintenance" method="post" class="form-horizontal">
<div class="card-header">
<span class="m-0">Website Status<span class="float-right">
<div class="custom-control custom-switch custom-switch-off-danger custom-switch-on-success">
<input type="checkbox" class="custom-control-input" name="status" id="status" value="true" {% if not is_closed %} checked{% endif %}>
<label id="status-label" class="custom-control-label" for="status"> {% if is_closed %}Closed{% else %}Open{% endif %}</label>
</div></span>
</span>
<div class="card-header">
<span class="m-0">Website Status<span class="float-right">
<div class="custom-control custom-switch custom-switch-off-danger custom-switch-on-success">
<input form="maintenance-form" type="checkbox" class="custom-control-input" name="status" id="status" value="true" {% if not is_closed %} checked{% endif %}>
<label id="status-label" class="custom-control-label" for="status"> {% if is_closed %}Closed{% else %}Open{% endif %}</label>
</div></span>
</span>
</div>
<div class="card-body p-2">
<div class="col-sm-12">
<label for="message" class="col-form-label">Maintenance Message</label>
<textarea form="maintenance-form" name="message" class="form-control" cols="40" rows="3" maxlength="255" placeholder="Enter ...">{{ closed_message }}</textarea>
<small>(only visible if closed)</small>
</div>
<div class="card-body p-2">
<div class="col-sm-12">
<label for="message" class="col-form-label">Maintenance Message</label>
<textarea name="message" class="form-control" cols="40" rows="3" maxlength="255" placeholder="Enter ...">{{ closed_message }}</textarea>
<small>(only visible if closed)</small>
</div>
</div>
<div class="card-footer">
</div>
<div class="card-footer">
<form id="maintenance-form" method="post" action="?p=dashboard" class="float-left">
{{ csrf() }}
<input type="hidden" name="maintenance" value="1" />
<button type="submit" class="btn btn-info"><i class="far fa-update"></i> Update</button>
<a href="?p=dashboard&clear_cache" onclick="return confirm('Are you sure?');" class="float-right">
<span class="btn btn-danger"><i class="fas fa-clear"></i>Clear cache</span>
</a>
</div>
</form>
</form>
<form method="post" action="?p=dashboard" class="float-right">
{{ csrf() }}
<input type="hidden" name="clear_cache" value="1" />
<button type="submit" onclick="return confirm('Are you sure that you want to clear cache?');" class="btn btn-danger" title="Clear Cache"><i class="fas fa-clear"></i>Clear cache</button>
</form>
</div>
</div>
</div>

View File

@@ -9,12 +9,15 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'News Panel';
csrfProtect();
$use_datatable = true;
require_once LIBS . 'forum.php';
require_once LIBS . 'news.php';
$title = 'News Panel';
$use_datatable = true;
if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) {
echo 'Access denied.';
return;
@@ -23,25 +26,25 @@ if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) {
header('X-XSS-Protection:0');
// some constants, used mainly by database (cannot by modified without schema changes)
define('NEWS_TITLE_LIMIT', 100);
define('NEWS_BODY_LIMIT', 65535); // maximum news body length
define('ARTICLE_TEXT_LIMIT', 300);
define('ARTICLE_IMAGE_LIMIT', 100);
const NEWS_TITLE_LIMIT = 100;
const NEWS_BODY_LIMIT = 65535; // maximum news body length
const ARTICLE_TEXT_LIMIT = 300;
const ARTICLE_IMAGE_LIMIT = 100;
$name = $p_title = '';
if(!empty($action))
{
$id = isset($_REQUEST['id']) ? $_REQUEST['id'] : null;
$p_title = isset($_REQUEST['title']) ? $_REQUEST['title'] : null;
$body = isset($_REQUEST['body']) ? stripslashes($_REQUEST['body']) : null;
$comments = isset($_REQUEST['comments']) ? $_REQUEST['comments'] : null;
$type = isset($_REQUEST['type']) ? (int)$_REQUEST['type'] : null;
$category = isset($_REQUEST['category']) ? (int)$_REQUEST['category'] : null;
$player_id = isset($_REQUEST['player_id']) ? (int)$_REQUEST['player_id'] : null;
$article_text = isset($_REQUEST['article_text']) ? $_REQUEST['article_text'] : null;
$article_image = isset($_REQUEST['article_image']) ? $_REQUEST['article_image'] : null;
$forum_section = isset($_REQUEST['forum_section']) ? $_REQUEST['forum_section'] : null;
$errors = array();
$id = $_POST['id'] ?? null;
$p_title = $_POST['title'] ?? null;
$body = isset($_POST['body']) ? stripslashes($_POST['body']) : null;
$comments = $_POST['comments'] ?? null;
$type = isset($_REQUEST['type']) ? (int)$_REQUEST['type'] : 1;
$category = isset($_POST['category']) ? (int)$_POST['category'] : null;
$player_id = isset($_POST['player_id']) ? (int)$_POST['player_id'] : null;
$article_text = $_POST['article_text'] ?? null;
$article_image = $_POST['article_image'] ?? null;
$forum_section = $_POST['forum_section'] ?? null;
$errors = [];
if($action == 'new') {
if(isset($forum_section) && $forum_section != '-1') {
@@ -52,12 +55,13 @@ if(!empty($action))
$p_title = $body = $comments = $article_text = $article_image = '';
$type = $category = $player_id = 0;
success("Added successful.");
success('Added successful.');
}
}
else if($action == 'delete') {
News::delete($id, $errors);
success("Deleted successful.");
if (News::delete($id, $errors)) {
success('Deleted successful.');
}
}
else if($action == 'edit')
{
@@ -82,13 +86,14 @@ if(!empty($action))
$action = $p_title = $body = $comments = $article_text = $article_image = '';
$type = $category = $player_id = 0;
success("Updated successful.");
success('Updated successful.');
}
}
}
else if($action == 'hide') {
News::toggleHidden($id, $errors, $status);
success(($status == 1 ? 'Show' : 'Hide') . " successful.");
if (News::toggleHidden($id, $errors, $status)) {
success(($status == 1 ? 'Hide' : 'Show') . ' successful.');
}
}
if(!empty($errors))
@@ -114,12 +119,10 @@ if($action == 'edit' || $action == 'new') {
$account_players->orderBy('group_id', POT::ORDER_DESC);
$twig->display('admin.news.form.html.twig', array(
'action' => $action,
'news_link' => getLink(PAGE),
'news_link_form' => '?p=news&action=' . ($action == 'edit' ? 'edit' : 'new'),
'news_id' => $id ?? null,
'title' => $p_title ?? '',
'body' => isset($body) ? escapeHtml($body) : '',
'type' => $type ?? null,
'type' => $type,
'player' => isset($player) && $player->isLoaded() ? $player : null,
'player_id' => $player_id ?? null,
'account_players' => $account_players,

View File

@@ -7,46 +7,35 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Notepad as ModelsNotepad;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Notepad';
$notepad_content = Notepad::get($account_logged->getId());
csrfProtect();
/**
* @var $account_logged OTS_Account
*/
$_content = '';
$notepad = ModelsNotepad::where('account_id', $account_logged->getId())->first();
if (isset($_POST['content'])) {
$_content = html_entity_decode(stripslashes($_POST['content']));
if (!$notepad_content)
Notepad::create($account_logged->getId(), $_content);
else
Notepad::update($account_logged->getId(), $_content);
if (!$notepad) {
ModelsNotepad::create([
'account_id' => $account_logged->getId(),
'content' => $_content
]);
}
else {
ModelsNotepad::where('account_id', $account_logged->getId())->update(['content' => $_content]);
}
echo '<div class="success" style="text-align: center;">Saved at ' . date('H:i') . '</div>';
success('Saved at ' . date('H:i'));
} else {
if ($notepad_content !== false)
$_content = $notepad_content;
if ($notepad)
$_content = $notepad->content;
}
$twig->display('admin.notepad.html.twig', array('content' => isset($_content) ? $_content : null));
class Notepad
{
static public function get($account_id)
{
global $db;
$query = $db->select(TABLE_PREFIX . 'notepad', array('account_id' => $account_id));
if ($query !== false)
return $query['content'];
return false;
}
static public function create($account_id, $content = '')
{
global $db;
$db->insert(TABLE_PREFIX . 'notepad', array('account_id' => $account_id, 'content' => $content));
}
static public function update($account_id, $content = '')
{
global $db;
$db->update(TABLE_PREFIX . 'notepad', array('content' => $content), array('account_id' => $account_id));
}
}
$twig->display('admin.notepad.html.twig', ['content' => $_content]);

View File

@@ -7,10 +7,16 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Pages as ModelsPages;
use MyAAC\Admin\Pages;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Pages';
$use_datatable = true;
csrfProtect();
if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) {
echo 'Access denied.';
return;
@@ -26,31 +32,36 @@ $enable_tinymce = true;
$access = 0;
// some constants, used mainly by database (cannot by modified without schema changes)
define('PAGE_TITLE_LIMIT', 30);
define('PAGE_NAME_LIMIT', 30);
define('PAGE_BODY_LIMIT', 65535); // maximum page body length
const PAGE_TITLE_LIMIT = 30;
const PAGE_NAME_LIMIT = 30;
const PAGE_BODY_LIMIT = 65535; // maximum page body length
if (!empty($action)) {
if ($action == 'delete' || $action == 'edit' || $action == 'hide')
$id = $_REQUEST['id'];
if (isset($_REQUEST['name']))
$name = $_REQUEST['name'];
if (isset($_REQUEST['title']))
$p_title = $_REQUEST['title'];
$php = isset($_REQUEST['php']) && $_REQUEST['php'] == 1;
$enable_tinymce = isset($_REQUEST['enable_tinymce']) && $_REQUEST['enable_tinymce'] == 1;
if ($php)
$body = $_REQUEST['body'];
else if (isset($_REQUEST['body'])) {
//$body = $_REQUEST['body'];
$body = html_entity_decode(stripslashes($_REQUEST['body']));
if ($action == 'delete' || $action == 'edit' || $action == 'hide') {
$id = $_POST['id'];
}
if (isset($_REQUEST['access']))
$access = $_REQUEST['access'];
if (isset($_POST['name'])) {
$name = $_POST['name'];
}
if (isset($_POST['title'])) {
$p_title = $_POST['title'];
}
$php = isset($_POST['php']) && $_POST['php'] == 1;
$enable_tinymce = isset($_POST['enable_tinymce']) && $_POST['enable_tinymce'] == 1;
if ($php) {
$body = $_POST['body'];
}
else if (isset($_POST['body'])) {
//$body = $_POST['body'];
$body = html_entity_decode(stripslashes($_POST['body']));
}
if (isset($_POST['access'])) {
$access = $_POST['access'];
}
$errors = array();
$player_id = 1;
@@ -67,7 +78,7 @@ if (!empty($action)) {
if (Pages::delete($id, $errors))
success('Page with id ' . $id . ' has been deleted');
} else if ($action == 'edit') {
if (isset($id) && !isset($_REQUEST['name'])) {
if (isset($id) && !isset($_POST['name'])) {
$_page = Pages::get($id);
$name = $_page['name'];
$p_title = $_page['title'];
@@ -86,29 +97,26 @@ if (!empty($action)) {
}
}
} else if ($action == 'hide') {
Pages::toggleHidden($id, $errors, $status);
success(($status == 1 ? 'Show' : 'Hide') . ' successful.');
if (Pages::toggleHidden($id, $errors, $status)) {
success(($status == 0 ? 'Show' : 'Hide') . ' successful.');
}
}
if (!empty($errors))
error(implode(", ", $errors));
}
$query =
$db->query('SELECT * FROM ' . $db->tableName(TABLE_PREFIX . 'pages'));
$pages = ModelsPages::all()->map(function ($e) {
return [
'link' => getFullLink($e->name, $e->name, true),
'title' => substr($e->title, 0, 20),
'php' => $e->php == '1',
'id' => $e->id,
'hidden' => $e->hidden
];
})->toArray();
$pages = array();
foreach ($query as $_page) {
$pages[] = array(
'link' => getFullLink($_page['name'], $_page['name'], true),
'title' => substr($_page['title'], 0, 20),
'php' => $_page['php'] == '1',
'id' => $_page['id'],
'hidden' => $_page['hidden']
);
}
$twig->display('admin.pages.form.html.twig', array(
$twig->display('admin.pages.form.html.twig', [
'action' => $action,
'id' => $action == 'edit' ? $id : null,
'name' => $name,
@@ -118,143 +126,8 @@ $twig->display('admin.pages.form.html.twig', array(
'body' => isset($body) ? escapeHtml($body) : '',
'groups' => $groups->getGroups(),
'access' => $access
));
]);
$twig->display('admin.pages.html.twig', array(
$twig->display('admin.pages.html.twig', [
'pages' => $pages
));
class Pages
{
static public function verify($name, $title, $body, $player_id, $php, $enable_tinymce, $access, &$errors)
{
if(!isset($title[0]) || !isset($body[0])) {
$errors[] = 'Please fill all inputs.';
return false;
}
if(strlen($name) > PAGE_NAME_LIMIT) {
$errors[] = 'Page name cannot be longer than ' . PAGE_NAME_LIMIT . ' characters.';
return false;
}
if(strlen($title) > PAGE_TITLE_LIMIT) {
$errors[] = 'Page title cannot be longer than ' . PAGE_TITLE_LIMIT . ' characters.';
return false;
}
if(strlen($body) > PAGE_BODY_LIMIT) {
$errors[] = 'Page content cannot be longer than ' . PAGE_BODY_LIMIT . ' characters.';
return false;
}
if(!isset($player_id) || $player_id == 0) {
$errors[] = 'Player ID is wrong.';
return false;
}
if(!isset($php) || ($php != 0 && $php != 1)) {
$errors[] = 'Enable PHP is wrong.';
return false;
}
if ($php == 1 && !getBoolean(config('admin_pages_php_enable'))) {
$errors[] = 'PHP pages disabled on this server. To enable go to config.php and change admin_pages_php_enable to "yes".';
return false;
}
if(!isset($enable_tinymce) || ($enable_tinymce != 0 && $enable_tinymce != 1)) {
$errors[] = 'Enable TinyMCE is wrong.';
return false;
}
if(!isset($access) || $access < 0 || $access > PHP_INT_MAX) {
$errors[] = 'Access is wrong.';
return false;
}
return true;
}
static public function get($id)
{
global $db;
$query = $db->select(TABLE_PREFIX . 'pages', array('id' => $id));
if ($query !== false)
return $query;
return false;
}
static public function add($name, $title, $body, $player_id, $php, $enable_tinymce, $access, &$errors)
{
if(!self::verify($name, $title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) {
return false;
}
global $db;
$query = $db->select(TABLE_PREFIX . 'pages', array('name' => $name));
if ($query === false)
$db->insert(TABLE_PREFIX . 'pages',
array(
'name' => $name,
'title' => $title,
'body' => $body,
'player_id' => $player_id,
'php' => $php ? '1' : '0',
'enable_tinymce' => $enable_tinymce ? '1' : '0',
'access' => $access
)
);
else
$errors[] = 'Page with this link already exists.';
return !count($errors);
}
static public function update($id, $name, $title, $body, $player_id, $php, $enable_tinymce, $access, &$errors)
{
if(!self::verify($name, $title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) {
return false;
}
global $db;
$db->update(TABLE_PREFIX . 'pages',
array(
'name' => $name,
'title' => $title,
'body' => $body,
'player_id' => $player_id,
'php' => $php ? '1' : '0',
'enable_tinymce' => $enable_tinymce ? '1' : '0',
'access' => $access
),
array('id' => $id));
return true;
}
static public function delete($id, &$errors)
{
global $db;
if (isset($id)) {
if ($db->select(TABLE_PREFIX . 'pages', array('id' => $id)) !== false)
$db->delete(TABLE_PREFIX . 'pages', array('id' => $id));
else
$errors[] = 'Page with id ' . $id . ' does not exists.';
} else
$errors[] = 'id not set';
return !count($errors);
}
static public function toggleHidden($id, &$errors, &$status)
{
global $db;
if (isset($id)) {
$query = $db->select(TABLE_PREFIX . 'pages', array('id' => $id));
if ($query !== false) {
$db->update(TABLE_PREFIX . 'pages', array('hidden' => ($query['hidden'] == 1 ? 0 : 1)), array('id' => $id));
$status = $query['hidden'];
}
else {
$errors[] = 'Page with id ' . $id . ' does not exists.';
}
} else
$errors[] = 'id not set';
return !count($errors);
}
}
]);

View File

@@ -7,9 +7,15 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Player;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Player editor';
csrfProtect();
$player_base = ADMIN_URL . '?p=players';
$use_datatable = true;
@@ -72,7 +78,7 @@ else if (isset($_REQUEST['search'])) {
$player = new OTS_Player();
$player->load($id);
if (isset($player) && $player->isLoaded() && isset($_POST['save'])) {// we want to save
if ($player->isLoaded() && isset($_POST['save'])) {// we want to save
$error = false;
if ($player->isOnline())
@@ -370,6 +376,7 @@ else if (isset($_REQUEST['search'])) {
</ul>
</div>
<form action="<?php echo $player_base . ((isset($id) && $id > 0) ? '&id=' . $id : ''); ?>" method="post">
<?php csrf(); ?>
<div class="card-body">
<div class="tab-content" id="tabs-tabContent">
<div class="tab-pane fade active show" id="tabs-home">
@@ -387,8 +394,8 @@ else if (isset($_REQUEST['search'])) {
<div class="col-12 col-sm-12 col-lg-6">
<label for="group">Group:</label>
<select name="group" id="group" class="form-control custom-select">
<?php foreach ($groups->getGroups() as $id => $group): ?>
<option value="<?php echo $id; ?>" <?php echo($player->getGroup()->getId() == $id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option>
<?php foreach ($groups->getGroups() as $_id => $group): ?>
<option value="<?php echo $_id; ?>" <?php echo($player->getGroup()->getId() == $_id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option>
<?php endforeach; ?>
</select>
</div>
@@ -396,8 +403,8 @@ else if (isset($_REQUEST['search'])) {
<label for="vocation">Vocation</label>
<select name="vocation" id="vocation" class="form-control custom-select">
<?php
foreach ($config['vocations'] as $id => $name) {
echo '<option value=' . $id . ($id == $player->getVocation() ? ' selected' : '') . '>' . $name . '</option>';
foreach ($config['vocations'] as $_id => $name) {
echo '<option value=' . $_id . ($_id == $player->getVocation() ? ' selected' : '') . '>' . $name . '</option>';
}
?>
</select>
@@ -407,8 +414,8 @@ else if (isset($_REQUEST['search'])) {
<div class="col-12 col-sm-12 col-lg-6">
<label for="sex">Sex:</label>
<select name="sex" id="sex" class="form-control custom-select">>
<?php foreach ($config['genders'] as $id => $sex): ?>
<option value="<?php echo $id; ?>" <?php echo($player->getSex() == $id ? 'selected' : ''); ?>><?php echo strtolower($sex); ?></option>
<?php foreach ($config['genders'] as $_id => $sex): ?>
<option value="<?php echo $_id; ?>" <?php echo($player->getSex() == $_id ? 'selected' : ''); ?>><?php echo strtolower($sex); ?></option>
<?php endforeach; ?>
</select>
</div>
@@ -421,8 +428,8 @@ else if (isset($_REQUEST['search'])) {
$configTowns[$player->getTownId()] = 'Unknown Town';
}
foreach ($configTowns as $id => $town): ?>
<option value="<?php echo $id; ?>" <?php echo($player->getTownId() == $id ? 'selected' : ''); ?>><?php echo $town; ?></option>
foreach ($configTowns as $_id => $town): ?>
<option value="<?php echo $_id; ?>" <?php echo($player->getTownId() == $_id ? 'selected' : ''); ?>><?php echo $town; ?></option>
<?php endforeach; ?>
</select>
</div>
@@ -433,8 +440,8 @@ else if (isset($_REQUEST['search'])) {
<select name="skull" id="skull" class="form-control custom-select">
<?php
foreach ($skull_type as $id => $s_name) {
echo '<option value=' . $id . ($id == $player->getSkull() ? ' selected' : '') . '>' . $s_name . '</option>';
foreach ($skull_type as $_id => $s_name) {
echo '<option value=' . $_id . ($_id == $player->getSkull() ? ' selected' : '') . '>' . $s_name . '</option>';
}
?>
</select>
@@ -551,22 +558,22 @@ else if (isset($_REQUEST['search'])) {
</div>
<div class="tab-pane fade" id="tabs-skills">
<?php
foreach ($skills as $id => $info) {
foreach ($skills as $_id => $info) {
?>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<?php echo '<label for="skills[' . $id . ']" class="control-label">' . $info[0] . '</label>
<input type="text" class="form-control" id="skills[' . $id . ']" name="skills[' . $id . ']" maxlength="10" autocomplete="off" value="' . $player->getSkill($id) . '"/>'; ?>
<?php echo '<label for="skills[' . $_id . ']" class="control-label">' . $info[0] . '</label>
<input type="text" class="form-control" id="skills[' . $_id . ']" name="skills[' . $_id . ']" maxlength="10" autocomplete="off" value="' . $player->getSkill($_id) . '"/>'; ?>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<?php echo '<label for="skills_tries[' . $id . ']" class="control-label">' . $info[0] . ' tries</label>
<input type="text" class="form-control" id="skills_tries[' . $id . ']" name="skills_tries[' . $id . ']" maxlength="10" autocomplete="off" value="' . $player->getSkillTries($id) . '"/>'; ?>
<?php echo '<label for="skills_tries[' . $_id . ']" class="control-label">' . $info[0] . ' tries</label>
<input type="text" class="form-control" id="skills_tries[' . $_id . ']" name="skills_tries[' . $_id . ']" maxlength="10" autocomplete="off" value="' . $player->getSkillTries($_id) . '"/>'; ?>
</div>
</div>
<?php } ?>
</div>
<div class="tab-pane fade" id="tabs-pos">
<?php $outfit = $config['outfit_images_url'] . '?id=' . $player->getLookType() . ($hasLookAddons ? '&addons=' . $player->getLookAddons() : '') . '&head=' . $player->getLookHead() . '&body=' . $player->getLookBody() . '&legs=' . $player->getLookLegs() . '&feet=' . $player->getLookFeet(); ?>
<?php $outfit = setting('core.outfit_images_url') . '?id=' . $player->getLookType() . ($hasLookAddons ? '&addons=' . $player->getLookAddons() : '') . '&head=' . $player->getLookHead() . '&body=' . $player->getLookBody() . '&legs=' . $player->getLookLegs() . '&feet=' . $player->getLookFeet(); ?>
<div id="imgchar" style="width:64px;height:64px;position:absolute; top:30px; right:30px">
<img id="player_outfit" style="margin-left:0;margin-top:0;width:64px;height:64px;" src="<?php echo $outfit; ?>" alt="player outfit"/>
</div>
@@ -619,7 +626,7 @@ else if (isset($_REQUEST['search'])) {
if ($outfitlist) { ?>
<select name="look_type" id="look_type" class="form-control custom-select">
<?php
foreach ($outfitlist as $id => $outfit) {
foreach ($outfitlist as $_id => $outfit) {
if ($outfit['enabled'] == 'yes') ;
echo '<option value=' . $outfit['id'] . ($outfit['id'] == $player->getLookType() ? ' selected' : '') . '>' . $outfit['name'] . ' - ' . ($outfit['type'] == 1 ? 'Male' : 'Female') . '</option>';
}
@@ -635,8 +642,8 @@ else if (isset($_REQUEST['search'])) {
<select name="look_addons" id="look_addons" class="form-control custom-select">
<?php
$addon_type = array("None", "First", "Second", "Both");
foreach ($addon_type as $id => $s_name) {
echo '<option value=' . $id . ($id == $player->getLookAddons() ? ' selected' : '') . '>' . $s_name . '</option>';
foreach ($addon_type as $_id => $s_name) {
echo '<option value=' . $_id . ($_id == $player->getLookAddons() ? ' selected' : '') . '>' . $s_name . '</option>';
}
?>
</select>
@@ -701,7 +708,7 @@ else if (isset($_REQUEST['search'])) {
<div class="form-group row">
<div class="col-12">
<label for="comment" class="control-label">Comment:</label>
<textarea class="form-control" name="comment" rows="10" cols="50" wrap="virtual"><?php echo $player->getCustomField("comment"); ?></textarea>
<textarea class="form-control" id="comment" name="comment" rows="10" cols="50" wrap="virtual"><?php echo $player->getCustomField("comment"); ?></textarea>
<small>[max. length: 2000 chars, 50 lines (ENTERs)]</small>
</div>
</div>
@@ -744,8 +751,7 @@ else if (isset($_REQUEST['search'])) {
<div class="row">
<?php
if (isset($account) && $account->isLoaded()) {
$account_players = $account->getPlayersList();
$account_players->orderBy('id');
$account_players = Player::where('account_id', $account->getId())->orderBy('id')->get();
if (isset($account_players)) { ?>
<table class="table table-striped table-condensed table-responsive d-md-table">
<thead>
@@ -758,23 +764,13 @@ else if (isset($_REQUEST['search'])) {
</tr>
</thead>
<tbody>
<?php foreach ($account_players as $i => $player):
$player_vocation = $player->getVocation();
$player_promotion = $player->getPromotion();
if (isset($player_promotion)) {
if ((int)$player_promotion > 0)
$player_vocation += ($player_promotion * $config['vocations_amount']);
}
if (isset($config['vocations'][$player_vocation])) {
$vocation_name = $config['vocations'][$player_vocation];
} ?>
<?php foreach ($account_players as $i => $player): ?>
<tr>
<th><?php echo $i; ?></th>
<td><?php echo $player->getName(); ?></td>
<td><?php echo $player->getLevel(); ?></td>
<td><?php echo $vocation_name; ?></td>
<td><a href="?p=players&id=<?php echo $player->getId() ?>" class=" btn btn-success btn-sm" title="Edit"><i class="fas fa-pencil-alt"></i></a></td>
<th><?php echo $i + 1; ?></th>
<td><?php echo $player->name; ?></td>
<td><?php echo $player->level; ?></td>
<td><?php echo $player->vocation_name; ?></td>
<td><a href="?p=players&id=<?php echo $player->getKey() ?>" class=" btn btn-success btn-sm" title="Edit"><i class="fas fa-pencil-alt"></i></a></td>
</tr>
<?php endforeach ?>
</tbody>
@@ -849,7 +845,7 @@ else if (isset($_REQUEST['search'])) {
<?php if($hasLookAddons): ?>
const $addonvalue = $('#look_addons');
$('#look_addons').on('change', () => {
$addonvalue.on('change', () => {
updateOutfit();
});
<?php endif; ?>
@@ -866,7 +862,7 @@ else if (isset($_REQUEST['search'])) {
<?php if($hasLookAddons): ?>
look_addons = '&addons=' + $('#look_addons').val();
<?php endif; ?>
$("#player_outfit").attr("src", '<?= $config['outfit_images_url']; ?>?id=' + look_type + look_addons + '&head=' + look_head + '&body=' + look_body + '&legs=' + look_legs + '&feet=' + look_feet);
$("#player_outfit").attr("src", '<?= setting('core.outfit_images_url'); ?>?id=' + look_type + look_addons + '&head=' + look_head + '&body=' + look_body + '&legs=' + look_legs + '&feet=' + look_feet);
}
</script>
<?php } ?>
@@ -878,18 +874,20 @@ else if (isset($_REQUEST['search'])) {
<div class="card-body row">
<div class="col-6 col-lg-12">
<form action="<?php echo $player_base; ?>" method="post">
<label for="name">Player Name:</label>
<?php csrf(); ?>
<label for="search">Player Name:</label>
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="search" value="<?php echo $search_player; ?>" maxlength="32" size="32">
<input type="text" class="form-control" id="search" name="search" value="<?= escapeHtml($search_player); ?>" maxlength="32" size="32">
<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span>
</div>
</form>
</div>
<div class="col-6 col-lg-12">
<form action="<?php echo $player_base; ?>" method="post">
<label for="name">Player ID:</label>
<?php csrf(); ?>
<label for="id">Player ID:</label>
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="id" value="" maxlength="32" size="32">
<input type="text" class="form-control" id="id" name="id" value="<?= $id; ?>" maxlength="32" size="32">
<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span>
</div>
</form>
@@ -900,7 +898,7 @@ else if (isset($_REQUEST['search'])) {
</div>
<script>
$(document).ready(function () {
$(function () {
$('.player_datatable').DataTable({
"order": [[0, "asc"]]
});

View File

@@ -9,33 +9,36 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Plugin manager';
csrfProtect();
$use_datatable = true;
require_once LIBS . 'plugins.php';
if (!getBoolean(config('admin_plugins_manage_enable'))) {
warning('Plugin installation and management is disabled in config.<br/>If you wish to enable, go to config.php and change <b>admin_plugins_manage_enable</b> to "yes".');
if (!getBoolean(setting('core.admin_plugins_manage_enable'))) {
warning('Plugin installation and management is disabled in Settings.<br/>If you wish to enable, go to Settings and enable <strong>Enable Plugins Manage</strong>.');
}
else {
$twig->display('admin.plugins.form.html.twig');
if (isset($_REQUEST['uninstall'])) {
$uninstall = $_REQUEST['uninstall'];
if (isset($_POST['uninstall'])) {
$uninstall = $_POST['uninstall'];
if (Plugins::uninstall($uninstall)) {
success('Successfully uninstalled plugin ' . $uninstall);
} else {
error('Error while uninstalling plugin ' . $uninstall . ': ' . Plugins::getError());
}
} else if (isset($_REQUEST['enable'])) {
$enable = $_REQUEST['enable'];
} else if (isset($_POST['enable'])) {
$enable = $_POST['enable'];
if (Plugins::enable($enable)) {
success('Successfully enabled plugin ' . $enable);
} else {
error('Error while enabling plugin ' . $enable . ': ' . Plugins::getError());
}
} else if (isset($_REQUEST['disable'])) {
$disable = $_REQUEST['disable'];
} else if (isset($_POST['disable'])) {
$disable = $_POST['disable'];
if (Plugins::disable($disable)) {
success('Successfully disabled plugin ' . $disable);
} else {
@@ -116,7 +119,7 @@ foreach (get_plugins(true) as $plugin) {
if (!$plugin_info) {
warning('Cannot load plugin info ' . $plugin . '.json');
} else {
$disabled = (strpos($plugin, 'disabled.') !== false);
$disabled = (str_contains($plugin, 'disabled.'));
$pluginOriginal = ($disabled ? str_replace('disabled.', '', $plugin) : $plugin);
$plugins[] = array(
'name' => $plugin_info['name'] ?? '',

56
admin/pages/settings.php Normal file
View File

@@ -0,0 +1,56 @@
<?php
/**
* Menus
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Settings';
require_once SYSTEM . 'clients.conf.php';
if (empty($_GET['plugin'])) {
error('Please select plugin from left Panel.');
return;
}
$plugin = $_GET['plugin'];
if($plugin != 'core') {
$pluginSettings = Plugins::getPluginSettings($plugin);
if (!$pluginSettings) {
error('This plugin does not exist or does not have settings defined.');
return;
}
$settingsFilePath = BASE . $pluginSettings;
}
else {
$settingsFilePath = SYSTEM . 'settings.php';
}
if (!file_exists($settingsFilePath)) {
error("Plugin $plugin does not exist or does not have settings defined.");
return;
}
$settingsFile = require $settingsFilePath;
if (!is_array($settingsFile)) {
error("Cannot load settings file for plugin $plugin");
return;
}
$settingsKeyName = ($plugin == 'core' ? $plugin : $settingsFile['key']);
$title = ($plugin == 'core' ? 'Settings' : 'Plugin Settings - ' . $plugin);
$settingsParsed = Settings::display($settingsKeyName, $settingsFile['settings']);
$twig->display('admin.settings.html.twig', [
'settingsParsed' => $settingsParsed['content'],
'settings' => $settingsFile['settings'],
'script' => $settingsParsed['script'],
'settingsKeyName' => $settingsKeyName,
]);

View File

@@ -7,26 +7,25 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Account;
use MyAAC\Models\Guild;
use MyAAC\Models\House;
use MyAAC\Models\Player;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Statistics';
$query = $db->query('SELECT count(*) as `how_much` FROM `accounts`;');
$query = $query->fetch();
$total_accounts = $query['how_much'];
$total_accounts = Account::count();
$total_players = Player::count();
$total_guilds = Guild::count();
$total_houses = House::count();
$query = $db->query('SELECT count(*) as `how_much` FROM `players`;');
$query = $query->fetch();
$total_players = $query['how_much'];
$query = $db->query('SELECT count(*) as `how_much` FROM `guilds`;');
$query = $query->fetch();
$total_guilds = $query['how_much'];
$query = $db->query('SELECT count(*) as `how_much` FROM `houses`;');
$query = $query->fetch();
$total_houses = $query['how_much'];
$points = $db->query('SELECT `premium_points`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `premium_points` DESC LIMIT 10;');
$points = Account::select(['premium_points', (USE_ACCOUNT_NAME ? 'name' : 'id')])
->orderByDesc('premium_points')
->limit(10)
->get()
->toArray();
$twig->display('admin.statistics.html.twig', array(
'total_accounts' => $total_accounts,

View File

@@ -16,7 +16,7 @@ use DeviceDetector\Parser\OperatingSystem;
$title = 'Visitors';
$use_datatable = true;
if (!$config['visitors_counter']): ?>
if (!setting('core.visitors_counter')): ?>
Visitors counter is disabled.<br/>
You can enable it by editing this configurable in <b>config.local.php</b> file:<br/>
<p style="margin-left: 3em;"><b>$config['visitors_counter'] = true;</b></p>
@@ -25,10 +25,9 @@ if (!$config['visitors_counter']): ?>
endif;
require SYSTEM . 'libs/visitors.php';
$visitors = new Visitors($config['visitors_counter_ttl']);
$visitors = new Visitors(setting('core.visitors_counter_ttl'));
function compare($a, $b)
{
function compare($a, $b): int {
return $a['lastvisit'] > $b['lastvisit'] ? -1 : 1;
}
@@ -61,7 +60,7 @@ foreach ($tmp as &$visitor) {
}
$twig->display('admin.visitors.html.twig', array(
'config_visitors_counter_ttl' => $config['visitors_counter_ttl'],
'config_visitors_counter_ttl' => setting('core.visitors_counter_ttl'),
'visitors' => $tmp
));
?>

View File

@@ -1,8 +1,11 @@
<?php
$menus = [
return [
['name' => 'Dashboard', 'icon' => 'tachometer-alt', 'order' => 10, 'link' => 'dashboard'],
['name' => 'News', 'icon' => 'newspaper', 'order' => 20, 'link' =>
['name' => 'Settings', 'icon' => 'edit', 'order' => 19, 'link' =>
require ADMIN . 'includes/settings_menus.php'
],
['name' => 'News', 'icon' => 'newspaper', 'order' => 20, 'link' =>
[
['name' => 'View', 'link' => 'news', 'icon' => 'list', 'order' => 10],
['name' => 'Add news', 'link' => 'news&action=new&type=1', 'icon' => 'plus', 'order' => 20],
@@ -16,7 +19,7 @@ $menus = [
['name' => 'Add', 'link' => 'changelog&action=new', 'icon' => 'plus', 'order' => 20],
],
],
['name' => 'Mailer', 'icon' => 'envelope', 'order' => 40, 'link' => 'mailer', 'disabled' => !config('mail_enabled')],
['name' => 'Mailer', 'icon' => 'envelope', 'order' => 40, 'link' => 'mailer', 'disabled' => !setting('core.mail_enabled')],
['name' => 'Pages', 'icon' => 'book', 'order' => 50, 'link' =>
[
['name' => 'View', 'link' => 'pages', 'icon' => 'list', 'order' => 10],

View File

@@ -0,0 +1,43 @@
<?php
const MYAAC_ADMIN = true;
require '../../common.php';
require SYSTEM . 'functions.php';
require SYSTEM . 'init.php';
require SYSTEM . 'login.php';
// event system
require_once SYSTEM . 'hooks.php';
$hooks = new Hooks();
$hooks->load();
if(!admin()) {
http_response_code(500);
die('Access denied.');
}
csrfProtect();
if (!isset($_REQUEST['plugin'])) {
http_response_code(500);
die('Please enter plugin name.');
}
if (!isset($_POST['settings'])) {
http_response_code(500);
die('Please enter settings.');
}
$settings = Settings::getInstance();
$success = $settings->save($_REQUEST['plugin'], $_POST['settings']);
$errors = $settings->getErrors();
if (count($errors) > 0) {
http_response_code(500);
die(implode('<br/>', $errors));
}
if ($success) {
echo 'Saved at ' . date('H:i');
}

View File

@@ -23,11 +23,11 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
if (version_compare(phpversion(), '7.2.5', '<')) die('PHP version 7.2.5 or higher is required.');
if (version_compare(phpversion(), '8.0', '<')) die('PHP version 8.0 or higher is required.');
const MYAAC = true;
const MYAAC_VERSION = '0.9.0-alpha';
const DATABASE_VERSION = 35;
const MYAAC_VERSION = '0.10.0-dev';
const DATABASE_VERSION = 36;
const TABLE_PREFIX = 'myaac_';
define('START_TIME', microtime(true));
define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));
@@ -108,6 +108,13 @@ const TFS_FIRST = TFS_02;
const TFS_LAST = TFS_03;
// other definitions
const MAIL_MAIL = 0;
const MAIL_SMTP = 1;
const SMTP_SECURITY_NONE = 0;
const SMTP_SECURITY_SSL = 1;
const SMTP_SECURITY_TLS = 2;
const ACCOUNT_NUMBER_LENGTH = 8;
if (!IS_CLI) {
@@ -136,16 +143,41 @@ if(!IS_CLI) {
}
}
define('SERVER_URL', 'http' . (isset($_SERVER['HTTPS'][0]) && strtolower($_SERVER['HTTPS']) === 'on' ? 's' : '') . '://' . $baseHost);
define('SERVER_URL', 'http' . (isHttps() ? 's' : '') . '://' . $baseHost);
define('BASE_URL', SERVER_URL . BASE_DIR . '/');
define('ADMIN_URL', SERVER_URL . BASE_DIR . '/' . ADMIN_PANEL_FOLDER . '/');
//define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']);
}
if (file_exists(BASE . 'config.local.php')) {
require BASE . 'config.local.php';
}
/** @var array $config */
ini_set('log_errors', 1);
if(@$config['env'] === 'dev') {
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
}
else {
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);
}
$autoloadFile = VENDOR . 'autoload.php';
if (!is_file($autoloadFile)) {
throw new RuntimeException('The vendor folder is missing. Please download Composer: <a href="https://getcomposer.org/download">https://getcomposer.org/download</a>, install it and execute in the main MyAAC directory this command: <b>composer install</b>. Or download MyAAC from <a href="https://github.com/slawkens/myaac/releases">GitHub releases</a>, which includes Vendor folder.');
}
require $autoloadFile;
function isHttps(): bool
{
return
(!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https')
|| (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
|| (isset($_SERVER['SERVER_PORT']) && (int) $_SERVER['SERVER_PORT'] === 443);
}

View File

@@ -1,6 +1,6 @@
{
"require": {
"php": "^7.2.5 || ^8.0",
"php": "^8.0",
"ext-pdo": "*",
"ext-pdo_mysql": "*",
"ext-json": "*",
@@ -11,9 +11,16 @@
"twig/twig": "^2.0",
"erusev/parsedown": "^1.7",
"nikic/fast-route": "^1.3",
"matomo/device-detector": "^6.0"
"matomo/device-detector": "^6.0",
"illuminate/database": "^10.18",
"peppeocchi/php-cron-scheduler": "4.*"
},
"require-dev": {
"filp/whoops": "^2.15"
},
"autoload": {
"psr-4": {
"MyAAC\\": "system/src"
}
}
}

View File

@@ -1,318 +0,0 @@
<?php
/**
* This is MyAAC's Main Configuration file
*
* All the default values are kept here, you should not modify it but use
* a config.local.php file instead to override the settings from here.
*
* This is a piece of PHP code so PHP syntax applies!
* For boolean values please use true/false.
*
* Minimally 'server_path' directive have to be filled, other options are optional.
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
$config = array(
// directories & files
'server_path' => '', // path to the server directory (same directory where config file is located)
/**
* Environment Setting
*
* if you use this script on your live server - set to 'prod' (production)
* if you want to test and debug the script locally, or develop plugins, set to 'dev' (development)
* WARNING: on 'dev' cache is disabled, so site will be significantly slower !!!
* WARNING2: on 'dev' all PHP errors/warnings are displayed
* Recommended: 'prod' cause of speed (page load time is better)
*/
'env' => 'prod', // 'prod' for production and 'dev' for development
'template' => 'kathrine', // template used by website (kathrine, tibiacom)
'template_allow_change' => true, // allow users to choose their own template while browsing website?
'vocations_amount' => 4, // how much basic vocations your server got (without promotion)
// what client version are you using on this OT?
// used for the Downloads page and some templates aswell
'client' => 1098, // 954 = client 9.54
'session_prefix' => 'myaac_', // must be unique for every site on your server
'friendly_urls' => false, // mod_rewrite is required for this, it makes links looks more elegant to eye, and also are SEO friendly (example: https://my-aac.org/guilds/Testing instead of https://my-aac.org/?subtopic=guilds&name=Testing). Remember to rename .htaccess.dist to .htaccess
'gzip_output' => false, // gzip page content before sending it to the browser, uses less bandwidth but more cpu cycles
// gesior backward support (templates & pages)
// allows using gesior templates and pages with myaac
// might bring some performance when disabled
'backward_support' => true,
// head options (html)
'meta_description' => 'Tibia is a free massive multiplayer online role playing game (MMORPG).', // description of the site
'meta_keywords' => 'free online game, free multiplayer game, ots, open tibia server', // keywords list separated by commas
// footer
'footer' => ''/*'<br/>Your Server &copy; 2016. All rights reserved.'*/,
'language' => 'en', // default language (currently only 'en' available)
'language_allow_change' => false,
'visitors_counter' => true,
'visitors_counter_ttl' => 10, // how long visitor will be marked as online (in minutes)
'views_counter' => true,
// cache system. by default file cache is used
'cache_engine' => 'auto', // apc, apcu, eaccelerator, xcache, file, auto, or blank to disable.
'cache_prefix' => 'myaac_', // have to be unique if running more MyAAC instances on the same server (except file system cache)
// database details (leave blank for auto detect from config.lua)
'database_host' => '',
'database_port' => '', // leave blank to default 3306
'database_user' => '',
'database_password' => '',
'database_name' => '',
'database_log' => false, // should database queries be logged and saved into system/logs/database.log?
'database_socket' => '', // set if you want to connect to database through socket (example: /var/run/mysqld/mysqld.sock)
'database_persistent' => false, // use database permanent connection (like server), may speed up your site
// multiworld system (only TFS 0.3)
'multiworld' => false, // use multiworld system?
'worlds' => array( // list of worlds
//'1' => 'Your World Name',
//'2' => 'Your Second World Name'
),
// images
'outfit_images_url' => 'https://outfit-images.ots.me/outfit.php', // set to animoutfit.php for animated outfit
'outfit_images_wrong_looktypes' => [75, 126, 127, 266, 302], // this looktypes needs to have different margin-top and margin-left because they are wrong positioned
'item_images_url' => 'https://item-images.ots.me/1092/', // set to images/items if you host your own items in images folder
'item_images_extension' => '.gif',
// creatures
'creatures_images_url' => 'images/monsters/', // set to images/monsters if you host your own creatures in images folder
'creatures_images_extension' => '.gif',
'creatures_images_preview' => false, // set to true to allow picture previews for creatures
'creatures_items_url' => 'https://tibia.fandom.com/wiki/', // set to website which shows details about items.
'creatures_loot_percentage' => true, // set to true to show the loot tooltip percent
// account
'account_management' => true, // disable if you're using other method to manage users (fe. tfs account manager)
'account_login_by_email' => false, // use email instead of Account Name like in latest Tibia
'account_login_by_email_fallback' => false, // allow also additionally login by Account Name/Number (for users that might forget their email)
'account_create_auto_login' => false, // auto login after creating account?
'account_create_character_create' => true, // allow directly to create character on create account page?
'account_mail_verify' => false, // force users to confirm their email addresses when registering
'account_mail_confirmed_reward' => [ // reward users for confirming their E-Mails
// account_mail_verify needs to be enabled too
'premium_days' => 0,
'premium_points' => 0,
'coins' => 0,
'message' => 'You received %d %s for confirming your E-Mail address.' // example: You received 20 premium points for confirming your E-Mail address.
],
'account_mail_unique' => true, // email addresses cannot be duplicated? (one account = one email)
'account_mail_block_plus_sign' => true, // block email with '+' signs like test+box@gmail.com (help protect against spamming accounts)
'account_premium_days' => 0, // default premium days on new account
'account_premium_points' => 0, // default premium points on new account
'account_welcome_mail' => true, // send welcome email when user registers
'account_mail_change' => 2, // how many days user need to change email to account - block hackers
'account_country' => true, // user will be able to set country of origin when registering account, this information will be viewable in others places aswell
'account_country_recognize' => true, // should country of user be automatically recognized by his IP? This makes an external API call to http://ipinfo.io
'account_change_character_name' => false, // can user change their character name for premium points?
'account_change_character_name_points' => 30, // cost of name change
'account_change_character_sex' => false, // can user change their character sex for premium points?
'account_change_character_sex_points' => 30, // cost of sex change
'characters_per_account' => 10, // max. number of characters per account
// mail
'mail_enabled' => false, // is aac maker configured to send e-mails?
'mail_address' => 'no-reply@your-server.org', // server e-mail address (from:)
'mail_admin' => 'your-address@your-server.org', // admin email address, where mails from contact form will be sent
'mail_signature' => array( // signature that will be included at the end of every message sent using _mail function
'plain' => ""/*"--\nMy Server,\nhttp://www.myserver.com"*/,
'html' => ''/*'<br/>My Server,\n<a href="http://www.myserver.com">myserver.com</a>'*/
),
'smtp_enabled' => false, // send by smtp or mail function (set false if use mail function, set to true if you use GMail or Microsoft Outlook)
'smtp_host' => '', // mail host. smtp.gmail.com for GMail / smtp-mail.outlook.com for Microsoft Outlook
'smtp_port' => 25, // 25 (default) / 465 (ssl, GMail) / 587 (tls, Microsoft Outlook)
'smtp_auth' => true, // need authorization?
'smtp_user' => 'admin@example.org', // here your email username
'smtp_pass' => '',
'smtp_secure' => '', // What kind of encryption to use on the SMTP connection. Options: '', 'ssl' (GMail) or 'tls' (Microsoft Outlook)
'smtp_debug' => false, // set true to debug (you will see more info in error.log)
//
'generate_new_reckey' => true, // let player generate new recovery key, he will receive e-mail with new rec key (not display on page, hacker can't generate rec key)
'generate_new_reckey_price' => 20, // price for new recovery key
'send_mail_when_change_password' => true, // send e-mail with new password when change password to account
'send_mail_when_generate_reckey' => true, // send e-mail with rec key (key is displayed on page anyway when generate)
// you may need to adjust this for older tfs versions
// by removing Community Manager
'account_types' => [
'None',
'Normal',
'Tutor',
'Senior Tutor',
'Gamemaster',
'Community Manager',
'God',
],
// genders (aka sex)
'genders' => array(
0 => 'Female',
1 => 'Male'
),
// new character config
'character_samples' => array( // vocations, format: ID_of_vocation => 'Name of Character to copy'
//0 => 'Rook Sample',
1 => 'Sorcerer Sample',
2 => 'Druid Sample',
3 => 'Paladin Sample',
4 => 'Knight Sample'
),
'use_character_sample_skills' => false,
// it must show limited number of players after using search in character page
'characters_search_limit' => 15,
// town list used when creating character
// won't be displayed if there is only one item (rookgaard for example)
'character_towns' => array(1),
// characters length
// This is the minimum and the maximum length that a player can create a character. It is highly recommend the maximum length to be 21.
'character_name_min_length' => 4,
'character_name_max_length' => 21,
'character_name_npc_check' => true,
// list of towns
// if you use TFS 1.3 with support for 'towns' table in database, then you can ignore this - it will be configured automatically (from MySQL database - Table - towns)
// otherwise it will try to load from your .OTBM map file
// if you don't see towns on website, then you need to fill this out
'towns' => array(
0 => 'No town',
1 => 'Sample town'
),
// guilds
'guild_management' => true, // enable guild management system on the site?
'guild_need_level' => 1, // min. level to form a guild
'guild_need_premium' => true, // require premium account to form a guild?
'guild_image_size_kb' => 80, // maximum size of the guild logo image in KB (kilobytes)
'guild_description_default' => 'New guild. Leader must edit this text :)',
'guild_description_chars_limit' => 1000, // limit of guild description
'guild_description_lines_limit' => 6, // limit of lines, if description has more lines it will be showed as long text, without 'enters'
'guild_motd_chars_limit' => 150, // limit of MOTD (message of the day) that is shown later in the game on the guild channel
// online page
'online_record' => true, // display players record?
'online_vocations' => false, // display vocation statistics?
'online_vocations_images' => false, // display vocation images?
'online_skulls' => false, // display skull images
'online_outfit' => true,
'online_afk' => false,
// support list page
'team_style' => 2, // 1/2 (1 - normal table, 2 - in boxes, grouped by group id)
'team_display_status' => true,
'team_display_lastlogin' => true,
'team_display_world' => false,
'team_display_outfit' => true,
// bans page
'bans_per_page' => 20,
// highscores page
'highscores_vocation_box' => true, // show 'Choose a vocation' box on the highscores (allowing peoples to sort highscores by vocation)?
'highscores_vocation' => true, // show player vocation under his nickname?
'highscores_frags' => false, // show 'Frags' tab (best fraggers on the server)?
'highscores_balance' => false, // show 'Balance' tab (richest players on the server)
'highscores_outfit' => true, // show player outfit?
'highscores_country_box' => false, // doesnt work yet! (not implemented)
'highscores_groups_hidden' => 3, // this group id and higher won't be shown on the highscores
'highscores_ids_hidden' => array(0), // this ids of players will be hidden on the highscores (should be ids of samples)
'highscores_per_page' => 100, // how many records per page on highscores
'highscores_cache_ttl' => 15, // how often to update highscores from database in minutes (default 15 minutes)
// characters page
'characters' => array( // what things to display on character view page (true/false in each option)
'level' => true,
'experience' => false,
'magic_level' => false,
'balance' => false,
'marriage_info' => true, // only 0.3
'outfit' => true,
'creation_date' => true,
'quests' => true,
'skills' => true,
'equipment' => true,
'frags' => false,
'deleted' => false, // should deleted characters from same account be still listed on the list of characters? When enabled it will show that character is "[DELETED]"
),
'quests' => array(
//'Some Quest' => 123,
//'Some Quest Two' => 456,
), // quests list (displayed in character view), name => storage
'signature_enabled' => true,
'signature_type' => 'tibian', // signature engine to use: tibian, mango, gesior
'signature_cache_time' => 5, // how long to store cached file (in minutes), default 5 minutes
'signature_browser_cache' => 60, // how long to cache by browser (in minutes), default 1 hour
// news page
'news_limit' => 5, // limit of news on the latest news page
'news_ticker_limit' => 5, // limit of news in tickers (mini news) (0 to disable)
'news_date_format' => 'j.n.Y', // check php manual date() function for more info about this
'news_author' => true, // show author of the news
// gifts/shop system
'gifts_system' => false,
// support/system
'bug_report' => true, // this configurable has no effect, its always enabled
// forum
'forum' => 'site', // link to the server forum, set to "site" if you want to use build in forum system, otherwise leave empty if you aren't going to use any forum
'forum_level_required' => 0, // level required to post, 0 to disable
'forum_post_interval' => 30, // in seconds
'forum_posts_per_page' => 20,
'forum_threads_per_page' => 20,
// uncomment to force use table for forum
//'forum_table_prefix' => 'z_', // what forum mysql table to use, z_ (for gesior old forum) or myaac_ (for myaac)
// last kills
'last_kills_limit' => 50, // max. number of deaths shown on the last kills page
// status, took automatically from config file if empty
'status_enabled' => true, // you can disable status checking by settings this to "false"
'status_ip' => '',
'status_port' => '',
'status_timeout' => 2.0, // how long to wait for the initial response from the server (default: 2 seconds)
// how often to connect to server and update status (default: every minute)
// if your status timeout in config.lua is bigger, that it will be used instead
// when server is offline, it will be checked every time web refreshes, ignoring this variable
'status_interval' => 60,
// admin panel
'admin_plugins_manage_enable' => 'yes', // you can disable possibility to upload and uninstall plugins, for security
// enable support for plain php pages in admin panel, for security
// existing pages still will be working, so you need to delete them manually
'admin_pages_php_enable' => 'no',
'admin_panel_modules' => 'statistics,web_status,server_status,lastlogin,created,points,coins,balance', // default - statistics,web_status,server_status,lastlogin,created,points,coins,balance
// other
'anonymous_usage_statistics' => true,
'email_lai_sec_interval' => 60, // time in seconds between e-mails to one account from lost account interface, block spam
'google_analytics_id' => '', // e.g.: UA-XXXXXXX-X
'experiencetable_columns' => 3, // how many columns to display in experience table page. * experiencetable_rows, 5 = 500 (will show up to 500 level)
'experiencetable_rows' => 200, // till how many levels in one column
'date_timezone' => 'Europe/Berlin', // more info at http://php.net/manual/en/timezones.php
'footer_show_load_time' => true, // display load time of the page in the footer
'npc' => array()
);

View File

@@ -14,7 +14,7 @@ describe('Create Account Page', () => {
cy.get('#email').type('tester@example.com')
cy.get('#password').type('test1234')
cy.get('#password2').type('test1234')
cy.get('#password_confirm').type('test1234')
cy.get('#character_name').type('Slaw')

View File

@@ -56,22 +56,6 @@ if(preg_match("/^(.*)\.(gif|jpg|png|jpeg|tiff|bmp|css|js|less|map|html|zip|rar|g
exit;
}
if(file_exists(BASE . 'config.local.php')) {
require_once BASE . 'config.local.php';
}
ini_set('log_errors', 1);
if(config('env') === 'dev') {
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
}
else {
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);
}
if((!isset($config['installed']) || !$config['installed']) && file_exists(BASE . 'install'))
{
header('Location: ' . BASE_URL . 'install/');
@@ -87,10 +71,6 @@ if(!$db->hasTable('myaac_account_actions')) {
throw new RuntimeException('Seems that the table <strong>myaac_account_actions</strong> of MyAAC doesn\'t exist in the database. This is a fatal error. You can try to reinstall MyAAC by visiting <a href="' . BASE_URL . 'install">this</a> url.');
}
// event system
require_once SYSTEM . 'hooks.php';
$hooks = new Hooks();
$hooks->load();
require_once SYSTEM . 'template.php';
require_once SYSTEM . 'login.php';
require_once SYSTEM . 'status.php';
@@ -100,13 +80,11 @@ $twig->addGlobal('status', $status);
require_once SYSTEM . 'router.php';
require SYSTEM . 'migrate.php';
$hooks->trigger(HOOK_STARTUP);
// anonymous usage statistics
// sent only when user agrees
if(isset($config['anonymous_usage_statistics']) && $config['anonymous_usage_statistics']) {
if(setting('core.anonymous_usage_statistics')) {
$report_time = 30 * 24 * 60 * 60; // report one time per 30 days
$should_report = true;
@@ -139,17 +117,16 @@ if(isset($config['anonymous_usage_statistics']) && $config['anonymous_usage_stat
}
}
if($config['views_counter'])
if(setting('core.views_counter'))
require_once SYSTEM . 'counter.php';
if($config['visitors_counter'])
{
if(setting('core.visitors_counter')) {
require_once SYSTEM . 'libs/visitors.php';
$visitors = new Visitors($config['visitors_counter_ttl']);
$visitors = new Visitors(setting('core.visitors_counter_ttl'));
}
// backward support for gesior
if($config['backward_support']) {
if(setting('core.backward_support')) {
define('INITIALIZED', true);
$SQL = $db;
$layout_header = template_header();
@@ -165,7 +142,7 @@ if($config['backward_support']) {
$config['site'] = &$config;
$config['server'] = &$config['lua'];
$config['site']['shop_system'] = $config['gifts_system'];
$config['site']['shop_system'] = setting('core.gifts_system');
$config['site']['gallery_page'] = true;
if(!isset($config['vdarkborder']))
@@ -179,8 +156,9 @@ if($config['backward_support']) {
$config['site']['serverinfo_page'] = true;
$config['site']['screenshot_page'] = true;
if($config['forum'] != '')
$config['forum_link'] = (strtolower($config['forum']) === 'site' ? getLink('forum') : $config['forum']);
$forumSetting = setting('core.forum');
if($forumSetting != '')
$config['forum_link'] = (strtolower($forumSetting) === 'site' ? getLink('forum') : $forumSetting);
foreach($status as $key => $value)
$config['status']['serverStatus_' . $key] = $value;

View File

@@ -1,4 +1,4 @@
SET @myaac_database_version = 35;
SET @myaac_database_version = 36;
CREATE TABLE `myaac_account_actions`
(
@@ -127,75 +127,6 @@ CREATE TABLE `myaac_menu`
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
/* MENU_CATEGORY_NEWS kathrine */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Latest News', 'news', 1, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'News Archive', 'news/archive', 1, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Changelog', 'changelog', 1, 2);
/* MENU_CATEGORY_ACCOUNT kathrine */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Account Management', 'account/manage', 2, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Create Account', 'account/create', 2, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Lost Account?', 'account/lost', 2, 2);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Server Rules', 'rules', 2, 3);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Downloads', 'downloads', 5, 4);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Report Bug', 'bugtracker', 2, 5);
/* MENU_CATEGORY_COMMUNITY kathrine */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Who is Online?', 'online', 3, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Characters', 'characters', 3, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Guilds', 'guilds', 3, 2);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Highscores', 'highscores', 3, 3);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Last Deaths', 'lastkills', 3, 4);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Houses', 'houses', 3, 5);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Bans', 'bans', 3, 6);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Forum', 'forum', 3, 7);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Team', 'team', 3, 8);
/* MENU_CATEGORY_LIBRARY kathrine */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Monsters', 'creatures', 5, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Spells', 'spells', 5, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Server Info', 'serverInfo', 5, 2);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Commands', 'commands', 5, 3);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Gallery', 'gallery', 5, 4);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Experience Table', 'experienceTable', 5, 5);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'FAQ', 'faq', 5, 6);
/* MENU_CATEGORY_SHOP kathrine */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Buy Points', 'points', 6, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Shop Offer', 'gifts', 6, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Shop History', 'gifts/history', 6, 2);
/* MENU_CATEGORY_NEWS tibiacom */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Latest News', 'news', 1, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'News Archive', 'news/archive', 1, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Changelog', 'changelog', 1, 2);
/* MENU_CATEGORY_ACCOUNT tibiacom */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Account Management', 'account/manage', 2, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Create Account', 'account/create', 2, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Lost Account?', 'account/lost', 2, 2);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Server Rules', 'rules', 2, 3);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Downloads', 'downloads', 2, 4);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Report Bug', 'bugtracker', 2, 5);
/* MENU_CATEGORY_COMMUNITY tibiacom */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Characters', 'characters', 3, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Who Is Online?', 'online', 3, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Highscores', 'highscores', 3, 2);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Last Kills', 'lastkills', 3, 3);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Houses', 'houses', 3, 4);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Guilds', 'guilds', 3, 5);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Polls', 'polls', 3, 6);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Bans', 'bans', 3, 7);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Support List', 'team', 3, 8);
/* MENU_CATEGORY_FORUM tibiacom */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Forum', 'forum', 4, 0);
/* MENU_CATEGORY_LIBRARY tibiacom */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Creatures', 'creatures', 5, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Spells', 'spells', 5, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Commands', 'commands', 5, 2);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Exp Stages', 'experienceStages', 5, 3);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Gallery', 'gallery', 5, 4);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Server Info', 'serverInfo', 5, 5);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Experience Table', 'experienceTable', 5, 6);
/* MENU_CATEGORY_SHOP tibiacom */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Buy Points', 'points', 6, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Shop Offer', 'gifts', 6, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Shop History', 'gifts/history', 6, 2);
CREATE TABLE `myaac_monsters` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`hidden` tinyint(1) NOT NULL default 0,
@@ -303,6 +234,16 @@ CREATE TABLE `myaac_gallery`
INSERT INTO `myaac_gallery` (`id`, `ordering`, `comment`, `image`, `thumb`, `author`) VALUES (NULL, 1, 'Demon', 'images/gallery/demon.jpg', 'images/gallery/demon_thumb.gif', 'MyAAC');
CREATE TABLE `myaac_settings`
(
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL DEFAULT '',
`key` VARCHAR(255) NOT NULL DEFAULT '',
`value` TEXT NOT NULL,
PRIMARY KEY (`id`),
KEY `key` (`key`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE `myaac_spells`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,

View File

@@ -12,9 +12,7 @@ require SYSTEM . 'functions.php';
require BASE . 'install/includes/functions.php';
require BASE . 'install/includes/locale.php';
require SYSTEM . 'clients.conf.php';
if(file_exists(BASE . 'config.local.php'))
require BASE . 'config.local.php';
require LIBS . 'Settings.php';
// ignore undefined index from Twig autoloader
$config['env'] = 'prod';
@@ -91,10 +89,6 @@ if($step == 'database') {
break;
}
}
else if($key == 'mail_admin' && !Validator::email($value)) {
$errors[] = $locale['step_config_mail_admin_error'];
break;
}
else if($key == 'timezone' && !in_array($value, DateTimeZone::listIdentifiers())) {
$errors[] = $locale['step_config_timezone_error'];
break;

View File

@@ -11,16 +11,12 @@ if(!isset($_SESSION['var_server_path'])) {
}
if(!$error) {
$content = "<?php";
$content .= PHP_EOL;
$content .= '// place for your configuration directives, so you can later easily update myaac';
$content .= PHP_EOL;
$content .= '$config[\'installed\'] = true;';
$content .= PHP_EOL;
// by default, set env to prod
// user can disable when he wants
$content .= '$config[\'env\'] = \'prod\'; // dev or prod';
$content .= PHP_EOL;
$configToSave = [
// by default, set env to prod
// user can disable when he wants
'env' => 'prod',
];
foreach($_SESSION as $key => $value)
{
if(strpos($key, 'var_') !== false)
@@ -32,17 +28,16 @@ if(!$error) {
$value .= '/';
}
if($key === 'var_usage') {
$content .= '$config[\'anonymous_usage_statistics\'] = ' . ((int)$value == 1 ? 'true' : 'false') . ';';
$content .= PHP_EOL;
}
else if(!in_array($key, array('var_account', 'var_account_id', 'var_password', 'var_step', 'var_email', 'var_player_name'), true)) {
$content .= '$config[\'' . str_replace('var_', '', $key) . '\'] = \'' . $value . '\';';
$content .= PHP_EOL;
if(!in_array($key, ['var_usage', 'var_date_timezone', 'var_client', 'var_account', 'var_account_id', 'var_password', 'var_password_confirm', 'var_step', 'var_email', 'var_player_name'], true)) {
$configToSave[str_replace('var_', '', $key)] = $value;
}
}
}
$configToSave['gzip_output'] = false;
$configToSave['cache_engine'] = 'auto';
$configToSave['cache_prefix'] = 'myaac_' . generateRandomString(8, true, false, true);
require BASE . 'install/includes/config.php';
if(!$error) {
@@ -79,31 +74,17 @@ if(!$error) {
'message' => $locale['loading_spinner']
));
if(!Validator::email($_SESSION['var_mail_admin'])) {
error($locale['step_config_mail_admin_error']);
$error = true;
}
$content .= '$config[\'session_prefix\'] = \'myaac_' . generateRandomString(8, true, false, true, false) . '_\';';
$content .= PHP_EOL;
$content .= '$config[\'cache_prefix\'] = \'myaac_' . generateRandomString(8, true, false, true, false) . '_\';';
$saved = true;
if(!$error) {
$saved = file_put_contents(BASE . 'config.local.php', $content);
}
$content = '';
$saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content);
if($saved) {
success($locale['step_database_config_saved']);
if(!$error) {
$_SESSION['saved'] = true;
}
$_SESSION['saved'] = true;
}
else {
$_SESSION['config_content'] = $content;
unset($_SESSION['saved']);
$locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.local.php</b>', $locale['step_database_error_file']);
$locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.php</b>', $locale['step_database_error_file']);
error($locale['step_database_error_file'] . '<br/>
<textarea cols="70" rows="10">' . $content . '</textarea>');
}

View File

@@ -116,6 +116,23 @@ else {
}
}
$settings = Settings::getInstance();
foreach($_SESSION as $key => $value) {
if (in_array($key, ['var_usage', 'var_date_timezone', 'var_client'])) {
if ($key == 'var_usage') {
$key = 'anonymous_usage_statistics';
$value = ((int)$value == 1 ? 'true' : 'false');
} elseif ($key == 'var_date_timezone') {
$key = 'date_timezone';
} elseif ($key == 'var_client') {
$key = 'client';
}
$settings->updateInDatabase('core', $key, $value);
}
}
success('Settings saved.');
$twig->display('install.installer.html.twig', array(
'url' => 'tools/7-finish.php',
'message' => $locale['importing_spinner']

View File

@@ -11,11 +11,11 @@ ini_set('max_execution_time', 300);
ob_implicit_flush();
ob_end_flush();
header('X-Accel-Buffering: no');
/*
if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['saved'])) {
warning($locale['already_installed']);
return;
}
}*/
require SYSTEM . 'init.php';
@@ -45,19 +45,16 @@ if($success) {
success($locale['step_database_imported_players']);
}
require_once LIBS . 'plugins.php';
Plugins::installMenus('kathrine', require TEMPLATES . 'kathrine/menus.php');
Plugins::installMenus('tibiacom', require TEMPLATES . 'tibiacom/menus.php');
require LIBS . 'DataLoader.php';
DataLoader::setLocale($locale);
DataLoader::load();
// update config.highscores_ids_hidden
require_once SYSTEM . 'migrations/20.php';
$database_migration_20 = true;
$content = '';
if(!databaseMigration20($content)) {
$locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.local.php</b>', $locale['step_database_error_file']);
warning($locale['step_database_error_file'] . '<br/>
<textarea cols="70" rows="10">' . $content . '</textarea>');
}
// add z_polls tables
require_once SYSTEM . 'migrations/22.php';
@@ -66,6 +63,14 @@ require_once SYSTEM . 'migrations/22.php';
require_once SYSTEM . 'migrations/27.php';
require_once SYSTEM . 'migrations/30.php';
use MyAAC\Models\FAQ as ModelsFAQ;
if(ModelsFAQ::count() == 0) {
ModelsFAQ::create([
'question' => 'What is this?',
'answer' => 'This is website for OTS powered by MyAAC.',
]);
}
$locale['step_finish_desc'] = str_replace('$ADMIN_PANEL$', generateLink(str_replace('tools/', '',ADMIN_URL), $locale['step_finish_admin_panel'], true), $locale['step_finish_desc']);
$locale['step_finish_desc'] = str_replace('$HOMEPAGE$', generateLink(str_replace('tools/', '', BASE_URL), $locale['step_finish_homepage'], true), $locale['step_finish_desc']);
$locale['step_finish_desc'] = str_replace('$LINK$', generateLink('https://my-aac.org', 'https://my-aac.org', true), $locale['step_finish_desc']);

104
login.php
View File

@@ -1,7 +1,11 @@
<?php
use MyAAC\Models\BoostedCreature;
use MyAAC\Models\PlayerOnline;
use MyAAC\Models\Account;
use MyAAC\Models\Player;
require_once 'common.php';
require_once 'config.php';
require_once 'config.local.php';
require_once SYSTEM . 'functions.php';
require_once SYSTEM . 'init.php';
require_once SYSTEM . 'status.php';
@@ -45,9 +49,9 @@ $action = $request->type ?? '';
switch ($action) {
case 'cacheinfo':
$playersonline = $db->query("select count(*) from `players_online`")->fetchAll();
$playersonline = PlayerOnline::count();
die(json_encode([
'playersonline' => (intval($playersonline[0][0])),
'playersonline' => $playersonline,
'twitchstreams' => 0,
'twitchviewer' => 0,
'gamingyoutubestreams' => 0,
@@ -81,13 +85,11 @@ switch ($action) {
die(json_encode(['eventlist' => $eventlist, 'lastupdatetimestamp' => time()]));
case 'boostedcreature':
$boostDB = $db->query("select * from " . $db->tableName('boosted_creature'))->fetchAll();
foreach ($boostDB as $Tableboost) {
$boostedCreature = BoostedCreature::latest();
die(json_encode([
'boostedcreature' => true,
'raceid' => intval($Tableboost['raceid'])
'raceid' => $boostedCreature->raceid
]));
}
break;
case 'login':
@@ -114,29 +116,32 @@ switch ($action) {
];
$characters = [];
$account = new OTS_Account();
$inputEmail = $request->email ?? false;
$inputAccountName = $request->accountname ?? false;
$inputToken = $request->token ?? false;
$account = Account::query();
if ($inputEmail != false) { // login by email
$account->findByEmail($request->email);
$account->where('email', $inputEmail);
}
else if($inputAccountName != false) { // login by account name
$account->find($inputAccountName);
$account->where('name', $inputAccountName);
}
$current_password = encrypt((USE_ACCOUNT_SALT ? $account->getCustomField('salt') : '') . $request->password);
if (!$account->isLoaded() || $account->getPassword() != $current_password) {
$account = $account->first();
if (!$account) {
sendError(($inputEmail != false ? 'Email' : 'Account name') . ' or password is not correct.');
}
$current_password = encrypt((USE_ACCOUNT_SALT ? $account->salt : '') . $request->password);
if (!$account || $account->password != $current_password) {
sendError(($inputEmail != false ? 'Email' : 'Account name') . ' or password is not correct.');
}
//log_append('test.log', var_export($account->getCustomField('secret'), true));
$accountHasSecret = false;
if (fieldExist('secret', 'accounts')) {
$accountSecret = $account->getCustomField('secret');
$accountSecret = $account->secret;
if ($accountSecret != null && $accountSecret != '') {
$accountHasSecret = true;
if ($inputToken === false) {
@@ -161,18 +166,9 @@ switch ($action) {
$columns .= ', istutorial';
}
$players = $db->query("select {$columns} from players where account_id = " . $account->getId() . " AND deletion = 0");
if($players && $players->rowCount() > 0) {
$players = $players->fetchAll();
$highestLevelId = 0;
$highestLevel = 0;
foreach ($players as $player) {
if ($player['level'] >= $highestLevel) {
$highestLevel = $player['level'];
$highestLevelId = $player['id'];
}
}
$players = Player::where('account_id', $account->id)->notDeleted()->selectRaw($columns)->get();
if($players && $players->count()) {
$highestLevelId = $players->sortByDesc('experience')->first()->getKey();
foreach ($players as $player) {
$characters[] = create_char($player, $highestLevelId);
@@ -182,15 +178,10 @@ switch ($action) {
if (fieldExist('premdays', 'accounts') && fieldExist('lastday', 'accounts')) {
$save = false;
$timeNow = time();
$query = $db->query("select `premdays`, `lastday` from `accounts` where `id` = " . $account->getId());
if ($query->rowCount() > 0) {
$query = $query->fetch();
$premDays = (int)$query['premdays'];
$lastDay = (int)$query['lastday'];
$lastLogin = $lastDay;
} else {
sendError("Error while fetching your account data. Please contact admin.");
}
$premDays = $account->premdays;
$lastDay = $account->lastday;
$lastLogin = $lastDay;
if ($premDays != 0 && $premDays != PHP_INT_MAX) {
if ($lastDay == 0) {
$lastDay = $timeNow;
@@ -215,7 +206,9 @@ switch ($action) {
$save = true;
}
if ($save) {
$db->query("update `accounts` set `premdays` = " . $premDays . ", `lastday` = " . $lastDay . " where `id` = " . $account->getId());
$account->premdays = $premDays;
$account->lastday = $lastDay;
$account->save();
}
}
@@ -237,13 +230,11 @@ switch ($action) {
$sessionKey .= "\n".floor(time() / 30);
}
//log_append('slaw.log', $sessionKey);
$session = [
'sessionkey' => $sessionKey,
'lastlogintime' => 0,
'ispremium' => $config['lua']['freePremium'] || $account->isPremium(),
'premiumuntil' => ($account->getPremDays()) > 0 ? (time() + ($account->getPremDays() * 86400)) : 0,
'ispremium' => $account->is_premium,
'premiumuntil' => ($account->premium_days) > 0 ? (time() + ($account->premium_days * 86400)) : 0,
'status' => 'active', // active, frozen or suspended
'returnernotification' => false,
'showrewardnews' => true,
@@ -261,24 +252,23 @@ switch ($action) {
}
function create_char($player, $highestLevelId) {
global $config;
return [
'worldid' => 0,
'name' => $player['name'],
'ismale' => intval($player['sex']) === 1,
'tutorial' => isset($player['istutorial']) && $player['istutorial'],
'level' => intval($player['level']),
'vocation' => $config['vocations'][$player['vocation']],
'outfitid' => intval($player['looktype']),
'headcolor' => intval($player['lookhead']),
'torsocolor' => intval($player['lookbody']),
'legscolor' => intval($player['looklegs']),
'detailcolor' => intval($player['lookfeet']),
'addonsflags' => intval($player['lookaddons']),
'ishidden' => isset($player['deletion']) && (int)$player['deletion'] === 1,
'name' => $player->name,
'ismale' => $player->sex === 1,
'tutorial' => isset($player->istutorial) && $player->istutorial,
'level' => $player->level,
'vocation' => $player->vocation_name,
'outfitid' => $player->looktype,
'headcolor' => $player->lookhead,
'torsocolor' => $player->lookbody,
'legscolor' => $player->looklegs,
'detailcolor' => $player->lookfeet,
'addonsflags' => $player->lookaddons,
'ishidden' => $player->is_deleted,
'istournamentparticipant' => false,
'ismaincharacter' => $highestLevelId == $player['id'],
'dailyrewardstate' => isset($player['isreward']) ? intval($player['isreward']) : 0,
'ismaincharacter' => $highestLevelId === $player->getKey(),
'dailyrewardstate' => $player->isreward ?? 0,
'remainingdailytournamentplaytime' => 0
];
}

View File

@@ -1,3 +1,3 @@
To play on {{ config.lua.serverName }} you need an account.
All you have to do to create your new account is to enter an account {% if constant('USE_ACCOUNT_NAME') %}name{% else %}number{% endif %}, password{% if config.account_country %}, country{% endif %} and your email address.
All you have to do to create your new account is to enter an account {% if constant('USE_ACCOUNT_NAME') %}name{% else %}number{% endif %}, password{% if setting('core.account_country') %}, country{% endif %} and your email address.
Also you have to agree to the terms presented below. If you have done so, your account {% if constant('USE_ACCOUNT_NAME') %}name{% else %}number{% endif %} will be shown on the following page and your account password will be sent to your email address along with further instructions. If you do not receive the email with your password, please check your spam filter.<br/><br/>

View File

@@ -1,33 +1,37 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
$reward = config('account_mail_confirmed_reward');
$reward = setting('core.account_mail_confirmed_reward');
$hasCoinsColumn = $db->hasColumn('accounts', 'coins');
if ($reward['coins'] > 0 && $hasCoinsColumn) {
log_append('email_confirm_error.log', 'accounts.coins column does not exist.');
$rewardCoins = setting('core.account_mail_confirmed_reward_coins');
if ($rewardCoins > 0 && !$hasCoinsColumn) {
log_append('error.log', 'email_confirm: accounts.coins column does not exist.');
}
if (!isset($account) || !$account->isLoaded()) {
log_append('email_confirm_error.log', 'Account not loaded.');
return;
}
if ($reward['premium_points'] > 0) {
$account->setCustomField('premium_points', (int)$account->getCustomField('premium_points') + $reward['premium_points']);
$rewardMessage = 'You received %d %s for confirming your E-Mail address.';
success(sprintf($reward['message'], $reward['premium_points'], 'premium points'));
$rewardPremiumPoints = setting('core.account_mail_confirmed_reward_premium_points');
if ($rewardPremiumPoints > 0) {
$account->setCustomField('premium_points', (int)$account->getCustomField('premium_points') + $rewardPremiumPoints);
success(sprintf($rewardMessage, $rewardPremiumPoints, 'premium points'));
}
if ($reward['coins'] > 0 && $hasCoinsColumn) {
$account->setCustomField('coins', (int)$account->getCustomField('coins') + $reward['coins']);
if ($rewardCoins > 0 && $hasCoinsColumn) {
$account->setCustomField('coins', (int)$account->getCustomField('coins') + $rewardCoins);
success(sprintf($reward['message'], $reward['coins'], 'coins'));
success(sprintf($rewardMessage, $rewardCoins, 'coins'));
}
if ($reward['premium_days'] > 0) {
$account->setPremDays($account->getPremDays() + $reward['premium_days']);
$rewardPremiumDays = setting('core.account_mail_confirmed_reward_premium_days');
if ($rewardPremiumDays > 0) {
$account->setPremDays($account->getPremDays() + $rewardPremiumDays);
$account->save();
success(sprintf($reward['message'], $reward['premium_days'], 'premium days'));
success(sprintf($rewardMessage, $rewardPremiumDays, 'premium days'));
}

View File

@@ -39,5 +39,6 @@
"redirect_from": "/redirectExample",
"redirect_to": "account/manage"
}
}
},
"settings": "plugins/your-plugin-folder/settings.php"
}

View File

@@ -22,7 +22,7 @@ if [ $1 = "prepare" ]; then
mkdir -p tmp
# get myaac from git archive
git archive --format zip --output tmp/myaac.zip 0.9
git archive --format zip --output tmp/myaac.zip develop
cd tmp/ || exit

19
system/bin/cronjob.php Normal file
View File

@@ -0,0 +1,19 @@
<?php
require_once __DIR__ . '/../../common.php';
require_once SYSTEM . 'functions.php';
require_once SYSTEM . 'init.php';
require_once SYSTEM . 'hooks.php';
$hooks = new Hooks();
$hooks->load();
use GO\Scheduler;
// Create a new scheduler
$scheduler = new Scheduler();
$hooks->trigger(HOOK_CRONJOB, ['scheduler' => $scheduler]);
// Let the scheduler execute jobs which are due.
$scheduler->run();

View File

@@ -0,0 +1,50 @@
<?php
require_once __DIR__ . '/../../common.php';
require_once SYSTEM . 'functions.php';
require_once SYSTEM . 'init.php';
if(!IS_CLI) {
echo 'This script can be run only in command line mode.' . PHP_EOL;
exit(1);
}
if (MYAAC_OS !== 'LINUX') {
echo 'This script can be run only on linux.' . PHP_EOL;
exit(1);
}
$job = '* * * * * /usr/bin/php ' . SYSTEM . 'bin/cronjob.php >> ' . SYSTEM . 'logs/cron.log 2>&1';
if (cronjob_exists($job)) {
echo 'MyAAC cronjob already installed.' . PHP_EOL;
exit(0);
}
exec ('crontab -l', $content);
$content = implode(' ', $content);
$content .= PHP_EOL . $job;
file_put_contents(CACHE . 'cronjob', $content . PHP_EOL);
exec('crontab ' . CACHE. 'cronjob');
echo 'Installed crontab successfully.' . PHP_EOL;
function cronjob_exists($command)
{
$cronjob_exists=false;
exec('crontab -l', $crontab);
if(isset($crontab)&&is_array($crontab)) {
$crontab = array_flip($crontab);
if(isset($crontab[$command])){
$cronjob_exists = true;
}
}
return $cronjob_exists;
}

118
system/compat/config.php Normal file
View File

@@ -0,0 +1,118 @@
<?php
$deprecatedConfig = [
'date_timezone',
'genders',
'template',
'template_allow_change',
'vocations_amount',
'vocations',
'client',
'session_prefix',
'friendly_urls',
'backward_support',
'charset',
'meta_description',
'meta_keywords',
'footer',
'database_encryption' => 'database_hash',
//'language',
'visitors_counter',
'visitors_counter_ttl',
'views_counter',
'outfit_images_url',
'outfit_images_wrong_looktypes',
'item_images_url',
'account_country',
'towns',
'quests',
'character_samples',
'character_towns',
'characters_per_account',
'characters_search_limit',
'news_author',
'news_limit',
'news_ticker_limit',
'news_date_format',
'guild_management',
'guild_need_level',
'guild_need_premium',
'guild_image_size_kb',
'guild_description_default',
'guild_description_chars_limit',
'guild_motd_chars_limit',
'highscores_groups_hidden',
'highscores_ids_hidden',
'highscores_vocation_box',
'highscores_vocation',
'highscores_outfit',
'online_record',
'online_vocations',
'online_vocations_images',
'online_skulls',
'online_outfit',
'online_afk',
'team_display_outfit' => 'team_outfit',
'team_display_status' => 'team_status',
'team_display_world' => 'team_world',
'team_display_lastlogin' => 'team_lastlogin',
'last_kills_limit',
'multiworld',
'forum',
'signature_enabled',
'signature_type',
'signature_cache_time',
'signature_browser_cache',
'gifts_system',
'status_enabled',
'status_ip',
'status_port',
'mail_enabled',
'mail_address',
'account_login_by_email',
'account_login_by_email_fallback',
'account_mail_verify',
'account_mail_unique',
'account_mail_change',
'account_premium_days',
'account_premium_points',
'account_create_character_create',
'account_change_character_name',
'account_change_character_name_points' => 'account_change_character_name_price',
'account_change_character_sex',
'account_change_character_sex_points' => 'account_change_character_name_price',
];
foreach ($deprecatedConfig as $key => $value) {
config(
[
(is_string($key) ? $key : $value),
setting('core.'.$value)
]
);
//var_dump($settings['core.'.$value]['value']);
}
$deprecatedConfigCharacters = [
'level',
'experience',
'magic_level',
'balance',
'marriage_info' => 'marriage',
'outfit',
'creation_date',
'quests',
'skills',
'equipment',
'frags',
'deleted',
];
$tmp = [];
foreach ($deprecatedConfigCharacters as $key => $value) {
$tmp[(is_string($key) ? $key : $value)] = setting('core.characters_'.$value);
}
config(['characters', $tmp]);
unset($tmp);

View File

@@ -7,9 +7,16 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use Illuminate\Database\Capsule\Manager as Capsule;
defined('MYAAC') or die('Direct access not allowed!');
if(!isset($config['database_user'][0], $config['database_password'][0], $config['database_name'][0]))
if (!isset($config['database_overwrite'])) {
$config['database_overwrite'] = false;
}
if(!$config['database_overwrite'] && !isset($config['database_user'][0], $config['database_password'][0], $config['database_name'][0]))
{
if(isset($config['lua']['sqlType'])) {// tfs 0.3
if(isset($config['lua']['mysqlHost'])) {// tfs 0.2
@@ -87,21 +94,34 @@ if(!isset($config['database_socket'])) {
$config['database_socket'] = '';
}
try {
$ots->connect(array(
'host' => $config['database_host'],
'user' => $config['database_user'],
'password' => $config['database_password'],
'database' => $config['database_name'],
'log' => $config['database_log'],
'socket' => @$config['database_socket'],
'persistent' => @$config['database_persistent']
)
);
'host' => $config['database_host'],
'user' => $config['database_user'],
'password' => $config['database_password'],
'database' => $config['database_name'],
'log' => $config['database_log'],
'socket' => @$config['database_socket'],
'persistent' => @$config['database_persistent']
));
$db = POT::getInstance()->getDBHandle();
}
catch(PDOException $error) {
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'mysql',
'database' => $config['database_name'],
]);
$capsule->getConnection()->setPdo($db);
$capsule->getConnection()->setReadPdo($db);
$capsule->setAsGlobal();
$capsule->bootEloquent();
$eloquentConnection = $capsule->getConnection();
} catch (Exception $e) {
if(isset($cache) && $cache->enabled()) {
$cache->delete('config_lua');
}
@@ -115,5 +135,5 @@ catch(PDOException $error) {
'<ul>' .
'<li>MySQL is not configured propertly in <i>config.lua</i>.</li>' .
'<li>MySQL server is not running.</li>' .
'</ul>' . $error->getMessage());
'</ul>' . $e->getMessage());
}

View File

@@ -9,6 +9,12 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
use MyAAC\CsrfToken;
use MyAAC\Models\Config;
use MyAAC\Models\Guild;
use MyAAC\Models\House;
use MyAAC\Models\Pages;
use MyAAC\Models\Player;
use PHPMailer\PHPMailer\PHPMailer;
use Twig\Loader\ArrayLoader as Twig_ArrayLoader;
@@ -32,55 +38,52 @@ function message($message, $type, $return)
return true;
}
function success($message, $return = false) {
return message($message, 'success', $return);
return message($message, 'success', $return);
}
function warning($message, $return = false) {
return message($message, 'warning', $return);
return message($message, 'warning', $return);
}
function note($message, $return = false) {
return message($message, 'note', $return);
return info($message, $return);
}
function info($message, $return = false) {
return message($message, 'info', $return);
}
function error($message, $return = false) {
return message($message, ((defined('MYAAC_INSTALL') || defined('MYAAC_ADMIN')) ? 'danger' : 'error'), $return);
return message($message, ((defined('MYAAC_INSTALL') || defined('MYAAC_ADMIN')) ? 'danger' : 'error'), $return);
}
function longToIp($ip)
function longToIp($ip): string
{
$exp = explode(".", long2ip($ip));
return $exp[3].".".$exp[2].".".$exp[1].".".$exp[0];
}
function generateLink($url, $name, $blank = false) {
function generateLink($url, $name, $blank = false): string {
return '<a href="' . $url . '"' . ($blank ? ' target="_blank"' : '') . '>' . $name . '</a>';
}
function getFullLink($page, $name, $blank = false) {
function getFullLink($page, $name, $blank = false): string {
return generateLink(getLink($page), $name, $blank);
}
function getLink($page, $action = null)
{
global $config;
return BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . $page . ($action ? '/' . $action : '');
function getLink($page, $action = null): string {
return BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . $page . ($action ? '/' . $action : '');
}
function internalLayoutLink($page, $action = null) {return getLink($page, $action);}
function getForumThreadLink($thread_id, $page = NULL)
{
global $config;
return BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'forum/thread/' . (int)$thread_id . (isset($page) ? '/' . $page : '');
function internalLayoutLink($page, $action = null): string {
return getLink($page, $action);
}
function getForumBoardLink($board_id, $page = NULL)
{
global $config;
return BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'forum/board/' . (int)$board_id . (isset($page) ? '/' . $page : '');
function getForumThreadLink($thread_id, $page = NULL): string {
return BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'forum/thread/' . (int)$thread_id . (isset($page) ? '/' . $page : '');
}
function getPlayerLink($name, $generate = true)
{
global $config;
function getForumBoardLink($board_id, $page = NULL): string {
return BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'forum/board/' . (int)$board_id . (isset($page) ? '/' . $page : '');
}
function getPlayerLink($name, $generate = true): string
{
if(is_numeric($name))
{
$player = new OTS_Player();
@@ -89,52 +92,45 @@ function getPlayerLink($name, $generate = true)
$name = $player->getName();
}
$url = BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'characters/' . urlencode($name);
$url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'characters/' . urlencode($name);
if(!$generate) return $url;
return generateLink($url, $name);
}
function getMonsterLink($name, $generate = true)
function getMonsterLink($name, $generate = true): string
{
global $config;
$url = BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'creatures/' . urlencode($name);
$url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'creatures/' . urlencode($name);
if(!$generate) return $url;
return generateLink($url, $name);
}
function getHouseLink($name, $generate = true)
function getHouseLink($name, $generate = true): string
{
global $db, $config;
if(is_numeric($name))
{
$house = $db->query(
'SELECT `name` FROM `houses` WHERE `id` = ' . (int)$name);
if($house->rowCount() > 0)
$name = $house->fetchColumn();
}
$url = BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'houses/' . urlencode($name);
if(!$generate) return $url;
return generateLink($url, $name);
}
function getGuildLink($name, $generate = true)
{
global $config;
if(is_numeric($name)) {
$name = getGuildNameById($name);
if ($name === false) {
$name = 'Unknown';
$house = House::find(intval($name), ['name']);
if ($house) {
$name = $house->name;
}
}
$url = BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'guilds/' . urlencode($name);
$url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'houses/' . urlencode($name);
if(!$generate) return $url;
return generateLink($url, $name);
}
function getGuildLink($name, $generate = true): string
{
if(is_numeric($name)) {
$guild = Guild::find(intval($name), ['name']);
$name = $guild->name ?? 'Unknown';
}
$url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'guilds/' . urlencode($name);
if(!$generate) return $url;
return generateLink($url, $name);
@@ -159,8 +155,7 @@ function getItemImage($id, $count = 1)
if($count > 1)
$file_name .= '-' . $count;
global $config;
return '<img src="' . $config['item_images_url'] . $file_name . config('item_images_extension') . '"' . $tooltip . ' width="32" height="32" border="0" alt="' .$id . '" />';
return '<img src="' . setting('core.item_images_url') . $file_name . setting('core.item_images_extension') . '"' . $tooltip . ' width="32" height="32" border="0" alt="' .$id . '" />';
}
function getItemRarity($chance) {
@@ -180,7 +175,7 @@ function getItemRarity($chance) {
return '';
}
function getFlagImage($country)
function getFlagImage($country): string
{
if(!isset($country[0]))
return '';
@@ -202,7 +197,7 @@ function getFlagImage($country)
* @param mixed $v Variable to check.
* @return bool Value boolean status.
*/
function getBoolean($v)
function getBoolean($v): bool
{
if(is_bool($v)) {
return $v;
@@ -225,7 +220,7 @@ function getBoolean($v)
* @param bool $special Should special characters by used?
* @return string Generated string.
*/
function generateRandomString($length, $lowCase = true, $upCase = false, $numeric = false, $special = false)
function generateRandomString($length, $lowCase = true, $upCase = false, $numeric = false, $special = false): string
{
$characters = '';
if($lowCase)
@@ -282,13 +277,12 @@ function getForumBoards()
*/
function fetchDatabaseConfig($name, &$value)
{
global $db;
$query = $db->query('SELECT `value` FROM `' . TABLE_PREFIX . 'config` WHERE `name` = ' . $db->quote($name));
if($query->rowCount() <= 0)
$config = Config::select('value')->where('name', '=', $name)->first();
if (!$config) {
return false;
}
$value = $query->fetchColumn();
$value = $config->value;
return true;
}
@@ -313,8 +307,7 @@ function getDatabaseConfig($name)
*/
function registerDatabaseConfig($name, $value)
{
global $db;
$db->insert(TABLE_PREFIX . 'config', array('name' => $name, 'value' => $value));
Config::create(compact('name', 'value'));
}
/**
@@ -325,8 +318,9 @@ function registerDatabaseConfig($name, $value)
*/
function updateDatabaseConfig($name, $value)
{
global $db;
$db->update(TABLE_PREFIX . 'config', array('value' => $value), array('name' => $name));
Config::where('name', '=', $name)->update([
'value' => $value
]);
}
/**
@@ -353,47 +347,55 @@ function encrypt($str)
//delete player with name
function delete_player($name)
{
global $db;
$player = new OTS_Player();
$player->find($name);
if($player->isLoaded()) {
try { $db->exec("DELETE FROM player_skills WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
try { $db->exec("DELETE FROM guild_invites WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
try { $db->exec("DELETE FROM player_items WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
try { $db->exec("DELETE FROM player_depotitems WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
try { $db->exec("DELETE FROM player_spells WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
try { $db->exec("DELETE FROM player_storage WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
try { $db->exec("DELETE FROM player_viplist WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
try { $db->exec("DELETE FROM player_deaths WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
try { $db->exec("DELETE FROM player_deaths WHERE killed_by = '".$player->getId()."';"); } catch(PDOException $error) {}
$rank = $player->getRank();
if($rank->isLoaded()) {
$guild = $rank->getGuild();
if($guild->getOwner()->getId() == $player->getId()) {
$rank_list = $guild->getGuildRanksList();
if(count($rank_list) > 0) {
$rank_list->orderBy('level');
foreach($rank_list as $rank_in_guild) {
$players_with_rank = $rank_in_guild->getPlayersList();
$players_with_rank->orderBy('name');
$players_with_rank_number = count($players_with_rank);
if($players_with_rank_number > 0) {
foreach($players_with_rank as $player_in_guild) {
$player_in_guild->setRank();
$player_in_guild->save();
}
}
$rank_in_guild->delete();
}
$guild->delete();
}
}
}
$player->delete();
return true;
// DB::beginTransaction();
global $capsule;
$player = Player::where(compact('name'))->first();
if (!$player) {
return false;
}
return false;
// global $db;
// $player = new OTS_Player();
// $player->find($name);
// if($player->isLoaded()) {
// try { $db->exec("DELETE FROM player_skills WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
// try { $db->exec("DELETE FROM guild_invites WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
// try { $db->exec("DELETE FROM player_items WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
// try { $db->exec("DELETE FROM player_depotitems WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
// try { $db->exec("DELETE FROM player_spells WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
// try { $db->exec("DELETE FROM player_storage WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
// try { $db->exec("DELETE FROM player_viplist WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
// try { $db->exec("DELETE FROM player_deaths WHERE player_id = '".$player->getId()."';"); } catch(PDOException $error) {}
// try { $db->exec("DELETE FROM player_deaths WHERE killed_by = '".$player->getId()."';"); } catch(PDOException $error) {}
// $rank = $player->getRank();
// if($rank->isLoaded()) {
// $guild = $rank->getGuild();
// if($guild->getOwner()->getId() == $player->getId()) {
// $rank_list = $guild->getGuildRanksList();
// if(count($rank_list) > 0) {
// $rank_list->orderBy('level');
// foreach($rank_list as $rank_in_guild) {
// $players_with_rank = $rank_in_guild->getPlayersList();
// $players_with_rank->orderBy('name');
// $players_with_rank_number = count($players_with_rank);
// if($players_with_rank_number > 0) {
// foreach($players_with_rank as $player_in_guild) {
// $player_in_guild->setRank();
// $player_in_guild->save();
// }
// }
// $rank_in_guild->delete();
// }
// $guild->delete();
// }
// }
// }
// $player->delete();
// return true;
// }
// return false;
}
//delete guild with id
@@ -465,7 +467,7 @@ function tickers()
* Types: head_start, head_end, body_start, body_end, center_top
*
*/
function template_place_holder($type)
function template_place_holder($type): string
{
global $twig, $template_place_holders;
$ret = '';
@@ -489,10 +491,10 @@ function template_place_holder($type)
/**
* Returns <head> content to be used by templates.
*/
function template_header($is_admin = false)
function template_header($is_admin = false): string
{
global $title_full, $config, $twig;
$charset = isset($config['charset']) ? $config['charset'] : 'utf-8';
global $title_full, $twig;
$charset = setting('core.charset') ?? 'utf-8';
return $twig->render('templates.header.html.twig',
[
@@ -506,29 +508,32 @@ function template_header($is_admin = false)
/**
* Returns footer content to be used by templates.
*/
function template_footer()
function template_footer(): string
{
global $config, $views_counter;
global $views_counter;
$ret = '';
if(admin())
if(admin()) {
$ret .= generateLink(ADMIN_URL, 'Admin Panel', true);
}
if($config['visitors_counter'])
{
if(setting('core.visitors_counter')) {
global $visitors;
$amount = $visitors->getAmountVisitors();
$ret .= '<br/>Currently there ' . ($amount > 1 ? 'are' : 'is') . ' ' . $amount . ' visitor' . ($amount > 1 ? 's' : '') . '.';
}
if($config['views_counter'])
if(setting('core.views_counter')) {
$ret .= '<br/>Page has been viewed ' . $views_counter . ' times.';
}
if(config('footer_show_load_time')) {
if(setting('core.footer_load_time')) {
$ret .= '<br/>Load time: ' . round(microtime(true) - START_TIME, 4) . ' seconds.';
}
if(isset($config['footer'][0]))
$ret .= '<br/>' . $config['footer'];
$settingFooter = setting('core.footer');
if(isset($settingFooter[0])) {
$ret .= '<br/>' . $settingFooter;
}
// please respect my work and help spreading the word, thanks!
return $ret . '<br/>' . base64_decode('UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vbXktYWFjLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk15QUFDLjwvYT4=');
@@ -536,8 +541,8 @@ function template_footer()
function template_ga_code()
{
global $config, $twig;
if(!isset($config['google_analytics_id'][0]))
global $twig;
if(!isset(setting('core.google_analytics_id')[0]))
return '';
return $twig->render('google_analytics.html.twig');
@@ -822,7 +827,7 @@ function getWorldName($id)
/**
* Mailing users.
* $config['mail_enabled'] have to be enabled.
* Mailing has to be enabled in settings (in Admin Panel).
*
* @param string $to Recipient email address.
* @param string $subject Subject of the message.
@@ -834,8 +839,9 @@ function _mail($to, $subject, $body, $altBody = '', $add_html_tags = true)
{
global $mailer, $config;
if (!config('mail_enabled')) {
log_append('mailer-error.log', '_mail() function has been used, but config.mail_enabled is disabled.');
if (!setting('core.mail_enabled')) {
log_append('mailer-error.log', '_mail() function has been used, but Mail Support is disabled.');
return false;
}
if(!$mailer)
@@ -847,47 +853,53 @@ function _mail($to, $subject, $body, $altBody = '', $add_html_tags = true)
$mailer->clearAllRecipients();
}
$signature_html = '';
if(isset($config['mail_signature']['html']))
$signature_html = $config['mail_signature']['html'];
$signature_html = setting('core.mail_signature_html');
if($add_html_tags && isset($body[0]))
$tmp_body = '<html><head></head><body>' . $body . '<br/><br/>' . $signature_html . '</body></html>';
else
$tmp_body = $body . '<br/><br/>' . $signature_html;
if($config['smtp_enabled'])
$mailOption = setting('core.mail_option');
if($mailOption == MAIL_SMTP)
{
$mailer->isSMTP();
$mailer->Host = $config['smtp_host'];
$mailer->Port = (int)$config['smtp_port'];
$mailer->SMTPAuth = $config['smtp_auth'];
$mailer->Username = $config['smtp_user'];
$mailer->Password = $config['smtp_pass'];
$mailer->SMTPSecure = isset($config['smtp_secure']) ? $config['smtp_secure'] : '';
$mailer->Host = setting('core.smtp_host');
$mailer->Port = setting('core.smtp_port');
$mailer->SMTPAuth = setting('core.smtp_auth');
$mailer->Username = setting('core.smtp_user');
$mailer->Password = setting('core.smtp_pass');
$security = setting('core.smtp_security');
$tmp = '';
if ($security === SMTP_SECURITY_SSL) {
$tmp = 'ssl';
}
else if ($security == SMTP_SECURITY_TLS) {
$tmp = 'tls';
}
$mailer->SMTPSecure = $tmp;
}
else {
$mailer->isMail();
}
$mailer->isHTML(isset($body[0]) > 0);
$mailer->From = $config['mail_address'];
$mailer->Sender = $config['mail_address'];
$mailer->From = setting('core.mail_address');
$mailer->Sender = setting('core.mail_address');
$mailer->CharSet = 'utf-8';
$mailer->FromName = $config['lua']['serverName'];
$mailer->Subject = $subject;
$mailer->addAddress($to);
$mailer->Body = $tmp_body;
if(config('smtp_debug')) {
if(setting('core.smtp_debug')) {
$mailer->SMTPDebug = 2;
$mailer->Debugoutput = 'echo';
}
$signature_plain = '';
if(isset($config['mail_signature']['plain']))
$signature_plain = $config['mail_signature']['plain'];
$signature_plain = setting('core.mail_signature_plain');
if(isset($altBody[0])) {
$mailer->AltBody = $altBody . $signature_plain;
}
@@ -1020,14 +1032,36 @@ function get_browser_real_ip() {
return '0';
}
function setSession($key, $data) {
$_SESSION[config('session_prefix') . $key] = $data;
$_SESSION[setting('core.session_prefix') . $key] = $data;
}
function getSession($key) {
$key = config('session_prefix') . $key;
$key = setting('core.session_prefix') . $key;
return isset($_SESSION[$key]) ? $_SESSION[$key] : false;
}
function unsetSession($key) {
unset($_SESSION[config('session_prefix') . $key]);
unset($_SESSION[setting('core.session_prefix') . $key]);
}
function csrf(): void {
CsrfToken::create();
}
function csrfToken(): string {
return CsrfToken::get();
}
function isValidToken(): bool {
$token = $_POST['csrf_token'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? null;
return ($_SERVER['REQUEST_METHOD'] !== 'POST' || (isset($token) && CsrfToken::isValid($token)));
}
function csrfProtect(): void
{
if (!isValidToken()) {
$lastUri = BASE_URL . str_replace_first('/', '', getSession('last_uri'));
echo 'Request has been cancelled due to security reasons - token is invalid. Go <a href="' . $lastUri . '">back</a>';
exit();
}
}
function getTopPlayers($limit = 5) {
@@ -1042,26 +1076,38 @@ function getTopPlayers($limit = 5) {
}
if (!isset($players)) {
$deleted = 'deleted';
if($db->hasColumn('players', 'deletion'))
$deleted = 'deletion';
$columns = [
'id', 'name', 'level', 'vocation', 'experience',
'looktype', 'lookhead', 'lookbody', 'looklegs', 'lookfeet'
];
$is_tfs10 = $db->hasTable('players_online');
$players = $db->query('SELECT `id`, `name`, `level`, `vocation`, `experience`, `looktype`' . ($db->hasColumn('players', 'lookaddons') ? ', `lookaddons`' : '') . ', `lookhead`, `lookbody`, `looklegs`, `lookfeet`' . ($is_tfs10 ? '' : ', `online`') . ' FROM `players` WHERE `group_id` < ' . config('highscores_groups_hidden') . ' AND `id` NOT IN (' . implode(', ', config('highscores_ids_hidden')) . ') AND `' . $deleted . '` = 0 AND `account_id` != 1 ORDER BY `experience` DESC LIMIT ' . (int)$limit)->fetchAll();
if($is_tfs10) {
foreach($players as &$player) {
$query = $db->query('SELECT `player_id` FROM `players_online` WHERE `player_id` = ' . $player['id']);
$player['online'] = ($query->rowCount() > 0 ? 1 : 0);
}
unset($player);
if ($db->hasColumn('players', 'lookaddons')) {
$columns[] = 'lookaddons';
}
$i = 0;
foreach($players as &$player) {
$player['rank'] = ++$i;
if ($db->hasColumn('players', 'online')) {
$columns[] = 'online';
}
unset($player);
$players = Player::query()
->select($columns)
->withOnlineStatus()
->notDeleted()
->where('group_id', '<', setting('core.highscores_groups_hidden'))
->whereNotIn('id', setting('core.highscores_ids_hidden'))
->where('account_id', '!=', 1)
->orderByDesc('experience')
->limit($limit)
->get()
->map(function ($e, $i) {
$row = $e->toArray();
$row['online'] = $e->online_status;
$row['rank'] = $i + 1;
unset($row['online_table']);
return $row;
})->toArray();
if($cache->enabled()) {
$cache->set('top_' . $limit . '_level', serialize($players), 120);
@@ -1100,6 +1146,9 @@ function deleteDirectory($dir, $ignore = array(), $contentOnly = false) {
function config($key) {
global $config;
if (is_array($key)) {
if (is_null($key[1])) {
unset($config[$key[0]]);
}
return $config[$key[0]] = $key[1];
}
@@ -1115,6 +1164,21 @@ function configLua($key) {
return @$config['lua'][$key];
}
function setting($key)
{
$settings = Settings::getInstance();
if (is_array($key)) {
if (is_null($key[1])) {
unset($settings[$key[0]]);
}
return $settings[$key[0]] = $key[1];
}
return $settings[$key]['value'];
}
function clearCache()
{
require_once LIBS . 'news.php';
@@ -1152,15 +1216,37 @@ function clearCache()
if ($cache->fetch('failed_logins', $tmp))
$cache->delete('failed_logins');
global $template_name;
if ($cache->fetch('template_ini' . $template_name, $tmp))
$cache->delete('template_ini' . $template_name);
foreach (get_templates() as $template) {
if ($cache->fetch('template_ini_' . $template, $tmp)) {
$cache->delete('template_ini_' . $template);
}
}
if ($cache->fetch('plugins_hooks', $tmp))
if ($cache->fetch('template_menus', $tmp)) {
$cache->delete('template_menus');
}
if ($cache->fetch('database_tables', $tmp)) {
$cache->delete('database_tables');
}
if ($cache->fetch('database_columns', $tmp)) {
$cache->delete('database_columns');
}
if ($cache->fetch('database_checksum', $tmp)) {
$cache->delete('database_checksum');
}
if ($cache->fetch('last_kills', $tmp)) {
$cache->delete('last_kills');
}
if ($cache->fetch('hooks', $tmp)) {
$cache->delete('hooks');
}
if ($cache->fetch('plugins_hooks', $tmp)) {
$cache->delete('plugins_hooks');
if ($cache->fetch('plugins_routes', $tmp))
}
if ($cache->fetch('plugins_routes', $tmp)) {
$cache->delete('plugins_routes');
}
}
deleteDirectory(CACHE . 'signatures', ['index.html'], true);
@@ -1177,49 +1263,44 @@ function clearCache()
return true;
}
function getCustomPageInfo($page)
function getCustomPageInfo($name)
{
global $db, $logged_access;
$query =
$db->query(
'SELECT `id`, `title`, `body`, `php`, `hidden`' .
' FROM `' . TABLE_PREFIX . 'pages`' .
' WHERE `name` LIKE ' . $db->quote($page) . ' AND `hidden` != 1 AND `access` <= ' . $db->quote($logged_access));
if($query->rowCount() > 0) // found page
{
return $query->fetch(PDO::FETCH_ASSOC);
global $logged_access;
$page = Pages::isPublic()
->where('name', 'LIKE', $name)
->where('access', '<=', $logged_access)
->first();
if (!$page) {
return null;
}
return null;
return $page->toArray();
}
function getCustomPage($page, &$success): string
function getCustomPage($name, &$success): string
{
global $db, $twig, $title, $ignore, $logged_access;
global $twig, $title, $ignore;
$success = false;
$content = '';
$query =
$db->query(
'SELECT `id`, `title`, `body`, `php`, `hidden`' .
' FROM `' . TABLE_PREFIX . 'pages`' .
' WHERE `name` LIKE ' . $db->quote($page) . ' AND `hidden` != 1 AND `access` <= ' . $db->quote($logged_access));
if($query->rowCount() > 0) // found page
$page = getCustomPageInfo($name);
if($page) // found page
{
$success = $ignore = true;
$query = $query->fetch();
$title = $query['title'];
$title = $page['title'];
if($query['php'] == '1') // execute it as php code
if($page['php'] == '1') // execute it as php code
{
$tmp = substr($query['body'], 0, 10);
$tmp = substr($page['body'], 0, 10);
if(($pos = strpos($tmp, '<?php')) !== false) {
$tmp = preg_replace('/<\?php/', '', $query['body'], 1);
$tmp = preg_replace('/<\?php/', '', $page['body'], 1);
}
else if(($pos = strpos($tmp, '<?')) !== false) {
$tmp = preg_replace('/<\?/', '', $query['body'], 1);
$tmp = preg_replace('/<\?/', '', $page['body'], 1);
}
else
$tmp = $query['body'];
$tmp = $page['body'];
$php_errors = array();
function error_handler($errno, $errstr) {
@@ -1229,7 +1310,7 @@ function getCustomPage($page, &$success): string
set_error_handler('error_handler');
global $config;
if($config['backward_support']) {
if(setting('core.backward_support')) {
global $SQL, $main_content, $subtopic;
}
@@ -1247,7 +1328,7 @@ function getCustomPage($page, &$success): string
$oldLoader = $twig->getLoader();
$twig_loader_array = new Twig_ArrayLoader(array(
'content.html' => $query['body']
'content.html' => $page['body']
));
$twig->setLoader($twig_loader_array);
@@ -1365,22 +1446,17 @@ function getChangelogWhere($v)
function getPlayerNameByAccountId($id)
{
global $db;
if (!is_numeric($id)) {
return '';
}
$account = new OTS_Account();
$account->load($id);
if ($account->isLoaded()) {
$query = $db->query('SELECT `name` FROM `players` WHERE `account_id` = ' . $id . ' ORDER BY `lastlogin` DESC LIMIT 1;');
if (!$query || !$query->rowCount()) {
$account = \MyAAC\Models\Account::find(intval($id), ['id']);
if ($account) {
$player = \MyAAC\Models\Player::where('account_id', $account->id)->orderByDesc('lastlogin')->select('name')->first();
if (!$player) {
return '';
}
return $query->fetch(PDO::FETCH_ASSOC)['name'];
return $player->name;
}
return '';
@@ -1400,10 +1476,9 @@ function getPlayerNameById($id)
return '';
}
$player = new OTS_Player();
$player->load($id);
if ($player->isLoaded()) {
return $player->getName();
$player = \MyAAC\Models\Player::find((int)$id, ['name']);
if ($player) {
return $player->name;
}
return '';
@@ -1417,7 +1492,7 @@ function echo_success($message)
function echo_error($message)
{
global $error;
echo '<div class="col-12 alert alert-error mb-2">' . $message . '</div>';
echo '<div class="col-12 alert alert-danger mb-2">' . $message . '</div>';
$error = true;
}
@@ -1492,8 +1567,8 @@ function right($str, $length) {
}
function getCreatureImgPath($creature){
$creature_path = config('creatures_images_url');
$creature_gfx_name = trim(strtolower($creature)) . config('creatures_images_extension');
$creature_path = setting('core.monsters_images_url');
$creature_gfx_name = trim(strtolower($creature)) . setting('core.monsters_images_extension');
if (!file_exists($creature_path . $creature_gfx_name)) {
$creature_gfx_name = str_replace(" ", "", $creature_gfx_name);
if (file_exists($creature_path . $creature_gfx_name)) {
@@ -1558,12 +1633,9 @@ function escapeHtml($html) {
function getGuildNameById($id)
{
global $db;
$guild = $db->query('SELECT `name` FROM `guilds` WHERE `id` = ' . (int)$id);
if($guild->rowCount() > 0) {
return $guild->fetchColumn();
$guild = Guild::where('id', intval($id))->select('name')->first();
if ($guild) {
return $guild->name;
}
return false;
@@ -1571,15 +1643,11 @@ function getGuildNameById($id)
function getGuildLogoById($id)
{
global $db;
$logo = 'default.gif';
$query = $db->query('SELECT `logo_name` FROM `guilds` WHERE `id` = ' . (int)$id);
if ($query->rowCount() == 1) {
$query = $query->fetch(PDO::FETCH_ASSOC);
$guildLogo = $query['logo_name'];
$guild = Guild::where('id', intval($id))->select('logo_name')->first();
if ($guild) {
$guildLogo = $guild->logo_name;
if (!empty($guildLogo) && file_exists(GUILD_IMAGES_DIR . $guildLogo)) {
$logo = $guildLogo;

View File

@@ -68,8 +68,15 @@ define('HOOK_ADMIN_LOGIN_AFTER_ACCOUNT', ++$i);
define('HOOK_ADMIN_LOGIN_AFTER_PASSWORD', ++$i);
define('HOOK_ADMIN_LOGIN_AFTER_SIGN_IN', ++$i);
define('HOOK_ADMIN_ACCOUNTS_SAVE_POST', ++$i);
define('HOOK_ADMIN_SETTINGS_BEFORE_SAVE', ++$i);
define('HOOK_CRONJOB', ++$i);
define('HOOK_EMAIL_CONFIRMED', ++$i);
define('HOOK_GUILDS_BEFORE_GUILD_HEADER', ++$i);
define('HOOK_GUILDS_AFTER_GUILD_HEADER', ++$i);
define('HOOK_GUILDS_AFTER_GUILD_INFORMATION', ++$i);
define('HOOK_GUILDS_AFTER_GUILD_MEMBERS', ++$i);
define('HOOK_GUILDS_AFTER_INVITED_CHARACTERS', ++$i);
define('HOOK_TWIG', ++$i);
const HOOK_FIRST = HOOK_STARTUP;
define('HOOK_LAST', $i);
@@ -87,15 +94,25 @@ class Hook
public function execute($params)
{
extract($params);
/*if(is_callable($this->_callback))
{
$tmp = $this->_callback;
$ret = $tmp($params);
}*/
global $db, $config, $template_path, $ots, $content, $twig;
$ret = include BASE . $this->_file;
if(is_callable($this->_file))
{
$params['db'] = $db;
$params['config'] = $config;
$params['template_path'] = $template_path;
$params['ots'] = $ots;
$params['content'] = $content;
$params['twig'] = $twig;
$tmp = $this->_file;
$ret = $tmp($params);
}
else {
extract($params);
$ret = include BASE . $this->_file;
}
return !isset($ret) || $ret == 1 || $ret;
}

View File

@@ -7,12 +7,10 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
// load configuration
require_once BASE . 'config.php';
if(file_exists(BASE . 'config.local.php')) // user customizations
require BASE . 'config.local.php';
use MyAAC\CsrfToken;
defined('MYAAC') or die('Direct access not allowed!');
if(!isset($config['installed']) || !$config['installed']) {
throw new RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.');
@@ -22,19 +20,27 @@ if(config('env') === 'dev') {
require SYSTEM . 'exception.php';
}
date_default_timezone_set($config['date_timezone']);
if(empty($config['server_path'])) {
throw new RuntimeException('Server Path has been not set. Go to config.php and set it.');
}
// take care of trailing slash at the end
if($config['server_path'][strlen($config['server_path']) - 1] !== '/')
$config['server_path'] .= '/';
// enable gzip compression if supported by the browser
if($config['gzip_output'] && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false && function_exists('ob_gzhandler'))
if(isset($config['gzip_output']) && $config['gzip_output'] && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false && function_exists('ob_gzhandler'))
ob_start('ob_gzhandler');
// cache
require_once SYSTEM . 'libs/cache.php';
$cache = Cache::getInstance();
// event system
require_once SYSTEM . 'hooks.php';
$hooks = new Hooks();
$hooks->load();
// twig
require_once SYSTEM . 'twig.php';
@@ -96,9 +102,6 @@ if(isset($config['lua']['servername']))
if(isset($config['lua']['houserentperiod']))
$config['lua']['houseRentPeriod'] = $config['lua']['houserentperiod'];
if($config['item_images_url'][strlen($config['item_images_url']) - 1] !== '/')
$config['item_images_url'] .= '/';
// localize data/ directory based on data directory set in config.lua
foreach(array('dataDirectory', 'data_directory', 'datadir') as $key) {
if(!isset($config['lua'][$key][0])) {
@@ -122,51 +125,47 @@ if(!isset($foundValue)) {
$config['data_path'] = $foundValue;
unset($foundValue);
// new config values for compatibility
if(!isset($config['highscores_ids_hidden']) || count($config['highscores_ids_hidden']) == 0) {
$config['highscores_ids_hidden'] = array(0);
}
$config['account_create_character_create'] = config('account_create_character_create') && (!config('mail_enabled') || !config('account_mail_verify'));
// POT
require_once SYSTEM . 'libs/pot/OTS.php';
$ots = POT::getInstance();
$eloquentConnection = null;
require_once SYSTEM . 'database.php';
// execute migrations
require SYSTEM . 'migrate.php';
// settings
require_once LIBS . 'Settings.php';
$settings = Settings::getInstance();
$settings->load();
// csrf protection
$token = getSession('csrf_token');
if (!isset($token) || !$token) {
CsrfToken::generate();
}
// deprecated config values
require_once SYSTEM . 'compat/config.php';
date_default_timezone_set(setting('core.date_timezone'));
setting(
[
'core.account_create_character_create',
setting('core.account_create_character_create') && (!setting('core.mail_enabled') || !setting('core.account_mail_verify'))
]
);
$settingsItemImagesURL = setting('core.item_images_url');
if($settingsItemImagesURL[strlen($settingsItemImagesURL) - 1] !== '/') {
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'));
// load vocation names
$tmp = '';
if($cache->enabled() && $cache->fetch('vocations', $tmp)) {
$config['vocations'] = unserialize($tmp);
}
else {
if(!class_exists('DOMDocument')) {
throw new RuntimeException('Please install PHP xml extension. MyAAC will not work without it.');
}
$vocations = new DOMDocument();
$file = $config['data_path'] . 'XML/vocations.xml';
if(!@file_exists($file))
$file = $config['data_path'] . 'vocations.xml';
if(!$vocations->load($file))
throw new RuntimeException('ERROR: Cannot load <i>vocations.xml</i> - the file is malformed. Check the file with xml syntax validator.');
$config['vocations'] = array();
foreach($vocations->getElementsByTagName('vocation') as $vocation) {
$id = $vocation->getAttribute('id');
$config['vocations'][$id] = $vocation->getAttribute('name');
}
if($cache->enabled()) {
$cache->set('vocations', serialize($config['vocations']), 120);
}
}
unset($tmp, $id, $vocation);
require LIBS . 'Towns.php';
Towns::load();

View File

@@ -1,60 +0,0 @@
<?php
/**
* Item parser
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
require_once SYSTEM . 'libs/items_images.php';
Items_Images::$files = array(
'otb' => SYSTEM . 'data/items.otb',
'spr' => SYSTEM . 'data/Tibia.spr',
'dat' => SYSTEM . 'data/Tibia.dat'
);
Items_Images::$outputDir = BASE . 'images/items/';
function generateItem($id = 100, $count = 1) {
Items_Images::generate($id, $count);
}
function itemImageExists($id, $count = 1)
{
if(!isset($id))
throw new RuntimeException('ERROR - itemImageExists: id has been not set!');
$file_name = $id;
if($count > 1)
$file_name .= '-' . $count;
$file_name = Items_Images::$outputDir . $file_name . '.gif';
return file_exists($file_name);
}
function outputItem($id = 100, $count = 1)
{
if(!(int)$count)
$count = 1;
if(!itemImageExists($id, $count))
{
//echo 'plik istnieje';
Items_Images::generate($id, $count);
}
$expires = 60 * 60 * 24 * 30; // 30 days
header('Content-type: image/gif');
header('Cache-Control: public');
header('Cache-Control: maxage=' . $expires);
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expires) . ' GMT');
$file_name = $id;
if($count > 1)
$file_name .= '-' . $count;
$file_name = Items_Images::$outputDir . $file_name . '.gif';
readfile($file_name);
}

View File

@@ -1,4 +1,7 @@
<?php
use MyAAC\Models\Player;
/**
* CreateCharacter
*
@@ -18,8 +21,8 @@ class CreateCharacter
*/
public function checkName($name, &$errors)
{
$minLength = config('character_name_min_length');
$maxLength = config('character_name_max_length');
$minLength = setting('core.create_character_name_min_length');
$maxLength = setting('core.create_character_name_max_length');
if(empty($name)) {
$errors['name'] = 'Please enter a name for your character!';
@@ -52,9 +55,7 @@ class CreateCharacter
return false;
}
$player = new OTS_Player();
$player->find($name);
if($player->isLoaded()) {
if(Player::where('name', '=', $name)->exists()) {
$errors['name'] = 'Character with this name already exist.';
return false;
}
@@ -139,8 +140,8 @@ class CreateCharacter
if(empty($errors))
{
$number_of_players_on_account = $account->getPlayersList(true)->count();
if($number_of_players_on_account >= config('characters_per_account'))
$errors[] = 'You have too many characters on your account <b>('.$number_of_players_on_account.'/'.config('characters_per_account').')</b>!';
if($number_of_players_on_account >= setting('core.characters_per_account'))
$errors[] = 'You have too many characters on your account <b>('.$number_of_players_on_account . '/' . setting('core.characters_per_account') . ')</b>!';
}
if(empty($errors))
@@ -149,7 +150,7 @@ class CreateCharacter
$char_to_copy = new OTS_Player();
$char_to_copy->find($char_to_copy_name);
if(!$char_to_copy->isLoaded())
$errors[] = 'Wrong characters configuration. Try again or contact with admin. ADMIN: Edit file config.php and set valid characters to copy names. Character to copy: <b>'.$char_to_copy_name.'</b> doesn\'t exist.';
$errors[] = 'Wrong characters configuration. Try again or contact with admin. ADMIN: Go to Admin Panel -> Settings -> Create Character and set valid characters to copy names. Character to copy: <b>'.$char_to_copy_name.'</b> doesn\'t exist.';
}
if(!empty($errors)) {
@@ -195,7 +196,7 @@ class CreateCharacter
for($skill = POT::SKILL_FIRST; $skill <= POT::SKILL_LAST; $skill++) {
$value = 10;
if (config('use_character_sample_skills')) {
if (setting('core.use_character_sample_skills')) {
$value = $char_to_copy->getSkill($skill);
}
@@ -239,14 +240,14 @@ class CreateCharacter
}
if($db->hasTable('player_skills')) {
for($i=0; $i<7; $i++) {
for($skill = POT::SKILL_FIRST; $skill <= POT::SKILL_LAST; $skill++) {
$value = 10;
if (config('use_character_sample_skills')) {
$value = $char_to_copy->getSkill($i);
if (setting('core.use_character_sample_skills')) {
$value = $char_to_copy->getSkill($skill);
}
$skillExists = $db->query('SELECT `skillid` FROM `player_skills` WHERE `player_id` = ' . $player->getId() . ' AND `skillid` = ' . $i);
$skillExists = $db->query('SELECT `skillid` FROM `player_skills` WHERE `player_id` = ' . $player->getId() . ' AND `skillid` = ' . $skill);
if($skillExists->rowCount() <= 0) {
$db->query('INSERT INTO `player_skills` (`player_id`, `skillid`, `value`, `count`) VALUES ('.$player->getId().', '.$i.', ' . $value . ', 0)');
$db->query('INSERT INTO `player_skills` (`player_id`, `skillid`, `value`, `count`) VALUES ('.$player->getId().', '.$skill.', ' . $value . ', 0)');
}
}
}

596
system/libs/Settings.php Normal file
View File

@@ -0,0 +1,596 @@
<?php
use MyAAC\Models\Settings as ModelsSettings;
/**
* CreateCharacter
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
class Settings implements ArrayAccess
{
static private $instance;
private $settingsFile = [];
private $settingsDatabase = [];
private $cache = [];
private $valuesAsked = [];
private $errors = [];
/**
* @return Settings
*/
public static function getInstance(): Settings
{
if (!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
public function load()
{
$cache = Cache::getInstance();
if ($cache->enabled()) {
$tmp = '';
if ($cache->fetch('settings', $tmp)) {
$this->settingsDatabase = unserialize($tmp);
return;
}
}
$settings = ModelsSettings::all();
foreach ($settings as $setting)
{
$this->settingsDatabase[$setting->name][$setting->key] = $setting->value;
}
if ($cache->enabled()) {
$cache->set('settings', serialize($this->settingsDatabase), 600);
}
}
public function save($pluginName, $values) {
if (!isset($this->settingsFile[$pluginName])) {
throw new RuntimeException('Error on save settings: plugin does not exist');
}
$settings = $this->settingsFile[$pluginName];
global $hooks;
if (!$hooks->trigger(HOOK_ADMIN_SETTINGS_BEFORE_SAVE, [
'name' => $pluginName,
'values' => $values,
'settings' => $settings,
])) {
return false;
}
if (isset($settings['callbacks']['beforeSave'])) {
if (!$settings['callbacks']['beforeSave']($settings, $values)) {
return false;
}
}
$this->errors = [];
ModelsSettings::where('name', $pluginName)->delete();
foreach ($values as $key => $value) {
$errorMessage = '';
if (isset($settings['settings'][$key]['callbacks']['beforeSave']) && !$settings['settings'][$key]['callbacks']['beforeSave']($key, $value, $errorMessage)) {
$this->errors[] = $errorMessage;
continue;
}
try {
ModelsSettings::create([
'name' => $pluginName,
'key' => $key,
'value' => $value
]);
} catch (PDOException $error) {
$this->errors[] = 'Error while saving setting (' . $pluginName . ' - ' . $key . '): ' . $error->getMessage();
}
}
$cache = Cache::getInstance();
if ($cache->enabled()) {
$cache->delete('settings');
}
return true;
}
public function updateInDatabase($pluginName, $key, $value)
{
ModelsSettings::where(['name' => $pluginName, 'key' => $key])->update(['value' => $value]);
}
public function deleteFromDatabase($pluginName, $key = null)
{
if (!isset($key)) {
ModelsSettings::where('name', $pluginName)->delete();
}
else {
ModelsSettings::where('name', $pluginName)->where('key', $key)->delete();
}
}
public static function display($plugin, $settings): array
{
$settingsDb = ModelsSettings::where('name', $plugin)->pluck('value', 'key')->toArray();
$config = [];
require BASE . 'config.local.php';
foreach ($config as $key => $value) {
if (is_bool($value)) {
$settingsDb[$key] = $value ? 'true' : 'false';
}
else {
$settingsDb[$key] = (string)$value;
}
}
$javascript = '';
ob_start();
?>
<ul class="nav nav-tabs" id="myTab">
<?php
$i = 0;
foreach($settings as $setting) {
if (isset($setting['script'])) {
$javascript .= $setting['script'] . PHP_EOL;
}
if ($setting['type'] === 'category') {
?>
<li class="nav-item">
<a class="nav-link<?= ($i === 0 ? ' active' : ''); ?>" id="home-tab-<?= $i++; ?>" data-toggle="tab" href="#tab-<?= str_replace(' ', '', $setting['title']); ?>" type="button"><?= $setting['title']; ?></a>
</li>
<?php
}
}
?>
</ul>
<div class="tab-content" id="tab-content">
<?php
$checkbox = function ($key, $type, $value) {
echo '<label><input type="radio" id="' . $key . '_' . ($type ? 'yes' : 'no') . '" name="settings[' . $key . ']" value="' . ($type ? 'true' : 'false') . '" ' . ($value === $type ? 'checked' : '') . '/>' . ($type ? 'Yes' : 'No') . '</label> ';
};
$i = 0;
$j = 0;
foreach($settings as $key => $setting) {
if ($setting['type'] === 'category') {
if ($j++ !== 0) { // close previous category
echo '</tbody></table></div>';
}
?>
<div class="tab-pane fade show<?= ($j === 1 ? ' active' : ''); ?>" id="tab-<?= str_replace(' ', '', $setting['title']); ?>">
<?php
continue;
}
if ($setting['type'] === 'section') {
if ($i++ !== 0) { // close previous section
echo '</tbody></table>';
}
?>
<h3 id="row_<?= $key ?>" style="text-align: center"><strong><?= $setting['title']; ?></strong></h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th style="width: 13%">Name</th>
<th style="width: 30%">Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<?php
continue;
}
if (!isset($setting['hidden']) || !$setting['hidden']) {
?>
<tr id="row_<?= $key ?>">
<td><label for="<?= $key ?>" class="control-label"><?= $setting['name'] ?></label></td>
<td>
<?php
}
if (isset($setting['hidden']) && $setting['hidden']) {
$value = '';
if ($setting['type'] === 'boolean') {
$value = ($setting['default'] ? 'true' : 'false');
}
else if (in_array($setting['type'], ['text', 'number', 'email', 'password', 'textarea'])) {
$value = $setting['default'];
}
else if ($setting['type'] === 'options') {
$value = $setting['options'][$setting['default']];
}
echo '<input type="hidden" name="settings[' . $key . ']" value="' . $value . '" id="' . $key . '"';
}
else if ($setting['type'] === 'boolean') {
if(isset($settingsDb[$key])) {
if($settingsDb[$key] === 'true') {
$value = true;
}
else {
$value = false;
}
}
else {
$value = ($setting['default'] ?? false);
}
$checkbox($key, true, $value);
$checkbox($key, false, $value);
}
else if (in_array($setting['type'], ['text', 'number', 'email', 'password'])) {
if ($setting['type'] === 'number') {
$min = (isset($setting['min']) ? ' min="' . $setting['min'] . '"' : '');
$max = (isset($setting['max']) ? ' max="' . $setting['max'] . '"' : '');
$step = (isset($setting['step']) ? ' step="' . $setting['step'] . '"' : '');
}
else {
$min = $max = $step = '';
}
echo '<input class="form-control" type="' . $setting['type'] . '" name="settings[' . $key . ']" value="' . ($settingsDb[$key] ?? ($setting['default'] ?? '')) . '" id="' . $key . '"' . $min . $max . $step . '/>';
}
else if($setting['type'] === 'textarea') {
$value = ($settingsDb[$key] ?? ($setting['default'] ?? ''));
$valueWithSpaces = array_map('trim', preg_split('/\r\n|\r|\n/', trim($value)));
$rows = count($valueWithSpaces);
if ($rows < 2) {
$rows = 2; // always min 2 rows for textarea
}
echo '<textarea class="form-control" rows="' . $rows . '" name="settings[' . $key . ']" id="' . $key . '">' . $value . '</textarea>';
}
else if ($setting['type'] === 'options') {
if ($setting['options'] === '$templates') {
$templates = [];
foreach (get_templates() as $value) {
$templates[$value] = $value;
}
$setting['options'] = $templates;
}
else if($setting['options'] === '$clients') {
$clients = [];
foreach((array)config('clients') as $client) {
$client_version = (string)($client / 100);
if(strpos($client_version, '.') === false)
$client_version .= '.0';
$clients[$client] = $client_version;
}
$setting['options'] = $clients;
}
else if ($setting['options'] == '$timezones') {
$timezones = [];
foreach (DateTimeZone::listIdentifiers() as $value) {
$timezones[$value] = $value;
}
$setting['options'] = $timezones;
}
else {
if (is_string($setting['options'])) {
$setting['options'] = explode(',', $setting['options']);
foreach ($setting['options'] as &$option) {
$option = trim($option);
}
}
}
echo '<select class="form-control" name="settings[' . $key . ']" id="' . $key . '">';
foreach ($setting['options'] as $value => $option) {
$compareTo = ($settingsDb[$key] ?? ($setting['default'] ?? ''));
if($value === 'true') {
$selected = $compareTo === true;
}
else if($value === 'false') {
$selected = $compareTo === false;
}
else {
$selected = $compareTo == $value;
}
echo '<option value="' . $value . '" ' . ($selected ? 'selected' : '') . '>' . $option . '</option>';
}
echo '</select>';
}
if (!isset($setting['hidden']) || !$setting['hidden']) {
?>
</td>
<td>
<div class="well setting-default"><?php
echo ($setting['desc'] ?? '');
echo '<br/>';
echo '<strong>Default:</strong> ';
if ($setting['type'] === 'boolean') {
echo ($setting['default'] ? 'Yes' : 'No');
}
else if (in_array($setting['type'], ['text', 'number', 'email', 'password', 'textarea'])) {
echo $setting['default'];
}
else if ($setting['type'] === 'options') {
if (!empty($setting['default'])) {
echo $setting['options'][$setting['default']];
}
}
?></div>
</td>
</tr>
<?php
}
}
?>
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<button name="save" type="submit" class="btn btn-primary">Save</button>
</div>
<?php
return ['content' => ob_get_clean(), 'script' => $javascript];
}
#[\ReturnTypeWillChange]
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
throw new \RuntimeException("Settings: You cannot set empty offset with value: $value!");
}
$this->loadPlugin($offset);
$pluginKeyName = $this->valuesAsked['pluginKeyName'];
$key = $this->valuesAsked['key'];
// remove whole plugin settings
if (!isset($value)) {
$this->offsetUnset($offset);
$this->deleteFromDatabase($pluginKeyName, $key);
return;
}
$this->settingsDatabase[$pluginKeyName][$key] = $value;
$this->updateInDatabase($pluginKeyName, $key, $value);
}
#[\ReturnTypeWillChange]
public function offsetExists($offset): bool
{
$this->loadPlugin($offset);
$pluginKeyName = $this->valuesAsked['pluginKeyName'];
$key = $this->valuesAsked['key'];
// remove specified plugin settings (all)
if(is_null($key)) {
return isset($this->settingsDatabase[$offset]);
}
return isset($this->settingsDatabase[$pluginKeyName][$key]);
}
#[\ReturnTypeWillChange]
public function offsetUnset($offset)
{
$this->loadPlugin($offset);
$pluginKeyName = $this->valuesAsked['pluginKeyName'];
$key = $this->valuesAsked['key'];
if (isset($this->cache[$offset])) {
unset($this->cache[$offset]);
}
// remove specified plugin settings (all)
if(!isset($key)) {
unset($this->settingsFile[$pluginKeyName]);
unset($this->settingsDatabase[$pluginKeyName]);
$this->deleteFromDatabase($pluginKeyName);
return;
}
unset($this->settingsFile[$pluginKeyName]['settings'][$key]);
unset($this->settingsDatabase[$pluginKeyName][$key]);
$this->deleteFromDatabase($pluginKeyName, $key);
}
/**
* Get settings
* Usage: $setting['plugin_name.key']
* Example: $settings['shop_system.paypal_email']
*
* @param mixed $offset
* @return array|mixed
*/
#[\ReturnTypeWillChange]
public function offsetGet($offset)
{
// try cache hit
if(isset($this->cache[$offset])) {
return $this->cache[$offset];
}
$this->loadPlugin($offset);
$pluginKeyName = $this->valuesAsked['pluginKeyName'];
$key = $this->valuesAsked['key'];
// return specified plugin settings (all)
if(!isset($key)) {
if (!isset($this->settingsFile[$pluginKeyName]['settings'])) {
throw new RuntimeException('Unknown plugin settings: ' . $pluginKeyName);
}
return $this->settingsFile[$pluginKeyName]['settings'];
}
$ret = [];
if(isset($this->settingsFile[$pluginKeyName]['settings'][$key])) {
$ret = $this->settingsFile[$pluginKeyName]['settings'][$key];
}
if(isset($this->settingsDatabase[$pluginKeyName][$key])) {
$value = $this->settingsDatabase[$pluginKeyName][$key];
$ret['value'] = $value;
}
else {
$ret['value'] = $this->settingsFile[$pluginKeyName]['settings'][$key]['default'];
}
if(isset($ret['type'])) {
switch($ret['type']) {
case 'boolean':
$ret['value'] = getBoolean($ret['value']);
break;
case 'number':
if (!isset($ret['step']) || (int)$ret['step'] == 1) {
$ret['value'] = (int)$ret['value'];
}
break;
default:
break;
}
}
if (isset($ret['callbacks']['get'])) {
$ret['value'] = $ret['callbacks']['get']($ret['value']);
}
$this->cache[$offset] = $ret;
return $ret;
}
private function updateValuesAsked($offset)
{
$pluginKeyName = $offset;
if (strpos($offset, '.')) {
$explode = explode('.', $offset, 2);
$pluginKeyName = $explode[0];
$key = $explode[1];
$this->valuesAsked = ['pluginKeyName' => $pluginKeyName, 'key' => $key];
}
else {
$this->valuesAsked = ['pluginKeyName' => $pluginKeyName, 'key' => null];
}
}
private function loadPlugin($offset)
{
$this->updateValuesAsked($offset);
$pluginKeyName = $this->valuesAsked['pluginKeyName'];
$key = $this->valuesAsked['key'];
if (!isset($this->settingsFile[$pluginKeyName])) {
if ($pluginKeyName === 'core') {
$settingsFilePath = SYSTEM . 'settings.php';
} else {
//$pluginSettings = Plugins::getPluginSettings($pluginKeyName);
$settings = Plugins::getAllPluginsSettings();
if (!isset($settings[$pluginKeyName])) {
warning("Setting $pluginKeyName does not exist or does not have settings defined.");
return;
}
$settingsFilePath = BASE . $settings[$pluginKeyName]['settingsFilename'];
}
if (!file_exists($settingsFilePath)) {
throw new \RuntimeException('Failed to load settings file for plugin: ' . $pluginKeyName);
}
$this->settingsFile[$pluginKeyName] = require $settingsFilePath;
}
}
public static function saveConfig($config, $filename, &$content = '')
{
$content = "<?php" . PHP_EOL .
"\$config['installed'] = true;" . PHP_EOL;
foreach ($config as $key => $value) {
$content .= "\$config['$key'] = ";
$content .= var_export($value, true);
$content .= ';' . PHP_EOL;
}
$success = file_put_contents($filename, $content);
// we saved new config.php, need to revalidate cache (only if opcache is enabled)
if (function_exists('opcache_invalidate')) {
opcache_invalidate($filename);
}
return $success;
}
public static function testDatabaseConnection($config): bool
{
$user = null;
$password = null;
$dns = [];
if( isset($config['database_name']) ) {
$dns[] = 'dbname=' . $config['database_name'];
}
if( isset($config['database_user']) ) {
$user = $config['database_user'];
}
if( isset($config['database_password']) ) {
$password = $config['database_password'];
}
if( isset($config['database_host']) ) {
$dns[] = 'host=' . $config['database_host'];
}
if( isset($config['database_port']) ) {
$dns[] = 'port=' . $config['database_port'];
}
try {
$connectionTest = new PDO('mysql:' . implode(';', $dns), $user, $password);
$connectionTest->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $error) {
error('MySQL connection failed. Settings has been reverted.');
error($error->getMessage());
return false;
}
return true;
}
public function getErrors() {
return $this->errors;
}
}

View File

@@ -23,6 +23,8 @@
* @link https://my-aac.org
*/
use MyAAC\Models\Town;
/**
* Class Towns
*/
@@ -124,15 +126,6 @@ class Towns
*/
public static function getFromDatabase()
{
global $db;
$query = $db->query('SELECT `id`, `name` FROM `towns`;')->fetchAll(PDO::FETCH_ASSOC);
$towns = [];
foreach($query as $town) {
$towns[$town['id']] = $town['name'];
}
return $towns;
return Town::pluck('name', 'id')->toArray();
}
}

View File

@@ -1,5 +1,7 @@
<?php
use MyAAC\Models\Changelog as ModelsChangelog;
class Changelog
{
static public function verify($body,$date, &$errors)
@@ -19,43 +21,61 @@ class Changelog
static public function add($body, $type, $where, $player_id, $cdate, &$errors)
{
global $db;
if(!self::verify($body,$cdate, $errors))
return false;
$db->insert(TABLE_PREFIX . 'changelog', array('body' => $body, 'type' => $type, 'date' => $cdate, 'where' => $where, 'player_id' => isset($player_id) ? $player_id : 0));
self::clearCache();
return true;
$row = new ModelsChangelog;
$row->body = $body;
$row->type = $type;
$row->date = $cdate;
$row->where = $where;
$row->player_id = $player_id ?? 0;
if ($row->save()) {
self::clearCache();
return true;
}
return false;
}
static public function get($id) {
global $db;
return $db->select(TABLE_PREFIX . 'changelog', array('id' => $id));
return ModelsChangelog::find($id);
}
static public function update($id, $body, $type, $where, $player_id, $date, &$errors)
{
global $db;
if(!self::verify($body,$date, $errors))
return false;
$db->update(TABLE_PREFIX . 'changelog', array('body' => $body, 'type' => $type, 'where' => $where, 'player_id' => isset($player_id) ? $player_id : 0, 'date' => $date), array('id' => $id));
self::clearCache();
return true;
if (ModelsChangelog::where('id', '=', $id)->update([
'body' => $body,
'type' => $type,
'where' => $where,
'player_id' => $player_id ?? 0,
'date' => $date
])) {
self::clearCache();
return true;
}
return false;
}
static public function delete($id, &$errors)
{
global $db;
if(isset($id))
{
if($db->select(TABLE_PREFIX . 'changelog', array('id' => $id)) !== false)
$db->delete(TABLE_PREFIX . 'changelog', array('id' => $id));
else
$row = ModelsChangelog::find($id);
if ($row) {
if (!$row->delete()) {
$errors[] = 'Fail during delete Changelog.';
}
} else {
$errors[] = 'Changelog with id ' . $id . ' does not exist.';
}
else
}
} else {
$errors[] = 'Changelog id not set.';
}
if(count($errors)) {
return false;
@@ -67,17 +87,19 @@ class Changelog
static public function toggleHidden($id, &$errors, &$status)
{
global $db;
if(isset($id))
{
$query = $db->select(TABLE_PREFIX . 'changelog', array('id' => $id));
if($query !== false)
{
$db->update(TABLE_PREFIX . 'changelog', array('hidden' => ($query['hidden'] == 1 ? 0 : 1)), array('id' => $id));
$status = $query['hidden'];
}
else
$row = ModelsChangelog::find($id);
if ($row) {
$row->hidden = $row->hidden == 1 ? 0 : 1;
if (!$row->save()) {
$errors[] = 'Fail during toggle hidden Changelog.';
}
$status = $row->hidden;
} else {
$errors[] = 'Changelog with id ' . $id . ' does not exists.';
}
}
else
$errors[] = 'Changelog id not set.';

View File

@@ -8,6 +8,9 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Monster;
defined('MYAAC') or die('Direct access not allowed!');
require_once LIBS . 'items.php';
@@ -19,9 +22,9 @@ class Creatures {
private static $lastError = '';
public static function loadFromXML($show = false) {
global $db;
try { $db->exec('DELETE FROM `' . TABLE_PREFIX . 'monsters`;'); } catch(PDOException $error) {}
try {
Monster::query()->delete();
} catch(Exception $error) {}
if($show) {
echo '<h2>Reload monsters.</h2>';
@@ -124,7 +127,7 @@ class Creatures {
}
if(!in_array($name, $names_added)) {
try {
$db->insert(TABLE_PREFIX . 'monsters', array(
Monster::create(array(
'name' => $name,
'mana' => empty($mana) ? 0 : $mana,
'exp' => $monster->getExperience(),
@@ -158,7 +161,7 @@ class Creatures {
success('Added: ' . $name . '<br/>');
}
}
catch(PDOException $error) {
catch(Exception $error) {
if($show) {
warning('Error while adding monster (' . $name . '): ' . $error->getMessage());
}

View File

@@ -10,13 +10,13 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$configForumTablePrefix = config('forum_table_prefix');
if(null !== $configForumTablePrefix && !empty(trim($configForumTablePrefix))) {
if(!in_array($configForumTablePrefix, array('myaac_', 'z_'))) {
$settingForumTablePrefix = setting('core.forum_table_prefix');
if(null !== $settingForumTablePrefix && !empty(trim($settingForumTablePrefix))) {
if(!in_array($settingForumTablePrefix, array('myaac_', 'z_'))) {
throw new RuntimeException('Invalid value for forum_table_prefix in config.php. Can be only: "myaac_" or "z_".');
}
define('FORUM_TABLE_PREFIX', $configForumTablePrefix);
define('FORUM_TABLE_PREFIX', $settingForumTablePrefix);
}
else {
if($db->hasTable('z_forum')) {
@@ -47,7 +47,7 @@ class Forum
return
$db->query(
'SELECT `id` FROM `players` WHERE `account_id` = ' . $db->quote($account->getId()) .
' AND `level` >= ' . $db->quote($config['forum_level_required']) .
' AND `level` >= ' . $db->quote(setting('core.forum_level_required')) .
' LIMIT 1')->rowCount() > 0;
}

View File

@@ -78,8 +78,6 @@ class Items
}
public static function getDescription($id, $count = 1) {
global $db;
$item = self::get($id);
$attr = $item['attributes'];
@@ -112,17 +110,15 @@ class Items
$s .= 'an item of type ' . $item['id'];
if(isset($attr['type']) && strtolower($attr['type']) == 'rune') {
$query = $db->query('SELECT `level`, `maglevel`, `vocations` FROM `' . TABLE_PREFIX . 'spells` WHERE `item_id` = ' . $id);
if($query->rowCount() == 1) {
$query = $query->fetch();
if($query['level'] > 0 && $query['maglevel'] > 0) {
$item = Spells::where('item_id', $id)->first();
if($item) {
if($item->level > 0 && $item->maglevel > 0) {
$s .= '. ' . ($count > 1 ? "They" : "It") . ' can only be used by ';
}
$configVocations = config('vocations');
if(!empty(trim($query['vocations']))) {
$vocations = json_decode($query['vocations']);
if(!empty(trim($item->vocations))) {
$vocations = json_decode($item->vocations);
if(count($vocations) > 0) {
foreach($vocations as $voc => $show) {
$vocations[$configVocations[$voc]] = $show;

View File

@@ -1,265 +0,0 @@
<?php
/**
* Items_Images class
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
if ( !function_exists( 'stackId' ) )
{
function stackId( $count )
{
if ( $count >= 50 )
$stack = 8;
elseif ( $count >= 25 )
$stack = 7;
elseif ( $count >= 10 )
$stack = 6;
elseif ( $count >= 5 )
$stack = 5;
elseif ( $count >= 4 )
$stack = 4;
elseif ( $count >= 3 )
$stack = 3;
elseif ( $count >= 2 )
$stack = 2;
else
$stack = 1;
return $stack;
}
}
class Items_Images
{
public static $outputDir = '';
public static $files = array();
private static $otb, $dat, $spr;
private static $lastItem;
private static $loaded = false;
public function __destruct()
{
if(self::$otb)
fclose(self::$otb);
if(self::$dat)
fclose(self::$dat);
if(self::$spr)
fclose(self::$spr);
}
public static function generate($id = 100, $count = 1)
{
if(!self::$loaded)
self::load();
$originalId = $id;
if($id < 100)
return false;
//die('ID cannot be lower than 100.');
rewind(self::$otb);
rewind(self::$dat);
rewind(self::$spr);
$nostand = false;
$init = false;
$originalId = $id;
// parse info from otb
while( false !== ( $char = fgetc( self::$otb ) ) )
{
$byte = HEX_PREFIX.bin2hex( $char );
if ( $byte == 0xFE )
$init = true;
elseif ( $byte == 0x10 and $init ) {
extract( unpack( 'x2/Ssid', fread( self::$otb, 4 ) ) );
if ( $id == $sid ) {
if ( HEX_PREFIX.bin2hex( fread( self::$otb, 1 ) ) == 0x11 ) {
extract( unpack( 'x2/Sid', fread( self::$otb, 4 ) ) );
break;
}
}
$init = false;
}
}
self::$lastItem = array_sum( unpack( 'x4/S*', fread( self::$dat, 12 )));
if($id > self::$lastItem)
return false;
//ini_set('max_execution_time', 300);
// parse info from dat
for( $i = 100; $i <= $id; $i++ ) {
while( ( $byte = HEX_PREFIX.bin2hex( fgetc( self::$dat ) ) ) != 0xFF ) {
$offset = 0;
switch( $byte ) {
case 0x00:
case 0x09:
case 0x0A:
case 0x1A:
case 0x1D:
case 0x1E:
$offset = 2;
break;
case 0x16:
case 0x19:
$offset = 4;
break;
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
case 0x08:
case 0x0B:
case 0x0C:
case 0x0D:
case 0x0E:
case 0x0F:
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x17:
case 0x18:
case 0x1B:
case 0x1C:
case 0x1F:
case 0x20:
break;
default:
return false; #trigger_error( sprintf( 'Unknown .DAT byte %s (previous byte: %s; address %x)', $byte, $prev, ftell( $dat ), E_USER_ERROR ) );
break;
}
$prev = $byte;
fseek( self::$dat, $offset, SEEK_CUR );
}
extract( unpack( 'Cwidth/Cheight', fread( self::$dat, 2 ) ) );
if ( $width > 1 or $height > 1 ) {
fseek( self::$dat, 1, SEEK_CUR );
$nostand = true;
}
$sprites_c = array_product( unpack( 'C*', fread( self::$dat, 5 ) ) ) * $width * $height;
$sprites = unpack( 'S*', fread( self::$dat, 2 * $sprites_c ) );
}
if ( array_key_exists( stackId( $count ), $sprites ) ) {
$sprites = (array) $sprites[stackId( $count )];
}
else {
$sprites = (array) $sprites[array_rand( $sprites ) ];
}
fseek( self::$spr, 6 );
$sprite = imagecreatetruecolor( 32 * $width, 32 * $height );
imagecolortransparent( $sprite, imagecolorallocate( $sprite, 0, 0, 0 ) );
foreach( $sprites as $key => $value ) {
fseek( self::$spr, 6 + ( $value - 1 ) * 4 );
extract( unpack( 'Laddress', fread( self::$spr, 4 ) ) );
fseek( self::$spr, $address + 3 );
extract( unpack( 'Ssize', fread( self::$spr, 2 ) ) );
list( $num, $bit ) = array( 0, 0 );
while( $bit < $size ) {
$pixels = unpack( 'Strans/Scolored', fread( self::$spr, 4 ) );
$num += $pixels['trans'];
for( $i = 0; $i < $pixels['colored']; $i++ )
{
extract( unpack( 'Cred/Cgreen/Cblue', fread( self::$spr, 3 ) ) );
$red = ( $red == 0 ? ( $green == 0 ? ( $blue == 0 ? 1 : $red ) : $red ) : $red );
imagesetpixel( $sprite,
$num % 32 + ( $key % 2 == 1 ? 32 : 0 ),
$num / 32 + ( $key % 4 != 1 and $key % 4 != 0 ? 32 : 0 ),
imagecolorallocate( $sprite, $red, $green, $blue ) );
$num++;
}
$bit += 4 + 3 * $pixels['colored'];
}
}
if ( $count >= 2 ) {
if ( $count > 100 )
$count = 100;
$font = 3;
$length = imagefontwidth( $font ) * strlen( $count );
$pos = array(
'x' => ( 32 * $width ) - ( $length + 1 ),
'y' => ( 32 * $height ) - 13
);
imagestring( $sprite, $font, $pos['x'] - 1, $pos['y'] - 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) );
imagestring( $sprite, $font, $pos['x'], $pos['y'] - 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) );
imagestring( $sprite, $font, $pos['x'] - 1, $pos['y'], $count, imagecolorallocate( $sprite, 1, 1, 1 ) );
imagestring( $sprite, $font, $pos['x'], $pos['y'] + 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) );
imagestring( $sprite, $font, $pos['x'] + 1, $pos['y'], $count, imagecolorallocate( $sprite, 1, 1, 1 ) );
imagestring( $sprite, $font, $pos['x'] + 1, $pos['y'] + 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) );
imagestring( $sprite, $font, $pos['x'], $pos['y'], $count, imagecolorallocate( $sprite, 219, 219, 219 ) );
}
$imagePath = self::$outputDir . ($count > 1 ? $originalId . '-' . $count : $originalId ) . '.gif';
// save image
imagegif($sprite, $imagePath);
}
public static function load()
{
if(!defined( 'HEX_PREFIX'))
define('HEX_PREFIX', '0x');
self::$otb = fopen(self::$files['otb'], 'rb');
self::$dat = fopen(self::$files['dat'], 'rb');
self::$spr = fopen(self::$files['spr'], 'rb');
if(!self::$otb || !self::$dat || !self::$spr)
throw new RuntimeException('ERROR: Cannot load data files.');
/*
if ( $nostand )
{
for( $i = 0; $i < count( $sprites ) / 4; $i++ )
{
$sprites = array_merge( (array) $sprites, array_reverse( array_slice( $sprites, $i * 4, 4 ) ) );
}
}
else
{
$sprites = (array) $sprites[array_rand( $sprites ) ];
}
*/
self::$loaded = true;
}
public static function loaded() {
return self::$loaded;
}
}

View File

@@ -1,5 +1,7 @@
<?php
use MyAAC\Models\News as ModelsNews;
class News
{
static public function verify($title, $body, $article_text, $article_image, &$errors)
@@ -29,43 +31,64 @@ class News
static public function add($title, $body, $type, $category, $player_id, $comments, $article_text, $article_image, &$errors)
{
global $db;
if(!self::verify($title, $body, $article_text, $article_image, $errors))
return false;
$db->insert(TABLE_PREFIX . 'news', array('title' => $title, 'body' => $body, 'type' => $type, 'date' => time(), 'category' => $category, 'player_id' => isset($player_id) ? $player_id : 0, 'comments' => $comments, 'article_text' => ($type == 3 ? $article_text : ''), 'article_image' => ($type == 3 ? $article_image : '')));
ModelsNews::create([
'title' => $title,
'body' => $body,
'type' => $type,
'date' => time(),
'category' => $category,
'player_id' => isset($player_id) ? $player_id : 0,
'comments' => $comments,
'article_text' => ($type == 3 ? $article_text : ''),
'article_image' => ($type == 3 ? $article_image : '')
]);
self::clearCache();
return true;
}
static public function get($id) {
global $db;
return $db->select(TABLE_PREFIX . 'news', array('id' => $id));
return ModelsNews::find($id)->toArray();
}
static public function update($id, $title, $body, $type, $category, $player_id, $comments, $article_text, $article_image, &$errors)
{
global $db;
if(!self::verify($title, $body, $article_text, $article_image, $errors))
return false;
$db->update(TABLE_PREFIX . 'news', array('title' => $title, 'body' => $body, 'type' => $type, 'category' => $category, 'last_modified_by' => isset($player_id) ? $player_id : 0, 'last_modified_date' => time(), 'comments' => $comments, 'article_text' => $article_text, 'article_image' => $article_image), array('id' => $id));
ModelsNews::where('id', $id)->update([
'title' => $title,
'body' => $body,
'type' => $type,
'category' => $category,
'last_modified_by' => isset($player_id) ? $player_id : 0,
'last_modified_date' => time(),
'comments' => $comments,
'article_text' => $article_text,
'article_image' => $article_image
]);
self::clearCache();
return true;
}
static public function delete($id, &$errors)
{
global $db;
if(isset($id))
{
if($db->select(TABLE_PREFIX . 'news', array('id' => $id)) !== false)
$db->delete(TABLE_PREFIX . 'news', array('id' => $id));
else
if(isset($id)) {
$row = ModelsNews::find($id);
if($row) {
if (!$row->delete()) {
$errors[] = 'Fail during delete News.';
}
}
else {
$errors[] = 'News with id ' . $id . ' does not exists.';
}
}
else
else {
$errors[] = 'News id not set.';
}
if(count($errors)) {
return false;
@@ -77,14 +100,16 @@ class News
static public function toggleHidden($id, &$errors, &$status)
{
global $db;
if(isset($id))
{
$query = $db->select(TABLE_PREFIX . 'news', array('id' => $id));
if($query !== false)
$row = ModelsNews::find($id);
if($row)
{
$db->update(TABLE_PREFIX . 'news', array('hidden' => ($query['hidden'] == 1 ? 0 : 1)), array('id' => $id));
$status = $query['hidden'];
$row->hidden = $row->hidden == 1 ? 0 : 1;
if (!$row->save()) {
$errors[] = 'Fail during toggle hidden News.';
}
$status = $row->hidden;
}
else
$errors[] = 'News with id ' . $id . ' does not exists.';

View File

@@ -39,6 +39,7 @@ function is_sub_dir($path = NULL, $parent_folder = BASE) {
}
use Composer\Semver\Semver;
use MyAAC\Models\Menu;
class Plugins {
private static $warnings = [];
@@ -151,7 +152,7 @@ class Plugins {
foreach(self::getAllPluginsJson() as $plugin) {
if (isset($plugin['hooks'])) {
foreach ($plugin['hooks'] as $_name => $info) {
if (strpos($info['type'], 'HOOK_') !== false) {
if (str_contains($info['type'], 'HOOK_')) {
$info['type'] = str_replace('HOOK_', '', $info['type']);
}
@@ -172,6 +173,36 @@ class Plugins {
return $hooks;
}
public static function getAllPluginsSettings()
{
$cache = Cache::getInstance();
if ($cache->enabled()) {
$tmp = '';
if ($cache->fetch('plugins_settings', $tmp)) {
return unserialize($tmp);
}
}
$settings = [];
foreach (self::getAllPluginsJson() as $plugin) {
if (isset($plugin['settings'])) {
$settingsFile = require BASE . $plugin['settings'];
if (!isset($settingsFile['key'])) {
warning("Settings file for plugin - {$plugin['name']} does not contain 'key' field");
continue;
}
$settings[$settingsFile['key']] = ['pluginFilename' => $plugin['filename'], 'settingsFilename' => $plugin['settings']];
}
}
if ($cache->enabled()) {
$cache->set('plugins_settings', serialize($settings), 600); // cache for 10 minutes
}
return $settings;
}
public static function getAllPluginsJson($disabled = false)
{
$cache = Cache::getInstance();
@@ -184,30 +215,66 @@ class Plugins {
$plugins = [];
foreach (get_plugins($disabled) as $filename) {
$string = file_get_contents(PLUGINS . $filename . '.json');
$plugin = json_decode($string, true);
self::$plugin_json = $plugin;
if ($plugin == null) {
self::$warnings[] = 'Cannot load ' . $filename . '.json. File might be not a valid json code.';
continue;
}
if (isset($plugin['enabled']) && !getBoolean($plugin['enabled'])) {
self::$warnings[] = 'Skipping ' . $filename . '... The plugin is disabled.';
$plugin = self::getPluginJson($filename);
if (!$plugin) {
continue;
}
$plugin['filename'] = $filename;
$plugins[] = $plugin;
}
if ($cache->enabled()) {
$cache->set('plugins', serialize($plugins), 600);
$cache->set('plugins', serialize($plugins), 600); // cache for 10 minutes
}
return $plugins;
}
public static function install($file) {
public static function getPluginSettings($filename)
{
$plugin_json = self::getPluginJson($filename);
if (!$plugin_json) {
return false;
}
if (!isset($plugin_json['settings']) || !file_exists(BASE . $plugin_json['settings'])) {
return false;
}
return $plugin_json['settings'];
}
public static function getPluginJson($filename = null)
{
if(!isset($filename)) {
return self::$plugin_json;
}
$pathToPlugin = PLUGINS . $filename . '.json';
if (!file_exists($pathToPlugin)) {
self::$warnings[] = "Cannot load $filename.json. File doesn't exist.";
return false;
}
$string = file_get_contents($pathToPlugin);
$plugin_json = json_decode($string, true);
if ($plugin_json == null) {
self::$warnings[] = "Cannot load $filename.json. File might be not a valid json code.";
return false;
}
if (isset($plugin_json['enabled']) && !getBoolean($plugin_json['enabled'])) {
self::$warnings[] = 'Skipping ' . $filename . '... The plugin is disabled.';
return false;
}
return $plugin_json;
}
public static function install($file): bool
{
global $db;
if(!\class_exists('ZipArchive')) {
@@ -246,6 +313,12 @@ class Plugins {
return false;
}
$pluginFilename = str_replace('.json', '', basename($json_file));
if (self::existDisabled($pluginFilename)) {
success('The plugin already existed, but was disabled. It has been enabled again and will be now reinstalled.');
self::enable($pluginFilename);
}
$string = file_get_contents($file_name);
$plugin_json = json_decode($string, true);
self::$plugin_json = $plugin_json;
@@ -446,13 +519,23 @@ class Plugins {
return false;
}
public static function enable($pluginFileName): bool
public static function isEnabled($pluginFileName): bool
{
$filenameJson = $pluginFileName . '.json';
return !is_file(PLUGINS . 'disabled.' . $filenameJson) && is_file(PLUGINS . $filenameJson);
}
public static function existDisabled($pluginFileName): bool
{
$filenameJson = $pluginFileName . '.json';
return is_file(PLUGINS . 'disabled.' . $filenameJson);
}
public static function enable($pluginFileName): bool {
return self::enableDisable($pluginFileName, true);
}
public static function disable($pluginFileName): bool
{
public static function disable($pluginFileName): bool {
return self::enableDisable($pluginFileName, false);
}
@@ -530,7 +613,8 @@ class Plugins {
return false;
}
public static function is_installed($plugin_name, $version) {
public static function is_installed($plugin_name, $version): bool
{
$filename = BASE . 'plugins/' . $plugin_name . '.json';
if(!file_exists($filename)) {
return false;
@@ -538,7 +622,7 @@ class Plugins {
$string = file_get_contents($filename);
$plugin_info = json_decode($string, true);
if($plugin_info == false) {
if(!$plugin_info) {
return false;
}
@@ -561,10 +645,6 @@ class Plugins {
return self::$error;
}
public static function getPluginJson() {
return self::$plugin_json;
}
/**
* Install menus
* Helper function for plugins
@@ -574,11 +654,9 @@ class Plugins {
*/
public static function installMenus($templateName, $categories)
{
global $db;
// check if menus already exist
$query = $db->query('SELECT `id` FROM `' . TABLE_PREFIX . 'menu` WHERE `template` = ' . $db->quote($templateName) . ' LIMIT 1;');
if ($query->rowCount() > 0) {
$menuInstalled = Menu::where('template', $templateName)->select('id')->first();
if ($menuInstalled) {
return;
}
@@ -612,7 +690,7 @@ class Plugins {
'color' => $color,
];
$db->insert(TABLE_PREFIX . 'menu', $insert_array);
Menu::create($insert_array);
}
}
}

View File

@@ -57,7 +57,7 @@ class OTS_ServerInfo
private function send(OTS_Buffer $packet)
{
// connects to server
$socket = @fsockopen($this->server, $this->port, $error, $message, config('status_timeout'));
$socket = @fsockopen($this->server, $this->port, $error, $message, setting('core.status_timeout'));
// if connected then checking statistics
if($socket)

View File

@@ -8,6 +8,9 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Spell;
defined('MYAAC') or die('Direct access not allowed!');
class Spells {
@@ -31,9 +34,11 @@ class Spells {
}
public static function loadFromXML($show = false) {
global $config, $db;
global $config;
try { $db->exec('DELETE FROM `' . TABLE_PREFIX . 'spells`;'); } catch(PDOException $error) {}
try {
Spell::query()->delete();
} catch(Exception $error) {}
if($show) {
echo '<h2>Reload spells.</h2>';
@@ -63,7 +68,7 @@ class Spells {
continue;
try {
$db->insert(TABLE_PREFIX . 'spells', array(
Spell::create(array(
'name' => $name,
'words' => $words,
'type' => 2,
@@ -105,7 +110,7 @@ class Spells {
continue;
try {
$db->insert(TABLE_PREFIX . 'spells', array(
Spell::create(array(
'name' => $name,
'words' => $words,
'type' => 1,
@@ -142,7 +147,7 @@ class Spells {
$name = $spell->getName() . ' Rune';
try {
$db->insert(TABLE_PREFIX . 'spells', array(
Spell::create(array(
'name' => $name,
'words' => $spell->getWords(),
'type' => 3,

View File

@@ -106,8 +106,8 @@ WHERE TABLE_SCHEMA = "' . $config['database_name'] . '";');
}
$ret['templates'] = get_templates();
$ret['date_timezone'] = $config['date_timezone'];
$ret['backward_support'] = $config['backward_support'];
$ret['date_timezone'] = setting('core.date_timezone');
$ret['backward_support'] = setting('core.backward_support');
$cache_engine = strtolower($config['cache_engine']);
if($cache_engine == 'auto') {

View File

@@ -7,6 +7,10 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Monster;
use MyAAC\Models\Spell;
defined('MYAAC') or die('Direct access not allowed!');
class Validator
@@ -117,7 +121,7 @@ class Validator
return false;
}
if(config('account_mail_block_plus_sign')) {
if(setting('core.account_mail_block_plus_sign')) {
$explode = explode('@', $email);
if(isset($explode[0]) && (strpos($explode[0],'+') !== false)) {
self::$lastError = 'Please do not use plus (+) sign in your e-mail.';
@@ -180,15 +184,16 @@ class Validator
return false;
}
$minLength = config('character_name_min_length');
$maxLength = config('character_name_max_length');
// installer doesn't know config.php yet
// that's why we need to ignore the nulls
if(is_null($minLength) || is_null($maxLength)) {
if(defined('MYAAC_INSTALL')) {
$minLength = 4;
$maxLength = 21;
}
else {
$minLength = setting('core.create_character_name_min_length');
$maxLength = setting('core.create_character_name_max_length');
}
$length = strlen($name);
if($length < $minLength)
@@ -221,16 +226,6 @@ class Validator
return false;
}
$npcCheck = config('character_name_npc_check');
if ($npcCheck) {
require_once LIBS . 'npc.php';
NPCS::load();
if(NPCS::$npcs && in_array(strtolower($name), NPCS::$npcs)) {
self::$lastError = "Invalid name format. Do not use NPC Names";
return false;
}
}
return true;
}
@@ -247,9 +242,8 @@ class Validator
$name_lower = strtolower($name);
$first_words_blocked = array('admin ', 'administrator ', 'gm ', 'cm ', 'god ','tutor ', "'", '-');
foreach($first_words_blocked as $word)
{
$first_words_blocked = array_merge(["'", '-'], setting('core.create_character_name_blocked_prefix'));
foreach($first_words_blocked as $word) {
if($word == substr($name_lower, 0, strlen($word))) {
self::$lastError = 'Your name contains blocked words.';
return false;
@@ -271,8 +265,7 @@ class Validator
return false;
}
if(preg_match('/ {2,}/', $name))
{
if(preg_match('/ {2,}/', $name)) {
self::$lastError = 'Invalid character name format. Use only A-Z and numbers 0-9 and no double spaces.';
return false;
}
@@ -282,18 +275,16 @@ class Validator
return false;
}
$names_blocked = array('admin', 'administrator', 'gm', 'cm', 'god', 'tutor');
foreach($names_blocked as $word)
{
$names_blocked = setting('core.create_character_name_blocked_names');
foreach($names_blocked as $word) {
if($word == $name_lower) {
self::$lastError = 'Your name contains blocked words.';
return false;
}
}
$words_blocked = array('admin', 'administrator', 'gamemaster', 'game master', 'game-master', "game'master", '--', "''","' ", " '", '- ', ' -', "-'", "'-", 'fuck', 'sux', 'suck', 'noob', 'tutor');
foreach($words_blocked as $word)
{
$words_blocked = array_merge(['--', "''","' ", " '", '- ', ' -', "-'", "'-"], setting('core.create_character_name_blocked_words'));
foreach($words_blocked as $word) {
if(!(strpos($name_lower, $word) === false)) {
self::$lastError = 'Your name contains illegal words.';
return false;
@@ -309,7 +300,7 @@ class Validator
}
}
//check if was namelocked previously
// check if was namelocked previously
if($db->hasTable('player_namelocks') && $db->hasColumn('player_namelocks', 'name')) {
$namelock = $db->query('SELECT `player_id` FROM `player_namelocks` WHERE `name` = ' . $db->quote($name));
if($namelock->rowCount() > 0) {
@@ -318,39 +309,38 @@ class Validator
}
}
$monsters = $db->query('SELECT `name` FROM `' . TABLE_PREFIX . 'monsters` WHERE `name` LIKE ' . $db->quote($name_lower));
if($monsters->rowCount() > 0) {
self::$lastError = 'Your name cannot contains monster name.';
return false;
}
$spells_name = $db->query('SELECT `name` FROM `' . TABLE_PREFIX . 'spells` WHERE `name` LIKE ' . $db->quote($name_lower));
if($spells_name->rowCount() > 0) {
self::$lastError = 'Your name cannot contains spell name.';
return false;
}
$spells_words = $db->query('SELECT `words` FROM `' . TABLE_PREFIX . 'spells` WHERE `words` = ' . $db->quote($name_lower));
if($spells_words->rowCount() > 0) {
self::$lastError = 'Your name cannot contains spell name.';
return false;
}
if(isset($config['npc']))
{
if(in_array($name_lower, $config['npc'])) {
self::$lastError = 'Your name cannot contains NPC name.';
$monstersCheck = setting('core.create_character_name_monsters_check');
if ($monstersCheck) {
if (Monster::where('name', 'like', $name_lower)->exists()) {
self::$lastError = 'Your name cannot contains monster name.';
return false;
}
}
$npcCheck = config('character_name_npc_check');
$spellsCheck = setting('core.create_character_name_spells_check');
if ($spellsCheck) {
if (Spell::where('name', 'like', $name_lower)->exists()) {
self::$lastError = 'Your name cannot contains spell name.';
return false;
}
if (Spell::where('words', $name_lower)->exists()) {
self::$lastError = 'Your name cannot contains spell name.';
return false;
}
}
$npcCheck = setting('core.create_character_name_npc_check');
if ($npcCheck) {
require_once LIBS . 'npc.php';
NPCS::load();
if(NPCS::$npcs && in_array($name_lower, NPCS::$npcs)) {
self::$lastError = "Invalid name format. Do not use NPC Names";
return false;
if(NPCS::$npcs) {
foreach (NPCs::$npcs as $npc) {
if(strpos($name_lower, $npc) !== false) {
self::$lastError = 'Your name cannot contains NPC name.';
return false;
}
}
}
}

View File

@@ -7,6 +7,9 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Visitor;
defined('MYAAC') or die('Direct access not allowed!');
class Visitors
@@ -54,9 +57,7 @@ class Visitors
return isset($this->data[$ip]);
}
global $db;
$users = $db->query('SELECT COUNT(`ip`) as count FROM `' . TABLE_PREFIX . 'visitors' . '` WHERE ' . $db->fieldName('ip') . ' = ' . $db->quote($ip))->fetch();
return ($users['count'] > 0);
return Visitor::where('ip', $ip)->exists();
}
private function cleanVisitors()
@@ -73,8 +74,7 @@ class Visitors
return;
}
global $db;
$db->exec('DELETE FROM ' . $db->tableName(TABLE_PREFIX . 'visitors') . ' WHERE ' . $db->fieldName('lastvisit') . ' < ' . (time() - $this->sessionTime * 60));
Visitor::where('lastvisit', '<', (time() - $this->sessionTime * 60))->delete();
}
private function updateVisitor($ip, $page, $userAgent)
@@ -84,8 +84,7 @@ class Visitors
return;
}
global $db;
$db->update(TABLE_PREFIX . 'visitors', ['lastvisit' => time(), 'page' => $page, 'user_agent' => $userAgent], ['ip' => $ip]);
Visitor::where('ip', $ip)->update(['lastvisit' => time(), 'page' => $page, 'user_agent' => $userAgent]);
}
private function addVisitor($ip, $page, $userAgent)
@@ -95,8 +94,7 @@ class Visitors
return;
}
global $db;
$db->insert(TABLE_PREFIX . 'visitors', ['ip' => $ip, 'lastvisit' => time(), 'page' => $page, 'user_agent' => $userAgent]);
Visitor::create(['ip' => $ip, 'lastvisit' => time(), 'page' => $page, 'user_agent' => $userAgent]);
}
public function getVisitors()
@@ -108,8 +106,7 @@ class Visitors
return $this->data;
}
global $db;
return $db->query('SELECT ' . $db->fieldName('ip') . ', ' . $db->fieldName('lastvisit') . ', ' . $db->fieldName('page') . ', ' . $db->fieldName('user_agent') . ' FROM ' . $db->tableName(TABLE_PREFIX . 'visitors') . ' ORDER BY ' . $db->fieldName('lastvisit') . ' DESC')->fetchAll();
return Visitor::orderByDesc('lastvisit')->get()->toArray();
}
public function getAmountVisitors()
@@ -118,9 +115,7 @@ class Visitors
return count($this->data);
}
global $db;
$users = $db->query('SELECT COUNT(`ip`) as count FROM `' . TABLE_PREFIX . 'visitors`')->fetch();
return $users['count'];
return Visitor::count();
}
public function show() {

View File

@@ -8,6 +8,9 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Weapon;
defined('MYAAC') or die('Direct access not allowed!');
class Weapons {
@@ -15,10 +18,10 @@ class Weapons {
public static function loadFromXML($show = false)
{
global $config, $db;
global $config;
try {
$db->exec("DELETE FROM `myaac_weapons`;");
Weapon::query()->delete();
} catch (PDOException $error) {
}
@@ -45,7 +48,7 @@ class Weapons {
}
public static function parseNode($node, $show = false) {
global $config, $db;
global $config;
$id = (int)$node->getAttribute('id');
$vocations_ids = array_flip($config['vocations']);
@@ -64,14 +67,15 @@ class Weapons {
$vocations[$voc_id] = strlen($show) == 0 || $show != '0';
}
$exist = $db->query('SELECT `id` FROM `' . TABLE_PREFIX . 'weapons` WHERE `id` = ' . $id);
if($exist->rowCount() > 0) {
if(Weapon::find($id)) {
if($show) {
warning('Duplicated weapon with id: ' . $id);
}
}
else {
$db->insert(TABLE_PREFIX . 'weapons', array('id' => $id, 'level' => $level, 'maglevel' => $maglevel, 'vocations' => json_encode($vocations)));
Weapon::create([
'id' => $id, 'level' => $level, 'maglevel' => $maglevel, 'vocations' => json_encode($vocations)
]);
}
}

View File

@@ -7,6 +7,9 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\CsrfToken;
defined('MYAAC') or die('Direct access not allowed!');
if(isset($account_logged) && $account_logged->isLoaded()) {
@@ -15,6 +18,8 @@ if(isset($account_logged) && $account_logged->isLoaded()) {
unsetSession('password');
unsetSession('remember_me');
CsrfToken::generate();
$logged = false;
unset($account_logged);

View File

@@ -14,75 +14,9 @@ CREATE TABLE `myaac_menu`
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
");
$db->query("
/* MENU_CATEGORY_NEWS kathrine */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Latest News', 'news', 1, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'News Archive', 'news/archive', 1, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Changelog', 'changelog', 1, 2);
/* MENU_CATEGORY_ACCOUNT kathrine */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Account Management', 'account/manage', 2, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Create Account', 'account/create', 2, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Lost Account?', 'account/lost', 2, 2);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Server Rules', 'rules', 2, 3);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Downloads', 'downloads', 5, 4);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Report Bug', 'bugtracker', 2, 5);
/* MENU_CATEGORY_COMMUNITY kathrine */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Who is Online?', 'online', 3, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Characters', 'characters', 3, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Guilds', 'guilds', 3, 2);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Highscores', 'highscores', 3, 3);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Last Deaths', 'lastkills', 3, 4);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Houses', 'houses', 3, 5);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Bans', 'bans', 3, 6);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Forum', 'forum', 3, 7);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Team', 'team', 3, 8);
/* MENU_CATEGORY_LIBRARY kathrine */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Monsters', 'creatures', 5, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Spells', 'spells', 5, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Server Info', 'serverInfo', 5, 2);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Commands', 'commands', 5, 3);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Gallery', 'gallery', 5, 4);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Experience Table', 'experienceTable', 5, 5);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'FAQ', 'faq', 5, 6);
/* MENU_CATEGORY_SHOP kathrine */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Buy Points', 'points', 6, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Shop Offer', 'gifts', 6, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Shop History', 'gifts/history', 6, 2);
/* MENU_CATEGORY_NEWS tibiacom */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Latest News', 'news', 1, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'News Archive', 'news/archive', 1, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Changelog', 'changelog', 1, 2);
/* MENU_CATEGORY_ACCOUNT tibiacom */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Account Management', 'account/manage', 2, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Create Account', 'account/create', 2, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Lost Account?', 'account/lost', 2, 2);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Server Rules', 'rules', 2, 3);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Downloads', 'downloads', 2, 4);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Report Bug', 'bugtracker', 2, 5);
/* MENU_CATEGORY_COMMUNITY tibiacom */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Characters', 'characters', 3, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Who Is Online?', 'online', 3, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Highscores', 'highscores', 3, 2);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Last Kills', 'lastkills', 3, 3);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Houses', 'houses', 3, 4);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Guilds', 'guilds', 3, 5);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Polls', 'polls', 3, 6);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Bans', 'bans', 3, 7);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Support List', 'team', 3, 8);
/* MENU_CATEGORY_FORUM tibiacom */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Forum', 'forum', 4, 0);
/* MENU_CATEGORY_LIBRARY tibiacom */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Creatures', 'creatures', 5, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Spells', 'spells', 5, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Commands', 'commands', 5, 2);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Exp Stages', 'experienceStages', 5, 3);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Gallery', 'gallery', 5, 4);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Server Info', 'serverInfo', 5, 5);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Experience Table', 'experienceTable', 5, 6);
/* MENU_CATEGORY_SHOP tibiacom */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Buy Points', 'points', 6, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Shop Offer', 'gifts', 6, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Shop History', 'gifts/history', 6, 2);
");
}
require_once LIBS . 'plugins.php';
Plugins::installMenus('kathrine', require TEMPLATES . 'kathrine/menus.php');
Plugins::installMenus('tibiacom', require TEMPLATES . 'tibiacom/menus.php');

View File

@@ -1,47 +1,15 @@
<?php
if(!isset($database_migration_20)) {
databaseMigration20();
$query = $db->query("SELECT `id` FROM `players` WHERE (`name` = " . $db->quote("Rook Sample") . " OR `name` = " . $db->quote("Sorcerer Sample") . " OR `name` = " . $db->quote("Druid Sample") . " OR `name` = " . $db->quote("Paladin Sample") . " OR `name` = " . $db->quote("Knight Sample") . " OR `name` = " . $db->quote("Account Manager") . ") ORDER BY `id`;");
$highscores_ignored_ids = array();
if($query->rowCount() > 0) {
foreach($query->fetchAll() as $result)
$highscores_ignored_ids[] = $result['id'];
}
else {
$highscores_ignored_ids[] = 0;
}
function databaseMigration20(&$content = '') {
global $db;
$config_file = BASE . 'config.local.php';
if(!is_writable($config_file)) { // we can't do anything, just ignore
return false;
}
$content_of_file = trim(file_get_contents($config_file));
if(strpos($content_of_file, 'highscores_ids_hidden') !== false) { // already present
return true;
}
$query = $db->query("SELECT `id` FROM `players` WHERE (`name` = " . $db->quote("Rook Sample") . " OR `name` = " . $db->quote("Sorcerer Sample") . " OR `name` = " . $db->quote("Druid Sample") . " OR `name` = " . $db->quote("Paladin Sample") . " OR `name` = " . $db->quote("Knight Sample") . " OR `name` = " . $db->quote("Account Manager") . ") ORDER BY `id`;");
$highscores_ignored_ids = array();
if($query->rowCount() > 0) {
foreach($query->fetchAll() as $result)
$highscores_ignored_ids[] = $result['id'];
}
else {
$highscores_ignored_ids[] = 0;
}
$php_on_end = substr($content_of_file, -2, 2) == '?>';
$content = PHP_EOL;
if($php_on_end) {
$content .= '<?php';
}
$content .= PHP_EOL;
$content .= '$config[\'highscores_ids_hidden\'] = array(' . implode(', ', $highscores_ignored_ids) . ');';
$content .= PHP_EOL;
if($php_on_end) {
$content .= '?>';
}
file_put_contents($config_file, $content, FILE_APPEND);
return true;
}
$settings = Settings::getInstance();
$settings->updateInDatabase('core', 'highscores_ids_hidden', implode(', ', $highscores_ignored_ids));

14
system/migrations/36.php Normal file
View File

@@ -0,0 +1,14 @@
<?php
// add settings table
if(!$db->hasTable(TABLE_PREFIX . 'settings')) {
$db->exec("CREATE TABLE `" . TABLE_PREFIX . "settings`
(
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL DEFAULT '',
`key` VARCHAR(255) NOT NULL DEFAULT '',
`value` TEXT NOT NULL,
PRIMARY KEY (`id`),
KEY `key` (`key`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;");
}

View File

@@ -8,6 +8,9 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Player;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Change Comment';
@@ -17,36 +20,36 @@ if(!$logged) {
return;
}
$player = null;
$player_name = isset($_REQUEST['name']) ? stripslashes(urldecode($_REQUEST['name'])) : null;
$new_comment = isset($_POST['comment']) ? htmlspecialchars(stripslashes(substr($_POST['comment'],0,2000))) : NULL;
$new_hideacc = isset($_POST['accountvisible']) ? (int)$_POST['accountvisible'] : NULL;
if($player_name != null) {
if (Validator::characterName($player_name)) {
$player = new OTS_Player();
$player->find($player_name);
if ($player->isLoaded()) {
$player_account = $player->getAccount();
if ($account_logged->getId() == $player_account->getId()) {
if ($player->isDeleted()) {
$errors[] = 'This character is deleted.';
$player = null;
}
$player = Player::query()
->where('name', $player_name)
->where('account_id', $account_logged->getId())
->first();
if (isset($_POST['changecommentsave']) && $_POST['changecommentsave'] == 1) {
if(empty($errors)) {
$player->setCustomField("hidden", $new_hideacc);
$player->setCustomField("comment", $new_comment);
$account_logged->logAction('Changed comment for character <b>' . $player->getName() . '</b>.');
$twig->display('success.html.twig', array(
'title' => 'Character Information Changed',
'description' => 'The character information has been changed.'
));
$show_form = false;
}
if ($player) {
if ($player->is_deleted) {
$errors[] = 'This character is deleted.';
$player = null;
}
if (isset($_POST['changecommentsave']) && $_POST['changecommentsave'] == 1) {
if(empty($errors)) {
$player->hidden = $new_hideacc;
$player->comment = $new_comment;
$player->save();
$account_logged->logAction('Changed comment for character <b>' . $player->name . '</b>.');
$twig->display('success.html.twig', array(
'title' => 'Character Information Changed',
'description' => 'The character information has been changed.'
));
$show_form = false;
}
} else {
$errors[] = 'Error. Character <b>' . $player_name . '</b> is not on your account.';
}
} else {
$errors[] = "Error. Character with this name doesn't exist.";
@@ -64,9 +67,9 @@ if($show_form) {
$twig->display('error_box.html.twig', array('errors' => $errors));
}
if(isset($player) && $player->isLoaded()) {
if(isset($player) && $player) {
$twig->display('account.change_comment.html.twig', array(
'player' => $player
'player' => $player->toArray()
));
}
}

View File

@@ -43,7 +43,7 @@ if($email_new_time < 10) {
}
if(empty($errors)) {
$email_new_time = time() + $config['account_mail_change'] * 24 * 3600;
$email_new_time = time() + setting('core.account_mail_change') * 24 * 3600;
$account_logged->setCustomField("email_new", $email_new);
$account_logged->setCustomField("email_new_time", $email_new_time);
$twig->display('success.html.twig', array(
@@ -92,18 +92,22 @@ else
<tr>
<td width="30">&nbsp;</td>
<td align=left>
<form action="' . getLink('account/email') . '" method="post"><input type="hidden" name="changeemailsave" value=1 >
<form action="' . getLink('account/email') . '" method="post">
' . csrf() . '
<input type="hidden" name="changeemailsave" value=1 >
<INPUT TYPE=image NAME="I Agree" SRC="' . $template_path . '/images/global/buttons/sbutton_iagree.gif" BORDER=0 WIDTH=120 HEIGHT=17>
</form>
</td>
<td align=left>
<form action="' . getLink('account/email') . '" method="post">
' . csrf() . '
<input type="hidden" name="emailchangecancel" value=1 >
' . $twig->render('buttons.cancel.html.twig') . '
</form>
</td>
<td align=right>
<form action="?subtopic=accountmanagement" method="post" >
' . csrf() . '
' . $twig->render('buttons.back.html.twig') . '
</form>
</td>
@@ -125,6 +129,7 @@ else
<td>
<table border="0" cellspacing="0" cellpadding="0" >
<form action="' .getLink('account/email') . '" method="post" >
' . csrf() . '
<tr>
<td style="border:0px;" >
<input type="hidden" name="emailchangecancel" value="1" >
@@ -137,6 +142,7 @@ else
<td>
<table border="0" cellspacing="0" cellpadding="0" >
<form action="' . getLink('account/manage') . '" method="post" >
' . csrf() . '
<tr>
<td style="border:0px;" >
' . $twig->render('buttons.back.html.twig') . '

View File

@@ -8,6 +8,9 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Account;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Change Info';
@@ -17,9 +20,11 @@ if(!$logged) {
return;
}
if($config['account_country'])
if(setting('core.account_country'))
require SYSTEM . 'countries.conf.php';
$account = Account::find($account_logged->getId());
$show_form = true;
$new_rlname = isset($_POST['info_rlname']) ? htmlspecialchars(stripslashes($_POST['info_rlname'])) : NULL;
$new_location = isset($_POST['info_location']) ? htmlspecialchars(stripslashes($_POST['info_location'])) : NULL;
@@ -30,9 +35,10 @@ if(isset($_POST['changeinfosave']) && $_POST['changeinfosave'] == 1) {
if(empty($errors)) {
//save data from form
$account_logged->setCustomField("rlname", $new_rlname);
$account_logged->setCustomField("location", $new_location);
$account_logged->setCustomField("country", $new_country);
$account->rlname = $new_rlname;
$account->location = $new_location;
$account->country = $new_country;
$account->save();
$account_logged->logAction('Changed Real Name to <b>' . $new_rlname . '</b>, Location to <b>' . $new_location . '</b> and Country to <b>' . $config['countries'][$new_country] . '</b>.');
$twig->display('success.html.twig', array(
'title' => 'Public Information Changed',
@@ -47,10 +53,10 @@ if(isset($_POST['changeinfosave']) && $_POST['changeinfosave'] == 1) {
//show form
if($show_form) {
$account_rlname = $account_logged->getCustomField("rlname");
$account_location = $account_logged->getCustomField("location");
if ($config['account_country']) {
$account_country = $account_logged->getCustomField("country");
$account_rlname = $account->rlname;
$account_location = $account->location;
if (setting('core.account_country')) {
$account_country = $account->country;
$countries = array();
foreach (array('pl', 'se', 'br', 'us', 'gb',) as $country)

View File

@@ -19,17 +19,17 @@ if(!$logged) {
$player_id = isset($_POST['player_id']) ? (int)$_POST['player_id'] : NULL;
$name = isset($_POST['name']) ? stripslashes(ucwords(strtolower($_POST['name']))) : NULL;
if((!$config['account_change_character_name']))
if((!setting('core.account_change_character_name')))
echo 'Changing character name for premium points is disabled on this server.';
else
{
$points = $account_logged->getCustomField('premium_points');
$points = $account_logged->getCustomField(setting('core.donate_column'));
if(isset($_POST['changenamesave']) && $_POST['changenamesave'] == 1) {
if($points < $config['account_change_character_name_points'])
$errors[] = 'You need ' . $config['account_change_character_name_points'] . ' premium points to change name. You have <b>'.$points.'<b> premium points.';
if($points < setting('core.account_change_character_name_price'))
$errors[] = 'You need ' . setting('core.account_change_character_name_price') . ' premium points to change name. You have <b>'.$points.'<b> premium points.';
$minLength = config('character_name_min_length');
$maxLength = config('character_name_max_length');
$minLength = setting('core.create_character_name_min_length');
$maxLength = setting('core.create_character_name_max_length');
if(empty($errors) && empty($name))
$errors[] = 'Please enter a new name for your character!';
@@ -86,7 +86,7 @@ else
}
}
$account_logged->setCustomField("premium_points", $points - $config['account_change_character_name_points']);
$account_logged->setCustomField(setting('core.donate_column'), $points - setting('core.account_change_character_name_price'));
$account_logged->logAction('Changed name from <b>' . $old_name . '</b> to <b>' . $player->getName() . '</b>.');
$twig->display('success.html.twig', array(
'title' => 'Character Name Changed',

View File

@@ -18,18 +18,18 @@ if(!$logged) {
}
$new_password = $_POST['newpassword'] ?? NULL;
$new_password2 = $_POST['newpassword2'] ?? NULL;
$new_password_confirm = $_POST['newpassword_confirm'] ?? NULL;
$old_password = $_POST['oldpassword'] ?? NULL;
if(empty($new_password) && empty($new_password2) && empty($old_password)) {
if(empty($new_password) && empty($new_password_confirm) && empty($old_password)) {
$twig->display('account.change_password.html.twig');
}
else
{
if(empty($new_password) || empty($new_password2) || empty($old_password)){
if(empty($new_password) || empty($new_password_confirm) || empty($old_password)){
$errors[] = 'Please fill in form.';
}
$password_strlen = strlen($new_password);
if($new_password != $new_password2) {
if($new_password != $new_password_confirm) {
$errors[] = 'The new passwords do not match!';
}
@@ -69,7 +69,7 @@ else
$account_logged->logAction('Account password changed.');
$message = '';
if($config['mail_enabled'] && $config['send_mail_when_change_password']) {
if(setting('core.mail_enabled') && setting('core.mail_send_when_change_password')) {
$mailBody = $twig->render('mail.password_changed.html.twig', array(
'new_password' => $org_pass,
'ip' => get_browser_real_ip(),

View File

@@ -20,14 +20,14 @@ if(!$logged) {
$sex_changed = false;
$player_id = isset($_POST['player_id']) ? (int)$_POST['player_id'] : NULL;
$new_sex = isset($_POST['new_sex']) ? (int)$_POST['new_sex'] : NULL;
if((!$config['account_change_character_sex']))
if((!setting('core.account_change_character_sex')))
echo 'You cant change your character sex';
else
{
$points = $account_logged->getCustomField('premium_points');
$points = $account_logged->getCustomField(setting('core.donate_column'));
if(isset($_POST['changesexsave']) && $_POST['changesexsave'] == 1) {
if($points < $config['account_change_character_sex_points'])
$errors[] = 'You need ' . $config['account_change_character_sex_points'] . ' premium points to change sex. You have <b>'.$points.'</b> premium points.';
if($points < setting('core.account_change_character_sex_price'))
$errors[] = 'You need ' . setting('core.account_change_character_sex_price') . ' premium points to change sex. You have <b>'.$points.'</b> premium points.';
if(empty($errors) && !isset($config['genders'][$new_sex])) {
$errors[] = 'This sex is invalid.';
@@ -66,7 +66,7 @@ else
$new_sex_str = $config['genders'][$new_sex];
$player->save();
$account_logged->setCustomField("premium_points", $points - $config['account_change_character_name_points']);
$account_logged->setCustomField(setting('core.donate_column'), $points - setting('core.account_change_character_name_price'));
$account_logged->logAction('Changed sex on character <b>' . $player->getName() . '</b> from <b>' . $old_sex_str . '</b> to <b>' . $new_sex_str . '</b>.');
$twig->display('success.html.twig', array(
'title' => 'Character Sex Changed',

View File

@@ -7,6 +7,9 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Account;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Confirm Email';
@@ -17,14 +20,12 @@ if(empty($hash)) {
return;
}
$res = $db->query('SELECT `email_hash` FROM `accounts` WHERE `email_hash` = ' . $db->quote($hash));
if(!$res->rowCount()) {
if(!Account::where('email_hash', $hash)->exists()) {
note("Your email couldn't be verified. Please contact staff to do it manually.");
}
else
{
$query = $db->query('SELECT id FROM accounts WHERE email_hash = ' . $db->quote($hash) . ' AND email_verified = 0');
if ($query->rowCount() == 1) {
if (Account::where('email_hash', $hash)->where('email_verified', 0)->exists()) {
$query = $query->fetch(PDO::FETCH_ASSOC);
$account = new OTS_Account();
$account->load($query['id']);
@@ -33,7 +34,7 @@ else
}
}
$db->update('accounts', array('email_verified' => '1'), array('email_hash' => $hash));
Account::where('email_hash', $hash)->update('email_verified', 1);
success('You have now verified your e-mail, this will increase the security of your account. Thank you for doing this.');
}
?>

View File

@@ -11,7 +11,7 @@
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Create Account';
if($config['account_country'])
if (setting('core.account_country'))
require SYSTEM . 'countries.conf.php';
if($logged)
@@ -20,7 +20,7 @@ if($logged)
return;
}
if(config('account_create_character_create')) {
if(setting('core.account_create_character_create')) {
require_once LIBS . 'CreateCharacter.php';
$createCharacter = new CreateCharacter();
}
@@ -50,7 +50,7 @@ if($save)
$email = $_POST['email'];
$password = $_POST['password'];
$password2 = $_POST['password2'];
$password_confirm = $_POST['password_confirm'];
// account
if(!config('account_login_by_email')) {
@@ -68,7 +68,7 @@ if($save)
// country
$country = '';
if($config['account_country'])
if (setting('core.account_country'))
{
$country = $_POST['country'];
if(!isset($country))
@@ -81,7 +81,7 @@ if($save)
if(empty($password)) {
$errors['password'] = 'Please enter the password for your new account.';
}
elseif($password != $password2) {
elseif($password != $password_confirm) {
$errors['password'] = 'Passwords are not the same.';
}
else if(!Validator::password($password)) {
@@ -93,7 +93,7 @@ if($save)
$errors['password'] = 'Password may not be the same as account name.';
}
if($config['account_mail_unique'])
if(setting('core.account_mail_unique'))
{
$test_email_account = new OTS_Account();
$test_email_account->findByEMail($email);
@@ -115,7 +115,7 @@ if($save)
}
if($account_db->isLoaded()) {
if (config('account_login_by_email') && !config('account_mail_unique')) {
if (config('account_login_by_email') && !setting('core.account_mail_unique')) {
$errors['account'] = 'Account with this email already exist.';
}
else if (!config('account_login_by_email')) {
@@ -134,7 +134,7 @@ if($save)
'email' => $email,
'country' => $country,
'password' => $password,
'password2' => $password2,
'password_confirm' => $password_confirm,
'accept_rules' => isset($_POST['accept_rules']) ? $_POST['accept_rules'] === 'true' : false,
);
@@ -150,7 +150,7 @@ if($save)
return;
}
if(config('account_create_character_create')) {
if(setting('core.account_create_character_create')) {
$character_name = isset($_POST['name']) ? stripslashes(ucwords(strtolower($_POST['name']))) : null;
$character_sex = isset($_POST['sex']) ? (int)$_POST['sex'] : null;
$character_vocation = isset($_POST['vocation']) ? (int)$_POST['vocation'] : null;
@@ -191,27 +191,28 @@ if($save)
$new_account->setCustomField('created', time());
$new_account->logAction('Account created.');
if($config['account_country']) {
if(setting('core.account_country')) {
$new_account->setCustomField('country', $country);
}
if($config['account_premium_days'] && $config['account_premium_days'] > 0) {
$settingAccountPremiumDays = setting('core.account_premium_days');
if($settingAccountPremiumDays && $settingAccountPremiumDays > 0) {
if($db->hasColumn('accounts', 'premend')) { // othire
$new_account->setCustomField('premend', time() + $config['account_premium_days'] * 86400);
$new_account->setCustomField('premend', time() + $settingAccountPremiumDays * 86400);
}
else { // rest
if ($db->hasColumn('accounts', 'premium_ends_at')) { // TFS 1.4+
$new_account->setCustomField('premium_ends_at', time() + $config['account_premium_days'] * (60 * 60 * 24));
$new_account->setCustomField('premium_ends_at', time() + $settingAccountPremiumDays * (60 * 60 * 24));
}
else {
$new_account->setCustomField('premdays', $config['account_premium_days']);
$new_account->setCustomField('premdays', $settingAccountPremiumDays);
$new_account->setCustomField('lastday', time());
}
}
}
if($config['account_premium_points']) {
$new_account->setCustomField('premium_points', $config['account_premium_points']);
if(setting('core.account_premium_points') && setting('core.account_premium_points') > 0) {
$new_account->setCustomField('premium_points', setting('core.account_premium_points'));
}
$tmp_account = $email;
@@ -219,7 +220,7 @@ if($save)
$tmp_account = (USE_ACCOUNT_NAME ? $account_name : $account_id);
}
if($config['mail_enabled'] && $config['account_mail_verify'])
if(setting('core.mail_enabled') && setting('core.account_mail_verify'))
{
$hash = md5(generateRandomString(16, true, true) . $email);
$new_account->setCustomField('email_hash', $hash);
@@ -238,7 +239,7 @@ if($save)
'description' => 'Your account ' . $account_type . ' is <b>' . $tmp_account . '</b><br/>You will need the account ' . $account_type . ' and your password to play on ' . configLua('serverName') . '.
Please keep your account ' . $account_type . ' and password in a safe place and
never give your account ' . $account_type . ' or password to anybody.',
'custom_buttons' => config('account_create_character_create') ? '' : null
'custom_buttons' => setting('core.account_create_character_create') ? '' : null
));
}
else
@@ -249,7 +250,7 @@ if($save)
}
else
{
if(config('account_create_character_create')) {
if(setting('core.account_create_character_create')) {
// character creation
$character_created = $createCharacter->doCreate($character_name, $character_sex, $character_vocation, $character_town, $new_account, $errors);
if (!$character_created) {
@@ -258,7 +259,7 @@ if($save)
}
}
if(config('account_create_auto_login')) {
if(setting('core.account_create_auto_login')) {
if ($hasBeenCreatedByEMail) {
$_POST['account_login'] = $email;
}
@@ -266,14 +267,14 @@ if($save)
$_POST['account_login'] = USE_ACCOUNT_NAME ? $account_name : $account_id;
}
$_POST['password_login'] = $password2;
$_POST['password_login'] = $password_confirm;
require PAGES . 'account/login.php';
header('Location: ' . getLink('account/manage'));
}
echo 'Your account';
if(config('account_create_character_create')) {
if(setting('core.account_create_character_create')) {
echo ' and character have';
}
else {
@@ -281,7 +282,7 @@ if($save)
}
echo ' been created.';
if(!config('account_create_character_create')) {
if(!setting('core.account_create_character_create')) {
echo ' Now you can login and create your first character.';
}
@@ -291,10 +292,10 @@ if($save)
'description' => 'Your account ' . $account_type . ' is <b>' . $tmp_account . '</b><br/>You will need the account ' . $account_type . ' and your password to play on ' . configLua('serverName') . '.
Please keep your account ' . $account_type . ' and password in a safe place and
never give your account ' . $account_type . ' or password to anybody.',
'custom_buttons' => config('account_create_character_create') ? '' : null
'custom_buttons' => setting('core.account_create_character_create') ? '' : null
));
if($config['mail_enabled'] && $config['account_welcome_mail'])
if(setting('core.mail_enabled') && setting('core.account_welcome_mail'))
{
$mailBody = $twig->render('account.welcome_mail.html.twig', array(
'account' => $tmp_account
@@ -313,7 +314,7 @@ if($save)
}
$country_recognized = null;
if($config['account_country_recognize']) {
if(setting('core.account_country_recognize')) {
$country_session = getSession('country');
if($country_session !== false) { // get from session
$country_recognized = $country_session;
@@ -330,7 +331,7 @@ if($config['account_country_recognize']) {
if(!empty($errors))
$twig->display('error_box.html.twig', array('errors' => $errors));
if($config['account_country']) {
if (setting('core.account_country')) {
$countries = array();
foreach (array('pl', 'se', 'br', 'us', 'gb') as $c)
$countries[$c] = $config['countries'][$c];
@@ -353,7 +354,7 @@ $params = array(
'save' => $save
);
if($save && config('account_create_character_create')) {
if($save && setting('core.account_create_character_create')) {
$params = array_merge($params, array(
'name' => $character_name,
'sex' => $character_sex,

View File

@@ -11,7 +11,7 @@
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Lost Account Interface';
if(!$config['mail_enabled'])
if(!setting('core.mail_enabled'))
{
echo '<b>Account maker is not configured to send e-mails, you can\'t use Lost Account Interface. Contact with admin to get help.</b>';
return;
@@ -59,7 +59,7 @@ elseif($action == 'step1' && $action_type == 'email')
$minutesleft = floor($insec / 60);
$secondsleft = $insec - ($minutesleft * 60);
$timeleft = $minutesleft.' minutes '.$secondsleft.' seconds';
echo 'Account of selected character (<b>'.$nick.'</b>) received e-mail in last '.ceil($config['email_lai_sec_interval'] / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.';
echo 'Account of selected character (<b>'.$nick.'</b>) received e-mail in last '.ceil(setting('core.mail_lost_account_interval') / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.';
}
}
else
@@ -104,7 +104,7 @@ elseif($action == 'sendcode')
if(_mail($account_mail, $config['lua']['serverName'].' - Recover your account', $mailBody))
{
$account->setCustomField('email_code', $newcode);
$account->setCustomField('email_next', (time() + $config['email_lai_sec_interval']));
$account->setCustomField('email_next', (time() + setting('core.mail_lost_account_interval')));
echo '<br />Details about steps required to recover your account has been sent to <b>' . $account_mail . '</b>. You should receive this email within 15 minutes. Please check your inbox/spam directory.';
}
else
@@ -122,7 +122,7 @@ elseif($action == 'sendcode')
$minutesleft = floor($insec / 60);
$secondsleft = $insec - ($minutesleft * 60);
$timeleft = $minutesleft.' minutes '.$secondsleft.' seconds';
echo 'Account of selected character (<b>'.$nick.'</b>) received e-mail in last '.ceil($config['email_lai_sec_interval'] / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.';
echo 'Account of selected character (<b>'.$nick.'</b>) received e-mail in last '.ceil(setting('core.mail_lost_account_interval') / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.';
}
}
else

View File

@@ -35,7 +35,7 @@ if(empty($recovery_key))
$account_registered = '<b><span style="color: red">No</span></b>';
else
{
if($config['generate_new_reckey'] && $config['mail_enabled'])
if(setting('core.account_generate_new_reckey') && setting('core.mail_enabled'))
$account_registered = '<b><span style="color: green">Yes ( <a href="' . getLink('account/register/new') . '"> Buy new Recovery Key </a> )</span></b>';
else
$account_registered = '<b><span style="color: green">Yes</span></b>';

View File

@@ -31,7 +31,7 @@ if(isset($_POST['registeraccountsave']) && $_POST['registeraccountsave'] == "1")
$account_logged->logAction('Generated recovery key.');
$message = '';
if($config['mail_enabled'] && $config['send_mail_when_generate_reckey'])
if(setting('core.mail_enabled') && setting('core.mail_send_when_generate_reckey'))
{
$mailBody = $twig->render('mail.account.register.html.twig', array(
'recovery_key' => $new_rec_key

View File

@@ -21,18 +21,18 @@ if(isset($_POST['reg_password']))
$reg_password = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $_POST['reg_password']);
$reckey = $account_logged->getCustomField('key');
if((!$config['generate_new_reckey'] || !$config['mail_enabled']) || empty($reckey)) {
if((!setting('core.account_generate_new_reckey') || !setting('core.mail_enabled')) || empty($reckey)) {
$errors[] = 'You cant get new recovery key.';
$twig->display('error_box.html.twig', array('errors' => $errors));
}
else
{
$points = $account_logged->getCustomField('premium_points');
$points = $account_logged->getCustomField(setting('core.donate_column'));
if(isset($_POST['registeraccountsave']) && $_POST['registeraccountsave'] == '1')
{
if($reg_password == $account_logged->getPassword())
{
if($points >= $config['generate_new_reckey_price'])
if($points >= setting('core.account_generate_new_reckey_price'))
{
$show_form = false;
$new_rec_key = generateRandomString(10, false, true, true);
@@ -43,10 +43,10 @@ else
if(_mail($account_logged->getEMail(), $config['lua']['serverName']." - new recovery key", $mailBody))
{
$account_logged->setCustomField("key", $new_rec_key);
$account_logged->setCustomField("premium_points", $account_logged->getCustomField("premium_points") - $config['generate_new_reckey_price']);
$account_logged->logAction('Generated new recovery key for ' . $config['generate_new_reckey_price'] . ' premium points.');
$message = '<br />Your recovery key were send on email address <b>'.$account_logged->getEMail().'</b> for '.$config['generate_new_reckey_price'].' premium points.';
$account_logged->setCustomField('key', $new_rec_key);
$account_logged->setCustomField(setting('core.donate_column'), $account_logged->getCustomField(setting('core.donate_column')) - setting('core.account_generate_new_reckey_price'));
$account_logged->logAction('Generated new recovery key for ' . setting('core.account_generate_new_reckey_price') . ' premium points.');
$message = '<br />Your recovery key were send on email address <b>'.$account_logged->getEMail().'</b> for '.setting('core.account_generate_new_reckey_price').' premium points.';
}
else
$message = '<br /><p class="error">An error occurred while sending email ( <b>'.$account_logged->getEMail().'</b> ) with recovery key! Recovery key not changed. Try again later. For Admin: More info can be found in system/logs/mailer-error.log</p>';
@@ -57,7 +57,7 @@ else
));
}
else
$errors[] = 'You need '.$config['generate_new_reckey_price'].' premium points to generate new recovery key. You have <b>'.$points.'<b> premium points.';
$errors[] = 'You need ' . setting('core.account_generate_new_reckey_price') . ' premium points to generate new recovery key. You have <b>'.$points.'<b> premium points.';
}
else
$errors[] = 'Wrong password to account.';

View File

@@ -11,8 +11,8 @@
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Bans list';
$configBansPerPage = config('bans_per_page');
$_page = isset($_GET['page']) ? $_GET['page'] : 1;
$configBansPerPage = setting('core.bans_per_page');
$_page = $_GET['page'] ?? 1;
if(!is_numeric($_page) || $_page < 1 || $_page > PHP_INT_MAX) {
$_page = 1;

View File

@@ -8,6 +8,9 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\BugTracker;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Bug tracker';
@@ -29,10 +32,10 @@ $showed = $post = $reply = false;
if(admin() and isset($_REQUEST['control']) && $_REQUEST['control'] == "true")
{
if(empty($_REQUEST['id']) and empty($_REQUEST['acc']) or !is_numeric($_REQUEST['acc']) or !is_numeric($_REQUEST['id']) )
$bug[1] = $db->query('SELECT * FROM '.$db->tableName(TABLE_PREFIX . 'bugtracker').' where `type` = 1 order by `uid` desc');
$bug[1] = BugTracker::where('type', 1)->orderByDesc('uid')->get()->toArray();
if(!empty($_REQUEST['id']) and is_numeric($_REQUEST['id']) and !empty($_REQUEST['acc']) and is_numeric($_REQUEST['acc']))
$bug[2] = $db->query('SELECT * FROM '.$db->tableName(TABLE_PREFIX . 'bugtracker').' where `account` = '.$_REQUEST['acc'].' and `id` = '.$_REQUEST['id'].' and `type` = 1')->fetch();
$bug[2] = BugTracker::where('type', 1)->where('account', $_REQUEST['acc'])->where('id', $_REQUEST['id'])->get()->toArray();
if(!empty($_REQUEST['id']) and is_numeric($_REQUEST['id']) and !empty($_REQUEST['acc']) and is_numeric($_REQUEST['acc']))
{
@@ -67,7 +70,7 @@ $showed = $post = $reply = false;
echo '<TR BGCOLOR="'.$light.'"><td colspan=2>'.nl2br($bug[2]['text']).'</td></tr>';
echo '</TABLE>';
$answers = $db->query('SELECT * FROM '.$db->tableName(TABLE_PREFIX . 'bugtracker').' where `account` = '.$_REQUEST['acc'].' and `id` = '.$_REQUEST['id'].' and `type` = 2 order by `reply`');
$answers = BugTracker::where('account', $_REQUEST['acc'])->where('id', $_REQUEST['id'])->where('type', 2)->orderBy('reply')->get()->toArray();
foreach($answers as $answer)
{
if($answer['who'] == 1)
@@ -88,9 +91,9 @@ $showed = $post = $reply = false;
{
if($bug[2]['status'] != 3)
{
$reply = $db->query('SELECT MAX(reply) FROM `' . TABLE_PREFIX . 'bugtracker` where `account` = '.$_REQUEST['acc'].' and `id` = '.$_REQUEST['id'].' and `type` = 2')->fetch();
$reply = $reply[0] + 1;
$iswho = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'bugtracker` where `account` = '.$_REQUEST['acc'].' and `id` = '.$_REQUEST['id'].' and `type` = 2 order by `reply` desc limit 1')->fetch();
$reply = BugTracker::where('account', $_REQUEST['acc'])->where('id', $_REQUEST['id'])->where('type', 2)->max('reply');
$reply = $reply + 1;
$iswho = BugTracker::where('account', $_REQUEST['acc'])->where('id', $_REQUEST['id'])->where('type', 2)->orderByDesc('reply')->first()->toArray();
if(isset($_POST['finish']))
{
@@ -109,8 +112,17 @@ $showed = $post = $reply = false;
else
{
$type = 2;
$INSERT = $db->query('INSERT INTO `' . TABLE_PREFIX . 'bugtracker` (`account`,`id`,`text`,`reply`,`type`, `who`) VALUES ('.$db->quote($_REQUEST['acc']).','.$db->quote($_REQUEST['id']).','.$db->quote($_POST['text']).','.$db->quote($reply).','.$db->quote($type).','.$db->quote(1).')');
$UPDATE = $db->query('UPDATE `' . TABLE_PREFIX . 'bugtracker` SET `status` = '.$_POST['status'].' where `account` = '.$_REQUEST['acc'].' and `id` = '.$_REQUEST['id'].'');
$INSERT = BugTracker::create([
'account' => $_REQUEST['aac'],
'id' => $_REQUEST['id'],
'text' => $_POST['text'],
'reply' => $reply,
'type' => $type,
'who' => 1,
]);
$UPDATE = Bugtracker::where('id', $_REQUEST['id'])->where('account', $_REQUEST['acc'])->update([
'status' => $_POST['status']
]);
header('Location: ?subtopic=bugtracker&control=true&id='.$_REQUEST['id'].'&acc='.$_REQUEST['acc'].'');
}
}
@@ -159,10 +171,10 @@ $showed = $post = $reply = false;
$id = addslashes(htmlspecialchars(trim($_REQUEST['id'])));
if(empty($_REQUEST['id']))
$bug[1] = $db->query('SELECT * FROM '.$db->tableName(TABLE_PREFIX . 'bugtracker').' where `account` = '.$account_logged->getId().' and `type` = 1 order by `id` desc');
$bug[1] = BugTracker::where('account', $account_logged->getId())->where('type', 1)->orderBy('id')->get()->toArray();
if(!empty($_REQUEST['id']) and is_numeric($_REQUEST['id']))
$bug[2] = $db->query('SELECT * FROM '.$db->tableName(TABLE_PREFIX . 'bugtracker').' where `account` = '.$account_logged->getId().' and `id` = '.$id.' and `type` = 1')->fetch();
$bug[2] = BugTracker::where('account', $account_logged->getId())->where('type', 1)->where('id', $id)->get()->toArray();
else
$bug[2] = NULL;
@@ -186,7 +198,7 @@ $showed = $post = $reply = false;
echo '<TR BGCOLOR="'.$dark.'"><td colspan=2>'.nl2br($bug[2]['text']).'</td></tr>';
echo '</TABLE>';
$answers = $db->query('SELECT * FROM '.$db->tableName('myaac_bugtracker').' where `account` = '.$account_logged->getId().' and `id` = '.$id.' and `type` = 2 order by `reply`');
$answers = Bugtracker::where('account', $account_logged->getId())->where('id', $id)->where('type', 2)->orderBy('reply')->get()->toArray();
foreach($answers as $answer)
{
if($answer['who'] == 1)
@@ -207,9 +219,9 @@ $showed = $post = $reply = false;
{
if($bug[2]['status'] != 3)
{
$reply = $db->query('SELECT MAX(reply) FROM `' . TABLE_PREFIX . 'bugtracker` where `account` = '.$acc.' and `id` = '.$id.' and `type` = 2')->fetch();
$reply = $reply[0] + 1;
$iswho = $db->query('SELECT * FROM `myaac_bugtracker` where `account` = '.$acc.' and `id` = '.$id.' and `type` = 2 order by `reply` desc limit 1')->fetch();
$reply = BugTracker::where('account', $aac)->where('id', $id)->where('type', 2)->max('reply');
$reply = $reply + 1;
$iswho = BugTracker::where('account', $acc)->where('id', $id)->where('type', 2)->orderByDesc('reply')->first()->toArray();
if(isset($_POST['finish']))
{
@@ -228,8 +240,16 @@ $showed = $post = $reply = false;
else
{
$type = 2;
$INSERT = $db->query('INSERT INTO `myaac_bugtracker` (`account`,`id`,`text`,`reply`,`type`) VALUES ('.$db->quote($acc).','.$db->quote($id).','.$db->quote($_POST['text']).','.$db->quote($reply).','.$db->quote($type).')');
$UPDATE = $db->query('UPDATE `myaac_bugtracker` SET `status` = 1 where `account` = '.$acc.' and `id` = '.$id.'');
$INSERT = BugTracker::create([
'account' => $acc,
'id' => $id,
'text' => $_POST['text'],
'reply' => $reply,
'type' => $type
]);
$UPDATE = BugTracker::where('id', $id)->where('account', $acc)->update([
'status' => 1
]);
header('Location: ?subtopic=bugtracker&id='.$id.'');
}
}
@@ -289,9 +309,9 @@ $showed = $post = $reply = false;
}
elseif(isset($_REQUEST['add']) && $_REQUEST['add'] == TRUE)
{
$thread = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'bugtracker` where `account` = '.$acc.' and `type` = 1 order by `id` desc')->fetch();
$id_next = $db->query('SELECT MAX(id) FROM `' . TABLE_PREFIX . 'bugtracker` where `account` = '.$acc.' and `type` = 1')->fetch();
$id_next = $id_next[0] + 1;
$thread = BugTracker::where('account', $acc)->where('type', 1)->orderByDesc('id')->get()->toArray();
$id_next = BugTracker::where('account', $acc)->where('type', 1)->max('id');
$id_next = $id_next + 1;
if(empty($thread))
$thread['status'] = 3;
@@ -318,7 +338,16 @@ $showed = $post = $reply = false;
{
$type = 1;
$status = 1;
$INSERT = $db->query('INSERT INTO `' . TABLE_PREFIX . 'bugtracker` (`account`,`id`,`text`,`type`,`subject`, `reply`,`status`,`tag`) VALUES ('.$db->quote($acc).','.$db->quote($id_next).','.$db->quote($_POST['text']).','.$db->quote($type).','.$db->quote($_POST['subject']).', 0,'.$db->quote($status).','.$db->quote($_POST['tags']).')');
$INSERT = BugTracker::create([
'account' => $acc,
'id' => $id_next,
'text' => $_POST['text'],
'type' => $type,
'subject' => $_POST['subject'],
'reply' => 0,
'status' => $status,
'tag' => $_POST['tags']
]);
header('Location: ?subtopic=bugtracker&id='.$id_next.'');
}

View File

@@ -10,6 +10,8 @@
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Changelog';
use MyAAC\Models\Changelog;
$_page = isset($_GET['page']) ? (int)$_GET['page'] : 0;
$limit = 30;
$offset = $_page * $limit;
@@ -17,7 +19,7 @@ $next_page = false;
$canEdit = hasFlag(FLAG_CONTENT_NEWS) || superAdmin();
$changelogs = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'changelog` ' . ($canEdit ? '' : 'WHERE `hidden` = 0').' ORDER BY `id` DESC LIMIT ' . ($limit + 1) . ' OFFSET ' . $offset)->fetchAll();
$changelogs = Changelog::isPublic()->orderByDesc('id')->limit($limit + 1)->offset($offset)->get()->toArray();
$i = 0;
foreach($changelogs as $key => &$log)

View File

@@ -11,8 +11,6 @@
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Characters';
require_once SYSTEM . 'item.php';
$groups = new OTS_Groups_List();
function generate_search_form($autofocus = false)
{
@@ -79,10 +77,10 @@ if($player->isLoaded() && !$player->isDeleted())
$rows = 0;
if($config['characters']['outfit'])
$outfit = $config['outfit_images_url'] . '?id=' . $player->getLookType() . ($db->hasColumn('players', 'lookaddons') ? '&addons=' . $player->getLookAddons() : '') . '&head=' . $player->getLookHead() . '&body=' . $player->getLookBody() . '&legs=' . $player->getLookLegs() . '&feet=' . $player->getLookFeet();
$outfit = setting('core.outfit_images_url') . '?id=' . $player->getLookType() . ($db->hasColumn('players', 'lookaddons') ? '&addons=' . $player->getLookAddons() : '') . '&head=' . $player->getLookHead() . '&body=' . $player->getLookBody() . '&legs=' . $player->getLookLegs() . '&feet=' . $player->getLookFeet();
$flag = '';
if($config['account_country']) {
if(setting('core.account_country')) {
$flag = getFlagImage($account->getCountry());
}
@@ -340,8 +338,8 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil
}
// signature
if($config['signature_enabled']) {
$signature_url = BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . urlencode($player->getName()) . '.png';
if(setting('core.signature_enabled')) {
$signature_url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . urlencode($player->getName()) . '.png';
}
$hidden = $player->isHidden();
@@ -396,7 +394,7 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil
'rank' => isset($guild_name) ? $rank_of_player->getName() : null,
'link' => isset($guild_name) ? getGuildLink($guild_name) : null
),
'comment' => !empty($comment) ? wordwrap(nl2br($comment), 60, "<br/>", true) : null,
'comment' => !empty($comment) ? nl2br($comment) : null,
'skills' => isset($skills) ? $skills : null,
'quests_enabled' => $quests_enabled,
'quests' => isset($quests) ? $quests : null,
@@ -425,7 +423,7 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil
if($db->hasColumn('players', 'deletion'))
$deleted = 'deletion';
$query = $db->query('SELECT `name`, `level`, `vocation`' . $promotion . ' FROM `players` WHERE `name` LIKE ' . $db->quote('%' . $name . '%') . ' AND ' . $deleted . ' != 1 LIMIT ' . (int)config('characters_search_limit') . ';');
$query = $db->query('SELECT `name`, `level`, `vocation`' . $promotion . ' FROM `players` WHERE `name` LIKE ' . $db->quote('%' . $name . '%') . ' AND ' . $deleted . ' != 1 LIMIT ' . (int)setting('core.characters_search_limit') . ';');
if($query->rowCount() > 0) {
echo 'Did you mean:<ul>';
foreach($query as $player) {

View File

@@ -9,13 +9,18 @@
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Monster;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Creatures';
if (empty($_REQUEST['name'])) {
// display list of monsters
$preview = config('creatures_images_preview');
$creatures = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'monsters` WHERE `hidden` != 1 '.(empty($_REQUEST['boss']) ? '': 'AND `rewardboss` = 1').' ORDER BY name asc')->fetchAll();
$preview = setting('core.monsters_images_preview');
$creatures = Monster::where('hidden', '!=', 1)->when(!empty($_REQUEST['boss']), function ($query) {
$query->where('rewardboss', 1);
})->get()->toArray();
if ($preview) {
foreach($creatures as $key => &$creature)
@@ -34,9 +39,7 @@ if (empty($_REQUEST['name'])) {
// display monster
$creature_name = urldecode(stripslashes(ucwords(strtolower($_REQUEST['name']))));
$prep = $db->prepare('SELECT * FROM `' . TABLE_PREFIX . 'monsters` WHERE `hidden` != 1 AND `name` = ? LIMIT 1;');
$prep->execute([$creature_name]);
$creature = $prep->fetch();
$creature = Monster::where('hidden', '!=', 1)->where('name', $creature_name)->first()->toArray();
if (isset($creature['name'])) {
function sort_by_chance($a, $b)
@@ -62,7 +65,7 @@ if (isset($creature['name'])) {
$item['name'] = getItemNameById($item['id']);
$item['rarity_chance'] = round($item['chance'] / 1000, 2);
$item['rarity'] = getItemRarity($item['chance']);
$item['tooltip'] = ucfirst($item['name']) . '<br/>Chance: ' . $item['rarity'] . (config('creatures_loot_percentage') ? ' ('. $item['rarity_chance'] .'%)' : '') . '<br/>Max count: ' . $item['count'];
$item['tooltip'] = ucfirst($item['name']) . '<br/>Chance: ' . $item['rarity'] . (setting('core.monsters_loot_percentage') ? ' ('. $item['rarity_chance'] .'%)' : '') . '<br/>Max count: ' . $item['count'];
}
$creature['loot'] = isset($loot) ? $loot : null;

View File

@@ -11,9 +11,9 @@ defined('MYAAC') or die('Direct access not allowed!');
$title = 'Experience Table';
$experience = array();
$columns = $config['experiencetable_columns'];
$columns = setting('core.experience_table_columns');
for($i = 0; $i < $columns; $i++) {
for($level = $i * $config['experiencetable_rows'] + 1; $level < $i * $config['experiencetable_rows'] + ($config['experiencetable_rows'] + 1); $level++) {
for($level = $i * setting('core.experience_table_rows') + 1; $level < $i * setting('core.experience_table_rows') + (setting('core.experience_table_rows') + 1); $level++) {
$experience[$level] = OTS_Toolbox::experienceForLevel($level);
}
}

View File

@@ -7,6 +7,9 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\FAQ as ModelsFAQ;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Frequently Asked Questions';
@@ -68,21 +71,23 @@ if($canEdit)
));
}
$faqs =
$db->query('SELECT `id`, `question`, `answer`' .
($canEdit ? ', `hidden`, `ordering`' : '') .
' FROM `' . TABLE_PREFIX . 'faq`' .
(!$canEdit ? ' WHERE `hidden` != 1' : '') .
' ORDER BY `ordering`;');
$faqs = ModelsFAQ::select('id', 'question', 'answer')->when(!$canEdit, function ($query) {
$query->where('hidden', '!=', 1);
})->orderBy('ordering');
if(!$faqs->rowCount())
if ($canEdit) {
$faqs->addSelect(['hidden', 'ordering']);
}
$faqs = $faqs->get()->toArray();
if(!count($faqs))
{
?>
There are no questions added yet.
<?php
}
$last = $faqs->rowCount();
$last = count($faqs);
$twig->display('faq.html.twig', array(
'faqs' => $faqs,
'last' => $last,
@@ -93,26 +98,17 @@ class FAQ
{
static public function add($question, $answer, &$errors)
{
global $db;
if(isset($question[0]) && isset($answer[0]))
{
$query = $db->select(TABLE_PREFIX . 'faq', array('question' => $question));
if($query === false)
$row = ModelsFAQ::where('question', $question)->first();
if(!$row)
{
$query =
$db->query(
'SELECT ' . $db->fieldName('ordering') .
' FROM ' . $db->tableName(TABLE_PREFIX . 'faq') .
' ORDER BY ' . $db->fieldName('ordering') . ' DESC LIMIT 1'
);
$ordering = 0;
if($query->rowCount() > 0) {
$query = $query->fetch();
$ordering = $query['ordering'] + 1;
}
$db->insert(TABLE_PREFIX . 'faq', array('question' => $question, 'answer' => $answer, 'ordering' => $ordering));
$ordering = ModelsFAQ::max('ordering') ?? 0;
ModelsFAQ::create([
'question' => $question,
'answer' => $answer,
'ordering' => $ordering
]);
}
else
$errors[] = 'FAQ with this question already exists.';
@@ -124,22 +120,23 @@ class FAQ
}
static public function get($id) {
global $db;
return $db->select(TABLE_PREFIX . 'faq', array('id' => $id));
return ModelsFAQ::find($id)->toArray();
}
static public function update($id, $question, $answer) {
global $db;
$db->update(TABLE_PREFIX . 'faq', array('question' => $question, 'answer' => $answer), array('id' => $id));
ModelsFAQ::where('id', $id)->update([
'question' => $question,
'answer' => $answer
]);
}
static public function delete($id, &$errors)
{
global $db;
if(isset($id))
{
if(self::get($id) !== false)
$db->delete(TABLE_PREFIX . 'faq', array('id' => $id));
$row = ModelsFAQ::find($id);
if($row)
$row->delete();
else
$errors[] = 'FAQ with id ' . $id . ' does not exists.';
}
@@ -151,14 +148,17 @@ class FAQ
static public function toggleHidden($id, &$errors)
{
global $db;
if(isset($id))
{
$query = self::get($id);
if($query !== false)
$db->update(TABLE_PREFIX . 'faq', array('hidden' => ($query['hidden'] == 1 ? 0 : 1)), array('id' => $id));
else
$row = ModelsFAQ::find($id);
if ($row) {
$row->hidden = ($row->hidden == 1 ? 0 : 1);
if (!$row->save()) {
$errors[] = 'Fail during toggle hidden FAQ.';
}
} else {
$errors[] = 'FAQ with id ' . $id . ' does not exists.';
}
}
else
$errors[] = 'id not set';
@@ -169,15 +169,18 @@ class FAQ
static public function move($id, $i, &$errors)
{
global $db;
$query = self::get($id);
if($query !== false)
$row = ModelsFAQ::find($id);
if($row)
{
$ordering = $query['ordering'] + $i;
$old_record = $db->select(TABLE_PREFIX . 'faq', array('ordering' => $ordering));
if($old_record !== false)
$db->update(TABLE_PREFIX . 'faq', array('ordering' => $query['ordering']), array('ordering' => $ordering));
$ordering = $row->ordering + $i;
$old_record = ModelsFAQ::where('ordering', $ordering)->first();
if($old_record) {
$old_record->ordering = $row->ordering;
$old_record->save();
}
$db->update(TABLE_PREFIX . 'faq', array('ordering' => $ordering), array('id' => $id));
$row->ordering = $ordering;
$row->save();
}
else
$errors[] = 'FAQ with id ' . $id . ' does not exists.';

View File

@@ -10,7 +10,11 @@
*/
defined('MYAAC') or exit;
require __DIR__ . '/forum/base.php';
$ret = require __DIR__ . '/forum/base.php';
if ($ret === false) {
return;
}
require __DIR__ . '/forum/admin.php';
$errors = [];

View File

@@ -14,28 +14,32 @@ $canEdit = Forum::isModerator();
if($canEdit) {
$groups = new OTS_Groups_List();
if(!empty($action))
{
if(!empty($action)) {
if($action == 'delete_board' || $action == 'edit_board' || $action == 'hide_board' || $action == 'moveup_board' || $action == 'movedown_board')
$id = $_REQUEST['id'];
if(isset($_REQUEST['access']))
if(isset($_REQUEST['access'])) {
$access = $_REQUEST['access'];
}
if(isset($_REQUEST['guild']))
if(isset($_REQUEST['guild'])) {
$guild = $_REQUEST['guild'];
}
if(isset($_REQUEST['name']))
if(isset($_REQUEST['name'])) {
$name = $_REQUEST['name'];
}
if(isset($_REQUEST['description']))
if(isset($_REQUEST['description'])) {
$description = stripslashes($_REQUEST['description']);
}
$errors = array();
$errors = [];
if($action == 'add_board') {
if(Forum::add_board($name, $description, $access, $guild, $errors))
if(Forum::add_board($name, $description, $access, $guild, $errors)) {
$action = $name = $description = '';
}
}
else if($action == 'delete_board') {
Forum::delete_board($id, $errors);

View File

@@ -11,26 +11,26 @@
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Forum';
if(strtolower($config['forum']) != 'site')
{
if($config['forum'] != '')
{
header('Location: ' . $config['forum']);
require_once LIBS . 'forum.php';
$forumSetting = setting('core.forum');
if(strtolower($forumSetting) != 'site') {
if($forumSetting != '') {
header('Location: ' . $forumSetting);
exit;
}
echo 'Forum is disabled on this site.';
return;
return false;
}
if(!$logged)
echo 'You are not logged in. <a href="?subtopic=accountmanagement&redirect=' . BASE_URL . urlencode('?subtopic=forum') . '">Log in</a> to post on the forum.<br /><br />';
require_once LIBS . 'forum.php';
if(!$logged) {
echo 'You are not logged in. <a href="?subtopic=accountmanagement&redirect=' . BASE_URL . urlencode('?subtopic=forum') . '">Log in</a> to post on the forum.<br /><br />';
return false;
}
$sections = array();
foreach(getForumBoards() as $section)
{
foreach(getForumBoards() as $section) {
$sections[$section['id']] = array(
'id' => $section['id'],
'name' => $section['name'],

View File

@@ -10,7 +10,10 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
require __DIR__ . '/base.php';
$ret = require __DIR__ . '/base.php';
if ($ret === false) {
return;
}
if(Forum::canPost($account_logged))
{
@@ -22,17 +25,15 @@ if(Forum::canPost($account_logged))
}
$thread = $db->query("SELECT `author_guid`, `author_aid`, `first_post`, `post_topic`, `post_date`, `post_text`, `post_smile`, `post_html`, `id`, `section` FROM `" . FORUM_TABLE_PREFIX . "forum` WHERE `id` = ".$post_id." LIMIT 1")->fetch();
if(isset($thread['id']))
{
if(isset($thread['id'])) {
$first_post = $db->query("SELECT `" . FORUM_TABLE_PREFIX . "forum`.`author_guid`, `" . FORUM_TABLE_PREFIX . "forum`.`author_aid`, `" . FORUM_TABLE_PREFIX . "forum`.`first_post`, `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_smile`, `" . FORUM_TABLE_PREFIX . "forum`.`id`, `" . FORUM_TABLE_PREFIX . "forum`.`section` FROM `" . FORUM_TABLE_PREFIX . "forum` WHERE `" . FORUM_TABLE_PREFIX . "forum`.`id` = ".(int) $thread['first_post']." LIMIT 1")->fetch();
echo '<a href="' . getLink('forum') . '">Boards</a> >> <a href="' . getForumBoardLink($thread['section']) . '">'.$sections[$thread['section']]['name'].'</a> >> <a href="' . getForumThreadLink($thread['first_post']) . '">'.$first_post['post_topic'].'</a> >> <b>Edit post</b>';
if(Forum::hasAccess($thread['section'] && ($account_logged->getId() == $thread['author_aid'] || Forum::isModerator())))
{
if(Forum::hasAccess($thread['section'] && ($account_logged->getId() == $thread['author_aid'] || Forum::isModerator()))) {
$char_id = $post_topic = $text = $smile = $html = null;
$players_from_account = $db->query("SELECT `players`.`name`, `players`.`id` FROM `players` WHERE `players`.`account_id` = ".(int) $account_logged->getId())->fetchAll();
$saved = false;
if(isset($_REQUEST['save']))
{
if(isset($_REQUEST['save'])) {
$text = stripslashes(trim($_REQUEST['text']));
$char_id = (int) $_REQUEST['char_id'];
$post_topic = stripslashes(trim($_REQUEST['topic']));
@@ -40,28 +41,35 @@ if(Forum::canPost($account_logged))
$html = isset($_REQUEST['html']) ? (int)$_REQUEST['html'] : 0;
$length = strlen($post_topic);
if(($length < 1 || $length > 60) && $thread['id'] == $thread['first_post'])
if(($length < 1 || $length > 60) && $thread['id'] == $thread['first_post']) {
$errors[] = "Too short or too long topic (Length: $length letters). Minimum 1 letter, maximum 60 letters.";
}
$length = strlen($text);
if($length < 1 || $length > 15000)
if($length < 1 || $length > 15000) {
$errors[] = "Too short or too long post (Length: $length letters). Minimum 1 letter, maximum 15000 letters.";
}
if($char_id == 0)
if($char_id == 0) {
$errors[] = 'Please select a character.';
}
if(empty($post_topic) && $thread['id'] == $thread['first_post'])
if(empty($post_topic) && $thread['id'] == $thread['first_post']) {
$errors[] = 'Thread topic can\'t be empty.';
}
$player_on_account = false;
if(count($errors) == 0)
{
foreach($players_from_account as $player)
if($char_id == $player['id'])
if(count($errors) == 0) {
foreach($players_from_account as $player) {
if ($char_id == $player['id']) {
$player_on_account = true;
if(!$player_on_account)
$errors[] = 'Player with selected ID '.$char_id.' doesn\'t exist or isn\'t on your account';
}
}
if(!$player_on_account) {
$errors[] = 'Player with selected ID ' . $char_id . ' doesn\'t exist or isn\'t on your account';
}
}
if(count($errors) == 0) {
@@ -70,7 +78,7 @@ if(Forum::canPost($account_logged))
$char_id = $thread['author_guid'];
$db->query("UPDATE `" . FORUM_TABLE_PREFIX . "forum` SET `author_guid` = ".(int) $char_id.", `post_text` = ".$db->quote($text).", `post_topic` = ".$db->quote($post_topic).", `post_smile` = ".$smile.", `post_html` = ".$html.", `last_edit_aid` = ".(int) $account_logged->getId().",`edit_date` = ".time()." WHERE `id` = ".(int) $thread['id']);
$post_page = $db->query("SELECT COUNT(`" . FORUM_TABLE_PREFIX . "forum`.`id`) AS posts_count FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`post_date` <= ".$thread['post_date']." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".(int) $thread['first_post'])->fetch();
$_page = (int) ceil($post_page['posts_count'] / $config['forum_threads_per_page']) - 1;
$_page = (int) ceil($post_page['posts_count'] / setting('core.forum_threads_per_page')) - 1;
header('Location: ' . getForumThreadLink($thread['first_post'], $_page));
echo '<br />Thank you for editing post.<br /><a href="' . getForumThreadLink($thread['first_post'], $_page) . '">GO BACK TO LAST THREAD</a>';
}
@@ -83,10 +91,10 @@ if(Forum::canPost($account_logged))
$html = (int) $thread['post_html'];
}
if(!$saved)
{
if(!empty($errors))
if(!$saved) {
if(!empty($errors)) {
$twig->display('error_box.html.twig', array('errors' => $errors));
}
$twig->display('forum.edit_post.html.twig', array(
'post_id' => $post_id,
@@ -112,6 +120,6 @@ if(Forum::canPost($account_logged))
}
}
else {
$errors[] = "Your account is banned, deleted or you don't have any player with level " . $config['forum_level_required'] . " on your account. You can't post.";
$errors[] = "Your account is banned, deleted or you don't have any player with level " . setting('core.forum_level_required') . " on your account. You can't post.";
displayErrorBoxWithBackButton($errors, getLink('forum'));
}

View File

@@ -10,7 +10,10 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
require __DIR__ . '/base.php';
$ret = require __DIR__ . '/base.php';
if ($ret === false) {
return;
}
if(!Forum::isModerator()) {
echo 'You are not logged in or you are not moderator.';

View File

@@ -10,10 +10,12 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
require __DIR__ . '/base.php';
$ret = require __DIR__ . '/base.php';
if ($ret === false) {
return;
}
if(!$logged)
{
if(!$logged) {
$extra_url = '';
if(isset($_GET['thread_id'])) {
$extra_url = '&action=new_post&thread_id=' . $_GET['thread_id'];
@@ -23,8 +25,7 @@ if(!$logged)
return;
}
if(Forum::canPost($account_logged))
{
if(Forum::canPost($account_logged)) {
$players_from_account = $db->query("SELECT `players`.`name`, `players`.`id` FROM `players` WHERE `players`.`account_id` = ".(int) $account_logged->getId())->fetchAll();
$thread_id = isset($_REQUEST['thread_id']) ? (int) $_REQUEST['thread_id'] : 0;
if($thread_id == 0) {
@@ -35,43 +36,47 @@ if(Forum::canPost($account_logged))
$thread = $db->query("SELECT `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`id`, `" . FORUM_TABLE_PREFIX . "forum`.`section` FROM `" . FORUM_TABLE_PREFIX . "forum` WHERE `" . FORUM_TABLE_PREFIX . "forum`.`id` = ".(int) $thread_id." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".$thread_id." LIMIT 1")->fetch();
if(isset($thread['id']) && Forum::hasAccess($thread['section']))
{
if(isset($thread['id']) && Forum::hasAccess($thread['section'])) {
echo '<a href="' . getLink('forum') . '">Boards</a> >> <a href="' . getForumBoardLink($thread['section']) . '">'.$sections[$thread['section']]['name'].'</a> >> <a href="' . getForumThreadLink($thread_id) . '">'.$thread['post_topic'].'</a> >> <b>Post new reply</b><br /><h3>'.$thread['post_topic'].'</h3>';
$quote = isset($_REQUEST['quote']) ? (int) $_REQUEST['quote'] : NULL;
$text = isset($_REQUEST['text']) ? stripslashes(trim($_REQUEST['text'])) : NULL;
$char_id = (int) ($_REQUEST['char_id'] ?? 0);
$post_topic = isset($_REQUEST['topic']) ? stripslashes(trim($_REQUEST['topic'])) : '';
$smile = (isset($_REQUEST['smile']) ? (int)$_REQUEST['smile'] : 0);
$html = (isset($_REQUEST['html']) ? (int)$_REQUEST['html'] : 0);
$smile = (int)($_REQUEST['smile'] ?? 0);
$html = (int)($_REQUEST['html'] ?? 0);
$saved = false;
if(isset($_REQUEST['quote']))
{
$quoted_post = $db->query("SELECT `players`.`name`, `" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`id` = ".(int) $quote)->fetchAll();
if(isset($quoted_post[0]['name']))
$text = '[i]Originally posted by '.$quoted_post[0]['name'].' on '.date('d.m.y H:i:s', $quoted_post[0]['post_date']).':[/i][quote]'.$quoted_post[0]['post_text'].'[/quote]';
}
elseif(isset($_REQUEST['save']))
{
$length = strlen($text);
if($length < 1 || strlen($text) > 15000)
$errors[] = 'Too short or too long post (Length: $length letters). Minimum 1 letter, maximum 15000 letters.';
if($char_id == 0)
if(isset($_REQUEST['quote'])) {
$quoted_post = $db->query("SELECT `players`.`name`, `" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`id` = ".(int) $quote)->fetchAll();
if(isset($quoted_post[0]['name'])) {
$text = '[i]Originally posted by ' . $quoted_post[0]['name'] . ' on ' . date('d.m.y H:i:s', $quoted_post[0]['post_date']) . ':[/i][quote]' . $quoted_post[0]['post_text'] . '[/quote]';
}
}
elseif(isset($_REQUEST['save'])) {
$length = strlen($text);
if($length < 1 || strlen($text) > 15000) {
$errors[] = 'Too short or too long post (Length: $length letters). Minimum 1 letter, maximum 15000 letters.';
}
if($char_id == 0) {
$errors[] = 'Please select a character.';
}
$player_on_account = false;
if(count($errors) == 0)
{
foreach($players_from_account as $player)
if($char_id == $player['id'])
if(count($errors) == 0) {
foreach($players_from_account as $player) {
if ($char_id == $player['id']) {
$player_on_account = true;
if(!$player_on_account)
$errors[] = 'Player with selected ID '.$char_id.' doesn\'t exist or isn\'t on your account';
}
}
if(!$player_on_account) {
$errors[] = 'Player with selected ID ' . $char_id . ' doesn\'t exist or isn\'t on your account';
}
}
if(count($errors) == 0)
{
if(count($errors) == 0) {
$last_post = 0;
$query = $db->query('SELECT post_date FROM ' . FORUM_TABLE_PREFIX . 'forum ORDER BY post_date DESC LIMIT 1');
if($query->rowCount() > 0)
@@ -79,27 +84,28 @@ if(Forum::canPost($account_logged))
$query = $query->fetch();
$last_post = $query['post_date'];
}
if($last_post+$config['forum_post_interval']-time() > 0 && !Forum::isModerator())
$errors[] = 'You can post one time per '.$config['forum_post_interval'].' seconds. Next post after '.($last_post+$config['forum_post_interval']-time()).' second(s).';
if($last_post+setting('core.forum_post_interval')-time() > 0 && !Forum::isModerator())
$errors[] = 'You can post one time per ' . setting('core.forum_post_interval') . ' seconds. Next post after '.($last_post + setting('core.forum_post_interval')-time()).' second(s).';
}
if(count($errors) == 0)
{
if(count($errors) == 0) {
$saved = true;
Forum::add_post($thread['id'], $thread['section'], $account_logged->getId(), (int) $char_id, $text, $post_topic, $smile, $html);
Forum::add_post($thread['id'], $thread['section'], $account_logged->getId(), $char_id, $text, $post_topic, $smile, $html);
$db->query("UPDATE `" . FORUM_TABLE_PREFIX . "forum` SET `replies`=`replies`+1, `last_post`=".time()." WHERE `id` = ".$thread_id);
$post_page = $db->query("SELECT COUNT(`" . FORUM_TABLE_PREFIX . "forum`.`id`) AS posts_count FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`post_date` <= ".time()." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".(int) $thread['id'])->fetch();
$_page = (int) ceil($post_page['posts_count'] / $config['forum_threads_per_page']) - 1;
$_page = (int) ceil($post_page['posts_count'] / setting('core.forum_threads_per_page')) - 1;
header('Location: ' . getForumThreadLink($thread_id, $_page));
echo '<br />Thank you for posting.<br /><a href="' . getForumThreadLink($thread_id, $_page) . '">GO BACK TO LAST THREAD</a>';
}
}
if(!$saved)
{
if(!empty($errors))
if(!$saved) {
if(!empty($errors)) {
$twig->display('error_box.html.twig', array('errors' => $errors));
}
$threads = $db->query("SELECT `players`.`name`, `" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`post_smile`, `" . FORUM_TABLE_PREFIX . "forum`.`post_html`, `" . FORUM_TABLE_PREFIX . "forum`.`author_aid` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".(int) $thread_id." ORDER BY `" . FORUM_TABLE_PREFIX . "forum`.`post_date` DESC LIMIT 5")->fetchAll();
foreach($threads as &$thread) {
$player_account = new OTS_Account();
$player_account->load($thread['author_aid']);
@@ -128,7 +134,7 @@ if(Forum::canPost($account_logged))
}
}
else {
$errors[] = "Your account is banned, deleted or you don't have any player with level " . $config['forum_level_required'] . " on your account. You can't post.";
$errors[] = "Your account is banned, deleted or you don't have any player with level " . setting('core.forum_level_required') . " on your account. You can't post.";
displayErrorBoxWithBackButton($errors, getLink('forum'));
}

Some files were not shown because too many files have changed in this diff Show More