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)) {
$page = '404'; if (strpos($page, 'plugins/') !== false) {
$file = SYSTEM . 'pages/404.php'; $file = BASE . $page;
}
else {
$page = '404';
$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">';
@ -63,4 +59,4 @@ if (isset($configAdminPanelModules)) {
} }
} }
echo '</div>'; echo '</div>';
} }

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,31 +176,36 @@ 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', array(
array( 'name' => $name,
'name' => $name, 'title' => $title,
'title' => $title, 'body' => $body,
'body' => $body, 'player_id' => $player_id,
'player_id' => $player_id, 'php' => $php ? '1' : '0',
'php' => $php ? '1' : '0', 'enable_tinymce' => $enable_tinymce ? '1' : '0',
'enable_tinymce' => $enable_tinymce ? '1' : '0', 'access' => $access
'access' => $access )
) );
); 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));
}
else {
$tmp = explode('.', $uri);
}
if(preg_match("/^[A-Za-z0-9-_%'+]+\.png$/i", $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

@ -1,25 +1,29 @@
server { server {
listen 80; listen 80;
root /home/otserv/www/public; root /home/otserv/www/public;
index index.php; index index.php;
server_name your-domain.com; server_name your-domain.com;
location / { # increase max file upload
try_files $uri $uri/ /index.php; client_max_body_size 10M;
}
location ~ \.php$ { location / {
include snippets/fastcgi-php.conf; try_files $uri $uri/ /index.php;
fastcgi_read_timeout 240; }
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
location ~ /\.ht { location ~ \.php$ {
deny all; include snippets/fastcgi-php.conf;
} fastcgi_read_timeout 240;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
# for ubuntu 22.04+ it will be php8.1-sock
}
location /system { location ~ /\.ht {
deny all; deny all;
return 404; }
}
location /system {
deny all;
return 404;
}
} }

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;
$errors['name'] = 'Name is too long. Max. length <b>'.$maxLength.'</b> letters.'; }
else if(strlen($name) < $minLength)
$errors['name'] = 'Name is too short. Min. length <b>'.$minLength.'</b> letters.'; if(strlen($name) > $maxLength) {
else { $errors['name'] = 'Name is too long. Max. length <b>' . $maxLength . '</b> letters.';
if(!admin() && !Validator::newCharacterName($name)) { return false;
$errors['name'] = Validator::getLastError(); }
}
if(strlen($name) < $minLength) {
$errors['name'] = 'Name is too short. Min. length <b>' . $minLength . '</b> letters.';
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)) {
$errors['name'] = Validator::getLastError();
return false;
} }
$player = new OTS_Player(); $player = new OTS_Player();
@ -42,20 +59,38 @@ 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_".');
} }
@ -322,4 +322,4 @@ class Forum
return $hasAccess; return $hasAccess;
} }
} }
?> ?>

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) {
@ -138,4 +138,4 @@ class News
} }
} }
} }
} }

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,27 +364,59 @@ 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;
if(count($tmp) == 2) { $explode = explode(',', $version);
if(!$db->hasColumn($tmp[0], $tmp[1])) { foreach ($explode as $item) {
self::$error = "This plugin requires database column: " . $tmp[0] . "." . $tmp[1] . " to exist in database."; $tmp = explode('.', $item);
$continue = false;
break; if(count($tmp) == 2) {
if(!$db->hasColumn($tmp[0], $tmp[1])) {
$errors[] = "This plugin requires database column: " . $tmp[0] . "." . $tmp[1] . " to exist in database.";
$tmpDisplayError = true;
}
} }
else {
self::$warnings[] = "Invalid plugin require column: " . $item;
}
}
if ($tmpDisplayError) {
self::$error = implode('<br/>', $errors);
$continue = false;
break;
} }
} }
else if(strpos($req, 'ext-') !== false) { else if(strpos($req, 'ext-') !== false) {
@ -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,34 +83,47 @@ 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);
$count = count($fields); if (!empty($where)) {
for ($i = 0; $i < $count; $i++) $query .= ' WHERE (';
$query.= $this->fieldName($fields[$i]).' = '.$this->quote($values[$i]).' AND ';
$count = count($fields);
for ($i = 0; $i < $count; $i++) {
$query .= $this->fieldName($fields[$i]) . ' = ' . $this->quote($values[$i]) . ' AND ';
}
$query = substr($query, 0, -4);
$query .= ')';
}
$query = substr($query, 0, -4);
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();
return $query->fetch(); if ($rowCount <= 0) return false;
else if ($rowCount == 1) {
return $query->fetch();
}
return $query->fetchAll();
} }
public function insert($table, $data) public function insert($table, $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

@ -15,11 +15,11 @@
/** /**
* Container item representation. * Container item representation.
* *
* <p> * <p>
* This class represents items that can contain other items. It's {@link OTS_Container::count() count() method} has been overwritten so it now doesn't return count of current item (if it would even be possible for containers) but amount of items within (not recursively). * This class represents items that can contain other items. It's {@link OTS_Container::count() count() method} has been overwritten so it now doesn't return count of current item (if it would even be possible for containers) but amount of items within (not recursively).
* </p> * </p>
* *
* @package POT * @package POT
* @version 0.1.3 * @version 0.1.3
*/ */
@ -27,14 +27,14 @@ class OTS_Container extends OTS_Item implements IteratorAggregate
{ {
/** /**
* Contained items. * Contained items.
* *
* @var array * @var array
*/ */
private $items = array(); private $items = array();
/** /**
* Adds item to container. * Adds item to container.
* *
* @param OTS_Item $item Item. * @param OTS_Item $item Item.
*/ */
public function addItem(OTS_Item $item) public function addItem(OTS_Item $item)
@ -44,11 +44,11 @@ class OTS_Container extends OTS_Item implements IteratorAggregate
/** /**
* Removes given item from current container. * Removes given item from current container.
* *
* <p> * <p>
* Passed item must be exacly instance of item which is stored in container, not it's copy. This method bases on PHP references. * Passed item must be exacly instance of item which is stored in container, not it's copy. This method bases on PHP references.
* </p> * </p>
* *
* @param OTS_Item $item Item. * @param OTS_Item $item Item.
* @tutorial POT/Players.pkg#deleting * @tutorial POT/Players.pkg#deleting
*/ */
@ -66,14 +66,14 @@ class OTS_Container extends OTS_Item implements IteratorAggregate
/** /**
* Number of items inside container. * Number of items inside container.
* *
* <p> * <p>
* OTS_Container implementation of Countable interface differs from {@link OTS_Item OTS_Item} implemention. {@link OTS_Item::count() OTS_Item::count()} returns count of given item, OTS_Container::count() returns number of items inside container. If somehow it would be possible to make container items with more then 1 in one place, you can use {@link OTS_Item::getCount() OTS_Item::getCount()} and {@link OTS_Item::setCount() OTS_Item::setCount()} in code where you are not sure if working with regular item, or container. * OTS_Container implementation of Countable interface differs from {@link OTS_Item OTS_Item} implemention. {@link OTS_Item::count() OTS_Item::count()} returns count of given item, OTS_Container::count() returns number of items inside container. If somehow it would be possible to make container items with more then 1 in one place, you can use {@link OTS_Item::getCount() OTS_Item::getCount()} and {@link OTS_Item::setCount() OTS_Item::setCount()} in code where you are not sure if working with regular item, or container.
* </p> * </p>
* *
* @return int Number of items. * @return int Number of items.
*/ */
public function count() public function count(): int
{ {
return count($items); return count($items);
} }
@ -123,7 +123,7 @@ class OTS_Container extends OTS_Item implements IteratorAggregate
/** /**
* Returns iterator handle for loops. * Returns iterator handle for loops.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @return ArrayIterator Items iterator. * @return ArrayIterator Items iterator.
@ -135,7 +135,7 @@ class OTS_Container extends OTS_Item implements IteratorAggregate
/** /**
* Clones all contained items. * Clones all contained items.
* *
* @version 0.1.3 * @version 0.1.3
* @since 0.1.3 * @since 0.1.3
*/ */

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

@ -41,7 +41,7 @@ class OTS_Groups_List implements IteratorAggregate, Countable
$info['access'] = $group['name']; $info['access'] = $group['name'];
$this->groups[$group['id']] = new OTS_Group($info); $this->groups[$group['id']] = new OTS_Group($info);
} }
return; return;
} }
@ -50,7 +50,7 @@ class OTS_Groups_List implements IteratorAggregate, Countable
global $config; global $config;
$file = $config['data_path'] . 'XML/groups.xml'; $file = $config['data_path'] . 'XML/groups.xml';
} }
if(!@file_exists($file)) { if(!@file_exists($file)) {
error('Error: Cannot load groups.xml. More info in system/logs/error.log file.'); error('Error: Cannot load groups.xml. More info in system/logs/error.log file.');
log_append('error.log', '[OTS_Groups_List.php] Fatal error: Cannot load groups.xml (' . $file . '). It doesnt exist.'); log_append('error.log', '[OTS_Groups_List.php] Fatal error: Cannot load groups.xml (' . $file . '). It doesnt exist.');
@ -99,7 +99,7 @@ class OTS_Groups_List implements IteratorAggregate, Countable
log_append('error.log', '[OTS_Groups_List.php] Fatal error: Cannot load groups.xml (' . $file . '). Error: ' . print_r(error_get_last(), true)); log_append('error.log', '[OTS_Groups_List.php] Fatal error: Cannot load groups.xml (' . $file . '). Error: ' . print_r(error_get_last(), true));
return; return;
} }
// loads groups // loads groups
foreach($groups->getElementsByTagName('group') as $group) foreach($groups->getElementsByTagName('group') as $group)
{ {
@ -157,7 +157,7 @@ class OTS_Groups_List implements IteratorAggregate, Countable
if($id > $group_id) if($id > $group_id)
$group_id = $id; $group_id = $id;
} }
return $group_id; return $group_id;
} }
@ -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

