Compare commits

..

49 Commits

Author SHA1 Message Date
slawkens
998e15cabd Dump command
Doesnt work yet, just as notice
2023-11-11 14:43:15 +01:00
slawkens
c81861d8c8 debugbar dont like persistent connection 2023-11-11 14:40:10 +01:00
slawkens
c3c1a6b2a6 Preserve config.local.php on settings save
Will be helpful when migration from 0.8
2023-11-11 14:33:20 +01:00
slawkens
d0590d2747 Execute highscores_ids_hidden migration again, cause of settings 2023-11-11 14:29:49 +01:00
slawkens
c79a1d5f3a Fix changelog + news.tickers buttons 2023-11-11 13:18:37 +01:00
slawkens
ada1e391d4 Add option to restrict Page view to logged user
$logged_access = 0 -> not logged in
$logged_access = 1 -> logged in
2023-11-11 12:52:26 +01:00
slawkens
193e18523d Uncheck PHP after enable TinyMCE
This needs to be rewritten anyway
2023-11-11 12:22:42 +01:00
slawkens
3fb9b1ae2f Enable TinyMCE by default 2023-11-11 12:15:03 +01:00
slawkens
561bdcd766 My bad 2023-11-11 12:07:10 +01:00
slawkens
556ef47d59 Towns & NPCs & Items should be persistent 2023-11-11 12:04:21 +01:00
slawkens
130ad25c4d Saving setting in db is not intended - you can use Settings Model for that 2023-11-11 11:34:02 +01:00
slawkens
08bea2c541 Update index.php 2023-11-11 11:31:12 +01:00
slawkens
8974830621 Move debugbar code to separate file 2023-11-11 11:30:08 +01:00
slawkens
d582120fac Squashed commit of the following:
commit 94a61f32ae
Merge: 57772569 8227303b
Author: slawkens <slawkens@gmail.com>
Date:   Sat Nov 11 11:11:13 2023 +0100

    Merge branch 'develop' into feature/debug-bar

commit 577725690d
Author: slawkens <slawkens@gmail.com>
Date:   Mon Aug 21 11:08:12 2023 +0200

    Add option to enable debugbar, even if dev mode is disabled

commit c227fd4e96
Merge: 9fef84bf a692607c
Author: slawkens <slawkens@gmail.com>
Date:   Mon Aug 21 10:20:04 2023 +0200

    Merge branch 'develop' into feature/debug-bar

commit 9fef84bffe
Author: slawkens <slawkens@gmail.com>
Date:   Fri Aug 11 06:39:50 2023 +0200

    Fix debugBar mysql logs (Thanks @gpedro)

commit dedd54286f
Author: slawkens <slawkens@gmail.com>
Date:   Thu Aug 10 13:21:36 2023 +0200

    Log PDO queries, as stated in docs, but doesn't work yet (don't know the reason)

commit 7403a24030
Author: slawkens <slawkens@gmail.com>
Date:   Thu Aug 10 13:21:20 2023 +0200

    Use dev-master, cause of some bugs appearing

commit cc7aec8e28
Author: slawkens <slawkens@gmail.com>
Date:   Thu Aug 10 13:05:02 2023 +0200

    Init debugBar
