From b25f280849fc83eeb5372056e0049a592749e1c6 Mon Sep 17 00:00:00 2001 From: Clemens Schwaighofer Date: Wed, 11 Sep 2019 15:23:34 +0900 Subject: [PATCH] Add Base class set/get variable error check, strict updates The base class has now set/get class variable check handlers. Default they are off and setting undefined variables in a class works as before. The flag can be set to throw an error on an unset var but let var still be set or also surpress setting and unset var. This can be controlled via setting for the last parameter in class init or the global var $CLASS_VARIABLE_ERROR_MODE or in the config file the constant CLASS_VARIABLE_ERROR_MODE (constant > global). Note that if a global or constant is set the class constructor setting will be overridden. Backend/IO/Basic/Login classes are set to be type safe as much as possible if called from a strict defined php script. Added random key generator function to the basic class and removed the random key definitons from the Backend class. - randomKeyGen - initRandomKeyLength Updated the basic bytes to string and string to bytes functions. Added hrRunningTime method to use the hrtime for precise running time calculations. Default returns running time in ms. Can be set via parameter to ns (lowest), ys, ms, s. The old runningTime method is still there, but it is recommended to use the hrRunningTime method instead Removed Error Handling method in Basic, as there is no need for it there. The is a master one in lib Folder Error.Handling.inc if needed. Currently Generate/ArrayIO are not 100% type safe [because they are only used in the edit_base anyway] --- www/admin/class_test.php | 9 + www/configs/config.inc | 7 + www/lib/CoreLibs/ACL/Login.inc | 28 +- www/lib/CoreLibs/Admin/Backend.inc | 129 ++-- www/lib/CoreLibs/Basic.inc | 582 ++++++++++++------ www/lib/CoreLibs/DB/Extended/ArrayIO.inc | 22 +- www/lib/CoreLibs/DB/IO.inc | 148 +++-- .../CoreLibs/Language/Core/GetTextReader.inc | 8 +- www/lib/CoreLibs/Language/L10n.inc | 4 +- www/lib/CoreLibs/Output/Form/Generate.inc | 9 +- www/lib/CoreLibs/Template/SmartyExtend.inc | 2 +- 11 files changed, 630 insertions(+), 318 deletions(-) diff --git a/www/admin/class_test.php b/www/admin/class_test.php index 4aed8be2..f697f85e 100644 --- a/www/admin/class_test.php +++ b/www/admin/class_test.php @@ -30,6 +30,15 @@ $basic = new CoreLibs\Admin\Backend($DB_CONFIG[MAIN_DB], $lang); $basic->dbInfo(1); ob_end_flush(); +$basic->hrRunningTime(); +$basic->runningTime(); +echo "RANDOM KEY [50]: ".$basic->randomKeyGen(50)."
"; +echo "TIMED [hr]: ".$basic->hrRunningTime()."
"; +echo "TIMED [def]: ".$basic->runningTime()."
"; +$basic->hrRunningTime(); +echo "RANDOM KEY [default]: ".$basic->randomKeyGen()."
"; +echo "TIMED: ".$basic->hrRunningTime()."
"; + // set + check edit access id $edit_access_id = 3; if (isset($login) && is_object($login) && isset($login->acl['unit'])) { diff --git a/www/configs/config.inc b/www/configs/config.inc index 874f821c..4e415f75 100644 --- a/www/configs/config.inc +++ b/www/configs/config.inc @@ -146,6 +146,13 @@ DEFINE('DEFAULT_ENCODING', 'UTF-8'); /************* LOGGING *******************/ // DEFINE('LOG_FILE_ID', ''); +/************* CLASS ERRORS *******************/ +// 0 = default all OFF +// 1 = throw notice on unset class var +// 2 = no notice on unset class var, but do not set undefined class var +// 3 = throw error and do not set class var +define('CLASS_VARIABLE_ERROR_MODE', 3); + /************* QUEUE TABLE *************/ // if we have a dev/live system // set_live is a per page/per item diff --git a/www/lib/CoreLibs/ACL/Login.inc b/www/lib/CoreLibs/ACL/Login.inc index 1475f3af..22beae4a 100644 --- a/www/lib/CoreLibs/ACL/Login.inc +++ b/www/lib/CoreLibs/ACL/Login.inc @@ -78,6 +78,9 @@ class Login extends \CoreLibs\DB\IO private $pw_new_password; private $pw_new_password_confirm; private $pw_change_deny_users = array (); // array of users for which the password change is forbidden + private $logout_target; + private $max_login_error_count = -1; + private $lock_deny_users = array (); // if we have password change we need to define some rules private $password_min_length = PASSWORD_MIN_LENGTH; @@ -102,18 +105,21 @@ class Login extends \CoreLibs\DB\IO public $acl = array (); public $default_acl_list = array (); + // language + private $l; + // METHOD: login // PARAMS: db_config -> array for logging in to DB where edit_users tables are // db_debug -> sets debug output for db_io (can be overruled with DB_DEBUG) // RETURN: none // DESC : cunstroctuor, does ALL, opens db, works through connection checks, closes itself - public function __construct($db_config, $lang = 'en_utf8', $debug = 0, $db_debug = 0, $echo = 1, $print = 0) + public function __construct(array $db_config, string $lang = 'en_utf8', int $set_control_flag = 0) { // log login data for this class only $this->log_per_class = 1; // create db connection and init base class - if (!parent::__construct($db_config, $debug, $db_debug, $echo, $print)) { + if (!parent::__construct($db_config, $set_control_flag)) { echo 'Could not connect to DB
'; // if I can't connect to the DB to auth exit hard. No access allowed exit; @@ -282,7 +288,7 @@ class Login extends \CoreLibs\DB\IO // PARAMS: hash, optional password, to override // RETURN: true or false // DESC : checks if password is valid, sets internal error login variable - private function loginPasswordCheck($hash, $password = '') + private function loginPasswordCheck(string $hash, string $password = ''): bool { // check with what kind of prefix the password begins: // $2a$ or $2y$: BLOWFISCH @@ -551,7 +557,9 @@ class Login extends \CoreLibs\DB\IO $q .= "WHERE edit_user_id = ".$res['edit_user_id']; $this->dbExec($q); // totally lock the user if error max is reached - if ($res['login_error_count'] + 1 > $this->max_login_error_count) { + if ($this->max_login_error_count != -1 && + $res['login_error_count'] + 1 > $this->max_login_error_count + ) { // do some alert reporting in case this error is too big // if strict is set, lock this user // this needs manual unlocking by an admin user @@ -738,7 +746,7 @@ class Login extends \CoreLibs\DB\IO // PARAMS: edit_access_id to check // RETURN: true/false: if the edit access is not in the valid list: false // DESC : checks if this edit access id is valid - public function loginCheckEditAccess($edit_access_id) + public function loginCheckEditAccess($edit_access_id): bool { if (array_key_exists($edit_access_id, $this->acl['unit'])) { return true; @@ -773,7 +781,7 @@ class Login extends \CoreLibs\DB\IO // PARAMS: set the minimum length // RETURN: true/false on success // DESC : sets the minium length and checks on valid - public function loginSetPasswordMinLength($length) + 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 @@ -1176,7 +1184,13 @@ EOM; } } $q .= "'".session_id()."', "; - $q .= "'".$this->dbEscapeString($this->action)."', '".$this->dbEscapeString($this->username)."', NULL, '".$this->dbEscapeString($this->login_error)."', NULL, NULL, '".$this->dbEscapeString($this->permission_okay)."', NULL)"; + $q .= "'".$this->dbEscapeString($this->action)."', "; + $q .= "'".$this->dbEscapeString($this->username)."', "; + $q .= "NULL, "; + $q .= "'".$this->dbEscapeString((string)$this->login_error)."', "; + $q .= "NULL, NULL, "; + $q .= "'".$this->dbEscapeString((string)$this->permission_okay)."', "; + $q .= "NULL)"; $this->dbExec($q, 'NULL'); } diff --git a/www/lib/CoreLibs/Admin/Backend.inc b/www/lib/CoreLibs/Admin/Backend.inc index 0c4b5996..7ee3a705 100644 --- a/www/lib/CoreLibs/Admin/Backend.inc +++ b/www/lib/CoreLibs/Admin/Backend.inc @@ -27,7 +27,6 @@ namespace CoreLibs\Admin; class Backend extends \CoreLibs\DB\IO { // page name - public $page_name; // the name of the current page public $menu = array(); public $menu_show_flag = 0; // top menu flag (mostly string) // action ids @@ -43,6 +42,9 @@ class Backend extends \CoreLibs\DB\IO public $action_error; // ACL array variable if we want to set acl data from outisde public $acl = array (); + public $default_acl; + // queue key + public $queue_key; // the current active edit access id public $edit_access_id; // error/warning/info messages @@ -55,15 +57,41 @@ class Backend extends \CoreLibs\DB\IO public $HEADER; public $DEBUG_DATA; public $CONTENT_DATA; + // smarty include/set var + public $INC_TEMPLATE_NAME; + public $JS_TEMPLATE_NAME; + public $CSS_TEMPLATE_NAME; + public $CSS_SPECIAL_TEMPLATE_NAME; + public $JS_SPECIAL_TEMPLATE_NAME; + public $CACHE_ID; + public $COMPILE_ID; + public $includes; + public $template_path; + public $lang_dir; + public $javascript; + public $css; + public $pictures; + public $cache_pictures; + public $cache_pictures_root; + public $JS_INCLUDE; + public $JS_SPECIAL_INCLUDE; + public $CSS_INCLUDE; + public $CSS_SPECIAL_INCLUDE; + // language + public $l; // CONSTRUCTOR / DECONSTRUCTOR |====================================> - public function __construct($db_config, $lang, $debug = 0, $db_debug = 0, $echo = 1, $print = 0) + // METHOD: __construct + // PARAMS: array db config + // string for language set + // int set control flag (for core basic set/get var error control) + public function __construct(array $db_config, string $lang, int $set_control_flag = 0) { // get the language sub class & init it $this->l = new \CoreLibs\Language\L10n($lang); // init the database class - parent::__construct($db_config, $debug, $db_debug, $echo, $print); + parent::__construct($db_config, $set_control_flag); // internal $this->class_info["adbBackend"] = array( @@ -73,9 +101,6 @@ class Backend extends \CoreLibs\DB\IO "class_author" => "Clemens Schwaighofer" ); - // set page name - $this->page_name = $this->getPageName(); - // set the action ids foreach ($this->action_list as $_action) { $this->$_action = (isset($_POST[$_action])) ? $_POST[$_action] : ''; @@ -83,24 +108,9 @@ class Backend extends \CoreLibs\DB\IO $this->default_acl = DEFAULT_ACL_LEVEL; - // random key generation - $this->key_range = array_merge(range('A', 'Z'), range('a', 'z'), range('0', '9')); - $GLOBALS["_KEY_RANGE"] = $this->key_range; - $this->one_key_length = count($this->key_range); - $this->key_length = 4; // pow($this->one_key_length, 4); // hardcoded, should be more than enought (62*62*62*62) - // queue key if (preg_match("/^(add|save|delete|remove|move|up|down|push_live)$/", $this->action)) { - $this->queue_key = join( - '', - array_map( - function () { - $range = $GLOBALS['_KEY_RANGE']; - return $range[rand(0, (count($range) - 1))]; - }, - range(1, 3) - ) - ); + $this->queue_key = $this->randomKeyGen(3); } } @@ -116,16 +126,18 @@ class Backend extends \CoreLibs\DB\IO // PUBLIC METHODS |=================================================> // METHOD: adbEditLog() - // PARAMS: event -> any kind of event description, data -> any kind of data related to that event + // PARAMS: event -> any kind of event description, + // data -> any kind of data related to that event // RETURN: none // DESC : writes all action vars plus other info into edit_log table - public function adbEditLog($event = '', $data = '', $write_type = 'STRING') + public function adbEditLog(string $event = '', $data = '', string $write_type = 'STRING') { if ($write_type == 'BINARY') { $data_binary = $this->dbEscapeBytea(bzcompress(serialize($data))); $data = 'see bzip compressed data_binary field'; } if ($write_type == 'STRING') { + $data_binary = ''; $data = $this->dbEscapeString(serialize($data)); } @@ -134,17 +146,27 @@ class Backend extends \CoreLibs\DB\IO $q .= "ip, user_agent, referer, script_name, query_string, server_name, http_host, http_accept, http_accept_charset, http_accept_encoding, session_id, "; $q .= "action, action_id, action_yes, action_flag, action_menu, action_loaded, action_value, action_error) "; $q .= "VALUES "; - $q .= "(".@$_SESSION['EUID'].", NOW(), '".$this->dbEscapeString($event)."', '".$data."', '".$data_binary."', '".$this->page_name."', "; + $q .= "(".$this->dbEscapeString(isset($_SESSION['EUID']) ? $_SESSION['EUID'] : '').", "; + $q .= "NOW(), "; + $q .= "'".$this->dbEscapeString($event)."', '".$data."', '".$data_binary."', '".$this->dbEscapeString($this->page_name)."', "; $q .= "'".@$_SERVER["REMOTE_ADDR"]."', '".$this->dbEscapeString(@$_SERVER['HTTP_USER_AGENT'])."', "; - $q .= "'".$this->dbEscapeString(@$_SERVER['HTTP_REFERER'])."', '".$this->dbEscapeString(@$_SERVER['SCRIPT_FILENAME'])."', "; - $q .= "'".$this->dbEscapeString(@$_SERVER['QUERY_STRING'])."', '".$this->dbEscapeString(@$_SERVER['SERVER_NAME'])."', "; - $q .= "'".$this->dbEscapeString(@$_SERVER['HTTP_HOST'])."', '".$this->dbEscapeString(@$_SERVER['HTTP_ACCEPT'])."', "; - $q .= "'".$this->dbEscapeString(@$_SERVER['HTTP_ACCEPT_CHARSET'])."', '".$this->dbEscapeString(@$_SERVER['HTTP_ACCEPT_ENCODING'])."', "; + $q .= "'".$this->dbEscapeString(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '')."', "; + $q .= "'".$this->dbEscapeString(isset($_SERVER['SCRIPT_FILENAME']) ? $_SERVER['SCRIPT_FILENAME'] : '')."', "; + $q .= "'".$this->dbEscapeString(isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '')."', "; + $q .= "'".$this->dbEscapeString(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '')."', "; + $q .= "'".$this->dbEscapeString(isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '')."', "; + $q .= "'".$this->dbEscapeString(isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : '')."', "; + $q .= "'".$this->dbEscapeString(isset($_SERVER['HTTP_ACCEPT_CHARSET']) ? $_SERVER['HTTP_ACCEPT_CHARSET'] : '')."', "; + $q .= "'".$this->dbEscapeString(isset($_SERVER['HTTP_ACCEPT_ENCODING']) ? $_SERVER['HTTP_ACCEPT_ENCODING'] : '')."', "; $q .= "'".session_id()."', "; - $q .= "'".$this->dbEscapeString($this->action)."', '".$this->dbEscapeString($this->action_id)."', "; - $q .= "'".$this->dbEscapeString($this->action_yes)."', '".$this->dbEscapeString($this->action_flag)."', "; - $q .= "'".$this->dbEscapeString($this->action_menu)."', '".$this->dbEscapeString($this->action_loaded)."', "; - $q .= "'".$this->dbEscapeString($this->action_value)."', '".$this->dbEscapeString($this->action_error)."')"; + $q .= "'".$this->dbEscapeString($this->action)."', "; + $q .= "'".$this->dbEscapeString($this->action_id)."', "; + $q .= "'".$this->dbEscapeString($this->action_yes)."', "; + $q .= "'".$this->dbEscapeString($this->action_flag)."', "; + $q .= "'".$this->dbEscapeString($this->action_menu)."', "; + $q .= "'".$this->dbEscapeString($this->action_loaded)."', "; + $q .= "'".$this->dbEscapeString($this->action_value)."', "; + $q .= "'".$this->dbEscapeString($this->action_error)."')"; $this->dbExec($q, 'NULL'); } @@ -152,7 +174,7 @@ class Backend extends \CoreLibs\DB\IO // PARAMS: level // RETURN: returns an array for the top menu with all correct settings // DESC : menu creater - public function adbTopMenu($flag = 0) + public function adbTopMenu(int $flag = 0): array { if ($this->menu_show_flag) { $flag = $this->menu_show_flag; @@ -243,12 +265,12 @@ class Backend extends \CoreLibs\DB\IO // PARAMS: filename // RETURN: returns boolean true/false // DESC : checks if this filename is in the current situation (user id, etc) available - public function adbShowMenuPoint($filename) + public function adbShowMenuPoint(string $filename): bool { - $enabled = 0; + $enabled = false; switch ($filename) { default: - $enabled = 1; + $enabled = true; break; }; return $enabled; @@ -259,8 +281,9 @@ class Backend extends \CoreLibs\DB\IO // PARAMS: db array, key, value part // RETURN: returns and associative array // DESC : creates out of a normal db_return array an assoc array - public function adbAssocArray($db_array, $key, $value) + public function adbAssocArray(array $db_array, $key, $value): array { + trigger_error('Method '.__METHOD__.' is deprecated', E_USER_DEPRECATED); return $this->genAssocArray($db_array, $key, $value); } @@ -269,8 +292,9 @@ class Backend extends \CoreLibs\DB\IO // PARAMS: int // RETURN: string // DESC : converts bytes into formated string with KB, MB, etc - public function adbByteStringFormat($number) + public function adbByteStringFormat($number): string { + trigger_error('Method '.__METHOD__.' is deprecated', E_USER_DEPRECATED); return $this->byteStringFormat($number); } @@ -286,6 +310,7 @@ class Backend extends \CoreLibs\DB\IO // DESC : converts picture to a thumbnail with max x and max y size public function adbCreateThumbnail($pic, $size_x, $size_y, $dummy = false, $path = "", $cache = "") { + trigger_error('Method '.__METHOD__.' is deprecated', E_USER_DEPRECATED); return $this->createThumbnail($pic, $size_x, $size_y, $dummy, $path, $cache); } @@ -295,7 +320,7 @@ class Backend extends \CoreLibs\DB\IO // var array -> optional data for a possible printf formated msg // RETURN: none // DESC : wrapper function to fill up the mssages array - public function adbMsg($level, $msg, $vars = array ()) + public function adbMsg(string $level, string $msg, array $vars = array ()): void { if (!preg_match("/^info|warning|error$/", $level)) { $level = "info"; @@ -328,8 +353,16 @@ class Backend extends \CoreLibs\DB\IO // file -> string for special file copy actions; mostyle "test#live;..." // RETURN: none // DESC : writes live queue - public function adbLiveQueue($queue_key, $type, $target, $data, $key_name, $key_value, $associate = null, $file = null) - { + public function adbLiveQueue( + $queue_key, + $type, + $target, + $data, + $key_name, + $key_value, + $associate = null, + $file = null + ) { $q = "INSERT INTO ".GLOBAL_DB_SCHEMA.".live_queue ("; $q .= "queue_key, key_value, key_name, type, target, data, group_key, action, associate, file"; $q .= ") VALUES ("; @@ -353,8 +386,16 @@ class Backend extends \CoreLibs\DB\IO // DESC : print the date/time drop downs, used in any queue/send/insert at date/time place // NOTE : Basic class holds exact the same, except the Year/Month/Day/etc strings // are translated in this call - public function adbPrintDateTime($year, $month, $day, $hour, $min, $suffix = '', $min_steps = 1, $name_pos_back = false) - { + public function adbPrintDateTime( + $year, + $month, + $day, + $hour, + $min, + string $suffix = '', + int $min_steps = 1, + bool $name_pos_back = false + ) { // get the build layout $html_time = $this->printDateTime($year, $month, $day, $hour, $min, $suffix, $min_steps, $name_pos_back); // translate the strings inside diff --git a/www/lib/CoreLibs/Basic.inc b/www/lib/CoreLibs/Basic.inc index 8109cfbe..540c8c81 100644 --- a/www/lib/CoreLibs/Basic.inc +++ b/www/lib/CoreLibs/Basic.inc @@ -95,18 +95,28 @@ namespace CoreLibs; +// define check vars for the flags we can have +define('CLASS_STRICT_MODE', 1); +define('CLASS_OFF_COMPATIBLE_MODE', 2); + class Basic { public $class_info; // class info var - + // control vars + // compatible mode sets variable even if it is not defined + private $set_compatible = true; + // strict mode throws an error if the variable is not defined + private $set_strict_mode = false; + // page and host name public $page_name; public $host_name; public $host_port; - + // internal error reporting vars private $error_id; // error ID for errors in classes private $error_string; // error strings in classes (for error_id) private $error_msg = array (); // the "connection" to the outside errors - + public $error_msg_prefix = ''; // prefix to the error string (the class name) + // debug flags public $debug_output; // if this is true, show debug on desconstructor public $debug_output_not; public $debug_output_all; @@ -116,7 +126,11 @@ class Basic public $print_output; // errors: print to file, default is 0 public $print_output_not; public $print_output_all; - + // debug flags/settings + public $debug_fp = ''; // filepointer for writing to file + public $debug_filename = 'debug_file.log'; // where to write output + public $hash_algo = 'crc32b'; // the hash algo used for the internal debug uid + public $running_uid = ''; // unique ID set on class init and used in logging as prefix // log file name private $log_file_name_ext = 'log'; // use this for date rotate public $log_max_filesize = 0; // set in kilobytes @@ -128,20 +142,21 @@ class Basic public $log_per_class = 0; // set, will split log per class public $log_per_page = 0; // set, will split log per called file public $log_per_run = 0; // create a new log file per run (time stamp + unique ID) - + // run time messurements private $starttime; // start time if time debug is used private $endtime; // end time if time debug is used + private $runningtime_string; // the running time as a string with info text + private $hr_starttime; // start time + private $hr_endtime; // end time + private $hr_runtime; // run time + // email valid checks + public $email_regex_check = array (); + public $mobile_email_type = array (); + public $mobile_email_type_short = array (); public $email_regex; // regex var for email check public $keitai_email_regex; // regex var for email check - public $error_msg_prefix = ''; // prefix to the error string (the class name) - - public $debug_fp = ''; // filepointer for writing to file - public $debug_filename = 'debug_file.log'; // where to write output - public $hash_algo = 'crc32b'; // the hash algo used for the internal debug uid - public $running_uid = ''; // unique ID set on class init and used in logging as prefix - // data path for files public $data_path = array (); @@ -158,16 +173,24 @@ class Basic // session name private $session_name = ''; private $session_id = ''; + // key generation + private $key_range = array (); + private $one_key_length; + private $key_length; + private $max_key_length = 256; // max allowed length // form token (used for form validation) private $form_token = ''; // METHOD: __construct - // PARAMS: debug_all (0)/1, echo_all (1)/0, print_all (0)/1 + // PARAMS: set_control_flag [current sets set/get var errors] // RETURN: none // DESC constructor - public function __construct($debug_all = 0, $echo_all = 1, $print_all = 0) + public function __construct(int $set_control_flag = 0) { + // init flags + $this->__setControlFlag($set_control_flag); + // set per run UID for logging $this->running_uid = hash($this->hash_algo, uniqid((string)rand(), true)); @@ -222,9 +245,9 @@ class Basic ); // if given via parameters, only for all - $this->debug_output_all = $debug_all; - $this->echo_output_all = $echo_all; - $this->print_output_all = $print_all; + $this->debug_output_all = false; + $this->echo_output_all = true; + $this->print_output_all = false; // globals overrule given settings, for one (array), eg $ECHO['db'] = 1; if (isset($GLOBALS['DEBUG'])) { $this->debug_output = $GLOBALS['DEBUG']; @@ -372,6 +395,9 @@ class Basic // new better password init $this->passwordInit(); + // key generation init + $this->initRandomKeyData(); + // start logging running time $this->runningTime(); } @@ -389,6 +415,69 @@ class Basic // $this->fdebugFP('c'); } + // ************************************************************* + // INTERAL VARIABLE ERROR HANDLER + // ************************************************************* + + // METHOD: __setControlFlag + // PARAMS: control flag as bit list + // RETURN: none + // DESC : sets internal control flags for class variable check + // 0 -> turn of all, works like default php class + // CLASS_STRICT_MODE: 1 -> if set throws error on unset class variable + // CLASS_OFF_COMPATIBLE_MODE: 2 -> if set turns of auto set for unset variables + // 3 -> sets error on unset and does not set variable (strict) + private function __setControlFlag(int $set_control_flag) + { + // is there either a constant or global set to override the control flag + if (defined('CLASS_VARIABLE_ERROR_MODE')) { + $set_control_flag = CLASS_VARIABLE_ERROR_MODE; + } + if (isset($GLOBALS['CLASS_VARIABLE_ERROR_MODE'])) { + $set_control_flag = $GLOBALS['CLASS_VARIABLE_ERROR_MODE']; + } + // bit wise check of int and set + if ($set_control_flag & CLASS_OFF_COMPATIBLE_MODE) { + $this->set_compatible = false; + } else { + $this->set_compatible = true; + } + if ($set_control_flag & CLASS_STRICT_MODE) { + $this->set_strict_mode = true; + } else { + $this->set_strict_mode = false; + } + } + + // METHOD: __set + // PARAMS: var name, var value + // RETURN: none + // DESC : if strict mode is set, throws an error if the class variable is not set + // if compatible mode is set, also auto sets variable even if not declared + // default is strict mode false and compatible mode on + public function __set($name, $value) + { + if ($this->set_strict_mode === true && !property_exists($this, $name)) { + trigger_error('Undefined property via __set(): '.$name, E_USER_NOTICE); + } + // use this for fallback as to work like before to set unset + if ($this->set_compatible === true) { + return $this->{$name} = $value; + } + } + + // METHOD: __get + // PARAMS: var name + // RETURN: none + // DESC : if strict mode is set, throws an error if the class variable is not set + // default is strict mode false + public function __get($name) + { + if ($this->set_strict_mode === true && !property_exists($this, $name)) { + trigger_error('Undefined property via __get(): '.$name, E_USER_NOTICE); + } + } + // ************************************************************* // GENERAL METHODS // ************************************************************* @@ -398,7 +487,7 @@ class Basic // RETURN: current set string // DESC : sets the log file prefix id // must be alphanumeric only (\w) - public function basicSetLogId($string) + public function basicSetLogId(string $string): string { if (!isset($log_file_id)) { $log_file_id = ''; @@ -409,11 +498,11 @@ class Basic return $log_file_id; } - // METHOD: db_io_info - // PARAMS: show, default 1, if set to 0 won't write to error_msg var + // METHOD: classInfo + // PARAMS: print to debug (true/false) // RETURN: string with info // DESC : default class info (prints out class info) - public function info($class_name = "basic", $stdio = 0) + public function classInfo(string $class_name = 'basic', bool $print_to_debug = false): string { unset($string); list($major, $minor, $patchlvl) = explode(".", $this->class_info[$class_name]["class_version"]); @@ -424,25 +513,71 @@ class Basic $string .= "-Class-info-[".$class_name."]-> Class Revision: ".$this->class_info[$class_name]["class_revision"]."
"; $string .= "-Class-info-[".$class_name."]-> Class Created: ".$this->class_info[$class_name]["class_created"]."
"; $string .= "-Class-info-[".$class_name."]-> Class Last Change: ".$this->class_info[$class_name]["class_last_changed"].""; - if ($stdio) { - echo $string.'
'; - } else { + if ($print_to_debug === true) { $this->debug('info', '
'.$string); } return $string; } + // ****** DEBUG/ERROR FUNCTIONS ****** + + // METHOD: hrRunningTime + // PARAMS: time return conversion, default is ms + // allowed are ns (nano), ys (micro), ms (milli), s + // RETURN: running time or nothing on start + // DESC : uses the hrtime() for running time + public function hrRunningTime(string $out_time = 'ms'): float + { + // if start time not set, set start time + if (!$this->hr_starttime) { + $this->hr_starttime = hrtime(true); + } else { + $this->hr_endtime = hrtime(true); + $this->hr_runtime = $this->hr_endtime - $this->hr_starttime; + // reset start and end time past run + $this->hr_starttime = 0; + $this->hr_endtime = 0; + } + // init divisor, just in case + $divisor = 1; + // check through valid out time, if nothing matches default to ms + switch ($out_time) { + case 'n': + case 'ns': + $divisor = 1; + break; + case 'y': + case 'ys': + $divisor = 1000; + break; + case 'm': + case 'ms': + $divisor = 1000000; + break; + case 's': + $divisor = 1000000000; + break; + // default is ms + default: + $divisor = 1000000; + break; + } + // return the run time in converted format + $this->hr_runtime /= $divisor; + return $this->hr_runtime; + } + // METHOD: runningTime // WAS : running_time // PARAMS: simple flag true/false, if given print non HTML info // RETURN: string with running time for debugging // DESC : prints start or end time in text format. On first call sets start time // on second call it sends the end time and then also prints the running time - public function runningTime($simple = false) + public function runningTime(bool $simple = false): float { list($micro, $timestamp) = explode(' ', microtime()); $string = ''; - $running_time = ''; + $running_time = 0; if (!$this->starttime) { $this->starttime = ((float)$micro + (float)$timestamp); $string .= $simple ? 'Start: ' : "Started at: "; @@ -450,12 +585,13 @@ class Basic $this->endtime = ((float)$micro + (float)$timestamp); $string .= $simple ? 'End: ' : "Stopped at: "; } - $string .= date("Y-m-d H:i:s", (int)$timestamp); - $string .= " ".$micro; + $string .= date('Y-m-d H:i:s', (int)$timestamp); + $string .= ' '.$micro; if ($this->starttime && $this->endtime) { $running_time = $this->endtime - $this->starttime; $string .= ($simple ? 'Run: ' : "
Script running time: ").$running_time." s"; } + $this->runningtime_string = $string; // $this->debug('info', $string); return $running_time; } @@ -464,10 +600,11 @@ class Basic // PARAMS: none // RETURN: none // DESC : resets start & end time for runningTime call - public function resetRunningTime() + public function resetRunningTime(): void { $this->starttime = ''; $this->endtime = ''; + $this->runningtime_string = ''; } // METHOD: printTime @@ -475,7 +612,7 @@ class Basic // PARAMS: $set_microtime, 0 shows none, default (-1) shows all, positive number is for rounding // RETURN: formated datetime string // DESC : wrapper around microtime function to print out y-m-d h:i:s.ms - public static function printTime($set_microtime = -1) + public static function printTime(int $set_microtime = -1): string { list($microtime, $timestamp) = explode(' ', microtime()); $string = date("Y-m-d H:i:s", (int)$timestamp); @@ -495,11 +632,11 @@ class Basic // $enter: default on true, if set to false, no linebreak (\n) will be put at the end // RETURN: none // DESC : writes a string to a file immediatly, for fast debug output - public function fdebug($string, $enter = 1) + public function fdebug(string $string, $enter = true): void { if ($this->debug_filename) { $this->fdebugFP(); - if ($enter) { + if ($enter === true) { $string .= "\n"; } $string = "[".$this->printTime()."] [".$this->getPageName(2)."] - ".$string; @@ -513,7 +650,7 @@ class Basic // PARAMS: $flag: default '', 'o' -> open, 'c' -> close // RETURN: none // DESC : if no debug_fp found, opens a new one; if fp exists close it - private function fdebugFP($flag = '') + private function fdebugFP(string $flag = ''): void { if (!$this->debug_fp || $flag == 'o') { $fn = BASE.LOG.$this->debug_filename; @@ -531,14 +668,14 @@ class Basic // RETURN: none // DESC : passes list of level names, to turn on debug // eg $foo->debug_for('print', 'on', array('LOG', 'DEBUG', 'INFO')); - public function debugFor($type, $flag) + public function debugFor(string $type, string $flag): void { $debug_on = func_get_args(); array_shift($debug_on); // kick out type array_shift($debug_on); // kick out flag (on/off) if (count($debug_on) >= 1) { foreach ($debug_on as $level) { - $switch = $type."_output"; + $switch = $type.'_output'; if ($flag == 'off') { $switch .= '_not'; } @@ -554,7 +691,7 @@ class Basic // this is only used for debug output // RETURN: none // DESC : write debug data to error_msg array - public function debug($level, $string, $strip = false) + public function debug(string $level, string $string, bool $strip = false): void { if (($this->debug_output[$level] || $this->debug_output_all) && !$this->debug_output_not[$level]) { if (!isset($this->error_msg[$level])) { @@ -572,7 +709,7 @@ class Basic // find any
and replace them with \n $string = str_replace('
', "\n", $string); // strip rest of html elements - $string = preg_replace("/(<\/?)(\w+)([^>]*>)/", "", $string); + $string = preg_replace("/(<\/?)(\w+)([^>]*>)/", '', $string); } // same string put for print (no html crap inside) $error_string_print = '['.$this->printTime().'] ['.$this->host_name.'] ['.$this->getPageName(2).'] ['.$this->running_uid.'] {'.get_class($this).'} <'.$level.'> - '.$string; @@ -592,7 +729,7 @@ class Basic // RETURN: null or the function that called the function where this methid is called // DESC : if there is a need to find out which parent method called a child method, eg for debugging, this function does this // call this method in the child method and you get the parent function that called it - public function getCallerMethod($level = 2) + public function getCallerMethod(int $level = 2): ?string { $traces = debug_backtrace(); // extended info (later) @@ -617,7 +754,7 @@ class Basic // RETURN: none // DESC : merges the given error array with the one from this class // only merges visible ones - public function mergeErrors($error_msg = array ()) + public function mergeErrors(array $error_msg = array ()): void { if (!is_array($error_msg)) { $error_msg = array (); @@ -632,7 +769,7 @@ class Basic // PARAMS: $string: prefix string for header // RETURN: error msg for all levels // DESC : prints out the error string - public function printErrorMsg($string = '') + public function printErrorMsg(string $string = ''): string { $string_output = ''; if ($this->debug_output_all) { @@ -665,7 +802,7 @@ class Basic // PARAMS: $level: the level to write // RETURN: none // DESC : writes error msg data to file for current level - private function writeErrorMsg($level, $error_string) + private function writeErrorMsg(string $level, string $error_string): void { if (($this->debug_output[$level] || $this->debug_output_all) && !$this->debug_output_not[$level]) { // only write if write is requested @@ -734,75 +871,114 @@ class Basic // DESC : unsests the error message array // can be used if writing is primary to file // if no level given resets all - public function resetErrorMsg($level = '') + public function resetErrorMsg(string $level = ''): void { if (!$level) { unset($this->error_msg); - } else { + } elseif (isset($this->error_msg[$level])) { unset($this->error_msg[$level]); } } - // METHOD: errorHandler - // WAS : ErrorHandler - // PARAMS: none - // RETURN: none - // DESC : catch function to handle all errors that are not handled by php itself - // eg all errors that would be surpressed are written to a log file if this function is enabled - // to use it call with set_error_handler(array("Basic", "ErrorHandler")); - // NOTE : this will only catch any additional erros created AFTER the set_error_handler was set, - // so mostly no strict/notices from the classes are visible - // also, this currently returns true, which will invoke the standard PHP error reporter too - public static function errorHandler($type, $message, $file, $line) - { - // error levels for PHP - // values based on 5.3 - $error_level = array ( - 1 => 'E_ERROR', - 2 => 'E_WARNING', - 4 => 'E_PARSE', - 8 => 'E_NOTICE', - 16 => 'E_CORE_ERROR', - 32 => 'E_CORE_WARNING', - 64 => 'E_COMPILE_ERROR', - 128 => 'E_COMPILE_WARNING', - 256 => 'E_USER_ERROR', - 512 => 'E_USER_WARNING', - 1024 => 'E_USER_NOTICE', - 2048 => 'E_STRICT', - 4096 => 'E_RECOVERABLE_ERROR', // since 5.2 - 8192 => 'E_DEPRICATED', // since 5.3 - 16384 => 'E_USER_DEPRICATED', // since 5.3 - 30719 => 'E_ALL' // 6143 in 5.2, 2047 in previous versions - ); - - $fn = BASE.LOG.'php_errors-'.date('Y-m-d').'.log'; - $output = '['.Basic::print_time().'] {'.Basic::get_page_name().'} ['.$file.'] <'.$line.'> ['.$error_level[$type].'|'.$type.']: '.$message."\n"; - $fp = fopen($fn, 'a'); - fwrite($fp, $output); - fclose($fp); - // if set to false the PHP error reporter will be called after this - return false; - } - // METHOD: printAr // WAS : print_ar // PARAMS: $array // RETURN: string html formatted // DESC : prints a html formatted (pre) array - public static function printAr(array $array) + public static function printAr(array $array): string { return "
".print_r($array, true)."
"; } + // ****** DEBUG/ERROR FUNCTIONS ****** + + // ****** RANDOM KEY GEN ****** + + // METHOD: initRandomKeyData + // PARAMS: none + // RETURN: none + // DESC : sets the random key range with the default values + private function initRandomKeyData() + { + // random key generation + $this->key_range = array_merge(range('A', 'Z'), range('a', 'z'), range('0', '9')); + $this->one_key_length = count($this->key_range); + // pow($this->one_key_length, 4); + // default set to 4, should be more than enought (62*62*62*62) + $this->key_length = 4; + } + + // METHOD: validateRandomKeyLenght + // PARAMS: int key length + // RETURN: true for valid, false for invalid length + // DESC : validates they key length + private function validateRandomKeyLenght(int $key_length): bool + { + if (isset($key_length) && + is_numeric($key_length) && + $key_length > 0 && + $key_length <= $this->max_key_length + ) { + return true; + } else { + return false; + } + } + + // METHOD: initRandomKeyLength + // PARAMS: key length in int + // RETURN: true/false for set status + // DESC : sets the key length and checks that they key given is valid + // if failed it will not change the default key length and return false + public function initRandomKeyLength(int $key_length): bool + { + // only if valid int key with valid length + if ($this->validateRandomKeyLenght($key_length) === true) { + $this->key_length = $key_length; + return true; + } else { + return false; + } + } + + // METHOD: randomKeyGen + // PARAMS: key length override, -1 for use default + // RETURN: random key + // DESC : creates a random key based on the key_range with key_length + // if override key length is set, it will check on valid key and use this + // this will not set the class key length variable + public function randomKeyGen(int $key_length = -1): string + { + $use_key_length; + // only if valid int key with valid length + if ($this->validateRandomKeyLenght($key_length) === true) { + $use_key_length= $key_length; + } else { + $use_key_length = $this->key_length; + } + + return join( + '', + array_map( + function () { + return $this->key_range[rand(0, $this->one_key_length - 1)]; + }, + range(1, $use_key_length) + ) + ); + } + + // ****** RANDOM KEY GEN ****** + // METHOD: checked - // PARAMS: haystack (search in), needle (search for), type: 0: returns selected, 1, returns checked - // haystack can be an array or a string + // PARAMS: haystack (search in) haystack can be an array or a string + // needle (search for) + // type: 0: returns selected, 1, returns checked // RETURN: returns checked or selected, else returns nothing (empty return) // DESC : returns 'checked' or 'selected' if okay // $needle is a var, $haystack an array - // **** THE RETURN: VALUE WILL CHANGE TO A DEFAULT "FALSE" **** - public static function checked($haystack, $needle, $type = 0) + // **** THE RETURN: VALUE WILL CHANGE TO A DEFAULT NULL IF NOT FOUND **** + public static function checked($haystack, $needle, int $type = 0): ?string { if (is_array($haystack)) { if (in_array((string)$needle, $haystack)) { @@ -813,6 +989,7 @@ class Basic return (($type) ? "checked" : "selected"); } } + return null; } // METHOD: magicLinks @@ -822,7 +999,7 @@ class Basic // DESC : tries to find mailto:user@bubu.at and changes it into -> E-Mail senden // or tries to take any url (http, ftp, etc) and transform it into a valid URL // the string is in the format: some url|name#css|, same for email - public function magicLinks($string, $target = "_blank") + public function magicLinks(string $string, string $target = "_blank"): string { $output = $string; $protList = array("http", "https", "ftp", "news", "nntp"); @@ -894,7 +1071,7 @@ class Basic // RETURN: correct string for url href process // DESC : internal function, called by the magic url create functions. // checks if title $_4 exists, if not, set url as title - private function createUrl($href, $atag, $_1, $_2, $_3, $name, $class) + private function createUrl($href, $atag, $_1, $_2, $_3, $name, $class): string { // $this->debug('URL', "1: $_1 - 2: $_2 - $_3 - atag: $atag - name: $name - class: $class"); // if $_1 ends with //, then we strip $_1 complete & target is also blanked (its an internal link) @@ -938,7 +1115,7 @@ class Basic // PARAMS: none // RETURN: host name // DESC : get the host name without the port as given by the SELF var - public function getHostName() + public function getHostName(): string { $port = ''; if ($_SERVER['HTTP_HOST'] && preg_match("/:/", $_SERVER['HTTP_HOST'])) { @@ -961,7 +1138,7 @@ class Basic // 2: keep filename as is, but add dirname too // RETURN: filename // DESC : get the page name of the curronte page: - public static function getPageName($strip_ext = 0) + public static function getPageName(int $strip_ext = 0): string { // get the file info $page_temp = pathinfo($_SERVER["PHP_SELF"]); @@ -979,7 +1156,7 @@ class Basic // PARAMS: filename // RETURN: extension of the file name // DESC : quick return the extension of the given file name - public static function getFilenameEnding($filename) + public static function getFilenameEnding(string $filename): string { $page_temp = pathinfo($filename); return $page_temp['extension']; @@ -993,7 +1170,7 @@ class Basic // RETURN: array with the elements where the needle can be found in the haystack array // DESC : searches key = value in an array / array // only returns the first one found - public static function arraySearchRecursive($needle, $haystack, $key_lookin = '') + public static function arraySearchRecursive($needle, array $haystack, $key_lookin = ''): ?array { $path = null; if (!is_array($haystack)) { @@ -1025,16 +1202,16 @@ class Basic // path: recursive call for previous path // RETURN: all array elements paths where the element was found // DESC : recursive array search function, which returns all found not only the first one - public static function arraySearchRecursiveAll($needle, $haystack, $key, $path = null) + public static function arraySearchRecursiveAll($needle, array $haystack, $key, $path = null): ?array { if (!isset($path['level'])) { $path['level'] = 0; } if (!isset($path['work'])) { - $path['work'] = array(); + $path['work'] = array (); } if (!isset($haystack)) { - $haystack = array(); + $haystack = array (); } // go through the array, @@ -1068,7 +1245,7 @@ class Basic // PARAMS: array (search in), key (key to search in), value (what to find // RETURN: true on found, false on not found // DESC : array search simple. looks for key, value combination, if found, returns true - public static function arraySearchSimple($array, $key, $value) + public static function arraySearchSimple(array $array, $key, $value): bool { if (!is_array($array)) { $array = array (); @@ -1147,8 +1324,11 @@ class Basic // RETURN: modified array // DESC : searches for key -> value in an array tree and writes the value one level up // this will remove this leaf will all other values - public static function arrayFlatForKey($array, $search) + public static function arrayFlatForKey(array $array, $search): array { + if (!is_array($array)) { + $array = array (); + } foreach ($array as $key => $value) { // if it is not an array do just nothing if (is_array($value)) { @@ -1173,7 +1353,7 @@ class Basic // RETURN: found elements: array // DESC : search for the needle array elements in haystack and return the ones found as an array, // is there nothing found, it returns FALSE (boolean) - public static function inArrayAny($needle, $haystack) + public static function inArrayAny($needle, array $haystack) { if (!is_array($needle)) { return false; @@ -1199,8 +1379,9 @@ class Basic // PARAMS: db array, key, value part, flag if set all or only set // RETURN: returns and associative array // DESC : creates out of a normal db_return array an assoc array - public static function genAssocArray($db_array, $key, $value, $set_only = 0) + public static function genAssocArray(array $db_array, $key, $value, bool $set_only = false): array { + $ret_array = array (); // do this to only run count once for ($i = 0, $iMax = count($db_array); $i < $iMax; $i ++) { // if no key then we make an order reference @@ -1220,13 +1401,12 @@ class Basic // PARAMS: array, connect char // RETRUN: string // DESC : wrapper for join, but checks if input is an array and if not returns null - public static function arrayToString($array, $connect_char) + public static function arrayToString(array $array, string $connect_char): string { if (is_array($array)) { - return join($connect_char, $array); - } else { - return false; + $array = array (); } + return join($connect_char, $array); } // METHOD: flattenArray @@ -1234,7 +1414,7 @@ class Basic // RETURN: returns a flatten array // DESC : converts multi dimensional array to a flat array // does NOT preserve keys - public static function flattenArray(array $array) + public static function flattenArray(array $array): array { $return = array (); array_walk_recursive( @@ -1251,7 +1431,7 @@ class Basic // RETURN: flattened array with array keys as values in order of tree // DESC : note: the second parameter $return is automatically set // will loop through an array recursivly and write the array keys back - public static function flattenArrayKey(array $array, array $return = array ()) + public static function flattenArrayKey(array $array, array $return = array ()): array { foreach ($array as $key => $sub) { $return[] = $key; @@ -1267,7 +1447,7 @@ class Basic // PARAMS: string to encode, encoding to encode in // RETURN: encoded string // DESC : wrapper function for mb mime convert, for correct conversion with long strings - public static function __mbMimeEncode($string, $encoding) + public static function __mbMimeEncode(string $string, string $encoding): string { // set internal encoding, so the mimeheader encode works correctly mb_internal_encoding($encoding); @@ -1301,39 +1481,67 @@ class Basic // PARAMS: int bytes, boolean for space, default is set // RETURN: string // DESC : converts bytes into formated string with KB, MB, etc - public static function byteStringFormat($number, $space = true) + public static function byteStringFormat($number, bool $space = true): string { if (is_numeric($number) && $number > 0) { // labels in order of size - $labels = array('B', 'KB', 'MB', 'GB', 'TB'); + $labels = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB'); // calc file size, round down too two digits, add label based max change - return round($number / pow(1024, ($i = floor(log($number, 1024)))), 2).($space ? ' ' : '').$labels[$i]; + return round($number / pow(1024, ($i = floor(log($number, 1024)))), 2).($space ? ' ' : '').(isset($labels[$i]) ? $labels[$i] : '>EB'); } - return $number; + return (string)$number; } // METHOD: stringByteFormat // WAS : StringByteFormat - // PARAMS: string - // RETURN: int - // DESC : calculates the bytes based on a string with nnG, nnM, etc - public static function stringByteFormat($number) + // PARAMS: some string with byte info, flag if the number is . or , thousand notaded + // RETURN: int or string as is if not mathcing + // DESC : calculates the bytes based on a string with nnG, nnGB, nnM, etc + // if the number has a non standard thousand seperator , inside, the second + // flag needs to be set true (eg german style notaded numbers) + public static function stringByteFormat($number, bool $dot_thousand = false) { - $last = strtolower($number[strlen($number) - 1]); - $number = (int)trim($number); - switch ($last) { - case 't': - $number *= 1024; - // no break, calc down next level - case 'g': - $number *= 1024; - // no break: if we have giga we do first multiplication before the others - case 'm': - $number *= 1024; - // no break: if we have mega, do first before we do final kilo - case 'k': - $number *= 1024; + // detects up to exo bytes + preg_match("/([\d.,]*)\s?(eb|pb|tb|gb|mb|kb|e|p|t|g|m|k|b)$/", strtolower($number), $matches); + if (isset($matches[1]) && isset($matches[2])) { + // $last = strtolower($number[strlen($number) - 1]); + if ($dot_thousand === false) { + $number = str_replace(',', '', $matches[1]); + } else { + $number = str_replace('.', '', $matches[1]); + } + $number = (float)trim($number); + // match string in type to calculate + switch ($matches[2]) { + // exo bytes + case 'e': + case 'eb': + $number *= 1024; + // peta bytes + case 'p': + case 'pb': + $number *= 1024; + // tera bytes + case 't': + case 'tb': + $number *= 1024; + // giga bytes + case 'g': + case 'gb': + $number *= 1024; + // mega bytes + case 'm': + case 'mb': + $number *= 1024; + // kilo bytes + case 'k': + case 'kb': + $number *= 1024; + break; + } + $number = (int)round($number, 0); } + // if not matching return as is return $number; } @@ -1342,7 +1550,7 @@ class Basic // PARAMS: unix timestamp, true/false to show microtime // RETURN: string formated date+time in Y-M-D h:m:s // DESC : a simple wrapper for the date format - public static function dateStringFormat($timestamp, $show_micro = true) + public static function dateStringFormat($timestamp, bool $show_micro = true): string { list ($timestamp, $ms) = explode('.', round($timestamp, 4)); $string = date("Y-m-d H:i:s", $timestamp); @@ -1357,7 +1565,7 @@ class Basic // PARAMS: seconds // RETURN: formated time string // DESC : formats a timestamp into time from. not a date - public static function timeStringFormat($timestamp, $show_micro = true) + public static function timeStringFormat($timestamp, bool $show_micro = true): string { // check if the timestamp has any h/m/s/ms inside, if yes skip if (!preg_match("/(h|m|s|ms)/", (string)$timestamp)) { @@ -1394,7 +1602,7 @@ class Basic // RETURN: timestamp with microseconds // DESC : does a reverse of the TimeStringFormat and converts the string from // xd xh xm xs xms to a timestamp.microtime format - public static function stringToTime($timestring) + public static function stringToTime($timestring): string { $timestamp = 0; if (preg_match("/(d|h|m|s|ms)/", $timestring)) { @@ -1424,7 +1632,7 @@ class Basic // PARAMS: date (YYYY-MM-DD) // RETURN: true if valid date, false if date not valid // DESC : splits & checks date, wrap around for check_date function - public static function checkDate($date) + public static function checkDate($date): bool { list ($year, $month, $day) = preg_split("/[\/-]/", $date); if (!$year || !$month || !$day) { @@ -1441,7 +1649,7 @@ class Basic // PARAMS: date (YYYY-MM-DD) + time (HH:MM:SS), SS can be dropped // RETURN: true if valid date, false if date not valid // DESC : splits & checks date, wrap around for check_date function - public static function checkDateTime($datetime) + public static function checkDateTime($datetime): bool { list ($year, $month, $day, $hour, $min, $sec) = preg_split("/[\/\- :]/", $datetime); if (!$year || !$month || !$day) { @@ -1465,7 +1673,10 @@ class Basic // METHOD: compareDate // WAS : CompareDate // PARAMS: start_date, end_date (both: YYYY-MM-DD) - // RETURN: -1 if the first date is smaller the last, 0 if both are equal, 1 if the first date is bigger than the last + // RETURN: -1 if the first date is smaller the last + // 0 if both are equal + // 1 if the first date is bigger than the last + // false if there are no valid dates to be found // DESC : splits & checks date, wrap around for check_date function public static function compareDate($start_date, $end_date) { @@ -1495,11 +1706,9 @@ class Basic // now do the compare if ($start_date < $end_date) { return -1; - } - if ($start_date == $end_date) { + } elseif ($start_date == $end_date) { return 0; - } - if ($start_date > $end_date) { + } elseif ($start_date > $end_date) { return 1; } } @@ -1507,7 +1716,10 @@ class Basic // METHOD: compareDateTime // WAS : CompareDateTime // PARAMS: start_datetime, end_datetime (both YYYY-MM-DD HH:mm:ss) - // RETURN: -1 if the first date is smaller the last, 0 if both are equal, 1 if the end date is bigger than the last + // RETURN: -1 if the first date is smaller the last + // 0 if both are equal + // 1 if the end date is bigger than the last + // false if no valid date/times chould be found // DESC : compares the two dates + times. if seconds missing in one set, add :00, converts / to - public static function compareDateTime($start_datetime, $end_datetime) { @@ -1519,11 +1731,9 @@ class Basic $end_timestamp = strtotime($end_datetime); if ($start_timestamp < $end_timestamp) { return -1; - } - if ($start_timestamp == $end_timestamp) { + } elseif ($start_timestamp == $end_timestamp) { return 0; - } - if ($start_timestamp > $end_timestamp) { + } elseif ($start_timestamp > $end_timestamp) { return 1; } } @@ -1532,7 +1742,7 @@ class Basic // PARAMS: start date, end date // RETURN: overall days, week days, weekend days as array 0...2 or named // DESC : calculates the days between two dates - public static function calcDaysInterval($start_date, $end_date, $return_named = false) + public static function calcDaysInterval($start_date, $end_date, bool $return_named = false): array { // pos 0 all, pos 1 weekday, pos 2 weekend $days = array (); @@ -1575,7 +1785,7 @@ class Basic // clear cache -> if set to true, will create thumb all the tame // RETURN: thumbnail name // DESC : converts picture to a thumbnail with max x and max y size - public static function createThumbnail($pic, $size_x, $size_y, $dummy = "", $path = "", $cache_source = "", $clear_cache = false) + public static function createThumbnail($pic, $size_x, $size_y, $dummy = "", $path = "", $cache_source = "", bool $clear_cache = false) { // get image type flags $image_types = array ( @@ -1696,7 +1906,7 @@ class Basic // if check to ISO-2022-JP-MS // set three dots (∴) as wrong character for correct convert error detect // (this char is used, because it is one of the least used ones) - public function checkConvertEncoding($string, $from_encoding, $to_encoding) + public function checkConvertEncoding(string $string, string $from_encoding, string $to_encoding) { // convert to target encoding and convert back $temp = mb_convert_encoding($string, $to_encoding, $from_encoding); @@ -1726,7 +1936,7 @@ class Basic // optional source encoding // RETURN: converted string // DESC : detects the source encoding of the string and if doesn't match to the given target encoding it convert is - public static function convertEncoding($string, $to_encoding, $source_encoding = '') + public static function convertEncoding(string $string, string $to_encoding, string $source_encoding = ''): string { // set if not given if (!$source_encoding) { @@ -1747,7 +1957,7 @@ class Basic // PARAMS: string // RETURN: old (wrong) crc32b hash // DESC : checks php version and if >=5.2.7 it will flip the string - public function __crc32b($string) + public function __crc32b(string $string): string { // do normal hash crc32b $string = hash('crc32b', $string); @@ -1764,7 +1974,7 @@ class Basic // PARAMS: string, flag to use sha // RETURN: sha1 short (9 chars), but current calls __crc32b // DESC : replacement for __crc32b call - public function __sha1Short($string, $use_sha = false) + public function __sha1Short(string $string, bool $use_sha = false): string { if ($use_sha) { return substr(hash('sha1', $string), 0, 9); @@ -1780,7 +1990,7 @@ class Basic // DESC : replacemend for __crc32b call (alternate) // defaults to adler 32, fnv132, fnv1a32, joaat // all that create 8 char long hashes - public function __hash($string, $hash_type = 'adler32') + public function __hash(string $string, string $hash_type = 'adler32'): string { if (!in_array($hash_type, array('adler32', 'fnv132', 'fnv1a32', 'joaat'))) { $hash_type = 'adler32'; @@ -1793,7 +2003,7 @@ class Basic // $max_version: default empty, else in same format as min version // RETURN: true if ok, false if not matching version // DESC : checks if running PHP version matches given PHP version (min or max) - public static function checkPHPVersion($min_version, $max_version = '') + public static function checkPHPVersion(string $min_version, string $max_version = ''): bool { // exit with false if the min/max strings are wrong if (!preg_match("/^\d{1}(\.\d{1})?(\.\d{1,2})?$/", $min_version)) { @@ -1952,7 +2162,7 @@ class Basic // RETURN: none // DESC : inits the password options set // currently this is et empty, and the default options are used - private function passwordInit() + private function passwordInit(): void { // set default password cost: use default set automatically $this->password_options = array ( @@ -1964,7 +2174,7 @@ class Basic // PARAMS: password // RETURN: hashed password // DESC : creates the password hash - public function passwordSet($password) + public function passwordSet(string $password): string { // always use the PHP default for the password // password options ca be set in the password init, but should be kept as default @@ -1975,7 +2185,7 @@ class Basic // PARAMS: password and hash // RETURN: true or false // DESC : checks if the entered password matches the hash - public function passwordVerify($password, $hash) + public function passwordVerify(string $password, string $hash): bool { if (password_verify($password, $hash)) { return true; @@ -1990,7 +2200,7 @@ class Basic // PARAMS: hash // RETURN: true or false // DESC : checks if the password needs to be rehashed - public function passwordRehashCheck($hash) + public function passwordRehashCheck(string $hash): bool { if (password_needs_rehash($hash, PASSWORD_DEFAULT, $this->password_options)) { return true; @@ -2007,7 +2217,7 @@ class Basic // PARAMS: hexstring, flag to return as string (true/false), string seperator: default: , // RETURN: array with RGB or a string with the seperator // DESC : converts a hex RGB color to the int numbers - public static function hex2rgb($hexStr, $returnAsString = false, $seperator = ',') + public static function hex2rgb(string $hexStr, bool $returnAsString = false, string $seperator = ',') { $hexStr = preg_replace("/[^0-9A-Fa-f]/", '', $hexStr); // Gets a proper hex string $rgbArray = array(); @@ -2032,7 +2242,7 @@ class Basic // PARAMS: red, green, blue (0-255) // RETURN: string with hex rgb color plus # in front // DESC : converts the rgb values from int data to the valid rgb html hex string - public static function rgb2hex($red, $green, $blue) + public static function rgb2hex(int $red, int $green, int $blue): string { $hex_color = '#'; foreach (array ('red', 'green', 'blue') as $color) { @@ -2046,7 +2256,7 @@ class Basic // PARAMS: red, green, blue (0-255) // RETURN: array with hue (0-360), sat (0-100%), brightness/value (0-100%) // DESC : converts RGB to HSB/V values - public static function rgb2hsb($r, $g, $b) + public static function rgb2hsb(int $r, int $g, int $b): array { // check that rgb is from 0 to 255 foreach (array('r', 'g', 'b') as $c) { @@ -2081,7 +2291,7 @@ class Basic // PARAMS: hue (0-360), saturation (0-1), brightness/value (0-1) // RETURN: array with red, blue, green // DESC : converts HSB/V to RGB values RGB is full INT - public static function hsb2rgb($H, $S, $V) + public static function hsb2rgb(int $H, int $S, int $V): array { // check that H is 0 to 359, 360 = 0 // and S and V are 0 to 1 @@ -2149,7 +2359,7 @@ class Basic // PARAMS: red, blue, green (all 0-255) // RETURN: array with hue (0-360), saturation (0-100%) and luminance (0-100%) // DESC : converts a RGB (0-255) to HSL - public static function rgb2hsl($r, $g, $b) + public static function rgb2hsl(int $r, int $g, int $b): array { // check that rgb is from 0 to 255 foreach (array('r', 'g', 'b') as $c) { @@ -2193,7 +2403,7 @@ class Basic // luminance: 0-1 // RETURN: array with RGB as full int // DESC : converts an HSL to RGB - public static function hsl2rgb($h, $s, $l) + public static function hsl2rgb(int $h, int $s, int $l): array { $h = (1 / 360) * $h; // calc to internal convert value for hue // if saturation is 0 @@ -2228,7 +2438,7 @@ class Basic // PARAMS: red, green, blue // RETRUN valid # prefix hex html color string // DESC : converts and int RGB to the HTML color string in hex format - public static function rgb2html($red, $green, $blue) + public static function rgb2html(int $red, int $green, int $blue): string { // check that each color is between 0 and 255 foreach (array('red', 'green', 'blue') as $color) { @@ -2249,11 +2459,11 @@ class Basic // RETURN: string for email type, eg "pc", "docomo", etc // DESC : guesses the email type (mostly for mobile) from the domain // if second is set to true, it will return short naming scheme (only provider) - public function getEmailType($email, $short = false) + public function getEmailType(string $email, bool $short = false): string { // trip if there is no email address if (!$email) { - return "invalid"; + return 'invalid'; } // loop until we match a mobile type, return this first found type foreach ($this->mobile_email_type as $email_regex => $email_type) { @@ -2267,9 +2477,9 @@ class Basic } // if no previous return we assume this is a pc address if ($short) { - return "pc"; + return 'pc'; } else { - return "pc_html"; + return 'pc_html'; } } @@ -2277,9 +2487,15 @@ class Basic // PARAMS: long email type (not email) // RETURN: short email type // DESC : gets the short email type from a long email type - public function getShortEmailType($email_type) + public function getShortEmailType(string $email_type) { - return $this->mobile_email_type_short[$email_type]; + // check if the short email type exists + if (isset($this->mobile_email_type_short[$email_type])) { + return $this->mobile_email_type_short[$email_type]; + } else { + // return false on not found + return false; + } } // METHOD: printDateTime @@ -2291,7 +2507,7 @@ class Basic // after the drop down and not before the drop down // RETURN: HTML formated strings for drop down lists of date and time // DESC : print the date/time drop downs, used in any queue/send/insert at date/time place - public static function printDateTime($year, $month, $day, $hour, $min, $suffix = '', $min_steps = 1, $name_pos_back = false) + public static function printDateTime($year, $month, $day, $hour, $min, string $suffix = '', int $min_steps = 1, bool $name_pos_back = false) { // if suffix given, add _ before if ($suffix) { @@ -2383,7 +2599,7 @@ class Basic // PARAMS: string to encode // RETURN: encoded string // DESC : full wrapper for html entities - public function htmlent($string) + public function htmlent(string $string): string { if (is_string($string)) { return htmlentities($string, ENT_COMPAT|ENT_HTML401, 'UTF-8', false); @@ -2396,7 +2612,7 @@ class Basic // PARAMS: string, optional replace character // RETURN: string with line breaks removed // DESC : strips out all line breaks or replaced with given string - public function removeLB($string, $replace = ' ') + public function removeLB(string $string, string $replace = ' '): string { return str_replace(array("\r", "\n"), $replace, $string); } @@ -2405,7 +2621,7 @@ class Basic // PARAMS: number, round decimals (default 10) // RETURN: correct ceil number // DESC : some float numbers will be rounded up even if they have no decimal entries - public function fceil($number, $precision = 10) + public function fceil(float $number, int $precision = 10): float { return ceil(round($number, $precision)); } @@ -2414,7 +2630,7 @@ class Basic // PARAMS: number, round to // RETURN: floor number but with tround to // DESC : eg 48767 with -2 -> 48700 - public function floorp($number, $precision = -2) + public function floorp(float $number, int $precision = -2): float { $mult = pow(10, $precision); // Can be cached in lookup table return floor($number * $mult) / $mult; @@ -2424,7 +2640,7 @@ class Basic // PARAMS: any value // RETURN: if not numeric, sets to 0, else returns value already set // DESC : inits input to 0, if value is not numeric - public function initNumeric($number) + public function initNumeric(float $number): float { if (!is_numeric($number)) { return 0; @@ -2437,7 +2653,7 @@ class Basic // PARAMS: session name, if not set then default is form_token // RETURN: form token // DESC : sets a form token in a session and returns form token - public function setFormToken($name = 'form_token') + public function setFormToken(string $name = 'form_token'): string { // current hard set to sha256 $token = uniqid(hash('sha256', rand())); @@ -2449,9 +2665,13 @@ class Basic // PARAMS: form token, session name (default form_token) // RETURN: true or false // DESC : checks if the form token matches the session set form token - public function validateFormToken($token, $name = 'form_token') + public function validateFormToken(string $token, string $name = 'form_token'): bool { - return $_SESSION[$name] === $token; + if (isset($_SESSION[$name])) { + return $_SESSION[$name] === $token; + } else { + return false; + } } // ************************************************************* diff --git a/www/lib/CoreLibs/DB/Extended/ArrayIO.inc b/www/lib/CoreLibs/DB/Extended/ArrayIO.inc index 4d65107c..e911d6bd 100644 --- a/www/lib/CoreLibs/DB/Extended/ArrayIO.inc +++ b/www/lib/CoreLibs/DB/Extended/ArrayIO.inc @@ -19,6 +19,7 @@ * PRIVATE METHOD:S * * HISTORY: +* 2019/9/11 (cs) error string 21->91, 22->92 for not overlapping with IO * 2005/07/07 (cs) updated array class for postgres: set 0 & NULL if int field given, insert uses () values () syntax * 2005/03/31 (cs) fixed the class call with all debug vars * 2003-03-10: error_ids where still wrong chagned 11->21 and 12->22 @@ -51,17 +52,17 @@ class ArrayIO extends \CoreLibs\DB\IO // PARAMS: db_config -> db_io class init vars // table_array -> the array from the table // table_name -> name of the table (for the array) - // db_debug -> turn on db_io debug output (DB_DEBUG as global var does the same) + // set_control_flag -> set basic class set/get variable error flags // RETURN: none // DESC : constructor for the array io class, set the // primary key name automatically (from array) - public function __construct($db_config, $table_array, $table_name, $debug = 0, $db_debug = 0, $echo = 1, $print = 0) + public function __construct(array $db_config, array $table_array, string $table_name, int $set_control_flag = 0) { // instance db_io class - parent::__construct($db_config, $debug, $db_debug, $echo, $print); + parent::__construct($db_config, $set_control_flag); // more error vars for this class - $this->error_string['21'] = 'No Primary Key given'; - $this->error_string['22'] = 'Could not run Array Query'; + $this->error_string['91'] = 'No Primary Key given'; + $this->error_string['92'] = 'Could not run Array Query'; $this->table_array = $table_array; $this->table_name = $table_name; @@ -75,12 +76,13 @@ class ArrayIO extends \CoreLibs\DB\IO } } // set pk_name IF table_array was given // internal - $this->class_info['db_array_io'] = array( + $this->class_info['db_array_io'] = array ( 'class_name' => 'DB Array IO', 'class_version' => '1.0.0', 'class_created' => '2002/12/17', 'class_author' => 'Clemens Schwaighofer' ); + // echo "CALSS INFO POST [A]:
".print_r($this->class_info, true)."

"; } // deconstruktor @@ -158,7 +160,7 @@ class ArrayIO extends \CoreLibs\DB\IO // if not set ... produce error if (!$this->table_array[$this->pk_name]['value']) { // if no PK found, error ... - $this->error_id = 21; + $this->error_id = 91; $this->__dbError(); return 0; } else { @@ -234,7 +236,7 @@ class ArrayIO extends \CoreLibs\DB\IO // if 0, error unset($this->pk_id); if (!$this->dbExec($q)) { - $this->error_id=22; + $this->error_id = 92; $this->__dbError(); } return $this->table_array; @@ -306,7 +308,7 @@ class ArrayIO extends \CoreLibs\DB\IO // possible dbFetchArray errors ... $this->pk_id = $this->table_array[$this->pk_name]['value']; } else { - $this->error_id = 22; + $this->error_id = 92; $this->__dbError(); } return $this->table_array; @@ -514,7 +516,7 @@ class ArrayIO extends \CoreLibs\DB\IO } // return success or not if (!$this->dbExec($q)) { - $this->error_id = 22; + $this->error_id = 92; $this->__dbError(); } // set primary key diff --git a/www/lib/CoreLibs/DB/IO.inc b/www/lib/CoreLibs/DB/IO.inc index 1b754a80..34a8bd4c 100644 --- a/www/lib/CoreLibs/DB/IO.inc +++ b/www/lib/CoreLibs/DB/IO.inc @@ -270,14 +270,16 @@ class IO extends \CoreLibs\Basic public $cursor; // actual cursor (DBH) public $num_rows; // how many rows have been found public $num_fields; // how many fields has the query - public $field_names; // array with the field names of the current query + public $field_names = array (); // array with the field names of the current query public $insert_id; // last inserted ID public $insert_id_ext; // extended insert ID (for data outside only primary key) + private $temp_sql; // other vars private $nbsp = ''; // used by print_array recursion function // error & warning id private $error_id; private $warning_id; + private $had_warning; // sub include with the database functions private $db_functions; @@ -285,7 +287,7 @@ class IO extends \CoreLibs\Basic private $MAX_QUERY_CALL; private $query_called = array (); // error string - private $error_string = array (); + protected $error_string = array (); // prepared list public $prepare_cursor = array (); // primary key per table list @@ -300,14 +302,13 @@ class IO extends \CoreLibs\Basic // METHOD __construct // PARAMS db_config -> array with db, user, password & host - // debug -> turns debugging output on or of (default 0), - // debugging can also be triggerd via DB_DEBUG var on global level + // set_control_flag -> flags for core class get/set variable error handling // RETURN nothing // DESC constructor for db_clss - public function __construct($db_config, $debug = 0, $db_debug = 0, $echo = 1, $print = 0) + public function __construct(array $db_config, int $set_control_flag = 0) { // start basic class - parent::__construct($debug, $echo, $print); + parent::__construct($set_control_flag); // dummy init array for db config if not array if (!is_array($db_config)) { $db_config = array (); @@ -355,7 +356,7 @@ class IO extends \CoreLibs\Basic $this->error_string['42'] = 'Cannot check for async query, none has been started yet.'; // set debug, either via global var, or debug var during call - $this->db_debug = $db_debug; + $this->db_debug = false; // global overrules local if (isset($GLOBALS['DB_DEBUG'])) { $this->db_debug = $GLOBALS['DB_DEBUG']; @@ -389,7 +390,7 @@ class IO extends \CoreLibs\Basic 'class_author' => 'Clemens Schwaighofer' ); - // all ok return true + // so we can check that we have a successful DB connection created return true; } @@ -414,7 +415,7 @@ class IO extends \CoreLibs\Basic // DESC : // internal connection function. Used to connect to the DB if there is no connection done yet. // Called before any execute - private function __connectToDB() + private function __connectToDB(): bool { // generate connect string $this->dbh = $this->db_functions->__dbConnect($this->db_host, $this->db_user, $this->db_pwd, $this->db_name, $this->db_port, $this->db_ssl); @@ -449,7 +450,7 @@ class IO extends \CoreLibs\Basic // RETURN: none // DESC : close db connection // only used by the deconstructor - private function __closeDB() + private function __closeDB(): void { if (isset($this->dbh) && $this->dbh) { $this->db_functions->__dbClose(); @@ -463,7 +464,7 @@ class IO extends \CoreLibs\Basic // RETURN: true if matching, false if not // DESC : checks if query is a SELECT, SHOW or WITH, if not error, 0 return // NOTE : Query needs to start with SELECT, SHOW or WITH. if starts with "with" it is ignored - private function __checkQueryForSelect($query) + private function __checkQueryForSelect(string $query): bool { // perhaps allow spaces before select ?!? if (preg_match("/^(select|show|with) /i", $query)) { @@ -479,7 +480,7 @@ class IO extends \CoreLibs\Basic // DESC : check for DELETE, INSERT, UPDATE // : if pure is set to true, only when INSERT is set will return true // NOTE : Queries need to start with INSERT, UPDATE, DELETE. Anything else is ignored - private function __checkQueryForInsert($query, $pure = false) + private function __checkQueryForInsert(string $query, bool $pure = false): bool { if ($pure && preg_match("/^insert /i", $query)) { return true; @@ -495,7 +496,7 @@ class IO extends \CoreLibs\Basic // RETURN: true if UPDATE, else false // DESC : returns true if the query starts with UPDATE // NOTE : query NEEDS to start with UPDATE - private function __checkQueryForUpdate($query) + private function __checkQueryForUpdate(string $query): bool { if (preg_match("/^update /i", $query)) { return true; @@ -509,9 +510,12 @@ class IO extends \CoreLibs\Basic // RETURN: string with printed and formated array // DESC : internal funktion that creates the array // NOTE : used in db_dump_data only - private function __printArray($array) + private function __printArray(array $array): string { $string = ''; + if (!is_array($array)) { + $array = array (); + } foreach ($array as $key => $value) { $string .= $this->nbsp.''.$key.' => '; if (is_array($value)) { @@ -534,7 +538,7 @@ class IO extends \CoreLibs\Basic // type -> query identifiery (Q, I, etc) // RETURN: none // DESC : calls the basic class debug with strip command - private function __dbDebug($debug_id, $error_string, $id = '', $type = '') + private function __dbDebug(string $debug_id, string $error_string, string $id = '', string $type = ''): void { $prefix = ''; if ($id) { @@ -557,7 +561,7 @@ class IO extends \CoreLibs\Basic // RETURN: none // DESC : if error_id set, writes long error string into error_msg // NOTE : needed to make public so it can be called from DB.Array.IO too - public function __dbError($cursor = '', $msg = '') + public function __dbError($cursor = '', string $msg = ''): void { $pg_error_string = ''; $where_called = $this->getCallerMethod(); @@ -591,15 +595,15 @@ class IO extends \CoreLibs\Basic // PARAMS: array from fetch_row // RETURN: convert fetch_row array // DESC : if there is the 'to_encoding' var set, and the field is in the wrong encoding converts it to the target - private function __dbConvertEncoding($row) + private function __dbConvertEncoding(array $row): array { if ($this->to_encoding && $this->db_encoding) { // go through each row and convert the encoding if needed - for ($i = 0; $i < $this->num_fields; $i ++) { - $from_encoding = mb_detect_encoding($row[$i]); + foreach ($row as $key => $value) { + $from_encoding = mb_detect_encoding($value); // convert only if encoding doesn't match and source is not pure ASCII if ($from_encoding != $this->to_encoding && $from_encoding != 'ASCII') { - $row[$i] = mb_convert_encoding($row[$i], $this->to_encoding, $from_encoding); + $row[$key] = mb_convert_encoding($value, $this->to_encoding, $from_encoding); } } } @@ -611,7 +615,7 @@ class IO extends \CoreLibs\Basic // PARAMS: $stm_name, data array // RETURN: query in prepared form // DESC : for debug purpose replaces $1, $2, etc with actual data - private function __dbDebugPrepare($stm_name, $data = array()) + private function __dbDebugPrepare(string $stm_name, array $data = array()): string { // get the keys from data array $keys = array_keys($data); @@ -628,7 +632,7 @@ class IO extends \CoreLibs\Basic // PARAMS: insert/select/update/delete query // RETURN: array with schema and table // DESC : extracts schema and table from the query, if no schema returns just empty string - private function __dbReturnTable($query) + private function __dbReturnTable(string $query): array { if (preg_match("/^SELECT /i", $query)) { preg_match("/ (FROM) (([\w_]+)\.)?([\w_]+) /i", $query, $matches); @@ -649,7 +653,7 @@ class IO extends \CoreLibs\Basic // * checks for insert if returning is set/pk name // * sets internal md5 for query // * checks multiple call count - private function __dbPrepareExec($query, $pk_name) + private function __dbPrepareExec(string $query, string $pk_name) { // to either use the returning method or the guess method for getting primary keys $this->returning_id = false; @@ -741,7 +745,7 @@ class IO extends \CoreLibs\Basic // PARAMS: none // RETURN: true on success or false if an error occured // DESC : runs post execute for rows affected, field names, inserted primary key, etc - private function __dbPostExec() + private function __dbPostExec(): bool { // if FALSE returned, set error stuff // if either the cursor is false @@ -762,7 +766,7 @@ class IO extends \CoreLibs\Basic // count the fields $this->num_fields = $this->db_functions->__dbNumFields($this->cursor); // set field names - unset($this->field_names); + $this->field_names = array (); for ($i = 0; $i < $this->num_fields; $i ++) { $this->field_names[] = $this->db_functions->__dbFieldName($this->cursor, $i); } @@ -1177,7 +1181,7 @@ class IO extends \CoreLibs\Basic // like num_rows, num_fields, etc depending on query // for INSERT INTO queries it is highly recommended to set the pk_name to avoid an additional // read from the database for the PK NAME - public function dbExec($query = 0, $pk_name = '') + public function dbExec(string $query = '', string $pk_name = '') { // prepare and check if we can actually run it if (($md5 = $this->__dbPrepareExec($query, $pk_name)) === false) { @@ -1204,7 +1208,7 @@ class IO extends \CoreLibs\Basic // for INSERT INTO queries it is highly recommended to set the pk_name to avoid an additional // read from the database for the PK NAME // NEEDS : dbCheckAsync - public function dbExecAsync($query, $pk_name = '') + public function dbExecAsync(string $query, string $pk_name = ''): bool { // prepare and check if we can actually run the query if (($md5 = $this->__dbPrepareExec($query, $pk_name)) === false) { @@ -1262,7 +1266,7 @@ class IO extends \CoreLibs\Basic // assoc_only -> false is default, if true only assoc rows // RETURN: a mixed row // DESC : executes a cursor and returns the data, if no more data 0 will be returned - public function dbFetchArray($cursor = 0, $assoc_only = false) + public function dbFetchArray($cursor = 0, bool $assoc_only = false) { // return false if no query or cursor set ... if (!$cursor) { @@ -1287,7 +1291,7 @@ class IO extends \CoreLibs\Basic // assoc_only -> if true, only return assoc entry, else both (pgsql) // RETURN: mixed db result // DESC : returns the FIRST row of the given query - public function dbReturnRow($query, $assoc_only = false) + public function dbReturnRow(string $query, bool $assoc_only = false) { if (!$query) { $this->error_id = 11; @@ -1311,7 +1315,7 @@ class IO extends \CoreLibs\Basic // assoc_only -> if true, only name ref are returned // RETURN: array of hashes (row -> fields) // DESC : createds an array of hashes of the query (all data) - public function dbReturnArray($query, $assoc_only = false) + public function dbReturnArray(string $query, bool $assoc_only = false) { if (!$query) { $this->error_id = 11; @@ -1339,7 +1343,7 @@ class IO extends \CoreLibs\Basic // PARAMS: $query -> query to find in cursor_ext // RETURN: position (int) // DESC : returns the current position the read out - public function dbCursorPos($query) + public function dbCursorPos(string $query) { if (!$query) { $this->error_id = 11; @@ -1355,7 +1359,7 @@ class IO extends \CoreLibs\Basic // PARAMS: $query -> query to find in cursor_ext // RETURN: row count (int) // DESC : returns the number of rows for the current select query - public function dbCursorNumRows($query) + public function dbCursorNumRows(string $query) { if (!$query) { $this->error_id = 11; @@ -1370,9 +1374,9 @@ class IO extends \CoreLibs\Basic // WAS : db_show_table_meta_data // PARAMS: $table -> table name // $schema -> optional schema name - // RETURN: array of table data + // RETURN: array of table data, false on error (table not found) // DESC : returns an array of the table with columns and values. FALSE on no table found - public function dbShowTableMetaData($table, $schema = '') + public function dbShowTableMetaData(string $table, string $schema = '') { $table = ($schema ? $schema.'.' : '').$table; @@ -1386,11 +1390,11 @@ class IO extends \CoreLibs\Basic // METHOD: dbPrepare // WAS : db_prepare // PARAMS: $stm_name, $query, $pk_name: optional - // RETURN: false on error + // RETURN: false on error, true on warning or result on full ok // DESC : prepares a query // for INSERT INTO queries it is highly recommended to set the pk_name to avoid an additional // read from the database for the PK NAME - public function dbPrepare($stm_name, $query, $pk_name = '') + public function dbPrepare(string $stm_name, string $query, string $pk_name = '') { if (!$query) { $this->error_id = 11; @@ -1469,9 +1473,9 @@ class IO extends \CoreLibs\Basic // METHOD: dbExecute // WAS : db_execute // PARAMS: $stm_name, data array - // RETURN: false on error + // RETURN: false on error, result on OK // DESC : runs a prepare query - public function dbExecute($stm_name, $data = array()) + public function dbExecute(string $stm_name, array $data = array()) { // if we do not have no prepare cursor array entry for this statement name, abort if (!is_array($this->prepare_cursor[$stm_name])) { @@ -1492,22 +1496,25 @@ class IO extends \CoreLibs\Basic if ($this->db_debug) { $this->__dbDebug('db', $this->__dbDebugPrepare($stm_name, $data), 'dbExecPrep', 'Q'); } - $code = $this->db_functions->__dbExecute($stm_name, $data); - if (!$code) { + $result = $this->db_functions->__dbExecute($stm_name, $data); + if (!$result) { $this->debug('ExecuteData', 'ERROR in STM['.$stm_name.'|'.$this->prepare_cursor[$stm_name]['result'].']: '.$this->print_ar($data)); $this->error_id = 22; $this->__dbError($this->prepare_cursor[$stm_name]['result']); $this->__dbDebug('db', 'DB-Error '.$stm_name.': Execution failed', 'DB_ERROR'); + return false; } - if ($this->__checkQueryForInsert($this->prepare_cursor[$stm_name]['query'], true) && $this->prepare_cursor[$stm_name]['pk_name'] != 'NULL') { + if ($this->__checkQueryForInsert($this->prepare_cursor[$stm_name]['query'], true) && + $this->prepare_cursor[$stm_name]['pk_name'] != 'NULL' + ) { if (!$this->prepare_cursor[$stm_name]['returning_id']) { $this->insert_id = $this->db_functions->__dbInsertId($this->prepare_cursor[$stm_name]['query'], $this->prepare_cursor[$stm_name]['pk_name']); - } elseif ($code) { + } elseif ($result) { $this->insert_id = array (); $this->insert_id_ext = array (); // we have returning, now we need to check if we get one or many returned // we'll need to loop this, if we have multiple insert_id returns - while ($_insert_id = $this->db_functions->__dbFetchArray($code, PGSQL_ASSOC)) { + while ($_insert_id = $this->db_functions->__dbFetchArray($result, PGSQL_ASSOC)) { $this->insert_id[] = $_insert_id; } // if we have only one, revert from arry to single @@ -1517,7 +1524,9 @@ class IO extends \CoreLibs\Basic // if this has only the pk_name, then only return this, else array of all data (but without the position) // example if insert_id[0]['foo'] && insert_id[0]['bar'] it will become insert_id['foo'] & insert_id['bar'] // if only ['foo_id'] and it is the PK then the PK is directly written to the insert_id - if (count($this->insert_id[0]) > 1 || !array_key_exists($this->prepare_cursor[$stm_name]['pk_name'], $this->insert_id[0])) { + if (count($this->insert_id[0]) > 1 || + !array_key_exists($this->prepare_cursor[$stm_name]['pk_name'], $this->insert_id[0]) + ) { $this->insert_id_ext = $this->insert_id[0]; $this->insert_id = $this->insert_id[0][$this->prepare_cursor[$stm_name]['pk_name']]; } elseif ($this->insert_id[0][$this->prepare_cursor[$stm_name]['pk_name']]) { @@ -1543,7 +1552,7 @@ class IO extends \CoreLibs\Basic $this->__dbDebug('db', 'DB-Warning '.$stm_name.': Could not get insert id', 'DB_WARNING'); } } - return $code; + return $result; } } @@ -1552,7 +1561,7 @@ class IO extends \CoreLibs\Basic // PARAMS: $string -> string to escape // RETURN: escaped string // DESC : neutral function to escape a string for DB writing - public function dbEscapeString($string) + public function dbEscapeString(string $string): string { return $this->db_functions->__dbEscapeString($string); } @@ -1572,7 +1581,7 @@ class IO extends \CoreLibs\Basic // PARAMS: none // RETURN: database version as string // DESC : return current database version - public function dbVersion() + public function dbVersion(): string { return $this->db_functions->__dbVersion(); } @@ -1583,7 +1592,7 @@ class IO extends \CoreLibs\Basic // =X.Y, >X.Y, , < prefix, and gets stripped, if the rest is not X.Y format then error preg_match("/^([<>=]{1,})(\d{1,})\.(\d{1,})/", $compare, $matches); @@ -1700,6 +1709,7 @@ class IO extends \CoreLibs\Basic // -> alternate the primary key can be an array with // 'row' => 'row name', 'value' => 'data' to use a // different column as the primary key + // !!! primary key can be an array or a number/string // table -> name for the target table // (optional) // not_write_array -> list of elements not to write @@ -1707,13 +1717,21 @@ class IO extends \CoreLibs\Basic // data -> optional array with data, if not _POST vars are used // RETURN: primary key id // DESC : writes into one table based on array of table columns - public function dbWriteDataExt($write_array, $primary_key, $table, $not_write_array = array (), $not_write_update_array = array (), $data = array ()) - { + public function dbWriteDataExt( + array $write_array, + $primary_key, + string $table, + array $not_write_array = array (), + array $not_write_update_array = array (), + array $data = array () + ) { if (!is_array($primary_key)) { $primary_key = array ( 'row' => $table.'_id', 'value' => $primary_key ); + } elseif (!isset($primary_key['value'])) { + $primary_key['value'] = ''; } // var set for strings $q_sub_value = ''; @@ -1799,7 +1817,7 @@ class IO extends \CoreLibs\Basic // micro on off (default false) // RETURN: Y/M/D/h/m/s formatted string (like TimeStringFormat // DESC : only for postgres. pretty formats an age or datetime difference string - public function dbTimeFormat($age, $show_micro = false) + public function dbTimeFormat(string $age, bool $show_micro = false): string { // in string (datetime diff): 1786 days 22:11:52.87418 // or (age): 4 years 10 mons 21 days 12:31:11.87418 @@ -1821,7 +1839,7 @@ class IO extends \CoreLibs\Basic // PARAMS: text: input text to parse to an array // RETURN: PHP array of the parsed data // DESC : this is only needed for Postgresql. Converts postgresql arrays to PHP - public function dbArrayParse($text) + public function dbArrayParse(string $text): array { $output = array (); return $this->db_functions->__dbArrayParse($text, $output); @@ -1833,23 +1851,23 @@ class IO extends \CoreLibs\Basic // kbn -> escape trigger type // RETURN: escaped value // DESC : clear up any data for valid DB insert - public function dbSqlEscape($value, $kbn = "") + public function dbSqlEscape($value, string $kbn = '') { switch ($kbn) { - case "i": - $value = (!isset($value) || $value === "") ? "NULL" : intval($value); + case 'i': + $value = (!isset($value) || $value === '') ? "NULL" : intval($value); break; - case "f": - $value = (!isset($value) || $value === "") ? "NULL" : floatval($value); + case 'f': + $value = (!isset($value) || $value === '') ? "NULL" : floatval($value); break; - case "t": - $value = (!isset($value) || $value === "") ? "NULL" : "'".$this->dbEscapeString($value)."'"; + case 't': + $value = (!isset($value) || $value === '') ? "NULL" : "'".$this->dbEscapeString($value)."'"; break; - case "d": - $value = (!isset($value) || $value === "") ? "NULL" : "'".$this->dbEscapeString($value)."'"; + case 'd': + $value = (!isset($value) || $value === '') ? "NULL" : "'".$this->dbEscapeString($value)."'"; break; - case "i2": - $value = (!isset($value) || $value === "") ? 0 : intval($value); + case 'i2': + $value = (!isset($value) || $value === '') ? 0 : intval($value); break; } return $value; @@ -2022,7 +2040,7 @@ class IO extends \CoreLibs\Basic return $this->dbCacheReset($query); } - public function db_exec($query = 0, $pk_name = '') + public function db_exec($query = '', $pk_name = '') { error_log('DEPRECATED CALL: '.__METHOD__.', '.__FILE__.':'.__LINE__.', '.debug_backtrace()[0]['file'].':'.debug_backtrace()[0]['line']); trigger_error('Method '.__METHOD__.' is deprecated', E_USER_DEPRECATED); @@ -2057,7 +2075,7 @@ class IO extends \CoreLibs\Basic return $this->dbReturnRow($query); } - public function db_return_array($query, $named_only = 0) + public function db_return_array($query, $named_only = false) { error_log('DEPRECATED CALL: '.__METHOD__.', '.__FILE__.':'.__LINE__.', '.debug_backtrace()[0]['file'].':'.debug_backtrace()[0]['line']); trigger_error('Method '.__METHOD__.' is deprecated', E_USER_DEPRECATED); diff --git a/www/lib/CoreLibs/Language/Core/GetTextReader.inc b/www/lib/CoreLibs/Language/Core/GetTextReader.inc index a2270d2a..061c125c 100755 --- a/www/lib/CoreLibs/Language/Core/GetTextReader.inc +++ b/www/lib/CoreLibs/Language/Core/GetTextReader.inc @@ -50,7 +50,7 @@ class GetTextReader private $total = 0; // total string count private $table_originals = null; // table for original strings (offsets) private $table_translations = null; // table for translated strings (offsets) - private $cache_translations = null; // original -> translation mapping + private $cache_translations = array (); // original -> translation mapping /* Methods */ @@ -272,7 +272,7 @@ class GetTextReader if ($this->enable_cache) { // Caching enabled, get translated string from cache - if (array_key_exists($string, $this->cache_translations)) { + if (is_array($this->cache_translations) && array_key_exists($string, $this->cache_translations)) { return $this->cache_translations[$string]; } else { return $string; @@ -355,7 +355,7 @@ class GetTextReader // cache header field for plural forms if (! is_string($this->pluralheader)) { if ($this->enable_cache) { - $header = $this->cache_translations[""]; + $header = $this->cache_translations['']; } else { $header = $this->get_translation_string(0); } @@ -415,7 +415,7 @@ class GetTextReader $key = $single . chr(0) . $plural; if ($this->enable_cache) { - if (! array_key_exists($key, $this->cache_translations)) { + if (is_array($this->cache_translations) && !array_key_exists($key, $this->cache_translations)) { return ($number != 1) ? $plural : $single; } else { $result = $this->cache_translations[$key]; diff --git a/www/lib/CoreLibs/Language/L10n.inc b/www/lib/CoreLibs/Language/L10n.inc index 31479324..8c99a3ab 100644 --- a/www/lib/CoreLibs/Language/L10n.inc +++ b/www/lib/CoreLibs/Language/L10n.inc @@ -35,7 +35,7 @@ class L10n extends \CoreLibs\Basic private $input; private $l10n; - public function __construct($lang = '', $path = '') + public function __construct(string $lang = '', string $path = '') { if (!$lang) { $this->lang = 'en'; @@ -60,7 +60,7 @@ class L10n extends \CoreLibs\Basic } // reloads the mofile, if the location of the lang file changes - public function l10nReloadMOfile($lang, $path = '') + public function l10nReloadMOfile(string $lang, string $path = ''): bool { $success = false; $old_mofile = $this->mofile; diff --git a/www/lib/CoreLibs/Output/Form/Generate.inc b/www/lib/CoreLibs/Output/Form/Generate.inc index 676b597f..6cf0967e 100644 --- a/www/lib/CoreLibs/Output/Form/Generate.inc +++ b/www/lib/CoreLibs/Output/Form/Generate.inc @@ -235,9 +235,10 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO public $delete; public $really_delete; public $save; + public $remove_button; // security publics public $base_acl_level; - public $security_levels; + public $security_level; // layout publics public $table_width; @@ -248,8 +249,8 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO // PARAMS: $db_config -> connect to DB // $lang -> language code ('en', 'ja', etc) // $table_width -> width of table - // $db_debug -> turns db_io debug on/off (DB_DEBUG as global var does the same) - public function __construct($db_config, $lang, $table_width = 750, $debug = 0, $db_debug = 0, $echo = 1, $print = 0) + // $set_control_flag -> basic class set/get variable error flags + public function __construct(array $db_config, string $lang, int $table_width = 750, int $set_control_flag = 0) { $this->my_page_name = $this->getPageName(1); // init the language class @@ -278,7 +279,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO } // start the array_io class which will start db_io ... - parent::__construct($db_config, $config_array['table_array'], $config_array['table_name'], $debug, $db_debug, $echo, $print); + parent::__construct($db_config, $config_array['table_array'], $config_array['table_name'], $set_control_flag); // here should be a check if the config_array is correct ... if (isset($config_array['show_fields']) && is_array($config_array['show_fields'])) { $this->field_array = $config_array['show_fields']; diff --git a/www/lib/CoreLibs/Template/SmartyExtend.inc b/www/lib/CoreLibs/Template/SmartyExtend.inc index 9ad470ed..f89a7dbe 100644 --- a/www/lib/CoreLibs/Template/SmartyExtend.inc +++ b/www/lib/CoreLibs/Template/SmartyExtend.inc @@ -20,7 +20,7 @@ class SmartyExtend extends SmartyBC public $l10n; // constructor class, just sets the language stuff - public function __construct($lang) + public function __construct(string $lang) { SmartyBC::__construct(); $this->l10n = new \CoreLibs\Language\L10n($lang);