@ -15,7 +15,7 @@
/** /**
* Wrapper for houses list. * Wrapper for houses list.
* *
* @package POT * @package POT
* @version 0.1.3 * @version 0.1.3
* @tutorial POT/data_directory.pkg#towns.houses * @tutorial POT/data_directory.pkg#towns.houses
@ -24,14 +24,14 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
{ {
/** /**
* List of houses elements. * List of houses elements.
* *
* @var array * @var array
*/ */
private $houses = array(); private $houses = array();
/** /**
* Loads houses information. * Loads houses information.
* *
* @version 0.1.3 * @version 0.1.3
* @param string $path Houses file. * @param string $path Houses file.
* @throws DOMException On DOM operation error. * @throws DOMException On DOM operation error.
@ -49,11 +49,11 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/** /**
* Magic PHP5 method. * Magic PHP5 method.
* *
* <p> * <p>
* Allows object importing from {@link http://www.php.net/manual/en/function.var-export.php var_export()}. * Allows object importing from {@link http://www.php.net/manual/en/function.var-export.php var_export()}.
* </p> * </p>
* *
* @param array $properties List of object properties. * @param array $properties List of object properties.
* @throws DOMException On DOM operation error. * @throws DOMException On DOM operation error.
*/ */
@ -72,7 +72,7 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/** /**
* Checks if given house exists on list. * Checks if given house exists on list.
* *
* @version 0.1.3 * @version 0.1.3
* @since 0.1.3 * @since 0.1.3
* @param string $name Name. * @param string $name Name.
@ -94,7 +94,7 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/** /**
* Returns house information. * Returns house information.
* *
* @version 0.1.3 * @version 0.1.3
* @param int $id House ID. * @param int $id House ID.
* @return OTS_House House information wrapper. * @return OTS_House House information wrapper.
@ -112,7 +112,7 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/** /**
* Checks if given house ID exists on list. * Checks if given house ID exists on list.
* *
* @version 0.1.3 * @version 0.1.3
* @since 0.1.3 * @since 0.1.3
* @param int $id ID. * @param int $id ID.
@ -125,7 +125,7 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/** /**
* Returns ID of house with given name. * Returns ID of house with given name.
* *
* @version 0.1.3 * @version 0.1.3
* @param string $name House name. * @param string $name House name.
* @return int House ID. * @return int House ID.
@ -147,17 +147,17 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/** /**
* Returns amount of houses. * Returns amount of houses.
* *
* @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);
} }
/** /**
* Returns iterator handle for loops. * Returns iterator handle for loops.
* *
* @return ArrayIterator Houses list iterator. * @return ArrayIterator Houses list iterator.
*/ */
public function getIterator() public function getIterator()
@ -167,7 +167,7 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/** /**
* Checks if given element exists. * Checks if given element exists.
* *
* @param string|int $offset Array key. * @param string|int $offset Array key.
* @return bool True if it's set. * @return bool True if it's set.
*/ */
@ -185,7 +185,7 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/** /**
* Returns item from given position. * Returns item from given position.
* *
* @version 0.1.3 * @version 0.1.3
* @param string|int $offset Array key. * @param string|int $offset Array key.
* @return OTS_House|int If key is an integer (type-sensitive!) then returns house instance. If it's a string then return associated ID found by house name. * @return OTS_House|int If key is an integer (type-sensitive!) then returns house instance. If it's a string then return associated ID found by house name.
@ -204,7 +204,7 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/** /**
* This method is implemented for ArrayAccess interface. In fact you can't write/append to houses list. Any call to this method will cause {@link E_OTS_ReadOnly E_OTS_ReadOnly} raise. * This method is implemented for ArrayAccess interface. In fact you can't write/append to houses list. Any call to this method will cause {@link E_OTS_ReadOnly E_OTS_ReadOnly} raise.
* *
* @param string|int $offset Array key. * @param string|int $offset Array key.
* @param mixed $value Field value. * @param mixed $value Field value.
* @throws E_OTS_ReadOnly Always - this class is read-only. * @throws E_OTS_ReadOnly Always - this class is read-only.
@ -216,7 +216,7 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/** /**
* This method is implemented for ArrayAccess interface. In fact you can't write/append to houses list. Any call to this method will cause {@link E_OTS_ReadOnly E_OTS_ReadOnly} raise. * This method is implemented for ArrayAccess interface. In fact you can't write/append to houses list. Any call to this method will cause {@link E_OTS_ReadOnly E_OTS_ReadOnly} raise.
* *
* @param string|int $offset Array key. * @param string|int $offset Array key.
* @throws E_OTS_ReadOnly Always - this class is read-only. * @throws E_OTS_ReadOnly Always - this class is read-only.
*/ */
@ -227,11 +227,11 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/** /**
* Returns string representation of object. * Returns string representation of object.
* *
* <p> * <p>
* If any display driver is currently loaded then it uses it's method. * If any display driver is currently loaded then it uses it's method.
* </p> * </p>
* *
* @version 0.1.3 * @version 0.1.3
* @since 0.1.3 * @since 0.1.3
* @return string String representation of object. * @return string String representation of object.

View File

@ -15,11 +15,11 @@
/** /**
* Single item representation. * Single item representation.
* *
* <p> * <p>
* This class represents item that player has. It has no information about item feature, just it's handle in database. To get information about item type and it's features you have to use {@link OTS_ItemType OTS_ItemType class} - you can get it's object by calling {@link OTS_Item::getItemType() getItemType() method}, however you need to have global item types list loaded. * This class represents item that player has. It has no information about item feature, just it's handle in database. To get information about item type and it's features you have to use {@link OTS_ItemType OTS_ItemType class} - you can get it's object by calling {@link OTS_Item::getItemType() getItemType() method}, however you need to have global item types list loaded.
* </p> * </p>
* *
* @package POT * @package POT
* @version 0.1.0 * @version 0.1.0
* @property int $count Amount of item. * @property int $count Amount of item.
@ -31,28 +31,28 @@ class OTS_Item implements Countable
{ {
/** /**
* Item ID. * Item ID.
* *
* @var int * @var int
*/ */
private $id; private $id;
/** /**
* Item count. * Item count.
* *
* @var int * @var int
*/ */
private $count = 0; private $count = 0;
/** /**
* Additional attributes. * Additional attributes.
* *
* @var string * @var string
*/ */
private $attributes; private $attributes;
/** /**
* Creates item of given ID. * Creates item of given ID.
* *
* @param int $id Item ID. * @param int $id Item ID.
*/ */
public function __construct($id) public function __construct($id)
@ -62,7 +62,7 @@ class OTS_Item implements Countable
/** /**
* Returns item type. * Returns item type.
* *
* @return int Item ID. * @return int Item ID.
*/ */
public function getId() public function getId()
@ -72,7 +72,7 @@ class OTS_Item implements Countable
/** /**
* Returns count of item. * Returns count of item.
* *
* @return int Count of item. * @return int Count of item.
*/ */
public function getCount() public function getCount()
@ -82,7 +82,7 @@ class OTS_Item implements Countable
/** /**
* Sets count of item. * Sets count of item.
* *
* @param int $count Count. * @param int $count Count.
*/ */
public function setCount($count) public function setCount($count)
@ -92,7 +92,7 @@ class OTS_Item implements Countable
/** /**
* Returns item custom attributes. * Returns item custom attributes.
* *
* @return string Attributes. * @return string Attributes.
*/ */
public function getAttributes() public function getAttributes()
@ -102,7 +102,7 @@ class OTS_Item implements Countable
/** /**
* Sets item attributes. * Sets item attributes.
* *
* @param string $attributes Item Attributes. * @param string $attributes Item Attributes.
*/ */
public function setAttributes($attributes) public function setAttributes($attributes)
@ -112,7 +112,7 @@ class OTS_Item implements Countable
/** /**
* Returns type of item. * Returns type of item.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @return OTS_ItemType Returns item type of item (null if not exists). * @return OTS_ItemType Returns item type of item (null if not exists).
@ -125,17 +125,17 @@ class OTS_Item implements Countable
/** /**
* Count value for current item. * Count value for current item.
* *
* @return int Count of item. * @return int Count of item.
*/ */
public function count() public function count(): int
{ {
return $this->count; return $this->count;
} }
/** /**
* Magic PHP5 method. * Magic PHP5 method.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @param string $name Property name. * @param string $name Property name.
@ -166,7 +166,7 @@ class OTS_Item implements Countable
/** /**
* Magic PHP5 method. * Magic PHP5 method.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @param string $name Property name. * @param string $name Property name.

View File

@ -7,7 +7,7 @@
/** /**
* Code in this file bases on oryginal OTServ items loading C++ code (itemloader.h, items.cpp, items.h). * Code in this file bases on oryginal OTServ items loading C++ code (itemloader.h, items.cpp, items.h).
* *
* @package POT * @package POT
* @version 0.1.3 * @version 0.1.3
* @author Wrzasq <wrzasq@gmail.com> * @author Wrzasq <wrzasq@gmail.com>
@ -17,7 +17,7 @@
/** /**
* Items list loader. * Items list loader.
* *
* @package POT * @package POT
* @version 0.1.3 * @version 0.1.3
* @property-read int $otbVersion OTB file version. * @property-read int $otbVersion OTB file version.
@ -88,35 +88,35 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Temple positions. * Temple positions.
* *
* @var array * @var array
*/ */
private $items = array(); private $items = array();
/** /**
* OTB version. * OTB version.
* *
* @var int * @var int
*/ */
private $otbVersion; private $otbVersion;
/** /**
* Client version. * Client version.
* *
* @var int * @var int
*/ */
private $clientVersion; private $clientVersion;
/** /**
* Build version. * Build version.
* *
* @var int * @var int
*/ */
private $buildVersion; private $buildVersion;
/** /**
* Magic PHP5 method. * Magic PHP5 method.
* *
* <p> * <p>
* Allows object unserialisation. * Allows object unserialisation.
* </p> * </p>
@ -129,11 +129,11 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Loads items.xml and items.otb files. * Loads items.xml and items.otb files.
* *
* <p> * <p>
* This method loads both items.xml and items.otb files. Both of them has to be in given directory. * This method loads both items.xml and items.otb files. Both of them has to be in given directory.
* </p> * </p>
* *
* @version 0.1.3 * @version 0.1.3
* @param string $path Path to data/items directory. * @param string $path Path to data/items directory.
* @throws E_OTS_FileLoaderError When error occurs during file operation. * @throws E_OTS_FileLoaderError When error occurs during file operation.
@ -191,7 +191,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Parses loaded file. * Parses loaded file.
* *
* @version 0.1.0 * @version 0.1.0
* @throws E_OTS_FileLoaderError If file has invalid format. * @throws E_OTS_FileLoaderError If file has invalid format.
*/ */
@ -378,7 +378,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Returns OTB file version. * Returns OTB file version.
* *
* @return int OTB format version. * @return int OTB format version.
*/ */
public function getOTBVersion() public function getOTBVersion()
@ -388,7 +388,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Returns client version. * Returns client version.
* *
* @return int Client version. * @return int Client version.
*/ */
public function getClientVersion() public function getClientVersion()
@ -398,7 +398,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Returns build version. * Returns build version.
* *
* @return int Build version. * @return int Build version.
*/ */
public function getBuildVersion() public function getBuildVersion()
@ -408,7 +408,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Checks if given item type exists on list. * Checks if given item type exists on list.
* *
* @version 0.1.3 * @version 0.1.3
* @since 0.1.3 * @since 0.1.3
* @param string $name Name. * @param string $name Name.
@ -430,7 +430,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Returns given item type. * Returns given item type.
* *
* @version 0.1.3 * @version 0.1.3
* @param int $id Item type (server) ID. * @param int $id Item type (server) ID.
* @return OTS_ItemType Returns item type of given ID. * @return OTS_ItemType Returns item type of given ID.
@ -448,7 +448,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Checks if given type ID exists on list. * Checks if given type ID exists on list.
* *
* @version 0.1.3 * @version 0.1.3
* @since 0.1.3 * @since 0.1.3
* @param int $id ID. * @param int $id ID.
@ -461,11 +461,11 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Finds item type by it's name. * Finds item type by it's name.
* *
* <p> * <p>
* Note: If there are more then one items with same name this function will return first found server ID. It doesn't also mean that it will be the lowest ID - item types are ordered in order that they were loaded from items.xml file. * Note: If there are more then one items with same name this function will return first found server ID. It doesn't also mean that it will be the lowest ID - item types are ordered in order that they were loaded from items.xml file.
* </p> * </p>
* *
* @version 0.1.3 * @version 0.1.3
* @param string $name Item type name. * @param string $name Item type name.
* @return int Returns item type (server) ID. * @return int Returns item type (server) ID.
@ -497,10 +497,10 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Returns amount of items loaded. * Returns amount of items loaded.
* *
* @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);
} }
@ -550,7 +550,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Returns iterator handle for loops. * Returns iterator handle for loops.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @return ArrayIterator Items list iterator. * @return ArrayIterator Items list iterator.
@ -562,7 +562,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Checks if given element exists. * Checks if given element exists.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @param string|int $offset Array key. * @param string|int $offset Array key.
@ -582,7 +582,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Returns item from given position. * Returns item from given position.
* *
* @version 0.1.3 * @version 0.1.3
* @since 0.1.0 * @since 0.1.0
* @param string|int $offset Array key. * @param string|int $offset Array key.
@ -602,7 +602,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* This method is implemented for ArrayAccess interface. In fact you can't write/append to items list. Any call to this method will cause {@link E_OTS_ReadOnly E_OTS_ReadOnly} raise. * This method is implemented for ArrayAccess interface. In fact you can't write/append to items list. Any call to this method will cause {@link E_OTS_ReadOnly E_OTS_ReadOnly} raise.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @param string|int $offset Array key. * @param string|int $offset Array key.
@ -616,7 +616,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* This method is implemented for ArrayAccess interface. In fact you can't write/append to items list. Any call to this method will cause {@link E_OTS_ReadOnly E_OTS_ReadOnly} raise. * This method is implemented for ArrayAccess interface. In fact you can't write/append to items list. Any call to this method will cause {@link E_OTS_ReadOnly E_OTS_ReadOnly} raise.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @param string|int $offset Array key. * @param string|int $offset Array key.
@ -629,7 +629,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Magic PHP5 method. * Magic PHP5 method.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @param string $name Property name. * @param string $name Property name.
@ -652,11 +652,11 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/** /**
* Returns string representation of object. * Returns string representation of object.
* *
* <p> * <p>
* If any display driver is currently loaded then it uses it's method. * If any display driver is currently loaded then it uses it's method.
* </p> * </p>
* *
* @version 0.1.3 * @version 0.1.3
* @since 0.1.3 * @since 0.1.3
* @return string String representation of object. * @return string String representation of object.

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

@ -7,7 +7,7 @@
/** /**
* Code in this file bases on oryginal OTServ OTBM format loading C++ code (iomapotbm.h, iomapotbm.cpp). * Code in this file bases on oryginal OTServ OTBM format loading C++ code (iomapotbm.h, iomapotbm.cpp).
* *
* @package POT * @package POT
* @version 0.1.3 * @version 0.1.3
* @author Wrzasq <wrzasq@gmail.com> * @author Wrzasq <wrzasq@gmail.com>
@ -20,11 +20,11 @@
/** /**
* OTBM format reader. * OTBM format reader.
* *
* <p> * <p>
* POT OTBM file parser is less strict then oryginal OTServ one. For instance it will read waypoints from version 1 OTBM file even that there were no waypoints in that format. * POT OTBM file parser is less strict then oryginal OTServ one. For instance it will read waypoints from version 1 OTBM file even that there were no waypoints in that format.
* </p> * </p>
* *
* @package POT * @package POT
* @version 0.1.6 * @version 0.1.6
* @property-read OTS_HousesList $housesList Houses list loaded from associated houses file. * @property-read OTS_HousesList $housesList Houses list loaded from associated houses file.
@ -95,56 +95,56 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
const OTBM_ATTR_HOUSEDOORID = 14; const OTBM_ATTR_HOUSEDOORID = 14;
/** /**
* Amount. * Amount.
* *
* @version 0.1.6 * @version 0.1.6
* @since 0.1.6 * @since 0.1.6
*/ */
const OTBM_ATTR_COUNT = 15; const OTBM_ATTR_COUNT = 15;
/** /**
* Time interval. * Time interval.
* *
* @version 0.1.6 * @version 0.1.6
* @since 0.1.6 * @since 0.1.6
*/ */
const OTBM_ATTR_DURATION = 16; const OTBM_ATTR_DURATION = 16;
/** /**
* Metamorphic stage. * Metamorphic stage.
* *
* @version 0.1.6 * @version 0.1.6
* @since 0.1.6 * @since 0.1.6
*/ */
const OTBM_ATTR_DECAYING_STATE = 17; const OTBM_ATTR_DECAYING_STATE = 17;
/** /**
* Date of being written. * Date of being written.
* *
* @version 0.1.6 * @version 0.1.6
* @since 0.1.6 * @since 0.1.6
*/ */
const OTBM_ATTR_WRITTENDATE = 18; const OTBM_ATTR_WRITTENDATE = 18;
/** /**
* Sign author. * Sign author.
* *
* @version 0.1.6 * @version 0.1.6
* @since 0.1.6 * @since 0.1.6
*/ */
const OTBM_ATTR_WRITTENBY = 19; const OTBM_ATTR_WRITTENBY = 19;
/** /**
* Sleeping player ID. * Sleeping player ID.
* *
* @version 0.1.6 * @version 0.1.6
* @since 0.1.6 * @since 0.1.6
*/ */
const OTBM_ATTR_SLEEPERGUID = 20; const OTBM_ATTR_SLEEPERGUID = 20;
/** /**
* Time of sleep started. * Time of sleep started.
* *
* @version 0.1.6 * @version 0.1.6
* @since 0.1.6 * @since 0.1.6
*/ */
const OTBM_ATTR_SLEEPSTART = 21; const OTBM_ATTR_SLEEPSTART = 21;
/** /**
* Number of charges. * Number of charges.
* *
* @version 0.1.6 * @version 0.1.6
* @since 0.1.6 * @since 0.1.6
*/ */
@ -208,14 +208,14 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
const OTBM_NODE_HOUSETILE = 14; const OTBM_NODE_HOUSETILE = 14;
/** /**
* Waypoints list. * Waypoints list.
* *
* @version 0.1.6 * @version 0.1.6
* @since 0.1.6 * @since 0.1.6
*/ */
const OTBM_NODE_WAYPOINTS = 15; const OTBM_NODE_WAYPOINTS = 15;
/** /**
* Waypoint. * Waypoint.
* *
* @version 0.1.6 * @version 0.1.6
* @since 0.1.6 * @since 0.1.6
*/ */
@ -223,56 +223,56 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Map width. * Map width.
* *
* @var int * @var int
*/ */
private $width; private $width;
/** /**
* Map height. * Map height.
* *
* @var int * @var int
*/ */
private $height; private $height;
/** /**
* Map description. * Map description.
* *
* @var string * @var string
*/ */
private $description = ''; private $description = '';
/** /**
* List of towns. * List of towns.
* *
* @var array * @var array
*/ */
private $towns = array(); private $towns = array();
/** /**
* Temple positions. * Temple positions.
* *
* @var array * @var array
*/ */
private $temples = array(); private $temples = array();
/** /**
* Directory path. * Directory path.
* *
* @var string * @var string
*/ */
private $directory; private $directory;
/** /**
* External houses file. * External houses file.
* *
* @var OTS_HousesList * @var OTS_HousesList
*/ */
private $housesList; private $housesList;
/** /**
* List of map tracks. * List of map tracks.
* *
* @var array * @var array
* @version 0.1.6 * @version 0.1.6
* @since 0.1.6 * @since 0.1.6
@ -281,11 +281,11 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Magic PHP5 method. * Magic PHP5 method.
* *
* <p> * <p>
* Allows object unserialisation. * Allows object unserialisation.
* </p> * </p>
* *
* @throws E_OTS_FileLoaderError When error occurs during file operation. * @throws E_OTS_FileLoaderError When error occurs during file operation.
*/ */
public function __wakeup() public function __wakeup()
@ -296,7 +296,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Loads OTBM file content. * Loads OTBM file content.
* *
* @version 0.1.0 * @version 0.1.0
* @param string $file Filename. * @param string $file Filename.
* @throws E_OTS_FileLoaderError When error occurs during file operation. * @throws E_OTS_FileLoaderError When error occurs during file operation.
@ -316,7 +316,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Parses loaded file. * Parses loaded file.
* *
* @version 0.1.0 * @version 0.1.0
* @throws E_OTS_FileLoaderError When error occurs during file operation. * @throws E_OTS_FileLoaderError When error occurs during file operation.
* @throws E_OTS_OutOfBuffer When there is read attemp after end of stream. * @throws E_OTS_OutOfBuffer When there is read attemp after end of stream.
@ -476,7 +476,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Loads map's houses list. * Loads map's houses list.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @return OTS_HousesList Houses from external file. * @return OTS_HousesList Houses from external file.
@ -488,7 +488,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Returns map width. * Returns map width.
* *
* @return int Map width. * @return int Map width.
*/ */
public function getWidth() public function getWidth()
@ -498,7 +498,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Returns map height. * Returns map height.
* *
* @return int Map height. * @return int Map height.
*/ */
public function getHeight() public function getHeight()
@ -508,7 +508,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Returns map description. * Returns map description.
* *
* @return string Map description. * @return string Map description.
*/ */
public function getDescription() public function getDescription()
@ -518,11 +518,11 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Returns map waypoints list. * Returns map waypoints list.
* *
* <p> * <p>
* Each item of returned array is sub-array with list of waypoints. * Each item of returned array is sub-array with list of waypoints.
* </p> * </p>
* *
* @version 0.1.6 * @version 0.1.6
* @since 0.1.6 * @since 0.1.6
* @return array List of tracks. * @return array List of tracks.
@ -534,7 +534,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Checks if given town ID exists on list. * Checks if given town ID exists on list.
* *
* @version 0.1.3 * @version 0.1.3
* @since 0.1.3 * @since 0.1.3
* @param int $id ID. * @param int $id ID.
@ -547,7 +547,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Returns town's ID. * Returns town's ID.
* *
* @version 0.1.3 * @version 0.1.3
* @param string $name Town. * @param string $name Town.
* @return int ID. * @return int ID.
@ -567,7 +567,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Checks if given town name exists on list. * Checks if given town name exists on list.
* *
* @version 0.1.3 * @version 0.1.3
* @since 0.1.3 * @since 0.1.3
* @param string $name Town. * @param string $name Town.
@ -580,7 +580,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Returns name of given town's ID. * Returns name of given town's ID.
* *
* @version 0.1.3 * @version 0.1.3
* @param int $id Town ID. * @param int $id Town ID.
* @return string Name. * @return string Name.
@ -607,7 +607,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Returns town's temple position. * Returns town's temple position.
* *
* @param int $id Town id. * @param int $id Town id.
* @return OTS_MapCoords|bool Point on map (false if not found). * @return OTS_MapCoords|bool Point on map (false if not found).
*/ */
@ -625,12 +625,12 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Returns amount of towns loaded. * Returns amount of towns loaded.
* *
* @version 0.0.8 * @version 0.0.8
* @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);
} }
@ -690,7 +690,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Returns iterator handle for loops. * Returns iterator handle for loops.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @return ArrayIterator Towns list iterator. * @return ArrayIterator Towns list iterator.
@ -702,7 +702,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Checks if given element exists. * Checks if given element exists.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @param string|int $offset Array key. * @param string|int $offset Array key.
@ -724,7 +724,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Returns item from given position. * Returns item from given position.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @param string|int $offset Array key. * @param string|int $offset Array key.
@ -754,7 +754,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* This method is implemented for ArrayAccess interface. In fact you can't write/append to towns list. Any call to this method will cause {@link E_OTS_ReadOnly E_OTS_ReadOnly} raise. * This method is implemented for ArrayAccess interface. In fact you can't write/append to towns list. Any call to this method will cause {@link E_OTS_ReadOnly E_OTS_ReadOnly} raise.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @param string|int $offset Array key. * @param string|int $offset Array key.
@ -768,7 +768,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* This method is implemented for ArrayAccess interface. In fact you can't write/append to towns list. Any call to this method will cause {@link E_OTS_ReadOnly E_OTS_ReadOnly} raise. * This method is implemented for ArrayAccess interface. In fact you can't write/append to towns list. Any call to this method will cause {@link E_OTS_ReadOnly E_OTS_ReadOnly} raise.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @param string|int $offset Array key. * @param string|int $offset Array key.
@ -781,7 +781,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Magic PHP5 method. * Magic PHP5 method.
* *
* @version 0.1.0 * @version 0.1.0
* @since 0.1.0 * @since 0.1.0
* @param string $name Property name. * @param string $name Property name.
@ -814,11 +814,11 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/** /**
* Returns string representation of object. * Returns string representation of object.
* *
* <p> * <p>
* If any display driver is currently loaded then it uses it's method. * If any display driver is currently loaded then it uses it's method.
* </p> * </p>
* *
* @version 0.1.3 * @version 0.1.3
* @since 0.1.3 * @since 0.1.3
* @return string String representation of object. * @return string String representation of object.

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