Merge branch 'develop' into feature/settings

This commit is contained in:
slawkens 2023-02-08 15:02:56 +01:00
commit 1340b8e63e
362 changed files with 7410 additions and 2732 deletions

View File

@ -12,5 +12,8 @@ insert_final_newline = true
[*.md] [*.md]
trim_trailing_whitespace = false trim_trailing_whitespace = false
[composer.json] [{composer.json,package.json}]
indent_style = space indent_style = space
[package.json]
indent_size = 2

13
.github/workflows/phplint.yml vendored Normal file
View File

@ -0,0 +1,13 @@
name: PHP Linting
on:
pull_request:
branches: [master, develop]
push:
branches: [master]
jobs:
phplint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: michaelw90/PHP-Lint@master

19
.gitignore vendored
View File

@ -1,15 +1,19 @@
Thumbs.db Thumbs.db
.DS_Store .DS_Store
.idea .idea
tmp
# composer # composer
composer.lock composer.lock
vendor vendor
# npm
node_modules
# created by release.sh
releases releases
tmp
config.local.php config.local.php
PERSONAL_NOTES
# all custom templates # all custom templates
templates/* templates/*
@ -20,6 +24,10 @@ templates/*
images/guilds/* images/guilds/*
!images/guilds/default.gif !images/guilds/default.gif
# editor images
images/editor/*
!images/editor/index.html
# cache # cache
system/cache/* system/cache/*
!system/cache/index.html !system/cache/index.html
@ -35,16 +43,21 @@ system/logs/*
system/data/* system/data/*
!system/data/index.html !system/data/index.html
# php sessions
system/php_sessions/*
!system/php_sessions/index.html
# plugins # plugins
plugins/* plugins/*
!plugins/.htaccess !plugins/.htaccess
!plugins/example.json !plugins/example.json
!plugins/account-create-hint.json !plugins/account-create-hint.json
!plugins/account-create-hint !plugins/account-create-hint
!plugins/email-confirmed-reward.json
!plugins/email-confirmed-reward
!plugins/example-settings-plugin.json !plugins/example-settings-plugin.json
!plugins/example-settings-plugin !plugins/example-settings-plugin
landing landing
/login.php
# system # system
system/functions_custom.php system/functions_custom.php

View File

@ -9,8 +9,6 @@
<IfModule mod_rewrite.c> <IfModule mod_rewrite.c>
RewriteEngine On RewriteEngine On
# you can put here your myaac root folder
# path relative to web root
#RewriteBase /myaac/ #RewriteBase /myaac/
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-f

14
CONTRIBUTORS.txt Normal file
View File

@ -0,0 +1,14 @@
# automatically exported using this script:
# git log --all --format='%cN <%cE>' | sort -u > contributors
# in no particular order
# cleaned for readability
Evil Puncker <EPuncker@users.noreply.github.com>
Fernando Matos <fernando@pixele.com.br>
Lee <42119604+Leesneaks@users.noreply.github.com>
caio <caio.zucoli@gmail.com>
slawkens <slawkens@gmail.com>
tobi132 <52947952+tobi132@users.noreply.github.com>
vankk <nwtr.otland@hotmail.com>
whiteblXK <krzys16001@gmail.com>
xitobuh <jonas.hockert92@gmail.com>

View File

@ -1,2 +1,3 @@
* Gesior.pl (2007 - 2008) * Gesior.pl (2007 - 2008)
* Slawkens (2009 - 2020) * Slawkens (2009 - 2022)
* Contributors listed in CONTRIBUTORS.txt

View File

@ -1,4 +1,4 @@
# MyAAC # [MyAAC](https://my-aac.org)
[![Build Status Master](https://img.shields.io/travis/slawkens/myaac/master)](https://travis-ci.org/github/slawkens/myaac) [![Build Status Master](https://img.shields.io/travis/slawkens/myaac/master)](https://travis-ci.org/github/slawkens/myaac)
[![License: GPL-3.0](https://img.shields.io/github/license/slawkens/myaac)](https://opensource.org/licenses/gpl-license) [![License: GPL-3.0](https://img.shields.io/github/license/slawkens/myaac)](https://opensource.org/licenses/gpl-license)
@ -11,7 +11,7 @@ MyAAC is a free and open-source Automatic Account Creator (AAC) written in PHP.
Official website: https://my-aac.org Official website: https://my-aac.org
### REQUIREMENTS ### Requirements
- PHP 5.6 or later - PHP 5.6 or later
- MySQL database - MySQL database
@ -20,7 +20,7 @@ Official website: https://my-aac.org
- ZIP PHP Extension - ZIP PHP Extension
- (optional) mod_rewrite to use friendly_urls - (optional) mod_rewrite to use friendly_urls
### INSTALLATION AND CONFIGURATION ### Installation
Just decompress and untar the source (which you should have done by now, Just decompress and untar the source (which you should have done by now,
if you're reading this), into your webserver's document root. if you're reading this), into your webserver's document root.
@ -40,15 +40,40 @@ Official website: https://my-aac.org
Visit http://your_domain/install (http://localhost/install) and follow instructions in the browser. Visit http://your_domain/install (http://localhost/install) and follow instructions in the browser.
### KNOWN PROBLEMS ### Configuration
- none - Check *config.php* to get more informations.
Use *config.local.php* for your local configuration changes.
### OTHER NOTES ### Branches
This repository follows the Git Flow Workflow.
Cheatsheet: [Git-Flow-Cheetsheet](https://danielkummer.github.io/git-flow-cheatsheet)
That means, we use:
* master branch, for current stable release
* develop branch, for development version (next release)
* feature branches, for features etc.
### Known Problems
- Some compatibility issues with some exotical distibutions.
### Contributing
Contributions are more than welcome.
Pull requests should be made to the *develop* branch as that is the working branch, master is for release code.
Bug fixes to current release should be done to master branch.
Look: [Contributing](https://github.com/otsoft/myaac/wiki/Contributing) in our wiki.
### Other Notes
If you have a great idea or want contribute to the project - visit our website at https://www.my-aac.org If you have a great idea or want contribute to the project - visit our website at https://www.my-aac.org
### LICENSING ### License
This program and all associated files are released under the GNU Public This program and all associated files are released under the GNU Public License.
License, see LICENSE for details. See [LICENSE](https://github.com/slawkens/myaac/blob/master/LICENSE) for details.

View File

@ -1 +0,0 @@
0.9.0-dev

View File

@ -1,9 +1,10 @@
<?php <?php
// few things we'll need // few things we'll need
require '../common.php'; require '../common.php';
define('ADMIN_PANEL', true); const ADMIN_PANEL = true;
define('MYAAC_ADMIN', true); const MYAAC_ADMIN = true;
if(file_exists(BASE . 'config.local.php')) { if(file_exists(BASE . 'config.local.php')) {
require_once BASE . 'config.local.php'; require_once BASE . 'config.local.php';
@ -18,8 +19,8 @@ if(file_exists(BASE . 'install') && (!isset($config['installed']) || !$config['i
$content = ''; $content = '';
// validate page // validate page
$page = isset($_GET['p']) ? $_GET['p'] : ''; $page = $_GET['p'] ?? '';
if(empty($page) || preg_match("/[^a-zA-Z0-9_\-]/", $page)) if(empty($page) || preg_match("/[^a-zA-Z0-9_\-\/.]/", $page))
$page = 'dashboard'; $page = 'dashboard';
$page = strtolower($page); $page = strtolower($page);
@ -42,30 +43,40 @@ $hooks->load();
require SYSTEM . 'status.php'; require SYSTEM . 'status.php';
require SYSTEM . 'login.php'; require SYSTEM . 'login.php';
require SYSTEM . 'migrate.php'; require SYSTEM . 'migrate.php';
require ADMIN . 'includes/functions.php'; require __DIR__ . '/includes/functions.php';
$twig->addGlobal('config', $config); $twig->addGlobal('config', $config);
$twig->addGlobal('status', $status); $twig->addGlobal('status', $status);
if (ACTION == 'logout') {
require SYSTEM . 'logout.php';
}
// if we're not logged in - show login box // if we're not logged in - show login box
if(!$logged || !admin()) { if(!$logged || !admin()) {
$page = 'login'; $page = 'login';
} }
// include our page // include our page
$file = SYSTEM . 'pages/admin/' . $page . '.php'; $file = __DIR__ . '/pages/' . $page . '.php';
if(!@file_exists($file)) { if(!@file_exists($file)) {
if (strpos($page, 'plugins/') !== false) {
$file = BASE . $page;
}
else {
$page = '404'; $page = '404';
$file = SYSTEM . 'pages/404.php'; $file = SYSTEM . 'pages/404.php';
} }
}
ob_start(); ob_start();
include($file); if($hooks->trigger(HOOK_ADMIN_BEFORE_PAGE)) {
require $file;
}
$content .= ob_get_contents(); $content .= ob_get_contents();
ob_end_clean(); ob_end_clean();
// template // template
$template_path = 'template/'; $template_path = 'template/';
require ADMIN . $template_path . 'template.php'; require __DIR__ . '/' . $template_path . 'template.php';
?>

View File

@ -31,8 +31,8 @@ if ($config['account_country']) {
foreach ($config['countries'] as $code => $c) foreach ($config['countries'] as $code => $c)
$countries[$code] = $c; $countries[$code] = $c;
} }
$web_acc = array("None", "Admin", "Super Admin", "(Admin + Super Admin)"); $web_acc = ACCOUNT_WEB_FLAGS;
$acc_type = array("None", "Normal", "Tutor", "Senior Tutor", "Gamemaster", "God"); $acc_type = config('account_types');
?> ?>
<link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ > <link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ >
@ -70,7 +70,6 @@ else if (isset($_REQUEST['search'])) {
?> ?>
<div class="row"> <div class="row">
<?php <?php
$groups = new OTS_Groups_List();
if ($id > 0) { if ($id > 0) {
$account = new OTS_Account(); $account = new OTS_Account();
$account->load($id); $account->load($id);
@ -186,8 +185,7 @@ else if (isset($_REQUEST['search'])) {
$account->setCustomField('web_lastlogin', $web_lastlogin); $account->setCustomField('web_lastlogin', $web_lastlogin);
if (isset($password)) { if (isset($password)) {
$config_salt_enabled = $db->hasColumn('accounts', 'salt'); if (USE_ACCOUNT_SALT) {
if ($config_salt_enabled) {
$salt = generateRandomString(10, false, true, true); $salt = generateRandomString(10, false, true, true);
$password = $salt . $password; $password = $salt . $password;
$account->setCustomField('salt', $salt); $account->setCustomField('salt', $salt);
@ -196,7 +194,7 @@ else if (isset($_REQUEST['search'])) {
$password = encrypt($password); $password = encrypt($password);
$account->setPassword($password); $account->setPassword($password);
if ($config_salt_enabled) if (USE_ACCOUNT_SALT)
$account->setCustomField('salt', $salt); $account->setCustomField('salt', $salt);
} }

View File

@ -17,18 +17,18 @@ if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) {
$title = 'Changelog'; $title = 'Changelog';
$use_datatable = true; $use_datatable = true;
define('CL_LIMIT', 600); // maximum changelog body length const CL_LIMIT = 600; // maximum changelog body length
?> ?>
<link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ > <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> <script src="<?php echo BASE_URL; ?>tools/js/jquery.datetimepicker.js"></script>
<?php <?php
$id = isset($_GET['id']) ? $_GET['id'] : 0; $id = $_GET['id'] ?? 0;
require_once LIBS . 'changelog.php'; require_once LIBS . 'changelog.php';
if(!empty($action)) if(!empty($action))
{ {
$id = isset($_REQUEST['id']) ? $_REQUEST['id'] : null; $id = $_REQUEST['id'] ?? null;
$body = isset($_REQUEST['body']) ? stripslashes($_REQUEST['body']) : null; $body = isset($_REQUEST['body']) ? stripslashes($_REQUEST['body']) : null;
$create_date = isset($_REQUEST['createdate']) ? (int)strtotime($_REQUEST['createdate'] ): null; $create_date = isset($_REQUEST['createdate']) ? (int)strtotime($_REQUEST['createdate'] ): null;
$player_id = isset($_REQUEST['player_id']) ? (int)$_REQUEST['player_id'] : null; $player_id = isset($_REQUEST['player_id']) ? (int)$_REQUEST['player_id'] : null;
@ -37,9 +37,9 @@ if(!empty($action))
$errors = array(); $errors = array();
if($action == 'add') { if($action == 'new') {
if(Changelog::add($body, $type, $where, $player_id, $create_date, $errors)) { if(isset($body) && Changelog::add($body, $type, $where, $player_id, $create_date, $errors)) {
$body = ''; $body = '';
$type = $where = $player_id = $create_date = 0; $type = $where = $player_id = $create_date = 0;
@ -110,15 +110,14 @@ if($action == 'edit' || $action == 'new') {
$account_players->orderBy('group_id', POT::ORDER_DESC); $account_players->orderBy('group_id', POT::ORDER_DESC);
$twig->display('admin.changelog.form.html.twig', array( $twig->display('admin.changelog.form.html.twig', array(
'action' => $action, 'action' => $action,
'cl_link_form' => constant('ADMIN_URL').'?p=changelog&action=' . ($action == 'edit' ? 'edit' : 'add'), 'cl_link_form' => constant('ADMIN_URL').'?p=changelog&action=' . ($action == 'edit' ? 'edit' : 'new'),
'cl_id' => isset($id) ? $id : null, 'cl_id' => $id ?? null,
'body' => isset($body) ? htmlentities($body, ENT_COMPAT, 'UTF-8') : '', 'body' => isset($body) ? escapeHtml($body) : '',
'create_date' => isset($create_date) ? $create_date : '', 'create_date' => $create_date ?? '',
'player' => isset($player) && $player->isLoaded() ? $player : null, 'player_id' => $player_id ?? null,
'player_id' => isset($player_id) ? $player_id : null,
'account_players' => $account_players, 'account_players' => $account_players,
'type' => isset($type) ? $type : 0, 'type' => $type ?? 0,
'where' => isset($where) ? $where : 0, 'where' => $where ?? 0,
'log_type' => $log_type, 'log_type' => $log_type,
'log_where' => $log_where, 'log_where' => $log_where,
)); ));

View File

@ -47,10 +47,6 @@ $tmp = '';
if (fetchDatabaseConfig('site_closed_message', $tmp)) if (fetchDatabaseConfig('site_closed_message', $tmp))
$closed_message = $tmp; $closed_message = $tmp;
echo '<div class="row">';
$twig->display('admin.dashboard.html.twig', array());
echo '</div>';
$configAdminPanelModules = config('admin_panel_modules'); $configAdminPanelModules = config('admin_panel_modules');
if (isset($configAdminPanelModules)) { if (isset($configAdminPanelModules)) {
echo '<div class="row">'; echo '<div class="row">';

24
admin/pages/login.php Normal file
View File

@ -0,0 +1,24 @@
<?php
/**
* Login
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Login';
require PAGES . 'account/login.php';
if ($logged) {
header('Location: ' . ADMIN_URL);
return;
}
$twig->display('admin.login.html.twig', [
'logout' => (ACTION == 'logout' ? 'You have been logged out!' : ''),
'account' => USE_ACCOUNT_NAME ? 'Name' : 'Number',
'account_login_by' => getAccountLoginByLabel(),
'errors' => $errors ?? ''
]);

View File

@ -9,6 +9,7 @@
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = 'Logs Viewer'; $title = 'Logs Viewer';
$use_datatable = true;
$files = array(); $files = array();
$aac_path_logs = BASE . 'system/logs/'; $aac_path_logs = BASE . 'system/logs/';

View File

@ -0,0 +1,215 @@
<?php
/**
* Account Admin Tool
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @author Lee
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Mass Account Actions';
$hasCoinsColumn = $db->hasColumn('accounts', 'coins');
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
$freePremium = $config['lua']['freePremium'];
function admin_give_points($points)
{
global $db, $hasPointsColumn;
if (!$hasPointsColumn) {
displayMessage('Points not supported.');
return;
}
$statement = $db->prepare('UPDATE `accounts` SET `premium_points` = `premium_points` + :points');
if (!$statement) {
displayMessage('Failed to prepare query statement.');
return;
}
if (!$statement->execute([
'points' => $points
])) {
displayMessage('Failed to add points.');
return;
}
displayMessage($points . ' points added to all accounts.', true);
}
function admin_give_coins($coins)
{
global $db, $hasCoinsColumn;
if (!$hasCoinsColumn) {
displayMessage('Coins not supported.');
return;
}
$statement = $db->prepare('UPDATE `accounts` SET `coins` = `coins` + :coins');
if (!$statement) {
displayMessage('Failed to prepare query statement.');
return;
}
if (!$statement->execute([
'coins' => $coins
])) {
displayMessage('Failed to add coins.');
return;
}
displayMessage($coins . ' coins added to all accounts.', true);
}
function query_add_premium($column, $value_query, $condition_query = '1=1', $params = [])
{
global $db;
$statement = $db->prepare("UPDATE `accounts` SET `{$column}` = $value_query WHERE $condition_query");
if (!$statement) {
displayMessage('Failed to prepare query statement.');
return false;
}
if (!$statement->execute($params)) {
displayMessage('Failed to add premium days.');
return false;
}
return true;
}
function admin_give_premdays($days)
{
global $db, $freePremium;
if ($freePremium) {
displayMessage('Premium days not supported. Free Premium enabled.');
return;
}
$value = $days * 86400;
$now = time();
// othire
if ($db->hasColumn('accounts', 'premend')) {
// append premend
if (query_add_premium('premend', '`premend` + :value', '`premend` > :now', ['value' => $value, 'now' => $now])) {
// set premend
if (query_add_premium('premend', ':value', '`premend` <= :now', ['value' => $now + $value, 'now' => $now])) {
displayMessage($days . ' premium days added to all accounts.', true);
return;
} else {
displayMessage('Failed to execute set query.');
return;
}
} else {
displayMessage('Failed to execute append query.');
return;
}
return;
}
// tfs 0.x
if ($db->hasColumn('accounts', 'premdays')) {
// append premdays
if (query_add_premium('premdays', '`premdays` + :value', '1=1', ['value' => $days])) {
// append lastday
if (query_add_premium('lastday', '`lastday` + :value', '`lastday` > :now', ['value' => $value, 'now' => $now])) {
// set lastday
if (query_add_premium('lastday', ':value', '`lastday` <= :now', ['value' => $now + $value, 'now' => $now])) {
displayMessage($days . ' premium days added to all accounts.', true);
return;
} else {
displayMessage('Failed to execute set query.');
return;
}
return;
} else {
displayMessage('Failed to execute append query.');
return;
}
} else {
displayMessage('Failed to execute set days query.');
return;
}
return;
}
// tfs 1.x
if ($db->hasColumn('accounts', 'premium_ends_at')) {
// append premium_ends_at
if (query_add_premium('premium_ends_at', '`premium_ends_at` + :value', '`premium_ends_at` > :now', ['value' => $value, 'now' => $now])) {
// set premium_ends_at
if (query_add_premium('premium_ends_at', ':value', '`premium_ends_at` <= :now', ['value' => $now + $value, 'now' => $now])) {
displayMessage($days . ' premium days added to all accounts.', true);
return;
} else {
displayMessage('Failed to execute set query.');
return;
}
} else {
displayMessage('Failed to execute append query.');
return;
}
return;
}
displayMessage('Premium Days not supported.');
}
if (isset($_POST['action']) && $_POST['action']) {
$action = $_POST['action'];
if (preg_match("/[^A-z0-9_\-]/", $action)) {
displayMessage('Invalid action.');
} else {
$value = isset($_POST['value']) ? intval($_POST['value']) : 0;
if (!$value) {
displayMessage('Please fill all inputs');
} else {
switch ($action) {
case 'give-points':
admin_give_points($value);
break;
case 'give-coins':
admin_give_coins($value);
break;
case 'give-premdays':
admin_give_premdays($value);
break;
default:
displayMessage('Action ' . $action . 'not found.');
}
}
}
}
else {
$twig->display('admin.tools.account.html.twig', array(
'hasCoinsColumn' => $hasCoinsColumn,
'hasPointsColumn' => $hasPointsColumn,
'freePremium' => $freePremium,
));
}
function displayMessage($message, $success = false) {
global $twig, $hasCoinsColumn, $hasPointsColumn, $freePremium;
$success ? success($message): error($message);
$twig->display('admin.tools.account.html.twig', array(
'hasCoinsColumn' => $hasCoinsColumn,
'hasPointsColumn' => $hasPointsColumn,
'freePremium' => $freePremium,
));
}

View File

@ -0,0 +1,116 @@
<?php
/**
* Teleport Admin Tool
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @author Lee
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
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;
}
if (!$statement->execute([
'x' => $x, 'y' => $y, 'z' => $z
])) {
displayMessage('Failed to execute query.');
return;
}
displayMessage('Player\'s position updated.', true);
}
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
])) {
displayMessage('Failed to execute query.');
return;
}
displayMessage('Player\'s town updated.', true);
}
if (isset($_POST['action']) && $_POST['action']) {
$action = $_POST['action'];
if (preg_match("/[^A-z0-9_\-]/", $action)) {
displayMessage('Invalid action.');
} else {
$playersOnline = 0;
if($db->hasTable('players_online')) {// tfs 1.0
$query = $db->query('SELECT count(*) AS `count` FROM `players_online`');
} else {
$query = $db->query('SELECT count(*) AS `count` FROM `players` WHERE `players`.`online` > 0');
}
$playersOnline = $query->fetch(PDO::FETCH_ASSOC);
if ($playersOnline['count'] > 0) {
displayMessage('Please, close the server before execute this action otherwise players will not be affected.');
return;
}
$town_id = isset($_POST['town_id']) ? intval($_POST['town_id']) : null;
$posx = isset($_POST['posx']) ? intval($_POST['posx']) : null;
$posy = isset($_POST['posy']) ? intval($_POST['posy']) : null;
$posz = isset($_POST['posz']) ? intval($_POST['posz']) : null;
$to_temple = $_POST['to_temple'] ?? null;
switch ($action) {
case 'set-town':
if (!$town_id) {
displayMessage('Please fill all inputs');
return;
}
if (!isset($config['towns'][$town_id])) {
displayMessage('Specified town does not exist');
return;
}
admin_teleport_town($town_id);
break;
case 'set-position':
if (!$to_temple && ($posx < 0 || $posx > 65535 || $posy < 0 || $posy > 65535|| $posz < 0 || $posz > 16)) {
displayMessage('Invalid Position');
return;
}
admin_teleport_position($posx, $posy, $posz);
break;
default:
displayMessage('Action ' . $action . 'not found.');
}
}
}
else {
$twig->display('admin.tools.teleport.html.twig', array());
}
function displayMessage($message, $success = false) {
global $twig;
$success ? success($message): error($message);
$twig->display('admin.tools.teleport.html.twig', array());
}

View File

@ -93,7 +93,7 @@ if (isset($_REQUEST['template'])) {
if (isset($menus[$id])) { if (isset($menus[$id])) {
foreach ($menus[$id] as $i => $menu): foreach ($menus[$id] as $i => $menu):
?> ?>
<li class="ui-state-default" id="list-<?php echo $id ?>-<?php echo $i ?>"><label>Name:</label> <input type="text" name="menu[<?php echo $id ?>][]" value="<?php echo $menu['name'] ?>"/> <li class="ui-state-default" id="list-<?php echo $id ?>-<?php echo $i ?>"><label>Name:</label> <input type="text" name="menu[<?php echo $id ?>][]" value="<?php echo escapeHtml($menu['name']); ?>"/>
<label>Link:</label> <input type="text" name="menu_link[<?php echo $id ?>][]" value="<?php echo $menu['link'] ?>"/> <label>Link:</label> <input type="text" name="menu_link[<?php echo $id ?>][]" value="<?php echo $menu['link'] ?>"/>
<input type="hidden" name="menu_blank[<?php echo $id ?>][]" value="0"/> <input type="hidden" name="menu_blank[<?php echo $id ?>][]" value="0"/>
<label><input class="blank-checkbox" type="checkbox" <?php echo($menu['blank'] == 1 ? 'checked' : '') ?>/><span title="Open in New Window">New Window</span></label> <label><input class="blank-checkbox" type="checkbox" <?php echo($menu['blank'] == 1 ? 'checked' : '') ?>/><span title="Open in New Window">New Window</span></label>

View File

@ -23,8 +23,8 @@ if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) {
header('X-XSS-Protection:0'); header('X-XSS-Protection:0');
// some constants, used mainly by database (cannot by modified without schema changes) // some constants, used mainly by database (cannot by modified without schema changes)
define('TITLE_LIMIT', 100); define('NEWS_TITLE_LIMIT', 100);
define('BODY_LIMIT', 65535); // maximum news body length define('NEWS_BODY_LIMIT', 65535); // maximum news body length
define('ARTICLE_TEXT_LIMIT', 300); define('ARTICLE_TEXT_LIMIT', 300);
define('ARTICLE_IMAGE_LIMIT', 100); define('ARTICLE_IMAGE_LIMIT', 100);
@ -43,12 +43,12 @@ if(!empty($action))
$forum_section = isset($_REQUEST['forum_section']) ? $_REQUEST['forum_section'] : null; $forum_section = isset($_REQUEST['forum_section']) ? $_REQUEST['forum_section'] : null;
$errors = array(); $errors = array();
if($action == 'add') { if($action == 'new') {
if(isset($forum_section) && $forum_section != '-1') { if(isset($forum_section) && $forum_section != '-1') {
$forum_add = Forum::add_thread($p_title, $body, $forum_section, $player_id, $account_logged->getId(), $errors); $forum_add = Forum::add_thread($p_title, $body, $forum_section, $player_id, $account_logged->getId(), $errors);
} }
if(News::add($p_title, $body, $type, $category, $player_id, isset($forum_add) && $forum_add != 0 ? $forum_add : 0, $article_text, $article_image, $errors)) { if(isset($p_title) && News::add($p_title, $body, $type, $category, $player_id, isset($forum_add) && $forum_add != 0 ? $forum_add : 0, $article_text, $article_image, $errors)) {
$p_title = $body = $comments = $article_text = $article_image = ''; $p_title = $body = $comments = $article_text = $article_image = '';
$type = $category = $player_id = 0; $type = $category = $player_id = 0;
@ -115,21 +115,21 @@ if($action == 'edit' || $action == 'new') {
$twig->display('admin.news.form.html.twig', array( $twig->display('admin.news.form.html.twig', array(
'action' => $action, 'action' => $action,
'news_link' => getLink(PAGE), 'news_link' => getLink(PAGE),
'news_link_form' => '?p=news&action=' . ($action == 'edit' ? 'edit' : 'add'), 'news_link_form' => '?p=news&action=' . ($action == 'edit' ? 'edit' : 'new'),
'news_id' => isset($id) ? $id : null, 'news_id' => $id ?? null,
'title' => isset($p_title) ? $p_title : '', 'title' => $p_title ?? '',
'body' => isset($body) ? htmlentities($body, ENT_COMPAT, 'UTF-8') : '', 'body' => isset($body) ? escapeHtml($body) : '',
'type' => isset($type) ? $type : null, 'type' => $type ?? null,
'player' => isset($player) && $player->isLoaded() ? $player : null, 'player' => isset($player) && $player->isLoaded() ? $player : null,
'player_id' => isset($player_id) ? $player_id : null, 'player_id' => $player_id ?? null,
'account_players' => $account_players, 'account_players' => $account_players,
'category' => isset($category) ? $category : 0, 'category' => $category ?? 0,
'categories' => $categories, 'categories' => $categories,
'forum_boards' => getForumBoards(), 'forum_boards' => getForumBoards(),
'forum_section' => isset($forum_section) ? $forum_section : null, 'forum_section' => $forum_section ?? null,
'comments' => isset($comments) ? $comments : null, 'comments' => $comments ?? null,
'article_text' => isset($article_text) ? $article_text : null, 'article_text' => $article_text ?? null,
'article_image' => isset($article_image) ? $article_image : null 'article_image' => $article_image ?? null
)); ));
} }

View File

@ -1,16 +1,14 @@
<?php <?php
/** /**
* Account confirm mail * Open Source libraries
* Keept for compability
* *
* @package MyAAC * @package MyAAC
* @author Slawkens <slawkens@gmail.com> * @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC * @copyright 2023 MyAAC
* @link https://my-aac.org * @link https://my-aac.org
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
if($action == 'confirm_email') { $title = 'Open Source';
require_once PAGES . 'account/confirm_email.php';
} $twig->display('admin.open_source.html.twig');
?>

View File

@ -9,6 +9,7 @@
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = 'Pages'; $title = 'Pages';
$use_datatable = true;
if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) { if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) {
echo 'Access denied.'; echo 'Access denied.';
@ -17,13 +18,18 @@ if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) {
header('X-XSS-Protection:0'); header('X-XSS-Protection:0');
$name = $p_title = ''; $name = $p_title = null;
$groups = new OTS_Groups_List(); $groups = new OTS_Groups_List();
$php = false; $php = false;
$enable_tinymce = true; $enable_tinymce = true;
$access = 0; $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
if (!empty($action)) { if (!empty($action)) {
if ($action == 'delete' || $action == 'edit' || $action == 'hide') if ($action == 'delete' || $action == 'edit' || $action == 'hide')
$id = $_REQUEST['id']; $id = $_REQUEST['id'];
@ -49,12 +55,13 @@ if (!empty($action)) {
$errors = array(); $errors = array();
$player_id = 1; $player_id = 1;
if ($action == 'add') { if ($action == 'new') {
if (Pages::add($name, $p_title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) { if (isset($p_title) && Pages::add($name, $p_title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) {
$name = $p_title = $body = ''; $name = $p_title = $body = '';
$player_id = $access = 0; $player_id = $access = 0;
$php = false; $php = false;
$enable_tinymce = true; $enable_tinymce = true;
success('Added successful.');
} }
} else if ($action == 'delete') { } else if ($action == 'delete') {
if (Pages::delete($id, $errors)) if (Pages::delete($id, $errors))
@ -69,15 +76,18 @@ if (!empty($action)) {
$enable_tinymce = $_page['enable_tinymce'] == '1'; $enable_tinymce = $_page['enable_tinymce'] == '1';
$access = $_page['access']; $access = $_page['access'];
} else { } else {
Pages::update($id, $name, $p_title, $body, $player_id, $php, $enable_tinymce, $access); if(Pages::update($id, $name, $p_title, $body, $player_id, $php, $enable_tinymce, $access)) {
$action = $name = $p_title = $body = ''; $action = $name = $p_title = $body = '';
$player_id = 1; $player_id = 1;
$access = 0; $access = 0;
$php = false; $php = false;
$enable_tinymce = true; $enable_tinymce = true;
success("Updated successful.");
}
} }
} else if ($action == 'hide') { } else if ($action == 'hide') {
Pages::toggleHidden($id, $errors); Pages::toggleHidden($id, $errors, $status);
success(($status == 1 ? 'Show' : 'Hide') . " successful.");
} }
if (!empty($errors)) if (!empty($errors))
@ -105,7 +115,7 @@ $twig->display('admin.pages.form.html.twig', array(
'title' => $p_title, 'title' => $p_title,
'php' => $php, 'php' => $php,
'enable_tinymce' => $enable_tinymce, 'enable_tinymce' => $enable_tinymce,
'body' => isset($body) ? htmlentities($body, ENT_COMPAT, 'UTF-8') : '', 'body' => isset($body) ? escapeHtml($body) : '',
'groups' => $groups->getGroups(), 'groups' => $groups->getGroups(),
'access' => $access 'access' => $access
)); ));
@ -116,6 +126,44 @@ $twig->display('admin.pages.html.twig', array(
class 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(!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) static public function get($id)
{ {
global $db; global $db;
@ -128,8 +176,11 @@ class Pages
static public function add($name, $title, $body, $player_id, $php, $enable_tinymce, $access, &$errors) 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; global $db;
if (isset($name[0]) && isset($title[0]) && isset($body[0]) && $player_id != 0) {
$query = $db->select(TABLE_PREFIX . 'pages', array('name' => $name)); $query = $db->select(TABLE_PREFIX . 'pages', array('name' => $name));
if ($query === false) if ($query === false)
$db->insert(TABLE_PREFIX . 'pages', $db->insert(TABLE_PREFIX . 'pages',
@ -145,14 +196,16 @@ class Pages
); );
else else
$errors[] = 'Page with this link already exists.'; $errors[] = 'Page with this link already exists.';
} else
$errors[] = 'Please fill all inputs.';
return !count($errors); return !count($errors);
} }
static public function update($id, $name, $title, $body, $player_id, $php, $enable_tinymce, $access) static public function update($id, $name, $title, $body, $player_id, $php, $enable_tinymce, $access)
{ {
if(!self::verify($name, $title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) {
return false;
}
global $db; global $db;
$db->update(TABLE_PREFIX . 'pages', $db->update(TABLE_PREFIX . 'pages',
array( array(
@ -165,6 +218,8 @@ class Pages
'access' => $access 'access' => $access
), ),
array('id' => $id)); array('id' => $id));
return true;
} }
static public function delete($id, &$errors) static public function delete($id, &$errors)
@ -181,15 +236,18 @@ class Pages
return !count($errors); return !count($errors);
} }
static public function toggleHidden($id, &$errors) static public function toggleHidden($id, &$errors, &$status)
{ {
global $db; global $db;
if (isset($id)) { if (isset($id)) {
$query = $db->select(TABLE_PREFIX . 'pages', array('id' => $id)); $query = $db->select(TABLE_PREFIX . 'pages', array('id' => $id));
if ($query !== false) if ($query !== false) {
$db->update(TABLE_PREFIX . 'pages', array('hidden' => ($query['hidden'] == 1 ? 0 : 1)), array('id' => $id)); $db->update(TABLE_PREFIX . 'pages', array('hidden' => ($query['hidden'] == 1 ? 0 : 1)), array('id' => $id));
else $status = $query['hidden'];
}
else {
$errors[] = 'Page with id ' . $id . ' does not exists.'; $errors[] = 'Page with id ' . $id . ' does not exists.';
}
} else } else
$errors[] = 'id not set'; $errors[] = 'id not set';

View File

@ -634,9 +634,9 @@ else if (isset($_REQUEST['search'])) {
<label for="look_addons" class="control-label">Addons:</label> <label for="look_addons" class="control-label">Addons:</label>
<select name="look_addons" id="look_addons" class="form-control custom-select"> <select name="look_addons" id="look_addons" class="form-control custom-select">
<?php <?php
$addon_type = array(0, 1, 2, 3); $addon_type = array("None", "First", "Second", "Both");
foreach ($addon_type as $id => $s_name) { foreach ($addon_type as $id => $s_name) {
echo '<option value=' . $s_name . ($id == $player->getLookAddons() ? ' selected' : '') . '>' . $s_name . '</option>'; echo '<option value=' . $id . ($id == $player->getLookAddons() ? ' selected' : '') . '>' . $s_name . '</option>';
} }
?> ?>
</select> </select>

View File

@ -9,6 +9,7 @@
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = 'Plugin manager'; $title = 'Plugin manager';
$use_datatable = true;
require_once LIBS . 'plugins.php'; require_once LIBS . 'plugins.php';

View File

@ -9,6 +9,7 @@
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = 'Report Viewer'; $title = 'Report Viewer';
$use_datatable = true;
$files = array(); $files = array();
$server_path_reports = $config['data_path'] . 'reports/'; $server_path_reports = $config['data_path'] . 'reports/';

View File

@ -10,18 +10,24 @@
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = 'Tools'; $title = 'Tools';
$tool = $_GET['tool']; if (!isset($_GET['tool'])) {
if (!isset($tool)) {
echo 'Tool not set.'; echo 'Tool not set.';
return; return;
} }
$tool = $_GET['tool'];
if (preg_match("/[^A-z0-9_\-]/", $tool)) { if (preg_match("/[^A-z0-9_\-]/", $tool)) {
echo 'Invalid tool.'; echo 'Invalid tool.';
return; return;
} }
$file = BASE . 'admin/pages/tools/' . $tool . '.php'; $file = ADMIN . 'tools/' . $tool . '.php';
if (!@file_exists($file))
if (@file_exists($file)) {
require $file; require $file;
return;
}
echo 'Tool <strong>' . $tool . '</strong> not found.';
?> ?>

View File

@ -9,6 +9,7 @@
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = 'Visitors'; $title = 'Visitors';
$use_datatable = true;
if (!$config['visitors_counter']): ?> if (!$config['visitors_counter']): ?>
Visitors counter is disabled.<br/> Visitors counter is disabled.<br/>

View File

@ -1,49 +1,67 @@
<?php <?php
return [ return [
['name' => 'Dashboard', 'icon' => 'tachometer-alt', 'link' => 'dashboard'], ['name' => 'Dashboard', 'icon' => 'tachometer-alt', 'order' => 10, 'link' => 'dashboard'],
['name' => 'Settings', 'icon' => 'edit', 'link' => 'settings&plugin=core'], ['name' => 'Settings', 'icon' => 'edit', 'order' => 19, 'link' => 'settings&plugin=core'],
['name' => 'News', 'icon' => 'newspaper', 'link' => ['name' => 'News', 'icon' => 'newspaper', 'order' => 20, 'link' =>
[ [
['name' => 'View', 'link' => 'news'], ['name' => 'View', 'link' => 'news', 'icon' => 'list', 'order' => 10],
['name' => 'Add news', 'link' => 'news&action=new&type=1'], ['name' => 'Add news', 'link' => 'news&action=new&type=1', 'icon' => 'plus', 'order' => 20],
['name' => 'Add ticker', 'link' => 'news&action=new&type=2'], ['name' => 'Add ticker', 'link' => 'news&action=new&type=2', 'icon' => 'plus', 'order' => 30],
['name' => 'Add article', 'link' => 'news&action=new&type=3'], ['name' => 'Add article', 'link' => 'news&action=new&type=3', 'icon' => 'plus', 'order' => 40],
], ],
], ],
['name' => 'Changelogs', 'icon' => 'newspaper', 'link' => ['name' => 'Changelogs', 'icon' => 'newspaper', 'order' => 30, 'link' =>
[ [
['name' => 'View', 'link' => 'changelog'], ['name' => 'View', 'link' => 'changelog', 'icon' => 'list', 'order' => 10],
['name' => 'Add', 'link' => 'changelog&action=new'], ['name' => 'Add', 'link' => 'changelog&action=new', 'icon' => 'plus', 'order' => 20],
], ],
], ],
['name' => 'Mailer', 'icon' => 'envelope', 'link' => 'mailer', 'disabled' => !config('mail_enabled')], ['name' => 'Mailer', 'icon' => 'envelope', 'order' => 40, 'link' => 'mailer', 'disabled' => !config('mail_enabled')],
['name' => 'Pages', 'icon' => 'book', 'link' => ['name' => 'Pages', 'icon' => 'book', 'order' => 50, 'link' =>
[ [
['name' => 'View', 'link' => 'pages'], ['name' => 'View', 'link' => 'pages', 'icon' => 'list', 'order' => 10],
['name' => 'Add', 'link' => 'pages&action=new'], ['name' => 'Add', 'link' => 'pages&action=new', 'icon' => 'plus', 'order' => 20],
], ],
], ],
['name' => 'Menus', 'icon' => 'list', 'link' => 'menus'], ['name' => 'Menus', 'icon' => 'list', 'order' => 60, 'link' => 'menus'],
['name' => 'Plugins', 'icon' => 'plug', 'link' => 'plugins'], ['name' => 'Plugins', 'icon' => 'plug', 'order' => 70, 'link' => 'plugins'],
['name' => 'Server Data', 'icon' => 'gavel', 'link' => 'data'], ['name' => 'Server Data', 'icon' => 'gavel', 'order' => 80, 'link' => 'data'],
['name' => 'Editor', 'icon' => 'edit', 'link' => ['name' => 'Editor', 'icon' => 'edit', 'order' => 90, 'link' =>
[ [
['name' => 'Accounts', 'link' => 'accounts'], ['name' => 'Accounts', 'link' => 'accounts', 'icon' => 'users', 'order' => 10],
['name' => 'Players', 'link' => 'players'], ['name' => 'Players', 'link' => 'players', 'icon' => 'user-astronaut', 'order' => 20],
], ],
], ],
['name' => 'Tools', 'icon' => 'tools', 'link' => ['name' => 'Tools', 'icon' => 'tools', 'order' => 100, 'link' =>
[ [
['name' => 'Notepad', 'link' => 'notepad'], ['name' => 'Mass Account Actions', 'link' => 'mass_account', 'icon' => 'globe', 'order' => 10],
['name' => 'phpinfo', 'link' => 'phpinfo'], ['name' => 'Mass Teleport Actions', 'link' => 'mass_teleport', 'icon' => 'globe', 'order' => 20],
['name' => 'Notepad', 'link' => 'notepad', 'icon' => 'marker', 'order' => 30],
['name' => 'phpinfo', 'link' => 'phpinfo', 'icon' => 'server', 'order' => 40],
], ],
], ],
['name' => 'Logs', 'icon' => 'bug', 'link' => ['name' => 'Logs', 'icon' => 'bug', 'order' => 110, 'link' =>
[ [
['name' => 'Logs', 'link' => 'logs'], ['name' => 'Logs', 'link' => 'logs', 'icon' => 'book', 'order' => 10],
['name' => 'Reports', 'link' => 'reports'], ['name' => 'Reports', 'link' => 'reports', 'icon' => 'book', 'order' => 20],
['name' => 'Visitors', 'icon' => 'user', 'link' => 'visitors'], ['name' => 'Visitors', 'link' => 'visitors', 'icon' => 'user', 'order' => 30],
], ],
], ],
]; ];
$hooks->trigger(HOOK_ADMIN_MENU);
usort($menus, function ($a, $b) {
return $a['order'] - $b['order'];
});
foreach ($menus as $i => $menu) {
if (isset($menu['link']) && is_array($menu['link'])) {
usort($menus[$i]['link'], function ($a, $b) {
return $a['order'] - $b['order'];
});
}
}
return $menus;

View File

@ -2,6 +2,7 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<?php $hooks->trigger(HOOK_ADMIN_HEAD_START); ?>
<?php echo template_header(true); ?> <?php echo template_header(true); ?>
<title><?php echo (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];?></title> <title><?php echo (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];?></title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
@ -16,8 +17,10 @@
<script src="<?php echo BASE_URL; ?>tools/js/respond.min.js"></script> <script src="<?php echo BASE_URL; ?>tools/js/respond.min.js"></script>
<![endif]--> <![endif]-->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic">
<?php $hooks->trigger(HOOK_ADMIN_HEAD_END); ?>
</head> </head>
<body class="sidebar-mini "> <body class="sidebar-mini ">
<?php $hooks->trigger(HOOK_ADMIN_BODY_START); ?>
<?php if ($logged && admin()) { ?> <?php if ($logged && admin()) { ?>
<div class="wrapper"> <div class="wrapper">
<nav class="main-header navbar navbar-expand navbar-white navbar-light"> <nav class="main-header navbar navbar-expand navbar-white navbar-light">
@ -79,12 +82,12 @@
$nav_construct .= ' active'; $nav_construct .= ' active';
$used_menu = true; $used_menu = true;
} }
$nav_construct .= '"><i class="far fa-' . (isset($sub_menu['icon']) ? $sub_menu['icon'] : 'circle') . ' nav-icon"></i><p>' . $sub_menu['name'] . '</p></a></li>'; $nav_construct .= '"><i class="fas fa-' . ($sub_menu['icon'] ?? 'circle') . ' nav-icon"></i><p>' . $sub_menu['name'] . '</p></a></li>';
} }
?> ?>
<li class="nav-item has-treeview<?php echo($used_menu ? ' menu-open' : '') ?>"> <li class="nav-item has-treeview<?php echo($used_menu ? ' menu-open' : '') ?>">
<a href="#" class="nav-link<?php echo($used_menu ? ' active' : '') ?>"> <a href="#" class="nav-link<?php echo($used_menu ? ' active' : '') ?>">
<i class="nav-icon fas fa-<?php echo(isset($menu['icon']) ? $menu['icon'] : 'link') ?>"></i> <i class="nav-icon fas fa-<?php echo($menu['icon'] ?? 'link') ?>"></i>
<p><?php echo $menu['name'] ?></p><i class="right fas fa-angle-left"></i> <p><?php echo $menu['name'] ?></p><i class="right fas fa-angle-left"></i>
</a> </a>
<ul class="nav nav-treeview"> <ul class="nav nav-treeview">
@ -159,6 +162,9 @@
<p><h5><a href="http://my-aac.org/" target="_blank"><i class="fas fa-shoe-prints"></i> MyAAC Official</a></h5> <p><h5><a href="http://my-aac.org/" target="_blank"><i class="fas fa-shoe-prints"></i> MyAAC Official</a></h5>
<small>Goto MyAAC Official Website</small></p> <small>Goto MyAAC Official Website</small></p>
<p><h5><a href="?p=open_source"><i class="fas fa-wrench"></i> Open Source</a></h5>
<small>View Open Source Software MyAAC is using</small></p>
</div> </div>
</aside> </aside>
@ -175,6 +181,16 @@
echo $content; echo $content;
} }
?> ?>
<?php
/**
* @var OTS_Account $account_logged
*/
if ($logged && admin()) {
$twig->display('admin-bar.html.twig', [
'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()
]);
}
?>
<script src="<?php echo BASE_URL; ?>tools/js/bootstrap.min.js"></script> <script src="<?php echo BASE_URL; ?>tools/js/bootstrap.min.js"></script>
<script src="<?php echo BASE_URL; ?>tools/js/jquery-ui.min.js"></script> <script src="<?php echo BASE_URL; ?>tools/js/jquery-ui.min.js"></script>
<?php if (isset($use_datatable)) { ?> <?php if (isset($use_datatable)) { ?>
@ -182,5 +198,6 @@
<script src="<?php echo BASE_URL; ?>tools/js/datatables.bs.min.js"></script> <script src="<?php echo BASE_URL; ?>tools/js/datatables.bs.min.js"></script>
<?php } ?> <?php } ?>
<script src="<?php echo BASE_URL; ?>tools/js/adminlte.min.js"></script> <script src="<?php echo BASE_URL; ?>tools/js/adminlte.min.js"></script>
<?php $hooks->trigger(HOOK_ADMIN_BODY_END); ?>
</body> </body>
</html> </html>

