Merge branch 'develop' into feature/settings

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

View File

@@ -76,11 +76,13 @@ $config['clients'] = [
1096,
1097,
1098,
1100,
1102,
1140,
1150,
1180,
1200,
1202,
1215,
@@ -89,4 +91,12 @@ $config['clients'] = [
1240,
1251,
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!');
switch($page)
{
case 'createaccount':
$page = 'account/create';
break;
case 'accountmanagement':
$page = 'account/manage';
break;
case 'lostaccount':
$page = 'account/lost';
break;
case 'whoisonline':
$page = 'online';
break;
@@ -18,6 +30,10 @@ switch($page)
$page = 'news';
break;
case 'newsarchive':
$page = 'news/archive';
break;
case 'tibiarules':
$page = 'rules';
break;
@@ -37,4 +53,3 @@ switch($page)
default:
break;
}
?>

View File

@@ -39,7 +39,7 @@ function exception_handler($exception) {
// we just replace some values manually
// cause in case Twig throws exception, we can show it too
$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;
}

View File

@@ -62,20 +62,20 @@ function getFullLink($page, $name, $blank = false) {
function getLink($page, $action = null)
{
$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 getForumThreadLink($thread_id, $page = NULL)
{
$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)
{
$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)
@@ -89,7 +89,7 @@ function getPlayerLink($name, $generate = true)
}
$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;
return generateLink($url, $name);
@@ -98,7 +98,7 @@ function getPlayerLink($name, $generate = true)
function getMonsterLink($name, $generate = true)
{
$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;
return generateLink($url, $name);
@@ -117,7 +117,7 @@ function getHouseLink($name, $generate = true)
}
$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;
return generateLink($url, $name);
@@ -136,7 +136,7 @@ function getGuildLink($name, $generate = true)
}
$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;
return generateLink($url, $name);
@@ -268,6 +268,13 @@ function getForumBoards()
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.
*
@@ -462,7 +469,7 @@ function tickers()
*/
function template_place_holder($type)
{
global $template_place_holders;
global $twig, $template_place_holders;
$ret = '';
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') {
$ret .= template_header();
}
elseif ($type === 'body_start') {
$ret .= $twig->render('browsehappy.html.twig');
}
elseif($type === 'body_end') {
$ret .= template_ga_code();
}
@@ -1034,7 +1044,7 @@ function getTopPlayers($limit = 5) {
$deleted = 'deletion';
$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) {
foreach($players as &$player) {
@@ -1151,6 +1161,12 @@ function clearCache()
global $template_name;
if ($cache->fetch('template_ini' . $template_name, $tmp))
$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);
@@ -1158,6 +1174,12 @@ function clearCache()
deleteDirectory(CACHE . '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;
}
@@ -1432,6 +1454,32 @@ function Outfits_loadfromXML()
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) {
return substr($str, 0, $length);
}
@@ -1473,9 +1521,41 @@ function truncate($string, $length)
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
require_once LIBS . 'validator.php';
require_once SYSTEM . 'compat.php';
require_once SYSTEM . 'compat/base.php';
// custom functions
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_COUNTRY', ++$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_AFTER_CHARACTER_NAME', ++$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_BEFORE_SUBMIT_BUTTON', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_FORM', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_SUBMIT', ++$i);
define('HOOK_FIRST', HOOK_STARTUP);
define('HOOK_LAST', HOOK_ACCOUNT_CREATE_AFTER_SUBMIT);
define('HOOK_ACCOUNT_CREATE_POST', ++$i);
define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i);
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';
class Hook
@@ -73,9 +89,7 @@ class Hook
}*/
global $db, $config, $template_path, $ots, $content, $twig;
if(file_exists(BASE . $this->_file)) {
$ret = require BASE . $this->_file;
}
$ret = include BASE . $this->_file;
return !isset($ret) || $ret == 1 || $ret;
}
@@ -120,5 +134,7 @@ class Hooks
foreach(Plugins::getHooks() as $hook) {
$this->register($hook['name'], $hook['type'], $hook['file']);
}
Plugins::clearWarnings();
}
}

View File

