diff --git a/.env.example b/.env.example index f47c87658..d9aa2df2a 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,5 @@ # Common params -APP_ENV=local +APP_ENV=production APP_CRON_ENABLED=true APP_DEMO_MODE=false diff --git a/CHANGELOG.md b/CHANGELOG.md index 148415a88..75ab68ff7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,10 @@ **Merged pull requests:** - Release 2.4.4 🦩 ([belomaxorka](https://github.com/belomaxorka)) +- Some security improvements 🔑 [\#1503](https://github.com/torrentpier/torrentpier/pull/1503) ([belomaxorka](https://github.com/belomaxorka)) - Some improvements for integrity checker [\#1501](https://github.com/torrentpier/torrentpier/pull/1501) ([belomaxorka](https://github.com/belomaxorka)) - Minor improvements [\#1502](https://github.com/torrentpier/torrentpier/pull/1502) ([belomaxorka](https://github.com/belomaxorka)) +- New Crowdin updates [\#1504](https://github.com/torrentpier/torrentpier/pull/1504) ([Exileum](https://github.com/Exileum)) ## [v2.4.3](https://github.com/torrentpier/torrentpier/tree/v2.4.3) (2024-06-09) [Full Changelog](https://github.com/torrentpier/torrentpier/compare/v2.4.2...v2.4.3) diff --git a/library/defines.php b/library/defines.php index ef012e654..f119eb034 100644 --- a/library/defines.php +++ b/library/defines.php @@ -65,7 +65,6 @@ define('XS_TAG_ENDIF', 8); define('XS_TAG_BEGINELSE', 11); // Debug -define('APP_DEBUG', true); // enable application debug define('SQL_DEBUG', true); // enable forum sql & cache debug define('SQL_LOG_ERRORS', true); // all SQL_xxx options enabled only if SQL_DEBUG == TRUE define('SQL_BB_LOG_NAME', 'sql_error_bb'); // mysql log filename (Board) diff --git a/library/includes/page_footer.php b/library/includes/page_footer.php index bdabc2539..d4a8cd0d4 100644 --- a/library/includes/page_footer.php +++ b/library/includes/page_footer.php @@ -11,7 +11,7 @@ if (!defined('BB_ROOT')) { die(basename(__FILE__)); } -global $bb_cfg, $userdata, $template, $DBS, $lang; +global $bb_cfg, $debug, $userdata, $template, $DBS, $lang; if (!empty($template)) { $template->assign_vars([ @@ -25,7 +25,7 @@ if (!empty($template)) { $template->pparse('page_footer'); } -$show_dbg_info = (APP_DEBUG && !(isset($_GET['pane']) && $_GET['pane'] == 'left')); +$show_dbg_info = (!$debug->isProduction && !(isset($_GET['pane']) && $_GET['pane'] == 'left')); if (!$bb_cfg['gzip_compress']) { flush(); diff --git a/library/includes/page_footer_dev.php b/library/includes/page_footer_dev.php index ae470b6c8..932a09bb6 100644 --- a/library/includes/page_footer_dev.php +++ b/library/includes/page_footer_dev.php @@ -71,7 +71,7 @@ if (!empty($_COOKIE['explain'])) { } } -$sql_log = !empty($_COOKIE['sql_log']) ? \TorrentPier\Dev::get_sql_log() : false; +$sql_log = !empty($_COOKIE['sql_log']) ? $debug->getSqlLog() : false; if ($sql_log) { echo '
' . $sql_log . '

