Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71a431d5aa | ||
|
|
6970e6221b | ||
|
|
831f3be1a8 | ||
|
|
f2aba8c466 | ||
|
|
f085ccaa38 | ||
|
|
6c3c1a908d | ||
|
|
388b90913a | ||
|
|
07aea9d7b2 | ||
|
|
edcdbee523 | ||
|
|
43b51895f0 | ||
|
|
d0e294ecf5 |
14
4dev/bin/create_mo.sh
Executable file
14
4dev/bin/create_mo.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
base_folder='/var/www/html/developers/clemens/core_data/php_libraries/trunk/www/';
|
||||
|
||||
# locale gettext po to mo translator master
|
||||
for file in $(ls -1 ${base_folder}../4dev/locale/*.po); do
|
||||
file=$(basename $file .po);
|
||||
echo "Translate language ${file}";
|
||||
locale=$(echo "${file}" | cut -d "-" -f 1);
|
||||
domain=$(echo "${file}" | cut -d "-" -f 2);
|
||||
msgfmt -o ${base_folder}/includes/locale/${locale}/LC_MESSAGES/${domain}.mo ${base_folder}../4dev/locale/${locale}-${domain}.po;
|
||||
done;
|
||||
|
||||
# __END__
|
||||
@@ -1,4 +1,42 @@
|
||||
base="/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/";
|
||||
# -c phpunit.xml
|
||||
# --testdox
|
||||
${base}www/vendor/bin/phpunit -c ${base}phpunit.xml ${base}4dev/tests/
|
||||
# call with "t" to give verbose testdox output
|
||||
# SUPPORTED: https://www.php.net/supported-versions.php
|
||||
# call with 7.3, 7.4, 8.0, 8.1 to force a certain php version
|
||||
|
||||
opt_testdox="";
|
||||
if [ "${1}" = "t" ] || [ "${2}" = "t" ]; then
|
||||
opt_testdox="--testdox";
|
||||
fi;
|
||||
php_bin="";
|
||||
if [ ! -z "${1}" ]; then
|
||||
case "${1}" in
|
||||
# "7.3") php_bin="/usr/bin/php7.3 "; ;;
|
||||
"7.4") php_bin="/usr/bin/php7.4 "; ;;
|
||||
"8.0") php_bin="/usr/bin/php8.0 "; ;;
|
||||
"8.1") php_bin="/usr/bin/php8.1 "; ;;
|
||||
*) echo "Not support PHP: ${1}"; exit; ;;
|
||||
esac;
|
||||
fi;
|
||||
if [ ! -z "${2}" ] && [ -z "${php_bin}" ]; then
|
||||
case "${2}" in
|
||||
# "7.3") php_bin="/usr/bin/php7.3 "; ;;
|
||||
"7.4") php_bin="/usr/bin/php7.4 "; ;;
|
||||
"8.0") php_bin="/usr/bin/php8.0 "; ;;
|
||||
"8.1") php_bin="/usr/bin/php8.1 "; ;;
|
||||
*) echo "Not support PHP: ${1}"; exit; ;;
|
||||
esac;
|
||||
fi;
|
||||
|
||||
phpunit_call="${php_bin}${base}www/vendor/bin/phpunit ${opt_testdox} -c ${base}phpunit.xml ${base}4dev/tests/";
|
||||
|
||||
${phpunit_call};
|
||||
|
||||
if [ ! -z "${php_bin}" ]; then
|
||||
echo "CALLED WITH PHP: ${php_bin}"$(${php_bin} --version);
|
||||
else
|
||||
echo "Default PHP used: "$(php --version);
|
||||
fi;
|
||||
|
||||
# __END__
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
# AUTHOR: Clemens Schwaighofer
|
||||
# CREATED: 2005/08/09
|
||||
# SHORT DESCRIPTION:
|
||||
# Backned English Messages file for gettext
|
||||
# to craete: msgfmt -o <output.po> <input.mo>
|
||||
# Backend English Messages file for gettext
|
||||
# ********************************************************************/
|
||||
|
||||
msgid ""
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
# to craete: msgfmt -o <output.po> <input.mo>
|
||||
# ********************************************************************
|
||||
# AUTHOR: Clemens Schwaighofer
|
||||
# CREATED: 2005/08/09
|
||||
# SHORT DESCRIPTION:
|
||||
# Frontend English Messages file for gettext
|
||||
# ********************************************************************/
|
||||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
# AUTHOR: Clemens Schwaighofer
|
||||
# CREATED: 2018/03/28
|
||||
# SHORT DESCRIPTION:
|
||||
# Backend Japanese Messages file for gettext
|
||||
# to craete: msgfmt -o <output.po> <input.mo>
|
||||
# Backend Japanese Messages file for gettext>
|
||||
# ********************************************************************/
|
||||
|
||||
msgid ""
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
# to craete: msgfmt -o <output.po> <input.mo>
|
||||
# ********************************************************************
|
||||
# AUTHOR: Clemens Schwaighofer
|
||||
# CREATED: 2005/08/09
|
||||
# SHORT DESCRIPTION:
|
||||
# Frontend Japanese Messages file for gettext
|
||||
# ********************************************************************/
|
||||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
|
||||
@@ -13,18 +13,73 @@ use PHPUnit\Framework\TestCase;
|
||||
*/
|
||||
final class CoreLibsACLLoginTest extends TestCase
|
||||
{
|
||||
private static $db;
|
||||
private static $log;
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
* start DB conneciton, setup DB, etc
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setUp(): void
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
if (!extension_loaded('pgsql')) {
|
||||
$this->markTestSkipped(
|
||||
self::markTestSkipped(
|
||||
'The PgSQL extension is not available.'
|
||||
);
|
||||
}
|
||||
// logger is always needed
|
||||
// define basic connection set valid and one invalid
|
||||
self::$log = new \CoreLibs\Debug\Logging([
|
||||
// 'log_folder' => __DIR__ . DIRECTORY_SEPARATOR . 'log',
|
||||
'log_folder' => DIRECTORY_SEPARATOR . 'tmp',
|
||||
'file_id' => 'CoreLibs-ACL-Login-Test',
|
||||
'debug_all' => false,
|
||||
'echo_all' => false,
|
||||
'print_all' => false,
|
||||
]);
|
||||
// if we do have pgsql, we need to create a test DB or check that one
|
||||
// exists and clean the table to zero state
|
||||
self::$db = new \CoreLibs\DB\IO(
|
||||
[
|
||||
'db_name' => 'corelibs_acl_login_test',
|
||||
'db_user' => 'corelibs_acl_login_test',
|
||||
'db_pass' => 'corelibs_acl_login_test',
|
||||
'db_host' => 'localhost',
|
||||
'db_port' => 5432,
|
||||
'db_schema' => 'public',
|
||||
'db_type' => 'pgsql',
|
||||
'db_encoding' => '',
|
||||
'db_ssl' => 'allow', // allow, disable, require, prefer
|
||||
'db_debug' => true,
|
||||
],
|
||||
self::$log
|
||||
);
|
||||
if (!self::$db->dbGetConnectionStatus()) {
|
||||
self::markTestSkipped(
|
||||
'Cannot connect to valid Test DB for ACL\Login test.'
|
||||
);
|
||||
}
|
||||
/*
|
||||
// check if they already exist, drop them
|
||||
if ($db->dbShowTableMetaData('table_with_primary_key') !== false) {
|
||||
$db->dbExec("DROP TABLE table_with_primary_key");
|
||||
$db->dbExec("DROP TABLE table_without_primary_key");
|
||||
$db->dbExec("DROP TABLE test_meta");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* close db
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function tearDownAfterClass(): void
|
||||
{
|
||||
if (self::$db->dbGetConnectionStatus()) {
|
||||
self::$db->dbClose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -40,6 +95,8 @@ final class CoreLibsACLLoginTest extends TestCase
|
||||
$this->markTestIncomplete(
|
||||
'ACL\Login Tests have not yet been implemented'
|
||||
);
|
||||
|
||||
$login = new \CoreLibs\ACL\Login(self::$db, self::$log);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
);
|
||||
if (!$db->dbGetConnectionStatus()) {
|
||||
self::markTestSkipped(
|
||||
'Cannot connect to valid Test DB.'
|
||||
'Cannot connect to valid Test DB for DB\IO test.'
|
||||
);
|
||||
}
|
||||
// check if they already exist, drop them
|
||||
@@ -566,7 +566,7 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
public function testDbSetDebug(
|
||||
string $connection,
|
||||
?bool $set,
|
||||
bool $expected,
|
||||
bool $expected
|
||||
): void {
|
||||
$db = new \CoreLibs\DB\IO(
|
||||
self::$db_config[$connection],
|
||||
@@ -599,7 +599,7 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
public function testDbToggleDebug(
|
||||
string $connection,
|
||||
?bool $toggle,
|
||||
bool $expected,
|
||||
bool $expected
|
||||
): void {
|
||||
$db = new \CoreLibs\DB\IO(
|
||||
self::$db_config[$connection],
|
||||
@@ -1734,7 +1734,7 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
$expected,
|
||||
string $warning,
|
||||
string $error,
|
||||
string $insert_data,
|
||||
string $insert_data
|
||||
): void {
|
||||
// self::$log->setLogLevelAll('debug', true);
|
||||
// self::$log->setLogLevelAll('print', true);
|
||||
@@ -1871,7 +1871,7 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
$expected,
|
||||
string $warning,
|
||||
string $error,
|
||||
string $insert_data,
|
||||
string $insert_data
|
||||
): void {
|
||||
// self::$log->setLogLevelAll('debug', true);
|
||||
// self::$log->setLogLevelAll('print', true);
|
||||
@@ -2034,7 +2034,7 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
array $cursor_ext_checks,
|
||||
string $warning,
|
||||
string $error,
|
||||
string $insert_data,
|
||||
string $insert_data
|
||||
): void {
|
||||
// self::$log->setLogLevelAll('debug', true);
|
||||
// self::$log->setLogLevelAll('print', true);
|
||||
@@ -2356,7 +2356,7 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
string $error_execute,
|
||||
string $expected_data_query,
|
||||
array $expected_data,
|
||||
string $insert_data,
|
||||
string $insert_data
|
||||
): void {
|
||||
// self::$log->setLogLevelAll('debug', true);
|
||||
// self::$log->setLogLevelAll('print', true);
|
||||
@@ -3010,7 +3010,7 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
string $insert,
|
||||
?string $pk_name,
|
||||
string $table,
|
||||
string $primary_key,
|
||||
string $primary_key
|
||||
): void {
|
||||
// self::$log->setLogLevelAll('debug', true);
|
||||
// self::$log->setLogLevelAll('print', true);
|
||||
|
||||
@@ -730,7 +730,7 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
bool $expected_debug,
|
||||
string $expected_file,
|
||||
string $expected_string_start,
|
||||
string $expected_string_contains,
|
||||
string $expected_string_contains
|
||||
): void {
|
||||
// must run with below matrix
|
||||
// level | debug | print | echo | debug() | printErrorMsg() | file
|
||||
|
||||
@@ -240,7 +240,7 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase
|
||||
?string $path,
|
||||
?string $SESSION_DEFAULT_LOCALE,
|
||||
?string $SESSION_DEFAULT_CHARSET,
|
||||
array $expected,
|
||||
array $expected
|
||||
): void {
|
||||
$return_lang_settings = [];
|
||||
global $_SESSION;
|
||||
|
||||
@@ -109,10 +109,11 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
// 2: encoding
|
||||
// 3: path
|
||||
// 4: locale expected
|
||||
// 5: domain exepcted
|
||||
// 6: context (null for none)
|
||||
// 7: test string in
|
||||
// 8: test translated
|
||||
// 5: locale set expected
|
||||
// 6: domain exepcted
|
||||
// 7: context (null for none)
|
||||
// 8: test string in
|
||||
// 9: test translated
|
||||
// new style load
|
||||
'gettext load en' => [
|
||||
'en_US.UTF-8',
|
||||
@@ -120,6 +121,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
__DIR__ . 'includes/locale/',
|
||||
//
|
||||
'en_US.UTF-8',
|
||||
'en_US',
|
||||
'frontend',
|
||||
null,
|
||||
'Original',
|
||||
@@ -131,6 +133,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
__DIR__ . 'includes/locale/',
|
||||
//
|
||||
'en_US.UTF-8',
|
||||
'en_US',
|
||||
'frontend',
|
||||
'context',
|
||||
'Original',
|
||||
@@ -142,6 +145,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
__DIR__ . 'includes/locale/',
|
||||
//
|
||||
'ja_JP.UTF-8',
|
||||
'ja_JP',
|
||||
'admin',
|
||||
null,
|
||||
'Original',
|
||||
@@ -154,6 +158,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
'frontend',
|
||||
//
|
||||
'en_US.UTF-8',
|
||||
'en_US',
|
||||
'frontend',
|
||||
'context',
|
||||
'Original',
|
||||
@@ -167,6 +172,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
//
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
null,
|
||||
'Original',
|
||||
'Original',
|
||||
@@ -185,6 +191,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
* @param string|null $domain
|
||||
* @param string|null $path
|
||||
* @param string $locale_expected
|
||||
* @param string $locale_set_expected
|
||||
* @param string $domain_expected
|
||||
* @param ?string $context
|
||||
* @param string $original
|
||||
@@ -196,10 +203,11 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
?string $domain,
|
||||
?string $path,
|
||||
string $locale_expected,
|
||||
string $locale_set_expected,
|
||||
string $domain_expected,
|
||||
?string $context,
|
||||
string $original,
|
||||
string $translated,
|
||||
string $translated
|
||||
): void {
|
||||
if ($locale === null) {
|
||||
$l10n = new \CoreLibs\Language\L10n();
|
||||
@@ -217,6 +225,11 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
$l10n->getLocale(),
|
||||
'Locale assert failed'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$locale_set_expected,
|
||||
$l10n->getLocaleSet(),
|
||||
'Locale set assert failed'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$domain_expected,
|
||||
$l10n->getDomain(),
|
||||
@@ -255,15 +268,17 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
// 3: load error
|
||||
// 4: input string to translated
|
||||
// 5: expected locale
|
||||
// 6: expected domain
|
||||
// 7: expected translation
|
||||
// 8: change locale
|
||||
// 9: change domain
|
||||
// 10: change path
|
||||
// 11: change load error
|
||||
// 12: expected locale
|
||||
// 13: expected domain
|
||||
// 14: expected translation
|
||||
// 6: expected locale set
|
||||
// 7: expected domain
|
||||
// 8: expected translation
|
||||
// 9: change locale
|
||||
// 10: change domain
|
||||
// 11: change path
|
||||
// 12: change load error
|
||||
// 13: expected locale
|
||||
// 14: expected locale set
|
||||
// 15: expected domain
|
||||
// 16: expected translation
|
||||
'load and change (en->ja)' => [
|
||||
// set 0-2
|
||||
'en_US.UTF-8',
|
||||
@@ -275,6 +290,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
'Original',
|
||||
// check setter 5-7
|
||||
'en_US.UTF-8',
|
||||
'en_US',
|
||||
'frontend',
|
||||
'Translated frontend en_US',
|
||||
// set new 8-10
|
||||
@@ -285,6 +301,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
false,
|
||||
// check new setter 12-14
|
||||
'ja_JP.UTF-8',
|
||||
'ja_JP',
|
||||
'frontend',
|
||||
'Translated frontend ja_JP',
|
||||
],
|
||||
@@ -300,6 +317,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
// check setter 5-7
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'Original',
|
||||
// set new 8-10
|
||||
'en_US.UTF-8',
|
||||
@@ -309,6 +327,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
false,
|
||||
// check new setter 12-14
|
||||
'en_US.UTF-8',
|
||||
'en_US',
|
||||
'frontend',
|
||||
'Translated frontend en_US',
|
||||
]
|
||||
@@ -329,12 +348,14 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
* @param bool $load_error
|
||||
* @param string $original
|
||||
* @param string $locale_expected_a
|
||||
* @param string $locale_set_expected_a
|
||||
* @param string $domain_expected_a
|
||||
* @param string $translated_a
|
||||
* @param string|null $locale_new
|
||||
* @param string|null $domain_new
|
||||
* @param string|null $path_new
|
||||
* @param bool $load_error_new
|
||||
* @param string $locale_set_expected_b
|
||||
* @param string $locale_expected_b
|
||||
* @param string $domain_expected_b
|
||||
* @param string $translated_b
|
||||
@@ -351,6 +372,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
string $original,
|
||||
// 5-7
|
||||
string $locale_expected_a,
|
||||
string $locale_set_expected_a,
|
||||
string $domain_expected_a,
|
||||
string $translated_a,
|
||||
// 8-10
|
||||
@@ -361,8 +383,9 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
bool $load_error_new,
|
||||
// 12-14
|
||||
string $locale_expected_b,
|
||||
string $locale_set_expected_b,
|
||||
string $domain_expected_b,
|
||||
string $translated_b,
|
||||
string $translated_b
|
||||
): void {
|
||||
if ($locale === null) {
|
||||
$l10n = new \CoreLibs\Language\L10n();
|
||||
@@ -384,6 +407,10 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
$locale_expected_a,
|
||||
$l10n->getLocale(),
|
||||
'Locale init assert failed'
|
||||
);$this->assertEquals(
|
||||
$locale_set_expected_a,
|
||||
$l10n->getLocaleSet(),
|
||||
'Locale Set init assert failed'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$domain_expected_a,
|
||||
@@ -435,6 +462,11 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
$l10n->getLocale(),
|
||||
'Locale change assert failed'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$locale_set_expected_b,
|
||||
$l10n->getLocaleSet(),
|
||||
'Locale Set change assert failed'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$domain_expected_b,
|
||||
$l10n->getDomain(),
|
||||
@@ -731,7 +763,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
|
||||
string $type,
|
||||
string $var,
|
||||
string $value,
|
||||
string $expected,
|
||||
string $expected
|
||||
): void {
|
||||
switch ($type) {
|
||||
case 'global':
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace test;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class TemplateMethodsTest extends TestCase
|
||||
{
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
fwrite(STDOUT, __METHOD__ . "\n");
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
fwrite(STDOUT, __METHOD__ . "\n");
|
||||
}
|
||||
|
||||
protected function assertPreConditions(): void
|
||||
{
|
||||
fwrite(STDOUT, __METHOD__ . "\n");
|
||||
}
|
||||
|
||||
public function testOne(): void
|
||||
{
|
||||
fwrite(STDOUT, __METHOD__ . "\n");
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testTwo(): void
|
||||
{
|
||||
fwrite(STDOUT, __METHOD__ . "\n");
|
||||
$this->assertTrue(false);
|
||||
}
|
||||
|
||||
protected function assertPostConditions(): void
|
||||
{
|
||||
fwrite(STDOUT, __METHOD__ . "\n");
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
fwrite(STDOUT, __METHOD__ . "\n");
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass(): void
|
||||
{
|
||||
fwrite(STDOUT, __METHOD__ . "\n");
|
||||
}
|
||||
|
||||
protected function onNotSuccessfulTest(\Throwable $t): void
|
||||
{
|
||||
fwrite(STDOUT, __METHOD__ . "\n");
|
||||
throw $t;
|
||||
}
|
||||
}
|
||||
58
www/admin/class_test.config.direct.php
Normal file
58
www/admin/class_test.config.direct.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php // phpcs:ignore warning
|
||||
|
||||
/**
|
||||
* @phan-file-suppress PhanTypeSuspiciousStringExpression
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
$DEBUG_ALL_OVERRIDE = 0; // set to 1 to debug on live/remote server locations
|
||||
$DEBUG_ALL = 1;
|
||||
$PRINT_ALL = 1;
|
||||
$DB_DEBUG = 1;
|
||||
|
||||
if ($DEBUG_ALL) {
|
||||
error_reporting(E_ALL | E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR);
|
||||
}
|
||||
|
||||
ob_start();
|
||||
|
||||
// basic class test file
|
||||
define('USE_DATABASE', false);
|
||||
// sample config
|
||||
require '../configs/config.php';
|
||||
// define log file id
|
||||
$LOG_FILE_ID = 'classTest-config-direct';
|
||||
ob_end_flush();
|
||||
|
||||
$log = new CoreLibs\Debug\Logging([
|
||||
'log_folder' => BASE . LOG,
|
||||
'file_id' => $LOG_FILE_ID,
|
||||
// add file date
|
||||
'print_file_date' => true,
|
||||
// set debug and print flags
|
||||
'debug_all' => $DEBUG_ALL ?? false,
|
||||
'echo_all' => $ECHO_ALL ?? false,
|
||||
'print_all' => $PRINT_ALL ?? false,
|
||||
]);
|
||||
|
||||
print "<!DOCTYPE html>";
|
||||
print "<html><head><title>TEST CLASS: CONFIG DIRECT</title><head>";
|
||||
print "<body>";
|
||||
print '<div><a href="class_test.php">Class Test Master</a></div>';
|
||||
print '<div><b>CONFIG DIRECT</b></div>';
|
||||
|
||||
print "DIR: " . DIR . "<br>";
|
||||
print "BASE: " . BASE . "<br>";
|
||||
print "ROOT: " . ROOT . "<br>";
|
||||
print "BASE NAME: " . BASE_NAME . "<br>";
|
||||
echo "Config path prefix: " . $CONFIG_PATH_PREFIX . "<br>";
|
||||
print "DB Name: " . DB_CONFIG_NAME . "<br>";
|
||||
print "DB Config: " . \CoreLibs\Debug\Support::printAr(DB_CONFIG) . "<br>";
|
||||
|
||||
// error message
|
||||
print $log->printErrorMsg();
|
||||
|
||||
print "</body></html>";
|
||||
|
||||
// __END__
|
||||
58
www/admin/class_test.config.link.php
Normal file
58
www/admin/class_test.config.link.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php // phpcs:ignore warning
|
||||
|
||||
/**
|
||||
* @phan-file-suppress PhanTypeSuspiciousStringExpression
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
$DEBUG_ALL_OVERRIDE = 0; // set to 1 to debug on live/remote server locations
|
||||
$DEBUG_ALL = 1;
|
||||
$PRINT_ALL = 1;
|
||||
$DB_DEBUG = 1;
|
||||
|
||||
if ($DEBUG_ALL) {
|
||||
error_reporting(E_ALL | E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR);
|
||||
}
|
||||
|
||||
ob_start();
|
||||
|
||||
// basic class test file
|
||||
define('USE_DATABASE', false);
|
||||
// sample config
|
||||
require 'config.php';
|
||||
// define log file id
|
||||
$LOG_FILE_ID = 'classTest-config-link';
|
||||
ob_end_flush();
|
||||
|
||||
$log = new CoreLibs\Debug\Logging([
|
||||
'log_folder' => BASE . LOG,
|
||||
'file_id' => $LOG_FILE_ID,
|
||||
// add file date
|
||||
'print_file_date' => true,
|
||||
// set debug and print flags
|
||||
'debug_all' => $DEBUG_ALL ?? false,
|
||||
'echo_all' => $ECHO_ALL ?? false,
|
||||
'print_all' => $PRINT_ALL ?? false,
|
||||
]);
|
||||
|
||||
print "<!DOCTYPE html>";
|
||||
print "<html><head><title>TEST CLASS: CONFIG LINK</title><head>";
|
||||
print "<body>";
|
||||
print '<div><a href="class_test.php">Class Test Master</a></div>';
|
||||
print '<div><b>CONFIG LINK</b></div>';
|
||||
|
||||
print "DIR: " . DIR . "<br>";
|
||||
print "BASE: " . BASE . "<br>";
|
||||
print "ROOT: " . ROOT . "<br>";
|
||||
print "BASE NAME: " . BASE_NAME . "<br>";
|
||||
echo "Config path prefix: " . $CONFIG_PATH_PREFIX . "<br>";
|
||||
print "DB Name: " . DB_CONFIG_NAME . "<br>";
|
||||
print "DB Config: " . \CoreLibs\Debug\Support::printAr(DB_CONFIG) . "<br>";
|
||||
|
||||
// error message
|
||||
print $log->printErrorMsg();
|
||||
|
||||
print "</body></html>";
|
||||
|
||||
// __END__
|
||||
@@ -68,6 +68,9 @@ print "S::DEBUSTRING(s): " . DebugSupport::debugString('SET') . "<br>";
|
||||
print "S::DEBUSTRING(''): " . DebugSupport::debugString('') . "<br>";
|
||||
print "S::DEBUSTRING(,s): " . DebugSupport::debugString(null, '{-}') . "<br>";
|
||||
|
||||
// get test
|
||||
print "LOG FOLDER: " . $debug->getSetting('log_folder') . "<br>";
|
||||
|
||||
// debug
|
||||
print "C->DEBUG: " . $debug->debug('CLASS-TEST-DEBUG', 'Class Test Debug') . "<br>";
|
||||
print "C->DEBUG(html): " . $debug->debug('CLASS-TEST-DEBUG', 'HTML TAG<br><b>BOLD</b>') . "<br>";
|
||||
|
||||
61
www/admin/class_test.login.php
Normal file
61
www/admin/class_test.login.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php // phpcs:ignore warning
|
||||
|
||||
/**
|
||||
* @phan-file-suppress PhanTypeSuspiciousStringExpression
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
$DEBUG_ALL_OVERRIDE = 0; // set to 1 to debug on live/remote server locations
|
||||
$DEBUG_ALL = 1;
|
||||
$PRINT_ALL = 1;
|
||||
$DB_DEBUG = 1;
|
||||
|
||||
if ($DEBUG_ALL) {
|
||||
error_reporting(E_ALL | E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR);
|
||||
}
|
||||
|
||||
ob_start();
|
||||
|
||||
// basic class test file
|
||||
define('USE_DATABASE', false);
|
||||
// sample config
|
||||
require 'config.php';
|
||||
// set session name
|
||||
if (!defined('SET_SESSION_NAME')) {
|
||||
define('SET_SESSION_NAME', EDIT_SESSION_NAME);
|
||||
}
|
||||
// define log file id
|
||||
$LOG_FILE_ID = 'classTest-login';
|
||||
// init login & backend class
|
||||
$log = new CoreLibs\Debug\Logging([
|
||||
'log_folder' => BASE . LOG,
|
||||
'file_id' => $LOG_FILE_ID,
|
||||
// add file date
|
||||
'print_file_date' => true,
|
||||
// set debug and print flags
|
||||
'debug_all' => $DEBUG_ALL ?? false,
|
||||
'echo_all' => $ECHO_ALL ?? false,
|
||||
'print_all' => $PRINT_ALL ?? false,
|
||||
]);
|
||||
$db = new CoreLibs\DB\IO(DB_CONFIG, $log);
|
||||
$login = new CoreLibs\ACL\Login($db, $log);
|
||||
ob_end_flush();
|
||||
|
||||
print "<!DOCTYPE html>";
|
||||
print "<html><head><title>TEST CLASS: LOGIN</title><head>";
|
||||
print "<body>";
|
||||
print '<div><a href="class_test.php">Class Test Master</a></div>';
|
||||
|
||||
echo "CHECK PERMISSION: " . ($login->loginCheckPermissions() ? 'OK' : 'BAD') . "<br>";
|
||||
echo "IS ADMIN: " . ($login->loginIsAdmin() ? 'OK' : 'BAD') . "<br>";
|
||||
echo "MIN ACCESS BASE: " . ($login->loginCheckAccessBase('admin') ? 'OK' : 'BAD') . "<br>";
|
||||
echo "MIN ACCESS PAGE: " . ($login->loginCheckAccessPage('admin') ? 'OK' : 'BAD') . "<br>";
|
||||
|
||||
echo "ACL: " . \CoreLibs\Debug\Support::printAr($login->loginGetAcl()) . "<br>";
|
||||
echo "ACL (MIN): " . \CoreLibs\Debug\Support::printAr($login->loginGetAcl()['min']) . "<br>";
|
||||
|
||||
// error message
|
||||
print $log->printErrorMsg();
|
||||
|
||||
print "</body></html>";
|
||||
@@ -82,7 +82,11 @@ print '<div><a href="class_test.output.form.php">Class Test: OUTPUT FORM</a></di
|
||||
print '<div><a href="class_test.admin.backend.php">Class Test: BACKEND ADMIN CLASS</a></div>';
|
||||
print '<div><a href="class_test.lang.php">Class Test: LANG/L10n</a></div>';
|
||||
print '<div><a href="class_test.smarty.php">Class Test: SMARTY</a></div>';
|
||||
print '<div><a href="class_test.login.php">Class Test: LOGIN</a></div>';
|
||||
print '<div><a href="class_test.autoloader.php">Class Test: AUTOLOADER</a></div>';
|
||||
print '<div><a href="class_test.config.link.php">Class Test: CONFIG LINK</a></div>';
|
||||
print '<div><a href="class_test.config.direct.php">Class Test: CONFIG DIRECT</a></div>';
|
||||
print '<div><a href="subfolder/class_test.config.direct.php">Class Test: CONFIG DIRECT SUB</a></div>';
|
||||
|
||||
print "<hr>";
|
||||
print "L: " . CoreLibs\Debug\Support::printAr($locale) . "<br>";
|
||||
|
||||
58
www/admin/subfolder/class_test.config.direct.php
Normal file
58
www/admin/subfolder/class_test.config.direct.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php // phpcs:ignore warning
|
||||
|
||||
/**
|
||||
* @phan-file-suppress PhanTypeSuspiciousStringExpression
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
$DEBUG_ALL_OVERRIDE = 0; // set to 1 to debug on live/remote server locations
|
||||
$DEBUG_ALL = 1;
|
||||
$PRINT_ALL = 1;
|
||||
$DB_DEBUG = 1;
|
||||
|
||||
if ($DEBUG_ALL) {
|
||||
error_reporting(E_ALL | E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR);
|
||||
}
|
||||
|
||||
ob_start();
|
||||
|
||||
// basic class test file
|
||||
define('USE_DATABASE', false);
|
||||
// sample config
|
||||
require '../../configs/config.php';
|
||||
// define log file id
|
||||
$LOG_FILE_ID = 'classTest-config-direct';
|
||||
ob_end_flush();
|
||||
|
||||
$log = new CoreLibs\Debug\Logging([
|
||||
'log_folder' => BASE . LOG,
|
||||
'file_id' => $LOG_FILE_ID,
|
||||
// add file date
|
||||
'print_file_date' => true,
|
||||
// set debug and print flags
|
||||
'debug_all' => $DEBUG_ALL ?? false,
|
||||
'echo_all' => $ECHO_ALL ?? false,
|
||||
'print_all' => $PRINT_ALL ?? false,
|
||||
]);
|
||||
|
||||
print "<!DOCTYPE html>";
|
||||
print "<html><head><title>TEST CLASS: CONFIG DIRECT SUB</title><head>";
|
||||
print "<body>";
|
||||
print '<div><a href="../class_test.php">Class Test Master</a></div>';
|
||||
print '<div><b>CONFIG DIRECT SUB</b></div>';
|
||||
|
||||
print "DIR: " . DIR . "<br>";
|
||||
print "BASE: " . BASE . "<br>";
|
||||
print "ROOT: " . ROOT . "<br>";
|
||||
print "BASE NAME: " . BASE_NAME . "<br>";
|
||||
echo "Config path prefix: " . $CONFIG_PATH_PREFIX . "<br>";
|
||||
print "DB Name: " . DB_CONFIG_NAME . "<br>";
|
||||
print "DB Config: " . \CoreLibs\Debug\Support::printAr(DB_CONFIG) . "<br>";
|
||||
|
||||
// error message
|
||||
print $log->printErrorMsg();
|
||||
|
||||
print "</body></html>";
|
||||
|
||||
// __END__
|
||||
@@ -11,44 +11,56 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
define('CONFIG_PATH', 'configs' . DIRECTORY_SEPARATOR);
|
||||
// config path prefix search, start with 0, got down each level __DIR__ has, if nothing found -> bail
|
||||
// config path prefix search, start with 0, got down each level __DIR__ has,
|
||||
// if nothing found -> bail
|
||||
$CONFIG_PATH_PREFIX = '';
|
||||
// base path for loads
|
||||
$__DIR__PATH = __DIR__ . DIRECTORY_SEPARATOR;
|
||||
// don't load autoloader twice
|
||||
$end_autoload = false;
|
||||
for ($dir_pos = 0, $dir_max = count(explode(DIRECTORY_SEPARATOR, __DIR__)); $dir_pos <= $dir_max; $dir_pos++) {
|
||||
for (
|
||||
$dir_pos = 0, $dir_max = count(explode(DIRECTORY_SEPARATOR, __DIR__));
|
||||
$dir_pos <= $dir_max;
|
||||
$dir_pos++
|
||||
) {
|
||||
$CONFIG_PATH_PREFIX .= '..' . DIRECTORY_SEPARATOR;
|
||||
if ($end_autoload === false) {
|
||||
/************* AUTO LOADER *******************/
|
||||
// read auto loader for lib only
|
||||
// It is recommended to setup basic composer and use just one auto loader
|
||||
// if (is_file($CONFIG_PATH_PREFIX . 'lib' . DIRECTORY_SEPARATOR . 'autoloader.php')) {
|
||||
// require $CONFIG_PATH_PREFIX . 'lib' . DIRECTORY_SEPARATOR . 'autoloader.php';
|
||||
// $end_autoload = true;
|
||||
// }
|
||||
// composer auto loader, IF composer.json file includes classmap for lib/:
|
||||
// composer auto loader, in composer.json file add classmap for lib/:
|
||||
// "autoload": {
|
||||
// "classmap": [
|
||||
// "lib/"
|
||||
// ]
|
||||
// },
|
||||
// NOTE: MUST RUN composer dump-autoload if file/class names are changed or added
|
||||
// load auto loader
|
||||
if (is_file($CONFIG_PATH_PREFIX . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php')) {
|
||||
require $CONFIG_PATH_PREFIX . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
|
||||
// NOTE: MUST RUN composer dump-autoload if file/class names are
|
||||
// changed or new ones are added
|
||||
if (
|
||||
is_file(
|
||||
$__DIR__PATH . $CONFIG_PATH_PREFIX
|
||||
. 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'
|
||||
)
|
||||
) {
|
||||
require $__DIR__PATH . $CONFIG_PATH_PREFIX
|
||||
. 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
|
||||
$end_autoload = true;
|
||||
}
|
||||
// load enviorment file if it exists
|
||||
\CoreLibs\Get\ReadEnvFile::readEnvFile($CONFIG_PATH_PREFIX . CONFIG_PATH);
|
||||
}
|
||||
/************* MASTER CONFIG *******************/
|
||||
if (is_file($CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php')) {
|
||||
if (
|
||||
is_file($__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php')
|
||||
) {
|
||||
// load enviorment file if it exists
|
||||
\CoreLibs\Get\ReadEnvFile::readEnvFile(
|
||||
$__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH
|
||||
);
|
||||
// load master config file that loads all other config files
|
||||
require $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php';
|
||||
require $__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php';
|
||||
break;
|
||||
}
|
||||
}
|
||||
// fail if no base DIR is not set
|
||||
if (!defined('DIR')) {
|
||||
exit('Base config unloadable');
|
||||
exit('Base config could not be loaded');
|
||||
}
|
||||
// find trigger name "admin/" or "frontend/" in the getcwd() folder
|
||||
foreach (['admin', 'frontend'] as $folder) {
|
||||
|
||||
@@ -446,16 +446,15 @@ if ($form->my_page_name == 'edit_order') {
|
||||
$t_q = '';
|
||||
foreach ($output as $output_file) {
|
||||
// split the ouput into folder and file
|
||||
// eg ../admin/test.php is ../admin/ and test.php
|
||||
preg_match("/([\.\/\w]+\/)+(\w+\.\w{1,})$/", $output_file, $matches);
|
||||
// if named config.php, skip
|
||||
if ($matches[2] != 'config.php') {
|
||||
if ($t_q) {
|
||||
$t_q .= ', ';
|
||||
}
|
||||
$t_q .= "('" . $form->dbEscapeString($matches[1]) . "', '"
|
||||
. $form->dbEscapeString($matches[2]) . "')";
|
||||
$pathinfo = pathinfo($output_file);
|
||||
if (!empty($pathinfo['dirname'])) {
|
||||
$pathinfo['dirname'] .= DIRECTORY_SEPARATOR;
|
||||
}
|
||||
if ($t_q) {
|
||||
$t_q .= ', ';
|
||||
}
|
||||
$t_q .= "('" . $form->dbEscapeString($pathinfo['dirname']) . "', '"
|
||||
. $form->dbEscapeString($pathinfo['basename']) . "')";
|
||||
}
|
||||
$form->dbExec($q . $t_q, 'NULL');
|
||||
$elements[] = $form->formCreateElement('filename');
|
||||
|
||||
@@ -164,7 +164,9 @@ class Login
|
||||
public $l;
|
||||
|
||||
/**
|
||||
* constructor, does ALL, opens db, works through connection checks, closes itself
|
||||
* constructor, does ALL, opens db, works through connection checks,
|
||||
* finishes itself
|
||||
*
|
||||
* @param \CoreLibs\DB\IO $db Database connection class
|
||||
* @param \CoreLibs\Debug\Logging $log Logging class
|
||||
*/
|
||||
@@ -191,6 +193,7 @@ class Login
|
||||
// check if session exists and could be created
|
||||
// TODO: move session creation and check to outside?
|
||||
if (Session::startSession() === false) {
|
||||
$this->login_error = 1;
|
||||
echo '<b>Session not started or could not be started!</b><br>'
|
||||
. 'Use \'\CoreLibs\Create\Session::startSession();\'.<br>'
|
||||
. 'For less problems with other session, you can set a '
|
||||
@@ -200,12 +203,10 @@ class Login
|
||||
|
||||
// pre-check that password min/max lengths are inbetween 1 and 255;
|
||||
if ($this->password_max_length > 255) {
|
||||
echo '<b>Settings problem</b> PMaL<br>';
|
||||
exit;
|
||||
$this->password_max_length = 255;
|
||||
}
|
||||
if ($this->password_min_length < 1) {
|
||||
echo '<b>Settings problem</b> PMiL<br>';
|
||||
exit;
|
||||
$this->password_min_length = 1;
|
||||
}
|
||||
|
||||
// set global is ajax page for if we show the data directly,
|
||||
@@ -267,7 +268,8 @@ class Login
|
||||
// init default ACL list array
|
||||
$_SESSION['DEFAULT_ACL_LIST'] = [];
|
||||
// read the current edit_access_right list into an array
|
||||
$q = "SELECT level, type, name FROM edit_access_right WHERE level >= 0 ORDER BY level";
|
||||
$q = "SELECT level, type, name FROM edit_access_right "
|
||||
. "WHERE level >= 0 ORDER BY level";
|
||||
while (is_array($res = $this->db->dbReturn($q))) {
|
||||
// level to description format (numeric)
|
||||
$this->default_acl_list[$res['level']] = [
|
||||
@@ -286,7 +288,10 @@ class Login
|
||||
$this->loginLogoutUser();
|
||||
// ** LANGUAGE SET AFTER LOGIN **
|
||||
// set the locale
|
||||
if (Session::getSessionId() !== false && !empty($_SESSION['DEFAULT_LANG'])) {
|
||||
if (
|
||||
Session::getSessionId() !== false &&
|
||||
!empty($_SESSION['DEFAULT_LANG'])
|
||||
) {
|
||||
$locale = $_SESSION['DEFAULT_LOCALE'] ?? '';
|
||||
} else {
|
||||
$locale = defined('SITE_LOCALE') && !empty(SITE_LOCALE) ?
|
||||
@@ -314,7 +319,8 @@ class Login
|
||||
$this->login_html = $this->loginPrintLogin();
|
||||
// closing all connections, depending on error status, exit
|
||||
if (!$this->loginCloseClass()) {
|
||||
// if variable AJAX flag is not set, show output, else pass through for ajax work
|
||||
// if variable AJAX flag is not set, show output
|
||||
// else pass through for ajax work
|
||||
if ($this->login_is_ajax_page !== true) {
|
||||
// the login screen if we hav no login permission & login screen html data
|
||||
if ($this->login_html !== null) {
|
||||
@@ -360,8 +366,13 @@ class Login
|
||||
// NO OP
|
||||
}
|
||||
|
||||
// *************************************************************************
|
||||
// **** PRIVATE INTERNAL
|
||||
// *************************************************************************
|
||||
|
||||
/**
|
||||
* checks if password is valid, sets internal error login variable
|
||||
*
|
||||
* @param string $hash password hash
|
||||
* @param string $password submitted password
|
||||
* @return bool true or false on password ok or not
|
||||
@@ -418,7 +429,9 @@ class Login
|
||||
}
|
||||
|
||||
/**
|
||||
* if user pressed login button this script is called, but only if there is no preview euid set]
|
||||
* if user pressed login button this script is called,
|
||||
* but only if there is no preview euid set
|
||||
*
|
||||
* @return void has not return
|
||||
*/
|
||||
private function loginLoginUser(): void
|
||||
@@ -702,88 +715,6 @@ class Login
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* for every page the user access this script checks if he is allowed to do so
|
||||
* @return bool permission okay as true/false
|
||||
*/
|
||||
public function loginCheckPermissions(): bool
|
||||
{
|
||||
if ($this->euid && $this->login_error != 103) {
|
||||
$q = "SELECT filename "
|
||||
. "FROM edit_page ep, edit_page_access epa, edit_group eg, edit_user eu "
|
||||
. "WHERE ep.edit_page_id = epa.edit_page_id "
|
||||
. "AND eg.edit_group_id = epa.edit_group_id "
|
||||
. "AND eg.edit_group_id = eu.edit_group_id "
|
||||
. "AND eu.edit_user_id = " . $this->euid . " "
|
||||
. "AND filename = '" . $this->page_name . "' "
|
||||
. "AND eg.enabled = 1 AND epa.enabled = 1";
|
||||
$res = $this->db->dbReturnRow($q);
|
||||
if (!is_array($res)) {
|
||||
$this->login_error = 109;
|
||||
$this->permission_okay = false;
|
||||
return $this->permission_okay;
|
||||
}
|
||||
if (isset($res['filename']) && $res['filename'] == $this->page_name) {
|
||||
$this->permission_okay = true;
|
||||
} else {
|
||||
$this->login_error = 103;
|
||||
$this->permission_okay = false;
|
||||
}
|
||||
}
|
||||
// if called from public, so we can check if the permissions are ok
|
||||
return $this->permission_okay;
|
||||
}
|
||||
|
||||
/**
|
||||
* if a user pressed on logout, destroyes session and unsets all global vars
|
||||
* @return void has no return
|
||||
*/
|
||||
public function loginLogoutUser(): void
|
||||
{
|
||||
// must be either logout or error
|
||||
if (!$this->logout && !$this->login_error) {
|
||||
return;
|
||||
}
|
||||
// unregister and destroy session vars
|
||||
foreach (
|
||||
// TODO move this into some global array for easier update
|
||||
[
|
||||
'ADMIN',
|
||||
'BASE_ACL_LEVEL',
|
||||
'DB_DEBUG',
|
||||
'DEBUG_ALL',
|
||||
'DEFAULT_ACL_LIST',
|
||||
'DEFAULT_CHARSET',
|
||||
'DEFAULT_LANG',
|
||||
'DEFAULT_LOCALE',
|
||||
'EAID',
|
||||
'EUID',
|
||||
'GROUP_ACL_LEVEL',
|
||||
'GROUP_ACL_TYPE',
|
||||
'GROUP_NAME',
|
||||
'HEADER_COLOR',
|
||||
'LANG',
|
||||
'PAGES_ACL_LEVEL',
|
||||
'PAGES',
|
||||
'TEMPLATE',
|
||||
'UNIT_ACL_LEVEL',
|
||||
'UNIT_DEFAULT',
|
||||
'UNIT',
|
||||
'USER_ACL_LEVEL',
|
||||
'USER_ACL_TYPE',
|
||||
'USER_NAME',
|
||||
] as $session_var
|
||||
) {
|
||||
unset($_SESSION[$session_var]);
|
||||
}
|
||||
// final unset all
|
||||
session_unset();
|
||||
// final destroy session
|
||||
session_destroy();
|
||||
// then prints the login screen again
|
||||
$this->permission_okay = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets all the basic ACLs
|
||||
* init set the basic acl the user has, based on the following rules
|
||||
@@ -799,6 +730,7 @@ class Login
|
||||
* - if an account ACL is set, set this parallel, account ACL overrides user ACL if it applies
|
||||
* - if edit access ACL level is set, use this, else use page
|
||||
* set all base ACL levels as a list keyword -> ACL number
|
||||
*
|
||||
* @return void has no return
|
||||
*/
|
||||
private function loginSetAcl(): void
|
||||
@@ -837,10 +769,10 @@ class Login
|
||||
$_SESSION['BASE_ACL_LEVEL'] = $this->acl['base'];
|
||||
|
||||
// set the current page acl
|
||||
// start with default acl
|
||||
// start with base acl
|
||||
// set group if not -1, overrides default
|
||||
// set page if not -1, overrides group set
|
||||
$this->acl['page'] = DEFAULT_ACL_LEVEL;
|
||||
$this->acl['page'] = $this->acl['base'];
|
||||
if ($_SESSION['GROUP_ACL_LEVEL'] != -1) {
|
||||
$this->acl['page'] = $_SESSION['GROUP_ACL_LEVEL'];
|
||||
}
|
||||
@@ -885,37 +817,44 @@ class Login
|
||||
$this->acl['show_ea_extra'] = false;
|
||||
}
|
||||
// set the default edit access
|
||||
$this->acl['default_edit_access'] = $_SESSION['UNIT_DEFAULT'];
|
||||
$this->acl['default_edit_access'] = $_SESSION['UNIT_DEFAULT'] ?? null;
|
||||
// integrate the type acl list, but only for the keyword -> level
|
||||
foreach ($this->default_acl_list as $level => $data) {
|
||||
$this->acl['min'][$data['type']] = $level;
|
||||
}
|
||||
// set the full acl list too
|
||||
$this->acl['acl_list'] = $_SESSION['DEFAULT_ACL_LIST'];
|
||||
$this->acl['acl_list'] = $_SESSION['DEFAULT_ACL_LIST'] ?? [];
|
||||
// debug
|
||||
// $this->debug('ACL', $this->print_ar($this->acl));
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if this edit access id is valid
|
||||
* @param int|null $edit_access_id access id pk to check
|
||||
* @return bool true/false: if the edit access is not
|
||||
* in the valid list: false
|
||||
* Check if source (page, base) is matching to the given min access string
|
||||
* min access string must be valid access level string (eg read, mod, write)
|
||||
* This does not take in account admin flag set
|
||||
*
|
||||
* @param string $source a valid base level string eg base, page
|
||||
* @param string $min_access a valid min level string, eg read, mod, siteadmin
|
||||
* @return bool True for valid access, False for invalid
|
||||
*/
|
||||
public function loginCheckEditAccess($edit_access_id): bool
|
||||
public function loginCheckAccess(string $source, string $min_access): bool
|
||||
{
|
||||
if ($edit_access_id === null) {
|
||||
$source = 'base';
|
||||
if (
|
||||
empty($this->acl['min'][$min_access]) ||
|
||||
empty($this->acl[$source])
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (array_key_exists($edit_access_id, $this->acl['unit'])) {
|
||||
if ($this->acl[$source] >= $this->acl['min'][$min_access]) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if the password is in a valid format
|
||||
*
|
||||
* @param string $password the new password
|
||||
* @return bool true or false if valid password or not
|
||||
*/
|
||||
@@ -939,6 +878,7 @@ class Login
|
||||
|
||||
/**
|
||||
* dummy declare for password forget
|
||||
*
|
||||
* @return void has no return
|
||||
*/
|
||||
private function loginPasswordForgot(): void
|
||||
@@ -946,25 +886,9 @@ class Login
|
||||
// will do some password recovert, eg send email
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the minium length and checks on valid
|
||||
* @param int $length set the minimum length
|
||||
* @return bool true/false on success
|
||||
*/
|
||||
public function loginSetPasswordMinLength(int $length): bool
|
||||
{
|
||||
// check that numeric, positive numeric, not longer than max input string lenght
|
||||
// and not short than min password length
|
||||
if (is_numeric($length) && $length >= PASSWORD_MIN_LENGTH && $length <= $this->password_max_length) {
|
||||
$this->password_min_length = $length;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* changes a user password
|
||||
*
|
||||
* @return void has no return
|
||||
*/
|
||||
private function loginPasswordChange(): void
|
||||
@@ -1065,6 +989,7 @@ class Login
|
||||
|
||||
/**
|
||||
* prints out login html part if no permission (error) is set
|
||||
*
|
||||
* @return string|null html data for login page, or null for nothing
|
||||
*/
|
||||
private function loginPrintLogin()
|
||||
@@ -1170,6 +1095,7 @@ class Login
|
||||
/**
|
||||
* last function called, writes log and prints out error msg and
|
||||
* exists script if permission 0
|
||||
*
|
||||
* @return bool true on permission ok, false on permission wrong
|
||||
*/
|
||||
private function loginCloseClass(): bool
|
||||
@@ -1208,6 +1134,7 @@ class Login
|
||||
|
||||
/**
|
||||
* checks if there are external templates, if not uses internal fallback ones
|
||||
*
|
||||
* @return void has no return
|
||||
*/
|
||||
private function loginSetTemplates(): void
|
||||
@@ -1389,6 +1316,7 @@ EOM;
|
||||
|
||||
/**
|
||||
* writes detailed data into the edit user log table (keep log what user does)
|
||||
*
|
||||
* @param string $event string of what has been done
|
||||
* @param string $data data information (id, etc)
|
||||
* @param string|int $error error id (mostly an int)
|
||||
@@ -1449,11 +1377,190 @@ EOM;
|
||||
$this->db->dbExec($q, 'NULL');
|
||||
}
|
||||
|
||||
// *************************************************************************
|
||||
// **** PUBLIC INTERNAL
|
||||
// *************************************************************************
|
||||
|
||||
/**
|
||||
* sets the minium length and checks on valid
|
||||
*
|
||||
* @param int $length set the minimum length
|
||||
* @return bool true/false on success
|
||||
*/
|
||||
public function loginSetPasswordMinLength(int $length): bool
|
||||
{
|
||||
// check that numeric, positive numeric, not longer than max input string lenght
|
||||
// and not short than min password length
|
||||
if (is_numeric($length) && $length >= PASSWORD_MIN_LENGTH && $length <= $this->password_max_length) {
|
||||
$this->password_min_length = $length;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* if a user pressed on logout, destroyes session and unsets all global vars
|
||||
*
|
||||
* @return void has no return
|
||||
*/
|
||||
public function loginLogoutUser(): void
|
||||
{
|
||||
// must be either logout or error
|
||||
if (!$this->logout && !$this->login_error) {
|
||||
return;
|
||||
}
|
||||
// unregister and destroy session vars
|
||||
foreach (
|
||||
// TODO move this into some global array for easier update
|
||||
[
|
||||
'ADMIN',
|
||||
'BASE_ACL_LEVEL',
|
||||
'DB_DEBUG',
|
||||
'DEBUG_ALL',
|
||||
'DEFAULT_ACL_LIST',
|
||||
'DEFAULT_CHARSET',
|
||||
'DEFAULT_LANG',
|
||||
'DEFAULT_LOCALE',
|
||||
'EAID',
|
||||
'EUID',
|
||||
'GROUP_ACL_LEVEL',
|
||||
'GROUP_ACL_TYPE',
|
||||
'GROUP_NAME',
|
||||
'HEADER_COLOR',
|
||||
'LANG',
|
||||
'PAGES_ACL_LEVEL',
|
||||
'PAGES',
|
||||
'TEMPLATE',
|
||||
'UNIT_ACL_LEVEL',
|
||||
'UNIT_DEFAULT',
|
||||
'UNIT',
|
||||
'USER_ACL_LEVEL',
|
||||
'USER_ACL_TYPE',
|
||||
'USER_NAME',
|
||||
] as $session_var
|
||||
) {
|
||||
unset($_SESSION[$session_var]);
|
||||
}
|
||||
// final unset all
|
||||
session_unset();
|
||||
// final destroy session
|
||||
session_destroy();
|
||||
// then prints the login screen again
|
||||
$this->permission_okay = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* for every page the user access this script checks if he is allowed to do so
|
||||
*
|
||||
* @return bool permission okay as true/false
|
||||
*/
|
||||
public function loginCheckPermissions(): bool
|
||||
{
|
||||
// start with not allowed
|
||||
$this->permission_okay = false;
|
||||
// bail for no euid (no login)
|
||||
if (!$this->euid) {
|
||||
return $this->permission_okay;
|
||||
}
|
||||
// bail for previous wrong page match, eg if method is called twice
|
||||
if ($this->login_error == 103) {
|
||||
return $this->permission_okay;
|
||||
}
|
||||
// if ($this->euid && $this->login_error != 103) {
|
||||
$q = "SELECT filename "
|
||||
. "FROM edit_page ep, edit_page_access epa, edit_group eg, edit_user eu "
|
||||
. "WHERE ep.edit_page_id = epa.edit_page_id "
|
||||
. "AND eg.edit_group_id = epa.edit_group_id "
|
||||
. "AND eg.edit_group_id = eu.edit_group_id "
|
||||
. "AND eu.edit_user_id = " . $this->euid . " "
|
||||
. "AND filename = '" . $this->page_name . "' "
|
||||
. "AND eg.enabled = 1 AND epa.enabled = 1";
|
||||
$res = $this->db->dbReturnRow($q);
|
||||
if (!is_array($res)) {
|
||||
$this->login_error = 109;
|
||||
return $this->permission_okay;
|
||||
}
|
||||
if (isset($res['filename']) && $res['filename'] == $this->page_name) {
|
||||
$this->permission_okay = true;
|
||||
} else {
|
||||
$this->login_error = 103;
|
||||
}
|
||||
// if called from public, so we can check if the permissions are ok
|
||||
return $this->permission_okay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return ACL array as is
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function loginGetAcl(): array
|
||||
{
|
||||
return $this->acl;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if this edit access id is valid
|
||||
*
|
||||
* @param int|null $edit_access_id access id pk to check
|
||||
* @return bool true/false: if the edit access is not
|
||||
* in the valid list: false
|
||||
*/
|
||||
public function loginCheckEditAccess($edit_access_id): bool
|
||||
{
|
||||
if ($edit_access_id === null) {
|
||||
return false;
|
||||
}
|
||||
if (array_key_exists($edit_access_id, $this->acl['unit'])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if admin flag is set
|
||||
*
|
||||
* @return bool True if admin flag set
|
||||
*/
|
||||
public function loginIsAdmin(): bool
|
||||
{
|
||||
if (!empty($this->acl['admin'])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if min accesss string (eg, read, mod, etc) is matchable
|
||||
* EQUAL to BASE set right
|
||||
*
|
||||
* @param string $min_access
|
||||
* @return bool
|
||||
*/
|
||||
public function loginCheckAccessBase(string $min_access): bool
|
||||
{
|
||||
return $this->loginCheckAccess('base', $min_access);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if min accesss string (eg, read, mod, etc) is matchable
|
||||
* EQUAL to PAGE set right
|
||||
*
|
||||
* @param string $min_access
|
||||
* @return bool
|
||||
*/
|
||||
public function loginCheckAccessPage(string $min_access): bool
|
||||
{
|
||||
return $this->loginCheckAccess('page', $min_access);
|
||||
}
|
||||
|
||||
/**
|
||||
* checks that the given edit access id is valid for this user
|
||||
*
|
||||
* @param int|null $edit_access_id edit access id to check
|
||||
* @return int|null same edit access id if ok
|
||||
* or the default edit access id if given one is not valid
|
||||
* or the default edit access id
|
||||
* if given one is not valid
|
||||
*/
|
||||
public function loginCheckEditAccessId(?int $edit_access_id): ?int
|
||||
{
|
||||
@@ -1463,15 +1570,15 @@ EOM;
|
||||
is_array($_SESSION['UNIT']) &&
|
||||
!array_key_exists($edit_access_id, $_SESSION['UNIT'])
|
||||
) {
|
||||
return (int)$_SESSION['UNIT_DEFAULT'];
|
||||
} else {
|
||||
return $edit_access_id;
|
||||
return $_SESSION['UNIT_DEFAULT'] ?? null;
|
||||
}
|
||||
return $edit_access_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* retunrn a set entry from the UNIT session for an edit access_id
|
||||
* if not found return false
|
||||
*
|
||||
* @param int $edit_access_id edit access id
|
||||
* @param string|int $data_key key value to search for
|
||||
* @return bool|string false for not found or string for found data
|
||||
@@ -1480,9 +1587,8 @@ EOM;
|
||||
{
|
||||
if (!isset($_SESSION['UNIT'][$edit_access_id]['data'][$data_key])) {
|
||||
return false;
|
||||
} else {
|
||||
return $_SESSION['UNIT'][$edit_access_id]['data'][$data_key];
|
||||
}
|
||||
return $_SESSION['UNIT'][$edit_access_id]['data'][$data_key];
|
||||
}
|
||||
// close class
|
||||
}
|
||||
|
||||
@@ -85,11 +85,13 @@ class Basic
|
||||
* main Basic constructor to init and check base settings
|
||||
* @param \CoreLibs\Debug\Logging|null $log Logging class
|
||||
* @param string|null $session_name Set session name
|
||||
* @deprecated DO NOT USE Class\Basic anymore. Use dedicated logger and sub classes
|
||||
*/
|
||||
public function __construct(
|
||||
\CoreLibs\Debug\Logging $log = null,
|
||||
?string $session_name = null
|
||||
) {
|
||||
trigger_error('Class \CoreLibs\Basic is deprected', E_USER_DEPRECATED);
|
||||
// TODO make check dynamic for entries we MUST have depending on load type
|
||||
// before we start any work, we should check that all MUST constants are defined
|
||||
$abort = false;
|
||||
|
||||
@@ -20,7 +20,7 @@ class DateTime
|
||||
4 => 'Thu',
|
||||
5 => 'Fri',
|
||||
6 => 'Sat',
|
||||
7 => 'Sun'
|
||||
7 => 'Sun',
|
||||
];
|
||||
/** @var array<int,string> */
|
||||
public const DAY_LONG = [
|
||||
@@ -30,7 +30,7 @@ class DateTime
|
||||
4 => 'Thursday',
|
||||
5 => 'Friday',
|
||||
6 => 'Saturday',
|
||||
7 => 'Sunday'
|
||||
7 => 'Sunday',
|
||||
];
|
||||
/** @var array<int,string> */
|
||||
public const MONTH_LONG = [
|
||||
@@ -45,7 +45,7 @@ class DateTime
|
||||
9 => 'September',
|
||||
10 => 'October',
|
||||
11 => 'November',
|
||||
12 => 'December'
|
||||
12 => 'December',
|
||||
];
|
||||
/** @var array<int,string> */
|
||||
public const MONTH_SHORT = [
|
||||
@@ -60,7 +60,7 @@ class DateTime
|
||||
9 => 'Sep',
|
||||
10 => 'Oct',
|
||||
11 => 'Nov',
|
||||
12 => 'Dec'
|
||||
12 => 'Dec',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -349,7 +349,7 @@ class DateTime
|
||||
try {
|
||||
$start = new \DateTime($start_date);
|
||||
$end = new \DateTime($end_date);
|
||||
} catch (Exception) {
|
||||
} catch (Exception $e) {
|
||||
if ($return_named === true) {
|
||||
return [
|
||||
'overall' => 0,
|
||||
|
||||
@@ -43,7 +43,7 @@ class ArrayIO extends \CoreLibs\DB\IO
|
||||
/** @var string */
|
||||
public $table_name; // the table_name
|
||||
/** @var string */
|
||||
public $pk_name; // the primary key from this table
|
||||
public $pk_name = ''; // the primary key from this table
|
||||
/** @var int|string|null */
|
||||
public $pk_id; // the PK id
|
||||
|
||||
@@ -503,7 +503,7 @@ class ArrayIO extends \CoreLibs\DB\IO
|
||||
// max id, falls INSERT
|
||||
$q = 'SELECT MAX(' . $this->pk_name . ') + 1 AS pk_id FROM ' . $this->table_name;
|
||||
if (is_array($res = $this->dbReturnRow($q))) {
|
||||
$pk_id = $res['pkd_id'];
|
||||
$pk_id = $res['pk_id'];
|
||||
} else {
|
||||
$pk_id = 1;
|
||||
}
|
||||
|
||||
@@ -401,10 +401,10 @@ class Logging
|
||||
|
||||
/**
|
||||
* Temporary method to read all class variables for testing purpose
|
||||
* @param string $name
|
||||
* @return mixed can be anything, bool, string, int, array
|
||||
* @param string $name what variable to return
|
||||
* @return mixed can be anything, bool, string, int, array
|
||||
*/
|
||||
public function getSetting(string $name): mixed
|
||||
public function getSetting(string $name) //:mixed DOES not work with PHP 7.4
|
||||
{
|
||||
// for debug purpose only
|
||||
return $this->{$name};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Language\Encoding::__mbMimeEncode -> Convert\MimeEncode::__mbMimeEncode
|
||||
* Langauge\Encoding::checkConvertEncoding -> Check\Encoding::checkConvertEncoding
|
||||
* Langauge\Encoding::setErrorChar -> Check\Encoding::setErrorChar
|
||||
* Langauge\Encoding::getErrorChar -> Encoding::getErrorChar
|
||||
* Langauge\Encoding::getErrorChar -> Check\Encoding::getErrorChar
|
||||
* Langauge\Encoding::convertEncoding -> Convert\Encoding::convertEncoding
|
||||
*/
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ class L10n
|
||||
{
|
||||
/** @var string the current locale */
|
||||
private $locale = '';
|
||||
/** @var string the SET locale as WHERE the domain file is */
|
||||
private $locale_set = '';
|
||||
/** @var string the default selected/active domain */
|
||||
private $domain = '';
|
||||
/** @var array<string,array<string,GetTextReader>> locale > domain = translator */
|
||||
@@ -77,7 +79,7 @@ class L10n
|
||||
public function __construct(
|
||||
string $locale = '',
|
||||
string $domain = '',
|
||||
string $path = '',
|
||||
string $path = ''
|
||||
) {
|
||||
// auto load language only if at least locale and domain is set
|
||||
if (!empty($locale) && !empty($domain)) {
|
||||
@@ -141,6 +143,7 @@ class L10n
|
||||
// store old settings
|
||||
$old_mofile = $this->mofile;
|
||||
$old_lang = $this->locale;
|
||||
$old_lang_set = $this->locale_set;
|
||||
$old_domain = $this->domain;
|
||||
$old_base_locale_path = $this->base_locale_path;
|
||||
$old_base_content_path = $this->base_content_path;
|
||||
@@ -172,6 +175,7 @@ class L10n
|
||||
. $this->base_content_path
|
||||
. $domain . '.mo';
|
||||
if (file_exists($this->mofile)) {
|
||||
$this->locale_set = $_locale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -202,6 +206,7 @@ class L10n
|
||||
// else fall back to the old ones
|
||||
$this->mofile = $old_mofile;
|
||||
$this->locale = $old_lang;
|
||||
$this->locale_set = $old_lang_set;
|
||||
$this->domain = $old_domain;
|
||||
$this->base_locale_path = $old_base_locale_path;
|
||||
$this->base_content_path = $old_base_content_path;
|
||||
@@ -454,7 +459,7 @@ class L10n
|
||||
}
|
||||
|
||||
/**
|
||||
* get current set locale
|
||||
* get current set locale (want locale)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -463,6 +468,16 @@ class L10n
|
||||
return $this->locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* current set locale where mo file is located
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocaleSet(): string
|
||||
{
|
||||
return $this->locale_set;
|
||||
}
|
||||
|
||||
/**
|
||||
* get current set language
|
||||
*
|
||||
|
||||
@@ -32,6 +32,8 @@ class SmartyExtend extends \Smarty
|
||||
/** @var string */
|
||||
public $lang;
|
||||
/** @var string */
|
||||
public $locale_set;
|
||||
/** @var string */
|
||||
public $lang_short;
|
||||
/** @var string */
|
||||
public $domain;
|
||||
@@ -170,6 +172,7 @@ class SmartyExtend extends \Smarty
|
||||
// get first part from lang
|
||||
$this->lang_short = explode('_', $locale['lang'])[0];
|
||||
$this->domain = $this->l10n->getDomain();
|
||||
$this->locale_set = $this->l10n->getLocaleSet();
|
||||
$this->lang_dir = $this->l10n->getBaseLocalePath();
|
||||
|
||||
// opt load functions so we can use legacy init for smarty run perhaps
|
||||
@@ -312,16 +315,24 @@ class SmartyExtend extends \Smarty
|
||||
}
|
||||
// javascript translate data as template for auto translate
|
||||
if (empty($this->TEMPLATE_TRANSLATE)) {
|
||||
$this->TEMPLATE_TRANSLATE = 'jsTranslate_' . $this->lang . '.tpl';
|
||||
$this->TEMPLATE_TRANSLATE = 'jsTranslate_'
|
||||
. $this->locale_set . '.' . $this->encoding
|
||||
. '.tpl';
|
||||
} else {
|
||||
// we assume we have some fixed set
|
||||
// we must add _<$this->lang>
|
||||
// if .tpl, put before .tpl
|
||||
// if not .tpl, add _<$this->lang>.tpl
|
||||
if (strpos($this->TEMPLATE_TRANSLATE, '.tpl')) {
|
||||
$this->TEMPLATE_TRANSLATE = str_replace('.tpl', '_' . $this->lang . '.tpl', $this->TEMPLATE_TRANSLATE);
|
||||
$this->TEMPLATE_TRANSLATE = str_replace(
|
||||
'.tpl',
|
||||
'-' . $this->locale_set . '.' . $this->encoding . '.tpl',
|
||||
$this->TEMPLATE_TRANSLATE
|
||||
);
|
||||
} else {
|
||||
$this->TEMPLATE_TRANSLATE .= '_' . $this->lang . '.tpl';
|
||||
$this->TEMPLATE_TRANSLATE .= '_'
|
||||
. $this->locale_set . '.' . $this->encoding
|
||||
. '.tpl';
|
||||
}
|
||||
}
|
||||
// if we can't find it, dump it
|
||||
|
||||
Reference in New Issue
Block a user