View File

@ -0,0 +1,53 @@
<?php
define('MYAAC_ADMIN', true);
require '../../common.php';
require SYSTEM . 'functions.php';
require SYSTEM . 'init.php';
require SYSTEM . 'login.php';
if(!admin())
die('Access denied.');
// Don't attempt to process the upload on an OPTIONS request
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
header('Access-Control-Allow-Methods: POST, OPTIONS');
return;
}
$imageFolder = BASE . EDITOR_IMAGES_DIR;
reset ($_FILES);
$temp = current($_FILES);
if (is_uploaded_file($temp['tmp_name'])) {
header('Access-Control-Allow-Credentials: true');
header('P3P: CP="There is no P3P policy."');
// Sanitize input
if (preg_match("/([^\w\s\d\-_~,;:\[\]\(\).])|([\.]{2,})/", $temp['name'])) {
header('HTTP/1.1 400 Invalid file name.');
return;
}
// Verify extension
$ext = strtolower(pathinfo($temp['name'], PATHINFO_EXTENSION));
if (!in_array($ext, ['gif', 'jpg', 'png'])) {
header('HTTP/1.1 400 Invalid extension.');
return;
}
do {
$randomName = generateRandomString(8). ".$ext";
$fileToWrite = $imageFolder . $randomName;
} while (file_exists($fileToWrite));
move_uploaded_file($temp['tmp_name'], $fileToWrite);
$returnPathToImage = BASE_URL . EDITOR_IMAGES_DIR . $randomName;
echo json_encode(['location' => $returnPathToImage]);
} else {
// Notify editor that the upload failed
header('HTTP/1.1 500 Server Error');
}