'; diff --git a/src/Ajax.php b/src/Ajax.php index 77a904158..6b73aee1a 100644 --- a/src/Ajax.php +++ b/src/Ajax.php @@ -170,14 +170,16 @@ class Ajax /** * Send data * + * @return void * @throws Exception */ - public function send() + public function send(): void { + global $debug; $this->response['action'] = $this->action; - if (Dev::sql_dbg_enabled()) { - $this->response['sql_log'] = Dev::get_sql_log(); + if ($debug->sqlDebugAllowed()) { + $this->response['sql_log'] = $debug->getSqlLog(); } // sending output will be handled by $this->ob_handler() @@ -193,7 +195,9 @@ class Ajax */ public function ob_handler($contents): string { - if (APP_DEBUG) { + global $debug; + + if (!$debug->isProduction) { if ($contents) { $this->response['raw_output'] = $contents; } diff --git a/src/Dev.php b/src/Dev.php index 6452aa4c3..cf946c6cf 100644 --- a/src/Dev.php +++ b/src/Dev.php @@ -37,7 +37,14 @@ class Dev * * @var string */ - public string $envType = 'local'; + private string $envType; + + /** + * In production mode + * + * @var bool + */ + public bool $isProduction = false; /** * Whoops instance @@ -51,16 +58,20 @@ class Dev */ public function __construct() { - $this->envType = env('APP_ENV', 'local'); + $this->envType = env('APP_ENV', 'production'); $this->whoops = new Run; switch ($this->envType) { + case 'prod': case 'production': ini_set('display_errors', 0); ini_set('display_startup_errors', 0); $this->getWhoopsProduction(); + $this->isProduction = true; break; + case 'dev': case 'local': + case 'development': ini_set('display_errors', 1); ini_set('display_startup_errors', 1); $this->getWhoops(); @@ -128,10 +139,6 @@ class Dev */ private function getWhoops(): void { - if (!APP_DEBUG) { - return; - } - /** * Show errors on page */ @@ -170,28 +177,28 @@ class Dev * @return string * @throws Exception */ - public static function get_sql_log(): string + public function getSqlLog(): string { global $DBS, $CACHES, $datastore; $log = ''; foreach ($DBS->srv as $srv_name => $db_obj) { - $log .= !empty($db_obj->dbg) ? self::get_sql_log_html($db_obj, "database: $srv_name [{$db_obj->engine}]") : ''; + $log .= !empty($db_obj->dbg) ? $this->getSqlLogHtml($db_obj, "database: $srv_name [{$db_obj->engine}]") : ''; } foreach ($CACHES->obj as $cache_name => $cache_obj) { if (!empty($cache_obj->db->dbg)) { - $log .= self::get_sql_log_html($cache_obj->db, "cache: $cache_name [{$cache_obj->db->engine}]"); + $log .= $this->getSqlLogHtml($cache_obj->db, "cache: $cache_name [{$cache_obj->db->engine}]"); } elseif (!empty($cache_obj->dbg)) { - $log .= self::get_sql_log_html($cache_obj, "cache: $cache_name [{$cache_obj->engine}]"); + $log .= $this->getSqlLogHtml($cache_obj, "cache: $cache_name [{$cache_obj->engine}]"); } } if (!empty($datastore->db->dbg)) { - $log .= self::get_sql_log_html($datastore->db, "cache: datastore [{$datastore->db->engine}]"); + $log .= $this->getSqlLogHtml($datastore->db, "cache: datastore [{$datastore->db->engine}]"); } elseif (!empty($datastore->dbg)) { - $log .= self::get_sql_log_html($datastore, "cache: datastore [{$datastore->engine}]"); + $log .= $this->getSqlLogHtml($datastore, "cache: datastore [{$datastore->engine}]"); } return $log; @@ -202,9 +209,40 @@ class Dev * * @return bool */ - public static function sql_dbg_enabled(): bool + public function sqlDebugAllowed(): bool { - return (SQL_DEBUG && APP_DEBUG && !empty($_COOKIE['sql_log'])); + return (SQL_DEBUG && !$this->isProduction && !empty($_COOKIE['sql_log'])); + } + + /** + * Get SQL query html log + * + * @param object $db_obj + * @param string $log_name + * + * @return string + * @throws Exception + */ + private function getSqlLogHtml(object $db_obj, string $log_name): string + { + $log = ''; + + foreach ($db_obj->dbg as $i => $dbg) { + $id = "sql_{$i}_" . random_int(0, mt_getrandmax()); + $sql = $this->shortQuery($dbg['sql'], true); + $time = sprintf('%.4f', $dbg['time']); + $perc = '[' . round($dbg['time'] * 100 / $db_obj->sql_timetotal) . '%]'; + $info = !empty($dbg['info']) ? $dbg['info'] . ' [' . $dbg['src'] . ']' : $dbg['src']; + + $log .= '
' + . '' . $time . ' ' + . '' . $perc . ' ' + . '' . $sql . '' + . ' # ' . $info . ' ' + . '
'; + } + + return '
' . $log_name . '
' . $log; } /** @@ -214,7 +252,7 @@ class Dev * @param bool $esc_html * @return string */ - public static function short_query(string $sql, bool $esc_html = false): string + public function shortQuery(string $sql, bool $esc_html = false): string { $max_len = 100; $sql = str_compact($sql); @@ -227,40 +265,4 @@ class Dev return $esc_html ? htmlCHR($sql, true) : $sql; } - - /** - * Get SQL query html log - * - * @param object $db_obj - * @param string $log_name - * - * @return string - * @throws Exception - */ - private static function get_sql_log_html(object $db_obj, string $log_name): string - { - $log = ''; - - foreach ($db_obj->dbg as $i => $dbg) { - $id = "sql_{$i}_" . random_int(0, mt_getrandmax()); - $sql = self::short_query($dbg['sql'], true); - $time = sprintf('%.4f', $dbg['time']); - $perc = '[' . round($dbg['time'] * 100 / $db_obj->sql_timetotal) . '%]'; - $info = !empty($dbg['info']) ? $dbg['info'] . ' [' . $dbg['src'] . ']' : $dbg['src']; - - $log .= '' - . '
' - . '' . $time . ' ' - . '' . $perc . '' - . ' ' - . '' . $sql . '' - . ' # ' . $info . ' ' - . '
' - . "\n"; - } - return ' -
' . $log_name . '
- ' . $log . ' - '; - } } diff --git a/src/Legacy/Cache/APCu.php b/src/Legacy/Cache/APCu.php index a7a242fd1..7678629ab 100644 --- a/src/Legacy/Cache/APCu.php +++ b/src/Legacy/Cache/APCu.php @@ -23,12 +23,14 @@ class APCu extends Common public function __construct($prefix = null) { + global $debug; + if (!$this->is_installed()) { die("Error: $this->engine extension not installed"); } $this->prefix = $prefix; - $this->dbg_enabled = Dev::sql_dbg_enabled(); + $this->dbg_enabled = $debug->sqlDebugAllowed(); } public function get($name, $get_miss_key_callback = '', $ttl = 0) diff --git a/src/Legacy/Cache/Common.php b/src/Legacy/Cache/Common.php index 53bbf54ba..a9b473542 100644 --- a/src/Legacy/Cache/Common.php +++ b/src/Legacy/Cache/Common.php @@ -59,6 +59,8 @@ class Common public function debug($mode, $cur_query = null) { + global $debug; + if (!$this->dbg_enabled) { return; } @@ -69,7 +71,7 @@ class Common switch ($mode) { case 'start': $this->sql_starttime = utime(); - $dbg['sql'] = Dev::short_query($cur_query ?? $this->cur_query); + $dbg['sql'] = $debug->shortQuery($cur_query ?? $this->cur_query); $dbg['src'] = $this->debug_find_source(); $dbg['file'] = $this->debug_find_source('file'); $dbg['line'] = $this->debug_find_source('line'); diff --git a/src/Legacy/Cache/File.php b/src/Legacy/Cache/File.php index 20cff706f..81ed8cde0 100644 --- a/src/Legacy/Cache/File.php +++ b/src/Legacy/Cache/File.php @@ -24,9 +24,11 @@ class File extends Common public function __construct($dir, $prefix = null) { + global $debug; + $this->dir = $dir; $this->prefix = $prefix; - $this->dbg_enabled = Dev::sql_dbg_enabled(); + $this->dbg_enabled = $debug->sqlDebugAllowed(); } public function get($name, $get_miss_key_callback = '', $ttl = 0) diff --git a/src/Legacy/Cache/Memcache.php b/src/Legacy/Cache/Memcache.php index 8f37670d6..816c683dd 100644 --- a/src/Legacy/Cache/Memcache.php +++ b/src/Legacy/Cache/Memcache.php @@ -26,6 +26,8 @@ class Memcache extends Common public function __construct($cfg, $prefix = null) { + global $debug; + if (!$this->is_installed()) { die("Error: $this->engine extension not installed"); } @@ -33,7 +35,7 @@ class Memcache extends Common $this->cfg = $cfg; $this->prefix = $prefix; $this->memcache = new \Memcache(); - $this->dbg_enabled = Dev::sql_dbg_enabled(); + $this->dbg_enabled = $debug->sqlDebugAllowed(); } public function connect() diff --git a/src/Legacy/Cache/Redis.php b/src/Legacy/Cache/Redis.php index 969581517..e93eb7cfe 100644 --- a/src/Legacy/Cache/Redis.php +++ b/src/Legacy/Cache/Redis.php @@ -26,6 +26,8 @@ class Redis extends Common public function __construct($cfg, $prefix = null) { + global $debug; + if (!$this->is_installed()) { die("Error: $this->engine extension not installed"); } @@ -33,7 +35,7 @@ class Redis extends Common $this->cfg = $cfg; $this->prefix = $prefix; $this->redis = new \Redis(); - $this->dbg_enabled = Dev::sql_dbg_enabled(); + $this->dbg_enabled = $debug->sqlDebugAllowed(); } public function connect() diff --git a/src/Legacy/Cache/SqliteCommon.php b/src/Legacy/Cache/SqliteCommon.php index 7e99dcce9..a7e3cb37d 100644 --- a/src/Legacy/Cache/SqliteCommon.php +++ b/src/Legacy/Cache/SqliteCommon.php @@ -37,8 +37,10 @@ class SqliteCommon extends Common public function __construct($cfg) { + global $debug; + $this->cfg = array_merge($this->cfg, $cfg); - $this->dbg_enabled = Dev::sql_dbg_enabled(); + $this->dbg_enabled = $debug->sqlDebugAllowed(); } public function connect() diff --git a/src/Legacy/Datastore/APCu.php b/src/Legacy/Datastore/APCu.php index 06056e13e..61f1ca279 100644 --- a/src/Legacy/Datastore/APCu.php +++ b/src/Legacy/Datastore/APCu.php @@ -17,17 +17,19 @@ use TorrentPier\Dev; */ class APCu extends Common { - public $prefix; - public $engine = 'APCu'; + public string $prefix; + public string $engine = 'APCu'; public function __construct($prefix = null) { + global $debug; + if (!$this->is_installed()) { die("Error: $this->engine extension not installed"); } - $this->dbg_enabled = Dev::sql_dbg_enabled(); $this->prefix = $prefix; + $this->dbg_enabled = $debug->sqlDebugAllowed(); } public function store($title, $var) diff --git a/src/Legacy/Datastore/Common.php b/src/Legacy/Datastore/Common.php index f81467661..7774f27d0 100644 --- a/src/Legacy/Datastore/Common.php +++ b/src/Legacy/Datastore/Common.php @@ -139,6 +139,8 @@ class Common public function debug($mode, $cur_query = null) { + global $debug; + if (!$this->dbg_enabled) { return; } @@ -149,7 +151,7 @@ class Common switch ($mode) { case 'start': $this->sql_starttime = utime(); - $dbg['sql'] = Dev::short_query($cur_query ?? $this->cur_query); + $dbg['sql'] = $debug->shortQuery($cur_query ?? $this->cur_query); $dbg['src'] = $this->debug_find_source(); $dbg['file'] = $this->debug_find_source('file'); $dbg['line'] = $this->debug_find_source('line'); diff --git a/src/Legacy/Datastore/File.php b/src/Legacy/Datastore/File.php index 241892dcd..d27667c6b 100644 --- a/src/Legacy/Datastore/File.php +++ b/src/Legacy/Datastore/File.php @@ -23,9 +23,11 @@ class File extends Common public function __construct($dir, $prefix = null) { + global $debug; + $this->prefix = $prefix; $this->dir = $dir; - $this->dbg_enabled = Dev::sql_dbg_enabled(); + $this->dbg_enabled = $debug->sqlDebugAllowed(); } public function store($title, $var) diff --git a/src/Legacy/Datastore/Memcache.php b/src/Legacy/Datastore/Memcache.php index 37051b5fc..2203a8f69 100644 --- a/src/Legacy/Datastore/Memcache.php +++ b/src/Legacy/Datastore/Memcache.php @@ -25,6 +25,8 @@ class Memcache extends Common public function __construct($cfg, $prefix = null) { + global $debug; + if (!$this->is_installed()) { die("Error: $this->engine extension not installed"); } @@ -32,7 +34,7 @@ class Memcache extends Common $this->cfg = $cfg; $this->prefix = $prefix; $this->memcache = new \Memcache(); - $this->dbg_enabled = Dev::sql_dbg_enabled(); + $this->dbg_enabled = $debug->sqlDebugAllowed(); } public function connect() diff --git a/src/Legacy/Datastore/Redis.php b/src/Legacy/Datastore/Redis.php index 7a7e34465..8a7175bd9 100644 --- a/src/Legacy/Datastore/Redis.php +++ b/src/Legacy/Datastore/Redis.php @@ -25,13 +25,15 @@ class Redis extends Common public function __construct($cfg, $prefix = null) { + global $debug; + if (!$this->is_installed()) { die("Error: $this->engine extension not installed"); } $this->cfg = $cfg; $this->redis = new \Redis(); - $this->dbg_enabled = Dev::sql_dbg_enabled(); + $this->dbg_enabled = $debug->sqlDebugAllowed(); $this->prefix = $prefix; } diff --git a/src/Legacy/Datastore/SqliteCommon.php b/src/Legacy/Datastore/SqliteCommon.php index 69f2a7d32..2acbfe399 100644 --- a/src/Legacy/Datastore/SqliteCommon.php +++ b/src/Legacy/Datastore/SqliteCommon.php @@ -37,8 +37,10 @@ class SqliteCommon extends Common public function __construct($cfg) { + global $debug; + $this->cfg = array_merge($this->cfg, $cfg); - $this->dbg_enabled = Dev::sql_dbg_enabled(); + $this->dbg_enabled = $debug->sqlDebugAllowed(); } public function connect() diff --git a/src/Legacy/SqlDb.php b/src/Legacy/SqlDb.php index 8c1835438..93a69c60f 100644 --- a/src/Legacy/SqlDb.php +++ b/src/Legacy/SqlDb.php @@ -57,10 +57,10 @@ class SqlDb */ public function __construct($cfg_values) { - global $DBS; + global $DBS, $debug; $this->cfg = array_combine($this->cfg_keys, $cfg_values); - $this->dbg_enabled = (Dev::sql_dbg_enabled() || !empty($_COOKIE['explain'])); + $this->dbg_enabled = ($debug->sqlDebugAllowed() || !empty($_COOKIE['explain'])); $this->do_explain = ($this->dbg_enabled && !empty($_COOKIE['explain'])); $this->slow_time = SQL_SLOW_QUERY_TIME; @@ -886,6 +886,8 @@ class SqlDb */ public function log_query($log_file = 'sql_queries') { + global $debug; + $q_time = ($this->cur_query_time >= 10) ? round($this->cur_query_time, 0) : sprintf('%.4f', $this->cur_query_time); $msg = []; $msg[] = round($this->sql_starttime); @@ -893,7 +895,7 @@ class SqlDb $msg[] = sprintf('%-6s', $q_time); $msg[] = sprintf('%05d', getmypid()); $msg[] = $this->db_server; - $msg[] = Dev::short_query($this->cur_query); + $msg[] = $debug->shortQuery($this->cur_query); $msg = implode(LOG_SEPR, $msg); $msg .= ($info = $this->query_info()) ? ' # ' . $info : ''; $msg .= ' # ' . $this->debug_find_source() . ' '; @@ -951,12 +953,14 @@ class SqlDb * * @param $mode * @param string $html_table - * @param string $row + * @param array $row * * @return bool|string */ - public function explain($mode, $html_table = '', $row = '') + public function explain($mode, $html_table = '', array $row = []) { + global $debug; + $query = str_compact($this->cur_query); // remove comments $query = preg_replace('#(\s*)(/\*)(.*)(\*/)(\s*)#', '', $query); @@ -975,7 +979,7 @@ class SqlDb $html_table = false; if ($result = mysqli_query($this->link, "EXPLAIN $query")) { - while ($row = mysqli_fetch_assoc($result)) { + while ($row = $this->sql_fetchrow($result)) { $html_table = $this->explain('add_explain_row', $html_table, $row); } } @@ -1002,7 +1006,7 @@ class SqlDb ' . $this->explain_hold . ' -
' . Dev::short_query($dbg['sql'], true) . '  
+
' . $debug->shortQuery($dbg['sql'], true) . '  

'; break; @@ -1024,8 +1028,6 @@ class SqlDb return $html_table; - break; - case 'display': echo '
' . $this->explain_out . '
'; break; diff --git a/styles/templates/default/page_header.tpl b/styles/templates/default/page_header.tpl index 1837be317..9a7febee5 100644 --- a/styles/templates/default/page_header.tpl +++ b/styles/templates/default/page_header.tpl @@ -3,6 +3,7 @@ + <!-- IF HAVE_NEW_PM -->({HAVE_NEW_PM}) <!-- ENDIF --><!-- IF PAGE_TITLE -->{PAGE_TITLE} :: {SITENAME}<!-- ELSE -->{SITENAME}<!-- ENDIF -->