2023-11-11 11:26:38 +01:00
slawkens
8227303b89 1.0 will be our next release
we are starting to follow semantic versioning
2023-11-11 11:04:09 +01:00
slawkens
7a402ec0e0 fix #225 2023-11-11 11:00:28 +01:00
Slawomir Boczek
790d85a88a CSRF Protection (#235)
* Fix alert class name

* feature: csrf protection

* Cosmetics

* Fix token generate

* Admin Panel: changelogs csrf protection

* news/id route

* Refactor admin newses + add csrf

* Use admin.links instead

* Admin panel: Pages csrf

* Menus: better csrf + add success message on reset colors

* Plugins csrf

* Move definitions

* add info function, same as note($message)

* Update mailer.php

* Fix new page/news links

* clear_cache & maintenance csrf

* Formatting

* Fix news type

* Fix changelog link

* Add new changelog link

* More info to confirm dialog

* This is always true
2023-11-11 10:57:57 +01:00
slawkens
a04fbde607 Fix highscores error 2023-11-09 20:32:20 +01:00
slawkens
9d119b6279 This is more error tolerant 2023-11-07 22:15:23 +01:00
slawkens
7dd9b7764a Update common.php 2023-11-07 22:01:47 +01:00
slawkens
3297a7c51a Better https detection 2023-11-07 22:01:43 +01:00
slawkens
4a430ae9db Fix display ban info on account page
https://otland.net/threads/myacc-bans-display-problem.286825/
2023-11-02 22:06:14 +01:00
Kamil Grzechulski
26a80e0741 fix: password2 variable refactor to correct name (#237) 2023-10-06 07:52:21 +02:00
slawkens
3b9feaf3bd My fault 2023-09-26 22:03:30 +02:00
slawkens
21bff97137 Add additional cache keys to clear function 2023-09-26 21:52:05 +02:00
slawkens
a2a273cde2 Twig_SimpleFilter is deprecated 2023-09-22 16:21:52 +02:00
slawkens
fc5635bad3 spaceless twig tag is deprecated as well 2023-09-22 16:19:56 +02:00
slawkens
e01a44f352 Update .editorconfig 2023-09-16 14:40:19 +02:00
slawkens
855b05b15f Fix class names 2023-09-16 11:45:40 +02:00
slawkens
b3991a8e78 Add HOOK_TWIG. Also moved Hooks loading to init.php
For adding twig functions & filters by plugins
2023-09-16 11:07:38 +02:00
slawkens
0ac0f4e7a8 Fixes 2023-09-16 10:22:10 +02:00
slawkens
e9f155fb49 Fix XSS in players editor 2023-09-16 10:21:18 +02:00
slawkens
55b5e3b600 Fix XSS in accounts editor 2023-09-16 10:21:18 +02:00
slawkens
08339fe8b6 Fix XSS in tibiacom template - subtopic 2023-09-16 10:21:17 +02:00
slawkens
89c2e84bff Fix alert class name 2023-09-16 09:24:10 +02:00
slawkens
f76615e59b Fix getGuildLogoById 2023-09-16 05:54:41 +02:00
slawkens
4c4089a155 Quotes & const 2023-09-12 12:11:49 +02:00
slawkens
2d02d8d8b3 Fix news delete message part 2 2023-09-12 12:09:39 +02:00
slawkens
95b1460b13 Fix news delete message 2023-09-12 12:08:09 +02:00
slawkens
673e40350a Small adjustment to menus install 2023-09-12 11:42:03 +02:00
slawkens
f7cbe5170d set display quest default to false 2023-09-11 16:16:38 +02:00
slawkens
619b8ba4a0 Fix creatures datatable 2023-09-03 21:33:41 +02:00
slawkens
8c3b73ca9e Add account logs to admin panel accounts editor 2023-09-03 21:18:58 +02:00
slawkens
d90810cf84 Add latest clients versions 2023-08-31 14:20:24 +02:00
slawkens
fd25e6e881 Fix highscores country box to be hidden 2023-08-31 14:08:02 +02:00
slawkens
63e69c97b7 Fix login.php @gpedro <3 2023-08-31 14:01:30 +02:00
slawkens
574e35ba35 Fix: forgot to remove those menu items 2023-08-31 13:49:32 +02:00
slawkens
09627bdb1e Linux is case-sensitive! 2023-08-31 11:03:36 +02:00
Slawomir Boczek
5f10773189 feature: plugin cronjobs (#215) 2023-08-31 08:33:32 +02:00
132 changed files with 1141 additions and 688 deletions

View File

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

1
.gitignore vendored
View File

@@ -47,6 +47,7 @@ system/cache/*
!system/cache/twig/index.html
!system/cache/signatures/index.html
!system/cache/plugins/index.html
!system/cache/persistent/index.html
# logs
system/logs/*

View File

@@ -0,0 +1,22 @@
<?php
$hooks->register('debugbar_admin_head_end', HOOK_ADMIN_HEAD_END, function ($params) {
global $debugBar;
if (!isset($debugBar)) {
return;
}
$debugBarRenderer = $debugBar->getJavascriptRenderer();
echo $debugBarRenderer->renderHead();
});
$hooks->register('debugbar_admin_body_end', HOOK_ADMIN_BODY_END, function ($params) {
global $debugBar;
if (!isset($debugBar)) {
return;
}
$debugBarRenderer = $debugBar->getJavascriptRenderer();
echo $debugBarRenderer->render();
});

View File

@@ -30,11 +30,7 @@ if(!$db->hasTable('myaac_account_actions')) {
throw new RuntimeException('Seems that the table <strong>myaac_account_actions</strong> of MyAAC doesn\'t exist in the database. This is a fatal error. You can try to reinstall MyAAC by visiting <a href="' . BASE_URL . 'install">this</a> url.');
}
// event system
require_once SYSTEM . 'hooks.php';
$hooks = new Hooks();
$hooks->load();
require __DIR__ . '/includes/debugbar.php';
require SYSTEM . 'status.php';
require SYSTEM . 'login.php';
require __DIR__ . '/includes/functions.php';

View File

@@ -13,6 +13,9 @@ use MyAAC\Models\Player;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Account editor';
csrfProtect();
$admin_base = ADMIN_URL . '?p=accounts';
$use_datatable = true;
@@ -82,7 +85,7 @@ else if (isset($_REQUEST['search'])) {
$account = new OTS_Account();
$account->load($id);
if (isset($account, $_POST['save']) && $account->isLoaded()) {
if (isset($_POST['save']) && $account->isLoaded()) {
$error = false;
$_error = '';
@@ -266,6 +269,9 @@ else if (isset($_REQUEST['search'])) {
<li class="nav-item">
<a class="nav-link active" id="accounts-acc-tab" data-toggle="pill" href="#accounts-acc">Account</a>
</li>
<li class="nav-item">
<a class="nav-link" id="accounts-logs-tab" data-toggle="pill" href="#accounts-logs">Logs</a>
</li>
<li class="nav-item">
<a class="nav-link" id="accounts-chars-tab" data-toggle="pill" href="#accounts-chars">Characters</a>
</li>
@@ -286,6 +292,7 @@ else if (isset($_REQUEST['search'])) {
<div class="tab-content" id="accounts-tabContent">
<div class="tab-pane fade active show" id="accounts-acc">
<form action="<?php echo $admin_base . ((isset($id) && $id > 0) ? '&id=' . $id : ''); ?>" method="post">
<?php csrf(); ?>
<div class="form-group row">
<?php if (USE_ACCOUNT_NAME): ?>
<div class="col-12 col-sm-12 col-lg-4">
@@ -324,8 +331,8 @@ else if (isset($_REQUEST['search'])) {
<div class="col-12 col-sm-12 col-lg-6">
<label for="group">Account Type:</label>
<select name="group" id="group" class="form-control">
<?php foreach ($acc_type as $id => $a_type): ?>
<option value="<?php echo($id); ?>" <?php echo($acc_group == ($id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php foreach ($acc_type as $_id => $a_type): ?>
<option value="<?php echo($_id); ?>" <?php echo($acc_group == ($_id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php endforeach; ?>
</select>
</div>
@@ -335,8 +342,8 @@ else if (isset($_REQUEST['search'])) {
<div class="col-12 col-sm-12 col-lg-6">
<label for="group">Account Type:</label>
<select name="group" id="group" class="form-control">
<?php foreach ($groups->getGroups() as $id => $group): ?>
<option value="<?php echo $id; ?>" <?php echo($acc_group == $id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option>
<?php foreach ($groups->getGroups() as $_id => $group): ?>
<option value="<?php echo $_id; ?>" <?php echo($acc_group == $_id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option>
<?php endforeach; ?>
</select>
</div>
@@ -344,8 +351,8 @@ else if (isset($_REQUEST['search'])) {
<div class="col-12 col-sm-12 col-lg-6">
<label for="web_flags">Website Access:</label>
<select name="web_flags" id="web_flags" class="form-control">
<?php foreach ($web_acc as $id => $a_type): ?>
<option value="<?php echo($id); ?>" <?php echo($account->getWebFlags() == ($id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php foreach ($web_acc as $_id => $a_type): ?>
<option value="<?php echo($_id); ?>" <?php echo($account->getWebFlags() == ($_id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php endforeach; ?>
</select>
</div>
@@ -400,8 +407,8 @@ else if (isset($_REQUEST['search'])) {
<div class="col-12 col-sm-12 col-lg-4">
<label for="rl_country">Country:</label>
<select name="rl_country" id="rl_country" class="form-control">
<?php foreach ($countries as $id => $a_type): ?>
<option value="<?php echo($id); ?>" <?php echo($account->getCountry() == ($id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php foreach ($countries as $_id => $a_type): ?>
<option value="<?php echo($_id); ?>" <?php echo($account->getCountry() == ($_id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php endforeach; ?>
</select>
</div>
@@ -423,6 +430,34 @@ else if (isset($_REQUEST['search'])) {
<a href="<?php echo ADMIN_URL; ?>?p=accounts" class="btn btn-danger float-right"><i class="fas fa-cancel"></i> Cancel</a>
</form>
</div>
<div class="tab-pane fade" id="accounts-logs">
<div class="row">
<table class="table table-striped table-condensed table-responsive d-md-table">
<thead>
<tr>
<th>#</th>
<th>Date</th>
<th>Action</th>
<th>IP</th>
</tr>
</thead>
<tbody>
<?php
$accountActions = \MyAAC\Models\AccountAction::where('account_id', $account->getId())->orderByDesc('date')->get();
foreach ($accountActions as $i => $log):
$log->ip = ($log->ip != 0 ? long2ip($log->ip) : inet_ntop($log->ipv6));
?>
<tr>
<td><?php echo $i + 1; ?></td>
<td><?= date("M d Y, H:i:s", $log->date); ?></td>
<td><?= $log->action; ?></td>
<td><?= $log->ip; ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<div class="tab-pane fade" id="accounts-chars">
<div class="row">
<?php
@@ -550,18 +585,20 @@ else if (isset($_REQUEST['search'])) {
<div class="row">
<div class="col-6 col-lg-12">
<form action="<?php echo $admin_base; ?>" method="post">
<label for="name">Account Name:</label>
<?php csrf(); ?>
<label for="search">Account Name:</label>
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="search" value="<?php echo $search_account; ?>" maxlength="32" size="32">
<input type="text" class="form-control" id="search" name="search" value="<?= escapeHtml($search_account); ?>" maxlength="32" size="32">
<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span>
</div>
</form>
</div>
<div class="col-6 col-lg-12">
<form action="<?php echo $admin_base; ?>" method="post">
<label for="name">Account ID:</label>
<?php csrf(); ?>
<label for="id">Account ID:</label>
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="id" value="" maxlength="32" size="32">
<input type="text" class="form-control" id="id" name="id" value="<?= $id; ?>" maxlength="32" size="32">
<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span>
</div>
</form>

View File

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

View File

@@ -10,7 +10,9 @@
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Dashboard';
if (isset($_GET['clear_cache'])) {
csrfProtect();
if (isset($_POST['clear_cache'])) {
if (clearCache()) {
success('Cache cleared.');
} else {
@@ -18,7 +20,7 @@ if (isset($_GET['clear_cache'])) {
}
}
if (isset($_GET['maintenance'])) {
if (isset($_POST['maintenance'])) {
$message = (!empty($_POST['message']) ? $_POST['message'] : null);
$_status = (isset($_POST['status']) && $_POST['status'] == 'true');
$_status = ($_status ? '0' : '1');

View File

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

View File

@@ -10,6 +10,8 @@
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Mailer';
csrfProtect();
if (!hasFlag(FLAG_CONTENT_MAILER) && !superAdmin()) {
echo 'Access denied.';
return;
@@ -20,7 +22,7 @@ if (!setting('core.mail_enabled')) {
return;
}
$mail_to = isset($_REQUEST['mail_to']) ? stripslashes(trim($_REQUEST['mail_to'])) : null;
$mail_to = isset($_POST['mail_to']) ? stripslashes(trim($_POST['mail_to'])) : null;
$mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : null;
$mail_content = isset($_POST['mail_content']) ? stripslashes($_POST['mail_content']) : null;

View File

@@ -16,6 +16,8 @@ defined('MYAAC') or die('Direct access not allowed!');
$title = 'Mass Account Actions';
csrfProtect();
$hasCoinsColumn = $db->hasColumn('accounts', 'coins');
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
$freePremium = $config['lua']['freePremium'];

View File

@@ -16,6 +16,8 @@ defined('MYAAC') or die('Direct access not allowed!');
$title = 'Mass Teleport Actions';
csrfProtect();
function admin_teleport_position($x, $y, $z) {
if (!Player::query()->update([
'posx' => $x, 'posy' => $y, 'posz' => $z

View File

@@ -13,19 +13,21 @@ use MyAAC\Models\Menu;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Menus';
csrfProtect();
if (!hasFlag(FLAG_CONTENT_MENUS) && !superAdmin()) {
echo 'Access denied.';
return;
}
if (isset($_REQUEST['template'])) {
$template = $_REQUEST['template'];
if (isset($_POST['template'])) {
$template = $_POST['template'];
if (isset($_REQUEST['menu'])) {
$post_menu = $_REQUEST['menu'];
$post_menu_link = $_REQUEST['menu_link'];
$post_menu_blank = $_REQUEST['menu_blank'];
$post_menu_color = $_REQUEST['menu_color'];
if (isset($_POST['menu'])) {
$post_menu = $_POST['menu'];
$post_menu_link = $_POST['menu_link'];
$post_menu_blank = $_POST['menu_blank'];
$post_menu_color = $_POST['menu_color'];
if (count($post_menu) != count($post_menu_link)) {
echo 'Menu count is not equal menu links. Something went wrong when sending form.';
return;
@@ -69,9 +71,10 @@ if (isset($_REQUEST['template'])) {
return;
}
if (isset($_REQUEST['reset_colors'])) {
if (isset($_GET['reset_colors'])) {
if (isset($config['menu_default_color'])) {
Menu::where('template', $template)->update(['color' => str_replace('#', '', $config['menu_default_color'])]);
success('Colors has been reset.');
}
else {
warning('There is no default color defined, cannot reset colors.');
@@ -93,6 +96,7 @@ if (isset($_REQUEST['template'])) {
</p>
<?php if (isset($config['menu_default_color'])) {?>
<form method="post" action="?p=menus&reset_colors" onsubmit="return confirm('Do you really want to reset colors?');">
<?php csrf(); ?>
<input type="hidden" name="template" value="<?php echo $template ?>"/>
<button type="submit" class="btn btn-danger">Reset Colors to default</button>
</form>
@@ -112,6 +116,7 @@ if (isset($_REQUEST['template'])) {
$last_id = array();
?>
<form method="post" id="menus-form" action="?p=menus">
<?php csrf(); ?>
<input type="hidden" name="template" value="<?php echo $template ?>"/>
<button type="submit" class="btn btn-info">Save</button><br/><br/>
<div class="row">

View File

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

View File

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

View File

@@ -13,6 +13,8 @@ use MyAAC\Models\Notepad as ModelsNotepad;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Notepad';
csrfProtect();
/**
* @var $account_logged OTS_Account
*/

View File

@@ -9,11 +9,14 @@
*/
use MyAAC\Models\Pages as ModelsPages;
use MyAAC\Admin\Pages;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Pages';
$use_datatable = true;
csrfProtect();
if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) {
echo 'Access denied.';
return;
@@ -29,31 +32,36 @@ $enable_tinymce = true;
$access = 0;
// some constants, used mainly by database (cannot by modified without schema changes)
define('PAGE_TITLE_LIMIT', 30);
define('PAGE_NAME_LIMIT', 30);
define('PAGE_BODY_LIMIT', 65535); // maximum page body length
const PAGE_TITLE_LIMIT = 30;
const PAGE_NAME_LIMIT = 30;
const PAGE_BODY_LIMIT = 65535; // maximum page body length
if (!empty($action)) {
if ($action == 'delete' || $action == 'edit' || $action == 'hide')
$id = $_REQUEST['id'];
if (isset($_REQUEST['name']))
$name = $_REQUEST['name'];
if (isset($_REQUEST['title']))
$p_title = $_REQUEST['title'];
$php = isset($_REQUEST['php']) && $_REQUEST['php'] == 1;
$enable_tinymce = isset($_REQUEST['enable_tinymce']) && $_REQUEST['enable_tinymce'] == 1;
if ($php)
$body = $_REQUEST['body'];
else if (isset($_REQUEST['body'])) {
//$body = $_REQUEST['body'];
$body = html_entity_decode(stripslashes($_REQUEST['body']));
if ($action == 'delete' || $action == 'edit' || $action == 'hide') {
$id = $_POST['id'];
}
if (isset($_REQUEST['access']))
$access = $_REQUEST['access'];
if (isset($_POST['name'])) {
$name = $_POST['name'];
}
if (isset($_POST['title'])) {
$p_title = $_POST['title'];
}
$php = isset($_POST['php']) && $_POST['php'] == 1;
$enable_tinymce = (isset($_POST['enable_tinymce']) && $_POST['enable_tinymce'] == 1) ?: $enable_tinymce;
if ($php) {
$body = $_POST['body'];
}
else if (isset($_POST['body'])) {
//$body = $_POST['body'];
$body = html_entity_decode(stripslashes($_POST['body']));
}
if (isset($_POST['access'])) {
$access = $_POST['access'];
}
$errors = array();
$player_id = 1;
@@ -70,7 +78,7 @@ if (!empty($action)) {
if (Pages::delete($id, $errors))
success('Page with id ' . $id . ' has been deleted');
} else if ($action == 'edit') {
if (isset($id) && !isset($_REQUEST['name'])) {
if (isset($id) && !isset($_POST['name'])) {
$_page = Pages::get($id);
$name = $_page['name'];
$p_title = $_page['title'];
@@ -89,8 +97,9 @@ if (!empty($action)) {
}
}
} else if ($action == 'hide') {
Pages::toggleHidden($id, $errors, $status);
success(($status == 1 ? 'Show' : 'Hide') . ' successful.');
if (Pages::toggleHidden($id, $errors, $status)) {
success(($status == 0 ? 'Show' : 'Hide') . ' successful.');
}
}
if (!empty($errors))
@@ -107,7 +116,7 @@ $pages = ModelsPages::all()->map(function ($e) {
];
})->toArray();
$twig->display('admin.pages.form.html.twig', array(
$twig->display('admin.pages.form.html.twig', [
'action' => $action,
'id' => $action == 'edit' ? $id : null,
'name' => $name,
@@ -117,136 +126,8 @@ $twig->display('admin.pages.form.html.twig', array(
'body' => isset($body) ? escapeHtml($body) : '',
'groups' => $groups->getGroups(),
'access' => $access
));
]);
$twig->display('admin.pages.html.twig', array(
$twig->display('admin.pages.html.twig', [
'pages' => $pages
));
class Pages
{
static public function verify($name, $title, $body, $player_id, $php, $enable_tinymce, $access, &$errors)
{
if(!isset($title[0]) || !isset($body[0])) {
$errors[] = 'Please fill all inputs.';
return false;
}
if(strlen($name) > PAGE_NAME_LIMIT) {
$errors[] = 'Page name cannot be longer than ' . PAGE_NAME_LIMIT . ' characters.';
return false;
}
if(strlen($title) > PAGE_TITLE_LIMIT) {
$errors[] = 'Page title cannot be longer than ' . PAGE_TITLE_LIMIT . ' characters.';
return false;
}
if(strlen($body) > PAGE_BODY_LIMIT) {
$errors[] = 'Page content cannot be longer than ' . PAGE_BODY_LIMIT . ' characters.';
return false;
}
if(!isset($player_id) || $player_id == 0) {
$errors[] = 'Player ID is wrong.';
return false;
}
if(!isset($php) || ($php != 0 && $php != 1)) {
$errors[] = 'Enable PHP is wrong.';
return false;
}
if ($php == 1 && !getBoolean(setting('core.admin_pages_php_enable'))) {
$errors[] = 'PHP pages disabled on this server. To enable go to Settings in Admin Panel and enable <strong>Enable PHP Pages</strong>.';
return false;
}
if(!isset($enable_tinymce) || ($enable_tinymce != 0 && $enable_tinymce != 1)) {
$errors[] = 'Enable TinyMCE is wrong.';
return false;
}
if(!isset($access) || $access < 0 || $access > PHP_INT_MAX) {
$errors[] = 'Access is wrong.';
return false;
}
return true;
}
static public function get($id)
{
$row = ModelsPages::find($id);
if ($row) {
return $row->toArray();
}
return false;
}
static public function add($name, $title, $body, $player_id, $php, $enable_tinymce, $access, &$errors)
{
if(!self::verify($name, $title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) {
return false;
}
if (!ModelsPages::where('name', $name)->exists())
ModelsPages::create([
'name' => $name,
'title' => $title,
'body' => $body,
'player_id' => $player_id,
'php' => $php ? '1' : '0',
'enable_tinymce' => $enable_tinymce ? '1' : '0',
'access' => $access
]);
else
$errors[] = 'Page with this link already exists.';
return !count($errors);
}
static public function update($id, $name, $title, $body, $player_id, $php, $enable_tinymce, $access, &$errors)
{
if(!self::verify($name, $title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) {
return false;
}
ModelsPages::where('id', $id)->update([
'name' => $name,
'title' => $title,
'body' => $body,
'player_id' => $player_id,
'php' => $php ? '1' : '0',
'enable_tinymce' => $enable_tinymce ? '1' : '0',
'access' => $access
]);
return true;
}
static public function delete($id, &$errors)
{
if (isset($id)) {
$row = ModelsPages::find($id);
if ($row) {
$row->delete();
}
else
$errors[] = 'Page with id ' . $id . ' does not exists.';
} else
$errors[] = 'id not set';
return !count($errors);
}
static public function toggleHidden($id, &$errors, &$status)
{
if (isset($id)) {
$row = ModelsPages::find($id);
if ($row) {
$row->hidden = $row->hidden == 1 ? 0 : 1;
$row->save();
$status = $row->hidden;
}
else {
$errors[] = 'Page with id ' . $id . ' does not exists.';
}
} else
$errors[] = 'id not set';
return !count($errors);
}
}
]);

View File

@@ -13,6 +13,9 @@ use MyAAC\Models\Player;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Player editor';
csrfProtect();
$player_base = ADMIN_URL . '?p=players';
$use_datatable = true;
@@ -75,7 +78,7 @@ else if (isset($_REQUEST['search'])) {
$player = new OTS_Player();
$player->load($id);
if (isset($player) && $player->isLoaded() && isset($_POST['save'])) {// we want to save
if ($player->isLoaded() && isset($_POST['save'])) {// we want to save
$error = false;
if ($player->isOnline())
@@ -373,6 +376,7 @@ else if (isset($_REQUEST['search'])) {
</ul>
</div>
<form action="<?php echo $player_base . ((isset($id) && $id > 0) ? '&id=' . $id : ''); ?>" method="post">
<?php csrf(); ?>
<div class="card-body">
<div class="tab-content" id="tabs-tabContent">
<div class="tab-pane fade active show" id="tabs-home">
@@ -390,8 +394,8 @@ else if (isset($_REQUEST['search'])) {
<div class="col-12 col-sm-12 col-lg-6">
<label for="group">Group:</label>
<select name="group" id="group" class="form-control custom-select">
<?php foreach ($groups->getGroups() as $id => $group): ?>
<option value="<?php echo $id; ?>" <?php echo($player->getGroup()->getId() == $id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option>
<?php foreach ($groups->getGroups() as $_id => $group): ?>
<option value="<?php echo $_id; ?>" <?php echo($player->getGroup()->getId() == $_id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option>
<?php endforeach; ?>
</select>
</div>
@@ -399,8 +403,8 @@ else if (isset($_REQUEST['search'])) {
<label for="vocation">Vocation</label>
<select name="vocation" id="vocation" class="form-control custom-select">
<?php
foreach ($config['vocations'] as $id => $name) {
echo '<option value=' . $id . ($id == $player->getVocation() ? ' selected' : '') . '>' . $name . '</option>';
foreach ($config['vocations'] as $_id => $name) {
echo '<option value=' . $_id . ($_id == $player->getVocation() ? ' selected' : '') . '>' . $name . '</option>';
}
?>
</select>
@@ -410,8 +414,8 @@ else if (isset($_REQUEST['search'])) {
<div class="col-12 col-sm-12 col-lg-6">
<label for="sex">Sex:</label>
<select name="sex" id="sex" class="form-control custom-select">>
<?php foreach ($config['genders'] as $id => $sex): ?>
<option value="<?php echo $id; ?>" <?php echo($player->getSex() == $id ? 'selected' : ''); ?>><?php echo strtolower($sex); ?></option>
<?php foreach ($config['genders'] as $_id => $sex): ?>
<option value="<?php echo $_id; ?>" <?php echo($player->getSex() == $_id ? 'selected' : ''); ?>><?php echo strtolower($sex); ?></option>
<?php endforeach; ?>
</select>
</div>
@@ -424,8 +428,8 @@ else if (isset($_REQUEST['search'])) {
$configTowns[$player->getTownId()] = 'Unknown Town';
}
foreach ($configTowns as $id => $town): ?>
<option value="<?php echo $id; ?>" <?php echo($player->getTownId() == $id ? 'selected' : ''); ?>><?php echo $town; ?></option>
foreach ($configTowns as $_id => $town): ?>
<option value="<?php echo $_id; ?>" <?php echo($player->getTownId() == $_id ? 'selected' : ''); ?>><?php echo $town; ?></option>
<?php endforeach; ?>
</select>
</div>
@@ -436,8 +440,8 @@ else if (isset($_REQUEST['search'])) {
<select name="skull" id="skull" class="form-control custom-select">
<?php
foreach ($skull_type as $id => $s_name) {
echo '<option value=' . $id . ($id == $player->getSkull() ? ' selected' : '') . '>' . $s_name . '</option>';
foreach ($skull_type as $_id => $s_name) {
echo '<option value=' . $_id . ($_id == $player->getSkull() ? ' selected' : '') . '>' . $s_name . '</option>';
}
?>
</select>
@@ -554,16 +558,16 @@ else if (isset($_REQUEST['search'])) {
</div>
<div class="tab-pane fade" id="tabs-skills">
<?php
foreach ($skills as $id => $info) {
foreach ($skills as $_id => $info) {
?>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
<?php echo '<label for="skills[' . $id . ']" class="control-label">' . $info[0] . '</label>
<input type="text" class="form-control" id="skills[' . $id . ']" name="skills[' . $id . ']" maxlength="10" autocomplete="off" value="' . $player->getSkill($id) . '"/>'; ?>
<?php echo '<label for="skills[' . $_id . ']" class="control-label">' . $info[0] . '</label>
<input type="text" class="form-control" id="skills[' . $_id . ']" name="skills[' . $_id . ']" maxlength="10" autocomplete="off" value="' . $player->getSkill($_id) . '"/>'; ?>
</div>
<div class="col-12 col-sm-12 col-lg-6">
<?php echo '<label for="skills_tries[' . $id . ']" class="control-label">' . $info[0] . ' tries</label>
<input type="text" class="form-control" id="skills_tries[' . $id . ']" name="skills_tries[' . $id . ']" maxlength="10" autocomplete="off" value="' . $player->getSkillTries($id) . '"/>'; ?>
<?php echo '<label for="skills_tries[' . $_id . ']" class="control-label">' . $info[0] . ' tries</label>
<input type="text" class="form-control" id="skills_tries[' . $_id . ']" name="skills_tries[' . $_id . ']" maxlength="10" autocomplete="off" value="' . $player->getSkillTries($_id) . '"/>'; ?>
</div>
</div>
<?php } ?>
@@ -622,7 +626,7 @@ else if (isset($_REQUEST['search'])) {
if ($outfitlist) { ?>
<select name="look_type" id="look_type" class="form-control custom-select">
<?php
foreach ($outfitlist as $id => $outfit) {
foreach ($outfitlist as $_id => $outfit) {
if ($outfit['enabled'] == 'yes') ;
echo '<option value=' . $outfit['id'] . ($outfit['id'] == $player->getLookType() ? ' selected' : '') . '>' . $outfit['name'] . ' - ' . ($outfit['type'] == 1 ? 'Male' : 'Female') . '</option>';
}
@@ -638,8 +642,8 @@ else if (isset($_REQUEST['search'])) {
<select name="look_addons" id="look_addons" class="form-control custom-select">
<?php
$addon_type = array("None", "First", "Second", "Both");
foreach ($addon_type as $id => $s_name) {
echo '<option value=' . $id . ($id == $player->getLookAddons() ? ' selected' : '') . '>' . $s_name . '</option>';
foreach ($addon_type as $_id => $s_name) {
echo '<option value=' . $_id . ($_id == $player->getLookAddons() ? ' selected' : '') . '>' . $s_name . '</option>';
}
?>
</select>
@@ -704,7 +708,7 @@ else if (isset($_REQUEST['search'])) {
<div class="form-group row">
<div class="col-12">
<label for="comment" class="control-label">Comment:</label>
<textarea class="form-control" name="comment" rows="10" cols="50" wrap="virtual"><?php echo $player->getCustomField("comment"); ?></textarea>
<textarea class="form-control" id="comment" name="comment" rows="10" cols="50" wrap="virtual"><?php echo $player->getCustomField("comment"); ?></textarea>
<small>[max. length: 2000 chars, 50 lines (ENTERs)]</small>
</div>
</div>
@@ -841,7 +845,7 @@ else if (isset($_REQUEST['search'])) {
<?php if($hasLookAddons): ?>
const $addonvalue = $('#look_addons');
$('#look_addons').on('change', () => {
$addonvalue.on('change', () => {
updateOutfit();
});
<?php endif; ?>
@@ -870,18 +874,20 @@ else if (isset($_REQUEST['search'])) {
<div class="card-body row">
<div class="col-6 col-lg-12">
<form action="<?php echo $player_base; ?>" method="post">
<label for="name">Player Name:</label>
<?php csrf(); ?>
<label for="search">Player Name:</label>
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="search" value="<?php echo $search_player; ?>" maxlength="32" size="32">
<input type="text" class="form-control" id="search" name="search" value="<?= escapeHtml($search_player); ?>" maxlength="32" size="32">
<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span>
</div>
</form>
</div>
<div class="col-6 col-lg-12">
<form action="<?php echo $player_base; ?>" method="post">
<label for="name">Player ID:</label>
<?php csrf(); ?>
<label for="id">Player ID:</label>
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="id" value="" maxlength="32" size="32">
<input type="text" class="form-control" id="id" name="id" value="<?= $id; ?>" maxlength="32" size="32">
<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span>
</div>
</form>
@@ -892,7 +898,7 @@ else if (isset($_REQUEST['search'])) {
</div>
<script>
$(document).ready(function () {
$(function () {
$('.player_datatable').DataTable({
"order": [[0, "asc"]]
});

View File

@@ -9,6 +9,9 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Plugin manager';
csrfProtect();
$use_datatable = true;
require_once LIBS . 'plugins.php';
@@ -19,23 +22,23 @@ if (!getBoolean(setting('core.admin_plugins_manage_enable'))) {
else {
$twig->display('admin.plugins.form.html.twig');
if (isset($_REQUEST['uninstall'])) {
$uninstall = $_REQUEST['uninstall'];
if (isset($_POST['uninstall'])) {
$uninstall = $_POST['uninstall'];
if (Plugins::uninstall($uninstall)) {
success('Successfully uninstalled plugin ' . $uninstall);
} else {
error('Error while uninstalling plugin ' . $uninstall . ': ' . Plugins::getError());
}
} else if (isset($_REQUEST['enable'])) {
$enable = $_REQUEST['enable'];
} else if (isset($_POST['enable'])) {
$enable = $_POST['enable'];
if (Plugins::enable($enable)) {
success('Successfully enabled plugin ' . $enable);
} else {
error('Error while enabling plugin ' . $enable . ': ' . Plugins::getError());
}
} else if (isset($_REQUEST['disable'])) {
$disable = $_REQUEST['disable'];
} else if (isset($_POST['disable'])) {
$disable = $_POST['disable'];
if (Plugins::disable($disable)) {
success('Successfully disabled plugin ' . $disable);
} else {
@@ -116,7 +119,7 @@ foreach (get_plugins(true) as $plugin) {
if (!$plugin_info) {
warning('Cannot load plugin info ' . $plugin . '.json');
} else {
$disabled = (strpos($plugin, 'disabled.') !== false);
$disabled = (str_contains($plugin, 'disabled.'));
$pluginOriginal = ($disabled ? str_replace('disabled.', '', $plugin) : $plugin);
$plugins[] = array(
'name' => $plugin_info['name'] ?? '',

View File

@@ -16,6 +16,8 @@ if(!admin()) {
die('Access denied.');
}
csrfProtect();
if (!isset($_REQUEST['plugin'])) {
http_response_code(500);
die('Please enter plugin name.');

View File

@@ -26,8 +26,8 @@
if (version_compare(phpversion(), '8.0', '<')) die('PHP version 8.0 or higher is required.');
const MYAAC = true;
const MYAAC_VERSION = '0.10.0-dev';
const DATABASE_VERSION = 36;
const MYAAC_VERSION = '1.0-dev';
const DATABASE_VERSION = 38;
const TABLE_PREFIX = 'myaac_';
define('START_TIME', microtime(true));
define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));
@@ -108,6 +108,13 @@ const TFS_FIRST = TFS_02;
const TFS_LAST = TFS_03;
// other definitions
const MAIL_MAIL = 0;
const MAIL_SMTP = 1;
const SMTP_SECURITY_NONE = 0;
const SMTP_SECURITY_SSL = 1;
const SMTP_SECURITY_TLS = 2;
const ACCOUNT_NUMBER_LENGTH = 8;
if (!IS_CLI) {
@@ -136,7 +143,7 @@ if(!IS_CLI) {
}
}
define('SERVER_URL', 'http' . (isset($_SERVER['HTTPS'][0]) && strtolower($_SERVER['HTTPS']) === 'on' ? 's' : '') . '://' . $baseHost);
define('SERVER_URL', 'http' . (isHttps() ? 's' : '') . '://' . $baseHost);
define('BASE_URL', SERVER_URL . BASE_DIR . '/');
define('ADMIN_URL', SERVER_URL . BASE_DIR . '/' . ADMIN_PANEL_FOLDER . '/');
@@ -147,6 +154,7 @@ if (file_exists(BASE . 'config.local.php')) {
require BASE . 'config.local.php';
}
/** @var array $config */
ini_set('log_errors', 1);
if(@$config['env'] === 'dev') {
ini_set('display_errors', 1);
@@ -165,3 +173,11 @@ if (!is_file($autoloadFile)) {
}
require $autoloadFile;
function isHttps(): bool
{
return
(!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https')
|| (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
|| (isset($_SERVER['SERVER_PORT']) && (int) $_SERVER['SERVER_PORT'] === 443);
}

View File

@@ -13,10 +13,13 @@
"nikic/fast-route": "^1.3",
"matomo/device-detector": "^6.0",
"illuminate/database": "^10.18",
"peppeocchi/php-cron-scheduler": "4.*"
"illuminate/filesystem": "^10.18",
"peppeocchi/php-cron-scheduler": "4.*",
"symfony/process": "^6.3"
},
"require-dev": {
"filp/whoops": "^2.15"
"filp/whoops": "^2.15",
"maximebf/debugbar": "dev-master"
},
"autoload": {
"psr-4": {

View File

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

View File

@@ -71,10 +71,6 @@ if(!$db->hasTable('myaac_account_actions')) {
throw new RuntimeException('Seems that the table <strong>myaac_account_actions</strong> of MyAAC doesn\'t exist in the database. This is a fatal error. You can try to reinstall MyAAC by visiting <a href="' . BASE_URL . 'install">this</a> url.');
}
// event system
require_once SYSTEM . 'hooks.php';
$hooks = new Hooks();
$hooks->load();
require_once SYSTEM . 'template.php';
require_once SYSTEM . 'login.php';
require_once SYSTEM . 'status.php';

View File

@@ -127,11 +127,6 @@ CREATE TABLE `myaac_menu`
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
/* MENU_CATEGORY_SHOP tibiacom */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Buy Points', 'points', 6, 0);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Shop Offer', 'gifts', 6, 1);
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('tibiacom', 'Shop History', 'gifts/history', 6, 2);
CREATE TABLE `myaac_monsters` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`hidden` tinyint(1) NOT NULL default 0,

View File

@@ -12,7 +12,7 @@ require SYSTEM . 'functions.php';
require BASE . 'install/includes/functions.php';
require BASE . 'install/includes/locale.php';
require SYSTEM . 'clients.conf.php';
require LIBS . 'settings.php';
require LIBS . 'Settings.php';
// ignore undefined index from Twig autoloader
$config['env'] = 'prod';

View File

@@ -2,6 +2,8 @@
use MyAAC\Models\BoostedCreature;
use MyAAC\Models\PlayerOnline;
use MyAAC\Models\Account;
use MyAAC\Models\Player;
require_once 'common.php';
require_once SYSTEM . 'functions.php';

View File

@@ -0,0 +1,15 @@
<?php
if(PHP_SAPI !== 'cli') {
echo 'This script can be run only in command line mode.';
exit(1);
}
require_once __DIR__ . '/../../common.php';
require_once SYSTEM . 'functions.php';
require_once SYSTEM . 'init.php';
$test = new \Illuminate\Database\Schema\MySqlSchemaState($eloquentConnection);
$test->dump($eloquentConnection, BASE . 'dump.sql');
echo 'Dumped.';

0
system/cache/persistent/index.html vendored Normal file
View File

View File

@@ -99,4 +99,10 @@ $config['clients'] = [
1291,
1300,
1310,
1311,
1312,
1316,
1320,
1321,
];

View File

@@ -111,6 +111,8 @@ try {
$capsule->addConnection([
'driver' => 'mysql',
'database' => $config['database_name'],
'username' => $config['database_user'],
'password' => $config['database_password'],
]);
$capsule->getConnection()->setPdo($db);

View File

@@ -9,6 +9,7 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
use MyAAC\CsrfToken;
use MyAAC\Models\Config;
use MyAAC\Models\Guild;
use MyAAC\Models\House;
@@ -43,7 +44,10 @@ function warning($message, $return = false) {
return message($message, 'warning', $return);
}
function note($message, $return = false) {
return message($message, 'note', $return);
return info($message, $return);
}
function info($message, $return = false) {
return message($message, 'info', $return);
}
function error($message, $return = false) {
return message($message, ((defined('MYAAC_INSTALL') || defined('MYAAC_ADMIN')) ? 'danger' : 'error'), $return);
@@ -465,20 +469,30 @@ function tickers()
*/
function template_place_holder($type): string
{
global $twig, $template_place_holders;
global $twig, $template_place_holders, $debugBar;
$ret = '';
if (isset($debugBar)) {
$debugBarRenderer = $debugBar->getJavascriptRenderer();
}
if(array_key_exists($type, $template_place_holders) && is_array($template_place_holders[$type]))
$ret = implode($template_place_holders[$type]);
if($type === 'head_start') {
$ret .= template_header();
if (isset($debugBar)) {
$ret .= $debugBarRenderer->renderHead();
}
}
elseif ($type === 'body_start') {
$ret .= $twig->render('browsehappy.html.twig');
}
elseif($type === 'body_end') {
$ret .= template_ga_code();
if (isset($debugBar)) {
$ret .= $debugBarRenderer->render();
}
}
return $ret;
@@ -855,9 +869,6 @@ function _mail($to, $subject, $body, $altBody = '', $add_html_tags = true)
else
$tmp_body = $body . '<br/><br/>' . $signature_html;
define('MAIL_MAIL', 0);
define('MAIL_SMTP', 1);
$mailOption = setting('core.mail_option');
if($mailOption == MAIL_SMTP)
{
@@ -868,10 +879,6 @@ function _mail($to, $subject, $body, $altBody = '', $add_html_tags = true)
$mailer->Username = setting('core.smtp_user');
$mailer->Password = setting('core.smtp_pass');
define('SMTP_SECURITY_NONE', 0);
define('SMTP_SECURITY_SSL', 1);
define('SMTP_SECURITY_TLS', 2);
$security = setting('core.smtp_security');
$tmp = '';
@@ -1045,6 +1052,28 @@ function unsetSession($key) {
unset($_SESSION[setting('core.session_prefix') . $key]);
}
function csrf(): void {
CsrfToken::create();
}
function csrfToken(): string {
return CsrfToken::get();
}
function isValidToken(): bool {
$token = $_POST['csrf_token'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? null;
return ($_SERVER['REQUEST_METHOD'] !== 'POST' || (isset($token) && CsrfToken::isValid($token)));
}
function csrfProtect(): void
{
if (!isValidToken()) {
$lastUri = BASE_URL . str_replace_first('/', '', getSession('last_uri'));
echo 'Request has been cancelled due to security reasons - token is invalid. Go <a href="' . $lastUri . '">back</a>';
exit();
}
}
function getTopPlayers($limit = 5) {
global $db;
@@ -1197,21 +1226,43 @@ function clearCache()
if ($cache->fetch('failed_logins', $tmp))
$cache->delete('failed_logins');
global $template_name;
if ($cache->fetch('template_ini' . $template_name, $tmp))
$cache->delete('template_ini' . $template_name);
foreach (get_templates() as $template) {
if ($cache->fetch('template_ini_' . $template, $tmp)) {
$cache->delete('template_ini_' . $template);
}
}
if ($cache->fetch('plugins_hooks', $tmp))
if ($cache->fetch('template_menus', $tmp)) {
$cache->delete('template_menus');
}
if ($cache->fetch('database_tables', $tmp)) {
$cache->delete('database_tables');
}
if ($cache->fetch('database_columns', $tmp)) {
$cache->delete('database_columns');
}
if ($cache->fetch('database_checksum', $tmp)) {
$cache->delete('database_checksum');
}
if ($cache->fetch('last_kills', $tmp)) {
$cache->delete('last_kills');
}
if ($cache->fetch('hooks', $tmp)) {
$cache->delete('hooks');
}
if ($cache->fetch('plugins_hooks', $tmp)) {
$cache->delete('plugins_hooks');
if ($cache->fetch('plugins_routes', $tmp))
}
if ($cache->fetch('plugins_routes', $tmp)) {
$cache->delete('plugins_routes');
}
}
deleteDirectory(CACHE . 'signatures', ['index.html'], true);
deleteDirectory(CACHE . 'twig', ['index.html'], true);
deleteDirectory(CACHE . 'plugins', ['index.html'], true);
deleteDirectory(CACHE, ['signatures', 'twig', 'plugins', 'index.html'], true);
deleteDirectory(CACHE, ['signatures', 'twig', 'plugins', 'index.html', 'persistent'], true);
// routes cache
$routeCacheFile = CACHE . 'route.cache';
@@ -1451,7 +1502,7 @@ function echo_success($message)
function echo_error($message)
{
global $error;
echo '<div class="col-12 alert alert-error mb-2">' . $message . '</div>';
echo '<div class="col-12 alert alert-danger mb-2">' . $message . '</div>';
$error = true;
}
@@ -1606,7 +1657,7 @@ function getGuildLogoById($id)
$guild = Guild::where('id', intval($id))->select('logo_name')->first();
if ($guild) {
$guildLogo = $query->logo_name;
$guildLogo = $guild->logo_name;
if (!empty($guildLogo) && file_exists(GUILD_IMAGES_DIR . $guildLogo)) {
$logo = $guildLogo;

View File

@@ -76,6 +76,7 @@ define('HOOK_GUILDS_AFTER_GUILD_HEADER', ++$i);
define('HOOK_GUILDS_AFTER_GUILD_INFORMATION', ++$i);
define('HOOK_GUILDS_AFTER_GUILD_MEMBERS', ++$i);
define('HOOK_GUILDS_AFTER_INVITED_CHARACTERS', ++$i);
define('HOOK_TWIG', ++$i);
const HOOK_FIRST = HOOK_STARTUP;
define('HOOK_LAST', $i);

View File

@@ -7,16 +7,25 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\CsrfToken;
defined('MYAAC') or die('Direct access not allowed!');
if(!isset($config['installed']) || !$config['installed']) {
throw new RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.');
}
use DebugBar\StandardDebugBar;
if(config('env') === 'dev') {
require SYSTEM . 'exception.php';
}
if (config('env') === 'dev' || getBoolean(config('enable_debugbar'))) {
$debugBar = new StandardDebugBar();
}
if(empty($config['server_path'])) {
throw new RuntimeException('Server Path has been not set. Go to config.php and set it.');
}
@@ -33,6 +42,11 @@ if(isset($config['gzip_output']) && $config['gzip_output'] && isset($_SERVER['HT
require_once SYSTEM . 'libs/cache.php';
$cache = Cache::getInstance();
// event system
require_once SYSTEM . 'hooks.php';
$hooks = new Hooks();
$hooks->load();
// twig
require_once SYSTEM . 'twig.php';
@@ -132,6 +146,12 @@ require_once LIBS . 'Settings.php';
$settings = Settings::getInstance();
$settings->load();
// csrf protection
$token = getSession('csrf_token');
if (!isset($token) || !$token) {
CsrfToken::generate();
}
// deprecated config values
require_once SYSTEM . 'compat/config.php';

View File

@@ -38,7 +38,7 @@ class DataLoader
{
self::$startTime = microtime(true);
require LIBS . 'items.php';
require_once LIBS . 'items.php';
if(Items::loadFromXML()) {
success(self::$locale['step_database_loaded_items'] . self::getLoadedTime());
}

View File

@@ -129,6 +129,9 @@ class Settings implements ArrayAccess
if (is_bool($value)) {
$settingsDb[$key] = $value ? 'true' : 'false';
}
elseif (is_array($value)) {
$settingsDb[$key] = $value;
}
else {
$settingsDb[$key] = (string)$value;
}
@@ -373,7 +376,6 @@ class Settings implements ArrayAccess
}
$this->settingsDatabase[$pluginKeyName][$key] = $value;
$this->updateInDatabase($pluginKeyName, $key, $value);
}
#[\ReturnTypeWillChange]
@@ -414,7 +416,6 @@ class Settings implements ArrayAccess
unset($this->settingsFile[$pluginKeyName]['settings'][$key]);
unset($this->settingsDatabase[$pluginKeyName][$key]);
$this->deleteFromDatabase($pluginKeyName, $key);
}
/**
@@ -532,8 +533,11 @@ class Settings implements ArrayAccess
public static function saveConfig($config, $filename, &$content = '')
{
$content = "<?php" . PHP_EOL .
"\$config['installed'] = true;" . PHP_EOL;
$content = "<?php" . PHP_EOL;
unset($config['installed']);
$content .= "\$config['installed'] = true;" . PHP_EOL;
foreach ($config as $key => $value) {
$content .= "\$config['$key'] = ";

View File

@@ -33,7 +33,7 @@ class Towns
/**
* @var string
*/
private static $filename = CACHE . 'towns.php';
private static $filename = CACHE . 'persistent/' . 'towns.php';
/**
* Determine towns

View File

@@ -95,6 +95,7 @@ class Changelog
if (!$row->save()) {
$errors[] = 'Fail during toggle hidden Changelog.';
}
$status = $row->hidden;
} else {
$errors[] = 'Changelog with id ' . $id . ' does not exists.';
}

View File

@@ -40,7 +40,7 @@ class Items
}
require_once LIBS . 'cache_php.php';
$cache_php = new Cache_PHP(config('cache_prefix'), CACHE);
$cache_php = new Cache_PHP(config('cache_prefix'), CACHE . 'persistent/');
$cache_php->set('items', $items, 5 * 365 * 24 * 60 * 60);
return true;
}
@@ -68,7 +68,7 @@ class Items
}
require_once LIBS . 'cache_php.php';
$cache_php = new Cache_PHP(config('cache_prefix'), CACHE);
$cache_php = new Cache_PHP(config('cache_prefix'), CACHE . 'persistent/');
self::$items = $cache_php->get('items');
}

View File

@@ -75,18 +75,20 @@ class News
static public function delete($id, &$errors)
{
if(isset($id))
{
if(isset($id)) {
$row = ModelsNews::find($id);
if($row)
if($row) {
if (!$row->delete()) {
$errors[] = 'Fail during delete News.';
}
else
}
else {
$errors[] = 'News with id ' . $id . ' does not exists.';
}
}
else
else {
$errors[] = 'News id not set.';
}
if(count($errors)) {
return false;

View File

@@ -41,7 +41,7 @@ class NPCs
}
require_once LIBS . 'cache_php.php';
$cache_php = new Cache_PHP(config('cache_prefix'), CACHE);
$cache_php = new Cache_PHP(config('cache_prefix'), CACHE . 'persistent/');
$cache_php->set('npcs', $npcs, 5 * 365 * 24 * 60 * 60);
return true;
}
@@ -53,7 +53,7 @@ class NPCs
}
require_once LIBS . 'cache_php.php';
$cache_php = new Cache_PHP(config('cache_prefix'), CACHE);
$cache_php = new Cache_PHP(config('cache_prefix'), CACHE . 'persistent/');
self::$npcs = $cache_php->get('npcs');
}
}

View File

@@ -370,7 +370,14 @@ class POT
throw new RuntimeException('Please install PHP pdo extension. MyAAC will not work without it.');
}
$this->db = new OTS_DB_MySQL($params);
global $debugBar;
if (isset($debugBar)) {
$this->db = new DebugBar\DataCollector\PDO\TraceablePDO(new OTS_DB_MySQL($params));
$debugBar->addCollector(new DebugBar\DataCollector\PDO\PDOCollector($this->db));
}
else {
$this->db = new OTS_DB_MySQL($params);
}
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}

View File

@@ -952,7 +952,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
return $query['group_id'];
}
return 0;
return 1;
}
public function getAccGroupId()

View File

@@ -117,12 +117,15 @@ class OTS_DB_MySQL extends OTS_Base_DB
}
}
$driverAttributes = []; // debugbar dont like persistent connection
if (config('env') !== 'dev' && !getBoolean(config('enable_debugbar'))) {
$driverAttributes[PDO::ATTR_PERSISTENT] = $params['persistent'];
}
if(isset($params['socket'][0])) {
$dns[] = 'unix_socket=' . $params['socket'];
parent::__construct('mysql:' . implode(';', $dns), $user, $password, array(
PDO::ATTR_PERSISTENT => $params['persistent']
));
parent::__construct('mysql:' . implode(';', $dns), $user, $password, $driverAttributes);
return;
}
@@ -135,9 +138,7 @@ class OTS_DB_MySQL extends OTS_Base_DB
$dns[] = 'port=' . $params['port'];
}
parent::__construct('mysql:' . implode(';', $dns), $user, $password, array(
PDO::ATTR_PERSISTENT => $params['persistent']
));
parent::__construct('mysql:' . implode(';', $dns), $user, $password, $driverAttributes);
}
public function __destruct()

View File

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

View File

@@ -14,8 +14,9 @@ CREATE TABLE `myaac_menu`
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
");
require_once LIBS . 'plugins.php';
Plugins::installMenus('kathrine', require TEMPLATES . 'kathrine/menus.php');
Plugins::installMenus('tibiacom', require TEMPLATES . 'tibiacom/menus.php');
}
require_once LIBS . 'plugins.php';
Plugins::installMenus('kathrine', require TEMPLATES . 'kathrine/menus.php');
Plugins::installMenus('tibiacom', require TEMPLATES . 'tibiacom/menus.php');

View File

@@ -1,5 +1,7 @@
<?php
require_once LIBS . 'Settings.php';
$query = $db->query("SELECT `id` FROM `players` WHERE (`name` = " . $db->quote("Rook Sample") . " OR `name` = " . $db->quote("Sorcerer Sample") . " OR `name` = " . $db->quote("Druid Sample") . " OR `name` = " . $db->quote("Paladin Sample") . " OR `name` = " . $db->quote("Knight Sample") . " OR `name` = " . $db->quote("Account Manager") . ") ORDER BY `id`;");
$highscores_ignored_ids = array();

8
system/migrations/37.php Normal file
View File

@@ -0,0 +1,8 @@
<?php
// 2023-11-11
// Add Guest page access
use MyAAC\Models\Pages;
Pages::query()->where('access', 1)->update(['access' => 0]);

5
system/migrations/38.php Normal file
View File

@@ -0,0 +1,5 @@
<?php
// 2023-11-11
// execute highscores_ids_hidden once again, cause of settings
require __DIR__ . '/20.php';

View File

@@ -92,18 +92,22 @@ else
<tr>
<td width="30">&nbsp;</td>
<td align=left>
<form action="' . getLink('account/email') . '" method="post"><input type="hidden" name="changeemailsave" value=1 >
<form action="' . getLink('account/email') . '" method="post">
' . csrf() . '
<input type="hidden" name="changeemailsave" value=1 >
<INPUT TYPE=image NAME="I Agree" SRC="' . $template_path . '/images/global/buttons/sbutton_iagree.gif" BORDER=0 WIDTH=120 HEIGHT=17>
</form>
</td>
<td align=left>
<form action="' . getLink('account/email') . '" method="post">
' . csrf() . '
<input type="hidden" name="emailchangecancel" value=1 >
' . $twig->render('buttons.cancel.html.twig') . '
</form>
</td>
<td align=right>
<form action="?subtopic=accountmanagement" method="post" >
' . csrf() . '
' . $twig->render('buttons.back.html.twig') . '
</form>
</td>
@@ -125,6 +129,7 @@ else
<td>
<table border="0" cellspacing="0" cellpadding="0" >
<form action="' .getLink('account/email') . '" method="post" >
' . csrf() . '
<tr>
<td style="border:0px;" >
<input type="hidden" name="emailchangecancel" value="1" >
@@ -137,6 +142,7 @@ else
<td>
<table border="0" cellspacing="0" cellpadding="0" >
<form action="' . getLink('account/manage') . '" method="post" >
' . csrf() . '
<tr>
<td style="border:0px;" >
' . $twig->render('buttons.back.html.twig') . '

View File

@@ -18,18 +18,18 @@ if(!$logged) {
}
$new_password = $_POST['newpassword'] ?? NULL;
$new_password2 = $_POST['newpassword2'] ?? NULL;
$new_password_confirm = $_POST['newpassword_confirm'] ?? NULL;
$old_password = $_POST['oldpassword'] ?? NULL;
if(empty($new_password) && empty($new_password2) && empty($old_password)) {
if(empty($new_password) && empty($new_password_confirm) && empty($old_password)) {
$twig->display('account.change_password.html.twig');
}
else
{
if(empty($new_password) || empty($new_password2) || empty($old_password)){
if(empty($new_password) || empty($new_password_confirm) || empty($old_password)){
$errors[] = 'Please fill in form.';
}
$password_strlen = strlen($new_password);
if($new_password != $new_password2) {
if($new_password != $new_password_confirm) {
$errors[] = 'The new passwords do not match!';
}

View File

@@ -50,7 +50,7 @@ if($save)
$email = $_POST['email'];
$password = $_POST['password'];
$password2 = $_POST['password2'];
$password_confirm = $_POST['password_confirm'];
// account
if(!config('account_login_by_email')) {
@@ -81,7 +81,7 @@ if($save)
if(empty($password)) {
$errors['password'] = 'Please enter the password for your new account.';
}
elseif($password != $password2) {
elseif($password != $password_confirm) {
$errors['password'] = 'Passwords are not the same.';
}
else if(!Validator::password($password)) {
@@ -134,7 +134,7 @@ if($save)
'email' => $email,
'country' => $country,
'password' => $password,
'password2' => $password2,
'password_confirm' => $password_confirm,
'accept_rules' => isset($_POST['accept_rules']) ? $_POST['accept_rules'] === 'true' : false,
);
@@ -267,7 +267,7 @@ if($save)
$_POST['account_login'] = USE_ACCOUNT_NAME ? $account_name : $account_id;
}
$_POST['password_login'] = $password2;
$_POST['password_login'] = $password_confirm;
require PAGES . 'account/login.php';
header('Location: ' . getLink('account/manage'));

View File

@@ -153,7 +153,9 @@ class FAQ
$row = ModelsFAQ::find($id);
if ($row) {
$row->hidden = ($row->hidden == 1 ? 0 : 1);
$row->save();
if (!$row->save()) {
$errors[] = 'Fail during toggle hidden FAQ.';
}
} else {
$errors[] = 'FAQ with id ' . $id . ' does not exists.';
}

View File

@@ -135,6 +135,7 @@ if($settingHighscoresOutfit) {
$configHighscoresPerPage = setting('core.highscores_per_page');
$limit = $configHighscoresPerPage + 1;
$highscores = [];
$needReCache = true;
$cacheKey = 'highscores_' . $skill . '_' . $vocation . '_' . $page . '_' . $configHighscoresPerPage;
@@ -158,7 +159,7 @@ $query->join('accounts', 'accounts.id', '=', 'players.account_id')
->selectRaw('accounts.country, players.id, players.name, players.account_id, players.level, players.vocation' . $outfit . $promotion)
->orderByDesc('value');
if (!isset($highscores) || empty($highscores)) {
if (empty($highscores)) {
if ($skill >= POT::SKILL_FIRST && $skill <= POT::SKILL_LAST) { // skills
if ($db->hasColumn('players', 'skill_fist')) {// tfs 1.0
$skill_ids = array(
@@ -201,17 +202,17 @@ if (!isset($highscores) || empty($highscores)) {
$list = 'experience';
}
}
$highscores = $query->get()->map(function($row) {
$tmp = $row->toArray();
$tmp['online'] = $row->online_status;
$tmp['vocation'] = $row->vocation_name;
unset($tmp['online_table']);
return $tmp;
})->toArray();
}
$highscores = $query->get()->map(function($row) {
$tmp = $row->toArray();
$tmp['online'] = $row->online_status;
$tmp['vocation'] = $row->vocation_name;
unset($tmp['online_table']);
return $tmp;
})->toArray();
if ($cache->enabled() && $needReCache) {
$cache->set($cacheKey, serialize($highscores), setting('core.highscores_cache_ttl') * 60);
}

View File

@@ -13,6 +13,7 @@ defined('MYAAC') or die('Direct access not allowed!');
require_once LIBS . 'forum.php';
require_once LIBS . 'news.php';
$canEdit = hasFlag(FLAG_CONTENT_NEWS) || superAdmin();
if(isset($_GET['archive']))
{
$title = 'News Archive';
@@ -57,9 +58,14 @@ if(isset($_GET['archive']))
}
}
$admin_options = '';
if($canEdit) {
$admin_options = $twig->render('admin.links.html.twig', ['page' => 'news', 'id' => $news['id'], 'hidden' => $news['hidden']]);
}
$twig->display('news.html.twig', array(
'title' => stripslashes($news['title']),
'content' => $content_,
'content' => $content_ . $admin_options,
'date' => $news['date'],
'icon' => $categories[$news['category']]['icon_id'],
'author' => setting('core.news_author') ? $author : '',
@@ -81,7 +87,7 @@ if(isset($_GET['archive']))
foreach($news_DB as $news)
{
$newses[] = array(
'link' => getLink('news') . '/archive/' . $news['id'],
'link' => getLink('news') . '/' . $news['id'],
'icon_id' => $categories[$news['category']]['icon_id'],
'title' => stripslashes($news['title']),
'date' => $news['date']
@@ -99,7 +105,6 @@ header('X-XSS-Protection: 0');
$title = 'Latest News';
$cache = Cache::getInstance();
$canEdit = hasFlag(FLAG_CONTENT_NEWS) || superAdmin();
$news_cached = false;
if($cache->enabled())
@@ -180,18 +185,8 @@ if(!$news_cached)
}
$admin_options = '';
if($canEdit)
{
$admin_options = '<br/><br/><a target="_blank" rel="noopener noreferrer" href="' . ADMIN_URL . '?p=news&action=edit&id=' . $news['id'] . '" title="Edit">
<img src="images/edit.png"/>Edit
</a>
<a id="delete" target="_blank" rel="noopener noreferrer" href="' . ADMIN_URL . '?p=news&action=delete&id=' . $news['id'] . '" onclick="return confirm(\'Are you sure?\');" title="Delete">
<img src="images/del.png"/>Delete
</a>
<a target="_blank" rel="noopener noreferrer" href="' . ADMIN_URL . '?p=news&action=hide&id=' . $news['id'] . '" title="' . ($news['hidden'] != 1 ? 'Hide' : 'Show') . '">
<img src="images/' . ($news['hidden'] != 1 ? 'success' : 'error') . '.png"/>
' . ($news['hidden'] != 1 ? 'Hide' : 'Show') . '
</a>';
if($canEdit) {
$admin_options = $twig->render('admin.links.html.twig', ['page' => 'news', 'id' => $news['id'], 'hidden' => $news['hidden']]);
}
$content_ = $news['body'];

View File

@@ -79,7 +79,7 @@ $ignore = false;
/** @var boolean $logged */
/** @var OTS_Account $account_logged */
$logged_access = 1;
$logged_access = 0;
if($logged && $account_logged && $account_logged->isLoaded()) {
$logged_access = $account_logged->getAccess();
}
@@ -220,9 +220,8 @@ else {
$content .= $tmp_content;
if (hasFlag(FLAG_CONTENT_PAGES) || superAdmin()) {
$pageInfo = getCustomPageInfo($pageName);
$content = $twig->render('admin.pages.links.html.twig', array(
'page' => array('id' => $pageInfo !== null ? $pageInfo['id'] : 0, 'hidden' => $pageInfo !== null ? $pageInfo['hidden'] : '0')
)) . $content;
$content = $twig->render('admin.links.html.twig', ['page' => 'pages', 'id' => $pageInfo !== null ? $pageInfo['id'] : 0, 'hidden' => $pageInfo !== null ? $pageInfo['hidden'] : '0']
) . $content;
}
$page = $pageName;

View File

@@ -12,6 +12,7 @@ defined('MYAAC') or die('Direct access not allowed!');
return [
['GET', '', 'news.php'], // empty URL = show news
['GET', 'news/archive/{id:int}[/]', 'news/archive.php'],
['GET', 'news/{id:int}[/]', 'news/archive.php'],
// block access to some files
['*', 'account/base[/]', '404.php'], // this is to block account/base.php

View File

@@ -65,6 +65,12 @@ return [
'default' => false,
'is_config' => true,
],
'csrf_protection' => [
'name' => 'CSRF protection',
'type' => 'boolean',
'desc' => 'Its recommended to keep it enabled. Disable only if you know what you are doing.',
'default' => true,
],
'google_analytics_id' => [
'name' => 'Google Analytics ID',
'type' => 'text',
@@ -1048,8 +1054,9 @@ Sent by MyAAC,<br/>
'default' => true,
],
'highscores_country_box' => [ // not implemented yet
'hidden' => true,
'name' => 'Display Country Box',
'type' => 'hidden',
'type' => 'boolean',
'desc' => 'Show player outfit?',
'default' => false,
],
@@ -1126,7 +1133,7 @@ Sent by MyAAC,<br/>
'name' => 'Display Quests',
'type' => 'boolean',
'desc' => 'Show characters quests. Can be configured below',
'default' => true,
'default' => false,
],
'quests' => [
'name' => 'Quests List',
@@ -1581,7 +1588,13 @@ Sent by MyAAC,<br/>
'beforeSave' => function(&$settings, &$values) {
global $config;
$configToSave = [];
$configOriginal = $config;
unset($config);
$config = [];
require BASE . 'config.local.php';
$configToSave = $config;
$server_path = '';
$database = [];
@@ -1618,7 +1631,7 @@ Sent by MyAAC,<br/>
// if fail - revert the setting and inform the user
if (!file_exists($server_path . 'config.lua')) {
error('Server Path is invalid - cannot find config.lua in the directory. Setting have been reverted.');
$configToSave['server_path'] = $config['server_path'];
$configToSave['server_path'] = $configOriginal['server_path'];
}
// test database connection
@@ -1626,7 +1639,7 @@ Sent by MyAAC,<br/>
if ($database['database_overwrite'] && !Settings::testDatabaseConnection($database)) {
foreach ($database as $key => $value) {
if (!in_array($key, ['database_log', 'database_persistent'])) { // ignore these two
$configToSave[$key] = $config[$key];
$configToSave[$key] = $configOriginal[$key];
}
}
}

134
system/src/Admin/Pages.php Normal file
View File

@@ -0,0 +1,134 @@
<?php
namespace MyAAC\Admin;
use MyAAC\Models\Pages as ModelsPages;
class Pages
{
static public function verify($name, $title, $body, $player_id, $php, $enable_tinymce, $access, &$errors)
{
if(!isset($title[0]) || !isset($body[0])) {
$errors[] = 'Please fill all inputs.';
return false;
}
if(strlen($name) > PAGE_NAME_LIMIT) {
$errors[] = 'Page name cannot be longer than ' . PAGE_NAME_LIMIT . ' characters.';
return false;
}
if(strlen($title) > PAGE_TITLE_LIMIT) {
$errors[] = 'Page title cannot be longer than ' . PAGE_TITLE_LIMIT . ' characters.';
return false;
}
if(strlen($body) > PAGE_BODY_LIMIT) {
$errors[] = 'Page content cannot be longer than ' . PAGE_BODY_LIMIT . ' characters.';
return false;
}
if(!isset($player_id) || $player_id == 0) {
$errors[] = 'Player ID is wrong.';
return false;
}
if(!isset($php) || ($php != 0 && $php != 1)) {
$errors[] = 'Enable PHP is wrong.';
return false;
}
if ($php == 1 && !getBoolean(setting('core.admin_pages_php_enable'))) {
$errors[] = 'PHP pages disabled on this server. To enable go to Settings in Admin Panel and enable <strong>Enable PHP Pages</strong>.';
return false;
}
if(!isset($enable_tinymce) || ($enable_tinymce != 0 && $enable_tinymce != 1)) {
$errors[] = 'Enable TinyMCE is wrong.';
return false;
}
if(!isset($access) || $access < 0 || $access > PHP_INT_MAX) {
$errors[] = 'Access is wrong.';
return false;
}
return true;
}
static public function get($id)
{
$row = ModelsPages::find($id);
if ($row) {
return $row->toArray();
}
return false;
}
static public function add($name, $title, $body, $player_id, $php, $enable_tinymce, $access, &$errors)
{
if(!self::verify($name, $title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) {
return false;
}
if (!ModelsPages::where('name', $name)->exists())
ModelsPages::create([
'name' => $name,
'title' => $title,
'body' => $body,
'player_id' => $player_id,
'php' => $php ? '1' : '0',
'enable_tinymce' => $enable_tinymce ? '1' : '0',
'access' => $access
]);
else
$errors[] = 'Page with this link already exists.';
return !count($errors);
}
static public function update($id, $name, $title, $body, $player_id, $php, $enable_tinymce, $access, &$errors)
{
if(!self::verify($name, $title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) {
return false;
}
ModelsPages::where('id', $id)->update([
'name' => $name,
'title' => $title,
'body' => $body,
'player_id' => $player_id,
'php' => $php ? '1' : '0',
'enable_tinymce' => $enable_tinymce ? '1' : '0',
'access' => $access
]);
return true;
}
static public function delete($id, &$errors)
{
if (isset($id)) {
$row = ModelsPages::find($id);
if ($row) {
$row->delete();
}
else
$errors[] = 'Page with id ' . $id . ' does not exists.';
} else
$errors[] = 'id not set';
return !count($errors);
}
static public function toggleHidden($id, &$errors, &$status)
{
if (isset($id)) {
$row = ModelsPages::find($id);
if ($row) {
$row->hidden = $row->hidden == 1 ? 0 : 1;
if (!$row->save()) {
$errors[] = 'Fail during toggle hidden Page.';
}
$status = $row->hidden;
}
else {
$errors[] = 'Page with id ' . $id . ' does not exists.';
}
} else
$errors[] = 'id not set';
return !count($errors);
}
}

95
system/src/CsrfToken.php Normal file
View File

@@ -0,0 +1,95 @@
<?php
/**
* CsrfToken
*
* @package MyAAC
* @author Znote
* @author Slawkens <slawkens@gmail.com>
* @copyright 2023 MyAAC
* @link https://my-aac.org
*/
namespace MyAAC;
class CsrfToken
{
public static function generate(): void
{
$token = sha1(uniqid(time(), true));
setSession('csrf_token', $token);
}
/**
* Displays a random token to prevent CSRF attacks.
*
* @access public
* @static true
* @return void
**/
public static function create(): void {
echo '<input type="hidden" name="csrf_token" value="' . self::get() . '" />';
}
/**
* Returns the active token, if there is one.
*
* @access public
* @static true
* @return mixed
**/
public static function get(): mixed
{
$token = getSession('csrf_token');
return $token ?? false;
}
/**
* Validates whether the active token is valid or not.
*
* @param string $post
* @access public
* @static true
* @return boolean
**/
public static function isValid($post): bool
{
if (!setting('core.csrf_protection')) {
return true;
}
// Token doesn't exist yet, return false.
if (!self::get()) {
return false;
}
return ($post == getSession('csrf_token'));
}
/**
* Destroys the active token.
*
* @access protected
* @static true
* @return void
**/
protected static function reset(): void {
unsetSession('csrf_token');
}
/**
* Displays information on both the post token and the session token.
*
* @param string $post
* @access public
* @static true
* @return void
**/
public static function debug($post): void
{
echo '<pre>', var_export([
'post' => $post,
'token' => self::get()
], true), '</pre>';
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace MyAAC\Models;
use Illuminate\Database\Eloquent\Model;
class AccountAction extends Model {
protected $table = TABLE_PREFIX . 'account_actions';
public $timestamps = false;
protected $fillable = ['account_id', 'ip', 'ipv6', 'date', 'action'];
}

View File

@@ -3,7 +3,7 @@
namespace MyAAC\Models;
use Illuminate\Database\Eloquent\Model;
class GuildInvites extends Model {
class GuildInvite extends Model {
protected $table = 'guild_invites';

View File

@@ -2,5 +2,6 @@
<br/>
{% endif %}
<form action="{% if action is not defined %}{{ getLink('account/manage') }}{% else %}{{ action }}{% endif %}" method="post">
{{ csrf() }}
{{ include('buttons.back.html.twig') }}
</form>

View File

@@ -1,6 +1,7 @@
Here you can see and edit the information about your character.<br/>
If you do not want to specify a certain field, just leave it blank.<br/><br/>
<form action="{{ getLink('account/character/comment') }}" method="post">
{{ csrf() }}
<div class="TableContainer" >
<table class="Table5" cellpadding="0" cellspacing="0">
<div class="CaptionContainer">
@@ -99,6 +100,7 @@ If you do not want to specify a certain field, just leave it blank.<br/><br/>
<td>
<table border="0" cellspacing="0" cellpadding="0">
<form action="{{ getLink('account/manage') }}" method="post">
{{ csrf() }}
<tr>
<td style="border:0px;">
{{ include('buttons.back.html.twig') }}

View File

@@ -1,5 +1,6 @@
Here you can tell other players about yourself. This information will be displayed alongside the data of your characters. If you do not want to fill in a certain field, just leave it blank.<br/><br/>
<form action="{{ getLink('account/info') }}" method=post>
<form action="{{ getLink('account/info') }}" method="post">
{{ csrf() }}
<div class="TableContainer" >
<table class="Table1" cellpadding="0" cellspacing="0" >
<div class="CaptionContainer" >
@@ -88,6 +89,7 @@ Here you can tell other players about yourself. This information will be display
</form>
<table border="0" cellspacing="0" cellpadding="0" >
<form action="{{ getLink('account/manage') }}" method="post" >
{{ csrf() }}
<tr>
<td style="border:0px;" >
{{ include('buttons.back.html.twig') }}

View File

@@ -1,5 +1,6 @@
Please enter your password and the new email address. Make sure that you enter a valid email address which you have access to. <br/><b>For security reasons, the actual change will be finalised after a waiting period of {{ setting('core.account_mail_change') }} days.</b><br/><br/>
<form action="{{ getLink('account/email') }}" method="post">
{{ csrf() }}
<div class="TableContainer">
<table class="Table1" cellpadding="0" cellspacing="0">
<div class="CaptionContainer">
@@ -58,6 +59,7 @@ Please enter your password and the new email address. Make sure that you enter a
<td>
<table border="0" cellspacing="0" cellpadding="0">
<form action="{{ getLink('account/manage') }}" method="post">
{{ csrf() }}
<tr>
<td style="border:0px;">
{{ include('buttons.back.html.twig') }}

View File

@@ -1,6 +1,7 @@
To change a name of character select player and choose a new name.<br/>
<span style="color: red">Change name cost {{ setting('core.account_change_character_name_price') }} premium points. You have {{ points }} premium points.</span><br/><br/>
<form action="{{ getLink('account/character/name') }}" method="post">
{{ csrf() }}
<input type="hidden" name="changenamesave" value="1">
<div class="TableContainer">
<table class="Table1" cellpadding="0" cellspacing="0">
@@ -64,6 +65,7 @@ To change a name of character select player and choose a new name.<br/>
<td>
<table border="0" cellspacing="0" cellpadding="0">
<form action="{{ getLink('account/manage') }}" method="post">
{{ csrf() }}
<tr>
<td style="border:0px;">
{{ include('buttons.back.html.twig') }}

View File

@@ -1,6 +1,7 @@
Please enter your current password and a new password. For your security, please enter the new password twice.<br/>
<br/>
<form action="{{ getLink('account/password') }}" method="post">
{{ csrf() }}
<div class="TableContainer">
<table class="Table1" cellpadding="0" cellspacing="0">
<div class="CaptionContainer">
@@ -33,7 +34,7 @@ Please enter your current password and a new password. For your security, please
<span>New Password Again:</span>
</td>
<td>
<input type="password" name="newpassword2" size="30" maxlength="29">
<input type="password" name="newpassword_confirm" size="30" maxlength="29">
</td>
</tr>
<tr>
@@ -66,6 +67,7 @@ Please enter your current password and a new password. For your security, please
<td>
<table border="0" cellspacing="0" cellpadding="0">
<form action="{{ getLink('account/manage') }}" method="post">
{{ csrf() }}
<tr>
<td style="border:0px;">
{{ include('buttons.back.html.twig') }}
@@ -75,4 +77,4 @@ Please enter your current password and a new password. For your security, please
</table>
</td>
</tr>
</table>
</table>

View File

@@ -1,6 +1,7 @@
To change a sex of character select player and choose a new sex.<br/>
<span style="color: red">Change sex cost {{ setting('core.account_change_character_sex_price') }} premium points. You have {{ points }} premium points.</span><br/><br/>
<form action="{{ getLink('account/character/sex') }}" method="post">
{{ csrf() }}
<input type="hidden" name="changesexsave" value="1"/>
<div class="TableContainer">
<table class="Table1" cellpadding="0" cellspacing="0">
@@ -64,6 +65,7 @@ To change a sex of character select player and choose a new sex.<br/>
<td>
<table border="0" cellspacing="0" cellpadding="0">
<form action="{{ getLink('account/manage') }}" method="post">
{{ csrf() }}
<tr>
<td style="border:0px;" >
{{ include('buttons.back.html.twig') }}

View File

@@ -1,5 +1,6 @@
{{ hook('HOOK_ACCOUNT_CREATE_BEFORE_FORM') }}
<form action="{{ getLink('account/create') }}" method="post" id="createaccount">
{{ csrf() }}
<div class="TableContainer" >
<table class="Table5" cellpadding="0" cellspacing="0" >
<div class="CaptionContainer" >
@@ -104,11 +105,11 @@
<span{% if errors.password is defined %} class="red"{% endif %}>Repeat password:</span>
</td>
<td>
<input type="password" name="password2" id="password2" value="" size="30" maxlength="29" />
<img id="password2_indicator" src="images/global/general/{% if not save or errors.password is defined %}n{% endif %}ok.gif" style="display: none;" />
<input type="password" name="password_confirm" id="password_confirm" value="" size="30" maxlength="29" />
<img id="password_confirm_indicator" src="images/global/general/{% if not save or errors.password is defined %}n{% endif %}ok.gif" style="display: none;" />
</td>
</tr>
<tr><td></td><td><span id="password2_error" class="FormFieldError">{% if errors.password is defined %}{{ errors.password }}{% endif %}</span></td></tr>
<tr><td></td><td><span id="password_confirm_error" class="FormFieldError">{% if errors.password is defined %}{{ errors.password }}{% endif %}</span></td></tr>
{{ hook('HOOK_ACCOUNT_CREATE_AFTER_PASSWORDS') }}
</tbody>

View File

@@ -17,7 +17,7 @@
$('#password').blur(function() {
checkPassword();
});
$('#password2').blur(function() {
$('#password_confirm').blur(function() {
checkPassword();
});
$('#SuggestAccountNumber a').click(function (event) {
@@ -150,11 +150,11 @@
return;
}
if(document.getElementById("password2").value == "")
if(document.getElementById("password_confirm").value == "")
{
$('#password2_error').html('Please enter the password again!');
$('#password2_indicator').attr('src', 'images/global/general/nok.gif');
$('#password2_indicator').show();
$('#password_confirm_error').html('Please enter the password again!');
$('#password_confirm_indicator').attr('src', 'images/global/general/nok.gif');
$('#password_confirm_indicator').show();
return;
}
@@ -172,24 +172,24 @@
}
var password = document.getElementById("password").value;
var password2 = document.getElementById("password2").value;
$.getJSON("tools/validate.php", { password: password, password2: password2, uid: Math.random() },
var password_confirm = document.getElementById("password_confirm").value;
$.getJSON("tools/validate.php", { password: password, password_confirm: password_confirm, uid: Math.random() },
function(data){
if(data.hasOwnProperty('success')) {
$('#password_error').html ('');
$('#password2_error').html ('');
$('#password_confirm_error').html ('');
$('#password_indicator').attr('src', 'images/global/general/ok.gif');
$('#password2_indicator').attr('src', 'images/global/general/ok.gif');
$('#password_confirm_indicator').attr('src', 'images/global/general/ok.gif');
}
else if(data.hasOwnProperty('error')) {
$('#password_error').html(data.error);
$('#password2_error').html(data.error);
$('#password_confirm_error').html(data.error);
$('#password_indicator').attr('src', 'images/global/general/nok.gif');
$('#password2_indicator').attr('src', 'images/global/general/nok.gif');
$('#password_confirm_indicator').attr('src', 'images/global/general/nok.gif');
}
$('#password_indicator').show();
$('#password2_indicator').show();
$('#password_confirm_indicator').show();
}
);

View File

@@ -7,6 +7,7 @@ In any case the name must not violate the naming conventions stated in the <a hr
{% endif %}
<br/><br/>
<form action="{{ getLink('account/character/create') }}" method="post">
{{ csrf() }}
<input type="hidden" name="save" value="1">
<div class="TableContainer">
<table class="Table3" cellpadding="0" cellspacing="0">
@@ -135,6 +136,7 @@ In any case the name must not violate the naming conventions stated in the <a hr
<td>
<table border="0" cellspacing="0" cellpadding="0">
<form action="{{ getLink('account/manage') }}" method="post">
{{ csrf() }}
<tr>
<td style="border:0px;">
{{ include('buttons.back.html.twig') }}

View File

@@ -1,5 +1,6 @@
To delete a character enter the name of the character and your password.<br/><br/>
<form action="{{ getLink('account/character/delete') }}" method="post">
{{ csrf() }}
<input type="hidden" name="deletecharactersave" value="1"/>
<div class="TableContainer">
<table class="Table1" cellpadding="0" cellspacing="0" >
@@ -54,6 +55,7 @@ To delete a character enter the name of the character and your password.<br/><br
<td>
<table border="0" cellspacing="0" cellpadding="0">
<form action="{{ getLink('account/manage') }}" method="post">
{{ csrf() }}
<tr>
<td style="border:0px;">
{{ include('buttons.back.html.twig') }}
@@ -63,4 +65,4 @@ To delete a character enter the name of the character and your password.<br/><br
</table>
</td>
</tr>
</table>
</table>

View File

@@ -1,6 +1,7 @@
To generate new recovery key for your account please enter your password.<br/>
<span style="color: red"><b>New recovery key cost {{ setting('core.account_generate_new_reckey_price') }} Premium Points.</span> You have {{ points }} premium points. You will receive e-mail with this recovery key.</b><br/>
<form action="{{ getLink('account/register/new') }}" method="post">
{{ csrf() }}
<input type="hidden" name="registeraccountsave" value="1">
<div class="TableContainer" >
<table class="Table1" cellpadding="0" cellspacing="0">
@@ -47,6 +48,7 @@ To generate new recovery key for your account please enter your password.<br/>
<td>
<table border="0" cellspacing="0" cellpadding="0">
<form action="{{ getLink('account/manage') }}" method="post">
{{ csrf() }}
<tr>
<td style="border:0px;">
{{ include('buttons.back.html.twig') }}

View File

@@ -1,5 +1,6 @@
To generate recovery key for your account please enter your password.<br/><br/>
<form action="{{ getLink('account/register') }}" method="post">
{{ csrf() }}
<input type="hidden" name="registeraccountsave" value="1"/>
<div class="TableContainer">
<table class="Table1" cellpadding="0" cellspacing="0">
@@ -50,6 +51,7 @@ To generate recovery key for your account please enter your password.<br/><br/>
<td>
<table border="0" cellspacing="0" cellpadding="0">
<form action="{{ getLink('account/manage') }}" method="post">
{{ csrf() }}
<tr>
<td style="border: 0px;">
{{ include('buttons.back.html.twig') }}
@@ -59,4 +61,4 @@ To generate recovery key for your account please enter your password.<br/><br/>
</table>
</td>
</tr>
</table>
</table>

View File

@@ -1,6 +1,7 @@
{{ hook('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE') }}
Please enter your account {{ account|lower }} and your password.<br/><a href="{{ getLink('account/create') }}">Create an account</a> if you do not have one yet.<br/><br/>
<form action="{{ getLink('account/manage') }}" method="post" >
<form action="{{ getLink('account/manage') }}" method="post">
{{ csrf() }}
{% if redirect is not null %}
<input type="hidden" name="redirect" value="{{ redirect }}" />
{% endif %}
@@ -66,6 +67,7 @@ Please enter your account {{ account|lower }} and your password.<br/><a href="{{
<td>
<table border="0" cellspacing="0" cellpadding="0">
<form action="{{ getLink('account/lost') }}" method="post">
{{ csrf() }}
<tr>
<td style="border:0px;">
{{ include('buttons.account_lost.html.twig') }}

View File

@@ -1,5 +1,6 @@
The Lost Account Interface can help you to get back your account name and password. Please enter your character name and select what you want to do.<br/>
<form action="?subtopic=lostaccount&action=step1" method=post>
<form action="?subtopic=lostaccount&action=step1" method="post">
{{ csrf() }}
<input type="hidden" name="character" value="">
<table cellspacing="1" cellpadding="4" border="0" width="100%">
<tr>
@@ -32,4 +33,4 @@ The Lost Account Interface can help you to get back your account name and passwo
</td>
</tr>
</table>
</form>
</form>

View File

@@ -68,6 +68,7 @@
<div style="text-align:center">
You can register your account for increased protection. Click on "Register Account" and get your free recovery key today!<br/>
<form action="{{ getLink('account/register') }}" method="post">
{{ csrf() }}
{% set button_name = 'Register Account' %}
{% include('buttons.base.html.twig') %}
</form>
@@ -80,6 +81,7 @@
A request has been submitted to change the email address of this account to <b>{{ email_new }}</b>. After <b>{{ email_new_time|date("j F Y, G:i:s") }}</b> you can accept the new email address and finish the process. Please cancel the request if you do not want your email address to be changed! Also cancel the request if you have no access to the new email address!
<form action="{{ getLink('account/email') }}" method="post">
{{ csrf() }}
{% set button_name = 'Edit' %}
{% include('buttons.base.html.twig') %}
</form>
@@ -99,6 +101,7 @@
<td style="width: 90px;">Email Address:</td>
<td>{{ account_email ~ email_change }}
<form action="{{ getLink('account/email') }}" method="post">
{{ csrf() }}
{% set button_name = 'Change Email' %}
{% include('buttons.base.html.twig') %}
</form>
@@ -137,6 +140,7 @@
</tr>
</table>
<form action="{{ getLink('account/info') }}" method="post">
{{ csrf() }}
{% set button_name = 'Change Info' %}
{% include('buttons.base.html.twig') %}
</form>
@@ -188,6 +192,7 @@
<tr>
<td>
<form action="{{ getLink('account/character/create') }}" method="post" >
{{ csrf() }}
{% set button_name = 'Create Character' %}
{% include('buttons.base.html.twig') %}
</form>
@@ -195,6 +200,7 @@
{% if setting('core.account_change_character_name') %}
<td>
<form action="{{ getLink('account/character/name') }}" method="post" >
{{ csrf() }}
{% set button_name = 'Change Name' %}
{% include('buttons.base.html.twig') %}
</form>
@@ -203,6 +209,7 @@
{% if setting('core.account_change_character_sex') %}
<td>
<form action="{{ getLink('account/character/sex') }}" method="post" >
{{ csrf() }}
{% set button_name = 'Change Sex' %}
{% include('buttons.base.html.twig') %}
</form>
@@ -210,6 +217,7 @@
{% endif %}
<td>
<form action="{{ getLink('account/character/delete') }}" method="post">
{{ csrf() }}
{% set button_name = 'Delete Character' %}
{% include('buttons.base.html.twig') %}
</form>

View File

@@ -98,6 +98,7 @@ html { margin-top: 32px !important; }
<div class="dropdown-content">
<a href="{{ constant('ADMIN_URL') }}?p=news&action=new">News</a>
<a href="{{ constant('ADMIN_URL') }}?p=pages&action=new">Page</a>
<a href="{{ constant('ADMIN_URL') }}?p=changelog&action=new">Changelog</a>
</div>
</li>
<li>
@@ -106,9 +107,11 @@ html { margin-top: 32px !important; }
</a>
</li>
<li>
<a class="ab-item" href="{{ constant('ADMIN_URL') }}?p=dashboard&clear_cache">
Clear Cache
</a>
<form method="post" action="{{ constant('ADMIN_URL') }}?p=dashboard">
{{ csrf() }}
<input type="hidden" name="clear_cache" value="1" />
<a class="ab-item" href="#" onclick="confirm('Are you sure that you want to clear cache?') && $(this).closest('form').submit()" title="Clear Cache">Clear Cache</a>
</form>
</li>
</ul>
<ul class="ab-top-secondary">

View File

@@ -4,6 +4,8 @@
<h5 class="m-0">{{ (action == 'edit') ? 'Edit' : 'Add' }}</h5>
</div>
<form role="form" method="post" action="{{ cl_link_form }}" id="cl-edit-form">
{{ csrf() }}
<input type="hidden" name="action" value="{{ action }}" />
<div class="card-body">
{% if action == 'edit' %}
<input type="hidden" name="id" value="{{ cl_id }}"/>

View File

@@ -1,8 +1,11 @@
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">News:
<a href="{{ constant('ADMIN_URL') }}?p=changelog&action=new" class="float-right"><span
class="btn btn-sm btn-success">New</span></a>
<form method="post" class="float-right">
{{ csrf() }}
<input type="hidden" name="action" value="new" />
<button type="submit" class="btn btn-sm btn-success">New</button>
</form>
</h5>
</div>
@@ -30,15 +33,26 @@
<td><img src="{{ constant('BASE_URL') }}images/changelog/{{ log.where }}.png" alt="icon" title="{{ log.where|capitalize }}"/> {{ log.where|capitalize }}</td>
<td>
<div class="btn-group">
<a href="{{ constant('ADMIN_URL') }}?p=changelog&action=edit&id={{ log.id }}" class="btn btn-success btn-sm" title="Edit">
<i class="fas fa-pencil-alt"></i>
</a>
<a href="{{ constant('ADMIN_URL') }}?p=changelog&action=delete&id={{ log.id }}" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure?');" title="Delete">
<i class="fas fa-trash"></i>
</a>
<a href="{{ constant('ADMIN_URL') }}?p=changelog&action=hide&id={{ log.id }}" class="btn btn-{{ (log.hidden != 1) ? 'info' : 'default' }} btn-sm" title="{% if log.hidden != 1 %}Hide{% else %}Show{% endif %}">
<i class="fas fa-eye{{ (log.hidden != 1) ? '' : '-slash' }}"></i>
</a>
<form method="post">
{{ csrf() }}
<input type="hidden" name="action" value="edit" />
<input type="hidden" name="id" value="{{ log.id }}" />
<button type="submit" class="btn btn-success btn-sm" title="Edit"><i class="fas fa-pencil-alt"></i></button>
</form>
<form method="post">
{{ csrf() }}
<input type="hidden" name="action" value="delete" />
<input type="hidden" name="id" value="{{ log.id }}" />
<button type="submit" class="btn btn-danger btn-sm" title="Delete" onclick="return confirm('Are you sure?');"><i class="fas fa-pencil-alt"></i></button>
</form>
<form method="post">
{{ csrf() }}
<input type="hidden" name="action" value="hide" />
<input type="hidden" name="id" value="{{ log.id }}" />
<button type="submit" class="btn btn-{{ (log.hidden != 1) ? 'info' : 'default' }} btn-sm" title="{% if log.hidden != 1 %}Hide{% else %}Show{% endif %}"><i class="fas fa-eye{{ (log.hidden != 1) ? '' : '-slash' }}"></i></button>
</form>
</div>
</td>
</tr>
@@ -53,3 +67,15 @@
</table>
</div>
</div>
<link rel="stylesheet" type="text/css" href="{{ constant('BASE_URL') }}tools/css/jquery.datetimepicker.css"/ >
<script src="{{ constant('BASE_URL') }}tools/js/jquery.datetimepicker.js"></script>
<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

@@ -0,0 +1,20 @@
<form action="{{ constant('ADMIN_URL') }}?p={{ page }}" method="post" style="float: left">
{{ csrf() }}
<input type="hidden" name="action" value="edit" />
<input type="hidden" name="id" value="{{ id }}" />
<button type="submit" class="btn btn-success btn-sm" title="Edit"><img src="images/edit.png"/> Edit</button>
</form>
<form action="{{ constant('ADMIN_URL') }}?p={{ page }}" method="post" style="float: left">
{{ csrf() }}
<input type="hidden" name="action" value="delete" />
<input type="hidden" name="id" value="{{ id }}" />
<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure?');" title="Delete"><img src="images/del.png"/>Delete</button>
</form>
<form action="{{ constant('ADMIN_URL') }}?p={{ page }}" method="post" style="float: left">
{{ csrf() }}
<input type="hidden" name="action" value="hide" />
<input type="hidden" name="id" value="{{ id }}" />
<button type="submit" class="btn btn-{{ (hidden != 1) ? 'info' : 'default' }} btn-sm" title="{% if hidden != 1 %}Hide{% else %}Show{% endif %}"><img src="images/{{ hidden != 1 ? 'success' : 'error' }}.png"/>{{ hidden != 1 ? 'Hide' : 'Show' }}</button>
</form>

View File

@@ -19,6 +19,7 @@
<p class="login-box-msg">Please login.</p>
<form method="post" action="{{ constant('ADMIN_URL') }}">
{{ csrf() }}
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-lock"></i></span>

View File

@@ -9,6 +9,7 @@
<h5 class="m-0">Mailer</h5>
</div>
<form id="form" method="post">
{{ csrf() }}
<div class="card-body">
<div class="form-group row">
<label for="mail_to">To: (enter email, or leave empty to all)</label>

View File

@@ -4,6 +4,7 @@
</div>
<div class="card-body">
<form method="post" action="?p=menus">
{{ csrf() }}
<p>Please choose template in which you want to edit menu items.</p>
<div class="col-md-6">
<div class="input-group input-group-sm">

View File

@@ -1,9 +1,11 @@
{% if action %}
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">{% if action == 'edit' %}Edit{% else %}Add{% endif %} news</h5>
<h5 class="m-0">{% if action == 'edit' %}Edit{% else %}Add{% endif %} {% if type == constant('NEWS') %}News{% elseif type == constant('TICKER') %}Ticker{% else %}Article{% endif %}</h5>
</div>
<form id="form" role="form" method="post" action="{{ news_link_form }}">
<form id="form" role="form" method="post">
{{ csrf() }}
<input type="hidden" name="action" value="{{ action == 'edit' ? 'edit' : 'new' }}" />
<div class="card-body " id="page-edit-table">
{% if action == 'edit' %}
<input type="hidden" name="id" value="{{ news_id }}"/>
@@ -22,9 +24,9 @@
<div class="form-group row">
<label for="select-type">Type</label>
<select class="form-control" name="type" id="select-type">
<option value="{{ constant('NEWS') }}" {% if type is defined and type == constant('NEWS') %}selected="selected"{% endif %}{% if action == 'edit' and type != constant('NEWS') %} disabled{% endif %}>News</option>
<option value="{{ constant('TICKER') }}" {% if type is defined and type == constant('TICKER') %}selected="selected"{% endif %}{% if action == 'edit' and type != constant('TICKER') %} disabled{% endif %}>Ticker</option>
<option value="{{ constant('ARTICLE') }}" {% if type is defined and type == constant('ARTICLE') %}selected="selected"{% endif %}{% if action == 'edit' and type != constant('ARTICLE') %} disabled{% endif %}>Article</option>
<option value="{{ constant('NEWS') }}" {% if type == constant('NEWS') %}selected="selected"{% endif %}{% if action == 'edit' and type != constant('NEWS') %} disabled{% endif %}>News</option>
<option value="{{ constant('TICKER') }}" {% if type == constant('TICKER') %}selected="selected"{% endif %}{% if action == 'edit' and type != constant('TICKER') %} disabled{% endif %}>Ticker</option>
<option value="{{ constant('ARTICLE') }}" {% if type == constant('ARTICLE') %}selected="selected"{% endif %}{% if action == 'edit' and type != constant('ARTICLE') %} disabled{% endif %}>Article</option>
</select>
</div>
@@ -85,7 +87,7 @@
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-info"><i class="fas fa-update"></i> Update</button>
<button type="submit" class="btn btn-info"><i class="fas fa-update"></i> {{ action == 'edit' ? 'Update' : 'Add' }}</button>
<button type="button" onclick="window.location = '{{ constant('ADMIN_URL') }}?p=news';" class="btn btn-danger float-right"><i class="fas fa-cancel"></i> Cancel</button>
</div>
</form>

View File

@@ -1,136 +1,6 @@
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">News:
<a href="?p=news&action=new&type=1" class="float-right"><span class="btn btn-sm btn-success">New</span></a>
</h5>
</div>
<div class="card-body">
<table class="tb_datatable table table-striped table-bordered table-responsive d-md-table">
<thead>
<tr>
<th width="5%">ID</th>
<th>Title</th>
<th>Date</th>
<th>Player</th>
<th style="width: 150px;">Options</th>
</tr>
</thead>
<tbody>
{% for news in newses[constant('NEWS')] %}
<tr>
<td>{{ news.id|raw }}</td>
<td><i><a href="?p=news&action=edit&id={{ news.id }}">{{ news.title }}</a></i></td>
<td>{{ news.date|date(setting('core.news_date_format')) }}</td>
<td><a target="_blank" rel="noopener noreferrer" href="{{ news.player_link }}">{{ news.player_name }}</a></td>
<td>
<div class="btn-group">
<a href="?p=news&action=edit&id={{ news.id }}" class="btn btn-success btn-sm" title="Edit">
<i class="fas fa-pencil-alt"></i>
</a>
<a href="?p=news&action=delete&id={{ news.id }}" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure?');" title="Delete">
<i class="fas fa-trash"></i>
</a>
<a href="?p=news&action=hide&id={{ news.id }}" class="btn btn-{{ (news.hidden != 1) ? 'info' : 'default' }} btn-sm" title="{% if news.hidden != 1 %}Hide{% else %}Show{% endif %}">
<i class="fas fa-eye{{ (news.hidden != 1) ? '' : '-slash' }}"></i>
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">Tickers:
<a href="?p=news&action=new&type=2" class="float-right"><span class="btn btn-sm btn-success">New</span></a>
</h5>
</div>
<div class="card-body">
<table class="tb_datatable table table-striped table-bordered table-responsive d-md-table">
<thead>
<tr>
<th width="5%">ID</th>
<th>Title</th>
<th>Date</th>
<th>Player</th>
<th style="width: 150px;">Options</th>
</tr>
</thead>
<tbody>
{% for ticker in newses[constant('TICKER')] %}
<tr>
<td>{{ ticker.id|raw }}</td>
<td><i><a href="?p=news&action=edit&id={{ ticker.id }}">{{ ticker.title }}</a></i></td>
<td>{{ ticker.date|date(setting('core.news_date_format')) }}</td>
<td><a target="_blank" rel="noopener noreferrer" href="{{ ticker.player_link }}">{{ ticker.player_name }}</a></td>
<td>
<div class="btn-group">
<a href="?p=news&action=edit&id={{ ticker.id }}" class="btn btn-success btn-sm" title="Edit">
<i class="fas fa-pencil-alt"></i>
</a>
<a href="?p=news&action=delete&id={{ ticker.id }}" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure?');" title="Delete">
<i class="fas fa-trash"></i>
</a>
<a href="?p=news&action=hide&id={{ ticker.id }}" class="btn btn-{{ (ticker.hidden != 1) ? 'info' : 'default' }} btn-sm" title="{% if ticker.hidden != 1 %}Hide{% else %}Show{% endif %}">
<i class="fas fa-eye{{ (ticker.hidden != 1) ? '' : '-slash' }}"></i>
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">Articles: <a href="?p=news&action=new&type=3" class="float-right"><span class="btn btn-sm btn-success">New</span></a>
</h5>
</div>
<div class="card-body">
<table class="tb_datatable table table-striped table-bordered table-responsive d-md-table">
<thead>
<tr>
<th width="5%">ID</th>
<th>Title</th>
<th>Date</th>
<th>Player</th>
<th style="width: 150px;">Options</th>
</tr>
</thead>
<tbody>
{% for article in newses[constant('ARTICLE')] %}
<tr>
<td>{{ article.id|raw }}</td>
<td><i><a href="?p=news&action=edit&id={{ article.id }}">{{ article.title }}</a></i></td>
<td>{{ article.date|date(setting('core.news_date_format')) }}</td>
<td><a target="_blank" rel="noopener noreferrer" href="{{ article.player_link }}">{{ article.player_name }}</a></td>
<td>
<div class="btn-group">
<a href="?p=news&action=edit&id={{ article.id }}" class="btn btn-success btn-sm" title="Edit">
<i class="fas fa-pencil-alt"></i>
</a>
<a href="?p=news&action=delete&id={{ article.id }}" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure?');" title="Delete">
<i class="fas fa-trash"></i>
</a>
<a href="?p=news&action=hide&id={{ article.id }}" class="btn btn-{{ (article.hidden != 1) ? 'info' : 'default' }} btn-sm" title="{% if article.hidden != 1 %}Hide{% else %}Show{% endif %}">
<i class="fas fa-eye{{ (article.hidden != 1) ? '' : '-slash' }}"></i>
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{{ include('admin.news.table.html.twig', {type: 1, title: 'News'}) }}
{{ include('admin.news.table.html.twig', {type: 2, title: 'Tickers'}) }}
{{ include('admin.news.table.html.twig', {type: 3, title: 'Articles'}) }}
<script>
$(function () {

View File

@@ -0,0 +1,64 @@
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">{{ title }}:
<form method="post" class="float-right">
{{ csrf() }}
<input type="hidden" name="action" value="new" />
<input type="hidden" name="type" value="{{ type }}" />
<button type="submit" class="btn btn-sm btn-success">New</button>
</form>
</h5>
</div>
<div class="card-body">
<table class="tb_datatable table table-striped table-bordered table-responsive d-md-table">
<thead>
<tr>
<th width="5%">ID</th>
<th>Title</th>
<th>Date</th>
<th>Player</th>
<th style="width: 150px;">Options</th>
</tr>
</thead>
<tbody>
{% for news in newses[type] %}
<tr>
<td>{{ news.id|raw }}</td>
<td>
<i>
<a href="{{ getLink('news') }}/{{ news.id }}" target="_blank">{{ news.title }}</a>
</i>
</td>
<td>{{ news.date|date(setting('core.news_date_format')) }}</td>
<td><a target="_blank" href="{{ news.player_link }}">{{ news.player_name }}</a></td>
<td>
<div class="btn-group">
<form method="post">
{{ csrf() }}
<input type="hidden" name="action" value="edit" />
<input type="hidden" name="id" value="{{ news.id }}" />
<button type="submit" class="btn btn-success btn-sm" title="Edit"><i class="fas fa-pencil-alt"></i></button>
</form>
<form method="post">
{{ csrf() }}
<input type="hidden" name="action" value="delete" />
<input type="hidden" name="id" value="{{ news.id }}" />
<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure?');" title="Delete"><i class="fas fa-trash"></i></button>
</form>
<form method="post">
{{ csrf() }}
<input type="hidden" name="action" value="hide" />
<input type="hidden" name="id" value="{{ news.id }}" />
<button type="submit" class="btn btn-{{ (news.hidden != 1) ? 'info' : 'default' }} btn-sm" title="{% if news.hidden != 1 %}Hide{% else %}Show{% endif %}"><i class="fas fa-eye{{ (news.hidden != 1) ? '' : '-slash' }}"></i></button>
</form>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>

View File

@@ -3,6 +3,7 @@
<h5 class="m-0">Notepad</h5>
</div>
<form method="post">
{{ csrf() }}
<div class="card-body">
<div class="form-group">
<label>This is your personal notepad. Be sure to save it each time you modify something.</label>

View File

@@ -3,7 +3,9 @@
<div class="card-header">
<h5 class="m-0">{% if action == 'edit' %}Edit{% else %}Add{% endif %} page</h5>
</div>
<form id="form" class="form-horizontal" method="post" action="?p=pages&action={% if action == 'edit' %}edit{% else %}new{% endif %}">
<form id="form" class="form-horizontal" method="post">
{{ csrf() }}
<input type="hidden" name="action" value="{{ action }}" />
{% if action == 'edit' %}
<input type="hidden" name="id" value="{{ id }}"/>
{% endif %}
@@ -19,10 +21,12 @@
<div class="form-group row">
<label for="access">Access</label>
<select class="form-control" id="access" name="access">
<option value="0" {% if access == 0 %}selected{% endif %}>Guest*</option>
{% for id, group in groups %}
<option value="{{ group.getId() }}"{% if access == group.getId() %} selected{% endif %}>{{ group.getName() }}</option>
<option value="{{ group.getId() }}"{% if access == group.getId() %} selected{% endif %}>{{ group.getName()|title }}</option>
{% endfor %}
</select>
<br>* Guest means everyone will have access to this page. Player means registered and logged in user.
</div>
<div class="form-group row">
<label for="php">PHP
@@ -64,7 +68,8 @@
if (!this.checked) {
tinymce.remove('#editor');
} else {
if (tinymce.get('#editor')!== null){
$('#php').prop('checked', false);
if (tinymce.get('#editor')!== null) {
tinymce.activeEditor.show();
} else {
tinymceInit();

View File

@@ -1,7 +1,12 @@
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">Pages
<a href="?p=pages&action=new" class="float-right"><span class="btn btn-sm btn-success">New</span></a></h5>
<form method="post" class="float-right">
{{ csrf() }}
<input type="hidden" name="action" value="new" />
<button type="submit" class="btn btn-sm btn-success">New</button>
</form>
</h5>
</div>
<div class="card-body">
<table class="table table-striped table-bordered table-responsive d-md-table" id="tb_pages">
@@ -21,15 +26,26 @@
<td>{% if page.php %}Yes{% else %}No{% endif %}</td>
<td>
<div class="btn-group">
<a href="?p=pages&action=edit&id={{ page.id }}" class="btn btn-success btn-sm" title="Edit">
<i class="fas fa-pencil-alt"></i>
</a>
<a href="?p=pages&action=delete&id={{ page.id }}" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure?');" title="Delete">
<i class="fas fa-trash"></i>
</a>
<a href="?p=pages&action=hide&id={{ page.id }}" class="btn btn-{{ (page.hidden != 1) ? 'info' : 'default' }} btn-sm" title="{% if page.hidden != 1 %}Hide{% else %}Show{% endif %}">
<i class="fas fa-eye{{ (page.hidden != 1) ? '' : '-slash' }}"></i>
</a>
<form method="post">
{{ csrf() }}
<input type="hidden" name="action" value="edit" />
<input type="hidden" name="id" value="{{ page.id }}" />
<button type="submit" class="btn btn-success btn-sm" title="Edit"><i class="fas fa-pencil-alt"></i></button>
</form>
<form method="post">
{{ csrf() }}
<input type="hidden" name="action" value="delete" />
<input type="hidden" name="id" value="{{ page.id }}" />
<button type="submit" class="btn btn-danger btn-sm" title="Delete" onclick="return confirm('Are you sure?');"><i class="fas fa-pencil-alt"></i></button>
</form>
<form method="post">
{{ csrf() }}
<input type="hidden" name="action" value="hide" />
<input type="hidden" name="id" value="{{ page.id }}" />
<button type="submit" class="btn btn-{{ (page.hidden != 1) ? 'info' : 'default' }} btn-sm" title="{% if page.hidden != 1 %}Hide{% else %}Show{% endif %}"><i class="fas fa-eye{{ (log.hidden != 1) ? '' : '-slash' }}"></i></button>
</form>
</div>
</td>
</tr>

View File

@@ -1,14 +0,0 @@
<div style="text-align: right;">
<a href="{{ constant('ADMIN_URL') }}?p=pages&action=edit&id={{ page.id }}" title="Edit in Admin Panel" target="_blank">
<img src="images/edit.png"/>Edit
</a>
<a id="delete" href="{{ constant('ADMIN_URL') }}?p=pages&action=delete&id={{ page.id }}" onclick="return confirm('Are you sure?');"
title="Delete in Admin Panel" target="_blank">
<img src="images/del.png"/>Delete
</a>
<a href="{{ constant('ADMIN_URL') }}?p=pages&action=hide&id={{ page.id }}"
title="{% if page.hidden != 1 %}Hide{% else %}Show{% endif %} in Admin Panel" target="_blank">
<img src="images/{% if page.hidden != 1 %}success{% else %}error{% endif %}.png"/>{% if page.hidden != 1 %}Hide{% else %}Show{% endif %}
</a>
<br/>
</div>

View File

@@ -4,6 +4,7 @@
<h5 class="m-0">Install plugin</h5>
</div>
<form enctype="multipart/form-data" method="post" action="{{ constant('ADMIN_URL') }}?p=plugins">
{{ csrf() }}
<div class="card-body">
<input type="hidden" name="upload_plugin"/>

View File

@@ -19,13 +19,17 @@
<tr>
<td>
{% if plugin.enabled %}
<a href="?p=plugins&disable={{ plugin.file }}" class="btn btn-success" onclick="return confirm('Are you sure you want to disable plugin {{ plugin.name }}?');" title="Disable">
<i class="fas fa-check"></i> Enabled
</a>
<form method="post">
{{ csrf() }}
<input type="hidden" name="disable" value="{{ plugin.file }}" />
<button type="submit" class="btn btn-success" onclick="return confirm('Are you sure you want to disable plugin {{ plugin.name }}?');" title="Disable"><i class="fas fa-check"></i> Enabled</button>
</form>
{% else %}
<a href="?p=plugins&enable={{ plugin.file }}" class="btn btn-danger" onclick="return confirm('Are you sure you want to enable plugin {{ plugin.name }}?');" title="Enable">
<i class="fas fa-ban"></i> Disabled
</a>
<form method="post">
{{ csrf() }}
<input type="hidden" name="enable" value="{{ plugin.file }}" />
<button type="submit" class="btn btn-danger" onclick="return confirm('Are you sure you want to enable plugin {{ plugin.name }}?');" title="Enable"><i class="fas fa-ban"></i> Disabled</button>
</form>
{% endif %}
</td>
<td><b>{{ plugin.name }}</b><br>
@@ -38,9 +42,11 @@
<td>{{ plugin.file }}.json</td>
<td>
{% if plugin.uninstall %}
<a href="?p=plugins&uninstall={{ plugin.file }}" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure you want to uninstall {{ plugin.name }}?');" title="Uninstall">
<i class="fas fa-trash"></i>
</a>
<form method="post">
{{ csrf() }}
<input type="hidden" name="uninstall" value="{{ plugin.file }}" />
<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure you want to uninstall {{ plugin.name }}?');" title="Uninstall"><i class="fas fa-trash"></i></button>
</form>
{% endif %}
</td>
</tr>

View File

@@ -74,6 +74,12 @@
<link rel="stylesheet" type="text/css" href="{{ constant('BASE_URL') }}tools/css/toastify.min.css">
<script type="text/javascript" src="{{ constant('BASE_URL') }}tools/js/toastify.min.js"></script>
<script>
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$('#settings').submit(function(e) {
e.preventDefault();

View File

@@ -6,6 +6,7 @@
<h5 class="m-0">Give Premium Points</h5>
</div>
<form method="post" action="{{ constant('ADMIN_URL') }}?p=mass_account">
{{ csrf() }}
<div class="card-body">
<div class="form-group">
<label>Premium Points</label>
@@ -28,6 +29,7 @@
<h5 class="m-0">Give Coins</h5>
</div>
<form method="post" action="{{ constant('ADMIN_URL') }}?p=mass_account">
{{ csrf() }}
<div class="card-body">
<div class="form-group">
<label>Coins</label>
@@ -50,6 +52,7 @@
<h5 class="m-0">Give Premium Days</h5>
</div>
<form method="post" action="{{ constant('ADMIN_URL') }}?p=mass_account">
{{ csrf() }}
<div class="card-body">
<div class="form-group">
<label>Premium Days</label>

View File

@@ -25,15 +25,7 @@
<td>{{ log.body|nl2br}}</td>
{% if canEdit %}
<td>
<a href="{{ constant('ADMIN_URL') }}?p=changelog&action=edit&id={{ log.id }}" title="Edit in Admin Panel" target="_blank">
<img src="images/edit.png"/>Edit
</a>
<a href="{{ constant('ADMIN_URL') }}?p=changelog&action=delete&id={{ log.id }}" onclick="return confirm('Are you sure?');" title="Delete in Admin Panel" target="_blank">
<img src="images/del.png"/>Delete
</a>
<a href="{{ constant('ADMIN_URL') }}?p=changelog&action=hide&id={{ log.id }}" title="{% if log.hidden != 1 %}Hide{% else %}Show{% endif %} in Admin Panel" target="_blank">
<img src="images/{{ (log.hidden != 1 ? 'success' : 'error') }}.png"/>{{ (log.hidden != 1) ? 'Hide' : 'Show' }}
</a>
{{ include('admin.links.html.twig', {page: 'changelog', id: log.id, hidden: log.hidden }) }}
</td>
{% endif %}
</tr>

View File

@@ -106,6 +106,7 @@
<td>{{ house.name ~ house.town ~ house.add }}</td>
<td>
<form action="?subtopic=houses&page=view" method="post">
{{ csrf() }}
<input type="hidden" name="house" value="{{ house.name }}">
<input type="image" name="View" alt="View" src="{{ template_path }}/images/global/buttons/sbutton_view.gif" border="0" width="120">
</form>
@@ -402,7 +403,8 @@
<td>{% if player.isOnline() %}<b><span style="color: green">Online</span></b>{% endif %}</td>
<td>
<table border="0" cellspacing="0" cellpadding="0">
<form action="{{ getLink('characters') }}" method=post>
<form action="{{ getLink('characters') }}" method="post">
{{ csrf() }}
<tr>
<td>
<input type="hidden" name="name" value="{{ player.getName() }}"/>

View File

@@ -52,9 +52,8 @@
});
});
</script>
{{ generateLink('?creatures', 'All', false)|raw }} - <a href="?subtopic=creatures&boss=view">Bosses</a>
<div style="float: right;"><input id="cSearch" type="text" placeholder="Search.."></div>
<table width="100%">
{{ generateLink(getLink('creatures'), 'All', false)|raw }} - <a href="?subtopic=creatures&boss=view">Bosses</a>
<table width="100%" id="creaturestb">
<thead>
<tr>
<th>Name</th>
@@ -83,7 +82,15 @@
</tbody>
</table>
{% endif %}
<script src="tools/js/jquery.min.js"></script>
<script>
$(document).ready(function () {
$('#creaturestb').DataTable();
});
</script>
<script src="tools/js/datatables.min.js"></script>
<link rel="stylesheet" href="tools/css/datatables.min.css">
{% else %}
<table width="100%">
<tr>

View File

@@ -1,7 +1,8 @@
<form method="post" action="{{ link }}">
{% if action == 'edit' %}
<input type="hidden" name="id" value="{{ id }}" />
{% endif %}
{{ csrf() }}
{% if action == 'edit' %}
<input type="hidden" name="id" value="{{ id }}" />
{% endif %}
<table width="100%" border="0" cellspacing="1" cellpadding="4">
<tr>
<td bgcolor="{{ config.vdarkborder }}" class="white"><b>{% if action == 'edit' %}Edit{% else %}Add{% endif %} FAQ</b></td>
@@ -23,4 +24,4 @@
</td>
</tr>
</table>
</form>
</form>

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