@@ -34,6 +34,10 @@ $cache = Cache::getInstance();
// twig
require_once SYSTEM . 'twig.php';
// action, used by many pages
$action = $_REQUEST['action'] ?? '';
define('ACTION', $action);
// trim values we receive
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_NUMBER', $db->hasColumn('accounts', 'number'));
define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt'));
// load vocation names
$tmp = '';
if($cache->enabled() && $cache->fetch('vocations', $tmp)) {

View File

@@ -12,27 +12,44 @@
class CreateCharacter
{
/**
* @param string $name
* @param int $sex
* @param int $vocation
* @param int $town
* @param array $errors
* @param $name
* @param $errors
* @return bool
*/
public function check($name, $sex, &$vocation, &$town, &$errors) {
public function checkName($name, &$errors)
{
$minLength = config('character_name_min_length');
$maxLength = config('character_name_max_length');
if(empty($name))
if(empty($name)) {
$errors['name'] = 'Please enter a name for your character!';
else if(strlen($name) > $maxLength)
$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.';
else {
if(!admin() && !Validator::newCharacterName($name)) {
$errors['name'] = Validator::getLastError();
}
return false;
}
if(strlen($name) > $maxLength) {
$errors['name'] = 'Name is too long. Max. length <b>' . $maxLength . '</b> letters.';
return false;
}
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();
@@ -42,20 +59,38 @@ class CreateCharacter
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!';
}
if(count(config('character_samples')) > 1)
{
if(!isset($vocation))
$errors['vocation'] = 'Please select a vocation for your character.';
}
else
else {
$vocation = config('character_samples')[0];
}
if(count(config('character_towns')) > 1) {
if(!isset($town))
if(!isset($town)) {
$errors['town'] = 'Please select a town for your character.';
}
}
else {
$town = config('character_towns')[0];
@@ -158,8 +193,14 @@ class CreateCharacter
$player->setManaSpent($char_to_copy->getManaSpent());
$player->setSoul($char_to_copy->getSoul());
for($skill = POT::SKILL_FIRST; $skill <= POT::SKILL_LAST; $skill++)
$player->setSkill($skill, 10);
for($skill = POT::SKILL_FIRST; $skill <= POT::SKILL_LAST; $skill++) {
$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->setLookFeet($char_to_copy->getLookFeet());
@@ -199,16 +240,22 @@ class CreateCharacter
if($db->hasTable('player_skills')) {
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);
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()."");
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']."');");
foreach($loaded_items_to_copy as $save_item) {
$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;
$twig->display('success.html.twig', array(

View File

@@ -11,7 +11,7 @@
defined('MYAAC') or die('Direct access not allowed!');
$configForumTablePrefix = config('forum_table_prefix');
if(!empty(trim($configForumTablePrefix))) {
if(null !== $configForumTablePrefix && !empty(trim($configForumTablePrefix))) {
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_".');
}
@@ -322,4 +322,4 @@ class Forum
return $hasAccess;
}
}
?>
?>

View File

@@ -8,12 +8,12 @@ class News
$errors[] = 'Please fill all inputs.';
return false;
}
if(strlen($title) > TITLE_LIMIT) {
$errors[] = 'News title cannot be longer than ' . TITLE_LIMIT . ' characters.';
if(strlen($title) > NEWS_TITLE_LIMIT) {
$errors[] = 'News title cannot be longer than ' . NEWS_TITLE_LIMIT . ' characters.';
return false;
}
if(strlen($body) > BODY_LIMIT) {
$errors[] = 'News content cannot be longer than ' . BODY_LIMIT . ' characters.';
if(strlen($body) > NEWS_BODY_LIMIT) {
$errors[] = 'News content cannot be longer than ' . NEWS_BODY_LIMIT . ' characters.';
return false;
}
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()
{
$cache = Cache::getInstance();
if ($cache->enabled()) {
$tmp = '';
if ($cache->fetch('hooks', $tmp)) {
if ($cache->fetch('plugins_hooks', $tmp)) {
return unserialize($tmp);
}
}
@@ -96,7 +201,7 @@ class Plugins {
}
if ($cache->enabled()) {
$cache->set('hooks', serialize($hooks), 600);
$cache->set('plugins_hooks', serialize($hooks), 600);
}
return $hooks;
@@ -259,27 +364,59 @@ class Plugins {
}
if(in_array($req, array('php-ext', 'php-extension'))) { // require php extension
if(!extension_loaded($version)) {
self::$error = "This plugin requires php extension: " . $version . " to be installed.";
$tmpDisplayError = false;
$explode = explode(',', $version);
foreach ($explode as $item) {
if(!extension_loaded($item)) {
$errors[] = "This plugin requires php extension: " . $item . " to be installed.";
$tmpDisplayError = true;
}
}
if ($tmpDisplayError) {
self::$error = implode('<br/>', $errors);
$continue = false;
break;
}
}
else if($req == 'table') {
if(!$db->hasTable($version)) {
self::$error = "This plugin requires table: " . $version . " to exist in the database.";
$tmpDisplayError = false;
$explode = explode(',', $version);
foreach ($explode as $item) {
if(!$db->hasTable($item)) {
$errors[] = "This plugin requires table: " . $item . " to exist in the database.";
$tmpDisplayError = true;
}
}
if ($tmpDisplayError) {
self::$error = implode('<br/>', $errors);
$continue = false;
break;
}
}
else if($req == 'column') {
$tmp = explode('.', $version);
if(count($tmp) == 2) {
if(!$db->hasColumn($tmp[0], $tmp[1])) {
self::$error = "This plugin requires database column: " . $tmp[0] . "." . $tmp[1] . " to exist in database.";
$continue = false;
break;
$tmpDisplayError = false;
$explode = explode(',', $version);
foreach ($explode as $item) {
$tmp = explode('.', $item);
if(count($tmp) == 2) {
if(!$db->hasColumn($tmp[0], $tmp[1])) {
$errors[] = "This plugin requires database column: " . $tmp[0] . "." . $tmp[1] . " to exist in database.";
$tmpDisplayError = true;
}
}
else {
self::$warnings[] = "Invalid plugin require column: " . $item;
}
}
if ($tmpDisplayError) {
self::$error = implode('<br/>', $errors);
$continue = false;
break;
}
}
else if(strpos($req, 'ext-') !== false) {
@@ -412,6 +549,10 @@ class Plugins {
return self::$warnings;
}
public static function clearWarnings() {
self::$warnings = [];
}
public static function getError() {
return self::$error;
}

View File

@@ -101,6 +101,37 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
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.
*
@@ -138,11 +169,32 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
*/
public function create($name = NULL, $id = NULL)
{
// saves blank account info
$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() . ')');
if(isset($name)) {
$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;
}
else {
if (USE_ACCOUNT_NUMBER) {
$this->data['number'] = $name;
}
}
$lastInsertId = $this->db->lastInsertId();
if($lastInsertId != 0) {
@@ -179,15 +231,26 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @param int $id Account number.
* @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])) {
$this->data = self::$cache[$id];
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
$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;
}
@@ -306,6 +369,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
return $this->data['id'];
}
public function getNumber()
{
if (isset($this->data['number'])) {
return $this->data['number'];
}
return $this->data['id'];
}
public function getRLName()
{
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.
* @return Iterator List of players.
*/
#[\ReturnTypeWillChange]
public function getIterator()
{
return $this->getPlayersList();
@@ -1033,7 +1106,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error.
* @return int Count of players.
*/
public function count()
public function count(): int
{
return $this->getPlayersList()->count();
}

View File

@@ -83,34 +83,47 @@ abstract class OTS_Base_DB extends PDO implements IOTS_DB
$startTime = microtime(true);
}
$ret = parent::query(...$args);;
$ret = parent::query(...$args);
if($this->logged) {
$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;
}
public function select($table, $where, $limit = null)
public function select($table, $where = [], $limit = null)
{
$fields = array_keys($where);
$values = array_values($where);
$query = 'SELECT * FROM ' . $this->tableName($table) . ' WHERE (';
$query = 'SELECT * FROM ' . $this->tableName($table);
$count = count($fields);
for ($i = 0; $i < $count; $i++)
$query.= $this->fieldName($fields[$i]).' = '.$this->quote($values[$i]).' AND ';
if (!empty($where)) {
$query .= ' WHERE (';
$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))
$query .=') LIMIT '.$limit.';';
$query .=' LIMIT '.$limit.';';
else
$query .=');';
$query .=';';
$query = $this->query($query);
if($query->rowCount() != 1) return false;
return $query->fetch();
$rowCount = $query->rowCount();
if ($rowCount <= 0) return false;
else if ($rowCount == 1) {
return $query->fetch();
}
return $query->fetchAll();
}
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
* @return OTS_Base_DAO Current row.
*/
#[\ReturnTypeWillChange]
public function current()
{
$id = current($this->rows);
@@ -203,7 +204,7 @@ abstract class OTS_Base_List implements IOTS_DAO, Iterator, Countable
*
* @throws PDOException On PDO operation error.
*/
public function rewind()
public function rewind(): void
{
$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.
*/
public function next()
public function next(): void
{
next($this->rows);
}
@@ -221,6 +222,7 @@ abstract class OTS_Base_List implements IOTS_DAO, Iterator, Countable
*
* @return mixed Array key.
*/
#[\ReturnTypeWillChange]
public function key()
{
return key($this->rows);
@@ -231,7 +233,7 @@ abstract class OTS_Base_List implements IOTS_DAO, Iterator, Countable
*
* @return bool Does next row exist.
*/
public function valid()
public function valid(): bool
{
return key($this->rows) !== null;
}
@@ -243,7 +245,7 @@ abstract class OTS_Base_List implements IOTS_DAO, Iterator, Countable
* @return int Number of rows.
* @throws PDOException On PDO operation error.
*/
public function count()
public function count(): int
{
return $this->db->query( $this->getSQL(true) )->fetchColumn();
}

View File

@@ -15,11 +15,11 @@
/**
* Container item representation.
*
*
* <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).
* </p>
*
*
* @package POT
* @version 0.1.3
*/
@@ -27,14 +27,14 @@ class OTS_Container extends OTS_Item implements IteratorAggregate
{
/**
* Contained items.
*
*
* @var array
*/
private $items = array();
/**
* Adds item to container.
*
*
* @param OTS_Item $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.
*
*
* <p>
* Passed item must be exacly instance of item which is stored in container, not it's copy. This method bases on PHP references.
* </p>
*
*
* @param OTS_Item $item Item.
* @tutorial POT/Players.pkg#deleting
*/
@@ -66,14 +66,14 @@ class OTS_Container extends OTS_Item implements IteratorAggregate
/**
* Number of items inside container.
*
*
* <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.
* </p>
*
*
* @return int Number of items.
*/
public function count()
public function count(): int
{
return count($items);
}
@@ -123,7 +123,7 @@ class OTS_Container extends OTS_Item implements IteratorAggregate
/**
* Returns iterator handle for loops.
*
*
* @version 0.1.0
* @since 0.1.0
* @return ArrayIterator Items iterator.
@@ -135,7 +135,7 @@ class OTS_Container extends OTS_Item implements IteratorAggregate
/**
* Clones all contained items.
*
*
* @version 0.1.3
* @since 0.1.3
*/

View File

@@ -6,7 +6,7 @@ if (PHP_VERSION_ID >= 80000) {
/**
* @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);
}

View File

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

View File

@@ -41,7 +41,7 @@ class OTS_Groups_List implements IteratorAggregate, Countable
$info['access'] = $group['name'];
$this->groups[$group['id']] = new OTS_Group($info);
}
return;
}
@@ -50,7 +50,7 @@ class OTS_Groups_List implements IteratorAggregate, Countable
global $config;
$file = $config['data_path'] . 'XML/groups.xml';
}
if(!@file_exists($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.');
@@ -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));
return;
}
// loads groups
foreach($groups->getElementsByTagName('group') as $group)
{
@@ -157,7 +157,7 @@ class OTS_Groups_List implements IteratorAggregate, Countable
if($id > $group_id)
$group_id = $id;
}
return $group_id;
}
@@ -196,6 +196,7 @@ class OTS_Groups_List implements IteratorAggregate, Countable
* @since 0.1.5
* @return AppendIterator Iterator for all groups.
*/
#[\ReturnTypeWillChange]
public function getIterator()
{
$iterator = new AppendIterator();
@@ -210,7 +211,7 @@ class OTS_Groups_List implements IteratorAggregate, Countable
* @since 0.1.5
* @return int Amount of all groups.
*/
public function count()
public function count(): int
{
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.
* @return Iterator List of ranks.
*/
#[\ReturnTypeWillChange]
public function getIterator()
{
return $this->getGuildRanksList();
@@ -723,7 +724,7 @@ class OTS_Guild extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error.
* @return int Count of ranks.
*/
public function count()
public function count(): int
{
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.
* @return Iterator List of players.
*/
#[\ReturnTypeWillChange]
public function getIterator()
{
return $this->getPlayersList();
@@ -410,7 +411,7 @@ class OTS_GuildRank extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error.
* @return int Count of players.
*/
public function count()
public function count(): int
{
return $this->getPlayersList()->count();
}

View File

@@ -15,7 +15,7 @@
/**
* Wrapper for houses list.
*
*
* @package POT
* @version 0.1.3
* @tutorial POT/data_directory.pkg#towns.houses
@@ -24,14 +24,14 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
{
/**
* List of houses elements.
*
*
* @var array
*/
private $houses = array();
/**
* Loads houses information.
*
*
* @version 0.1.3
* @param string $path Houses file.
* @throws DOMException On DOM operation error.
@@ -49,11 +49,11 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/**
* Magic PHP5 method.
*
*
* <p>
* Allows object importing from {@link http://www.php.net/manual/en/function.var-export.php var_export()}.
* </p>
*
*
* @param array $properties List of object properties.
* @throws DOMException On DOM operation error.
*/
@@ -72,7 +72,7 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/**
* Checks if given house exists on list.
*
*
* @version 0.1.3
* @since 0.1.3
* @param string $name Name.
@@ -94,7 +94,7 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/**
* Returns house information.
*
*
* @version 0.1.3
* @param int $id House ID.
* @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.
*
*
* @version 0.1.3
* @since 0.1.3
* @param int $id ID.
@@ -125,7 +125,7 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/**
* Returns ID of house with given name.
*
*
* @version 0.1.3
* @param string $name House name.
* @return int House ID.
@@ -147,17 +147,17 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/**
* Returns amount of houses.
*
*
* @return int Count of houses.
*/
public function count()
public function count(): int
{
return count($this->houses);
}
/**
* Returns iterator handle for loops.
*
*
* @return ArrayIterator Houses list iterator.
*/
public function getIterator()
@@ -167,7 +167,7 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/**
* Checks if given element exists.
*
*
* @param string|int $offset Array key.
* @return bool True if it's set.
*/
@@ -185,7 +185,7 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
/**
* Returns item from given position.
*
*
* @version 0.1.3
* @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.
@@ -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.
*
*
* @param string|int $offset Array key.
* @param mixed $value Field value.
* @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.
*
*
* @param string|int $offset Array key.
* @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.
*
*
* <p>
* If any display driver is currently loaded then it uses it's method.
* </p>
*
*
* @version 0.1.3
* @since 0.1.3
* @return string String representation of object.

View File

@@ -15,11 +15,11 @@
/**
* Single item representation.
*
*
* <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.
* </p>
*
*
* @package POT
* @version 0.1.0
* @property int $count Amount of item.
@@ -31,28 +31,28 @@ class OTS_Item implements Countable
{
/**
* Item ID.
*
*
* @var int
*/
private $id;
/**
* Item count.
*
*
* @var int
*/
private $count = 0;
/**
* Additional attributes.
*
*
* @var string
*/
private $attributes;
/**
* Creates item of given ID.
*
*
* @param int $id Item ID.
*/
public function __construct($id)
@@ -62,7 +62,7 @@ class OTS_Item implements Countable
/**
* Returns item type.
*
*
* @return int Item ID.
*/
public function getId()
@@ -72,7 +72,7 @@ class OTS_Item implements Countable
/**
* Returns count of item.
*
*
* @return int Count of item.
*/
public function getCount()
@@ -82,7 +82,7 @@ class OTS_Item implements Countable
/**
* Sets count of item.
*
*
* @param int $count Count.
*/
public function setCount($count)
@@ -92,7 +92,7 @@ class OTS_Item implements Countable
/**
* Returns item custom attributes.
*
*
* @return string Attributes.
*/
public function getAttributes()
@@ -102,7 +102,7 @@ class OTS_Item implements Countable
/**
* Sets item attributes.
*
*
* @param string $attributes Item Attributes.
*/
public function setAttributes($attributes)
@@ -112,7 +112,7 @@ class OTS_Item implements Countable
/**
* Returns type of item.
*
*
* @version 0.1.0
* @since 0.1.0
* @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.
*
*
* @return int Count of item.
*/
public function count()
public function count(): int
{
return $this->count;
}
/**
* Magic PHP5 method.
*
*
* @version 0.1.0
* @since 0.1.0
* @param string $name Property name.
@@ -166,7 +166,7 @@ class OTS_Item implements Countable
/**
* Magic PHP5 method.
*
*
* @version 0.1.0
* @since 0.1.0
* @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).
*
*
* @package POT
* @version 0.1.3
* @author Wrzasq <wrzasq@gmail.com>
@@ -17,7 +17,7 @@
/**
* Items list loader.
*
*
* @package POT
* @version 0.1.3
* @property-read int $otbVersion OTB file version.
@@ -88,35 +88,35 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/**
* Temple positions.
*
*
* @var array
*/
private $items = array();
/**
* OTB version.
*
*
* @var int
*/
private $otbVersion;
/**
* Client version.
*
*
* @var int
*/
private $clientVersion;
/**
* Build version.
*
*
* @var int
*/
private $buildVersion;
/**
* Magic PHP5 method.
*
*
* <p>
* Allows object unserialisation.
* </p>
@@ -129,11 +129,11 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/**
* Loads items.xml and items.otb files.
*
*
* <p>
* This method loads both items.xml and items.otb files. Both of them has to be in given directory.
* </p>
*
*
* @version 0.1.3
* @param string $path Path to data/items directory.
* @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.
*
*
* @version 0.1.0
* @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.
*
*
* @return int OTB format version.
*/
public function getOTBVersion()
@@ -388,7 +388,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/**
* Returns client version.
*
*
* @return int Client version.
*/
public function getClientVersion()
@@ -398,7 +398,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/**
* Returns build version.
*
*
* @return int Build version.
*/
public function getBuildVersion()
@@ -408,7 +408,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/**
* Checks if given item type exists on list.
*
*
* @version 0.1.3
* @since 0.1.3
* @param string $name Name.
@@ -430,7 +430,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/**
* Returns given item type.
*
*
* @version 0.1.3
* @param int $id Item type (server) 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.
*
*
* @version 0.1.3
* @since 0.1.3
* @param int $id ID.
@@ -461,11 +461,11 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/**
* Finds item type by it's name.
*
*
* <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.
* </p>
*
*
* @version 0.1.3
* @param string $name Item type name.
* @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.
*
*
* @return int Count of types.
*/
public function count()
public function count(): int
{
return count($this->items);
}
@@ -550,7 +550,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/**
* Returns iterator handle for loops.
*
*
* @version 0.1.0
* @since 0.1.0
* @return ArrayIterator Items list iterator.
@@ -562,7 +562,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/**
* Checks if given element exists.
*
*
* @version 0.1.0
* @since 0.1.0
* @param string|int $offset Array key.
@@ -582,7 +582,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/**
* Returns item from given position.
*
*
* @version 0.1.3
* @since 0.1.0
* @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.
*
*
* @version 0.1.0
* @since 0.1.0
* @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.
*
*
* @version 0.1.0
* @since 0.1.0
* @param string|int $offset Array key.
@@ -629,7 +629,7 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/**
* Magic PHP5 method.
*
*
* @version 0.1.0
* @since 0.1.0
* @param string $name Property name.
@@ -652,11 +652,11 @@ class OTS_ItemsList extends OTS_FileLoader implements IteratorAggregate, Countab
/**
* Returns string representation of object.
*
*
* <p>
* If any display driver is currently loaded then it uses it's method.
* </p>
*
*
* @version 0.1.3
* @since 0.1.3
* @return string String representation of object.

View File

@@ -163,7 +163,7 @@ class OTS_MonstersList implements Iterator, Countable, ArrayAccess
*
* @return int Count of monsters.
*/
public function count()
public function count(): int
{
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).
*
*
* @package POT
* @version 0.1.3
* @author Wrzasq <wrzasq@gmail.com>
@@ -20,11 +20,11 @@
/**
* OTBM format reader.
*
*
* <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.
* </p>
*
*
* @package POT
* @version 0.1.6
* @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;
/**
* Amount.
*
*
* @version 0.1.6
* @since 0.1.6
*/
const OTBM_ATTR_COUNT = 15;
/**
* Time interval.
*
*
* @version 0.1.6
* @since 0.1.6
*/
const OTBM_ATTR_DURATION = 16;
/**
* Metamorphic stage.
*
*
* @version 0.1.6
* @since 0.1.6
*/
const OTBM_ATTR_DECAYING_STATE = 17;
/**
* Date of being written.
*
*
* @version 0.1.6
* @since 0.1.6
*/
const OTBM_ATTR_WRITTENDATE = 18;
/**
* Sign author.
*
*
* @version 0.1.6
* @since 0.1.6
*/
const OTBM_ATTR_WRITTENBY = 19;
/**
* Sleeping player ID.
*
*
* @version 0.1.6
* @since 0.1.6
*/
const OTBM_ATTR_SLEEPERGUID = 20;
/**
* Time of sleep started.
*
*
* @version 0.1.6
* @since 0.1.6
*/
const OTBM_ATTR_SLEEPSTART = 21;
/**
* Number of charges.
*
*
* @version 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;
/**
* Waypoints list.
*
*
* @version 0.1.6
* @since 0.1.6
*/
const OTBM_NODE_WAYPOINTS = 15;
/**
* Waypoint.
*
*
* @version 0.1.6
* @since 0.1.6
*/
@@ -223,56 +223,56 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Map width.
*
*
* @var int
*/
private $width;
/**
* Map height.
*
*
* @var int
*/
private $height;
/**
* Map description.
*
*
* @var string
*/
private $description = '';
/**
* List of towns.
*
*
* @var array
*/
private $towns = array();
/**
* Temple positions.
*
*
* @var array
*/
private $temples = array();
/**
* Directory path.
*
*
* @var string
*/
private $directory;
/**
* External houses file.
*
*
* @var OTS_HousesList
*/
private $housesList;
/**
* List of map tracks.
*
*
* @var array
* @version 0.1.6
* @since 0.1.6
@@ -281,11 +281,11 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Magic PHP5 method.
*
*
* <p>
* Allows object unserialisation.
* </p>
*
*
* @throws E_OTS_FileLoaderError When error occurs during file operation.
*/
public function __wakeup()
@@ -296,7 +296,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Loads OTBM file content.
*
*
* @version 0.1.0
* @param string $file Filename.
* @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.
*
*
* @version 0.1.0
* @throws E_OTS_FileLoaderError When error occurs during file operation.
* @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.
*
*
* @version 0.1.0
* @since 0.1.0
* @return OTS_HousesList Houses from external file.
@@ -488,7 +488,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Returns map width.
*
*
* @return int Map width.
*/
public function getWidth()
@@ -498,7 +498,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Returns map height.
*
*
* @return int Map height.
*/
public function getHeight()
@@ -508,7 +508,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Returns map description.
*
*
* @return string Map description.
*/
public function getDescription()
@@ -518,11 +518,11 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Returns map waypoints list.
*
*
* <p>
* Each item of returned array is sub-array with list of waypoints.
* </p>
*
*
* @version 0.1.6
* @since 0.1.6
* @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.
*
*
* @version 0.1.3
* @since 0.1.3
* @param int $id ID.
@@ -547,7 +547,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Returns town's ID.
*
*
* @version 0.1.3
* @param string $name Town.
* @return int ID.
@@ -567,7 +567,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Checks if given town name exists on list.
*
*
* @version 0.1.3
* @since 0.1.3
* @param string $name Town.
@@ -580,7 +580,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Returns name of given town's ID.
*
*
* @version 0.1.3
* @param int $id Town ID.
* @return string Name.
@@ -607,7 +607,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Returns town's temple position.
*
*
* @param int $id Town id.
* @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.
*
*
* @version 0.0.8
* @since 0.0.8
* @return int Count of towns.
*/
public function count()
public function count(): int
{
return count($this->towns);
}
@@ -690,7 +690,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Returns iterator handle for loops.
*
*
* @version 0.1.0
* @since 0.1.0
* @return ArrayIterator Towns list iterator.
@@ -702,7 +702,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Checks if given element exists.
*
*
* @version 0.1.0
* @since 0.1.0
* @param string|int $offset Array key.
@@ -724,7 +724,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Returns item from given position.
*
*
* @version 0.1.0
* @since 0.1.0
* @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.
*
*
* @version 0.1.0
* @since 0.1.0
* @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.
*
*
* @version 0.1.0
* @since 0.1.0
* @param string|int $offset Array key.
@@ -781,7 +781,7 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Magic PHP5 method.
*
*
* @version 0.1.0
* @since 0.1.0
* @param string $name Property name.
@@ -814,11 +814,11 @@ class OTS_OTBMFile extends OTS_FileLoader implements IteratorAggregate, Countabl
/**
* Returns string representation of object.
*
*
* <p>
* If any display driver is currently loaded then it uses it's method.
* </p>
*
*
* @version 0.1.3
* @since 0.1.3
* @return string String representation of object.

View File

@@ -602,7 +602,7 @@ class OTS_Player extends OTS_Row_DAO
}
$account = new OTS_Account();
$account->load($this->data['account_id']);
$account->load($this->data['account_id'], false, true);
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();
if($value !== false)
if($value === false)
{
return null;
}

View File

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

View File

@@ -15,7 +15,7 @@
/**
* Wrapper for vocations.xml file.
*
*
* @package POT
* @version 0.1.3
* @example examples/vocations.php vocations.php
@@ -25,14 +25,14 @@ class OTS_VocationsList implements IteratorAggregate, Countable, ArrayAccess
{
/**
* List of vocations.
*
*
* @var array
*/
private $vocations = array();
/**
* Loads vocations list from given file.
*
*
* @param string $file vocations.xml file location.
* @throws DOMException On DOM operation error.
*/
@@ -51,11 +51,11 @@ class OTS_VocationsList implements IteratorAggregate, Countable, ArrayAccess
/**
* Magic PHP5 method.
*
*
* <p>
* Allows object importing from {@link http://www.php.net/manual/en/function.var-export.php var_export()}.
* </p>
*
*
* @param array $properties List of object properties.
* @throws DOMException On DOM operation error.
*/
@@ -74,7 +74,7 @@ class OTS_VocationsList implements IteratorAggregate, Countable, ArrayAccess
/**
* Checks if given vocation ID exists on list.
*
*
* @version 0.1.3
* @since 0.1.3
* @param int $id ID.
@@ -87,7 +87,7 @@ class OTS_VocationsList implements IteratorAggregate, Countable, ArrayAccess
/**
* Returns vocation's ID.
*
*
* @version 0.1.3
* @param string $name Vocation.
* @return int ID.
@@ -108,7 +108,7 @@ class OTS_VocationsList implements IteratorAggregate, Countable, ArrayAccess
/**
* Checks if given vocation name exists on list.
*
*
* @version 0.1.3
* @since 0.1.3
* @param string $name Vocation.
@@ -121,7 +121,7 @@ class OTS_VocationsList implements IteratorAggregate, Countable, ArrayAccess
/**
* Returns name of given vocation's ID.
*
*
* @version 0.1.3
* @param int $id Vocation ID.
* @return string Name.
@@ -139,17 +139,17 @@ class OTS_VocationsList implements IteratorAggregate, Countable, ArrayAccess
/**
* Returns amount of vocations loaded.
*
*
* @return int Count of vocations.
*/
public function count()
public function count(): int
{
return count($this->vocations);
}
/**
* Returns iterator handle for loops.
*
*
* @return ArrayIterator Vocations list iterator.
*/
public function getIterator()
@@ -159,7 +159,7 @@ class OTS_VocationsList implements IteratorAggregate, Countable, ArrayAccess
/**
* Checks if given element exists.
*
*
* @version 0.1.3
* @param string|int $offset Array key.
* @return bool True if it's set.
@@ -178,7 +178,7 @@ class OTS_VocationsList implements IteratorAggregate, Countable, ArrayAccess
/**
* Returns item from given position.
*
*
* @version 0.1.3
* @param string|int $offset Array key.
* @return string|int If key is an integer (type-sensitive!) then returns vocation name. If it's a string then return associated ID.
@@ -197,7 +197,7 @@ class OTS_VocationsList implements IteratorAggregate, Countable, ArrayAccess
/**
* This method is implemented for ArrayAccess interface. In fact you can't write/append to vocations list. Any call to this method will cause {@link E_OTS_ReadOnly E_OTS_ReadOnly} raise.
*
*
* @param string|int $offset Array key.
* @param mixed $value Field value.
* @throws E_OTS_ReadOnly Always - this class is read-only.
@@ -209,7 +209,7 @@ class OTS_VocationsList implements IteratorAggregate, Countable, ArrayAccess
/**
* This method is implemented for ArrayAccess interface. In fact you can't write/append to vocations list. Any call to this method will cause {@link E_OTS_ReadOnly E_OTS_ReadOnly} raise.
*
*
* @param string|int $offset Array key.
* @throws E_OTS_ReadOnly Always - this class is read-only.
*/

285
system/libs/rfc6238.php Normal file
View File

@@ -0,0 +1,285 @@
<?php
/** https://github.com/Voronenko/PHPOTP/blob/08cda9cb9c30b7242cf0b3a9100a6244a2874927/code/base32static.php
* Encode in Base32 based on RFC 4648.
* Requires 20% more space than base64
* Great for case-insensitive filesystems like Windows and URL's (except for = char which can be excluded using the pad option for urls)
*
* @package default
* @author Bryan Ruiz
**/
class Base32Static {
private static $map = array(
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23
'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31
'=' // padding character
);
private static $flippedMap = array(
'A'=>'0', 'B'=>'1', 'C'=>'2', 'D'=>'3', 'E'=>'4', 'F'=>'5', 'G'=>'6', 'H'=>'7',
'I'=>'8', 'J'=>'9', 'K'=>'10', 'L'=>'11', 'M'=>'12', 'N'=>'13', 'O'=>'14', 'P'=>'15',
'Q'=>'16', 'R'=>'17', 'S'=>'18', 'T'=>'19', 'U'=>'20', 'V'=>'21', 'W'=>'22', 'X'=>'23',
'Y'=>'24', 'Z'=>'25', '2'=>'26', '3'=>'27', '4'=>'28', '5'=>'29', '6'=>'30', '7'=>'31'
);
/**
* Use padding false when encoding for urls
*
* @return base32 encoded string
* @author Bryan Ruiz
**/
public static function encode($input, $padding = true) {
if(empty($input)) return "";
$input = str_split($input);
$binaryString = "";
for($i = 0; $i < count($input); $i++) {
$binaryString .= str_pad(base_convert(ord($input[$i]), 10, 2), 8, '0', STR_PAD_LEFT);
}
$fiveBitBinaryArray = str_split($binaryString, 5);
$base32 = "";
$i=0;
while($i < count($fiveBitBinaryArray)) {
$base32 .= self::$map[base_convert(str_pad($fiveBitBinaryArray[$i], 5,'0'), 2, 10)];
$i++;
}
if($padding && ($x = strlen($binaryString) % 40) != 0) {
if($x == 8) $base32 .= str_repeat(self::$map[32], 6);
else if($x == 16) $base32 .= str_repeat(self::$map[32], 4);
else if($x == 24) $base32 .= str_repeat(self::$map[32], 3);
else if($x == 32) $base32 .= self::$map[32];
}
return $base32;
}
public static function decode($input) {
if(empty($input)) return;
$paddingCharCount = substr_count($input, self::$map[32]);
$allowedValues = array(6,4,3,1,0);
if(!in_array($paddingCharCount, $allowedValues)) return false;
for($i=0; $i<4; $i++){
if($paddingCharCount == $allowedValues[$i] &&
substr($input, -($allowedValues[$i])) != str_repeat(self::$map[32], $allowedValues[$i])) return false;
}
$input = str_replace('=','', $input);
$input = str_split($input);
$binaryString = "";
for($i=0; $i < count($input); $i = $i+8) {
$x = "";
if(!in_array($input[$i], self::$map)) return false;
for($j=0; $j < 8; $j++) {
$x .= str_pad(base_convert(@self::$flippedMap[@$input[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);
}
$eightBits = str_split($x, 8);
for($z = 0; $z < count($eightBits); $z++) {
$binaryString .= ( ($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48 ) ? $y:"";
}
}
return $binaryString;
}
}
// http://www.faqs.org/rfcs/rfc6238.html
// https://github.com/Voronenko/PHPOTP/blob/08cda9cb9c30b7242cf0b3a9100a6244a2874927/code/rfc6238.php
// Local changes: http -> https, consistent indentation, 200x200 -> 300x300 QR image size, PHP end tag
class TokenAuth6238 {
/**
* verify
*
* @param string $secretkey Secret clue (base 32).
* @return bool True if success, false if failure
*/
public static function verify($secretkey, $code, $rangein30s = 3) {
$key = base32static::decode($secretkey);
$unixtimestamp = time()/30;
for($i=-($rangein30s); $i<=$rangein30s; $i++) {
$checktime = (int)($unixtimestamp+$i);
$thiskey = self::oath_hotp($key, $checktime);
if ((int)$code == self::oath_truncate($thiskey,6)) {
return true;
}
}
return false;
}
public static function getTokenCode($secretkey,$rangein30s = 3) {
$result = "";
$key = base32static::decode($secretkey);
$unixtimestamp = time()/30;
for($i=-($rangein30s); $i<=$rangein30s; $i++) {
$checktime = (int)($unixtimestamp+$i);
$thiskey = self::oath_hotp($key, $checktime);
$result = $result." # ".self::oath_truncate($thiskey,6);
}
return $result;
}
public static function getTokenCodeDebug($secretkey,$rangein30s = 3) {
$result = "";
print "<br/>SecretKey: $secretkey <br/>";
$key = base32static::decode($secretkey);
print "Key(base 32 decode): $key <br/>";
$unixtimestamp = time()/30;
print "UnixTimeStamp (time()/30): $unixtimestamp <br/>";
for($i=-($rangein30s); $i<=$rangein30s; $i++) {
$checktime = (int)($unixtimestamp+$i);
print "Calculating oath_hotp from (int)(unixtimestamp +- 30sec offset): $checktime basing on secret key<br/>";
$thiskey = self::oath_hotp($key, $checktime, true);
print "======================================================<br/>";
print "CheckTime: $checktime oath_hotp:".$thiskey."<br/>";
$result = $result." # ".self::oath_truncate($thiskey,6,true);
}
return $result;
}
public static function getBarCodeUrl($username, $domain, $secretkey, $issuer) {
$url = "https://chart.apis.google.com/chart";
$url = $url."?chs=300x300&chld=M|0&cht=qr&chl=otpauth://totp/";
$url = $url.$username . "@" . $domain . "%3Fsecret%3D" . $secretkey . '%26issuer%3D' . rawurlencode($issuer);
return $url;
}
public static function generateRandomClue($length = 16) {
$b32 = "234567QWERTYUIOPASDFGHJKLZXCVBNM";
$s = "";
for ($i = 0; $i < $length; $i++)
$s .= $b32[rand(0,31)];
return $s;
}
private static function hotp_tobytestream($key) {
$result = array();
$last = strlen($key);
for ($i = 0; $i < $last; $i = $i + 2) {
$x = $key[$i] + $key[$i + 1];
$x = strtoupper($x);
$x = hexdec($x);
$result = $result.chr($x);
}
return $result;
}
private static function oath_hotp ($key, $counter, $debug=false) {
$result = "";
$orgcounter = $counter;
$cur_counter = array(0,0,0,0,0,0,0,0);
if ($debug) {
print "Packing counter $counter (".dechex($counter).")into binary string - pay attention to hex representation of key and binary representation<br/>";
}
for($i=7;$i>=0;$i--) { // C for unsigned char, * for repeating to the end of the input data
$cur_counter[$i] = pack ('C*', $counter);
if ($debug) {
print $cur_counter[$i]."(".dechex(ord($cur_counter[$i])).")"." from $counter <br/>";
}
$counter = $counter >> 8;
}
if ($debug) {
foreach ($cur_counter as $char) {
print ord($char) . " ";
}
print "<br/>";
}
$binary = implode($cur_counter);
// Pad to 8 characters
str_pad($binary, 8, chr(0), STR_PAD_LEFT);
if ($debug) {
print "Prior to HMAC calculation pad with zero on the left until 8 characters.<br/>";
print "Calculate sha1 HMAC(Hash-based Message Authentication Code http://en.wikipedia.org/wiki/HMAC).<br/>";
print "hash_hmac ('sha1', $binary, $key)<br/>";
}
$result = hash_hmac ('sha1', $binary, $key);
if ($debug) {
print "Result: $result <br/>";
}
return $result;
}
private static function oath_truncate($hash, $length = 6, $debug=false) {
$result="";
// Convert to dec
if($debug) {
print "converting hex hash into characters<br/>";
}
$hashcharacters = str_split($hash,2);
if($debug) {
print_r($hashcharacters);
print "<br/>and convert to decimals:<br/>";
}
for ($j=0; $j<count($hashcharacters); $j++) {
$hmac_result[]=hexdec($hashcharacters[$j]);
}
if($debug) {
print_r($hmac_result);
}
// http://php.net/manual/ru/function.hash-hmac.php
// adopted from brent at thebrent dot net 21-May-2009 08:17 comment
$offset = $hmac_result[19] & 0xf;
if($debug) {
print "Calculating offset as 19th element of hmac:".$hmac_result[19]."<br/>";
print "offset:".$offset;
}
$result = (
(($hmac_result[$offset+0] & 0x7f) << 24 ) |
(($hmac_result[$offset+1] & 0xff) << 16 ) |
(($hmac_result[$offset+2] & 0xff) << 8 ) |
($hmac_result[$offset+3] & 0xff)
) % pow(10,$length);
return $result;
}
}
?>

View File

@@ -354,16 +354,6 @@ class Validator
}
}
if(strspn($name, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM- '") != $name_length) {
self::$lastError = 'This name contains invalid letters, words or format. Please use only a-Z, - , \' and space.';
return false;
}
if(!preg_match("/[A-z ']/", $name)) {
self::$lastError = 'Your name containst illegal characters.';
return false;
}
return true;
}

View File

@@ -99,7 +99,10 @@ $locale['step_admin_account_id_error_same'] = 'Das Passwort darf nicht mit der K
$locale['step_admin_password'] = 'Administrator Konto Passwort';
$locale['step_admin_password_desc'] = 'Passwort für Ihr Administratorkonto.';
$locale['step_admin_password_error_empty'] = 'Bitte geben Sie das Passwort für Ihr neues Konto ein.';
$locale['step_admin_password_error_format'] = 'Ungültiges Passwortformat. Verwenden Sie nur a-Z und Ziffern 0-9. Mindestens 8, maximal 30 Zeichen.';
$locale['step_admin_password_error_format'] = 'Ungültiges Passwortformat. Mindestens eine Buchstabe und eine Ziffer. Mindestens 8, maximal 30 Zeichen.';
$locale['step_admin_password_confirm'] = 'Password wiederholen';
$locale['step_admin_password_confirm_desc'] = 'Passwort für dein Konto wiederholen.';
$locale['step_admin_password_confirm_error_not_same'] = 'Passwörter sind nicht gleich.';
// finish
$locale['step_finish_admin_panel'] = 'Admin Bereich';

View File

@@ -41,6 +41,7 @@ $locale['step_requirements_extension'] = '$EXTENSION$ PHP extension';
$locale['step_requirements_warning_images_guilds'] = 'Guild logo upload will not work';
$locale['step_requirements_warning_images_gallery'] = 'Gallery image upload will not work';
$locale['step_requirements_warning_player_signatures'] = 'Player Signatures will not work';
$locale['step_requirements_warning_install_plugins'] = 'It will be not possible to install plugins';
// config
$locale['step_config'] = 'Configuration';
@@ -113,7 +114,10 @@ $locale['step_admin_account_id_error_same'] = 'Password may not be the same as a
$locale['step_admin_password'] = 'Admin account password';
$locale['step_admin_password_desc'] = 'Password to your admin account.';
$locale['step_admin_password_error_empty'] = 'Please enter the password for your new account.';
$locale['step_admin_password_error_format'] = 'Invalid password format. Use only a-Z and numbers 0-9. Minimum 8, maximum 30 characters.';
$locale['step_admin_password_error_format'] = 'Invalid password format. Minimum one letter and one number. Minimum 8, maximum 30 characters.';
$locale['step_admin_password_confirm'] = 'Password confirm';
$locale['step_admin_password_confirm_desc'] = 'Repeat password to your account.';
$locale['step_admin_password_confirm_error_not_same'] = 'Passwords are not same.';
$locale['step_admin_player_name'] = 'Admin player name';
$locale['step_admin_player_name_desc'] = 'Name of your admin character.';
$locale['step_admin_player_name_error_empty'] = 'Please enter the name of your character.';

View File

@@ -41,6 +41,7 @@ $locale['step_requirements_extension'] = 'Rozszerzenie PHP - $EXTENSION$';
$locale['step_requirements_warning_images_guilds'] = 'Nie będzie możliwości uploadu obrazków gildii';
$locale['step_requirements_warning_images_gallery'] = 'Nie będzie możliwości uploadu obrazków do galerii';
$locale['step_requirements_warning_player_signatures'] = 'Sygnatury graczy nie będą działać';
$locale['step_requirements_warning_install_plugins'] = 'Nie będzie można instalować rozszerzeń';
// config
$locale['step_config'] = 'Konfiguracja';
@@ -112,7 +113,10 @@ $locale['step_admin_account_id_error_same'] = 'Hasło nie może być takie same
$locale['step_admin_password'] = 'Hasło Konta Admina';
$locale['step_admin_password_desc'] = 'Hasło do Twojego Konta Admina.';
$locale['step_admin_password_error_empty'] = 'Proszę podać hasło do Twojego nowego konta.';
$locale['step_admin_password_error_format'] = 'Nieprawidłowy format hasła. Używaj tylko znaków a-Z oraz liczb 0-9. Minimum 8, maksimum 30 znaków.';
$locale['step_admin_password_error_format'] = 'Nieprawidłowy format hasła. Minimum jeden znak i jedna liczba. Minimum 8, maksimum 30 znaków.';
$locale['step_admin_password_confirm'] = 'Potwierdź Hasło';
$locale['step_admin_password_confirm_desc'] = 'Potwierdzenie hasła do Twojego Konta Admina.';
$locale['step_admin_password_confirm_error_not_same'] = 'Hasła nie są takie same.';
$locale['step_admin_player_name'] = 'Nazwa postaci';
$locale['step_admin_player_name_desc'] = 'Nazwa postaci Konta Admina.';
$locale['step_admin_player_name_error_empty'] = 'Proszę podać nazwę postaci.';

View File

@@ -19,7 +19,7 @@ $locale['not_loaded'] = 'Não carregado';
$locale['loading_spinner'] = 'Por favor aguarde, instalando...';
$locale['importing_spinner'] = 'Por favor, aguarde, importando dados...';
$locale['please_fill_all'] = 'or favor, preencha todas as entradas!';
$locale['please_fill_all'] = 'Por favor, preencha todas as entradas!';
$locale['already_installed'] = 'MyAAC já foi instalado. Por favor, apague o diretório <b> install/ <b/>. Se você quiser reinstalar o MyAAC - exclua o arquivo <strong> config.local.php </strong> do diretório principal e atualize a página.';
// welcome

View File

@@ -11,11 +11,6 @@ defined('MYAAC') or die('Direct access not allowed!');
$logged = false;
$logged_flags = 0;
$action = isset($_REQUEST['action']) ? strtolower($_REQUEST['action']) : '';
if(!defined('ACTION')) {
define('ACTION', $action);
}
// stay-logged with sessions
$current_session = getSession('account');
if($current_session !== false)
@@ -33,133 +28,10 @@ if($current_session !== false)
}
}
if(ACTION === 'logout' && !isset($_REQUEST['account_login'])) {
if(isset($account_logged) && $account_logged->isLoaded()) {
if($hooks->trigger(HOOK_LOGOUT, array('account' => $account_logged, 'password' => getSession('password')))) {
unsetSession('account');
unsetSession('password');
unsetSession('remember_me');
$logged = false;
unset($account_logged);
if(isset($_REQUEST['redirect']))
{
header('Location: ' . urldecode($_REQUEST['redirect']));
exit;
}
}
}
}
else
{
// new login with data from form
if(!$logged && isset($_POST['account_login'], $_POST['password_login']))
{
$login_account = $_POST['account_login'];
$login_password = $_POST['password_login'];
$remember_me = isset($_POST['remember_me']);
if(!empty($login_account) && !empty($login_password))
{
if($cache->enabled())
{
$tmp = '';
if($cache->fetch('failed_logins', $tmp))
{
$tmp = unserialize($tmp);
$to_remove = array();
foreach($tmp as $ip => $t)
{
if(time() - $t['last'] >= 5 * 60)
$to_remove[] = $ip;
}
foreach($to_remove as $ip)
unset($tmp[$ip]);
}
else
$tmp = array();
$ip = $_SERVER['REMOTE_ADDR'];
$t = isset($tmp[$ip]) ? $tmp[$ip] : NULL;
}
$account_logged = new OTS_Account();
if(USE_ACCOUNT_NAME)
$account_logged->find($login_account);
else
$account_logged->load($login_account, true);
$config_salt_enabled = $db->hasColumn('accounts', 'salt');
if($account_logged->isLoaded() && encrypt(($config_salt_enabled ? $account_logged->getCustomField('salt') : '') . $login_password) == $account_logged->getPassword()
&& (!isset($t) || $t['attempts'] < 5)
)
{
setSession('account', $account_logged->getId());
setSession('password', encrypt(($config_salt_enabled ? $account_logged->getCustomField('salt') : '') . $login_password));
if($remember_me) {
setSession('remember_me', true);
}
$logged = true;
$logged_flags = $account_logged->getWebFlags();
if(isset($_POST['admin']) && !admin()) {
$errors[] = 'This account has no admin privileges.';
unsetSession('account');
unsetSession('password');
unsetSession('remember_me');
$logged = false;
}
else {
$account_logged->setCustomField('web_lastlogin', time());
}
$hooks->trigger(HOOK_LOGIN, array('account' => $account_logged, 'password' => $login_password, 'remember_me' => $remember_me));
}
else
{
$hooks->trigger(HOOK_LOGIN_ATTEMPT, array('account' => $login_account, 'password' => $login_password, 'remember_me' => $remember_me));
// temporary solution for blocking failed login attempts
if($cache->enabled())
{
if(isset($t))
{
$t['attempts']++;
$t['last'] = time();
if($t['attempts'] >= 5)
$errors[] = 'A wrong password has been entered 5 times in a row. You are unable to log into your account for the next 5 minutes. Please wait.';
else
$errors[] = 'Account name or password is not correct.';
}
else
{
$t = array('attempts' => 1, 'last' => time());
$errors[] = 'Account name or password is not correct.';
}
$tmp[$ip] = $t;
$cache->set('failed_logins', serialize($tmp), 60 * 60); // save for 1 hour
}
else {
$errors[] = 'Account name or password is not correct.';
}
}
}
else {
$errors[] = 'Please enter your account ' . (USE_ACCOUNT_NAME ? 'name' : 'number') . ' and password.';
$hooks->trigger(HOOK_LOGIN_ATTEMPT, array('account' => $login_account, 'password' => $login_password, 'remember_me' => $remember_me));
}
}
if($logged) {
$logged_flags = $account_logged->getWebFlags();
$twig->addGlobal('logged', true);
$twig->addGlobal('account_logged', $account_logged);
}
if($logged) {
$logged_flags = $account_logged->getWebFlags();
$twig->addGlobal('logged', true);
$twig->addGlobal('account_logged', $account_logged);
}
setSession('last_visit', time());

18
system/logout.php Normal file
View File

@@ -0,0 +1,18 @@
<?php
if(isset($account_logged) && $account_logged->isLoaded()) {
if($hooks->trigger(HOOK_LOGOUT, ['account_id' => $account_logged->getId()])) {
unsetSession('account');
unsetSession('password');
unsetSession('remember_me');
$logged = false;
unset($account_logged);
if(isset($_REQUEST['redirect']))
{
header('Location: ' . urldecode($_REQUEST['redirect']));
exit;
}
}
}

View File

@@ -3,12 +3,12 @@
$db->query("RENAME TABLE
" . TABLE_PREFIX . "screenshots TO " . TABLE_PREFIX . "gallery,
" . TABLE_PREFIX . "movies TO " . TABLE_PREFIX . "videos;");
// rename images dir
if(file_exists(BASE . 'images/screenshots') && !file_exists(BASE .'images/gallery')) {
rename(BASE . 'images/screenshots', BASE . 'images/gallery');
if(file_exists(BASE . 'images/screenshots') && !file_exists(BASE . GALLERY_DIR)) {
rename(BASE . 'images/screenshots', BASE . GALLERY_DIR);
}
// convert old database screenshots images to gallery
$query = $db->query('SELECT `id`, `image`, `thumb` FROM `' . TABLE_PREFIX . 'gallery`;');
foreach($query->fetchAll() as $item) {
@@ -17,4 +17,4 @@
'thumb' => str_replace('/screenshots/', '/gallery/', $item['thumb']),
), array('id' => $item['id']));
}
?>
?>

View File

@@ -1,13 +1,6 @@
<?php
// Increase size of ip in myaac_visitors table
// according to this answer: https://stackoverflow.com/questions/166132/maximum-length-of-the-textual-representation-of-an-ipv6-address
// the size of ipv6 can be maximal 45 chars
if(!$db->hasTable(TABLE_PREFIX . 'settings')) {
$db->exec("CREATE TABLE `" . TABLE_PREFIX . "settings`
(
`id` int(11) NOT NULL AUTO_INCREMENT,
`plugin_name` VARCHAR(255) NOT NULL DEFAULT '',
`key` VARCHAR(255) NOT NULL DEFAULT '',
`value` TEXT NOT NULL,
PRIMARY KEY (`id`),
KEY `key` (`key`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;");
}
$db->exec('ALTER TABLE `' . TABLE_PREFIX . "visitors` MODIFY `ip` VARCHAR(45) NOT NULL;");

16
system/pages/405.php Normal file
View File

@@ -0,0 +1,16 @@
<?php
/**
* 405 error page
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2021 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = '405 Method Not Allowed';
header('HTTP/1.0 405 Method Not Allowed');
?>
<h1>Method not allowed</h1>
<p>The requested method: <?php echo $_SERVER['REQUEST_METHOD']; ?> for URL <?php echo $_SERVER['REQUEST_URI']; ?> was not found on this server.</p>

View File

@@ -0,0 +1,29 @@
<?php
/**
* Account confirm mail
* Keept for compability
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
if(!$logged)
{
if(!empty($errors))
$twig->display('error_box.html.twig', array('errors' => $errors));
$twig->display('account.login.html.twig', array(
'redirect' => $_REQUEST['redirect'] ?? null,
'account' => USE_ACCOUNT_NAME ? 'Name' : 'Number',
'account_login_by' => getAccountLoginByLabel(),
'error' => $errors[0] ?? null
));
return;
}
else {
$show_form = true;
}

View File

@@ -10,6 +10,13 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Change Comment';
require __DIR__ . '/base.php';
if(!$logged) {
return;
}
$player_name = isset($_REQUEST['name']) ? stripslashes(urldecode($_REQUEST['name'])) : null;
$new_comment = isset($_POST['comment']) ? htmlspecialchars(stripslashes(substr($_POST['comment'],0,2000))) : NULL;
$new_hideacc = isset($_POST['accountvisible']) ? (int)$_POST['accountvisible'] : NULL;
@@ -56,4 +63,4 @@ if($show_form) {
));
}
}
?>
?>

View File

@@ -10,6 +10,13 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Change E-Mail';
require __DIR__ . '/base.php';
if(!$logged) {
return;
}
$email_new_time = $account_logged->getCustomField("email_new_time");
if($email_new_time > 10) {
@@ -29,7 +36,7 @@ if($email_new_time < 10) {
$errors[] = 'Please enter password to your account.';
}
else {
$post_password = encrypt(($config_salt_enabled ? $account_logged->getCustomField('salt') : '') . $post_password);
$post_password = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $post_password);
if($post_password != $account_logged->getPassword()) {
$errors[] = 'Wrong password to account.';
}
@@ -159,4 +166,4 @@ if(isset($_POST['emailchangecancel']) && $_POST['emailchangecancel'] == 1) {
'custom_buttons' => $custom_buttons
));
}
?>
?>

View File

@@ -10,6 +10,16 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Change Info';
require __DIR__ . '/base.php';
if(!$logged) {
return;
}
if($config['account_country'])
require SYSTEM . 'countries.conf.php';
$show_form = true;
$new_rlname = isset($_POST['info_rlname']) ? htmlspecialchars(stripslashes($_POST['info_rlname'])) : NULL;
$new_location = isset($_POST['info_location']) ? htmlspecialchars(stripslashes($_POST['info_location'])) : NULL;
@@ -53,10 +63,10 @@ if($show_form) {
}
$twig->display('account.change_info.html.twig', array(
'countries' => isset($countries) ? $countries : [],
'countries' => $countries ?? [],
'account_rlname' => $account_rlname,
'account_location' => $account_location,
'account_country' => isset($account_country) ? $account_country : ''
'account_country' => $account_country ?? ''
));
}
?>
?>

View File

@@ -10,6 +10,13 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Change Name';
require __DIR__ . '/base.php';
if(!$logged) {
return;
}
$player_id = isset($_POST['player_id']) ? (int)$_POST['player_id'] : NULL;
$name = isset($_POST['name']) ? stripslashes(ucwords(strtolower($_POST['name']))) : NULL;
if((!$config['account_change_character_name']))
@@ -52,6 +59,29 @@ else
$old_name = $player->getName();
$player->setName($name);
$player->save();
if ($db->hasTable('player_deaths') &&
$db->hasColumn('player_deaths', 'mostdamage_is_player') &&
$db->hasColumn('player_deaths', 'killed_by')) {
$namesToChange = $db->query('SELECT `player_id`, `time`, `is_player`, `killed_by`, `mostdamage_is_player`, `mostdamage_by` FROM `player_deaths` WHERE (`is_player` = 1 AND `killed_by` = ' . $db->quote($old_name) . ') OR (`mostdamage_is_player` = 1 AND `mostdamage_by` = ' . $db->quote($old_name) . ');');
if ($namesToChange->rowCount() > 0) {
foreach ($namesToChange->fetchAll(PDO::FETCH_ASSOC) as $row) {
$changeKey = '';
if ($row['is_player'] == '1' && $row['killed_by'] == $old_name) {
$changeKey = 'killed_by';
} else if ($row['mostdamage_is_player'] == '1' && $row['mostdamage_by'] == $old_name) {
$changeKey = 'mostdamage_by';
}
if (!empty($changeKey)) {
$db->update('player_deaths', [$changeKey => $name], ['player_id' => $row['player_id'], 'time' => $row['time']]);
}
}
}
}
$account_logged->setCustomField("premium_points", $points - $config['account_change_character_name_points']);
$account_logged->logAction('Changed name from <b>' . $old_name . '</b> to <b>' . $player->getName() . '</b>.');
$twig->display('success.html.twig', array(
@@ -83,4 +113,4 @@ else
}
}
?>
?>

View File

@@ -10,9 +10,16 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$new_password = isset($_POST['newpassword']) ? $_POST['newpassword'] : NULL;
$new_password2 = isset($_POST['newpassword2']) ? $_POST['newpassword2'] : NULL;
$old_password = isset($_POST['oldpassword']) ? $_POST['oldpassword'] : NULL;
$title = 'Change Password';
require __DIR__ . '/base.php';
if(!$logged) {
return;
}
$new_password = $_POST['newpassword'] ?? NULL;
$new_password2 = $_POST['newpassword2'] ?? NULL;
$old_password = $_POST['oldpassword'] ?? NULL;
if(empty($new_password) && empty($new_password2) && empty($old_password)) {
$twig->display('account.change_password.html.twig');
}
@@ -32,7 +39,7 @@ else
}
/** @var OTS_Account $account_logged */
$old_password = encrypt(($config_salt_enabled ? $account_logged->getCustomField('salt') : '') . $old_password);
$old_password = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $old_password);
if($old_password != $account_logged->getPassword()) {
$errors[] = "Current password is incorrect!";
}
@@ -48,7 +55,7 @@ else
{
$org_pass = $new_password;
if($config_salt_enabled)
if(USE_ACCOUNT_SALT)
{
$salt = generateRandomString(10, false, true, true);
$new_password = $salt . $new_password;
@@ -82,4 +89,4 @@ else
}
}
?>
?>

View File

@@ -10,6 +10,13 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Change Sex';
require __DIR__ . '/base.php';
if(!$logged) {
return;
}
$sex_changed = false;
$player_id = isset($_POST['player_id']) ? (int)$_POST['player_id'] : NULL;
$new_sex = isset($_POST['new_sex']) ? (int)$_POST['new_sex'] : NULL;
@@ -85,4 +92,4 @@ else
}
}
?>
?>

View File

@@ -11,7 +11,7 @@ defined('MYAAC') or die('Direct access not allowed!');
$title = 'Confirm Email';
$hash = isset($_GET['v']) ? $_GET['v'] : '';
$hash = $_GET['hash'] ?? '';
if(empty($hash)) {
warning('Please enter email hash code.<br/>If you copied the link, please try again with full link.');
return;
@@ -23,6 +23,16 @@ if(!$res->rowCount()) {
}
else
{
$query = $db->query('SELECT id FROM accounts WHERE email_hash = ' . $db->quote($hash) . ' AND email_verified = 0');
if ($query->rowCount() == 1) {
$query = $query->fetch(PDO::FETCH_ASSOC);
$account = new OTS_Account();
$account->load($query['id']);
if ($account->isLoaded()) {
$hooks->trigger(HOOK_EMAIL_CONFIRMED, ['account' => $account]);
}
}
$db->update('accounts', array('email_verified' => '1'), array('email_hash' => $hash));
success('You have now verified your e-mail, this will increase the security of your account. Thank you for doing this.');
}

View File

@@ -34,11 +34,13 @@ $errors = array();
$save = isset($_POST['save']) && $_POST['save'] == 1;
if($save)
{
if(USE_ACCOUNT_NAME) {
$account_name = $_POST['account'];
}
else {
$account_id = $_POST['account'];
if(!config('account_login_by_email')) {
if(USE_ACCOUNT_NAME) {
$account_name = $_POST['account'];
}
else {
$account_id = $_POST['account'];
}
}
$email = $_POST['email'];
@@ -46,12 +48,14 @@ if($save)
$password2 = $_POST['password2'];
// account
if(isset($account_id)) {
if(!Validator::accountId($account_id))
if(!config('account_login_by_email')) {
if (isset($account_id)) {
if (!Validator::accountId($account_id)) {
$errors['account'] = Validator::getLastError();
}
} else if (!Validator::accountName($account_name))
$errors['account'] = Validator::getLastError();
}
else if(!Validator::accountName($account_name))
$errors['account'] = Validator::getLastError();
// email
if(!Validator::email($email))
@@ -68,19 +72,6 @@ if($save)
$errors['country'] = 'Country is invalid.';
}
if($config['recaptcha_enabled'])
{
if(isset($_POST['g-recaptcha-response']) && !empty($_POST['g-recaptcha-response']))
{
$verifyResponse = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$config['recaptcha_secret_key'].'&response='.$_POST['g-recaptcha-response']);
$responseData = json_decode($verifyResponse);
if(!$responseData->success)
$errors['verification'] = "Please confirm that you're not a robot.";
}
else
$errors['verification'] = "Please confirm that you're not a robot.";
}
// password
if(empty($password)) {
$errors['password'] = 'Please enter the password for your new account.';
@@ -93,7 +84,7 @@ if($save)
}
// check if account name is not equal to password
if(USE_ACCOUNT_NAME && strtoupper($account_name) == strtoupper($password)) {
if(!config('account_login_by_email') && USE_ACCOUNT_NAME && strtoupper($account_name) == strtoupper($password)) {
$errors['password'] = 'Password may not be the same as account name.';
}
@@ -106,16 +97,28 @@ if($save)
}
$account_db = new OTS_Account();
if(USE_ACCOUNT_NAME)
$account_db->find($account_name);
else
$account_db->load($account_id);
if (config('account_login_by_email')) {
$account_db->findByEMail($email);
}
else {
if(USE_ACCOUNT_NAME) {
$account_db->find($account_name);
}
else {
$account_db->load($account_id);
}
}
if($account_db->isLoaded()) {
if(USE_ACCOUNT_NAME)
$errors['account'] = 'Account with this name already exist.';
else
$errors['account'] = 'Account with this id already exist.';
if (config('account_login_by_email') && !config('account_mail_unique')) {
$errors['account'] = 'Account with this email already exist.';
}
else if (!config('account_login_by_email')) {
if (USE_ACCOUNT_NAME)
$errors['account'] = 'Account with this name already exist.';
else
$errors['account'] = 'Account with this id already exist.';
}
}
if(!isset($_POST['accept_rules']) || $_POST['accept_rules'] !== 'true')
@@ -130,14 +133,17 @@ if($save)
'accept_rules' => isset($_POST['accept_rules']) ? $_POST['accept_rules'] === 'true' : false,
);
if(USE_ACCOUNT_NAME) {
$params['account_name'] = $_POST['account'];
}
else {
$params['account_id'] = $_POST['account'];
if (!config('account_login_by_email')) {
if (USE_ACCOUNT_NAME) {
$params['account_name'] = $_POST['account'];
} else {
$params['account_id'] = $_POST['account'];
}
}
$hooks->trigger(HOOK_ACCOUNT_CREATE_AFTER_SUBMIT, $params);
if (!$hooks->trigger(HOOK_ACCOUNT_CREATE_POST, $params)) {
return;
}
if(config('account_create_character_create')) {
$character_name = isset($_POST['name']) ? stripslashes(ucwords(strtolower($_POST['name']))) : null;
@@ -151,13 +157,17 @@ if($save)
if(empty($errors))
{
$new_account = new OTS_Account();
if(USE_ACCOUNT_NAME)
$new_account->create($account_name);
else
$new_account->create(NULL, $account_id);
if (config('account_login_by_email')) {
$new_account->createWithEmail($email);
}
else {
if(USE_ACCOUNT_NAME)
$new_account->create($account_name);
else
$new_account->create(NULL, $account_id);
}
$config_salt_enabled = $db->hasColumn('accounts', 'salt');
if($config_salt_enabled)
if(USE_ACCOUNT_SALT)
{
$salt = generateRandomString(10, false, true, true);
$password = $salt . $password;
@@ -168,7 +178,7 @@ if($save)
$new_account->unblock();
$new_account->save();
if($config_salt_enabled)
if(USE_ACCOUNT_SALT)
$new_account->setCustomField('salt', $salt);
$new_account->setCustomField('created', time());
@@ -183,8 +193,13 @@ if($save)
$new_account->setCustomField('premend', time() + $config['account_premium_days'] * 86400);
}
else { // rest
$new_account->setCustomField('premdays', $config['account_premium_days']);
$new_account->setCustomField('lastday', time());
if ($db->hasColumn('accounts', 'premium_ends_at')) { // TFS 1.4+
$new_account->setCustomField('premium_ends_at', time() + $config['account_premium_days'] * (60 * 60 * 24));
}
else {
$new_account->setCustomField('premdays', $config['account_premium_days']);
$new_account->setCustomField('lastday', time());
}
}
}
@@ -192,7 +207,11 @@ if($save)
$new_account->setCustomField('premium_points', $config['account_premium_points']);
}
$tmp_account = (USE_ACCOUNT_NAME ? $account_name : $account_id);
$tmp_account = $email;
if (!config('account_login_by_email')) {
$tmp_account = (USE_ACCOUNT_NAME ? $account_name : $account_id);
}
if($config['mail_enabled'] && $config['account_mail_verify'])
{
$hash = md5(generateRandomString(16, true, true) . $email);
@@ -223,6 +242,14 @@ if($save)
}
else
{
if(config('account_create_character_create')) {
// character creation
$character_created = $createCharacter->doCreate($character_name, $character_sex, $character_vocation, $character_town, $new_account, $errors);
if (!$character_created) {
error('There was an error creating your character. Please create your character later in account management page.');
}
}
if($config['account_create_auto_login']) {
$_POST['account_login'] = USE_ACCOUNT_NAME ? $account_name : $account_id;
$_POST['password_login'] = $password2;
@@ -265,14 +292,6 @@ if($save)
error('An error occurred while sending email. For Admin: More info can be found in system/logs/mailer-error.log');
}
}
if(config('account_create_character_create')) {
// character creation
$character_created = $createCharacter->doCreate($character_name, $character_sex, $character_vocation, $character_town, $new_account, $errors);
if (!$character_created) {
error('There was an error creating your character. Please create your character later in account management page.');
}
}
}
return;

View File

@@ -10,6 +10,13 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Create Character';
require __DIR__ . '/base.php';
if(!$logged) {
return;
}
$character_name = isset($_POST['name']) ? stripslashes($_POST['name']) : null;
$character_sex = isset($_POST['sex']) ? (int)$_POST['sex'] : null;
$character_vocation = isset($_POST['vocation']) ? (int)$_POST['vocation'] : null;

View File

@@ -10,9 +10,16 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Delete Character';
require __DIR__ . '/base.php';
if(!$logged) {
return;
}
$player_name = isset($_POST['delete_name']) ? stripslashes($_POST['delete_name']) : null;
$password_verify = isset($_POST['delete_password']) ? $_POST['delete_password'] : null;
$password_verify = encrypt(($config_salt_enabled ? $account_logged->getCustomField('salt') : '') . $password_verify);
$password_verify = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $password_verify);
if(isset($_POST['deletecharactersave']) && $_POST['deletecharactersave'] == 1) {
if(empty($player_name) || empty($password_verify)) {
$errors[] = 'Character name or/and password is empty. Please fill in form.';

View File

@@ -0,0 +1,113 @@
<?php
// new login with data from form
if(!$logged && isset($_POST['account_login'], $_POST['password_login']))
{
$login_account = $_POST['account_login'];
$login_password = $_POST['password_login'];
$remember_me = isset($_POST['remember_me']);
if(!empty($login_account) && !empty($login_password))
{
if($cache->enabled())
{
$tmp = '';
if($cache->fetch('failed_logins', $tmp))
{
$tmp = unserialize($tmp);
$to_remove = array();
foreach($tmp as $ip => $t)
{
if(time() - $t['last'] >= 5 * 60)
$to_remove[] = $ip;
}
foreach($to_remove as $ip)
unset($tmp[$ip]);
}
else
$tmp = array();
$ip = $_SERVER['REMOTE_ADDR'];
$t = $tmp[$ip] ?? null;
}
$account_logged = new OTS_Account();
if (config('account_login_by_email')) {
$account_logged->findByEMail($login_account);
}
if (!config('account_login_by_email') || config('account_login_by_email_fallback')) {
if(USE_ACCOUNT_NAME) {
$account_logged->find($login_account);
} else {
$account_logged->load($login_account, true);
}
}
if($account_logged->isLoaded() && encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $login_password) == $account_logged->getPassword()
&& (!isset($t) || $t['attempts'] < 5)
)
{
setSession('account', $account_logged->getNumber());
setSession('password', encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $login_password));
if($remember_me) {
setSession('remember_me', true);
}
$logged = true;
$logged_flags = $account_logged->getWebFlags();
if(isset($_POST['admin']) && !admin()) {
$errors[] = 'This account has no admin privileges.';
unsetSession('account');
unsetSession('password');
unsetSession('remember_me');
$logged = false;
}
else {
$account_logged->setCustomField('web_lastlogin', time());
}
$hooks->trigger(HOOK_LOGIN, array('account' => $account_logged, 'password' => $login_password, 'remember_me' => $remember_me));
}
else
{
$hooks->trigger(HOOK_LOGIN_ATTEMPT, array('account' => $login_account, 'password' => $login_password, 'remember_me' => $remember_me));
$errorMessage = getAccountLoginByLabel() . ' or password is not correct.';
// temporary solution for blocking failed login attempts
if($cache->enabled())
{
if(isset($t))
{
$t['attempts']++;
$t['last'] = time();
if($t['attempts'] >= 5)
$errors[] = 'A wrong password has been entered 5 times in a row. You are unable to log into your account for the next 5 minutes. Please wait.';
else
$errors[] = $errorMessage;
}
else
{
$t = array('attempts' => 1, 'last' => time());
$errors[] = $errorMessage;
}
$tmp[$ip] = $t;
$cache->set('failed_logins', serialize($tmp), 60 * 60); // save for 1 hour
}
else {
$errors[] = $errorMessage;
}
}
}
else {
$errors[] = 'Please enter your ' . getAccountLoginByLabel() . ' and password.';
$hooks->trigger(HOOK_LOGIN_ATTEMPT, array('account' => $login_account, 'password' => $login_password, 'remember_me' => $remember_me));
}
$hooks->trigger(HOOK_ACCOUNT_LOGIN_POST);
}

View File

@@ -0,0 +1,22 @@
<?php
/**
* Logout Account
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2021 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Logout';
require __DIR__ . '/base.php';
if(!$logged) {
return;
}
require SYSTEM . 'logout.php';
$twig->display('account.logout.html.twig');

View File

@@ -17,7 +17,6 @@ if(!$config['mail_enabled'])
return;
}
$config_salt_enabled = $db->hasColumn('accounts', 'salt');
$action_type = isset($_REQUEST['action_type']) ? $_REQUEST['action_type'] : '';
if($action == '')
{
@@ -111,7 +110,7 @@ elseif($action == 'sendcode')
else
{
$account->setCustomField('email_next', (time() + 60));
echo '<br /><p class="error">An error occorred while sending email! Try again later or contact with admin. For Admin: More info can be found in system/logs/mailer-error.log</p>';
echo '<br /><p class="error">An error occurred while sending email! Try again later or contact with admin. For Admin: More info can be found in system/logs/mailer-error.log</p>';
}
}
else
@@ -292,7 +291,7 @@ elseif($action == 'step3')
$account->setEMail($new_email);
$tmp_new_pass = $new_pass;
if($config_salt_enabled)
if(USE_ACCOUNT_SALT)
{
$salt = generateRandomString(10, false, true, true);
$tmp_new_pass = $salt . $new_pass;
@@ -301,7 +300,7 @@ elseif($action == 'step3')
$account->setPassword(encrypt($tmp_new_pass));
$account->save();
if($config_salt_enabled)
if(USE_ACCOUNT_SALT)
$account->setCustomField('salt', $salt);
echo 'Your account name, new password and new e-mail.<BR>
@@ -330,7 +329,7 @@ elseif($action == 'step3')
}
else
{
echo '<br /><p class="error">An error occorred while sending email! You will not receive e-mail with this informations. For Admin: More info can be found in system/logs/mailer-error.log</p>';
echo '<br /><p class="error">An error occurred while sending email! You will not receive e-mail with this informations. For Admin: More info can be found in system/logs/mailer-error.log</p>';
}
}
else
@@ -481,7 +480,7 @@ elseif($action == 'setnewpassword')
if(Validator::password($newpassword))
{
$tmp_new_pass = $newpassword;
if($config_salt_enabled)
if(USE_ACCOUNT_SALT)
{
$salt = generateRandomString(10, false, true, true);
$tmp_new_pass = $salt . $newpassword;
@@ -513,7 +512,7 @@ elseif($action == 'setnewpassword')
}
else
{
echo '<br /><p class="error">New password work! An error occorred while sending email! You will not receive e-mail with new password. For Admin: More info can be found in system/logs/mailer-error.log';
echo '<br /><p class="error">New password work! An error occurred while sending email! You will not receive e-mail with new password. For Admin: More info can be found in system/logs/mailer-error.log';
}
echo '</TD></TR>
</TABLE>

View File

@@ -0,0 +1,98 @@
<?php
/**
* Account management
*
* @package MyAAC
* @author Gesior <jerzyskalski@wp.pl>
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Account Management';
require __DIR__ . '/login.php';
require __DIR__ . '/base.php';
if(!$logged) {
return;
}
$groups = new OTS_Groups_List();
$freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']) || $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS;
$dayOrDays = $account_logged->getPremDays() == 1 ? 'day' : 'days';
/**
* @var OTS_Account $account_logged
*/
if(!$account_logged->isPremium())
$account_status = '<b><span style="color: red">Free Account</span></b>';
else
$account_status = '<b><span style="color: green">' . ($freePremium ? 'Gratis Premium Account' : 'Premium Account, ' . $account_logged->getPremDays() . ' '.$dayOrDays.' left') . '</span></b>';
$recovery_key = $account_logged->getCustomField('key');
if(empty($recovery_key))
$account_registered = '<b><span style="color: red">No</span></b>';
else
{
if($config['generate_new_reckey'] && $config['mail_enabled'])
$account_registered = '<b><span style="color: green">Yes ( <a href="' . getLink('account/register/new') . '"> Buy new Recovery Key </a> )</span></b>';
else
$account_registered = '<b><span style="color: green">Yes</span></b>';
}
$account_created = $account_logged->getCreated();
$account_email = $account_logged->getEMail();
$email_new_time = $account_logged->getCustomField("email_new_time");
if($email_new_time > 1)
$email_new = $account_logged->getCustomField("email_new");
$account_rlname = $account_logged->getRLName();
$account_location = $account_logged->getLocation();
if($account_logged->isBanned())
if($account_logged->getBanTime() > 0)
$welcome_message = '<span style="color: red">Your account is banished until '.date("j F Y, G:i:s", $account_logged->getBanTime()).'!</span>';
else
$welcome_message = '<span style="color: red">Your account is banished FOREVER!</span>';
else
$welcome_message = 'Welcome to your account!';
$email_change = '';
$email_request = false;
if($email_new_time > 1)
{
if($email_new_time < time())
$email_change = '<br>(You can accept <b>'.$email_new.'</b> as a new email.)';
else
{
$email_change = ' <br>You can accept <b>new e-mail after '.date("j F Y", $email_new_time).".</b>";
$email_request = true;
}
}
$actions = array();
foreach($account_logged->getActionsLog(0, 1000) as $action) {
$actions[] = array('action' => $action['action'], 'date' => $action['date'], 'ip' => $action['ip'] != 0 ? long2ip($action['ip']) : inet_ntop($action['ipv6']));
}
$players = array();
/** @var OTS_Players_List $account_players */
$account_players = $account_logged->getPlayersList();
$account_players->orderBy('id');
$twig->display('account.management.html.twig', array(
'welcome_message' => $welcome_message,
'recovery_key' => $recovery_key,
'email_change' => $email_change,
'email_request' => $email_request,
'email_new_time' => $email_new_time,
'email_new' => isset($email_new) ? $email_new : '',
'account' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId(),
'account_email' => $account_email,
'account_created' => $account_created,
'account_status' => $account_status,
'account_registered' => $account_registered,
'account_rlname' => $account_rlname,
'account_location' => $account_location,
'actions' => $actions,
'players' => $account_players
));

View File

@@ -1,16 +1,17 @@
<?php
/**
* Account confirm mail
* Keept for compability
* Change comment
*
* @package MyAAC
* @author Gesior <jerzyskalski@wp.pl>
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
if($action == 'confirm_email') {
require_once PAGES . 'account/confirm_email.php';
}
?>
$redirect = urldecode($_REQUEST['redirect']);
$twig->display('account.redirect.html.twig', array(
'redirect' => $redirect
));

View File

@@ -10,8 +10,15 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$_POST['reg_password'] = isset($_POST['reg_password']) ? $_POST['reg_password'] : '';
$reg_password = encrypt(($config_salt_enabled ? $account_logged->getCustomField('salt') : '') . $_POST['reg_password']);
$title = 'Register Account';
require __DIR__ . '/base.php';
if(!$logged) {
return;
}
$_POST['reg_password'] = $_POST['reg_password'] ?? '';
$reg_password = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $_POST['reg_password']);
$old_key = $account_logged->getCustomField("key");
if(isset($_POST['registeraccountsave']) && $_POST['registeraccountsave'] == "1") {
@@ -22,6 +29,7 @@ if(isset($_POST['registeraccountsave']) && $_POST['registeraccountsave'] == "1")
$account_logged->setCustomField("key", $new_rec_key);
$account_logged->logAction('Generated recovery key.');
$message = '';
if($config['mail_enabled'] && $config['send_mail_when_generate_reckey'])
{
@@ -54,5 +62,3 @@ if($show_form) {
//show form
$twig->display('account.generate_recovery_key.html.twig');
}
?>

View File

@@ -10,12 +10,21 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Register Account';
require __DIR__ . '/base.php';
if(!$logged) {
return;
}
if(isset($_POST['reg_password']))
$reg_password = encrypt(($config_salt_enabled ? $account_logged->getCustomField('salt') : '') . $_POST['reg_password']);
$reg_password = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $_POST['reg_password']);
$reckey = $account_logged->getCustomField('key');
if((!$config['generate_new_reckey'] || !$config['mail_enabled']) || empty($reckey))
echo 'You cant get new rec key';
if((!$config['generate_new_reckey'] || !$config['mail_enabled']) || empty($reckey)) {
$errors[] = 'You cant get new recovery key.';
$twig->display('error_box.html.twig', array('errors' => $errors));
}
else
{
$points = $account_logged->getCustomField('premium_points');
@@ -40,7 +49,7 @@ else
$message = '<br />Your recovery key were send on email address <b>'.$account_logged->getEMail().'</b> for '.$config['generate_new_reckey_price'].' premium points.';
}
else
$message = '<br /><p class="error">An error occorred while sending email ( <b>'.$account_logged->getEMail().'</b> ) with recovery key! Recovery key not changed. Try again later. For Admin: More info can be found in system/logs/mailer-error.log</p>';
$message = '<br /><p class="error">An error occurred while sending email ( <b>'.$account_logged->getEMail().'</b> ) with recovery key! Recovery key not changed. Try again later. For Admin: More info can be found in system/logs/mailer-error.log</p>';
$twig->display('success.html.twig', array(
'title' => 'Account Registered',
@@ -67,5 +76,3 @@ else
));
}
}
?>

View File

@@ -1,151 +0,0 @@
<?php
/**
* Account management
*
* @package MyAAC
* @author Gesior <jerzyskalski@wp.pl>
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Account Management';
if($config['account_country'])
require SYSTEM . 'countries.conf.php';
$groups = new OTS_Groups_List();
$show_form = true;
$config_salt_enabled = $db->hasColumn('accounts', 'salt');
if(ACTION == "logout" && !isset($_REQUEST['account_login'])) {
if(!defined('HOOK_LOGOUT_DISPLAY') || HOOK_LOGOUT_DISPLAY) { // plugin will take care of this message
$twig->display('account.logout.html.twig');
}
return;
}
if(!$logged)
{
if(ACTION == 'confirm_email') {
require PAGES . 'account/' . ACTION . '.php';
return;
}
if(!empty($errors))
$twig->display('error_box.html.twig', array('errors' => $errors));
$twig->display('account.login.html.twig', array(
'redirect' => isset($_REQUEST['redirect']) ? $_REQUEST['redirect'] : null,
'account' => USE_ACCOUNT_NAME ? 'Name' : 'Number',
'error' => isset($errors[0]) ? $errors[0] : null
));
return;
}
$errors = array();
if(isset($_REQUEST['redirect']))
{
$redirect = urldecode($_REQUEST['redirect']);
$twig->display('account.redirect.html.twig', array(
'redirect' => $redirect
));
return;
}
if($action == '')
{
$freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']) || $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS;
$dayOrDays = $account_logged->getPremDays() == 1 ? 'day' : 'days';
/**
* @var OTS_Account $account_logged
*/
if(!$account_logged->isPremium())
$account_status = '<b><span style="color: red">Free Account</span></b>';
else
$account_status = '<b><span style="color: green">' . ($freePremium ? 'Gratis Premium Account' : 'Premium Account, ' . $account_logged->getPremDays() . ' '.$dayOrDays.' left') . '</span></b>';
$recovery_key = $account_logged->getCustomField('key');
if(empty($recovery_key))
$account_registered = '<b><span style="color: red">No</span></b>';
else
{
if($config['generate_new_reckey'] && $config['mail_enabled'])
$account_registered = '<b><span style="color: green">Yes ( <a href="' . getLink('account/register/new') . '"> Buy new Recovery Key </a> )</span></b>';
else
$account_registered = '<b><span style="color: green">Yes</span></b>';
}
$account_created = $account_logged->getCreated();
$account_email = $account_logged->getEMail();
$email_new_time = $account_logged->getCustomField("email_new_time");
if($email_new_time > 1)
$email_new = $account_logged->getCustomField("email_new");
$account_rlname = $account_logged->getRLName();
$account_location = $account_logged->getLocation();
if($account_logged->isBanned())
if($account_logged->getBanTime() > 0)
$welcome_message = '<span style="color: red">Your account is banished until '.date("j F Y, G:i:s", $account_logged->getBanTime()).'!</span>';
else
$welcome_message = '<span style="color: red">Your account is banished FOREVER!</span>';
else
$welcome_message = 'Welcome to your account!';
$email_change = '';
$email_request = false;
if($email_new_time > 1)
{
if($email_new_time < time())
$email_change = '<br>(You can accept <b>'.$email_new.'</b> as a new email.)';
else
{
$email_change = ' <br>You can accept <b>new e-mail after '.date("j F Y", $email_new_time).".</b>";
$email_request = true;
}
}
$actions = array();
foreach($account_logged->getActionsLog(0, 1000) as $action) {
$actions[] = array('action' => $action['action'], 'date' => $action['date'], 'ip' => $action['ip'] != 0 ? long2ip($action['ip']) : inet_ntop($action['ipv6']));
}
$players = array();
/** @var OTS_Players_List $account_players */
$account_players = $account_logged->getPlayersList();
$account_players->orderBy('id');
$twig->display('account.management.html.twig', array(
'welcome_message' => $welcome_message,
'recovery_key' => $recovery_key,
'email_change' => $email_change,
'email_request' => $email_request,
'email_new_time' => $email_new_time,
'email_new' => isset($email_new) ? $email_new : '',
'account' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId(),
'account_email' => $account_email,
'account_created' => $account_created,
'account_status' => $account_status,
'account_registered' => $account_registered,
'account_rlname' => $account_rlname,
'account_location' => $account_location,
'actions' => $actions,
'players' => $account_players
));
}
else {
if(!ctype_alnum(str_replace(array('-', '_'), '', $action))) {
error('Error: Action contains illegal characters.');
}
else if(file_exists(PAGES . 'account/' . $action . '.php')) {
require PAGES . 'account/' . $action . '.php';
}
else {
error('This page does not exists.');
}
}
?>

View File

@@ -1,591 +0,0 @@
<?php
/**
* Account editor
*
* @package MyAAC
* @author Lee
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Account editor';
$admin_base = BASE_URL . 'admin/?p=accounts';
$use_datatable = true;
if ($config['account_country'])
require SYSTEM . 'countries.conf.php';
$hasSecretColumn = $db->hasColumn('accounts', 'secret');
$hasCoinsColumn = $db->hasColumn('accounts', 'coins');
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
$hasTypeColumn = $db->hasColumn('accounts', 'type');
$hasGroupColumn = $db->hasColumn('accounts', 'group_id');
if ($config['account_country']) {
$countries = array();
foreach (array('pl', 'se', 'br', 'us', 'gb') as $c)
$countries[$c] = $config['countries'][$c];
$countries['--'] = '----------';
foreach ($config['countries'] as $code => $c)
$countries[$code] = $c;
}
$web_acc = array("None", "Admin", "Super Admin", "(Admin + Super Admin)");
$acc_type = array("None", "Normal", "Tutor", "Senior Tutor", "Gamemaster", "God");
?>
<link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ >
<script src="<?php echo BASE_URL; ?>tools/js/jquery.datetimepicker.js"></script>
<?php
$id = 0;
$search_account = '';
if (isset($_REQUEST['id']))
$id = (int)$_REQUEST['id'];
else if (isset($_REQUEST['search'])) {
$search_account = $_REQUEST['search'];
if (strlen($search_account) < 3 && !Validator::number($search_account)) {
echo_error('Player name is too short.');
} else {
$query = $db->query('SELECT `id` FROM `accounts` WHERE `name` = ' . $db->quote($search_account));
if ($query->rowCount() == 1) {
$query = $query->fetch();
$id = (int)$query['id'];
} else {
$query = $db->query('SELECT `id`, `name` FROM `accounts` WHERE `name` LIKE ' . $db->quote('%' . $search_account . '%'));
if ($query->rowCount() > 0 && $query->rowCount() <= 10) {
$str_construct = 'Do you mean?<ul class="mb-0">';
foreach ($query as $row)
$str_construct .= '<li><a href="' . $admin_base . '&id=' . $row['id'] . '">' . $row['name'] . '</a></li>';
$str_construct .= '</ul>';
echo_error($str_construct);
} else if ($query->rowCount() > 10)
echo_error('Specified name resulted with too many accounts.');
else
echo_error('No entries found.');
}
}
}
?>
<div class="row">
<?php
$groups = new OTS_Groups_List();
if ($id > 0) {
$account = new OTS_Account();
$account->load($id);
if (isset($account, $_POST['save']) && $account->isLoaded()) {
$error = false;
$_error = '';
$account_db = new OTS_Account();
if (USE_ACCOUNT_NAME) {
$name = $_POST['name'];
$account_db->find($name);
if ($account_db->isLoaded() && $account->getName() != $name)
echo_error('This name is already used. Please choose another name!');
}
$account_db->load($id);
if (!$account_db->isLoaded())
echo_error('Account with this id doesn\'t exist.');
//type/group
if ($hasTypeColumn || $hasGroupColumn) {
$group = $_POST['group'];
}
$password = ((!empty($_POST["pass"]) ? $_POST['pass'] : null));
if (!Validator::password($password)) {
$errors['password'] = Validator::getLastError();
}
//secret
if ($hasSecretColumn) {
$secret = $_POST['secret'];
}
//key
$key = $_POST['key'];
$email = $_POST['email'];
if (!Validator::email($email))
$errors['email'] = Validator::getLastError();
//tibia coins
if ($hasCoinsColumn) {
$t_coins = $_POST['t_coins'];
verify_number($t_coins, 'Tibia coins', 12);
}
// prem days
$p_days = (int)$_POST['p_days'];
verify_number($p_days, 'Prem days', 11);
//prem points
$p_points = $_POST['p_points'];
verify_number($p_points, 'Prem Points', 11);
//rl name
$rl_name = $_POST['rl_name'];
//location
$rl_loca = $_POST['rl_loca'];
//country
$rl_country = $_POST['rl_country'];
$web_flags = $_POST['web_flags'];
verify_number($web_flags, 'Web Flags', 1);
//created
$created = strtotime($_POST['created']);
verify_number($created, 'Created', 11);
//web last login
$web_lastlogin = strtotime($_POST['web_lastlogin']);
verify_number($web_lastlogin, 'Web Last login', 11);
if (!$error) {
if (USE_ACCOUNT_NAME) {
$account->setName($name);
}
if ($hasTypeColumn) {
$account->setCustomField('type', $group);
} elseif ($hasGroupColumn) {
$account->setCustomField('group_id', $group);
}
if ($hasSecretColumn) {
$account->setCustomField('secret', $secret);
}
$account->setCustomField('key', $key);
$account->setEMail($email);
if ($hasCoinsColumn) {
$account->setCustomField('coins', $t_coins);
}
$lastDay = 0;
if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) {
$lastDay = time();
} else if ($lastDay != 0) {
$lastDay = 0;
}
$account->setPremDays($p_days);
$account->setLastLogin($lastDay);
if ($hasPointsColumn) {
$account->setCustomField('premium_points', $p_points);
}
$account->setRLName($rl_name);
$account->setLocation($rl_loca);
$account->setCountry($rl_country);
$account->setCustomField('created', $created);
$account->setWebFlags($web_flags);
$account->setCustomField('web_lastlogin', $web_lastlogin);
if (isset($password)) {
$config_salt_enabled = $db->hasColumn('accounts', 'salt');
if ($config_salt_enabled) {
$salt = generateRandomString(10, false, true, true);
$password = $salt . $password;
$account->setCustomField('salt', $salt);
}
$password = encrypt($password);
$account->setPassword($password);
if ($config_salt_enabled)
$account->setCustomField('salt', $salt);
}
$account->save();
echo_success('Account saved at: ' . date('G:i'));
}
}
} else if ($id == 0) {
$accounts_db = $db->query('SELECT `id`, `name`' . ($hasTypeColumn ? ',type' : ($hasGroupColumn ? ',group_id' : '')) . ' FROM `accounts` ORDER BY `id` ASC');
?>
<div class="col-12 col-sm-12 col-lg-10">
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">Accounts</h5>
</div>
<div class="card-body">
<table class="acc_datatable table table-striped table-bordered table-responsive d-md-table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<?php if($hasTypeColumn || $hasGroupColumn): ?>
<th>Position</th>
<?php endif; ?>
<th style="width: 40px">Edit</th>
</tr>
</thead>
<tbody>
<?php foreach ($accounts_db as $account_lst): ?>
<tr>
<th><?php echo $account_lst['id']; ?></th>
<td><?php echo $account_lst['name']; ?></a></td>
<?php if($hasTypeColumn || $hasGroupColumn): ?>
<td>
<?php if ($hasTypeColumn) {
echo $acc_type[$account_lst['type']];
} elseif ($hasGroupColumn) {
$group = $groups->getGroups();
echo $group[$account_lst['group_id']];
} ?>
</td>
<?php endif; ?>
<td><a href="?p=accounts&id=<?php echo $account_lst['id']; ?>" class="btn btn-success btn-sm" title="Edit">
<i class="fas fa-pencil-alt"></i>
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php } ?>
<?php if (isset($account) && $account->isLoaded()) { ?>
<div class="col-12 col-sm-12 col-lg-10">
<div class="card card-primary card-outline card-outline-tabs">
<div class="card-header p-0 border-bottom-0">
<ul class="nav nav-tabs" id="accounts-tab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="accounts-acc-tab" data-toggle="pill" href="#accounts-acc">Account</a>
</li>
<li class="nav-item">
<a class="nav-link" id="accounts-chars-tab" data-toggle="pill" href="#accounts-chars">Characters</a>
</li>
<?php if ($db->hasTable('bans')) : ?>
<li class="nav-item">
<a class="nav-link" id="accounts-bans-tab" data-toggle="pill" href="#accounts-bans">Bans</a>
</li>
<?php endif;
if ($db->hasTable('store_history')) : ?>
<li class="nav-item">
<a class="nav-link" id="accounts-store-tab" data-toggle="pill" href="#accounts-store">Store History</a>
</li>
<?php endif; ?>
</ul>
</div>
<div class="card-body">
<div class="tab-content" id="accounts-tabContent">
<div class="tab-pane fade active show" id="accounts-acc">
<form action="<?php echo $admin_base . ((isset($id) && $id > 0) ? '&id=' . $id : ''); ?>" method="post">
<div class="form-group row">
<?php if (USE_ACCOUNT_NAME): ?>
<div class="col-12 col-sm-12 col-lg-4">
<label for="name">Account Name:</label>
<input type="text" class="form-control" id="name" name="name" autocomplete="off" value="<?php echo $account->getName(); ?>"/>
</div>
<?php endif; ?>
<div class="col-12 col-sm-12 col-lg-5">
<div class="form-check">
<input type="checkbox"
name="c_pass"
id="c_pass"
value="false"
class="form-check-input"/>
<label for="c_pass">Password: (check to change)</label>
</div>
<div class="input-group">
<input type="text" class="form-control" id="pass" name="pass" autocomplete="off" maxlength="20" value=""/>
</div>
</div>
<div class="col-12 col-sm-12 col-lg-3">
<label for="account_id" class="control-label">Account ID:</label>
<input type="text" class="form-control" id="account_id" name="account_id" autocomplete="off" size="8" maxlength="11" disabled value="<?php echo $account->getId(); ?>"/>
</div>
</div>
<div class="form-group row">
<?php
$acc_group = $account->getAccGroupId();
if ($hasTypeColumn) {
?>
<div class="col-12 col-sm-12 col-lg-6">
<label for="group">Account Type:</label>
<select name="group" id="group" class="form-control">
<?php foreach ($acc_type as $id => $a_type): ?>
<option value="<?php echo($id); ?>" <?php echo($acc_group == ($id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php endforeach; ?>
</select>
</div>
<?php
} elseif ($hasGroupColumn) {
?>
<div class="col-12 col-sm-12 col-lg-6">
<label for="group">Account Type:</label>
<select name="group" id="group" class="form-control">
<?php foreach ($groups->getGroups() as $id => $group): ?>
<option value="<?php echo $id; ?>" <?php echo($acc_group == $id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option>
<?php endforeach; ?>
</select>
</div>
<?php } ?>
<div class="col-12 col-sm-12 col-lg-6">
<label for="web_flags">Website Access:</label>
<select name="web_flags" id="web_flags" class="form-control">
<?php foreach ($web_acc as $id => $a_type): ?>
<option value="<?php echo($id); ?>" <?php echo($account->getWebFlags() == ($id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="form-group row">
<?php if ($hasSecretColumn): ?>
<div class="col-12 col-sm-12 col-lg-6">
<label for="secret">Secret:</label>
<input type="text" class="form-control" id="secret" name="secret" autocomplete="off" value="<?php echo $account->getCustomField('secret'); ?>"/>
</div>
<?php endif; ?>
<div class="col-12 col-sm-12 col-lg-6">
<label for="key">Recovery Key:</label>
<input type="text" class="form-control" id="key" name="key" autocomplete="off" value="<?php echo $account->getCustomField('key'); ?>"/>
</div>
</div>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<label for="email">Email:</label><?php echo (config('mail_enabled') ? ' (<a href="' . ADMIN_URL . '?p=mailer&mail_to=' . $account->getEMail() . '">Send Mail</a>)' : ''); ?>
<input type="text" class="form-control" id="email" name="email" autocomplete="off" value="<?php echo $account->getEMail(); ?>"/>
</div>
<?php if ($hasCoinsColumn): ?>
<div class="col-12 col-sm-12 col-lg-6">
<label for="t_coins">Tibia Coins:</label>
<input type="text" class="form-control" id="t_coins" name="t_coins" autocomplete="off" maxlength="11" value="<?php echo $account->getCustomField('coins') ?>"/>
</div>
<?php endif; ?>
<div class="col-12 col-sm-12 col-lg-6">
<label for="p_days">Premium Days:</label>
<input type="text" class="form-control" id="p_days" name="p_days" autocomplete="off" maxlength="11" value="<?php echo $account->getPremDays(); ?>"/>
</div>
<?php if ($hasPointsColumn): ?>
<div class="col-12 col-sm-12 col-lg-6">
<label for="p_points" class="control-label">Premium Points:</label>
<input type="text" class="form-control" id="p_points" name="p_points" autocomplete="off" maxlength="8" value="<?php echo $account->getCustomField('premium_points') ?>"/>
</div>
<?php endif; ?>
</div>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-4">
<label for="rl_name">RL Name:</label>
<input type="text" class="form-control" id="rl_name" name="rl_name"
autocomplete="off" maxlength="20"
value="<?php echo $account->getRLName(); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-4">
<label for="rl_loca">Location:</label>
<input type="text" class="form-control" id="rl_loca" name="rl_loca"
autocomplete="off" maxlength="20"
value="<?php echo $account->getLocation(); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-4">
<label for="rl_country">Country:</label>
<select name="rl_country" id="rl_country" class="form-control">
<?php foreach ($countries as $id => $a_type): ?>
<option value="<?php echo($id); ?>" <?php echo($account->getCountry() == ($id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<label for="created" class="control-label">Created:</label>
<input type="text" class="form-control" id="created" name="created" autocomplete="off" maxlength="20" value="<?php echo date("M d Y, H:i:s", $account->getCustomField('created')); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="web_lastlogin" class="control-label">Web Last Login:</label>
<input type="text" class="form-control" id="web_lastlogin" name="web_lastlogin" autocomplete="off" maxlength="20" value="<?php echo date("M d Y, H:i:s", $account->getCustomField('web_lastlogin')); ?>"/>
</div>
</div>
<input type="hidden" name="save" value="yes"/>
<button type="submit" class="btn btn-info"><i class="fas fa-update"></i> Update</button>
<a href="<?php echo ADMIN_URL; ?>?p=accounts" class="btn btn-danger float-right"><i class="fas fa-cancel"></i> Cancel</a>
</form>
</div>
<div class="tab-pane fade" id="accounts-chars">
<div class="row">
<?php
if (isset($account) && $account->isLoaded()) {
$account_players = $account->getPlayersList();
$account_players->orderBy('id');
if (isset($account_players)) { ?>
<table class="table table-striped table-condensed table-responsive d-md-table">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Level</th>
<th>Vocation</th>
<th style="width: 40px">Edit</th>
</tr>
</thead>
<tbody>
<?php $i= 0;
foreach ($account_players as $i => $player):
$i++;
$player_vocation = $player->getVocation();
$player_promotion = $player->getPromotion();
if (isset($player_promotion)) {
if ((int)$player_promotion > 0)
$player_vocation += ($player_promotion * $config['vocations_amount']);
}
if (isset($config['vocations'][$player_vocation])) {
$vocation_name = $config['vocations'][$player_vocation];
} ?>
<tr>
<th><?php echo $i; ?></th>
<td><?php echo $player->getName(); ?></td>
<td><?php echo $player->getLevel(); ?></td>
<td><?php echo $vocation_name; ?></td>
<td><a href="?p=players&id=<?php echo $player->getId() ?>" class=" btn btn-success btn-sm" title="Edit"><i class="fas fa-pencil-alt"></i></a></td>
</tr>
<?php endforeach ?>
</tbody>
</table>
<?php
}
} ?>
</div>
</div>
<?php if ($db->hasTable('bans')) : ?>
<div class="tab-pane fade" id="accounts-bans">
<?php
$bans = $db->query('SELECT * FROM ' . $db->tableName('bans') . ' WHERE ' . $db->fieldName('active') . ' = 1 AND ' . $db->fieldName('id') . ' = ' . $account->getId() . ' ORDER BY ' . $db->fieldName('added') . ' DESC LIMIT 10');
if ($bans->rowCount()) {
?>
<table class="table table-striped table-condensed table-responsive d-md-table">
<thead>
<tr>
<th>Nick</th>
<th>Type</th>
<th>Expires</th>
<th>Reason</th>
<th>Comment</th>
<th>Added by:</th>
</tr>
</thead>
<tbody>
<?php
foreach ($bans as $ban) {
?>
<tr>
<td><?php
$pName = getPlayerNameByAccount($ban['value']);
echo '<a href="?p=players&search=' . $pName . '">' . $pName . '</a>'; ?>
</td>
<td><?php echo getBanType($ban['type']); ?></td>
<td>
<?php
if ($ban['expires'] == "-1")
echo 'Never';
else
echo date("H:i:s", $ban['expires']) . '<br/>' . date("d M Y", $ban['expires']);
?>
</td>
<td><?php echo getBanReason($ban['reason']); ?></td>
<td><?php echo $ban['comment']; ?></td>
<td>
<?php
if ($ban['admin_id'] == "0")
echo 'Autoban';
else
$aName = getPlayerNameByAccount($ban['admin_id']);
echo '<a href="?p=players&search=' . $aName . '">' . $aName . '</a>';
echo '<br/>' . date("d.m.Y", $ban['added']);
?>
</td>
</tr>
<?php } ?>
</tbody>
</table>
<?php
} else {
echo 'No Account bans.';
} ?>
</div>
<?php endif;
if ($db->hasTable('store_history')) { ?>
<div class="tab-pane fade" id="accounts-store">
<?php $store_history = $db->query('SELECT * FROM `store_history` WHERE `account_id` = "' . $account->getId() . '" ORDER BY `time` DESC')->fetchAll(); ?>
<table class="table table-striped table-condensed table-responsive d-md-table">
<thead>
<tr>
<th>Description</th>
<th>Coins</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<?php foreach ($store_history as $p): ?>
<tr>
<td><?php echo $p['description']; ?></td>
<td><?php echo $p['coin_amount']; ?></td>
<td><?php echo date('d M y H:i:s', $p['time']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php } ?>
</div>
</div>
</div>
</div>
<?php } ?>
<div class="col-12 col-sm-12 col-lg-2">
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">Search Accounts</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-6 col-lg-12">
<form action="<?php echo $admin_base; ?>" method="post">
<label for="name">Account Name:</label>
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="search" value="<?php echo $search_account; ?>" maxlength="32" size="32">
<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span>
</div>
</form>
</div>
<div class="col-6 col-lg-12">
<form action="<?php echo $admin_base; ?>" method="post">
<label for="name">Account ID:</label>
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="id" value="" maxlength="32" size="32">
<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('#created').datetimepicker({format: "M d Y, H:i:s",});
$('#web_lastlogin').datetimepicker({format: 'M d Y, H:i:s'});
$('#c_pass').change(function () {
const ipass = $('input[name=pass]');
ipass[0].disabled = !this.checked;
ipass[0].value = '';
}).change();
$('.acc_datatable').DataTable({
"order": [[0, "asc"]]
});
});
</script>

View File

@@ -1,140 +0,0 @@
<?php
/**
* CHANGELOG modifier
*
* @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!');
if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) {
echo 'Access denied.';
return;
}
$title = 'Changelog';
$use_datatable = true;
define('CL_LIMIT', 600); // maximum changelog body length
?>
<link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ >
<script src="<?php echo BASE_URL; ?>tools/js/jquery.datetimepicker.js"></script>
<?php
$id = isset($_GET['id']) ? $_GET['id'] : 0;
require_once LIBS . 'changelog.php';
if(!empty($action))
{
$id = isset($_REQUEST['id']) ? $_REQUEST['id'] : null;
$body = isset($_REQUEST['body']) ? stripslashes($_REQUEST['body']) : null;
$create_date = isset($_REQUEST['createdate']) ? (int)strtotime($_REQUEST['createdate'] ): null;
$player_id = isset($_REQUEST['player_id']) ? (int)$_REQUEST['player_id'] : null;
$type = isset($_REQUEST['type']) ? (int)$_REQUEST['type'] : null;
$where = isset($_REQUEST['where']) ? (int)$_REQUEST['where'] : null;
$errors = array();
if($action == 'add') {
if(Changelog::add($body, $type, $where, $player_id, $create_date, $errors)) {
$body = '';
$type = $where = $player_id = $create_date = 0;
success("Added successful.");
}
}
else if($action == 'delete') {
Changelog::delete($id, $errors);
success("Deleted successful.");
}
else if($action == 'edit')
{
if(isset($id) && !isset($body)) {
$cl = Changelog::get($id);
$body = $cl['body'];
$type = $cl['type'];
$where = $cl['where'];
$create_date = $cl['date'];
$player_id = $cl['player_id'];
}
else {
if(Changelog::update($id, $body, $type, $where, $player_id, $create_date,$errors)) {
$action = $body = '';
$type = $where = $player_id = $create_date = 0;
success("Updated successful.");
}
}
}
else if($action == 'hide') {
Changelog::toggleHidden($id, $errors, $status);
success(($status == 1 ? 'Show' : 'Hide') . " successful.");
}
if(!empty($errors))
error(implode(", ", $errors));
}
$changelogs = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'changelog' . '` ORDER BY `id` DESC')->fetchAll();
$i = 0;
$log_type = [
['id' => 1, 'icon' => 'added'],
['id' => 2, 'icon' => 'removed'],
['id' => 3, 'icon' => 'changed'],
['id' => 4, 'icon' => 'fixed'],
];
$log_where = [
['id' => 1, 'icon' => 'server'],
['id' => 2, 'icon' => 'website'],
];
foreach($changelogs as $key => &$log)
{
$log['type'] = getChangelogType($log['type']);
$log['where'] = getChangelogWhere($log['where']);
}
if($action == 'edit' || $action == 'new') {
if($action == 'edit') {
$player = new OTS_Player();
$player->load($player_id);
}
$account_players = $account_logged->getPlayersList();
$account_players->orderBy('group_id', POT::ORDER_DESC);
$twig->display('admin.changelog.form.html.twig', array(
'action' => $action,
'cl_link_form' => constant('ADMIN_URL').'?p=changelog&action=' . ($action == 'edit' ? 'edit' : 'add'),
'cl_id' => isset($id) ? $id : null,
'body' => isset($body) ? htmlentities($body, ENT_COMPAT, 'UTF-8') : '',
'create_date' => isset($create_date) ? $create_date : '',
'player' => isset($player) && $player->isLoaded() ? $player : null,
'player_id' => isset($player_id) ? $player_id : null,
'account_players' => $account_players,
'type' => isset($type) ? $type : 0,
'where' => isset($where) ? $where : 0,
'log_type' => $log_type,
'log_where' => $log_where,
));
}
$twig->display('admin.changelog.html.twig', array(
'changelogs' => $changelogs,
));
?>
<script>
$(document).ready(function () {
$('#createdate').datetimepicker({format: "M d Y, H:i:s",});
$('.tb_datatable').DataTable({
"order": [[0, "desc"]],
"columnDefs": [{targets: [1, 2,4,5],orderable: false}]
});
});
</script>

View File

@@ -1,25 +0,0 @@
<?php
/**
* CHANGELOG viewer
*
* @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 = 'MyAAC Changelog';
if (!file_exists(BASE . 'CHANGELOG.md')) {
echo 'File CHANGELOG.md doesn\'t exist.';
return;
}
$changelog = file_get_contents(BASE . 'CHANGELOG.md');
$Parsedown = new Parsedown();
$changelog = $Parsedown->text($changelog); # prints: <p>Hello <em>Parsedown</em>!</p>
echo '<div>' . $changelog . '</div>';

View File

@@ -1,66 +0,0 @@
<?php
/**
* Dashboard
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Dashboard';
if (isset($_GET['clear_cache'])) {
if (clearCache()) {
success('Cache cleared.');
} else {
error('Error while clearing cache.');
}
}
if (isset($_GET['maintenance'])) {
$message = (!empty($_POST['message']) ? $_POST['message'] : null);
$_status = (isset($_POST['status']) && $_POST['status'] == 'true');
$_status = ($_status ? '0' : '1');
if (empty($message)) {
error('Message cannot be empty.');
} else if (strlen($message) > 255) {
error('Message is too long. Maximum length allowed is 255 chars.');
} else {
$tmp = '';
if (fetchDatabaseConfig('site_closed', $tmp))
updateDatabaseConfig('site_closed', $_status);
else
registerDatabaseConfig('site_closed', $_status);
if (fetchDatabaseConfig('site_closed_message', $tmp))
updateDatabaseConfig('site_closed_message', $message);
else
registerDatabaseConfig('site_closed_message', $message);
}
}
$is_closed = getDatabaseConfig('site_closed') == '1';
$closed_message = 'Server is under maintenance, please visit later.';
$tmp = '';
if (fetchDatabaseConfig('site_closed_message', $tmp))
$closed_message = $tmp;
echo '<div class="row">';
$twig->display('admin.dashboard.html.twig', array());
echo '</div>';
$configAdminPanelModules = config('admin_panel_modules');
if (isset($configAdminPanelModules)) {
echo '<div class="row">';
$configAdminPanelModules = explode(',', $configAdminPanelModules);
$twig_loader->prependPath(__DIR__ . '/modules/templates');
foreach ($configAdminPanelModules as $box) {
$file = __DIR__ . '/modules/' . $box . '.php';
if (file_exists($file)) {
include($file);
}
}
echo '</div>';
}

View File

@@ -1,13 +0,0 @@
<?php
/**
* Load items.xml
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Server Data';
$twig->display('admin.data.html.twig');

View File

@@ -1,17 +0,0 @@
<?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';
$twig->display('admin.login.html.twig', array(
'logout' => ($action == 'logout' ? 'You have been logged out!' : ''),
'account' => USE_ACCOUNT_NAME ? 'Name' : 'Number',
'errors' => isset($errors)? $errors : ''
));

View File

@@ -1,82 +0,0 @@
<?php
/**
* Logs
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Logs Viewer';
$files = array();
$aac_path_logs = BASE . 'system/logs/';
foreach (scandir($aac_path_logs, SCANDIR_SORT_ASCENDING) as $f) {
if ($f[0] === '.' || is_dir($aac_path_logs . $f) || $f === 'index.html') {
continue;
}
$files[] = array($f, $aac_path_logs);
}
$server_path_logs = $config['server_path'] . 'logs/';
if (!file_exists($server_path_logs)) {
$server_path_logs = $config['data_path'] . 'logs/';
}
if (file_exists($server_path_logs)) {
foreach (scandir($server_path_logs, SCANDIR_SORT_ASCENDING) as $f) {
if ($f[0] === '.') {
continue;
}
if (is_dir($server_path_logs . $f)) {
foreach (scandir($server_path_logs . $f, SCANDIR_SORT_ASCENDING) as $f2) {
if ($f2[0] === '.') {
continue;
}
$files[] = array($f . '/' . $f2, $server_path_logs);
}
continue;
}
$files[] = array($f, $server_path_logs);
}
}
foreach ($files as &$f) {
$f['mtime'] = filemtime($f[1] . $f[0]);
$f['name'] = $f[0];
}
unset($f);
define('EXIST_NONE', 0);
define('EXIST_SERVER_LOG', 1);
define('EXIST_AAC_LOG', 2);
$exist = EXIST_NONE;
$file = isset($_GET['file']) ? $_GET['file'] : null;
if (!empty($file)) {
if (!preg_match('/[^A-z0-9\' _\/\-\.]/', $file)) {
if (file_exists($aac_path_logs . $file)) {
$exist = EXIST_AAC_LOG;
} else if (file_exists($server_path_logs . $file)) {
$exist = EXIST_SERVER_LOG;
} else {
echo 'Specified file does not exist.';
}
if ($exist !== EXIST_NONE) {
$file_content = nl2br(file_get_contents(($exist === EXIST_SERVER_LOG ? $server_path_logs : $aac_path_logs) . $file));
$twig->display('admin.logs.view.html.twig', array('file' => $file, 'content' => $file_content));
}
} else {
echo 'Invalid file name specified.';
}
}
$twig->display('admin.logs.html.twig', array('files' => $files));

View File

@@ -1,83 +0,0 @@
<?php
/**
* Mailer
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Mailer';
if (!hasFlag(FLAG_CONTENT_MAILER) && !superAdmin()) {
echo 'Access denied.';
return;
}
if (!config('mail_enabled')) {
echo 'Mail support disabled.';
return;
}
$mail_to = isset($_REQUEST['mail_to']) ? stripslashes(trim($_REQUEST['mail_to'])) : null;
$mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : null;
$mail_content = isset($_POST['mail_content']) ? stripslashes($_POST['mail_content']) : null;
if (isset($_POST['submit'])) {
if (empty($mail_subject)) {
warning('Please enter subject of the message.');
}
if (empty($mail_content)) {
warning('Please enter content of the message.');
}
}
if (!empty($mail_to)) {
if(!Validator::email($mail_to)) {
warning('E-Mail is invalid.');
}
else {
if (!empty($mail_content) && !empty($mail_subject)) {
if (_mail($mail_to, $mail_subject, $mail_content)) {
success("Successfully mailed <strong>$mail_to</strong>");
}
else {
error("Error while sending mail to <strong>$mail_to</strong>. More info can be found in system/logs/mailer-error.log");
}
}
}
}
if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) {
$success = 0;
$failed = 0;
$add = '';
if (config('account_mail_verify')) {
note('Note: Sending only to users with verified E-Mail.');
$add = ' AND `email_verified` = 1';
}
$query = $db->query('SELECT `email` FROM `accounts` WHERE `email` != ""' . $add);
foreach ($query as $email) {
if (_mail($email['email'], $mail_subject, $mail_content)) {
$success++;
}
else {
$failed++;
echo '<br />';
error('An error occorred while sending email to <b>' . $email['email'] . '</b>. For Admin: More info can be found in system/logs/mailer-error.log');
}
}
success('Mailing finished.');
success("$success emails delivered.");
warning("$failed emails failed.");
}
$twig->display('admin.mailer.html.twig', [
'mail_to' => $mail_to,
'mail_subject' => $mail_subject,
'mail_content' => $mail_content
]);

View File

@@ -1,139 +0,0 @@
<?php
/**
* Menus
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Menus';
if (!hasFlag(FLAG_CONTENT_MENUS) && !superAdmin()) {
echo 'Access denied.';
return;
}
if (isset($_REQUEST['template'])) {
$template = $_REQUEST['template'];
if (isset($_REQUEST['menu'])) {
$post_menu = $_REQUEST['menu'];
$post_menu_link = $_REQUEST['menu_link'];
$post_menu_blank = $_REQUEST['menu_blank'];
$post_menu_color = $_REQUEST['menu_color'];
if (count($post_menu) != count($post_menu_link)) {
echo 'Menu count is not equal menu links. Something went wrong when sending form.';
return;
}
$db->query('DELETE FROM `' . TABLE_PREFIX . 'menu` WHERE `template` = ' . $db->quote($template));
foreach ($post_menu as $category => $menus) {
foreach ($menus as $i => $menu) {
if (empty($menu)) // don't save empty menu item
continue;
try {
$db->insert(TABLE_PREFIX . 'menu', array('template' => $template, 'name' => $menu, 'link' => $post_menu_link[$category][$i], 'blank' => $post_menu_blank[$category][$i] == 'on' ? 1 : 0, 'color' => str_replace('#', '', $post_menu_color[$category][$i]), 'category' => $category, 'ordering' => $i));
} catch (PDOException $error) {
warning('Error while adding menu item (' . $menu . '): ' . $error->getMessage());
}
}
}
$cache = Cache::getInstance();
if ($cache->enabled()) {
$cache->delete('template_menus');
}
success('Saved at ' . date('H:i'));
}
$file = TEMPLATES . $template . '/config.php';
if (file_exists($file)) {
require_once $file;
} else {
echo 'Cannot find template config.php file.';
return;
}
if (!isset($config['menu_categories'])) {
echo "No menu categories set in template config.php.<br/>This template doesn't support dynamic menus.";
return;
}
$title = 'Menus - ' . $template;
?>
<div align="center" class="text-center">
<p class="note">You are editing: <?= $template ?><br/><br/>
Hint: You can drag menu items.<br/>
Hint: Add links to external sites using: <b>http://</b> or <b>https://</b> prefix.<br/>
Not all templates support blank and colorful links.
</p>
</div>
<?php
$menus = array();
$menus_db = $db->query('SELECT `name`, `link`, `blank`, `color`, `category`, `ordering` FROM `' . TABLE_PREFIX . 'menu` WHERE `enabled` = 1 AND `template` = ' . $db->quote($template) . ' ORDER BY `ordering` ASC;')->fetchAll();
foreach ($menus_db as $menu) {
$menus[$menu['category']][] = array('name' => $menu['name'], 'link' => $menu['link'], 'blank' => $menu['blank'], 'color' => $menu['color'], 'ordering' => $menu['ordering']);
}
$last_id = array();
?>
<form method="post" id="menus-form" action="?p=menus">
<input type="hidden" name="template" value="<?php echo $template ?>"/>
<div class="row">
<?php foreach ($config['menu_categories'] as $id => $cat): ?>
<div class="col-md-12 col-lg-6">
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0"><?php echo $cat['name'] ?> <i class="far fa-plus-square add-button" id="add-button-<?php echo $id ?>"></i></h5>
</div>
<div class="card-body">
<ul class="sortable" id="sortable-<?php echo $id ?>">
<?php
if (isset($menus[$id])) {
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'] ?>"/>
<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"/>
<label><input class="blank-checkbox" type="checkbox" <?php echo($menu['blank'] == 1 ? 'checked' : '') ?>/><span title="Open in New Window">New Window</span></label>
<input class="color-picker" type="text" name="menu_color[<?php echo $id ?>][]" value="#<?php echo $menu['color'] ?>"/>
<a class="remove-button" id="remove-button-<?php echo $id ?>-<?php echo $i ?>"><i class="fas fa-trash"></a></i></li>
<?php $last_id[$id] = $i;
endforeach;
} ?>
</ul>
</div>
</div>
</div>
<?php endforeach ?>
</div>
<div class="row pb-2">
<div class="col-md-12">
<button type="submit" class="btn btn-info"><i class="fas fa-update"></i> Save</button>
<?php
echo '<button type="button" class="btn btn-danger float-right" value="Cancel" onclick="window.location = \'' . ADMIN_URL . '?p=menus\';"><i class="fas fa-cancel"></i> Cancel</button>';
?>
</div>
</div>
</form>
<?php
$twig->display('admin.menus.js.html.twig', array(
'menus' => $menus,
'last_id' => $last_id
));
?>
<?php
} else {
$templates = $db->query('SELECT `template` FROM `' . TABLE_PREFIX . 'menu` GROUP BY `template`;')->fetchAll();
foreach ($templates as $key => $value) {
$file = TEMPLATES . $value['template'] . '/config.php';
if (!file_exists($file)) {
unset($templates[$key]);
}
}
$twig->display('admin.menus.form.html.twig', array(
'templates' => $templates
));
}

View File

@@ -1,6 +0,0 @@
<?php
$balance = ($db->hasColumn('players', 'balance') ? $db->query('SELECT `balance`, `id`, `name`,`level` FROM `players` ORDER BY `balance` DESC LIMIT 10;') : 0);
$twig->display('balance.html.twig', array(
'balance' => $balance
));

View File

@@ -1,6 +0,0 @@
<?php
$coins = ($db->hasColumn('accounts', 'coins') ? $db->query('SELECT `coins`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `coins` DESC LIMIT 10;') : 0);
$twig->display('coins.html.twig', array(
'coins' => $coins
));

View File

@@ -1,6 +0,0 @@
<?php
$players = ($db->hasColumn('accounts', 'created') ? $db->query('SELECT `created`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `created` DESC LIMIT 10;') : 0);
$twig->display('created.html.twig', array(
'players' => $players,
));

View File

@@ -1,5 +0,0 @@
<?php
$players = ($db->hasColumn('players', 'lastlogin') ? $db->query('SELECT name, level, lastlogin FROM players ORDER BY lastlogin DESC LIMIT 10;') : 0);
$twig->display('lastlogin.html.twig', array(
'players' => $players,
));

View File

@@ -1,6 +0,0 @@
<?php
$points = ($db->hasColumn('accounts', 'premium_points') ? $db->query('SELECT `premium_points`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `premium_points` DESC LIMIT 10;') : 0);
$twig->display('points.html.twig', array(
'points' => $points,
));

View File

@@ -1,46 +0,0 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
if (isset($status)) {
$error_icon = '<i class="fas fa-exclamation-circle text-danger"></i>'; ?>
<div class=" col-md-6 col-lg-6">
<div class="card card-info card-outline">
<div class="card-header border-bottom-0">
<span class="font-weight-bold m-0">Server Status</span> <span class="float-right small"><b>Last checked</b>: <?php echo(isset($status['lastCheck']) ? date("l, d.m.Y H:i:s", $status['lastCheck']) : $error_icon); ?></span>
</div>
<div class="card-body p-0 ">
<table class="table">
<tbody>
<tr>
<th width="30%">Server</th>
<td><?php echo(isset($status['server']) & isset($status['serverVersion']) ? $status['server'] . ' x ' . $status['serverVersion'] : $error_icon) ?></td>
</tr>
<tr>
<th>Client</th>
<td><?php echo(isset($status['clientVersion']) ? $status['clientVersion'] : $error_icon) ?></td>
</tr>
<tr>
<th>Map</th>
<td>
<?php if (isset($status['mapName']) & isset($status['mapAuthor']) & isset($status['mapWidth']) & isset($status['mapHeight'])) {
echo $status['mapName'] . ' by <b>' . $status['mapAuthor'] . '</b><br/>' . $status['mapWidth'] . ' x ' . $status['mapHeight'];
} else {
echo $error_icon;
} ?>
</td>
</tr>
<tr>
<th>Monsters</th>
<td><?php echo (isset($status['monsters']) ? $status['monsters'] : $error_icon); ?></td>
</tr>
<tr>
<th>MOTD:</th>
<td><?php echo(isset($status['motd']) ? $status['motd'] : $error_icon); ?></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<?php } ?>

View File

@@ -1,12 +0,0 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
$count = $db->query('SELECT
(SELECT COUNT(*) FROM `accounts`) as total_accounts,
(SELECT COUNT(*) FROM `players`) as total_players,
(SELECT COUNT(*) FROM `guilds`) as total_guilds,
(SELECT COUNT(*) FROM `' . TABLE_PREFIX . 'monsters`) as total_monsters,
(SELECT COUNT(*) FROM `houses`) as total_houses;')->fetch();
$twig->display('statistics.html.twig', array(
'count' => $count,
));

View File

@@ -1,31 +0,0 @@
{% if balance is iterable %}
<div class=" col-md-6 col-lg-3">
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">Top 10 - Balance</h5>
</div>
<div class="card-body p-0">
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>#</th>
<th>Player</th>
<th>Balance</th>
</tr>
</thead>
<tbody>
{% set i = 0 %}
{% for result in balance %}
{% set i = i + 1 %}
<tr>
<th>{{ i }}</th>
<td><a href="?p=players&search_name={{ result.name }}">{{ result.name }}</a></td>
<td>{{ result.balance }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endif %}

View File

@@ -1,31 +0,0 @@
{% if coins is iterable %}
<div class=" col-md-6 col-lg-3">
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">Top 10 - Most coins</h5>
</div>
<div class="card-body p-0">
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>#</th>
<th>Account</th>
<th>Tibia coins</th>
</tr>
</thead>
<tbody>
{% set i = 0 %}
{% for result in coins %}
{% set i = i + 1 %}
<tr>
<th>{{ i }}</th>
<td><a href="?p=accounts&search_name={{ result.name }}">{{ result.name }}</a></td>
<td>{{ result.coins }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endif %}

View File

@@ -1,31 +0,0 @@
{% if players is iterable %}
<div class=" col-md-6 col-lg-3">
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">Last 10 created</h5>
</div>
<div class="card-body p-0">
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>#</th>
<th>Account</th>
<th>Creation Date</th>
</tr>
</thead>
<tbody>
{% set i = 0 %}
{% for result in players %}
{% set i = i + 1 %}
<tr>
<th>{{ i }}</th>
<td><a href="?p=accounts&search_name={{ result.name }}">{{ result.name }}</a></td>
<td>{{ result.created|date("M d Y, H:i:s") }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endif %}

View File

@@ -1,31 +0,0 @@
{% if players is iterable %}
<div class=" col-md-6 col-lg-3">
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">Last 10 logins</h5>
</div>
<div class="card-body p-0">
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>#</th>
<th>Player</th>
<th>Login Date</th>
</tr>
</thead>
<tbody>
{% set i = 0 %}
{% for result in players %}
{% set i = i + 1 %}
<tr>
<th>{{ i }}</th>
<td><a href="?p=players&search_name={{ result.name }}">{{ result.name }}</a></td>
<td>{{ result.lastlogin|date("M d Y, H:i:s") }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endif %}

View File

@@ -1,31 +0,0 @@
{% if points is iterable %}
<div class=" col-md-6 col-lg-3">
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">Top 10 - Most premium points</h5>
</div>
<div class="card-body p-0">
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>#</th>
<th>Account</th>
<th>Premium points</th>
</tr>
</thead>
<tbody>
{% set i = 0 %}
{% for result in points %}
{% set i = i + 1 %}
<tr>
<th>{{ i }}</th>
<td><a href="?p=accounts&search_name={{ result.name }}">{{ result.name }}</a></td>
<td>{{ result.premium_points }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endif %}

View File

@@ -1,45 +0,0 @@
<div class="col">
<div class="info-box">
<span class="info-box-icon bg-info elevation-1"><i class="fas fa-user-plus"></i></span>
<div class="info-box-content">
<span class="info-box-text">Accounts:</span>
<span class="info-box-number">{{ count.total_accounts }}</span>
</div>
</div>
</div>
<div class="col">
<div class="info-box">
<span class="info-box-icon bg-red elevation-1"><i class="fas fa-user-plus"></i></span>
<div class="info-box-content">
<span class="info-box-text">Players:</span>
<span class="info-box-number">{{ count.total_players }}</span>
</div>
</div>
</div>
<div class="col">
<div class="info-box">
<span class="info-box-icon bg-teal elevation-1"><i class="fas fa-pastafarianism"></i></span>
<div class="info-box-content">
<span class="info-box-text">Monsters:</span>
<span class="info-box-number">{{ count.total_monsters }}</span>
</div>
</div>
</div>
<div class="col">
<div class="info-box">
<span class="info-box-icon bg-green elevation-1"><i class="fas fa-chart-pie"></i></span>
<div class="info-box-content">
<span class="info-box-text">Guilds:</span>
<span class="info-box-number">{{ count.total_guilds }}</span>
</div>
</div>
</div>
<div class="col">
<div class="info-box">
<span class="info-box-icon bg-yellow elevation-1"><i class="fas fa-home"></i></span>
<div class="info-box-content">
<span class="info-box-text">Houses:</span>
<span class="info-box-number">{{ count.total_houses }}</span>
</div>
</div>
</div>

View File

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

View File

@@ -1,10 +0,0 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
$twig->display('web_status.twig', array(
'is_closed' => $is_closed,
'closed_message' => $closed_message,
'status' => $status,
'account_type' => USE_ACCOUNT_NAME ? 'name' : 'number'
));
?>

View File

@@ -1,155 +0,0 @@
<?php
/**
* Pages
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
require_once LIBS . 'forum.php';
require_once LIBS . 'news.php';
$title = 'News Panel';
$use_datatable = true;
if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) {
echo 'Access denied.';
return;
}
header('X-XSS-Protection:0');
// some constants, used mainly by database (cannot by modified without schema changes)
define('TITLE_LIMIT', 100);
define('BODY_LIMIT', 65535); // maximum news body length
define('ARTICLE_TEXT_LIMIT', 300);
define('ARTICLE_IMAGE_LIMIT', 100);
$name = $p_title = '';
if(!empty($action))
{
$id = isset($_REQUEST['id']) ? $_REQUEST['id'] : null;
$p_title = isset($_REQUEST['title']) ? $_REQUEST['title'] : null;
$body = isset($_REQUEST['body']) ? stripslashes($_REQUEST['body']) : null;
$comments = isset($_REQUEST['comments']) ? $_REQUEST['comments'] : null;
$type = isset($_REQUEST['type']) ? (int)$_REQUEST['type'] : null;
$category = isset($_REQUEST['category']) ? (int)$_REQUEST['category'] : null;
$player_id = isset($_REQUEST['player_id']) ? (int)$_REQUEST['player_id'] : null;
$article_text = isset($_REQUEST['article_text']) ? $_REQUEST['article_text'] : null;
$article_image = isset($_REQUEST['article_image']) ? $_REQUEST['article_image'] : null;
$forum_section = isset($_REQUEST['forum_section']) ? $_REQUEST['forum_section'] : null;
$errors = array();
if($action == 'add') {
if(isset($forum_section) && $forum_section != '-1') {
$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)) {
$p_title = $body = $comments = $article_text = $article_image = '';
$type = $category = $player_id = 0;
success("Added successful.");
}
}
else if($action == 'delete') {
News::delete($id, $errors);
success("Deleted successful.");
}
else if($action == 'edit')
{
if(isset($id) && !isset($p_title)) {
$news = News::get($id);
$p_title = $news['title'];
$body = $news['body'];
$comments = $news['comments'];
$type = $news['type'];
$category = $news['category'];
$player_id = $news['player_id'];
$article_text = $news['article_text'];
$article_image = $news['article_image'];
}
else {
if(News::update($id, $p_title, $body, $type, $category, $player_id, $forum_section, $article_text, $article_image, $errors)) {
// update forum thread if exists
if(isset($forum_section) && Validator::number($forum_section)) {
$db->query("UPDATE `" . TABLE_PREFIX . "forum` SET `author_guid` = ".(int) $player_id.", `post_text` = ".$db->quote($body).", `post_topic` = ".$db->quote($p_title).", `edit_date` = " . time() . " WHERE `id` = " . $db->quote($forum_section));
}
$action = $p_title = $body = $comments = $article_text = $article_image = '';
$type = $category = $player_id = 0;
success("Updated successful.");
}
}
}
else if($action == 'hide') {
News::toggleHidden($id, $errors, $status);
success(($status == 1 ? 'Show' : 'Hide') . " successful.");
}
if(!empty($errors))
error(implode(", ", $errors));
}
$categories = array();
foreach($db->query('SELECT `id`, `name`, `icon_id` FROM `' . TABLE_PREFIX . 'news_categories` WHERE `hidden` != 1') as $cat)
{
$categories[$cat['id']] = array(
'name' => $cat['name'],
'icon_id' => $cat['icon_id']
);
}
if($action == 'edit' || $action == 'new') {
if($action == 'edit') {
$player = new OTS_Player();
$player->load($player_id);
}
$account_players = $account_logged->getPlayersList();
$account_players->orderBy('group_id', POT::ORDER_DESC);
$twig->display('admin.news.form.html.twig', array(
'action' => $action,
'news_link' => getLink(PAGE),
'news_link_form' => '?p=news&action=' . ($action == 'edit' ? 'edit' : 'add'),
'news_id' => isset($id) ? $id : null,
'title' => isset($p_title) ? $p_title : '',
'body' => isset($body) ? htmlentities($body, ENT_COMPAT, 'UTF-8') : '',
'type' => isset($type) ? $type : null,
'player' => isset($player) && $player->isLoaded() ? $player : null,
'player_id' => isset($player_id) ? $player_id : null,
'account_players' => $account_players,
'category' => isset($category) ? $category : 0,
'categories' => $categories,
'forum_boards' => getForumBoards(),
'forum_section' => isset($forum_section) ? $forum_section : null,
'comments' => isset($comments) ? $comments : null,
'article_text' => isset($article_text) ? $article_text : null,
'article_image' => isset($article_image) ? $article_image : null
));
}
$query = $db->query('SELECT * FROM ' . $db->tableName(TABLE_PREFIX . 'news'));
$newses = array();
foreach ($query as $_news) {
$_player = new OTS_Player();
$_player->load($_news['player_id']);
$newses[$_news['type']][] = array(
'id' => $_news['id'],
'hidden' => $_news['hidden'],
'archive_link' => getLink('news') . '/archive/' . $_news['id'],
'title' => $_news['title'],
'date' => $_news['date'],
'player_name' => isset($_player) && $_player->isLoaded() ? $_player->getName() : '',
'player_link' => isset($_player) && $_player->isLoaded() ? getPlayerLink($_player->getName(), false) : '',
);
}
$twig->display('admin.news.html.twig', array(
'newses' => $newses
));

View File

@@ -1,52 +0,0 @@
<?php
/**
* Notepad
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Notepad';
$notepad_content = Notepad::get($account_logged->getId());
if (isset($_POST['content'])) {
$_content = html_entity_decode(stripslashes($_POST['content']));
if (!$notepad_content)
Notepad::create($account_logged->getId(), $_content);
else
Notepad::update($account_logged->getId(), $_content);
echo '<div class="success" style="text-align: center;">Saved at ' . date('H:i') . '</div>';
} else {
if ($notepad_content !== false)
$_content = $notepad_content;
}
$twig->display('admin.notepad.html.twig', array('content' => isset($_content) ? $_content : null));
class Notepad
{
static public function get($account_id)
{
global $db;
$query = $db->select(TABLE_PREFIX . 'notepad', array('account_id' => $account_id));
if ($query !== false)
return $query['content'];
return false;
}
static public function create($account_id, $content = '')
{
global $db;
$db->insert(TABLE_PREFIX . 'notepad', array('account_id' => $account_id, 'content' => $content));
}
static public function update($account_id, $content = '')
{
global $db;
$db->update(TABLE_PREFIX . 'notepad', array('content' => $content), array('account_id' => $account_id));
}
}

View File

@@ -1,200 +0,0 @@
<?php
/**
* Pages
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Pages';
if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) {
echo 'Access denied.';
return;
}
header('X-XSS-Protection:0');
$name = $p_title = '';
$groups = new OTS_Groups_List();
$php = false;
$enable_tinymce = true;
$access = 0;
if (!empty($action)) {
if ($action == 'delete' || $action == 'edit' || $action == 'hide')
$id = $_REQUEST['id'];
if (isset($_REQUEST['name']))
$name = $_REQUEST['name'];
if (isset($_REQUEST['title']))
$p_title = $_REQUEST['title'];
$php = isset($_REQUEST['php']) && $_REQUEST['php'] == 1;
$enable_tinymce = isset($_REQUEST['enable_tinymce']) && $_REQUEST['enable_tinymce'] == 1;
if ($php)
$body = $_REQUEST['body'];
else if (isset($_REQUEST['body'])) {
//$body = $_REQUEST['body'];
$body = html_entity_decode(stripslashes($_REQUEST['body']));
}
if (isset($_REQUEST['access']))
$access = $_REQUEST['access'];
$errors = array();
$player_id = 1;
if ($action == 'add') {
if (Pages::add($name, $p_title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) {
$name = $p_title = $body = '';
$player_id = $access = 0;
$php = false;
$enable_tinymce = true;
}
} else if ($action == 'delete') {
if (Pages::delete($id, $errors))
success('Page with id ' . $id . ' has been deleted');
} else if ($action == 'edit') {
if (isset($id) && !isset($_REQUEST['name'])) {
$_page = Pages::get($id);
$name = $_page['name'];
$p_title = $_page['title'];
$body = $_page['body'];
$php = $_page['php'] == '1';
$enable_tinymce = $_page['enable_tinymce'] == '1';
$access = $_page['access'];
} else {
Pages::update($id, $name, $p_title, $body, $player_id, $php, $enable_tinymce, $access);
$action = $name = $p_title = $body = '';
$player_id = 1;
$access = 0;
$php = false;
$enable_tinymce = true;
}
} else if ($action == 'hide') {
Pages::toggleHidden($id, $errors);
}
if (!empty($errors))
error(implode(", ", $errors));
}
$query =
$db->query('SELECT * FROM ' . $db->tableName(TABLE_PREFIX . 'pages'));
$pages = array();
foreach ($query as $_page) {
$pages[] = array(
'link' => getFullLink($_page['name'], $_page['name'], true),
'title' => substr($_page['title'], 0, 20),
'php' => $_page['php'] == '1',
'id' => $_page['id'],
'hidden' => $_page['hidden']
);
}
$twig->display('admin.pages.form.html.twig', array(
'action' => $action,
'id' => $action == 'edit' ? $id : null,
'name' => $name,
'title' => $p_title,
'php' => $php,
'enable_tinymce' => $enable_tinymce,
'body' => isset($body) ? htmlentities($body, ENT_COMPAT, 'UTF-8') : '',
'groups' => $groups->getGroups(),
'access' => $access
));
$twig->display('admin.pages.html.twig', array(
'pages' => $pages
));
class Pages
{
static public function get($id)
{
global $db;
$query = $db->select(TABLE_PREFIX . 'pages', array('id' => $id));
if ($query !== false)
return $query;
return false;
}
static public function add($name, $title, $body, $player_id, $php, $enable_tinymce, $access, &$errors)
{
global $db;
if (isset($name[0]) && isset($title[0]) && isset($body[0]) && $player_id != 0) {
$query = $db->select(TABLE_PREFIX . 'pages', array('name' => $name));
if ($query === false)
$db->insert(TABLE_PREFIX . 'pages',
array(
'name' => $name,
'title' => $title,
'body' => $body,
'player_id' => $player_id,
'php' => $php ? '1' : '0',
'enable_tinymce' => $enable_tinymce ? '1' : '0',
'access' => $access
)
);
else
$errors[] = 'Page with this link already exists.';
} else
$errors[] = 'Please fill all inputs.';
return !count($errors);
}
static public function update($id, $name, $title, $body, $player_id, $php, $enable_tinymce, $access)
{
global $db;
$db->update(TABLE_PREFIX . 'pages',
array(
'name' => $name,
'title' => $title,
'body' => $body,
'player_id' => $player_id,
'php' => $php ? '1' : '0',
'enable_tinymce' => $enable_tinymce ? '1' : '0',
'access' => $access
),
array('id' => $id));
}
static public function delete($id, &$errors)
{
global $db;
if (isset($id)) {
if ($db->select(TABLE_PREFIX . 'pages', array('id' => $id)) !== false)
$db->delete(TABLE_PREFIX . 'pages', array('id' => $id));
else
$errors[] = 'Page with id ' . $id . ' does not exists.';
} else
$errors[] = 'id not set';
return !count($errors);
}
static public function toggleHidden($id, &$errors)
{
global $db;
if (isset($id)) {
$query = $db->select(TABLE_PREFIX . 'pages', array('id' => $id));
if ($query !== false)
$db->update(TABLE_PREFIX . 'pages', array('hidden' => ($query['hidden'] == 1 ? 0 : 1)), array('id' => $id));
else
$errors[] = 'Page with id ' . $id . ' does not exists.';
} else
$errors[] = 'id not set';
return !count($errors);
}
}
?>

View File

@@ -1,19 +0,0 @@
<?php
/**
* PHP Info
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'PHP Info';
if (!function_exists('phpinfo')) { ?>
<b>phpinfo()</b> function is disabled in your webserver config.<br/>
You can enable it by editing <b>php.ini</b> file.
<?php return;
}
?>
<iframe src="<?php echo BASE_URL; ?>admin/tools/phpinfo.php" width="1024" height="550"></iframe>

View File

@@ -1,901 +0,0 @@
<?php
/**
* Players editor
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Player editor';
$player_base = BASE_URL . 'admin/?p=players';
$use_datatable = true;
require_once LIBS . 'forum.php';
$skills = array(
POT::SKILL_FIST => array('Fist fighting', 'fist'),
POT::SKILL_CLUB => array('Club fighting', 'club'),
POT::SKILL_SWORD => array('Sword fighting', 'sword'),
POT::SKILL_AXE => array('Axe fighting', 'axe'),
POT::SKILL_DIST => array('Distance fighting', 'dist'),
POT::SKILL_SHIELD => array('Shielding', 'shield'),
POT::SKILL_FISH => array('Fishing', 'fish')
);
$hasBlessingsColumn = $db->hasColumn('players', 'blessings');
$hasBlessingColumn = $db->hasColumn('players', 'blessings1');
$hasLookAddons = $db->hasColumn('players', 'lookaddons');
$skull_type = array("None", "Yellow", "Green", "White", "Red", "Black", "Orange");
?>
<link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ >
<script src="<?php echo BASE_URL; ?>tools/js/jquery.datetimepicker.js"></script>
<?php
$id = 0;
$search_player = '';
if (isset($_REQUEST['id']))
$id = (int)$_REQUEST['id'];
else if (isset($_REQUEST['search'])) {
$search_player = $_REQUEST['search'];
if (strlen($search_player) < 3 && !Validator::number($search_player)) {
echo_error('Player name is too short.');
} else {
$query = $db->query('SELECT `id` FROM `players` WHERE `name` = ' . $db->quote($search_player));
if ($query->rowCount() == 1) {
$query = $query->fetch();
$id = (int)$query['id'];
} else {
$query = $db->query('SELECT `id`, `name` FROM `players` WHERE `name` LIKE ' . $db->quote('%' . $search_player . '%'));
if ($query->rowCount() > 0 && $query->rowCount() <= 10) {
$str_construct = 'Do you mean?<ul>';
foreach ($query as $row)
$str_construct .= '<li><a href="' . $player_base . '&id=' . $row['id'] . '">' . $row['name'] . '</a></li>';
$str_construct .= '</ul>';
echo_error($str_construct);
} else if ($query->rowCount() > 10)
echo_error('Specified name resulted with too many players.');
else
echo_error('No entries found.');
}
}
}
?>
<div class="row">
<?php
$groups = new OTS_Groups_List();
if ($id > 0) {
$player = new OTS_Player();
$player->load($id);
if (isset($player) && $player->isLoaded() && isset($_POST['save'])) {// we want to save
$error = false;
if ($player->isOnline())
echo_error('This player is actually online. You can\'t edit online players.');
$name = $_POST['name'];
$_error = '';
if (!Validator::characterName($name))
echo_error(Validator::getLastError());
//if(!Validator::newCharacterName($name)
// echo_error(Validator::getLastError());
$player_db = new OTS_Player();
$player_db->find($name);
if ($player_db->isLoaded() && $player->getName() != $name)
echo_error('This name is already used. Please choose another name!');
$account_id = $_POST['account_id'];
verify_number($account_id, 'Account id', 11);
$account_db = new OTS_Account();
$account_db->load($account_id);
if (!$account_db->isLoaded())
echo_error('Account with this id doesn\'t exist.');
$group = $_POST['group'];
if ($groups->getGroup($group) == false)
echo_error('Group with this id doesn\'t exist');
$level = $_POST['level'];
verify_number($level, 'Level', 11);
$experience = $_POST['experience'];
verify_number($experience, 'Experience', 20);
$vocation = $_POST['vocation'];
verify_number($vocation, 'Vocation id', 11);
if (!isset($config['vocations'][$vocation])) {
echo_error("Vocation with this id doesn't exist.");
}
// health
$health = $_POST['health'];
verify_number($health, 'Health', 11);
$health_max = $_POST['health_max'];
verify_number($health_max, 'Health max', 11);
// mana
$magic_level = $_POST['magic_level'];
verify_number($magic_level, 'Magic_level', 11);
$mana = $_POST['mana'];
verify_number($mana, 'Mana', 11);
$mana_max = $_POST['mana_max'];
verify_number($mana_max, 'Mana max', 11);
$mana_spent = $_POST['mana_spent'];
verify_number($mana_spent, 'Mana spent', 11);
// look
$look_body = $_POST['look_body'];
verify_number($look_body, 'Look body', 11);
$look_feet = $_POST['look_feet'];
verify_number($look_feet, 'Look feet', 11);
$look_head = $_POST['look_head'];
verify_number($look_head, 'Look head', 11);
$look_legs = $_POST['look_legs'];
verify_number($look_legs, 'Look legs', 11);
$look_type = $_POST['look_type'];
verify_number($look_type, 'Look type', 11);
if ($hasLookAddons) {
$look_addons = $_POST['look_addons'];
verify_number($look_addons, 'Look addons', 11);
}
// pos
$pos_x = $_POST['pos_x'];
verify_number($pos_x, 'Position x', 11);
$pos_y = $_POST['pos_y'];
verify_number($pos_y, 'Position y', 11);
$pos_z = $_POST['pos_z'];
verify_number($pos_z, 'Position z', 11);
$soul = $_POST['soul'];
verify_number($soul, 'Soul', 10);
$town = $_POST['town'];
verify_number($town, 'Town', 11);
$capacity = $_POST['capacity'];
verify_number($capacity, 'Capacity', 11);
$sex = $_POST['sex'];
verify_number($sex, 'Sex', 1);
$lastlogin = strtotime($_POST['lastlogin']);
verify_number($lastlogin, 'Last login', 20);
$lastlogout = strtotime($_POST['lastlogout']);
verify_number($lastlogout, 'Last logout', 20);
$skull = $_POST['skull'];
verify_number($skull, 'Skull', 1);
$skull_time = $_POST['skull_time'];
verify_number($skull_time, 'Skull time', 11);
if ($db->hasColumn('players', 'loss_experience')) {
$loss_experience = $_POST['loss_experience'];
verify_number($loss_experience, 'Loss experience', 11);
$loss_mana = $_POST['loss_mana'];
verify_number($loss_mana, 'Loss mana', 11);
$loss_skills = $_POST['loss_skills'];
verify_number($loss_skills, 'Loss skills', 11);
$loss_containers = $_POST['loss_containers'];
verify_number($loss_containers, 'Loss loss_containers', 11);
$loss_items = $_POST['loss_items'];
verify_number($loss_items, 'Loss items', 11);
}
if ($db->hasColumn('players', 'offlinetraining_time')) {
$offlinetraining = $_POST['offlinetraining'];
verify_number($offlinetraining, 'Offline Training time', 11);
}
if ($hasBlessingsColumn) {
$blessings = $_POST['blessings'];
verify_number($blessings, 'Blessings', 2);
}
$balance = $_POST['balance'];
verify_number($balance, 'Balance', 20);
if ($db->hasColumn('players', 'stamina')) {
$stamina = $_POST['stamina'];
verify_number($stamina, 'Stamina', 20);
}
$deleted = (isset($_POST['deleted']) && $_POST['deleted'] == 'true');
$hidden = (isset($_POST['hidden']) && $_POST['hidden'] == 'true');
$created = strtotime($_POST['created']);
verify_number($created, 'Created', 11);
$comment = isset($_POST['comment']) ? htmlspecialchars(stripslashes(substr($_POST['comment'], 0, 2000))) : NULL;
foreach ($_POST['skills'] as $skill => $value)
verify_number($value, $skills[$skill][0], 10);
foreach ($_POST['skills_tries'] as $skill => $value)
verify_number($value, $skills[$skill][0] . ' tries', 10);
if ($hasBlessingColumn) {
$bless_count = $_POST['blesscount'];
for ($i = 1; $i <= $bless_count; $i++) {
$a = 'blessing' . $i;
${'blessing' . $i} = (isset($_POST[$a]) && $_POST[$a] == 'true');
}
}
if (!$error) {
$player->setName($name);
$player->setAccount($account_db);
$player->setGroup($groups->getGroup($group));
$player->setLevel($level);
$player->setExperience($experience);
$player->setVocation($vocation);
$player->setHealth($health);
$player->setHealthMax($health_max);
$player->setMagLevel($magic_level);
$player->setMana($mana);
$player->setManaMax($mana_max);
$player->setManaSpent($mana_spent);
$player->setLookBody($look_body);
$player->setLookFeet($look_feet);
$player->setLookHead($look_head);
$player->setLookLegs($look_legs);
$player->setLookType($look_type);
if ($hasLookAddons)
$player->setLookAddons($look_addons);
if ($db->hasColumn('players', 'offlinetraining_time'))
$player->setCustomField('offlinetraining_time', $offlinetraining);
$player->setPosX($pos_x);
$player->setPosY($pos_y);
$player->setPosZ($pos_z);
$player->setSoul($soul);
$player->setTownId($town);
$player->setCap($capacity);
$player->setSex($sex);
$player->setLastLogin($lastlogin);
$player->setLastLogout($lastlogout);
//$player->setLastIP(ip2long($lastip));
$player->setSkull($skull);
$player->setSkullTime($skull_time);
if ($db->hasColumn('players', 'loss_experience')) {
$player->setLossExperience($loss_experience);
$player->setLossMana($loss_mana);
$player->setLossSkills($loss_skills);
$player->setLossContainers($loss_containers);
$player->setLossItems($loss_items);
}
if ($db->hasColumn('players', 'blessings'))
$player->setBlessings($blessings);
if ($hasBlessingColumn) {
for ($i = 1; $i <= $bless_count; $i++) {
$a = 'blessing' . $i;
$player->setCustomField('blessings' . $i, ${'blessing' . $i} ? '1' : '0');
}
}
$player->setBalance($balance);
if ($db->hasColumn('players', 'stamina'))
$player->setStamina($stamina);
if ($db->hasColumn('players', 'deletion'))
$player->setCustomField('deletion', $deleted ? '1' : '0');
else
$player->setCustomField('deleted', $deleted ? '1' : '0');
$player->setCustomField('hidden', $hidden ? '1' : '0');
$player->setCustomField('created', $created);
if (isset($comment))
$player->setCustomField('comment', $comment);
foreach ($_POST['skills'] as $skill => $value) {
$player->setSkill($skill, $value);
}
foreach ($_POST['skills_tries'] as $skill => $value) {
$player->setSkillTries($skill, $value);
}
$player->save();
echo_success('Player saved at: ' . date('G:i'));
$player->load($id);
}
}
} else if ($id == 0) {
$players_db = $db->query('SELECT `id`, `name`, `level` FROM `players` ORDER BY `id` asc');
?>
<div class="col-12 col-sm-12 col-lg-10">
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">Players</h5>
</div>
<div class="card-body">
<table class="player_datatable table table-striped table-bordered table-responsive d-md-table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Level</th>
<th style="width: 40px">Edit</th>
</tr>
</thead>
<tbody>
<?php foreach ($players_db as $player_db): ?>
<tr>
<th><?php echo $player_db['id']; ?></th>
<td><?php echo $player_db['name']; ?></a></td>
<td><?php echo $player_db['level']; ?></a></td>
<td><a href="?p=players&id=<?php echo $player_db['id']; ?>" class="btn btn-success btn-sm" title="Edit">
<i class="fas fa-pencil-alt"></i>
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php } ?>
<?php
if (isset($player) && $player->isLoaded()) {
$account = $player->getAccount();
?>
<div class="col-12 col-sm-12 col-lg-10">
<div class="card card-primary card-outline card-outline-tabs">
<div class="card-header p-0 border-bottom-0">
<ul class="nav nav-tabs" id="tabs-tab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="tabs-home-tab" data-toggle="pill" href="#tabs-home">Player</a>
</li>
<li class="nav-item">
<a class="nav-link" id="tabs-home-tab" data-toggle="pill" href="#tabs-stats">Stats</a>
</li>
<li class="nav-item">
<a class="nav-link" id="tabs-home-tab" data-toggle="pill" href="#tabs-skills">Skills</a>
</li>
<li class="nav-item">
<a class="nav-link" id="tabs-home-tab" data-toggle="pill" href="#tabs-pos">Pos/Look</a>
</li>
<li class="nav-item">
<a class="nav-link" id="tabs-home-tab" data-toggle="pill" href="#tabs-misc">Misc</a>
</li>
<li class="nav-item">
<a class="nav-link" id="tabs-posts-tab" data-toggle="pill" href="#tabs-posts">Posts</a>
</li>
<li class="nav-item">
<a class="nav-link" id="tabs-chars-tab" data-toggle="pill" href="#tabs-chars">Characters</a>
</li>
</ul>
</div>
<form action="<?php echo $player_base . ((isset($id) && $id > 0) ? '&id=' . $id : ''); ?>" method="post">
<div class="card-body">
<div class="tab-content" id="tabs-tabContent">
<div class="tab-pane fade active show" id="tabs-home">
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<label for="name" class="control-label">Name</label>
<input type="text" class="form-control" id="name" name="name" autocomplete="off" value="<?php echo $player->getName(); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="account_id">Account id:</label>
<input type="text" class="form-control" id="account_id" name="account_id" autocomplete="off" size="8" maxlength="11" value="<?php echo $account->getId(); ?>"/>
</div>
</div>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<label for="group">Group:</label>
<select name="group" id="group" class="form-control custom-select">
<?php foreach ($groups->getGroups() as $id => $group): ?>
<option value="<?php echo $id; ?>" <?php echo($player->getGroup()->getId() == $id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="vocation">Vocation</label>
<select name="vocation" id="vocation" class="form-control custom-select">
<?php
foreach ($config['vocations'] as $id => $name) {
echo '<option value=' . $id . ($id == $player->getVocation() ? ' selected' : '') . '>' . $name . '</option>';
}
?>
</select>
</div>
</div>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<label for="sex">Sex:</label>
<select name="sex" id="sex" class="form-control custom-select">>
<?php foreach ($config['genders'] as $id => $sex): ?>
<option value="<?php echo $id; ?>" <?php echo($player->getSex() == $id ? 'selected' : ''); ?>><?php echo strtolower($sex); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="town">Town:</label>
<select name="town" id="town" class="form-control">
<?php
$configTowns = config('towns');
if (!isset($configTowns[$player->getTownId()])) {
$configTowns[$player->getTownId()] = 'Unknown Town';
}
foreach ($configTowns as $id => $town): ?>
<option value="<?php echo $id; ?>" <?php echo($player->getTownId() == $id ? 'selected' : ''); ?>><?php echo $town; ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<label for="skull">Skull:</label>
<select name="skull" id="skull" class="form-control custom-select">
<?php
foreach ($skull_type as $id => $s_name) {
echo '<option value=' . $id . ($id == $player->getSkull() ? ' selected' : '') . '>' . $s_name . '</option>';
}
?>
</select>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="skull_time">Skull time:</label>
<input type="text" class="form-control" id="skull_time" name="skull_time"
autocomplete="off" maxlength="11"
value="<?php echo $player->getSkullTime(); ?>"/>
</div>
</div>
<div class="form-group row">
<?php if ($hasBlessingColumn):
$bless_count = $player->countBlessings();
$bless = $player->checkBlessings($bless_count); ?>
<input type="hidden" name="blesscount" value="<?php echo $bless_count; ?>"/>
<div class="col-12 col-sm-12 col-lg-6">
<label>Blessings:</label><br/>
<?php for ($i = 1; $i <= $bless_count; $i++): ?>
<label><input class="" type="checkbox" name="blessing<?php echo $i; ?>" id="blessing<?php echo $i; ?>" value="true"<?php echo(($bless[$i - 1] == 1) ? ' checked' : '') ?>/><?php echo $i; ?></label>
<?php endfor ?>
</div>
<?php endif; ?>
<?php if ($hasBlessingsColumn): ?>
<div class="col-12 col-sm-12 col-lg-6">
<label for="blessings">Blessings:</label>
<input type="text" class="form-control" id="blessings" name="blessings" autocomplete="off" maxlength="11" value="<?php echo $player->getBlessings(); ?>"/>
</div>
<?php endif; ?>
<div class="col-12 col-sm-12 col-lg-6">
<label for="balance" class="control-label">Bank Balance:</label>
<input type="text" class="form-control" id="balance" name="balance" autocomplete="off" maxlength="20" value="<?php echo $player->getBalance(); ?>"/>
</div>
</div>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<div class="custom-control custom-switch custom-switch-on-danger">
<input type="checkbox" class="custom-control-input" name="deleted" id="deleted" value="true" <?php echo($player->getCustomField($db->hasColumn('players', 'deletion') ? 'deletion' : 'deleted') == '1' ? ' checked' : ''); ?>>
<label class="custom-control-label" for="deleted">Deleted</label>
</div>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<div class="custom-control custom-switch custom-switch-on-success">
<input type="checkbox" class="custom-control-input" name="hidden" id="hidden" value="true" <?php echo($player->isHidden() ? ' checked' : ''); ?>>
<label class="custom-control-label" for="hidden">Hidden</label>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="tabs-stats">
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<label for="level" class="control-label">Level:</label>
<input type="text" class="form-control" id="level" name="level" autocomplete="off" value="<?php echo $player->getLevel(); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="experience" class="control-label">Experience:</label>
<input type="text" class="form-control" id="experience" name="experience" autocomplete="off" value="<?php echo $player->getExperience(); ?>"/>
</div>
</div>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<label for="magic_level" class="control-label">Magic level:</label>
<input type="text" class="form-control" id="magic_level" name="magic_level" autocomplete="off" size="8" maxlength="11" value="<?php echo $player->getMagLevel(); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="mana_spent" class="control-label">Mana spent:</label>
<input type="text" class="form-control" id="mana_spent" name="mana_spent" autocomplete="off" size="3" maxlength="11" value="<?php echo $player->getManaSpent(); ?>"/>
</div>
</div>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<label for="health" class="control-label">Health:</label>
<input type="text" class="form-control" id="health" name="health" autocomplete="off" size="5" maxlength="11" value="<?php echo $player->getHealth(); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="health_max" class="control-label">Health max:</label>
<input type="text" class="form-control" id="health_max" name="health_max" autocomplete="off" size="5" maxlength="11" value="<?php echo $player->getHealthMax(); ?>"/>
</div>
</div>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<label for="mana" class="control-label">Mana:</label>
<input type="text" class="form-control" id="mana" name="mana" autocomplete="off" size="3" maxlength="11" value="<?php echo $player->getMana(); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="mana_max" class="control-label">Mana max:</label>
<input type="text" class="form-control" id="mana_max" name="mana_max" autocomplete="off" size="3" maxlength="11" value="<?php echo $player->getManaMax(); ?>"/>
</div>
</div>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<label for="capacity" class="control-label">Capacity:</label>
<input type="text" class="form-control" id="capacity" name="capacity" autocomplete="off" size="3" maxlength="11" value="<?php echo $player->getCap(); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="soul" class="control-label">Soul:</label>
<input type="text" class="form-control" id="soul" name="soul" autocomplete="off" size="3" maxlength="10" value="<?php echo $player->getSoul(); ?>"/>
</div>
<?php if ($db->hasColumn('players', 'stamina')): ?>
<div class="col-12 col-sm-12 col-lg-6">
<label for="stamina" class="control-label">Stamina:</label>
<input type="text" class="form-control" id="stamina" name="stamina" autocomplete="off" maxlength="20" value="<?php echo $player->getStamina(); ?>"/>
</div>
<?php endif; ?>
<?php if ($db->hasColumn('players', 'offlinetraining_time')): ?>
<div class="col-12 col-sm-12 col-lg-6">
<label for="offlinetraining" class="control-label">Offline Training
Time:</label>
<input type="text" class="form-control" id="offlinetraining" name="offlinetraining" autocomplete="off" maxlength="11" value="<?php echo $player->getCustomField('offlinetraining_time'); ?>"/>
</div>
<?php endif; ?>
</div>
</div>
<div class="tab-pane fade" id="tabs-skills">
<?php
foreach ($skills as $id => $info) {
?>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<?php echo '<label for="skills[' . $id . ']" class="control-label">' . $info[0] . '</label>
<input type="text" class="form-control" id="skills[' . $id . ']" name="skills[' . $id . ']" maxlength="10" autocomplete="off" value="' . $player->getSkill($id) . '"/>'; ?>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<?php echo '<label for="skills_tries[' . $id . ']" class="control-label">' . $info[0] . ' tries</label>
<input type="text" class="form-control" id="skills_tries[' . $id . ']" name="skills_tries[' . $id . ']" maxlength="10" autocomplete="off" value="' . $player->getSkillTries($id) . '"/>'; ?>
</div>
</div>
<?php } ?>
</div>
<div class="tab-pane fade" id="tabs-pos">
<?php $outfit = $config['outfit_images_url'] . '?id=' . $player->getLookType() . ($hasLookAddons ? '&addons=' . $player->getLookAddons() : '') . '&head=' . $player->getLookHead() . '&body=' . $player->getLookBody() . '&legs=' . $player->getLookLegs() . '&feet=' . $player->getLookFeet(); ?>
<div id="imgchar" style="width:64px;height:64px;position:absolute; top:30px; right:30px">
<img id="player_outfit" style="margin-left:0;margin-top:0;width:64px;height:64px;" src="<?php echo $outfit; ?>" alt="player outfit"/>
</div>
<td>Position:</td>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-4">
<label for="pos_x" class="control-label">X:</label>
<input type="text" class="form-control" id="pos_x" name="pos_x" autocomplete="off" maxlength="11" value="<?php echo $player->getPosX(); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-4">
<label for="pos_y" class="control-label">Y:</label>
<input type="text" class="form-control" id="pos_y" name="pos_y" autocomplete="off" maxlength="11" value="<?php echo $player->getPosY(); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-4">
<label for="pos_z" class="control-label">Z:</label>
<input type="text" class="form-control" id="pos_z" name="pos_z" autocomplete="off" maxlength="11" value="<?php echo $player->getPosZ(); ?>"/>
</div>
</div>
<td>Look:</td>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-3">
<label for="look_head" class="control-label">Head: <span id="look_head_val" class="font-weight-bold text-primary"></span></label>
<input class="custom-range" type="range" min="0" max="132" id="look_head" name="look_head" value="<?php echo $player->getLookHead(); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-3">
<label for="look_body" class="control-label">Body: <span id="look_body_val" class="font-weight-bold text-primary"></span></label>
<input type="range" min="0" max="132"
value="<?php echo $player->getLookBody(); ?>"
class="custom-range" id="look_body" name="look_body">
</div>
<div class="col-12 col-sm-12 col-lg-3">
<label for="look_legs" class="control-label">Legs: <span id="look_legs_val" class="font-weight-bold text-primary"></span></label>
<input type="range" min="0" max="132"
value="<?php echo $player->getLookLegs(); ?>"
class="custom-range" id="look_legs" name="look_legs">
</div>
<div class="col-12 col-sm-12 col-lg-3">
<label for="look_feet" class="control-label">Feet: <span id="look_feet_val" class="font-weight-bold text-primary"></span></label>
<input type="range" min="0" max="132"
value="<?php echo $player->getLookBody(); ?>"
class="custom-range" id="look_feet" name="look_feet">
</div>
</div>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<label for="look_type" class="control-label">Type:</label>
<?php
$outfitlist = null;
$outfitlist = Outfits_loadfromXML();
if ($outfitlist) { ?>
<select name="look_type" id="look_type" class="form-control custom-select">
<?php
foreach ($outfitlist as $id => $outfit) {
if ($outfit['enabled'] == 'yes') ;
echo '<option value=' . $outfit['id'] . ($outfit['id'] == $player->getLookType() ? ' selected' : '') . '>' . $outfit['name'] . ' - ' . ($outfit['type'] == 1 ? 'Male' : 'Female') . '</option>';
}
?>
</select>
<?php } else { ?>
<input type="text" class="form-control" id="look_type" name="look_type" autocomplete="off" maxlength="11" value="<?php echo $player->getLookType(); ?>"/>
<?php } ?>
</div>
<?php if ($hasLookAddons): ?>
<div class="col-12 col-sm-12 col-lg-6">
<label for="look_addons" class="control-label">Addons:</label>
<select name="look_addons" id="look_addons" class="form-control custom-select">
<?php
$addon_type = array(0, 1, 2, 3);
foreach ($addon_type as $id => $s_name) {
echo '<option value=' . $s_name . ($id == $player->getLookAddons() ? ' selected' : '') . '>' . $s_name . '</option>';
}
?>
</select>
</div>
<?php endif; ?>
</div>
</div>
<div class="tab-pane fade" id="tabs-misc">
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<label for="created" class="control-label">Created:</label>
<input type="text" class="form-control" id="created" name="created"
autocomplete="off"
maxlength="10"
value="<?php echo date("M d Y, H:i:s", $player->getCustomField('created')); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="lastlogin" class="control-label">Last login:</label>
<input type="text" class="form-control" id="lastlogin" name="lastlogin" autocomplete="off" maxlength="20" value="<?php echo date("M d Y, H:i:s", $player->getLastLogin()); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="lastlogout" class="control-label">Last logout:</label>
<input type="text" class="form-control" id="lastlogout" name="lastlogout" autocomplete="off" maxlength="20" value="<?php echo date("M d Y, H:i:s", $player->getLastLogout()); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="lastip" class="control-label">Last IP:</label>
<input type="text" class="form-control" id="lastip" name="lastip" autocomplete="off" maxlength="10" value="<?php echo longToIp($player->getLastIP()); ?>" readonly/>
</div>
</div>
<?php if ($db->hasColumn('players', 'loss_experience')): ?>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<label for="loss_experience" class="control-label">Experience
Loss:</label>
<input type="text" class="form-control" id="loss_experience" name="loss_experience" autocomplete="off" maxlength="11" value="<?php echo $player->getLossExperience(); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="loss_mana" class="control-label">Mana Loss:</label>
<input type="text" class="form-control" id="loss_mana" name="loss_mana" autocomplete="off" maxlength="11" value="<?php echo $player->getLossMana(); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="loss_skills" class="control-label">Skills Loss:</label>
<input type="text" class="form-control" id="loss_skills" name="loss_skills" autocomplete="off" maxlength="11" value="<?php echo $player->getLossSkills(); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="loss_containers" class="control-label">Containers Loss:</label>
<input type="text" class="form-control" id="loss_containers" name="loss_containers" autocomplete="off" maxlength="11" value="<?php echo $player->getLossContainers(); ?>"/>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<label for="loss_items" class="control-label">Items Loss:</label>
<input type="text" class="form-control" id="loss_items" name="loss_items" autocomplete="off" maxlength="11" value="<?php echo $player->getLossItems(); ?>"/>
</div>
</div>
<?php endif; ?>
<div class="form-group row">
<div class="col-12">
<label for="comment" class="control-label">Comment:</label>
<textarea class="form-control" name="comment" rows="10" cols="50" wrap="virtual"><?php echo $player->getCustomField("comment"); ?></textarea>
<small>[max. length: 2000 chars, 50 lines (ENTERs)]</small>
</div>
</div>
</div>
<div class="tab-pane fade" id="tabs-posts">
<table class="table table-striped table-condensed table-responsive d-md-table">
<thead>
<tr>
<th class="w-25">Topic</th>
<th>Content</th>
</tr>
</thead>
<tbody>
<?php
$posts = $db->query('SELECT `author_guid`,`section`,`first_post`,`post_text`,`post_date`, `post_topic`,`post_html`,`post_smile`,`' . TABLE_PREFIX . 'forum_boards`.`name` AS `forum_Name` FROM `' .
TABLE_PREFIX . 'forum` LEFT JOIN `' . TABLE_PREFIX . 'forum_boards` ON `' .
TABLE_PREFIX . 'forum`.section = `' . TABLE_PREFIX . 'forum_boards`.id WHERE `author_guid` = "' . $player->getId() . '" ORDER BY `post_date` DESC LIMIT 10');
if ($posts->rowCount() > 0) {
$posts = $posts->fetchAll();
foreach ($posts as $post) {
$text = ($post['post_html'] > 0 ? $post['post_text'] : htmlspecialchars($post['post_text']));
$post['content'] = ($post['post_html'] > 0 ? $text : Forum::parseBBCode(nl2br($text), $post['post_smile'] == 0));
?>
<tr>
<th><?php echo htmlspecialchars($post['post_topic']); ?><br/><small><?php echo date('d M y H:i:s', $post['post_date']); ?></small><br/>
Topic: <a href="<?php echo getForumThreadLink($post['first_post']); ?>" class="link-black text-sm"><i class="fa fa-share margin-r-5"></i> Link</a><br/>
Forum: <a href="<?php echo getForumBoardLink($post['section']); ?>" class="link-black text-sm"><i class="fa fa-share margin-r-5"></i> <?php echo $post['forum_Name']; ?></a></th>
<th><?php echo $post['content']; ?></th>
</tr>
<?php
}
unset($post);
} else {
echo '<tr><td colspan="2">This user has no posts</td></tr>';
}; ?>
</tbody>
</table>
</div>
<div class="tab-pane fade" id="tabs-chars">
<div class="row">
<?php
if (isset($account) && $account->isLoaded()) {
$account_players = $account->getPlayersList();
$account_players->orderBy('id');
if (isset($account_players)) { ?>
<table class="table table-striped table-condensed table-responsive d-md-table">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Level</th>
<th>Vocation</th>
<th style="width: 40px">Edit</th>
</tr>
</thead>
<tbody>
<?php foreach ($account_players as $i => $player):
$player_vocation = $player->getVocation();
$player_promotion = $player->getPromotion();
if (isset($player_promotion)) {
if ((int)$player_promotion > 0)
$player_vocation += ($player_promotion * $config['vocations_amount']);
}
if (isset($config['vocations'][$player_vocation])) {
$vocation_name = $config['vocations'][$player_vocation];
} ?>
<tr>
<th><?php echo $i; ?></th>
<td><?php echo $player->getName(); ?></td>
<td><?php echo $player->getLevel(); ?></td>
<td><?php echo $vocation_name; ?></td>
<td><a href="?p=players&id=<?php echo $player->getId() ?>" class=" btn btn-success btn-sm" title="Edit"><i class="fas fa-pencil-alt"></i></a></td>
</tr>
<?php endforeach ?>
</tbody>
</table>
<?php
}
} ?>
</div>
</div>
</div>
</div>
<div class="card-footer text-center">
<input type="hidden" name="save" value="yes"/>
<button type="submit" class="btn btn-info float-left"><i class="fas fa-update"></i> Update</button>
<a href="<?php echo ADMIN_URL; ?>?p=accounts&id=<?php echo $account->getId(); ?>" class="btn btn-secondary">Edit Account</a>
<a href="<?php echo ADMIN_URL; ?>?p=players" class="btn btn-danger float-right"><i class="fas fa-cancel"></i> Cancel</a>
</div>
</form>
</div>
</div>
<script type="text/javascript">
$('#lastlogin').datetimepicker({format: "M d Y, H:i:s",});
$('#lastlogout').datetimepicker({format: "M d Y, H:i:s",});
$('#created').datetimepicker({format: "M d Y, H:i:s",});
$(document).ready(function () {
const $headSpan = $('#look_head_val');
const $headvalue = $('#look_head');
$headSpan.html($headvalue.val());
$headvalue.on('input', () => {
$headSpan.html($headvalue.val());
});
$headvalue.on('change', () => {
updateOutfit();
});
const $bodySpan = $('#look_body_val');
const $bodyvalue = $('#look_body');
$bodySpan.html($bodyvalue.val());
$bodyvalue.on('input', () => {
$bodySpan.html($bodyvalue.val());
});
$bodyvalue.on('change', () => {
updateOutfit();
});
const $legsSpan = $('#look_legs_val');
const $legsvalue = $('#look_legs');
$legsSpan.html($legsvalue.val());
$legsvalue.on('input', () => {
$legsSpan.html($legsvalue.val());
});
$legsvalue.on('change', () => {
updateOutfit();
});
const $feetSpan = $('#look_feet_val');
const $feetvalue = $('#look_feet');
$feetSpan.html($feetvalue.val());
$feetvalue.on('input', () => {
$feetSpan.html($feetvalue.val());
});
$feetvalue.on('change', () => {
updateOutfit();
});
const $lookvalue = $('#look_type');
$lookvalue.on('change', () => {
updateOutfit();
});
<?php if($hasLookAddons): ?>
const $addonvalue = $('#look_addons');
$('#look_addons').on('change', () => {
updateOutfit();
});
<?php endif; ?>
});
function updateOutfit() {
const look_head = $('#look_head').val();
const look_body = $('#look_body').val();
const look_legs = $('#look_legs').val();
const look_feet = $('#look_feet').val();
const look_type = $('#look_type').val();
let look_addons = '';
<?php if($hasLookAddons): ?>
look_addons = '&addons=' + $('#look_addons').val();
<?php endif; ?>
$("#player_outfit").attr("src", '<?= $config['outfit_images_url']; ?>?id=' + look_type + look_addons + '&head=' + look_head + '&body=' + look_body + '&legs=' + look_legs + '&feet=' + look_feet);
}
</script>
<?php } ?>
<div class="col-12 col-sm-12 col-lg-2">
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">Search Player</h5>
</div>
<div class="card-body row">
<div class="col-6 col-lg-12">
<form action="<?php echo $player_base; ?>" method="post">
<label for="name">Player Name:</label>
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="search" value="<?php echo $search_player; ?>" maxlength="32" size="32">
<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span>
</div>
</form>
</div>
<div class="col-6 col-lg-12">
<form action="<?php echo $player_base; ?>" method="post">
<label for="name">Player ID:</label>
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="id" value="" maxlength="32" size="32">
<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.player_datatable').DataTable({
"order": [[0, "asc"]]
});
});
</script>

View File

@@ -1,114 +0,0 @@
<?php
/**
* Plugins
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Plugin manager';
require_once LIBS . 'plugins.php';
$twig->display('admin.plugins.form.html.twig');
if (isset($_REQUEST['uninstall'])) {
$uninstall = $_REQUEST['uninstall'];
if (Plugins::uninstall($uninstall)) {
success('Successfully uninstalled plugin ' . $uninstall);
} else {
error('Error while uninstalling plugin ' . $uninstall . ': ' . Plugins::getError());
}
} else if (isset($_FILES["plugin"]["name"])) {
$file = $_FILES["plugin"];
$filename = $file["name"];
$tmp_name = $file["tmp_name"];
$type = $file["type"];
$name = explode(".", $filename);
$accepted_types = array('application/zip', 'application/x-zip-compressed', 'multipart/x-zip', 'application/x-compressed', 'application/octet-stream', 'application/zip-compressed');
if (isset($file['error'])) {
$error = 'Error uploading file';
switch ($file['error']) {
case UPLOAD_ERR_OK:
$error = false;
break;
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
$error .= ' - file too large (limit of ' . ini_get('upload_max_filesize') . ' bytes). You can enlarge the limits by changing "upload_max_filesize" in php.ini';
break;
case UPLOAD_ERR_PARTIAL:
$error .= ' - file upload was not completed.';
break;
case UPLOAD_ERR_NO_FILE:
$error .= ' - zero-length file uploaded.';
break;
default:
$error .= ' - internal error #' . $file['error'];
break;
}
}
if (isset($error) && $error != false) {
error($error);
} else {
if (is_uploaded_file($file['tmp_name'])) {
$filetype = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
if ($filetype == 'zip') // check if it is zipped/compressed file
{
$tmp_filename = pathinfo($filename, PATHINFO_FILENAME);
$targetzip = BASE . 'plugins/' . $tmp_filename . '.zip';
if (move_uploaded_file($tmp_name, $targetzip)) { // move uploaded file
if (Plugins::install($targetzip)) {
foreach (Plugins::getWarnings() as $warning) {
warning($warning);
}
$info = Plugins::getPluginJson();
success((isset($info['name']) ? '<strong>' . $info['name'] . '</strong> p' : 'P') . 'lugin has been successfully installed.');
} else {
$error = Plugins::getError();
error(!empty($error) ? $error : 'Unexpected error happened while installing plugin. Please try again later.');
}
unlink($targetzip); // delete the Zipped file
} else
error('There was a problem with the upload. Please try again.');
} else {
error('The file you are trying to upload is not a .zip file. Please try again.');
}
} else {
error('Error uploading file - unknown error.');
}
}
}
$plugins = array();
foreach (get_plugins() as $plugin) {
$string = file_get_contents(BASE . 'plugins/' . $plugin . '.json');
$string = Plugins::removeComments($string);
$plugin_info = json_decode($string, true);
if ($plugin_info == false) {
warning('Cannot load plugin info ' . $plugin . '.json');
} else {
$plugins[] = array(
'name' => isset($plugin_info['name']) ? $plugin_info['name'] : '',
'description' => isset($plugin_info['description']) ? $plugin_info['description'] : '',
'version' => isset($plugin_info['version']) ? $plugin_info['version'] : '',
'author' => isset($plugin_info['author']) ? $plugin_info['author'] : '',
'contact' => isset($plugin_info['contact']) ? $plugin_info['contact'] : '',
'file' => $plugin,
'uninstall' => isset($plugin_info['uninstall'])
);
}
}
$twig->display('admin.plugins.html.twig', array(
'plugins' => $plugins
));

View File

@@ -1,60 +0,0 @@
<?php
/**
* Reports
*
* @package MyAAC
* @author Lee
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Report Viewer';
$files = array();
$server_path_reports = $config['data_path'] . 'reports/';
if (file_exists($server_path_reports)) {
foreach (scandir($server_path_reports, SCANDIR_SORT_ASCENDING) as $f) {
if ($f[0] === '.') {
continue;
}
if (is_dir($server_path_reports . $f)) {
foreach (scandir($server_path_reports . $f, SCANDIR_SORT_ASCENDING) as $f2) {
if ($f2[0] === '.') {
continue;
}
$files[] = array($f . '/' . $f2, $server_path_reports);
}
continue;
}
$files[] = array($f, $server_path_reports);
}
}
foreach ($files as &$f) {
$f['mtime'] = filemtime($f[1] . $f[0]);
$f['name'] = $f[0];
}
unset($f);
$file = isset($_GET['file']) ? $_GET['file'] : NULL;
if (!empty($file)) {
if (!preg_match('/[^A-z0-9\' _\/\-\.]/', $file)) {
if (file_exists($server_path_reports . $file)) {
$file_content = nl2br(file_get_contents($server_path_reports . $file));
$twig->display('admin.logs.view.html.twig', array('file' => $file, 'content' => $file_content));
} else {
echo 'Specified file does not exist.';
}
} else {
echo 'Invalid file name specified.';
}
}
$twig->display('admin.reports.html.twig', array('files' => $files));

View File

@@ -1,198 +0,0 @@
<?php
/**
* Menus
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Settings';
require_once SYSTEM . 'clients.conf.php';
if (!isset($_GET['plugin']) || empty($_GET['plugin'])) {
error('Please select plugin name from left Panel.');
return;
}
$plugin = $_GET['plugin'];
if($plugin != 'core') {
$settingsFilePath = PLUGINS . $plugin . '/settings.php';
}
else {
$settingsFilePath = SYSTEM . 'settings.php';
}
if (!file_exists($settingsFilePath)) {
error('This plugin does not exist or does not have settings defined.');
return;
}
if($plugin === 'core') {
$settingsFile = require $settingsFilePath;
}
else {
$settingsFile = require $settingsFilePath;
}
if (!is_array($settingsFile)) {
return;
}
if (isset($_POST['save'])) {
$db->query('DELETE FROM `' . TABLE_PREFIX . 'settings` WHERE `plugin_name` = ' . $db->quote($plugin) . ';');
foreach ($_POST['settings'] as $key => $value) {
try {
$db->insert(TABLE_PREFIX . 'settings', ['plugin_name' => $plugin, 'key' => $key, 'value' => $value]);
} catch (PDOException $error) {
warning('Error while saving setting (' . $plugin . ' - ' . $key . '): ' . $error->getMessage());
}
}
$cache = Cache::getInstance();
if ($cache->enabled()) {
$cache->delete('settings');
}
success('Saved at ' . date('H:i'));
}
$title = ($plugin == 'core' ? 'MyAAC Settings' : 'Plugin Settings - ' . $plugin);
$query = 'SELECT `key`, `value` FROM `' . TABLE_PREFIX . 'settings` WHERE `plugin_name` = ' . $db->quote($plugin) . ';';
$query = $db->query($query);
$settingsDb = [];
if($query->rowCount() > 0) {
foreach($query->fetchAll(PDO::FETCH_ASSOC) as $value) {
$settingsDb[$value['key']] = $value['value'];
}
}
?>
<form method="post">
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body">
<button name="save" type="submit" class="btn btn-primary">Save</button>
</div>
<?php
$checkbox = function ($key, $type, $value) {
echo '<label><input type="radio" id="' . $key . '" name="settings[' . $key . ']" value="' . ($type ? 'true' : 'false') . '" ' . ($value === $type ? 'checked' : '') . '/>' . ($type ? 'Yes' : 'No') . '</label> ';
};
$i = 0;
foreach($settingsFile as $key => $setting) {
if($setting['type'] === 'section') {
if($i++ !== 0) {
echo '</tbody></table>';
}
?>
<h2 style="text-align: center"><strong><?= $setting['title']; ?></strong></h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th style="width: 10%">Name</th>
<th style="width: 30%">Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<?php
continue;
}
?>
<tr>
<td><label for="<?= $key ?>" class="control-label"><?= $setting['name'] ?></label></td>
<td>
<?php
if ($setting['type'] === 'boolean') {
if(isset($settingsDb[$key])) {
if($settingsDb[$key] === 'true') {
$value = true;
}
else {
$value = false;
}
}
else {
$value = (isset($setting['default']) ? $setting['default'] : false);
}
$checkbox($key, true, $value);
$checkbox($key, false, $value);
}
else if (in_array($setting['type'], ['text', 'number', 'email', 'password'])) {
echo '<input class="form-control" type="' . $setting['type'] . '" name="settings[' . $key . ']" value="' . (isset($settingsDb[$key]) ? $settingsDb[$key] : (!empty($setting['default']) ? $setting['default'] : '')) . '" id="' . $key . '"/>';
}
else if($setting['type'] === 'textarea') {
echo '<textarea class="form-control" name="settings[' . $key . ']" id="' . $key . '">' . (isset($settingsDb[$key]) ? $settingsDb[$key] : (!empty($setting['default']) ? $setting['default'] : '')) . '</textarea>';
}
if ($setting['type'] === 'options') {
if ($setting['options'] === '$templates') {
$templates = [];
foreach (get_templates() as $value) {
$templates[$value] = $value;
}
$setting['options'] = $templates;
}
else if($setting['options'] === '$clients') {
$clients = [];
foreach((array)config('clients') as $client) {
$client_version = (string)($client / 100);
if(strpos($client_version, '.') === false)
$client_version .= '.0';
$clients[$client] = $client_version;
}
$setting['options'] = $clients;
}
echo '<select class="form-control" name="settings[' . $key . ']" id="' . $key . '">';
foreach ($setting['options'] as $value => $option) {
$compareTo = (isset($settingsDb[$key]) ? $settingsDb[$key] : (isset($setting['default']) ? $setting['default'] : ''));
if($value === 'true') {
$selected = $compareTo === true;
}
else if($value === 'false') {
$selected = $compareTo === false;
}
else {
$selected = $compareTo == $value;
}
echo '<option value="' . $value . '" ' . ($selected ? 'selected' : '') . '>' . $option . '</option>';
}
echo '</select>';
}
?>
</td>
<td>
<div class="well">
<?= $setting['desc'] ?>
</div>
</td>
</tr>
<?php
}
?>
</tbody>
</table>
<div class="box-footer">
<button name="save" type="submit" class="btn btn-primary">Save</button>
</div>
</div>
</div>
</div>
</form>

View File

@@ -1,39 +0,0 @@
<?php
/**
* Statistics
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Statistics';
$query = $db->query('SELECT count(*) as `how_much` FROM `accounts`;');
$query = $query->fetch();
$total_accounts = $query['how_much'];
$query = $db->query('SELECT count(*) as `how_much` FROM `players`;');
$query = $query->fetch();
$total_players = $query['how_much'];
$query = $db->query('SELECT count(*) as `how_much` FROM `guilds`;');
$query = $query->fetch();
$total_guilds = $query['how_much'];
$query = $db->query('SELECT count(*) as `how_much` FROM `houses`;');
$query = $query->fetch();
$total_houses = $query['how_much'];
$points = $db->query('SELECT `premium_points`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `premium_points` DESC LIMIT 10;');
$twig->display('admin.statistics.html.twig', array(
'total_accounts' => $total_accounts,
'total_players' => $total_players,
'total_guilds' => $total_guilds,
'total_houses' => $total_houses,
'account_type' => (USE_ACCOUNT_NAME ? 'name' : 'number'),
'points' => $points
));
?>

View File

@@ -1,27 +0,0 @@
<?php
/**
* Tools
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Tools';
$tool = $_GET['tool'];
if (!isset($tool)) {
echo 'Tool not set.';
return;
}
if (preg_match("/[^A-z0-9_\-]/", $tool)) {
echo 'Invalid tool.';
return;
}
$file = BASE . 'admin/pages/tools/' . $tool . '.php';
if (!@file_exists($file))
require $file;
?>

View File

@@ -1,50 +0,0 @@
<?php
/**
* Version check
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Version check';
// fetch version
//$file = @fopen('https://my-aac.org/VERSION', 'r') or die('Error while fetching version.');
//$myaac_version = fgets($file);
$myaac_version = @file_get_contents('https://my-aac.org/VERSION');
if (!$myaac_version) {
warning('Error while fetching version info from https://my-aac.org<br/>
Please try again later.');
return;
}
// compare them
$version_compare = version_compare($myaac_version, MYAAC_VERSION);
if ($version_compare == 0) {
success('MyAAC latest version is ' . $myaac_version . '. You\'re using the latest version.
<br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=clmd', 'here'));
} else if ($version_compare < 0) {
success('Woah, seems you\'re using newer version as latest released one! MyAAC latest released version is ' . $myaac_version . ', and you\'re using version ' . MYAAC_VERSION . '.
<br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=clmd', 'here'));
} else {
warning('You\'re using outdated version.<br/>
Your version: <b>' . MYAAC_VERSION . '</b><br/>
Latest version: <b>' . $myaac_version . '</b><br/>
Download available at: <a href="https://my-aac.org" target="_blank">www.my-aac.org</a>');
}
/*
function version_revert($version)
{
$major = floor($version / 10000);
$version -= $major * 10000;
$minor = floor($version / 100);
$version -= $minor * 100;
$release = $version;
return $major . '.' . $minor . '.' . $release;
}*/
?>

View File

@@ -1,36 +0,0 @@
<?php
/**
* Visitors viewer
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Visitors';
if (!$config['visitors_counter']): ?>
Visitors counter is disabled.<br/>
You can enable it by editing this configurable in <b>config.local.php</b> file:<br/>
<p style="margin-left: 3em;"><b>$config['visitors_counter'] = true;</b></p>
<?php
return;
endif;
require SYSTEM . 'libs/visitors.php';
$visitors = new Visitors($config['visitors_counter_ttl']);
function compare($a, $b)
{
return $a['lastvisit'] > $b['lastvisit'] ? -1 : 1;
}
$tmp = $visitors->getVisitors();
usort($tmp, 'compare');
$twig->display('admin.visitors.html.twig', array(
'config_visitors_counter_ttl' => $config['visitors_counter_ttl'],
'visitors' => $tmp
));
?>

View File

@@ -10,8 +10,7 @@
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Changelog';
$_page = isset($_GET['page']) ? $_GET['page'] : 0;
$id = isset($_GET['id']) ? $_GET['id'] : 0;
$_page = isset($_GET['page']) ? (int)$_GET['page'] : 0;
$limit = 30;
$offset = $_page * $limit;
$next_page = false;
@@ -43,4 +42,3 @@ $twig->display('changelog.html.twig', array(
'next_page' => $next_page,
'canEdit' => $canEdit,
));
?>

View File

@@ -47,7 +47,7 @@ if(isset($_REQUEST['name']))
if(empty($name))
{
$tmp_link = getPlayerLink($name);
echo 'Here you can get detailed information about a certain player on ' . $config['lua']['serverName'] . '.<BR>';
echo 'Here you can get detailed information about a certain player on ' . $config['lua']['serverName'] . '.<br/>';
echo generate_search_form(true);
return;
}
@@ -82,8 +82,9 @@ if($player->isLoaded() && !$player->isDeleted())
$outfit = $config['outfit_images_url'] . '?id=' . $player->getLookType() . ($db->hasColumn('players', 'lookaddons') ? '&addons=' . $player->getLookAddons() : '') . '&head=' . $player->getLookHead() . '&body=' . $player->getLookBody() . '&legs=' . $player->getLookLegs() . '&feet=' . $player->getLookFeet();
$flag = '';
if($config['account_country'])
if($config['account_country']) {
$flag = getFlagImage($account->getCountry());
}
$player_sex = 'Unknown';
if(isset($config['genders'][$player->getSex()]))
@@ -147,9 +148,10 @@ if($player->isLoaded() && !$player->isDeleted())
if($config['characters']['skills'])
{
if($db->hasColumn('players', 'skill_fist')) {// tfs 1.0+
$skills_db = $db->query('SELECT `skill_fist`, `skill_club`, `skill_sword`, `skill_axe`, `skill_dist`, `skill_shielding`, `skill_fishing` FROM `players` WHERE `id` = ' . $player->getId())->fetch();
$skills_db = $db->query('SELECT `maglevel`, `skill_fist`, `skill_club`, `skill_sword`, `skill_axe`, `skill_dist`, `skill_shielding`, `skill_fishing` FROM `players` WHERE `id` = ' . $player->getId())->fetch();
$skill_ids = array(
POT::SKILL_MAGIC => 'maglevel',
POT::SKILL_FIST => 'skill_fist',
POT::SKILL_CLUB => 'skill_club',
POT::SKILL_SWORD => 'skill_sword',
@@ -175,8 +177,7 @@ if($player->isLoaded() && !$player->isDeleted())
}
$quests_enabled = $config['characters']['quests'] && !empty($config['quests']);
if($quests_enabled)
{
if($quests_enabled) {
$quests = $config['quests'];
$sql_query_in = '';
$i = 0;
@@ -197,10 +198,10 @@ if($player->isLoaded() && !$player->isDeleted())
foreach($quests as &$storage) {
$storage = isset($player_storage[$storage]) && $player_storage[$storage] > 0;
}
unset($storage);
}
if($config['characters']['equipment'])
{
if($config['characters']['equipment']) {
global $db;
$eq_sql = $db->query('SELECT `pid`, `itemtype` FROM player_items WHERE player_id = '.$player->getId().' AND (`pid` >= 1 and `pid` <= 10)');
$equipment = array();
@@ -284,8 +285,7 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil
$deaths[] = array('time' => $death['date'], 'description' => $description . '.');
}
}
}
else {
} else {
$mostdamage = '';
if($db->hasColumn('player_deaths', 'mostdamage_by'))
$mostdamage = ', `mostdamage_by`, `mostdamage_is_player`, `unjustified`, `mostdamage_unjustified`';
@@ -294,8 +294,7 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil
FROM `player_deaths`
WHERE `player_id` = ' . $player->getId() . ' ORDER BY `time` DESC LIMIT 10;')->fetchAll();
if(count($deaths_db))
{
if(count($deaths_db)) {
$number_of_rows = 0;
foreach($deaths_db as $death)
{
@@ -326,14 +325,12 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil
$frags = array();
$frag_add_content = '';
if($config['characters']['frags'] && $db->hasTable('killers'))
{
if($config['characters']['frags'] && $db->hasTable('killers')) {
//frags list by Xampy
$i = 0;
$frags_limit = 10; // frags limit to show? // default: 10
$player_frags = $db->query('SELECT `player_deaths`.*, `players`.`name`, `killers`.`unjustified` FROM `player_deaths` LEFT JOIN `killers` ON `killers`.`death_id` = `player_deaths`.`id` LEFT JOIN `player_killers` ON `player_killers`.`kill_id` = `killers`.`id` LEFT JOIN `players` ON `players`.`id` = `player_deaths`.`player_id` WHERE `player_killers`.`player_id` = '.$player->getId().' ORDER BY `date` DESC LIMIT 0,'.$frags_limit.';')->fetchAll();
if(count($player_frags))
{
if(count($player_frags)) {
$row_count = 0;
foreach($player_frags as $frag)
{
@@ -346,7 +343,7 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil
// signature
$settings = Settings::getInstance();
if($config['signature_enabled']) {
$signature_url = BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : '?') . urlencode($player->getName()) . '.png';
$signature_url = BASE_URL . ($settings['core.friendly_urls']['value'] ? '' : 'index.php/') . urlencode($player->getName()) . '.png';
}
$hidden = $player->isHidden();
@@ -417,9 +414,7 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil
'search_form' => generate_search_form(),
'canEdit' => hasFlag(FLAG_CONTENT_PLAYERS) || superAdmin()
));
}
else
{
} else {
$search_errors[] = 'Character <b>' . $name . '</b> does not exist or has been deleted.';
$twig->display('error_box.html.twig', array('errors' => $search_errors));
$search_errors = array();
@@ -433,8 +428,7 @@ else
$deleted = 'deletion';
$query = $db->query('SELECT `name`, `level`, `vocation`' . $promotion . ' FROM `players` WHERE `name` LIKE ' . $db->quote('%' . $name . '%') . ' AND ' . $deleted . ' != 1 LIMIT ' . (int)config('characters_search_limit') . ';');
if($query->rowCount() > 0)
{
if($query->rowCount() > 0) {
echo 'Did you mean:<ul>';
foreach($query as $player) {
if(isset($player['promotion'])) {

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