Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1bb4d5f426 | |||
| a65485e56a | |||
| 5e6ba85639 | |||
| 3cf891a7d2 | |||
| 6e19f30ff5 | |||
| 95079885c5 | |||
| 14dab54f2c | |||
| 180fba596a | |||
| 69e2503a36 | |||
| c06ae55919 | |||
| 6098d1091a | |||
| 2a8038835f | |||
| 984dec37e2 | |||
| d91fbd5a46 |
@@ -1 +1 @@
|
|||||||
9.17.0
|
9.17.6.1
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace CoreLibs\Admin;
|
namespace CoreLibs\Admin;
|
||||||
|
|
||||||
|
use CoreLibs\Convert\Json;
|
||||||
|
|
||||||
class Backend
|
class Backend
|
||||||
{
|
{
|
||||||
// page name
|
// page name
|
||||||
@@ -42,7 +44,7 @@ class Backend
|
|||||||
/** @var array<string> */
|
/** @var array<string> */
|
||||||
public array $action_list = [
|
public array $action_list = [
|
||||||
'action', 'action_id', 'action_sub_id', 'action_yes', 'action_flag',
|
'action', 'action_id', 'action_sub_id', 'action_yes', 'action_flag',
|
||||||
'action_menu', 'action_value', 'action_error', 'action_loaded'
|
'action_menu', 'action_value', 'action_type', 'action_error', 'action_loaded'
|
||||||
];
|
];
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public string $action;
|
public string $action;
|
||||||
@@ -61,20 +63,31 @@ class Backend
|
|||||||
/** @var string */
|
/** @var string */
|
||||||
public string $action_value;
|
public string $action_value;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
|
public string $action_type;
|
||||||
|
/** @var string */
|
||||||
public string $action_error;
|
public string $action_error;
|
||||||
|
|
||||||
// ACL array variable if we want to set acl data from outisde
|
// ACL array variable if we want to set acl data from outisde
|
||||||
/** @var array<mixed> */
|
/** @var array<mixed> */
|
||||||
public array $acl = [];
|
public array $acl = [];
|
||||||
/** @var int */
|
/** @var int */
|
||||||
public int $default_acl;
|
public int $default_acl;
|
||||||
|
|
||||||
// queue key
|
// queue key
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public string $queue_key;
|
public string $queue_key;
|
||||||
|
|
||||||
|
/** @var array<string> list of allowed types for edit log write */
|
||||||
|
private const WRITE_TYPES = ['BINARY', 'BZIP2', 'LZIP', 'STRING', 'SERIAL', 'JSON'];
|
||||||
|
/** @var array<string> list of available write types for log */
|
||||||
|
private array $write_types_available = [];
|
||||||
|
|
||||||
// the current active edit access id
|
// the current active edit access id
|
||||||
/** @var int|null */
|
/** @var int|null */
|
||||||
public int|null $edit_access_id;
|
public int|null $edit_access_id;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public string $page_name;
|
public string $page_name;
|
||||||
|
|
||||||
// error/warning/info messages
|
// error/warning/info messages
|
||||||
/** @var array<mixed> */
|
/** @var array<mixed> */
|
||||||
public array $messages = [];
|
public array $messages = [];
|
||||||
@@ -84,6 +97,7 @@ class Backend
|
|||||||
public bool $warning = false;
|
public bool $warning = false;
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
public bool $info = false;
|
public bool $info = false;
|
||||||
|
|
||||||
// internal lang & encoding vars
|
// internal lang & encoding vars
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public string $lang_dir = '';
|
public string $lang_dir = '';
|
||||||
@@ -95,6 +109,7 @@ class Backend
|
|||||||
public string $domain;
|
public string $domain;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public string $encoding;
|
public string $encoding;
|
||||||
|
|
||||||
/** @var \CoreLibs\Logging\Logging logger */
|
/** @var \CoreLibs\Logging\Logging logger */
|
||||||
public \CoreLibs\Logging\Logging $log;
|
public \CoreLibs\Logging\Logging $log;
|
||||||
/** @var \CoreLibs\DB\IO database */
|
/** @var \CoreLibs\DB\IO database */
|
||||||
@@ -103,6 +118,7 @@ class Backend
|
|||||||
public \CoreLibs\Language\L10n $l;
|
public \CoreLibs\Language\L10n $l;
|
||||||
/** @var \CoreLibs\Create\Session session class */
|
/** @var \CoreLibs\Create\Session session class */
|
||||||
public \CoreLibs\Create\Session $session;
|
public \CoreLibs\Create\Session $session;
|
||||||
|
|
||||||
// smarty publics [end processing in smarty class]
|
// smarty publics [end processing in smarty class]
|
||||||
/** @var array<mixed> */
|
/** @var array<mixed> */
|
||||||
public array $DATA = [];
|
public array $DATA = [];
|
||||||
@@ -172,9 +188,12 @@ class Backend
|
|||||||
}
|
}
|
||||||
|
|
||||||
// queue key
|
// queue key
|
||||||
if (preg_match("/^(add|save|delete|remove|move|up|down|push_live)$/", $this->action)) {
|
if (preg_match("/^(add|save|delete|remove|move|up|down|push_live)$/", $this->action ?? '')) {
|
||||||
$this->queue_key = \CoreLibs\Create\RandomKey::randomKeyGen(3);
|
$this->queue_key = \CoreLibs\Create\RandomKey::randomKeyGen(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check what edit log data write types are allowed
|
||||||
|
$this->adbSetEditLogWriteTypeAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -185,7 +204,26 @@ class Backend
|
|||||||
// NO OP
|
// NO OP
|
||||||
}
|
}
|
||||||
|
|
||||||
// PUBLIC METHODS |=================================================>
|
// MARK: PRIVATE METHODS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the write types that are allowed
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function adbSetEditLogWriteTypeAvailable()
|
||||||
|
{
|
||||||
|
// check what edit log data write types are allowed
|
||||||
|
$this->write_types_available = self::WRITE_TYPES;
|
||||||
|
if (!function_exists('bzcompress')) {
|
||||||
|
$this->write_types_available = array_diff($this->write_types_available, ['BINARY', 'BZIP']);
|
||||||
|
}
|
||||||
|
if (!function_exists('gzcompress')) {
|
||||||
|
$this->write_types_available = array_diff($this->write_types_available, ['LZIP']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: PUBLIC METHODS |=================================================>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set internal ACL from login ACL
|
* set internal ACL from login ACL
|
||||||
@@ -223,27 +261,69 @@ class Backend
|
|||||||
/**
|
/**
|
||||||
* writes all action vars plus other info into edit_log table
|
* writes all action vars plus other info into edit_log table
|
||||||
*
|
*
|
||||||
* @param string $event any kind of event description,
|
* @param string $event [default=''] any kind of event description,
|
||||||
* @param string|array<mixed> $data any kind of data related to that event
|
* @param string|array<mixed> $data [default=''] any kind of data related to that event
|
||||||
* @param string $write_type write type can bei STRING or BINARY
|
* @param string $write_type [default=JSON] write type can be
|
||||||
* @param string|null $db_schema override target schema
|
* JSON, STRING/SERIEAL, BINARY/BZIP or ZLIB
|
||||||
|
* @param string|null $db_schema [default=null] override target schema
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function adbEditLog(
|
public function adbEditLog(
|
||||||
string $event = '',
|
string $event = '',
|
||||||
string|array $data = '',
|
string|array $data = '',
|
||||||
string $write_type = 'STRING',
|
string $write_type = 'JSON',
|
||||||
?string $db_schema = null
|
?string $db_schema = null
|
||||||
): void {
|
): void {
|
||||||
$data_binary = '';
|
$data_binary = '';
|
||||||
$data_write = '';
|
$data_write = '';
|
||||||
if ($write_type == 'BINARY') {
|
// check if write type is valid, if not fallback to JSON
|
||||||
$data_binary = $this->db->dbEscapeBytea((string)bzcompress(serialize($data)));
|
if (!in_array($write_type, $this->write_types_available)) {
|
||||||
$data_write = 'see bzip compressed data_binary field';
|
$this->log->warning('Write type not in allowed array, fallback to JSON', context:[
|
||||||
|
"write_type" => $write_type,
|
||||||
|
"write_list" => $this->write_types_available,
|
||||||
|
]);
|
||||||
|
$write_type = 'JSON';
|
||||||
}
|
}
|
||||||
if ($write_type == 'STRING') {
|
switch ($write_type) {
|
||||||
$data_binary = '';
|
case 'BINARY':
|
||||||
$data_write = $this->db->dbEscapeString(serialize($data));
|
case 'BZIP':
|
||||||
|
$data_binary = $this->db->dbEscapeBytea((string)bzcompress(serialize($data)));
|
||||||
|
$data_write = Json::jsonConvertArrayTo([
|
||||||
|
'type' => 'BZIP',
|
||||||
|
'message' => 'see bzip compressed data_binary field'
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case 'ZLIB':
|
||||||
|
$data_binary = $this->db->dbEscapeBytea((string)gzcompress(serialize($data)));
|
||||||
|
$data_write = Json::jsonConvertArrayTo([
|
||||||
|
'type' => 'ZLIB',
|
||||||
|
'message' => 'see zlib compressed data_binary field'
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case 'STRING':
|
||||||
|
case 'SERIAL':
|
||||||
|
$data_binary = $this->db->dbEscapeBytea(Json::jsonConvertArrayTo([
|
||||||
|
'type' => 'SERIAL',
|
||||||
|
'message' => 'see serial string data field'
|
||||||
|
]));
|
||||||
|
$data_write = serialize($data);
|
||||||
|
break;
|
||||||
|
case 'JSON':
|
||||||
|
$data_binary = $this->db->dbEscapeBytea(Json::jsonConvertArrayTo([
|
||||||
|
'type' => 'JSON',
|
||||||
|
'message' => 'see json string data field'
|
||||||
|
]));
|
||||||
|
// must be converted to array
|
||||||
|
if (!is_array($data)) {
|
||||||
|
$data = ["data" => $data];
|
||||||
|
}
|
||||||
|
$data_write = Json::jsonConvertArrayTo($data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->log->alert('Invalid type for data compression was set', context:[
|
||||||
|
"write_type" => $write_type
|
||||||
|
]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var string $DB_SCHEMA check schema */
|
/** @var string $DB_SCHEMA check schema */
|
||||||
@@ -253,44 +333,62 @@ class Backend
|
|||||||
} elseif (!empty($this->db->dbGetSchema())) {
|
} elseif (!empty($this->db->dbGetSchema())) {
|
||||||
$DB_SCHEMA = $this->db->dbGetSchema();
|
$DB_SCHEMA = $this->db->dbGetSchema();
|
||||||
}
|
}
|
||||||
$q = "INSERT INTO " . $DB_SCHEMA . ".edit_log "
|
$q = <<<SQL
|
||||||
. "(euid, event_date, event, data, data_binary, page, "
|
INSERT INTO {DB_SCHEMA}.edit_log (
|
||||||
. "ip, user_agent, referer, script_name, query_string, server_name, http_host, "
|
euid, event_date, event, data, data_binary, page,
|
||||||
. "http_accept, http_accept_charset, http_accept_encoding, session_id, "
|
ip, user_agent, referer, script_name, query_string, server_name, http_host,
|
||||||
. "action, action_id, action_yes, action_flag, action_menu, action_loaded, action_value, action_error) "
|
http_accept, http_accept_charset, http_accept_encoding, session_id,
|
||||||
. "VALUES "
|
action, action_id, action_yes, action_flag, action_menu, action_loaded,
|
||||||
. "(" . $this->db->dbEscapeString(isset($_SESSION['EUID']) && is_numeric($_SESSION['EUID']) ?
|
action_value, action_type, action_error
|
||||||
$_SESSION['EUID'] :
|
) VALUES (
|
||||||
'NULL')
|
$1, NOW(), $2, $3, $4, $5,
|
||||||
. ", "
|
$6, $7, $8, $9, $10, $11, $12,
|
||||||
. "NOW(), "
|
$13, $14, $15, $16,
|
||||||
. "'" . $this->db->dbEscapeString((string)$event) . "', "
|
$17, $18, $19, $20, $21, $22,
|
||||||
. "'" . $data_write . "', "
|
$23, $24, $25
|
||||||
. "'" . $data_binary . "', "
|
)
|
||||||
. "'" . $this->db->dbEscapeString((string)$this->page_name) . "', "
|
SQL;
|
||||||
. "'" . ($_SERVER["REMOTE_ADDR"] ?? '') . "', "
|
$this->db->dbExecParams(
|
||||||
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_USER_AGENT'] ?? '') . "', "
|
str_replace(
|
||||||
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_REFERER'] ?? '') . "', "
|
['{DB_SCHEMA}'],
|
||||||
. "'" . $this->db->dbEscapeString($_SERVER['SCRIPT_FILENAME'] ?? '') . "', "
|
[$DB_SCHEMA],
|
||||||
. "'" . $this->db->dbEscapeString($_SERVER['QUERY_STRING'] ?? '') . "', "
|
$q
|
||||||
. "'" . $this->db->dbEscapeString($_SERVER['SERVER_NAME'] ?? '') . "', "
|
),
|
||||||
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_HOST'] ?? '') . "', "
|
[
|
||||||
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_ACCEPT'] ?? '') . "', "
|
// row 1
|
||||||
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_ACCEPT_CHARSET'] ?? '') . "', "
|
isset($_SESSION['EUID']) && is_numeric($_SESSION['EUID']) ?
|
||||||
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_ACCEPT_ENCODING'] ?? '') . "', "
|
$_SESSION['EUID'] : null,
|
||||||
. ($this->session->getSessionId() === false ?
|
(string)$event,
|
||||||
"NULL" :
|
$data_write,
|
||||||
"'" . $this->session->getSessionId() . "'")
|
$data_binary,
|
||||||
. ", "
|
(string)$this->page_name,
|
||||||
. "'" . $this->db->dbEscapeString($this->action) . "', "
|
// row 2
|
||||||
. "'" . $this->db->dbEscapeString($this->action_id) . "', "
|
$_SERVER["REMOTE_ADDR"] ?? '',
|
||||||
. "'" . $this->db->dbEscapeString($this->action_yes) . "', "
|
$_SERVER['HTTP_USER_AGENT'] ?? '',
|
||||||
. "'" . $this->db->dbEscapeString($this->action_flag) . "', "
|
$_SERVER['HTTP_REFERER'] ?? '',
|
||||||
. "'" . $this->db->dbEscapeString($this->action_menu) . "', "
|
$_SERVER['SCRIPT_FILENAME'] ?? '',
|
||||||
. "'" . $this->db->dbEscapeString($this->action_loaded) . "', "
|
$_SERVER['QUERY_STRING'] ?? '',
|
||||||
. "'" . $this->db->dbEscapeString($this->action_value) . "', "
|
$_SERVER['SERVER_NAME'] ?? '',
|
||||||
. "'" . $this->db->dbEscapeString($this->action_error) . "')";
|
$_SERVER['HTTP_HOST'] ?? '',
|
||||||
$this->db->dbExec($q, 'NULL');
|
// row 3
|
||||||
|
$_SERVER['HTTP_ACCEPT'] ?? '',
|
||||||
|
$_SERVER['HTTP_ACCEPT_CHARSET'] ?? '',
|
||||||
|
$_SERVER['HTTP_ACCEPT_ENCODING'] ?? '',
|
||||||
|
$this->session->getSessionId() !== false ?
|
||||||
|
$this->session->getSessionId() : null,
|
||||||
|
// row 4
|
||||||
|
$this->action ?? '',
|
||||||
|
$this->action_id ?? '',
|
||||||
|
$this->action_yes ?? '',
|
||||||
|
$this->action_flag ?? '',
|
||||||
|
$this->action_menu ?? '',
|
||||||
|
$this->action_loaded ?? '',
|
||||||
|
$this->action_value ?? '',
|
||||||
|
$this->action_type ?? '',
|
||||||
|
$this->action_error ?? '',
|
||||||
|
],
|
||||||
|
'NULL'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -540,16 +638,30 @@ class Backend
|
|||||||
} elseif (!empty($this->db->dbGetSchema())) {
|
} elseif (!empty($this->db->dbGetSchema())) {
|
||||||
$DB_SCHEMA = $this->db->dbGetSchema();
|
$DB_SCHEMA = $this->db->dbGetSchema();
|
||||||
}
|
}
|
||||||
$q = "INSERT INTO " . $DB_SCHEMA . ".live_queue ("
|
$q = <<<SQL
|
||||||
. "queue_key, key_value, key_name, type, target, data, group_key, action, associate, file"
|
INSERT INTO {DB_SCHEMA}.live_queue (
|
||||||
. ") VALUES ("
|
queue_key, key_value, key_name, type,
|
||||||
. "'" . $this->db->dbEscapeString($queue_key) . "', '" . $this->db->dbEscapeString($key_value) . "', "
|
target, data, group_key, action, associate, file
|
||||||
. "'" . $this->db->dbEscapeString($key_name) . "', '" . $this->db->dbEscapeString($type) . "', "
|
) VALUES (
|
||||||
. "'" . $this->db->dbEscapeString($target) . "', '" . $this->db->dbEscapeString($data) . "', "
|
$1, $2, $3, $4,
|
||||||
. "'" . $this->queue_key . "', '" . $this->action . "', "
|
$5, $6, $7, $8, $9, $10
|
||||||
. "'" . $this->db->dbEscapeString((string)$associate) . "', "
|
)
|
||||||
. "'" . $this->db->dbEscapeString((string)$file) . "')";
|
SQL;
|
||||||
$this->db->dbExec($q);
|
// $this->db->dbExec($q);
|
||||||
|
$this->db->dbExecParams(
|
||||||
|
str_replace(
|
||||||
|
['{DB_SCHEMA}'],
|
||||||
|
[$DB_SCHEMA],
|
||||||
|
$q
|
||||||
|
),
|
||||||
|
[
|
||||||
|
$queue_key, $key_value,
|
||||||
|
$key_name, $type,
|
||||||
|
$target, $data,
|
||||||
|
$this->queue_key, $this->action,
|
||||||
|
(string)$associate, (string)$file
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -509,6 +509,22 @@ class ArrayHandler
|
|||||||
}
|
}
|
||||||
return $array;
|
return $array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove entries from a simple array, will not keep key order
|
||||||
|
*
|
||||||
|
* any array content is allowed
|
||||||
|
*
|
||||||
|
* https://stackoverflow.com/a/369608
|
||||||
|
*
|
||||||
|
* @param array<mixed> $array Array where elements are located
|
||||||
|
* @param array<mixed> $remove Elements to remove
|
||||||
|
* @return array<mixed> Array with $remove elements removed
|
||||||
|
*/
|
||||||
|
public static function arrayRemoveEntry(array $array, array $remove): array
|
||||||
|
{
|
||||||
|
return array_diff($array, $remove);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// __END__
|
// __END__
|
||||||
|
|||||||
@@ -823,6 +823,10 @@ class IO
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
// no context on DB_INFO
|
||||||
|
if ($id == 'DB_INFO') {
|
||||||
|
$context = [];
|
||||||
|
}
|
||||||
// used named arguments so we can easy change the order of debug
|
// used named arguments so we can easy change the order of debug
|
||||||
$this->log->debug(
|
$this->log->debug(
|
||||||
group_id: $debug_id,
|
group_id: $debug_id,
|
||||||
@@ -1814,14 +1818,13 @@ class IO
|
|||||||
$html_tags = ['{b}', '{/b}', '{br}'];
|
$html_tags = ['{b}', '{/b}', '{br}'];
|
||||||
$replace_html = ['<b>', '</b>', '<br>'];
|
$replace_html = ['<b>', '</b>', '<br>'];
|
||||||
$replace_text = ['', '', ' **** '];
|
$replace_text = ['', '', ' **** '];
|
||||||
$string = '';
|
$string = '{b}-DB-info->{/b} Connected to db {b}\'' . $this->db_name . '\'{/b} '
|
||||||
$string .= '{b}-DB-info->{/b} Connected to db {b}\'' . $this->db_name . '\'{/b} ';
|
. 'with schema {b}\'' . $this->db_schema . '\'{/b} '
|
||||||
$string .= 'with schema {b}\'' . $this->db_schema . '\'{/b} ';
|
. 'as user {b}\'' . $this->db_user . '\'{/b} '
|
||||||
$string .= 'as user {b}\'' . $this->db_user . '\'{/b} ';
|
. 'at host {b}\'' . $this->db_host . '\'{/b} '
|
||||||
$string .= 'at host {b}\'' . $this->db_host . '\'{/b} ';
|
. 'on port {b}\'' . $this->db_port . '\'{/b} '
|
||||||
$string .= 'on port {b}\'' . $this->db_port . '\'{/b} ';
|
. 'with ssl mode {b}\'' . $this->db_ssl . '\'{/b}{br}'
|
||||||
$string .= 'with ssl mode {b}\'' . $this->db_ssl . '\'{/b}{br}';
|
. '{b}-DB-info->{/b} DB IO Class debug output: {b}'
|
||||||
$string .= '{b}-DB-info->{/b} DB IO Class debug output: {b}'
|
|
||||||
. ($this->dbGetDebug() ? 'Yes' : 'No') . '{/b}';
|
. ($this->dbGetDebug() ? 'Yes' : 'No') . '{/b}';
|
||||||
if ($log === true) {
|
if ($log === true) {
|
||||||
// if debug, remove / change b
|
// if debug, remove / change b
|
||||||
@@ -1829,7 +1832,7 @@ class IO
|
|||||||
$html_tags,
|
$html_tags,
|
||||||
$replace_text,
|
$replace_text,
|
||||||
$string
|
$string
|
||||||
), 'dbInfo');
|
), 'DB_INFO');
|
||||||
} else {
|
} else {
|
||||||
$string = $string . '{br}';
|
$string = $string . '{br}';
|
||||||
}
|
}
|
||||||
@@ -1985,7 +1988,7 @@ class IO
|
|||||||
if (is_array($array)) {
|
if (is_array($array)) {
|
||||||
$this->nbsp = '';
|
$this->nbsp = '';
|
||||||
$string .= $this->__printArray($array);
|
$string .= $this->__printArray($array);
|
||||||
$this->__dbDebugMessage('db', $string, 'dbDumpData');
|
$this->__dbDebugMessage('db', $string, 'DB_INFO');
|
||||||
}
|
}
|
||||||
return $string;
|
return $string;
|
||||||
}
|
}
|
||||||
|
|||||||
1022
src/UrlRequests/Curl.php
Normal file
1022
src/UrlRequests/Curl.php
Normal file
File diff suppressed because it is too large
Load Diff
152
src/UrlRequests/CurlTrait.php
Normal file
152
src/UrlRequests/CurlTrait.php
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AUTHOR: Clemens Schwaighofer
|
||||||
|
* CREATED: 2024/10/29
|
||||||
|
* DESCRIPTION:
|
||||||
|
* Curl Client Trait for get/post/put/delete requests through the php curl inteface
|
||||||
|
*
|
||||||
|
* For anything more complex use guzzlehttp/http
|
||||||
|
* https://docs.guzzlephp.org/en/stable/index.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
// phpcs:disable Generic.Files.LineLength
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace CoreLibs\UrlRequests;
|
||||||
|
|
||||||
|
trait CurlTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Set the array block that is sent to the request call
|
||||||
|
* Make sure that if headers is set as key but null it stays null and set to empty array
|
||||||
|
* if headers key is missing
|
||||||
|
* "get" calls do not set any body
|
||||||
|
*
|
||||||
|
* @param string $type if set as get do not add body, else add body
|
||||||
|
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options Request options
|
||||||
|
* @return array{auth?:array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool}
|
||||||
|
*/
|
||||||
|
private function setOptions(string $type, array $options): array
|
||||||
|
{
|
||||||
|
$base = [
|
||||||
|
"auth" => !array_key_exists('auth', $options) ? [] : $options['auth'],
|
||||||
|
"headers" => !array_key_exists('headers', $options) ? [] : $options['headers'],
|
||||||
|
"query" => $options['query'] ?? null,
|
||||||
|
"http_errors" => !array_key_exists('http_errors', $options) ? null : $options['http_errors'],
|
||||||
|
];
|
||||||
|
if ($type != "get") {
|
||||||
|
$base["body"] = $options['body'] ?? null;
|
||||||
|
}
|
||||||
|
return $base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* combined set call for any type of request with options type parameters
|
||||||
|
* The following options can be set:
|
||||||
|
* header: as array string:string
|
||||||
|
* query as string or array string:string
|
||||||
|
* body as string or array of any type
|
||||||
|
*
|
||||||
|
* @param string $type What type of request we send, will throw exception if not a valid one
|
||||||
|
* @param string $url The url to send
|
||||||
|
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options Request options
|
||||||
|
* @return array{code:string,headers:array<string,array<string>>,content:string} [default=[]] Result code, headers and content as array, content is json
|
||||||
|
* @throws \UnexpectedValueException on missing body data when body data is needed
|
||||||
|
*/
|
||||||
|
abstract public function request(string $type, string $url, array $options = []): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes an request to the target url via curl: GET
|
||||||
|
* Returns result as string (json)
|
||||||
|
*
|
||||||
|
* @param string $url The URL being requested,
|
||||||
|
* including domain and protocol
|
||||||
|
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options Options to set
|
||||||
|
* @return array{code:string,headers:array<string,array<string>>,content:string} [default=[]] Result code, headers and content as array, content is json
|
||||||
|
*/
|
||||||
|
public function get(string $url, array $options = []): array
|
||||||
|
{
|
||||||
|
return $this->request(
|
||||||
|
"get",
|
||||||
|
$url,
|
||||||
|
$this->setOptions('get', $options),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes an request to the target url via curl: POST
|
||||||
|
* Returns result as string (json)
|
||||||
|
*
|
||||||
|
* @param string $url The URL being requested,
|
||||||
|
* including domain and protocol
|
||||||
|
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options Options to set
|
||||||
|
* @return array{code:string,headers:array<string,array<string>>,content:string} Result code, headers and content as array, content is json
|
||||||
|
*/
|
||||||
|
public function post(string $url, array $options): array
|
||||||
|
{
|
||||||
|
return $this->request(
|
||||||
|
"post",
|
||||||
|
$url,
|
||||||
|
$this->setOptions('post', $options),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes an request to the target url via curl: PUT
|
||||||
|
* Returns result as string (json)
|
||||||
|
*
|
||||||
|
* @param string $url The URL being requested,
|
||||||
|
* including domain and protocol
|
||||||
|
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options Options to set
|
||||||
|
* @return array{code:string,headers:array<string,array<string>>,content:string} Result code, headers and content as array, content is json
|
||||||
|
*/
|
||||||
|
public function put(string $url, array $options): array
|
||||||
|
{
|
||||||
|
return $this->request(
|
||||||
|
"put",
|
||||||
|
$url,
|
||||||
|
$this->setOptions('put', $options),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes an request to the target url via curl: PATCH
|
||||||
|
* Returns result as string (json)
|
||||||
|
*
|
||||||
|
* @param string $url The URL being requested,
|
||||||
|
* including domain and protocol
|
||||||
|
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options Options to set
|
||||||
|
* @return array{code:string,headers:array<string,array<string>>,content:string} Result code, headers and content as array, content is json
|
||||||
|
*/
|
||||||
|
public function patch(string $url, array $options): array
|
||||||
|
{
|
||||||
|
return $this->request(
|
||||||
|
"patch",
|
||||||
|
$url,
|
||||||
|
$this->setOptions('patch', $options),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes an request to the target url via curl: DELETE
|
||||||
|
* Returns result as string (json)
|
||||||
|
* Note that DELETE body is optional
|
||||||
|
*
|
||||||
|
* @param string $url The URL being requested,
|
||||||
|
* including domain and protocol
|
||||||
|
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options Options to set
|
||||||
|
* @return array{code:string,headers:array<string,array<string>>,content:string} [default=[]] Result code, headers and content as array, content is json
|
||||||
|
*/
|
||||||
|
public function delete(string $url, array $options = []): array
|
||||||
|
{
|
||||||
|
return $this->request(
|
||||||
|
"delete",
|
||||||
|
$url,
|
||||||
|
$this->setOptions('delete', $options),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// __END__
|
||||||
83
src/UrlRequests/Interface/RequestsInterface.php
Normal file
83
src/UrlRequests/Interface/RequestsInterface.php
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AUTHOR: Clemens Schwaighofer
|
||||||
|
* CREATED: 2024/9/20
|
||||||
|
* DESCRIPTION:
|
||||||
|
* URL Requests client interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CoreLibs\UrlRequests\Interface;
|
||||||
|
|
||||||
|
interface RequestsInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* get the config array with all settings
|
||||||
|
*
|
||||||
|
* @return array<string,mixed> all current config settings
|
||||||
|
*/
|
||||||
|
public function getConfig(): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the full url as it was sent
|
||||||
|
*
|
||||||
|
* @return string url sent
|
||||||
|
*/
|
||||||
|
public function getUrlSent(): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the parsed url
|
||||||
|
*
|
||||||
|
* @return array{scheme?:string,user?:string,host?:string,port?:string,path?:string,query?:string,fragment?:string,pass?:string}
|
||||||
|
*/
|
||||||
|
public function getUrlParsedSent(): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the full headers as they where sent
|
||||||
|
*
|
||||||
|
* @return array<string,string>
|
||||||
|
*/
|
||||||
|
public function getHeadersSent(): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set, add or overwrite header
|
||||||
|
* On default this will overwrite header, and not set
|
||||||
|
*
|
||||||
|
* @param array<string,string|array<string>> $header
|
||||||
|
* @param bool $add [default=false] if set will add header to existing value
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setHeaders(array $header, bool $add = false): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove header entry
|
||||||
|
* if key is only set then match only key, if both are set both sides must match
|
||||||
|
*
|
||||||
|
* @param array<string,string> $remove_headers
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function removeHeaders(array $remove_headers): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the base url set, if empty will unset the base url
|
||||||
|
*
|
||||||
|
* @param string $base_uri
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setBaseUri(string $base_uri): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* combined set call for any type of request with options type parameters
|
||||||
|
*
|
||||||
|
* phpcs:disable Generic.Files.LineLength
|
||||||
|
* @param string $type
|
||||||
|
* @param string $url
|
||||||
|
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options
|
||||||
|
* @return array{code:string,headers:array<string,array<string>>,content:string} Result code, headers and content as array, content is json
|
||||||
|
* @throws \UnexpectedValueException on missing body data when body data is needed
|
||||||
|
* phpcs:enable Generic.Files.LineLength
|
||||||
|
*/
|
||||||
|
public function request(string $type, string $url, array $options = []): array;
|
||||||
|
}
|
||||||
|
|
||||||
|
// __END__
|
||||||
@@ -100,27 +100,6 @@ define('DEFAULT_ACL_LEVEL', 80);
|
|||||||
/************* LOGOUT ********************/
|
/************* LOGOUT ********************/
|
||||||
// logout target
|
// logout target
|
||||||
define('LOGOUT_TARGET', '');
|
define('LOGOUT_TARGET', '');
|
||||||
// password change allowed
|
|
||||||
define('PASSWORD_CHANGE', false);
|
|
||||||
define('PASSWORD_FORGOT', false);
|
|
||||||
// min/max password length
|
|
||||||
define('PASSWORD_MIN_LENGTH', 9);
|
|
||||||
define('PASSWORD_MAX_LENGTH', 255);
|
|
||||||
// defines allowed special characters
|
|
||||||
define('PASSWORD_SPECIAL_RANGE', '@$!%*?&');
|
|
||||||
// password must have upper case, lower case, number, special
|
|
||||||
// comment out for not mandatory
|
|
||||||
define('PASSWORD_LOWER', '(?=.*[a-z])');
|
|
||||||
define('PASSWORD_UPPER', '(?=.*[A-Z])');
|
|
||||||
define('PASSWORD_NUMBER', '(?=.*\d)');
|
|
||||||
define('PASSWORD_SPECIAL', "(?=.*[" . PASSWORD_SPECIAL_RANGE . "])");
|
|
||||||
// define full regex
|
|
||||||
define('PASSWORD_REGEX', "/^"
|
|
||||||
. (defined('PASSWORD_LOWER') ? PASSWORD_LOWER : '')
|
|
||||||
. (defined('PASSWORD_UPPER') ? PASSWORD_UPPER : '')
|
|
||||||
. (defined('PASSWORD_NUMBER') ? PASSWORD_NUMBER : '')
|
|
||||||
. (defined('PASSWORD_SPECIAL') ? PASSWORD_SPECIAL : '')
|
|
||||||
. "[A-Za-z\d" . PASSWORD_SPECIAL_RANGE . "]{" . PASSWORD_MIN_LENGTH . "," . PASSWORD_MAX_LENGTH . "}$/");
|
|
||||||
|
|
||||||
/************* AJAX / ACCESS *************/
|
/************* AJAX / ACCESS *************/
|
||||||
// ajax request type
|
// ajax request type
|
||||||
@@ -161,13 +140,6 @@ define('DEFAULT_LOCALE', 'en_US.UTF-8');
|
|||||||
// default web page encoding setting
|
// default web page encoding setting
|
||||||
define('DEFAULT_ENCODING', 'UTF-8');
|
define('DEFAULT_ENCODING', 'UTF-8');
|
||||||
|
|
||||||
/************* LOGGING *******************/
|
|
||||||
// below two can be defined here, but they should be
|
|
||||||
// defined in either the header file or the file itself
|
|
||||||
// as $LOG_FILE_ID which takes presence over LOG_FILE_ID
|
|
||||||
// see Basic class constructor
|
|
||||||
define('LOG_FILE_ID', BASE_NAME);
|
|
||||||
|
|
||||||
/************* QUEUE TABLE *************/
|
/************* QUEUE TABLE *************/
|
||||||
// if we have a dev/live system
|
// if we have a dev/live system
|
||||||
// set_live is a per page/per item
|
// set_live is a per page/per item
|
||||||
@@ -291,22 +263,4 @@ if (file_exists(BASE . CONFIGS . 'config.other.php')) {
|
|||||||
require BASE . CONFIGS . 'config.other.php';
|
require BASE . CONFIGS . 'config.other.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
/************* DEBUG *******************/
|
|
||||||
// turn off debug if debug flag is OFF
|
|
||||||
if (defined('DEBUG') && DEBUG == false) {
|
|
||||||
$ECHO_ALL = false;
|
|
||||||
$DEBUG_ALL = false;
|
|
||||||
$PRINT_ALL = false;
|
|
||||||
$DB_DEBUG = false;
|
|
||||||
$ENABLE_ERROR_HANDLING = false;
|
|
||||||
$DEBUG_ALL_OVERRIDE = false;
|
|
||||||
} else {
|
|
||||||
$ECHO_ALL = false;
|
|
||||||
$DEBUG_ALL = true;
|
|
||||||
$PRINT_ALL = true;
|
|
||||||
$DB_DEBUG = true;
|
|
||||||
$ENABLE_ERROR_HANDLING = false;
|
|
||||||
$DEBUG_ALL_OVERRIDE = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// __END__
|
// __END__
|
||||||
|
|||||||
28
test/configs/config.path.php
Normal file
28
test/configs/config.path.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php // phpcs:ignore PSR1.Files.SideEffects
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* AUTHOR: Clemens Schwaighofer
|
||||||
|
* CREATED: 2018/10/11
|
||||||
|
* SHORT DESCRIPTION:
|
||||||
|
* configuration file for core path settings
|
||||||
|
* CSV target paths, and other download access URLS or paths needed
|
||||||
|
* HISTORY:
|
||||||
|
*********************************************************************/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
// find trigger name "admin/" or "frontend/" in the getcwd() folder
|
||||||
|
$folder = '';
|
||||||
|
foreach (['admin', 'frontend'] as $_folder) {
|
||||||
|
if (strstr(getcwd() ?: '', DIRECTORY_SEPARATOR . $_folder)) {
|
||||||
|
$folder = $_folder;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if content path is empty, fallback is default
|
||||||
|
if (empty($folder)) {
|
||||||
|
$folder = 'default';
|
||||||
|
}
|
||||||
|
define('CONTENT_PATH', $folder . DIRECTORY_SEPARATOR);
|
||||||
|
|
||||||
|
// __END__
|
||||||
@@ -53,19 +53,6 @@ for (
|
|||||||
\gullevek\dotEnv\DotEnv::readEnvFile(
|
\gullevek\dotEnv\DotEnv::readEnvFile(
|
||||||
$__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH
|
$__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH
|
||||||
);
|
);
|
||||||
// find trigger name "admin/" or "frontend/" in the getcwd() folder
|
|
||||||
$folder = '';
|
|
||||||
foreach (['admin', 'frontend'] as $_folder) {
|
|
||||||
if (strstr(getcwd() ?: '', DIRECTORY_SEPARATOR . $_folder)) {
|
|
||||||
$folder = $_folder;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if content path is empty, fallback is default
|
|
||||||
if (empty($folder)) {
|
|
||||||
$folder = 'default';
|
|
||||||
}
|
|
||||||
define('CONTENT_PATH', $folder . DIRECTORY_SEPARATOR);
|
|
||||||
// load master config file that loads all other config files
|
// load master config file that loads all other config files
|
||||||
require $__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php';
|
require $__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php';
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -4,4 +4,7 @@ require "../vendor/autoload.php";
|
|||||||
|
|
||||||
print "Bytes: " . CoreLibs\Convert\Byte::humanReadableByteFormat(123414) . "<br>";
|
print "Bytes: " . CoreLibs\Convert\Byte::humanReadableByteFormat(123414) . "<br>";
|
||||||
|
|
||||||
|
$curl = new CoreLibs\UrlRequests\Curl();
|
||||||
|
print "Config: " . print_r($curl->getConfig(), true) . "<br>";
|
||||||
|
|
||||||
// __END__
|
// __END__
|
||||||
|
|||||||
51
test/phpunit/AAASetupData/requests/http_requests.php
Normal file
51
test/phpunit/AAASetupData/requests/http_requests.php
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?php // phpcs:ignore PSR1.Files.SideEffects
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AUTHOR: Clemens Schwaighofer
|
||||||
|
* CREATED: Ymd
|
||||||
|
* DESCRIPTION:
|
||||||
|
* DescriptionHere
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* build return json
|
||||||
|
*
|
||||||
|
* @param array<string,mixed> $http_headers
|
||||||
|
* @param string $body
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function buildContent(array $http_headers, string $body): string
|
||||||
|
{
|
||||||
|
return json_encode([
|
||||||
|
'HEADERS' => $http_headers,
|
||||||
|
"REQUEST_TYPE" => $_SERVER['REQUEST_METHOD'],
|
||||||
|
"PARAMS" => $_GET,
|
||||||
|
"BODY" => json_decode($body, true)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$http_headers = array_filter($_SERVER, function ($value, $key) {
|
||||||
|
if (str_starts_with($key, 'HTTP_')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}, ARRAY_FILTER_USE_BOTH);
|
||||||
|
|
||||||
|
header("Content-Type: application/json; charset=UTF-8");
|
||||||
|
|
||||||
|
// if the header has Authorization and RunAuthTest then exit with 401
|
||||||
|
if (!empty($http_headers['HTTP_AUTHORIZATION']) && !empty($http_headers['HTTP_RUNAUTHTEST'])) {
|
||||||
|
header("HTTP/1.1 401 Unauthorized");
|
||||||
|
print buildContent($http_headers, '{"code": 401, "content": {"Error": "Not Authorized"}}');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($file_get = file_get_contents('php://input')) === false) {
|
||||||
|
header("HTTP/1.1 404 Not Found");
|
||||||
|
print buildContent($http_headers, '{"code": 404, "content": {"Error": "file_get_contents failed"}}');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
print buildContent($http_headers, $file_get);
|
||||||
|
|
||||||
|
// __END__
|
||||||
@@ -10,7 +10,6 @@ use PHPUnit\Framework\TestCase;
|
|||||||
* Test class for DB\Extended\ArrayIO
|
* Test class for DB\Extended\ArrayIO
|
||||||
* This will only test the PgSQL parts
|
* This will only test the PgSQL parts
|
||||||
* @coversDefaultClass \CoreLibs\DB\Extended\ArrayIO
|
* @coversDefaultClass \CoreLibs\DB\Extended\ArrayIO
|
||||||
* @coversDefaultClass \CoreLibs\DB\Extended\ArrayIO
|
|
||||||
* @testdox \CoreLibs\Extended\ArrayIO method tests for extended DB interface
|
* @testdox \CoreLibs\Extended\ArrayIO method tests for extended DB interface
|
||||||
*/
|
*/
|
||||||
final class CoreLibsDBExtendedArrayIOTest extends TestCase
|
final class CoreLibsDBExtendedArrayIOTest extends TestCase
|
||||||
|
|||||||
1199
test/phpunit/UrlRequests/CoreLibsUrlRequestsCurlTest.php
Normal file
1199
test/phpunit/UrlRequests/CoreLibsUrlRequestsCurlTest.php
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user