View File

@ -23,69 +23,97 @@
* @copyright 2019 MyAAC * @copyright 2019 MyAAC
* @link https://my-aac.org * @link https://my-aac.org
*/ */
if (version_compare(phpversion(), '7.1', '<')) die('PHP version 7.1 or higher is required.'); if (version_compare(phpversion(), '7.2.5', '<')) die('PHP version 7.2.5 or higher is required.');
session_start();
define('MYAAC', true); const MYAAC = true;
define('MYAAC_VERSION', '0.9.0-dev'); const MYAAC_VERSION = '0.9.0-dev';
define('DATABASE_VERSION', 33); const DATABASE_VERSION = 34;
define('TABLE_PREFIX', 'myaac_'); const TABLE_PREFIX = 'myaac_';
define('START_TIME', microtime(true)); define('START_TIME', microtime(true));
define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX')); define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));
define('IS_CLI', in_array(php_sapi_name(), ['cli', 'phpdb'])); define('IS_CLI', in_array(php_sapi_name(), ['cli', 'phpdb']));
// account flags // account flags
define('FLAG_ADMIN', 1); const FLAG_NONE = 0;
define('FLAG_SUPER_ADMIN', 2); const FLAG_ADMIN = 1;
define('FLAG_CONTENT_PAGES', 4); const FLAG_SUPER_ADMIN = 2;
define('FLAG_CONTENT_MAILER', 8); const FLAG_SUPER_BOTH = 3;
define('FLAG_CONTENT_NEWS', 16); const FLAG_CONTENT_PAGES = 4;
define('FLAG_CONTENT_FORUM', 32); const FLAG_CONTENT_MAILER = 8;
define('FLAG_CONTENT_COMMANDS', 64); const FLAG_CONTENT_NEWS = 16;
define('FLAG_CONTENT_SPELLS', 128); const FLAG_CONTENT_FORUM = 32;
define('FLAG_CONTENT_MONSTERS', 256); const FLAG_CONTENT_COMMANDS = 64;
define('FLAG_CONTENT_GALLERY', 512); const FLAG_CONTENT_SPELLS = 128;
define('FLAG_CONTENT_VIDEOS', 1024); const FLAG_CONTENT_MONSTERS = 256;
define('FLAG_CONTENT_FAQ', 2048); const FLAG_CONTENT_GALLERY = 512;
define('FLAG_CONTENT_MENUS', 4096); const FLAG_CONTENT_VIDEOS = 1024;
define('FLAG_CONTENT_PLAYERS', 8192); const FLAG_CONTENT_FAQ = 2048;
const FLAG_CONTENT_MENUS = 4096;
const FLAG_CONTENT_PLAYERS = 8192;
// account access types
const ACCOUNT_WEB_FLAGS = [
FLAG_NONE => 'None',
FLAG_ADMIN =>'Admin',
FLAG_SUPER_ADMIN => 'Super Admin',
FLAG_SUPER_BOTH =>'(Admin + Super Admin)',
];
// news // news
define('NEWS', 1); const NEWS = 1;
define('TICKER', 2); const TICKER = 2;
define('ARTICLE', 3); const ARTICLE = 3;
// here you can change location of admin panel
// you need also to rename folder "admin"
// this may improve security
const ADMIN_PANEL_FOLDER = 'admin';
// directories // directories
define('BASE', __DIR__ . '/'); const BASE = __DIR__ . '/';
define('ADMIN', BASE . 'admin/'); const ADMIN = BASE . ADMIN_PANEL_FOLDER . '/';
define('SYSTEM', BASE . 'system/'); const SYSTEM = BASE . 'system/';
define('CACHE', SYSTEM . 'cache/'); const CACHE = SYSTEM . 'cache/';
define('LOCALE', SYSTEM . 'locale/'); const LOCALE = SYSTEM . 'locale/';
define('LIBS', SYSTEM . 'libs/'); const LIBS = SYSTEM . 'libs/';
define('LOGS', SYSTEM . 'logs/'); const LOGS = SYSTEM . 'logs/';
define('PAGES', SYSTEM . 'pages/'); const PAGES = SYSTEM . 'pages/';
define('PLUGINS', BASE . 'plugins/'); const PLUGINS = BASE . 'plugins/';
define('TEMPLATES', BASE . 'templates/'); const TEMPLATES = BASE . 'templates/';
define('TOOLS', BASE . 'tools/'); const TOOLS = BASE . 'tools/';
define('VENDOR', BASE . 'vendor/'); const VENDOR = BASE . 'vendor/';
// other dirs
const SESSIONS_DIR = SYSTEM . 'php_sessions';
const GUILD_IMAGES_DIR = 'images/guilds/';
const EDITOR_IMAGES_DIR = 'images/editor/';
const GALLERY_DIR = 'images/gallery/';
// menu categories // menu categories
define('MENU_CATEGORY_NEWS', 1); const MENU_CATEGORY_NEWS = 1;
define('MENU_CATEGORY_ACCOUNT', 2); const MENU_CATEGORY_ACCOUNT = 2;
define('MENU_CATEGORY_COMMUNITY', 3); const MENU_CATEGORY_COMMUNITY = 3;
define('MENU_CATEGORY_FORUM', 4); const MENU_CATEGORY_FORUM = 4;
define('MENU_CATEGORY_LIBRARY', 5); const MENU_CATEGORY_LIBRARY = 5;
define('MENU_CATEGORY_SHOP', 6); const MENU_CATEGORY_SHOP = 6;
// otserv versions // otserv versions
define('OTSERV', 1); const OTSERV = 1;
define('OTSERV_06', 2); const OTSERV_06 = 2;
define('OTSERV_FIRST', OTSERV); const OTSERV_FIRST = OTSERV;
define('OTSERV_LAST', OTSERV_06); const OTSERV_LAST = OTSERV_06;
define('TFS_02', 3); const TFS_02 = 3;
define('TFS_03', 4); const TFS_03 = 4;
define('TFS_FIRST', TFS_02); const TFS_FIRST = TFS_02;
define('TFS_LAST', TFS_03); const TFS_LAST = TFS_03;
// other definitions
const ACCOUNT_NUMBER_LENGTH = 8;
if (!IS_CLI) {
session_save_path(SESSIONS_DIR);
session_start();
}
// basedir // basedir
$basedir = ''; $basedir = '';
@ -94,7 +122,7 @@ $size = count($tmp) - 1;
for($i = 1; $i < $size; $i++) for($i = 1; $i < $size; $i++)
$basedir .= '/' . $tmp[$i]; $basedir .= '/' . $tmp[$i];
$basedir = str_replace(array('/admin', '/install'), '', $basedir); $basedir = str_replace(['/' . ADMIN_PANEL_FOLDER, '/install', '/tools'], '', $basedir);
define('BASE_DIR', $basedir); define('BASE_DIR', $basedir);
if(!IS_CLI) { if(!IS_CLI) {

View File

@ -1,16 +1,15 @@
{ {
"require": { "require": {
"php": ">=7.1", "php": "^7.2.5 || ^8.0",
"ext-dom": "*",
"ext-json": "*",
"ext-gd": "*",
"ext-pdo": "*", "ext-pdo": "*",
"ext-pdo_mysql": "*", "ext-pdo_mysql": "*",
"ext-json": "*",
"ext-xml": "*", "ext-xml": "*",
"ext-zip": "*", "ext-dom": "*",
"phpmailer/phpmailer": "^6.1", "phpmailer/phpmailer": "^6.1",
"composer/semver": "^3.2", "composer/semver": "^3.2",
"twig/twig": "~1.42.5", "twig/twig": "^2.0",
"erusev/parsedown": "^1.7" "erusev/parsedown": "^1.7",
"nikic/fast-route": "^1.3"
} }
} }

View File

@ -43,7 +43,7 @@ $config = array(
'database_user' => '', 'database_user' => '',
'database_password' => '', 'database_password' => '',
'database_name' => '', 'database_name' => '',
'database_log' => false, // should database queries be logged and and saved into system/logs/database.log? '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_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 'database_persistent' => false, // use database permanent connection (like server), may speed up your site
@ -69,9 +69,18 @@ $config = array(
// account // account
'account_management' => true, // disable if you're using other method to manage users (fe. tfs account manager) '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_auto_login' => false, // auto login after creating account?
'account_create_character_create' => true, // allow directly to create character on create account page? '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 '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_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_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_days' => 0, // default premium days on new account
@ -103,18 +112,24 @@ $config = array(
'smtp_secure' => '', // What kind of encryption to use on the SMTP connection. Options: '', 'ssl' (GMail) or 'tls' (Microsoft Outlook) '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) 'smtp_debug' => false, // set true to debug (you will see more info in error.log)
// reCAPTCHA (prevent spam bots)
'recaptcha_enabled' => false, // enable recaptcha verification code
'recaptcha_site_key' => '', // get your own site and secret keys at https://www.google.com/recaptcha
'recaptcha_secret_key' => '',
'recaptcha_theme' => 'light', // light, dark
// //
'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' => 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 '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_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) '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 (aka sex)
'genders' => array( 'genders' => array(
0 => 'Female', 0 => 'Female',
@ -130,6 +145,8 @@ $config = array(
4 => 'Knight Sample' 4 => 'Knight Sample'
), ),
'use_character_sample_skills' => false,
// it must show limited number of players after using search in character page // it must show limited number of players after using search in character page
'characters_search_limit' => 15, 'characters_search_limit' => 15,

228
index.php
View File

@ -28,18 +28,22 @@ require_once 'common.php';
require_once SYSTEM . 'functions.php'; require_once SYSTEM . 'functions.php';
$uri = $_SERVER['REQUEST_URI']; $uri = $_SERVER['REQUEST_URI'];
if(false !== strpos($uri, 'index.php')) {
$uri = str_replace_first('/index.php', '', $uri);
}
$tmp = BASE_DIR; if(0 === strpos($uri, '/')) {
if(!empty($tmp))
$uri = str_replace(BASE_DIR . '/', '', $uri);
else
$uri = str_replace_first('/', '', $uri); $uri = str_replace_first('/', '', $uri);
}
$uri = str_replace(array('index.php/', '?'), '', $uri); if(preg_match("/^[A-Za-z0-9-_%'+\/]+\.png$/i", $uri)) {
define('URI', $uri); if (!empty(BASE_DIR)) {
$tmp = explode('.', str_replace_first(str_replace_first('/', '', BASE_DIR) . '/', '', $uri));
if(preg_match("/^[A-Za-z0-9-_%'+]+\.png$/i", $uri)) { }
else {
$tmp = explode('.', $uri); $tmp = explode('.', $uri);
}
$_REQUEST['name'] = urldecode($tmp[0]); $_REQUEST['name'] = urldecode($tmp[0]);
chdir(TOOLS . 'signature'); chdir(TOOLS . 'signature');
@ -47,7 +51,7 @@ if(preg_match("/^[A-Za-z0-9-_%'+]+\.png$/i", $uri)) {
exit(); exit();
} }
if(preg_match("/^(.*)\.(gif|jpg|png|jpeg|tiff|bmp|css|js|less|map|html|php|zip|rar|gz|ttf|woff|ico)$/i", $_SERVER['REQUEST_URI'])) { if(preg_match("/^(.*)\.(gif|jpg|png|jpeg|tiff|bmp|css|js|less|map|html|zip|rar|gz|ttf|woff|ico)$/i", $_SERVER['REQUEST_URI'])) {
http_response_code(404); http_response_code(404);
exit; exit;
} }
@ -74,110 +78,15 @@ if((!isset($config['installed']) || !$config['installed']) && file_exists(BASE .
throw new RuntimeException('Setup detected that <b>install/</b> directory exists. Please visit <a href="' . BASE_URL . 'install">this</a> url to start MyAAC Installation.<br/>Delete <b>install/</b> directory if you already installed MyAAC.<br/>Remember to REFRESH this page when you\'re done!'); throw new RuntimeException('Setup detected that <b>install/</b> directory exists. Please visit <a href="' . BASE_URL . 'install">this</a> url to start MyAAC Installation.<br/>Delete <b>install/</b> directory if you already installed MyAAC.<br/>Remember to REFRESH this page when you\'re done!');
} }
$found = false;
if(empty($uri) || isset($_REQUEST['template'])) {
$_REQUEST['p'] = 'news';
$found = true;
}
else {
$tmp = strtolower($uri);
if(!preg_match('/[^A-z0-9_\-]/', $uri) && file_exists(SYSTEM . 'pages/' . $tmp . '.php')) {
$_REQUEST['p'] = $uri;
$found = true;
}
else {
$rules = array(
'/^account\/manage\/?$/' => array('subtopic' => 'accountmanagement'),
'/^account\/create\/?$/' => array('subtopic' => 'createaccount'),
'/^account\/lost\/?$/' => array('subtopic' => 'lostaccount'),
'/^account\/logout\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'logout'),
'/^account\/password\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'change_password'),
'/^account\/register\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'register'),
'/^account\/register\/new\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'register_new'),
'/^account\/email\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'change_email'),
'/^account\/info\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'change_info'),
'/^account\/character\/create\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'create_character'),
'/^account\/character\/name\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'change_name'),
'/^account\/character\/sex\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'change_sex'),
'/^account\/character\/delete\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'delete_character'),
'/^account\/character\/comment\/[A-Za-z0-9-_%+\']+\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'change_comment', 'name' => '$3'),
'/^account\/character\/comment\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'change_comment'),
'/^account\/confirm_email\/[A-Za-z0-9-_]+\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'confirm_email', 'v' => '$2'),
'/^bans\/[0-9]+\/?$/' => array('subtopic' => 'bans', 'page' => '$1'),
'/^characters\/[A-Za-z0-9-_%+\']+$/' => array('subtopic' => 'characters', 'name' => '$1'),
'/^changelog\/[0-9]+\/?$/' => array('subtopic' => 'changelog', 'page' => '$1'),
'/^commands\/add\/?$/' => array('subtopic' => 'commands', 'action' => 'add'),
'/^commands\/edit\/?$/' => array('subtopic' => 'commands', 'action' => 'edit'),
'/^creatures\/[A-Za-z0-9-_%+\']+$/' => array('subtopic' => 'creatures', 'creature' => '$1'),
'/^faq\/add\/?$/' => array('subtopic' => 'faq', 'action' => 'add'),
'/^faq\/edit\/?$/' => array('subtopic' => 'faq', 'action' => 'edit'),
'/^forum\/add_board\/?$/' => array('subtopic' => 'forum', 'action' => 'add_board'),#
'/^forum\/edit_board\/?$/' => array('subtopic' => 'forum', 'action' => 'edit_board'),
'/^forum\/board\/[0-9]+\/?$/' => array('subtopic' => 'forum', 'action' => 'show_board', 'id' => '$2'),
'/^forum\/board\/[0-9]+\/[0-9]+\/?$/' => array('subtopic' => 'forum', 'action' => 'show_board', 'id' => '$2', 'page' => '$3'),
'/^forum\/thread\/[0-9]+\/?$/' => array('subtopic' => 'forum', 'action' => 'show_thread', 'id' => '$2'),
'/^forum\/thread\/[0-9]+\/[0-9]+\/?$/' => array('subtopic' => 'forum', 'action' => 'show_thread', 'id' => '$2', 'page' => '$3'),
'/^gallery\/add\/?$/' => array('subtopic' => 'gallery', 'action' => 'add'),
'/^gallery\/edit\/?$/' => array('subtopic' => 'gallery', 'action' => 'edit'),
'/^gallery\/[0-9]+\/?$/' => array('subtopic' => 'gallery', 'image' => '$1'),
'/^gifts\/history\/?$/' => array('subtopic' => 'gifts', 'action' => 'show_history'),
'/^guilds\/[A-Za-z0-9-_%+\']+$/' => array('subtopic' => 'guilds', 'action' => 'show', 'guild' => '$1'),
'/^highscores\/[A-Za-z0-9-_]+\/[A-Za-z0-9-_]+\/[0-9]+\/?$/' => array('subtopic' => 'highscores', 'list' => '$1', 'vocation' => '$2', 'page' => '$3'),
'/^highscores\/[A-Za-z0-9-_]+\/[0-9]+\/?$/' => array('subtopic' => 'highscores', 'list' => '$1', 'page' => '$2'),
'/^highscores\/[A-Za-z0-9-_]+\/[A-Za-z0-9-_]+\/?$/' => array('subtopic' => 'highscores', 'list' => '$1', 'vocation' => '$2'),
'/^highscores\/[A-Za-z0-9-_\']+\/?$/' => array('subtopic' => 'highscores', 'list' => '$1'),
'/^news\/add\/?$/' => array('subtopic' => 'news', 'action' => 'add'),
'/^news\/edit\/?$/' => array('subtopic' => 'news', 'action' => 'edit'),
'/^news\/archive\/?$/' => array('subtopic' => 'newsarchive'),
'/^news\/archive\/[0-9]+\/?$/' => array('subtopic' => 'newsarchive', 'id' => '$2'),
'/^polls\/[0-9]+\/?$/' => array('subtopic' => 'polls', 'id' => '$1'),
'/^spells\/[A-Za-z0-9-_%]+\/[A-Za-z0-9-_]+\/?$/' => array('subtopic' => 'spells', 'vocation' => '$1', 'order' => '$2'),
'/^houses\/view\/?$/' => array('subtopic' => 'houses', 'page' => 'view')
);
foreach($rules as $rule => $redirect) {
if (preg_match($rule, $uri)) {
$tmp = explode('/', $uri);
/* @var $redirect array */
foreach($redirect as $key => $value) {
if(strpos($value, '$') !== false) {
$value = str_replace('$' . $value[1], $tmp[$value[1]], $value);
}
$_REQUEST[$key] = $value;
$_GET[$key] = $value;
}
$found = true;
break;
}
}
}
}
// define page visited, so it can be used within events system
$page = isset($_REQUEST['subtopic']) ? $_REQUEST['subtopic'] : (isset($_REQUEST['p']) ? $_REQUEST['p'] : '');
if(empty($page) || !preg_match('/^[A-z0-9\_\-]+$/', $page)) {
$tmp = URI;
if(!empty($tmp)) {
$page = $tmp;
}
else {
if(!$found)
$page = '404';
else
$page = 'news';
}
}
$page = strtolower($page);
define('PAGE', $page);
$template_place_holders = array(); $template_place_holders = array();
require_once SYSTEM . 'init.php'; require_once SYSTEM . 'init.php';
// verify myaac tables exists in database
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 // event system
require_once SYSTEM . 'hooks.php'; require_once SYSTEM . 'hooks.php';
$hooks = new Hooks(); $hooks = new Hooks();
@ -189,10 +98,7 @@ require_once SYSTEM . 'status.php';
$twig->addGlobal('config', $config); $twig->addGlobal('config', $config);
$twig->addGlobal('status', $status); $twig->addGlobal('status', $status);
// verify myaac tables exists in database require_once SYSTEM . 'router.php';
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.');
}
require SYSTEM . 'migrate.php'; require SYSTEM . 'migrate.php';
@ -242,35 +148,6 @@ if($config['visitors_counter'])
$visitors = new Visitors($config['visitors_counter_ttl']); $visitors = new Visitors($config['visitors_counter_ttl']);
} }
// page content loading
if(!isset($content[0]))
$content = '';
$load_it = true;
// check if site has been closed
$site_closed = false;
if(fetchDatabaseConfig('site_closed', $site_closed)) {
$site_closed = ($site_closed == 1);
if($site_closed) {
if(!admin())
{
$title = getDatabaseConfig('site_closed_title');
$content .= '<p class="note">' . getDatabaseConfig('site_closed_message') . '</p><br/>';
$load_it = false;
}
if(!$logged)
{
ob_start();
require SYSTEM . 'pages/accountmanagement.php';
$content .= ob_get_contents();
ob_end_clean();
$load_it = false;
}
}
}
define('SITE_CLOSED', $site_closed);
// backward support for gesior // backward support for gesior
if($config['backward_support']) { if($config['backward_support']) {
define('INITIALIZED', true); define('INITIALIZED', true);
@ -279,7 +156,6 @@ if($config['backward_support']) {
$layout_name = $template_path; $layout_name = $template_path;
$news_content = ''; $news_content = '';
$tickers_content = ''; $tickers_content = '';
$subtopic = PAGE;
$main_content = ''; $main_content = '';
$config['access_admin_panel'] = 2; $config['access_admin_panel'] = 2;
@ -309,66 +185,14 @@ if($config['backward_support']) {
$config['status']['serverStatus_' . $key] = $value; $config['status']['serverStatus_' . $key] = $value;
} }
if($load_it) /**
{ * @var OTS_Account $account_logged
if(SITE_CLOSED && admin()) */
$content .= '<p class="note">Site is under maintenance (closed mode). Only privileged users can see it.</p>'; if ($logged && admin()) {
$content .= $twig->render('admin-bar.html.twig', [
if($config['backward_support']) 'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()
require SYSTEM . 'compat_pages.php'; ]);
$ignore = false;
$logged_access = 1;
if($logged && $account_logged && $account_logged->isLoaded()) {
$logged_access = $account_logged->getAccess();
} }
$success = false;
$tmp_content = getCustomPage($page, $success);
if($success) {
$content .= $tmp_content;
if(hasFlag(FLAG_CONTENT_PAGES) || superAdmin()) {
$pageInfo = getCustomPageInfo($page);
$content = $twig->render('admin.pages.links.html.twig', array(
'page' => array('id' => $pageInfo !== null ? $pageInfo['id'] : 0, 'hidden' => $pageInfo !== null ? $pageInfo['hidden'] : '0')
)) . $content;
}
} else {
$file = $template_path . '/pages/' . $page . '.php';
if(!@file_exists($file))
{
$file = SYSTEM . 'pages/' . $page . '.php';
if(!@file_exists($file))
{
$page = '404';
$file = SYSTEM . 'pages/404.php';
}
}
}
ob_start();
if($hooks->trigger(HOOK_BEFORE_PAGE)) {
if(!$ignore)
require $file;
}
if($config['backward_support'] && isset($main_content[0]))
$content .= $main_content;
$content .= ob_get_contents();
ob_end_clean();
$hooks->trigger(HOOK_AFTER_PAGE);
}
if($config['backward_support']) {
$main_content = $content;
if(!isset($title))
$title = ucfirst($page);
$topic = $title;
}
$title_full = (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName']; $title_full = (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];
require $template_path . '/' . $template_index; require $template_path . '/' . $template_index;

View File

@ -1,4 +1,4 @@
SET @myaac_database_version = 32; SET @myaac_database_version = 33;
CREATE TABLE `myaac_account_actions` CREATE TABLE `myaac_account_actions`
( (
@ -337,7 +337,7 @@ CREATE TABLE `myaac_spells`
CREATE TABLE `myaac_visitors` CREATE TABLE `myaac_visitors`
( (
`ip` VARCHAR(16) NOT NULL, `ip` VARCHAR(45) NOT NULL,
`lastvisit` INT(11) NOT NULL DEFAULT 0, `lastvisit` INT(11) NOT NULL DEFAULT 0,
`page` VARCHAR(2048) NOT NULL, `page` VARCHAR(2048) NOT NULL,
UNIQUE (`ip`) UNIQUE (`ip`)

View File

@ -2,10 +2,10 @@ We have detected that you don't have access to write to the system/cache directo
<style type="text/css"> <style type="text/css">
.console { .console {
font-family:Courier; font-family: Courier,serif;
color: #CCCCCC; color: #CCCCCC;
background: #000000; background: #000000;
border: 3px double #CCCCCC; border: 3px double #CCCCCC;
padding: 0px; padding: 0;
} }
</style> </style>

View File

@ -70,7 +70,7 @@ if($step == 'database') {
$key = str_replace('var_', '', $key); $key = str_replace('var_', '', $key);
if(in_array($key, array('account', 'password', 'email', 'player_name'))) { if(in_array($key, array('account', 'password', 'password_confirm', 'email', 'player_name'))) {
continue; continue;
} }
@ -122,6 +122,7 @@ else if($step == 'admin') {
else if($step == 'finish') { else if($step == 'finish') {
$email = $_SESSION['var_email']; $email = $_SESSION['var_email'];
$password = $_SESSION['var_password']; $password = $_SESSION['var_password'];
$password_confirm = $_SESSION['var_password_confirm'];
$player_name = $_SESSION['var_player_name']; $player_name = $_SESSION['var_player_name'];
// email check // email check
@ -163,6 +164,9 @@ else if($step == 'finish') {
else if(!Validator::password($password)) { else if(!Validator::password($password)) {
$errors[] = $locale['step_admin_password_error_format']; $errors[] = $locale['step_admin_password_error_format'];
} }
else if($password != $password_confirm) {
$errors[] = $locale['step_admin_password_confirm_error_not_same'];
}
// player name check // player name check
if(empty($player_name)) { if(empty($player_name)) {

View File

@ -7,15 +7,16 @@ $dirs_required = [
'system/cache', 'system/cache',
]; ];
$dirs_optional = [ $dirs_optional = [
'images/guilds' => $locale['step_requirements_warning_images_guilds'], GUILD_IMAGES_DIR => $locale['step_requirements_warning_images_guilds'],
'images/gallery' => $locale['step_requirements_warning_images_gallery'], GALLERY_DIR => $locale['step_requirements_warning_images_gallery'],
]; ];
$extensions_required = [ $extensions_required = [
'json', 'pdo', 'pdo_mysql', 'xml', 'zip' 'pdo', 'pdo_mysql', 'json', 'xml'
]; ];
$extensions_optional = [ $extensions_optional = [
'gd' => $locale['step_requirements_warning_player_signatures'], 'gd' => $locale['step_requirements_warning_player_signatures'],
'zip' => $locale['step_requirements_warning_install_plugins'],
]; ];
/* /*
* *

View File

@ -15,8 +15,7 @@ else {
$password = $_SESSION['var_password']; $password = $_SESSION['var_password'];
$config_salt_enabled = $db->hasColumn('accounts', 'salt'); if(USE_ACCOUNT_SALT)
if($config_salt_enabled)
{ {
$salt = generateRandomString(10, false, true, true); $salt = generateRandomString(10, false, true, true);
$password = $salt . $password; $password = $salt . $password;
@ -75,7 +74,7 @@ else {
$account_used = &$new_account; $account_used = &$new_account;
} }
if($config_salt_enabled) if(USE_ACCOUNT_SALT)
$account_used->setCustomField('salt', $salt); $account_used->setCustomField('salt', $salt);
$account_used->setCustomField('web_flags', FLAG_ADMIN + FLAG_SUPER_ADMIN); $account_used->setCustomField('web_flags', FLAG_ADMIN + FLAG_SUPER_ADMIN);
@ -83,7 +82,7 @@ else {
if($db->hasColumn('accounts', 'group_id')) if($db->hasColumn('accounts', 'group_id'))
$account_used->setCustomField('group_id', $groups->getHighestId()); $account_used->setCustomField('group_id', $groups->getHighestId());
if($db->hasColumn('accounts', 'type')) if($db->hasColumn('accounts', 'type'))
$account_used->setCustomField('type', 5); $account_used->setCustomField('type', 6);
if(!$player_db->isLoaded()) if(!$player_db->isLoaded())
$player->setAccountId($account_used->getId()); $player->setAccountId($account_used->getId());

284
login.php Normal file
View File

@ -0,0 +1,284 @@
<?php
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';
# error function
function sendError($message, $code = 3){
$ret = [];
$ret['errorCode'] = $code;
$ret['errorMessage'] = $message;
die(json_encode($ret));
}
# event schedule function
function parseEvent($table1, $date, $table2)
{
if ($table1) {
if ($date) {
if ($table2) {
$date = $table1->getAttribute('startdate');
return date_create("{$date}")->format('U');
} else {
$date = $table1->getAttribute('enddate');
return date_create("{$date}")->format('U');
}
} else {
foreach($table1 as $attr) {
if ($attr) {
return $attr->getAttribute($table2);
}
}
}
}
return 'error';
}
$request = json_decode(file_get_contents('php://input'));
$action = $request->type ?? '';
/** @var OTS_Base_DB $db */
/** @var array $config */
switch ($action) {
case 'cacheinfo':
$playersonline = $db->query("select count(*) from `players_online`")->fetchAll();
die(json_encode([
'playersonline' => (intval($playersonline[0][0])),
'twitchstreams' => 0,
'twitchviewer' => 0,
'gamingyoutubestreams' => 0,
'gamingyoutubeviewer' => 0
]));
case 'eventschedule':
$eventlist = [];
$file_path = config('server_path') . 'data/XML/events.xml';
if (!file_exists($file_path)) {
die(json_encode([]));
}
$xml = new DOMDocument;
$xml->load($file_path);
$tmplist = [];
$tableevent = $xml->getElementsByTagName('event');
foreach ($tableevent as $event) {
if ($event) { $tmplist = [
'colorlight' => parseEvent($event->getElementsByTagName('colors'), false, 'colorlight'),
'colordark' => parseEvent($event->getElementsByTagName('colors'), false, 'colordark'),
'description' => parseEvent($event->getElementsByTagName('description'), false, 'description'),
'displaypriority' => intval(parseEvent($event->getElementsByTagName('details'), false, 'displaypriority')),
'enddate' => intval(parseEvent($event, true, false)),
'isseasonal' => getBoolean(intval(parseEvent($event->getElementsByTagName('details'), false, 'isseasonal'))),
'name' => $event->getAttribute('name'),
'startdate' => intval(parseEvent($event, true, true)),
'specialevent' => intval(parseEvent($event->getElementsByTagName('details'), false, 'specialevent'))
];
$eventlist[] = $tmplist; } }
die(json_encode(['eventlist' => $eventlist, 'lastupdatetimestamp' => time()]));
case 'boostedcreature':
$boostDB = $db->query("select * from " . $db->tableName('boosted_creature'))->fetchAll();
foreach ($boostDB as $Tableboost) {
die(json_encode([
'boostedcreature' => true,
'raceid' => intval($Tableboost['raceid'])
]));
}
break;
case 'login':
$port = $config['lua']['gameProtocolPort'];
// default world info
$world = [
'id' => 0,
'name' => $config['lua']['serverName'],
'externaladdress' => $config['lua']['ip'],
'externalport' => $port,
'externaladdressprotected' => $config['lua']['ip'],
'externalportprotected' => $port,
'externaladdressunprotected' => $config['lua']['ip'],
'externalportunprotected' => $port,
'previewstate' => 0,
'location' => 'BRA', // BRA, EUR, USA
'anticheatprotection' => false,
'pvptype' => array_search($config['lua']['worldType'], ['pvp', 'no-pvp', 'pvp-enforced']),
'istournamentworld' => false,
'restrictedstore' => false,
'currenttournamentphase' => 2
];
$characters = [];
$account = new OTS_Account();
$inputEmail = $request->email ?? false;
$inputAccountName = $request->accountname ?? false;
$inputToken = $request->token ?? false;
if ($inputEmail != false) { // login by email
$account->findByEmail($request->email);
}
else if($inputAccountName != false) { // login by account name
$account->find($inputAccountName);
}
$current_password = encrypt((USE_ACCOUNT_SALT ? $account->getCustomField('salt') : '') . $request->password);
if (!$account->isLoaded() || $account->getPassword() != $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');
if ($accountSecret != null && $accountSecret != '') {
$accountHasSecret = true;
if ($inputToken === false) {
sendError('Submit a valid two-factor authentication token.', 6);
} else {
require_once LIBS . 'rfc6238.php';
if (TokenAuth6238::verify($accountSecret, $inputToken) !== true) {
sendError('Two-factor authentication failed, token is wrong.', 6);
}
}
}
}
// common columns
$columns = 'id, name, level, sex, vocation, looktype, lookhead, lookbody, looklegs, lookfeet, lookaddons';
if (fieldExist('isreward', 'accounts')) {
$columns .= ', isreward';
}
if (fieldExist('istutorial', 'accounts')) {
$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'];
}
}
foreach ($players as $player) {
$characters[] = create_char($player, $highestLevelId);
}
}
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.");
}
if ($premDays != 0 && $premDays != PHP_INT_MAX) {
if ($lastDay == 0) {
$lastDay = $timeNow;
$save = true;
} else {
$days = (int)(($timeNow - $lastDay) / 86400);
if ($days > 0) {
if ($days >= $premDays) {
$premDays = 0;
$lastDay = 0;
} else {
$premDays -= $days;
$reminder = ($timeNow - $lastDay) % 86400;
$lastDay = $timeNow - $reminder;
}
$save = true;
}
}
} else if ($lastDay != 0) {
$lastDay = 0;
$save = true;
}
if ($save) {
$db->query("update `accounts` set `premdays` = " . $premDays . ", `lastday` = " . $lastDay . " where `id` = " . $account->getId());
}
}
$worlds = [$world];
$playdata = compact('worlds', 'characters');
$sessionKey = ($inputEmail !== false) ? $inputEmail : $inputAccountName; // email or account name
$sessionKey .= "\n" . $request->password; // password
if (!fieldExist('istutorial', 'players')) {
$sessionKey .= "\n";
}
$sessionKey .= ($accountHasSecret && strlen($accountSecret) > 5) ? $inputToken : '';
// this is workaround to distinguish between TFS 1.x and otservbr
// TFS 1.x requires the number in session key
// otservbr requires just login and password
// so we check for istutorial field which is present in otservbr, and not in TFS
if (!fieldExist('istutorial', 'players')) {
$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,
'status' => 'active', // active, frozen or suspended
'returnernotification' => false,
'showrewardnews' => true,
'isreturner' => true,
'fpstracking' => false,
'optiontracking' => false,
'tournamentticketpurchasestate' => 0,
'emailcoderequest' => false
];
die(json_encode(compact('session', 'playdata')));
default:
sendError("Unrecognized event {$action}.");
break;
}
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,
'istournamentparticipant' => false,
'ismaincharacter' => $highestLevelId == $player['id'],
'dailyrewardstate' => isset($player['isreward']) ? intval($player['isreward']) : 0,
'remainingdailytournamentplaytime' => 0
];
}

View File

@ -4,6 +4,9 @@ server {
index index.php; index index.php;
server_name your-domain.com; server_name your-domain.com;
# increase max file upload
client_max_body_size 10M;
location / { location / {
try_files $uri $uri/ /index.php; try_files $uri $uri/ /index.php;
} }
@ -11,7 +14,8 @@ server {
location ~ \.php$ { location ~ \.php$ {
include snippets/fastcgi-php.conf; include snippets/fastcgi-php.conf;
fastcgi_read_timeout 240; fastcgi_read_timeout 240;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
# for ubuntu 22.04+ it will be php8.1-sock
} }
location ~ /\.ht { location ~ /\.ht {

View File

@ -1,3 +1,3 @@
To play on {{ config.lua.serverName }} you need an account. 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.recaptcha_enabled %}, confirm reCAPTCHA{% endif %}{% 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 config.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/> 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

@ -0,0 +1,17 @@
{
"name": "EMail Confirmed Reward",
"description": "Reward users for confirming their E-Mail.",
"version": "1.0",
"author": "MyAAC Authors",
"contact": "www.my-aac.org",
"hooks": {
"mail-confirmed-reward": {
"type": "EMAIL_CONFIRMED",
"file": "plugins/email-confirmed-reward/reward.php"
}
},
"uninstall": [
"plugins/email-confirmed-reward.json",
"plugins/email-confirmed-reward"
]
}

View File

@ -0,0 +1,33 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
$reward = config('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.');
}
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']);
success(sprintf($reward['message'], $reward['premium_points'], 'premium points'));
}
if ($reward['coins'] > 0 && $hasCoinsColumn) {
$account->setCustomField('coins', (int)$account->getCustomField('coins') + $reward['coins']);
success(sprintf($reward['message'], $reward['coins'], 'coins'));
}
if ($reward['premium_days'] > 0) {
$account->setPremDays($account->getPremDays() + $reward['premium_days']);
$account->save();
success(sprintf($reward['message'], $reward['premium_days'], 'premium days'));
}

View File

@ -6,31 +6,38 @@
"author": "nobody", "author": "nobody",
"contact": "nobody@example.org", "contact": "nobody@example.org",
"require": { "require": {
"myaac": "0.4.3", "myaac": "0.9.0",
"myaac_": ">=0.7,<1.0", // support for defining versions like in composer (since 0.8) "myaac_": ">=0.9,<1.0",
"php": "5.2.0", "php": "7.4",
"php_": ">5.4,<7.0", // support for defining versions like in composer (since 0.8) "php_": ">7.4,<8.0",
"database": "21", "database": "21",
"php-ext": "curl", // php extension needs to be installed (since 0.8) "php-ext": "curl",
"ext-curl": ">5.0", // php extension with version specifiec (since 0.8) "ext-curl": ">5.0",
"table": "accounts", // table need to exist in database (since 0.8) "table": "accounts",
"column": "players.online" // column need to exist in database (since 0.8) "column": "players.online"
}, },
"install": "plugins/example/install.php", "install": "plugins/example/install.php",
"uninstall": [ "uninstall": [
"plugins/example.json", "plugins/example.json",
"plugins/example-directory", "plugins/example-directory",
"templates/other-directory" "templates/other-directory"
/***
this is example of multi line comment
1. list example
2. something
****/
], ],
"hooks": { "hooks": {
"Example Hook": { "Example Hook": {
"type": "BEFORE_PAGE", "type": "BEFORE_PAGE",
"file": "plugins/example/before.php" "file": "plugins/example/before.php"
} }
},
"routes": {
"First Route": {
"pattern": "/YourAwesomePage/{name:string}/{page:int}",
"file": "plugins/your-plugin/your-awesome-page.php",
"method": "GET",
"priority": "130"
},
"Redirect Example": {
"redirect_from": "/redirectExample",
"redirect_to": "account/manage"
}
} }
} }

View File

@ -13,16 +13,18 @@ fi
if [ $1 = "prepare" ]; then if [ $1 = "prepare" ]; then
# define release version # define release version
version=`cat VERSION` version=`php system/get_version_for_release.php`
echo "Preparing to release version $version of the MyAAC Project!" echo "Preparing to release version $version of the MyAAC Project!"
# make required directories
mkdir -p releases
mkdir -p tmp
# get myaac from git archive # get myaac from git archive
git archive --format zip --output tmp/myaac.zip master git archive --format zip --output tmp/myaac.zip master
# make required directories cd tmp/ || exit
mkdir -p releases
mkdir -p tmp && cd tmp
dir="myaac-$version" dir="myaac-$version"
if [ -d "$dir" ] ; then if [ -d "$dir" ] ; then
@ -39,9 +41,9 @@ fi
if [ $1 = "pack" ]; then if [ $1 = "pack" ]; then
# define release version # define release version
version=`cat VERSION` version=`php system/get_version_for_release.php`
cd tmp cd tmp || exit
# tar.gz # tar.gz
echo "Creating .tar.gz package.." echo "Creating .tar.gz package.."

View File

@ -76,11 +76,13 @@ $config['clients'] = [
1096, 1096,
1097, 1097,
1098, 1098,
1100, 1100,
1102, 1102,
1140, 1140,
1150, 1150,
1180, 1180,
1200, 1200,
1202, 1202,
1215, 1215,
@ -89,4 +91,12 @@ $config['clients'] = [
1240, 1240,
1251, 1251,
1260, 1260,
1270,
1280,
1285,
1286,
1290,
1291,
1300,
]; ];

15
system/compat/classes.php Normal file
View File

@ -0,0 +1,15 @@
<?php
/**
* Compat classes (backward support for Gesior AAC)
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2022 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
class Player extends OTS_Player {}
class Guild extends OTS_Guild {}
class GuildRank extends OTS_GuildRank {}
class House extends OTS_House {}

View File

@ -10,6 +10,18 @@
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
switch($page) switch($page)
{ {
case 'createaccount':
$page = 'account/create';
break;
case 'accountmanagement':
$page = 'account/manage';
break;
case 'lostaccount':
$page = 'account/lost';
break;
case 'whoisonline': case 'whoisonline':
$page = 'online'; $page = 'online';
break; break;
@ -18,6 +30,10 @@ switch($page)
$page = 'news'; $page = 'news';
break; break;
case 'newsarchive':
$page = 'news/archive';
break;
case 'tibiarules': case 'tibiarules':
$page = 'rules'; $page = 'rules';
break; break;
@ -37,4 +53,3 @@ switch($page)
default: default:
break; break;
} }
?>

View File

@ -39,7 +39,7 @@ function exception_handler($exception) {
// we just replace some values manually // we just replace some values manually
// cause in case Twig throws exception, we can show it too // cause in case Twig throws exception, we can show it too
$content = file_get_contents($template_file); $content = file_get_contents($template_file);
$content = str_replace(array('{{ BASE_URL }}', '{{ message }}', '{{ backtrace }}', '{{ powered_by }}'), array(BASE_URL, $message, $backtrace_formatted, base64_decode('UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vbXktYWFjLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk15QUFDLjwvYT4=')), $content); $content = str_replace(array('{{ BASE_URL }}', '{{ exceptionClass }}', '{{ message }}', '{{ backtrace }}', '{{ powered_by }}'), array(BASE_URL, get_class($exception), $message, $backtrace_formatted, base64_decode('UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vbXktYWFjLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk15QUFDLjwvYT4=')), $content);
echo $content; echo $content;
} }

View File

@ -62,20 +62,20 @@ function getFullLink($page, $name, $blank = false) {
function getLink($page, $action = null) function getLink($page, $action = null)
{ {
$settings = Settings::getInstance(); $settings = Settings::getInstance();
return BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : '?') . $page . ($action ? '/' . $action : ''); return BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : 'index.php/') . $page . ($action ? '/' . $action : '');
} }
function internalLayoutLink($page, $action = null) {return getLink($page, $action);} function internalLayoutLink($page, $action = null) {return getLink($page, $action);}
function getForumThreadLink($thread_id, $page = NULL) function getForumThreadLink($thread_id, $page = NULL)
{ {
$settings = Settings::getInstance(); $settings = Settings::getInstance();
return BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : '?') . 'forum/thread/' . (int)$thread_id . (isset($page) ? '/' . $page : ''); return BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : 'index.php/') . 'forum/thread/' . (int)$thread_id . (isset($page) ? '/' . $page : '');
} }
function getForumBoardLink($board_id, $page = NULL) function getForumBoardLink($board_id, $page = NULL)
{ {
$settings = Settings::getInstance(); $settings = Settings::getInstance();
return BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : '?') . 'forum/board/' . (int)$board_id . (isset($page) ? '/' . $page : ''); return BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : 'index.php/') . 'forum/board/' . (int)$board_id . (isset($page) ? '/' . $page : '');
} }
function getPlayerLink($name, $generate = true) function getPlayerLink($name, $generate = true)
@ -89,7 +89,7 @@ function getPlayerLink($name, $generate = true)
} }
$settings = Settings::getInstance(); $settings = Settings::getInstance();
$url = BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : '?') . 'characters/' . urlencode($name); $url = BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : 'index.php/') . 'characters/' . urlencode($name);
if(!$generate) return $url; if(!$generate) return $url;
return generateLink($url, $name); return generateLink($url, $name);
@ -98,7 +98,7 @@ function getPlayerLink($name, $generate = true)
function getMonsterLink($name, $generate = true) function getMonsterLink($name, $generate = true)
{ {
$settings = Settings::getInstance(); $settings = Settings::getInstance();
$url = BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : '?') . 'creatures/' . urlencode($name); $url = BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : 'index.php/') . 'creatures/' . urlencode($name);
if(!$generate) return $url; if(!$generate) return $url;
return generateLink($url, $name); return generateLink($url, $name);
@ -117,7 +117,7 @@ function getHouseLink($name, $generate = true)
} }
$settings = Settings::getInstance(); $settings = Settings::getInstance();
$url = BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : '?') . 'houses/' . urlencode($name); $url = BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : 'index.php/') . 'houses/' . urlencode($name);
if(!$generate) return $url; if(!$generate) return $url;
return generateLink($url, $name); return generateLink($url, $name);
@ -136,7 +136,7 @@ function getGuildLink($name, $generate = true)
} }
$settings = Settings::getInstance(); $settings = Settings::getInstance();
$url = BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : '?') . 'guilds/' . urlencode($name); $url = BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : 'index.php/') . 'guilds/' . urlencode($name);
if(!$generate) return $url; if(!$generate) return $url;
return generateLink($url, $name); return generateLink($url, $name);
@ -268,6 +268,13 @@ function getForumBoards()
return array(); return array();
} }
// TODO:
// convert forum threads links from just forum/ID
// INTO: forum/thread-name-id, like in XenForo
//function convertForumThreadTitle($title) {
// return str_replace(' ', '-', strtolower($title));
//}
/** /**
* Retrieves data from myaac database config. * Retrieves data from myaac database config.
* *
@ -462,7 +469,7 @@ function tickers()
*/ */
function template_place_holder($type) function template_place_holder($type)
{ {
global $template_place_holders; global $twig, $template_place_holders;
$ret = ''; $ret = '';
if(array_key_exists($type, $template_place_holders) && is_array($template_place_holders[$type])) if(array_key_exists($type, $template_place_holders) && is_array($template_place_holders[$type]))
@ -471,6 +478,9 @@ function template_place_holder($type)
if($type === 'head_start') { if($type === 'head_start') {
$ret .= template_header(); $ret .= template_header();
} }
elseif ($type === 'body_start') {
$ret .= $twig->render('browsehappy.html.twig');
}
elseif($type === 'body_end') { elseif($type === 'body_end') {
$ret .= template_ga_code(); $ret .= template_ga_code();
} }
@ -1034,7 +1044,7 @@ function getTopPlayers($limit = 5) {
$deleted = 'deletion'; $deleted = 'deletion';
$is_tfs10 = $db->hasTable('players_online'); $is_tfs10 = $db->hasTable('players_online');
$players = $db->query('SELECT `id`, `name`, `level`, `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(); $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) { if($is_tfs10) {
foreach($players as &$player) { foreach($players as &$player) {
@ -1151,6 +1161,12 @@ function clearCache()
global $template_name; global $template_name;
if ($cache->fetch('template_ini' . $template_name, $tmp)) if ($cache->fetch('template_ini' . $template_name, $tmp))
$cache->delete('template_ini' . $template_name); $cache->delete('template_ini' . $template_name);
if ($cache->fetch('plugins_hooks', $tmp))
$cache->delete('plugins_hooks');
if ($cache->fetch('plugins_routes', $tmp))
$cache->delete('plugins_routes');
} }
deleteDirectory(CACHE . 'signatures', ['index.html'], true); deleteDirectory(CACHE . 'signatures', ['index.html'], true);
@ -1158,6 +1174,12 @@ function clearCache()
deleteDirectory(CACHE . 'plugins', ['index.html'], true); deleteDirectory(CACHE . 'plugins', ['index.html'], true);
deleteDirectory(CACHE, ['signatures', 'twig', 'plugins', 'index.html'], true); deleteDirectory(CACHE, ['signatures', 'twig', 'plugins', 'index.html'], true);
// routes cache
$routeCacheFile = CACHE . 'route.cache';
if (file_exists($routeCacheFile)) {
unlink($routeCacheFile);
}
return true; return true;
} }
@ -1432,6 +1454,32 @@ function Outfits_loadfromXML()
return array('id' => $looktype, 'type' => $type, 'name' => $lookname, 'premium' => $premium, 'unlocked' => $unlocked, 'enabled' => $enabled); return array('id' => $looktype, 'type' => $type, 'name' => $lookname, 'premium' => $premium, 'unlocked' => $unlocked, 'enabled' => $enabled);
} }
function Mounts_loadfromXML()
{
global $config;
$file_path = $config['data_path'] . 'XML/mounts.xml';
if (!file_exists($file_path)) { return null; }
$xml = new DOMDocument;
$xml->load($file_path);
$mounts = null;
foreach ($xml->getElementsByTagName('mount') as $mount) {
$mounts[] = Mount_parseNode($mount);
}
return $mounts;
}
function Mount_parseNode($node) {
$id = (int)$node->getAttribute('id');
$clientid = (int)$node->getAttribute('clientid');
$name = $node->getAttribute('name');
$speed = (int)$node->getAttribute('speed');
$premium = $node->getAttribute('premium');
$type = $node->getAttribute('type');
return array('id' => $id, 'clientid' => $clientid, 'name' => $name, 'speed' => $speed, 'premium' => $premium, 'type' => $type);
}
function left($str, $length) { function left($str, $length) {
return substr($str, 0, $length); return substr($str, 0, $length);
} }
@ -1473,9 +1521,41 @@ function truncate($string, $length)
return $string; return $string;
} }
function getAccountLoginByLabel()
{
$ret = '';
if (config('account_login_by_email')) {
$ret = 'Email Address';
if (config('account_login_by_email_fallback')) {
$ret .= ' or ';
}
}
if (!config('account_login_by_email') || config('account_login_by_email_fallback')) {
$ret .= 'Account ' . (USE_ACCOUNT_NAME ? 'Name' : 'Number');
}
return $ret;
}
function camelCaseToUnderscore($input)
{
return ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');
}
function removeIfFirstSlash(&$text) {
if(strpos($text, '/') === 0) {
$text = str_replace_first('/', '', $text);
}
};
function escapeHtml($html) {
return htmlentities($html, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
// validator functions // validator functions
require_once LIBS . 'validator.php'; require_once LIBS . 'validator.php';
require_once SYSTEM . 'compat.php'; require_once SYSTEM . 'compat/base.php';
// custom functions // custom functions
require SYSTEM . 'functions_custom.php'; require SYSTEM . 'functions_custom.php';

View File

@ -0,0 +1,6 @@
<?php
require __DIR__ . '/../common.php';
if(IS_CLI) {
echo MYAAC_VERSION;
}

View File

@ -40,7 +40,6 @@ define('HOOK_ACCOUNT_CREATE_AFTER_ACCOUNT', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_EMAIL', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_EMAIL', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_COUNTRY', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_COUNTRY', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_PASSWORDS', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_PASSWORDS', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_RECAPTCHA', ++$i);
define('HOOK_ACCOUNT_CREATE_BEFORE_CHARACTER_NAME', ++$i); define('HOOK_ACCOUNT_CREATE_BEFORE_CHARACTER_NAME', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_CHARACTER_NAME', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_CHARACTER_NAME', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_SEX', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_SEX', ++$i);
@ -48,9 +47,26 @@ define('HOOK_ACCOUNT_CREATE_AFTER_VOCATION', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_TOWNS', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_TOWNS', ++$i);
define('HOOK_ACCOUNT_CREATE_BEFORE_SUBMIT_BUTTON', ++$i); define('HOOK_ACCOUNT_CREATE_BEFORE_SUBMIT_BUTTON', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_FORM', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_FORM', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_SUBMIT', ++$i); define('HOOK_ACCOUNT_CREATE_POST', ++$i);
define('HOOK_FIRST', HOOK_STARTUP); define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i);
define('HOOK_LAST', HOOK_ACCOUNT_CREATE_AFTER_SUBMIT); define('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT', ++$i);
define('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT', ++$i);
define('HOOK_ACCOUNT_LOGIN_AFTER_PASSWORD', ++$i);
define('HOOK_ACCOUNT_LOGIN_AFTER_REMEMBER_ME', ++$i);
define('HOOK_ACCOUNT_LOGIN_AFTER_PAGE', ++$i);
define('HOOK_ACCOUNT_LOGIN_POST', ++$i);
define('HOOK_ADMIN_HEAD_END', ++$i);
define('HOOK_ADMIN_HEAD_START', ++$i);
define('HOOK_ADMIN_BODY_START', ++$i);
define('HOOK_ADMIN_BODY_END', ++$i);
define('HOOK_ADMIN_BEFORE_PAGE', ++$i);
define('HOOK_ADMIN_MENU', ++$i);
define('HOOK_ADMIN_LOGIN_AFTER_ACCOUNT', ++$i);
define('HOOK_ADMIN_LOGIN_AFTER_PASSWORD', ++$i);
define('HOOK_ADMIN_LOGIN_AFTER_SIGN_IN', ++$i);
define('HOOK_EMAIL_CONFIRMED', ++$i);
const HOOK_FIRST = HOOK_STARTUP;
const HOOK_LAST = HOOK_EMAIL_CONFIRMED;
require_once LIBS . 'plugins.php'; require_once LIBS . 'plugins.php';
class Hook class Hook
@ -73,9 +89,7 @@ class Hook
}*/ }*/
global $db, $config, $template_path, $ots, $content, $twig; global $db, $config, $template_path, $ots, $content, $twig;
if(file_exists(BASE . $this->_file)) { $ret = include BASE . $this->_file;
$ret = require BASE . $this->_file;
}
return !isset($ret) || $ret == 1 || $ret; return !isset($ret) || $ret == 1 || $ret;
} }
@ -120,5 +134,7 @@ class Hooks
foreach(Plugins::getHooks() as $hook) { foreach(Plugins::getHooks() as $hook) {
$this->register($hook['name'], $hook['type'], $hook['file']); $this->register($hook['name'], $hook['type'], $hook['file']);
} }
Plugins::clearWarnings();
} }
} }

View File

@ -34,6 +34,10 @@ $cache = Cache::getInstance();
// twig // twig
require_once SYSTEM . 'twig.php'; require_once SYSTEM . 'twig.php';
// action, used by many pages
$action = $_REQUEST['action'] ?? '';
define('ACTION', $action);
// trim values we receive // trim values we receive
if(isset($_POST)) if(isset($_POST))
{ {
@ -138,6 +142,9 @@ if($settingsItemImagesURL['value'][strlen($settingsItemImagesURL['value']) - 1]
} }
define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name')); 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 // load vocation names
$tmp = ''; $tmp = '';
if($cache->enabled() && $cache->fetch('vocations', $tmp)) { if($cache->enabled() && $cache->fetch('vocations', $tmp)) {

View File

@ -12,27 +12,44 @@
class CreateCharacter class CreateCharacter
{ {
/** /**
* @param string $name * @param $name
* @param int $sex * @param $errors
* @param int $vocation
* @param int $town
* @param array $errors
* @return bool * @return bool
*/ */
public function check($name, $sex, &$vocation, &$town, &$errors) { public function checkName($name, &$errors)
{
$minLength = config('character_name_min_length'); $minLength = config('character_name_min_length');
$maxLength = config('character_name_max_length'); $maxLength = config('character_name_max_length');
if(empty($name)) if(empty($name)) {
$errors['name'] = 'Please enter a name for your character!'; $errors['name'] = 'Please enter a name for your character!';
else if(strlen($name) > $maxLength) return false;
}
if(strlen($name) > $maxLength) {
$errors['name'] = 'Name is too long. Max. length <b>' . $maxLength . '</b> letters.'; $errors['name'] = 'Name is too long. Max. length <b>' . $maxLength . '</b> letters.';
else if(strlen($name) < $minLength) return false;
}
if(strlen($name) < $minLength) {
$errors['name'] = 'Name is too short. Min. length <b>' . $minLength . '</b> letters.'; $errors['name'] = 'Name is too short. Min. length <b>' . $minLength . '</b> letters.';
else { return false;
}
$name_length = strlen($name);
if(strspn($name, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM- '") != $name_length) {
$errors['name'] = 'This name contains invalid letters, words or format. Please use only a-Z, - , \' and space.';
return false;
}
if(!preg_match("/[A-z ']/", $name)) {
$errors['name'] = 'Your name contains illegal characters.';
return false;
}
if(!admin() && !Validator::newCharacterName($name)) { if(!admin() && !Validator::newCharacterName($name)) {
$errors['name'] = Validator::getLastError(); $errors['name'] = Validator::getLastError();
} return false;
} }
$player = new OTS_Player(); $player = new OTS_Player();
@ -42,21 +59,39 @@ class CreateCharacter
return false; return false;
} }
if(empty($sex) && $sex != "0") return empty($errors);
}
/**
* @param string $name
* @param int $sex
* @param int $vocation
* @param int $town
* @param array $errors
* @return bool
*/
public function check($name, $sex, &$vocation, &$town, &$errors)
{
$this->checkName($name, $errors);
if(empty($sex) && $sex != "0") {
$errors['sex'] = 'Please select the sex for your character!'; $errors['sex'] = 'Please select the sex for your character!';
}
if(count(config('character_samples')) > 1) if(count(config('character_samples')) > 1)
{ {
if(!isset($vocation)) if(!isset($vocation))
$errors['vocation'] = 'Please select a vocation for your character.'; $errors['vocation'] = 'Please select a vocation for your character.';
} }
else else {
$vocation = config('character_samples')[0]; $vocation = config('character_samples')[0];
}
if(count(config('character_towns')) > 1) { if(count(config('character_towns')) > 1) {
if(!isset($town)) if(!isset($town)) {
$errors['town'] = 'Please select a town for your character.'; $errors['town'] = 'Please select a town for your character.';
} }
}
else { else {
$town = config('character_towns')[0]; $town = config('character_towns')[0];
} }
@ -158,8 +193,14 @@ class CreateCharacter
$player->setManaSpent($char_to_copy->getManaSpent()); $player->setManaSpent($char_to_copy->getManaSpent());
$player->setSoul($char_to_copy->getSoul()); $player->setSoul($char_to_copy->getSoul());
for($skill = POT::SKILL_FIRST; $skill <= POT::SKILL_LAST; $skill++) for($skill = POT::SKILL_FIRST; $skill <= POT::SKILL_LAST; $skill++) {
$player->setSkill($skill, 10); $value = 10;
if (config('use_character_sample_skills')) {
$value = $char_to_copy->getSkill($skill);
}
$player->setSkill($skill, $value);
}
$player->setLookBody($char_to_copy->getLookBody()); $player->setLookBody($char_to_copy->getLookBody());
$player->setLookFeet($char_to_copy->getLookFeet()); $player->setLookFeet($char_to_copy->getLookFeet());
@ -199,16 +240,22 @@ class CreateCharacter
if($db->hasTable('player_skills')) { if($db->hasTable('player_skills')) {
for($i=0; $i<7; $i++) { for($i=0; $i<7; $i++) {
$value = 10;
if (config('use_character_sample_skills')) {
$value = $char_to_copy->getSkill($i);
}
$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` = ' . $i);
if($skillExists->rowCount() <= 0) { if($skillExists->rowCount() <= 0) {
$db->query('INSERT INTO `player_skills` (`player_id`, `skillid`, `value`, `count`) VALUES ('.$player->getId().', '.$i.', 10, 0)'); $db->query('INSERT INTO `player_skills` (`player_id`, `skillid`, `value`, `count`) VALUES ('.$player->getId().', '.$i.', ' . $value . ', 0)');
} }
} }
} }
$loaded_items_to_copy = $db->query("SELECT * FROM player_items WHERE player_id = ".$char_to_copy->getId().""); $loaded_items_to_copy = $db->query("SELECT * FROM player_items WHERE player_id = ".$char_to_copy->getId()."");
foreach($loaded_items_to_copy as $save_item) foreach($loaded_items_to_copy as $save_item) {
$db->query("INSERT INTO `player_items` (`player_id` ,`pid` ,`sid` ,`itemtype`, `count`, `attributes`) VALUES ('".$player->getId()."', '".$save_item['pid']."', '".$save_item['sid']."', '".$save_item['itemtype']."', '".$save_item['count']."', '".$save_item['attributes']."');"); $blob = $db->quote($save_item['attributes']);
$db->query("INSERT INTO `player_items` (`player_id` ,`pid` ,`sid` ,`itemtype`, `count`, `attributes`) VALUES ('".$player->getId()."', '".$save_item['pid']."', '".$save_item['sid']."', '".$save_item['itemtype']."', '".$save_item['count']."', $blob);");
}
global $twig; global $twig;
$twig->display('success.html.twig', array( $twig->display('success.html.twig', array(

View File

@ -11,7 +11,7 @@
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$configForumTablePrefix = config('forum_table_prefix'); $configForumTablePrefix = config('forum_table_prefix');
if(!empty(trim($configForumTablePrefix))) { if(null !== $configForumTablePrefix && !empty(trim($configForumTablePrefix))) {
if(!in_array($configForumTablePrefix, array('myaac_', 'z_'))) { if(!in_array($configForumTablePrefix, array('myaac_', 'z_'))) {
throw new RuntimeException('Invalid value for forum_table_prefix in config.php. Can be only: "myaac_" or "z_".'); throw new RuntimeException('Invalid value for forum_table_prefix in config.php. Can be only: "myaac_" or "z_".');
} }

View File

@ -8,12 +8,12 @@ class News
$errors[] = 'Please fill all inputs.'; $errors[] = 'Please fill all inputs.';
return false; return false;
} }
if(strlen($title) > TITLE_LIMIT) { if(strlen($title) > NEWS_TITLE_LIMIT) {
$errors[] = 'News title cannot be longer than ' . TITLE_LIMIT . ' characters.'; $errors[] = 'News title cannot be longer than ' . NEWS_TITLE_LIMIT . ' characters.';
return false; return false;
} }
if(strlen($body) > BODY_LIMIT) { if(strlen($body) > NEWS_BODY_LIMIT) {
$errors[] = 'News content cannot be longer than ' . BODY_LIMIT . ' characters.'; $errors[] = 'News content cannot be longer than ' . NEWS_BODY_LIMIT . ' characters.';
return false; return false;
} }
if(strlen($article_text) > ARTICLE_TEXT_LIMIT) { if(strlen($article_text) > ARTICLE_TEXT_LIMIT) {

View File

@ -71,12 +71,117 @@ class Plugins {
} }
} }
public static function getRoutes()
{
$cache = Cache::getInstance();
if ($cache->enabled()) {
$tmp = '';
if ($cache->fetch('plugins_routes', $tmp)) {
return unserialize($tmp);
}
}
$routes = [];
foreach(get_plugins() as $filename) {
$string = file_get_contents(PLUGINS . $filename . '.json');
$string = self::removeComments($string);
$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.';
continue;
}
$warningPreTitle = 'Plugin: ' . $filename . ' - ';
if (isset($plugin['routes'])) {
foreach ($plugin['routes'] as $_name => $info) {
// default method: get
$method = $info['method'] ?? ['GET'];
if ($method !== '*') {
$methods = is_string($method) ? explode(',', $info['method']) : $method;
foreach ($methods as $method) {
if (!in_array($method, ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD'])) {
self::$warnings[] = $warningPreTitle . 'Not allowed method ' . $method . '... Disabling this route...';
}
}
}
else {
$methods = '*'; // all available methods
}
if (!isset($info['priority'])) {
$info['priority'] = 100; // default priority
}
if (isset($info['redirect_from'])) {
removeIfFirstSlash($info['redirect_from']);
$info['pattern'] = $info['redirect_from'];
if (!isset($info['redirect_to'])) {
self::$warnings[] = $warningPreTitle . 'redirect set without "redirect_to".';
}
else {
removeIfFirstSlash($info['redirect_to']);
$info['file'] = '__redirect__/' . $info['redirect_to'];
}
}
// replace first occurence of / in pattern if found (will be auto-added later)
removeIfFirstSlash($info['pattern']);
foreach ($routes as $id => &$route) {
if($route[1] == $info['pattern']) {
if($info['priority'] < $route[3]) {
self::$warnings[] = $warningPreTitle . "Duplicated route with lower priority: {$info['pattern']}. Disabling this route...";
continue 2;
}
else {
self::$warnings[] = $warningPreTitle . "Duplicated route with lower priority: {$route[1]} ({$route[3]}). Disabling this route...";
unset($routes[$id]);
}
}
}
$routes[] = [$methods, $info['pattern'], $info['file'], $info['priority']];
}
}
}
/*
usort($routes, function ($a, $b)
{
// key 3 is priority
if ($a[3] == $b[3]) {
return 0;
}
return ($a[3] > $b[3]) ? -1 : 1;
});
*/
// cleanup before passing back
// priority is not needed anymore
foreach ($routes as &$route) {
unset($route[3]);
}
if ($cache->enabled()) {
$cache->set('plugins_routes', serialize($routes), 600);
}
return $routes;
}
public static function getHooks() public static function getHooks()
{ {
$cache = Cache::getInstance(); $cache = Cache::getInstance();
if ($cache->enabled()) { if ($cache->enabled()) {
$tmp = ''; $tmp = '';
if ($cache->fetch('hooks', $tmp)) { if ($cache->fetch('plugins_hooks', $tmp)) {
return unserialize($tmp); return unserialize($tmp);
} }
} }
@ -96,7 +201,7 @@ class Plugins {
} }
if ($cache->enabled()) { if ($cache->enabled()) {
$cache->set('hooks', serialize($hooks), 600); $cache->set('plugins_hooks', serialize($hooks), 600);
} }
return $hooks; return $hooks;
@ -259,29 +364,61 @@ class Plugins {
} }
if(in_array($req, array('php-ext', 'php-extension'))) { // require php extension if(in_array($req, array('php-ext', 'php-extension'))) { // require php extension
if(!extension_loaded($version)) { $tmpDisplayError = false;
self::$error = "This plugin requires php extension: " . $version . " to be installed."; $explode = explode(',', $version);
foreach ($explode as $item) {
if(!extension_loaded($item)) {
$errors[] = "This plugin requires php extension: " . $item . " to be installed.";
$tmpDisplayError = true;
}
}
if ($tmpDisplayError) {
self::$error = implode('<br/>', $errors);
$continue = false; $continue = false;
break; break;
} }
} }
else if($req == 'table') { else if($req == 'table') {
if(!$db->hasTable($version)) { $tmpDisplayError = false;
self::$error = "This plugin requires table: " . $version . " to exist in the database."; $explode = explode(',', $version);
foreach ($explode as $item) {
if(!$db->hasTable($item)) {
$errors[] = "This plugin requires table: " . $item . " to exist in the database.";
$tmpDisplayError = true;
}
}
if ($tmpDisplayError) {
self::$error = implode('<br/>', $errors);
$continue = false; $continue = false;
break; break;
} }
} }
else if($req == 'column') { else if($req == 'column') {
$tmp = explode('.', $version); $tmpDisplayError = false;
$explode = explode(',', $version);
foreach ($explode as $item) {
$tmp = explode('.', $item);
if(count($tmp) == 2) { if(count($tmp) == 2) {
if(!$db->hasColumn($tmp[0], $tmp[1])) { if(!$db->hasColumn($tmp[0], $tmp[1])) {
self::$error = "This plugin requires database column: " . $tmp[0] . "." . $tmp[1] . " to exist in database."; $errors[] = "This plugin requires database column: " . $tmp[0] . "." . $tmp[1] . " to exist in database.";
$tmpDisplayError = true;
}
}
else {
self::$warnings[] = "Invalid plugin require column: " . $item;
}
}
if ($tmpDisplayError) {
self::$error = implode('<br/>', $errors);
$continue = false; $continue = false;
break; break;
} }
} }
}
else if(strpos($req, 'ext-') !== false) { else if(strpos($req, 'ext-') !== false) {
$tmp = explode('-', $req); $tmp = explode('-', $req);
if(count($tmp) == 2) { if(count($tmp) == 2) {
@ -412,6 +549,10 @@ class Plugins {
return self::$warnings; return self::$warnings;
} }
public static function clearWarnings() {
self::$warnings = [];
}
public static function getError() { public static function getError() {
return self::$error; return self::$error;
} }

View File

@ -101,6 +101,37 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
return $name; return $name;
} }
/**
* @param $email
* @return mixed
* @throws Exception
*/
public function createWithEmail($email = null)
{
// if name is not passed then it will be generated randomly
if( !isset($email) )
{
throw new Exception(__CLASS__ . ':' . __METHOD__ . ' createWithEmail called without e-mail.');
}
// repeats until name is unique
do
{
$name = uniqid();
$query = $this->db->query('SELECT `id` FROM `accounts` WHERE `name` = ' . $this->db->quote($name));
} while($query->rowCount() >= 1);
// saves blank account info
$this->db->exec('INSERT INTO `accounts` (`name`, `password`, `email`, `created`) VALUES (' . $this->db->quote($name) . ', ' . '\'\', ' . $this->db->quote($email) . ', ' . time() . ')');
// reads created account's ID
$this->data['id'] = $this->db->lastInsertId();
$this->data['name'] = $name;
// return name of newly created account
return $name;
}
/** /**
* Creates new account. * Creates new account.
* *
@ -138,11 +169,32 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
*/ */
public function create($name = NULL, $id = NULL) public function create($name = NULL, $id = NULL)
{ {
// saves blank account info if(isset($name)) {
$this->db->exec('INSERT INTO `accounts` (' . (isset($id) ? '`id`,' : '') . (isset($name) ? '`name`,' : '') . '`password`, `email`, `created`) VALUES (' . (isset($id) ? $id . ',' : '') . (isset($name) ? $this->db->quote($name) . ',' : '') . ' \'\', \'\',' . time() . ')'); $nameOrNumber = 'name';
$nameOrNumberValue = $name;
}
else {
if (USE_ACCOUNT_NUMBER) {
$nameOrNumber = 'number';
$nameOrNumberValue = $id;
$id = null;
}
else {
$nameOrNumber = null;
}
}
if(isset($name)) // saves blank account info
$this->db->exec('INSERT INTO `accounts` (' . (isset($id) ? '`id`,' : '') . (isset($nameOrNumber) ? '`' . $nameOrNumber . '`,' : '') . '`password`, `email`, `created`) VALUES (' . (isset($id) ? $id . ',' : '') . (isset($nameOrNumber) ? $this->db->quote($nameOrNumberValue) . ',' : '') . ' \'\', \'\',' . time() . ')');
if(isset($name)) {
$this->data['name'] = $name; $this->data['name'] = $name;
}
else {
if (USE_ACCOUNT_NUMBER) {
$this->data['number'] = $name;
}
}
$lastInsertId = $this->db->lastInsertId(); $lastInsertId = $this->db->lastInsertId();
if($lastInsertId != 0) { if($lastInsertId != 0) {
@ -179,15 +231,26 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @param int $id Account number. * @param int $id Account number.
* @throws PDOException On PDO operation error. * @throws PDOException On PDO operation error.
*/ */
public function load($id, $fresh = false) public function load($id, $fresh = false, $searchOnlyById = false)
{ {
if(!$fresh && isset(self::$cache[$id])) { if(!$fresh && isset(self::$cache[$id])) {
$this->data = self::$cache[$id]; $this->data = self::$cache[$id];
return; return;
} }
$numberColumn = 'id';
$nameOrNumber = '';
if (!$searchOnlyById) {
if (USE_ACCOUNT_NAME) {
$nameOrNumber = '`name`,';
} else if (USE_ACCOUNT_NUMBER) {
$nameOrNumber = '`number`,';
$numberColumn = 'number';
}
}
// SELECT query on database // SELECT query on database
$this->data = $this->db->query('SELECT `id`, ' . ($this->db->hasColumn('accounts', 'name') ? '`name`,' : '') . '`password`, `email`, `blocked`, `rlname`, `location`, `country`, `web_flags`, ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays`, ' : '') . ($this->db->hasColumn('accounts', 'lastday') ? '`lastday`, ' : ($this->db->hasColumn('accounts', 'premend') ? '`premend`,' : ($this->db->hasColumn('accounts', 'premium_ends_at') ? '`premium_ends_at`,' : ''))) . '`created` FROM `accounts` WHERE `id` = ' . (int) $id)->fetch(); $this->data = $this->db->query('SELECT `id`, ' . $nameOrNumber . '`password`, `email`, `blocked`, `rlname`, `location`, `country`, `web_flags`, ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays`, ' : '') . ($this->db->hasColumn('accounts', 'lastday') ? '`lastday`, ' : ($this->db->hasColumn('accounts', 'premend') ? '`premend`,' : ($this->db->hasColumn('accounts', 'premium_ends_at') ? '`premium_ends_at`,' : ''))) . '`created` FROM `accounts` WHERE `' . $numberColumn . '` = ' . (int) $id)->fetch();
self::$cache[$id] = $this->data; self::$cache[$id] = $this->data;
} }
@ -306,6 +369,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
return $this->data['id']; return $this->data['id'];
} }
public function getNumber()
{
if (isset($this->data['number'])) {
return $this->data['number'];
}
return $this->data['id'];
}
public function getRLName() public function getRLName()
{ {
if( !isset($this->data['rlname']) ) if( !isset($this->data['rlname']) )
@ -1019,6 +1091,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error. * @throws PDOException On PDO operation error.
* @return Iterator List of players. * @return Iterator List of players.
*/ */
#[\ReturnTypeWillChange]
public function getIterator() public function getIterator()
{ {
return $this->getPlayersList(); return $this->getPlayersList();
@ -1033,7 +1106,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error. * @throws PDOException On PDO operation error.
* @return int Count of players. * @return int Count of players.
*/ */
public function count() public function count(): int
{ {
return $this->getPlayersList()->count(); return $this->getPlayersList()->count();
} }

View File

@ -83,36 +83,49 @@ abstract class OTS_Base_DB extends PDO implements IOTS_DB
$startTime = microtime(true); $startTime = microtime(true);
} }
$ret = parent::query(...$args);; $ret = parent::query(...$args);
if($this->logged) { if($this->logged) {
$totalTime = microtime(true) - $startTime; $totalTime = microtime(true) - $startTime;
$this->log .= round($totalTime, 4) . ' ms - ' . $query . PHP_EOL; $this->log .= round($totalTime, 4) . ' ms - ' . $args[0] . PHP_EOL;
} }
return $ret; return $ret;
} }
public function select($table, $where, $limit = null) public function select($table, $where = [], $limit = null)
{ {
$fields = array_keys($where); $fields = array_keys($where);
$values = array_values($where); $values = array_values($where);
$query = 'SELECT * FROM ' . $this->tableName($table) . ' WHERE ('; $query = 'SELECT * FROM ' . $this->tableName($table);
if (!empty($where)) {
$query .= ' WHERE (';
$count = count($fields); $count = count($fields);
for ($i = 0; $i < $count; $i++) for ($i = 0; $i < $count; $i++) {
$query .= $this->fieldName($fields[$i]) . ' = ' . $this->quote($values[$i]) . ' AND '; $query .= $this->fieldName($fields[$i]) . ' = ' . $this->quote($values[$i]) . ' AND ';
}
$query = substr($query, 0, -4); $query = substr($query, 0, -4);
$query .= ')';
}
if (isset($limit)) if (isset($limit))
$query .=') LIMIT '.$limit.';'; $query .=' LIMIT '.$limit.';';
else else
$query .=');'; $query .=';';
$query = $this->query($query); $query = $this->query($query);
if($query->rowCount() != 1) return false; $rowCount = $query->rowCount();
if ($rowCount <= 0) return false;
else if ($rowCount == 1) {
return $query->fetch(); return $query->fetch();
} }
return $query->fetchAll();
}
public function insert($table, $data) public function insert($table, $data)
{ {
$fields = array_keys($data); $fields = array_keys($data);

View File

@ -190,6 +190,7 @@ abstract class OTS_Base_List implements IOTS_DAO, Iterator, Countable
* @version 0.1.3 * @version 0.1.3
* @return OTS_Base_DAO Current row. * @return OTS_Base_DAO Current row.
*/ */
#[\ReturnTypeWillChange]
public function current() public function current()
{ {
$id = current($this->rows); $id = current($this->rows);
@ -203,7 +204,7 @@ abstract class OTS_Base_List implements IOTS_DAO, Iterator, Countable
* *
* @throws PDOException On PDO operation error. * @throws PDOException On PDO operation error.
*/ */
public function rewind() public function rewind(): void
{ {
$this->rows = $this->db->query( $this->getSQL() )->fetchAll(); $this->rows = $this->db->query( $this->getSQL() )->fetchAll();
} }
@ -211,7 +212,7 @@ abstract class OTS_Base_List implements IOTS_DAO, Iterator, Countable
/** /**
* Moves to next row. * Moves to next row.
*/ */
public function next() public function next(): void
{ {
next($this->rows); next($this->rows);
} }
@ -221,6 +222,7 @@ abstract class OTS_Base_List implements IOTS_DAO, Iterator, Countable
* *
* @return mixed Array key. * @return mixed Array key.
*/ */
#[\ReturnTypeWillChange]
public function key() public function key()
{ {
return key($this->rows); return key($this->rows);
@ -231,7 +233,7 @@ abstract class OTS_Base_List implements IOTS_DAO, Iterator, Countable
* *
* @return bool Does next row exist. * @return bool Does next row exist.
*/ */
public function valid() public function valid(): bool
{ {
return key($this->rows) !== null; return key($this->rows) !== null;
} }
@ -243,7 +245,7 @@ abstract class OTS_Base_List implements IOTS_DAO, Iterator, Countable
* @return int Number of rows. * @return int Number of rows.
* @throws PDOException On PDO operation error. * @throws PDOException On PDO operation error.
*/ */
public function count() public function count(): int
{ {
return $this->db->query( $this->getSQL(true) )->fetchColumn(); return $this->db->query( $this->getSQL(true) )->fetchColumn();
} }

View File

@ -73,7 +73,7 @@ class OTS_Container extends OTS_Item implements IteratorAggregate
* *
* @return int Number of items. * @return int Number of items.
*/ */
public function count() public function count(): int
{ {
return count($items); return count($items);
} }

View File

@ -6,7 +6,7 @@ if (PHP_VERSION_ID >= 80000) {
/** /**
* @return PDOStatement * @return PDOStatement
*/ */
public function query(?string $query = null, ?int $fetchMode = null, mixed ...$fetchModeArgs) public function query(?string $query = null, ?int $fetchMode = null, mixed ...$fetchModeArgs): PDOStatement
{ {
return $this->doQuery($query, $fetchMode, ...$fetchModeArgs); return $this->doQuery($query, $fetchMode, ...$fetchModeArgs);
} }

View File

@ -538,6 +538,7 @@ class OTS_Group extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error. * @throws PDOException On PDO operation error.
* @return Iterator List of players. * @return Iterator List of players.
*/ */
#[\ReturnTypeWillChange]
public function getIterator() public function getIterator()
{ {
return $this->getPlayersList(); return $this->getPlayersList();
@ -552,7 +553,7 @@ class OTS_Group extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error. * @throws PDOException On PDO operation error.
* @return int Count of players. * @return int Count of players.
*/ */
public function count() public function count(): int
{ {
return $this->getPlayersList()->count(); return $this->getPlayersList()->count();
} }

View File

@ -196,6 +196,7 @@ class OTS_Groups_List implements IteratorAggregate, Countable
* @since 0.1.5 * @since 0.1.5
* @return AppendIterator Iterator for all groups. * @return AppendIterator Iterator for all groups.
*/ */
#[\ReturnTypeWillChange]
public function getIterator() public function getIterator()
{ {
$iterator = new AppendIterator(); $iterator = new AppendIterator();
@ -210,7 +211,7 @@ class OTS_Groups_List implements IteratorAggregate, Countable
* @since 0.1.5 * @since 0.1.5
* @return int Amount of all groups. * @return int Amount of all groups.
*/ */
public function count() public function count(): int
{ {
return count($this->groups); return count($this->groups);
} }

View File

@ -709,6 +709,7 @@ class OTS_Guild extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error. * @throws PDOException On PDO operation error.
* @return Iterator List of ranks. * @return Iterator List of ranks.
*/ */
#[\ReturnTypeWillChange]
public function getIterator() public function getIterator()
{ {
return $this->getGuildRanksList(); return $this->getGuildRanksList();
@ -723,7 +724,7 @@ class OTS_Guild extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error. * @throws PDOException On PDO operation error.
* @return int Count of ranks. * @return int Count of ranks.
*/ */
public function count() public function count(): int
{ {
return $this->getGuildRanksList()->count(); return $this->getGuildRanksList()->count();
} }

View File

@ -396,6 +396,7 @@ class OTS_GuildRank extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error. * @throws PDOException On PDO operation error.
* @return Iterator List of players. * @return Iterator List of players.
*/ */
#[\ReturnTypeWillChange]
public function getIterator() public function getIterator()
{ {
return $this->getPlayersList(); return $this->getPlayersList();
@ -410,7 +411,7 @@ class OTS_GuildRank extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error. * @throws PDOException On PDO operation error.
* @return int Count of players. * @return int Count of players.
*/ */
public function count() public function count(): int
{ {
return $this->getPlayersList()->count(); return $this->getPlayersList()->count();
} }

View File

@ -150,7 +150,7 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
* *
* @return int Count of houses. * @return int Count of houses.
*/ */
public function count() public function count(): int
{ {
return count($this->houses); return count($this->houses);
} }

View File

@ -128,7 +128,7 @@ class OTS_Item implements Countable
* *
* @return int Count of item. * @return int Count of item.
*/ */
public function count() public function count(): int
{ {
return $this->count; return $this->count;
} }

View File

@ -500,7 +500,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
* *
* @return int Count of types. * @return int Count of types.
*/ */
public function count() public function count(): int
{ {
return count($this->items); return count($this->items);
} }

View File

@ -163,7 +163,7 @@ class OTS_MonstersList implements Iterator, Countable, ArrayAccess
* *
* @return int Count of monsters. * @return int Count of monsters.
*/ */
public function count() public function count(): int
{ {
return count($this->monsters); return count($this->monsters);
} }

View File

@ -630,7 +630,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
* @since 0.0.8 * @since 0.0.8
* @return int Count of towns. * @return int Count of towns.
*/ */
public function count() public function count(): int
{ {
return count($this->towns); return count($this->towns);
} }

View File

@ -602,7 +602,7 @@ class OTS_Player extends OTS_Row_DAO
} }
$account = new OTS_Account(); $account = new OTS_Account();
$account->load($this->data['account_id']); $account->load($this->data['account_id'], false, true);
return $account; return $account;
} }
@ -2489,7 +2489,7 @@ class OTS_Player extends OTS_Row_DAO
$value = $this->db->query('SELECT ' . $this->db->fieldName('value') . ' FROM ' . $this->db->tableName('player_storage') . ' WHERE ' . $this->db->fieldName('key') . ' = ' . (int) $key . ' AND ' . $this->db->fieldName('player_id') . ' = ' . $this->data['id'])->fetch(); $value = $this->db->query('SELECT ' . $this->db->fieldName('value') . ' FROM ' . $this->db->tableName('player_storage') . ' WHERE ' . $this->db->fieldName('key') . ' = ' . (int) $key . ' AND ' . $this->db->fieldName('player_id') . ' = ' . $this->data['id'])->fetch();
if($value !== false) if($value === false)
{ {
return null; return null;
} }

View File

@ -324,7 +324,7 @@ class OTS_SpellsList implements IteratorAggregate, Countable
* @since 0.1.5 * @since 0.1.5
* @return int Amount of all spells. * @return int Amount of all spells.
*/ */
public function count() public function count(): int
{ {
return count($this->runes) + count($this->instants) + count($this->conjures); return count($this->runes) + count($this->instants) + count($this->conjures);
} }

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