Compare commits

...

7 Commits

Author SHA1 Message Date
slawkens
e106ef7f6c First attempt 2025-09-28 16:58:37 +02:00
slawkens
c898fe25ef New function: getColumnInfo($table, $column) 2025-09-28 16:21:31 +02:00
slawkens
73c07d470d Add variable types, don't use $config 2025-09-28 16:10:58 +02:00
slawkens
56bd7ec5ed Prevent injection in $db->hasColumn 2025-09-28 16:09:14 +02:00
slawkens
4c6277c124 Start v1.8.3-dev 2025-09-28 14:16:28 +02:00
slawkens
228780f0ad Just leaving it here, for future use (twig hook display)
Maybe configurable in the future
2025-09-28 14:14:26 +02:00
slawkens
4e9999cc0d Do not use constant on twig hooks
So it can be displayed which hook is used
2025-09-28 14:13:51 +02:00
5 changed files with 81 additions and 25 deletions

View File

@@ -669,11 +669,17 @@ else if (isset($_REQUEST['search'])) {
<div class="col-12 col-sm-12 col-lg-6">
<label for="lastip" class="control-label">Last IP:</label>
<input type="text" class="form-control" id="lastip" name="lastip" autocomplete="off" maxlength="10" value="<?php
if (strlen($player->getLastIP()) > 11) {
echo inet_ntop($player->getLastIP());
$lastIPColumnInfo = $db->getColumnInfo('players', 'lastip');
if ($lastIPColumnInfo && is_array($lastIPColumnInfo)) {
if (str_contains($lastIPColumnInfo['type'], 'varbinary')) {
echo inet_ntop($player->getLastIP());
}
else {
echo longToIp($player->getLastIP());
}
}
else {
echo longToIp($player->getLastIP());
echo 'Error';
}
?>" readonly/>
</div>

View File

@@ -26,7 +26,7 @@
if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.');
const MYAAC = true;
const MYAAC_VERSION = '1.8.2';
const MYAAC_VERSION = '1.8.3-dev';
const DATABASE_VERSION = 45;
const TABLE_PREFIX = 'myaac_';
define('START_TIME', microtime(true));

View File

@@ -26,10 +26,11 @@ use MyAAC\Cache\Cache;
*/
class OTS_DB_MySQL extends OTS_Base_DB
{
private $has_table_cache = array();
private $has_column_cache = array();
private array $has_table_cache = [];
private array $has_column_cache = [];
private array $get_column_info_cache = [];
private $clearCacheAfter = false;
private bool $clearCacheAfter = false;
/**
* Creates database connection.
*
@@ -209,7 +210,8 @@ class OTS_DB_MySQL extends OTS_Base_DB
return $sql;
}
public function hasTable($name) {
public function hasTable($name): bool
{
if(isset($this->has_table_cache[$name])) {
return $this->has_table_cache[$name];
}
@@ -217,12 +219,13 @@ class OTS_DB_MySQL extends OTS_Base_DB
return $this->hasTableInternal($name);
}
private function hasTableInternal($name) {
global $config;
return ($this->has_table_cache[$name] = $this->query('SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA` = ' . $this->quote($config['database_name']) . ' AND `TABLE_NAME` = ' . $this->quote($name) . ' LIMIT 1;')->rowCount() > 0);
private function hasTableInternal($name): bool
{
return ($this->has_table_cache[$name] = $this->query('SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA` = ' . $this->quote(config('database_name')) . ' AND `TABLE_NAME` = ' . $this->quote($name) . ' LIMIT 1;')->rowCount() > 0);
}
public function hasColumn($table, $column) {
public function hasColumn($table, $column): bool
{
if(isset($this->has_column_cache[$table . '.' . $column])) {
return $this->has_column_cache[$table . '.' . $column];
}
@@ -230,8 +233,8 @@ class OTS_DB_MySQL extends OTS_Base_DB
return $this->hasColumnInternal($table, $column);
}
private function hasColumnInternal($table, $column) {
return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE '" . $column . "'")->fetchAll()) > 0);
private function hasColumnInternal($table, $column): bool {
return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE " . $this->quote($column))->fetchAll()) > 0);
}
public function hasTableAndColumns(string $table, array $columns = []): bool
@@ -247,6 +250,51 @@ class OTS_DB_MySQL extends OTS_Base_DB
return true;
}
public function getColumnInfo(string $table, string $column): bool|array
{
if(isset($this->get_column_info_cache[$table . '.' . $column])) {
return $this->get_column_info_cache[$table . '.' . $column];
}
return $this->getColumnInfoInternal($table, $column);
}
private function getColumnInfoInternal(string $table, string $column): bool|array
{
if (!$this->hasTable($table) || !$this->hasColumn($table, $column)) {
return false;
}
$formatResult = function ($result) {
return [
'field' => $result['Field'],
'type' => $result['Type'],
'null' => strtolower($result['Null']),
'default' => $result['Default'],
'extra' => $result['Extra'],
];
};
$query = $this->query('SHOW COLUMNS FROM `' . $table . "` LIKE " . $this->quote($column));
$rowCount = $query->rowCount();
if ($rowCount > 1) {
$tmp = [];
$results = $query->fetchAll(PDO::FETCH_ASSOC);
foreach ($results as $result) {
$tmp[] = $formatResult($result);
}
return ($this->get_column_info_cache[$table . '.' . $column] = $tmp);
}
else if ($rowCount == 1) {
$result = $query->fetch(PDO::FETCH_ASSOC);
return ($this->get_column_info_cache[$table . '.' . $column] = $formatResult($result));
}
return [];
}
public function revalidateCache() {
foreach($this->has_table_cache as $key => $value) {
$this->hasTableInternal($key);

View File

@@ -9,7 +9,7 @@
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tr>
<td><img src="{{ template_path }}/images/general/blank.gif" width="10" height="1" border="0"></td>
<td>
{{ hook(constant('HOOK_CHARACTERS_BEFORE_INFORMATIONS')) }}
{{ hook('HOOK_CHARACTERS_BEFORE_INFORMATIONS') }}
{% if canEdit %}
<a href="{{ constant('ADMIN_URL') }}?p=players&id={{ player.getId() }}" title="Edit in Admin Panel" target="_blank">
<img src="images/edit.png"/>Edit
@@ -153,11 +153,11 @@
<td>{% if account.isPremium() %}Premium Account{% else %}Free Account{% endif %}</td>
</tr>
</table>
{{ hook(constant('HOOK_CHARACTERS_AFTER_INFORMATIONS')) }}
{{ hook('HOOK_CHARACTERS_AFTER_INFORMATIONS') }}
<br/>
<table border="0" width="100%">
<tr>
{{ hook(constant('HOOK_CHARACTERS_BEFORE_SKILLS')) }}
{{ hook('HOOK_CHARACTERS_BEFORE_SKILLS') }}
{% if config.characters.skills %}
<!-- SKILLS -->
@@ -179,7 +179,7 @@
<!-- SKILLS_END -->
{% endif %}
{{ hook(constant('HOOK_CHARACTERS_AFTER_SKILLS')) }}
{{ hook('HOOK_CHARACTERS_AFTER_SKILLS') }}
{% if quests_enabled %}
<!-- QUESTS -->
@@ -201,7 +201,7 @@
<!-- QUESTS_END -->
{% endif %}
{{ hook(constant('HOOK_CHARACTERS_AFTER_QUESTS')) }}
{{ hook('HOOK_CHARACTERS_AFTER_QUESTS') }}
{% if config.characters.equipment %}
<!-- EQUIPMENT -->
@@ -239,11 +239,11 @@
<!-- EQUIPMENT_END -->
{% endif %}
{{ hook(constant('HOOK_CHARACTERS_AFTER_EQUIPMENT')) }}
{{ hook('HOOK_CHARACTERS_AFTER_EQUIPMENT') }}
</tr>
</table>
{{ hook(constant('HOOK_CHARACTERS_BEFORE_DEATHS')) }}
{{ hook('HOOK_CHARACTERS_BEFORE_DEATHS') }}
{% if deaths|length > 0 %}
<!-- DEATHS -->
@@ -283,7 +283,7 @@
<!-- FRAGS_END -->
{% endif %}
{{ hook(constant('HOOK_CHARACTERS_BEFORE_SIGNATURE')) }}
{{ hook('HOOK_CHARACTERS_BEFORE_SIGNATURE') }}
{% if setting('core.signature_enabled') %}
<!-- SIGNATURE -->
@@ -327,7 +327,7 @@
</table>
<!-- SIGNATURE_END -->
{% endif %}
{{ hook(constant('HOOK_CHARACTERS_AFTER_SIGNATURE')) }}
{{ hook('HOOK_CHARACTERS_AFTER_SIGNATURE') }}
{% if not player.isHidden() %}
{% set rows = 0 %}
<!-- ACCOUNT_INFORMATION -->
@@ -377,7 +377,7 @@
</tr>
</table>
<!-- ACCOUNT_INFORMATION_END -->
{{ hook(constant('HOOK_CHARACTERS_AFTER_ACCOUNT')) }}
{{ hook('HOOK_CHARACTERS_AFTER_ACCOUNT') }}
<!-- CHARACTERS_LIST -->
<br/><br/>
<table border="0" cellspacing="1" cellpadding="4" width="100%">
@@ -421,7 +421,7 @@
</table>
<!-- CHARACTERS_LIST_END -->
{% endif %}
{{ hook(constant('HOOK_CHARACTERS_AFTER_CHARACTERS')) }}
{{ hook('HOOK_CHARACTERS_AFTER_CHARACTERS') }}
{% if canEdit %}
<a href="{{ constant('ADMIN_URL') }}?p=players&id={{ player.getId() }}" title="Edit in Admin Panel" target="_blank">
<img src="images/edit.png"/>Edit

View File

@@ -101,6 +101,8 @@ $twig->addFunction($function);
$function = new TwigFunction('hook', function ($context, $hook, array $params = []) {
global $hooks;
//note($hook);
if(is_string($hook)) {
if (defined($hook)) {
$hook = constant($hook);