From ee2f76bc1629f9bf9c15a3da180024c98f6f2176 Mon Sep 17 00:00:00 2001 From: Yash Punwani Date: Wed, 25 Jun 2025 04:39:41 +0530 Subject: [PATCH 01/24] fix: fixed quoting of current timestamp function Signed-off-by: Yash Punwani --- libraries/classes/Table.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/classes/Table.php b/libraries/classes/Table.php index 426ae59629..494b13b41d 100644 --- a/libraries/classes/Table.php +++ b/libraries/classes/Table.php @@ -611,6 +611,11 @@ class Table implements Stringable } } elseif ($type === 'BINARY' || $type === 'VARBINARY') { $query .= ' DEFAULT 0x' . $defaultValue; + } elseif ( + str_contains($defaultValue, 'current_timestamp') + || str_contains($defaultValue, 'CURRENT_TIMESTAMP') + ) { + $query .= ' DEFAULT CURRENT_TIMESTAMP(' . $length . ')'; } else { $query .= ' DEFAULT \'' . $dbi->escapeString((string) $defaultValue) . '\''; From da90b543c31f7eccd3ef2446c091a5e1207cf241 Mon Sep 17 00:00:00 2001 From: William Desportes Date: Sun, 14 Sep 2025 20:54:33 +0200 Subject: [PATCH 02/24] Fix coding standard for new function use Ref: 47b233f5b71af0260c714bec3d078c5b2ceeb532 Signed-off-by: William Desportes --- libraries/classes/Utils/HttpRequest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/classes/Utils/HttpRequest.php b/libraries/classes/Utils/HttpRequest.php index 4e4f4857f5..f8143e2d2c 100644 --- a/libraries/classes/Utils/HttpRequest.php +++ b/libraries/classes/Utils/HttpRequest.php @@ -14,6 +14,7 @@ use function curl_setopt; use function file_get_contents; use function function_exists; use function getenv; +use function http_get_last_response_headers; use function ini_get; use function intval; use function is_array; From 889af69af89f78c02d4d9558524b62c0fd2191be Mon Sep 17 00:00:00 2001 From: efturtle Date: Fri, 7 Nov 2025 19:18:27 -0600 Subject: [PATCH 03/24] Preserve 2FA settings when saving partial user preferences Prevent two-factor authentication configuration from being lost when saving page-specific settings by merging existing 2FA data with new preferences instead of overwriting completely. Fixes #19900 Signed-off-by: efturtle --- libraries/classes/UserPreferences.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libraries/classes/UserPreferences.php b/libraries/classes/UserPreferences.php index 4237cfb377..68da9aee0e 100644 --- a/libraries/classes/UserPreferences.php +++ b/libraries/classes/UserPreferences.php @@ -155,6 +155,15 @@ class UserPreferences . $dbi->escapeString($relationParameters->user) . '\''; + // Smart merge: If this looks like a partial save (missing 2fa but we have it stored), + // automatically merge to prevent accidental overwrites + if (!isset($config_array['2fa'])) { + $existingPrefs = $this->load(); + if (isset($existingPrefs['config_data']['2fa'])) { + // This is likely a partial save from page settings - merge to preserve 2fa + $config_array = array_merge($existingPrefs['config_data'], $config_array); + } + } $has_config = $dbi->fetchValue($query, 0, DatabaseInterface::CONNECT_CONTROL); $config_data = json_encode($config_array); if ($has_config) { From 88608105b96dfd715a6470e3a4c782e02ac3d95a Mon Sep 17 00:00:00 2001 From: efturtle Date: Fri, 7 Nov 2025 19:30:44 -0600 Subject: [PATCH 04/24] Fix 2FA preservation for both session and database storage Extended the 2FA preservation logic to handle both storage paths: - Session storage (when pmadb is not configured) - Database storage (when pmadb is available) Previously only the database path was protected, causing 2FA settings to be lost when using session storage. Fixes #19900 Signed-off-by: efturtle --- libraries/classes/UserPreferences.php | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/libraries/classes/UserPreferences.php b/libraries/classes/UserPreferences.php index 68da9aee0e..01436c4e41 100644 --- a/libraries/classes/UserPreferences.php +++ b/libraries/classes/UserPreferences.php @@ -125,6 +125,16 @@ class UserPreferences */ public function save(array $config_array) { + // Smart merge: If this looks like a partial save (missing 2fa but we have it stored), + // automatically merge to prevent accidental overwrites + if (!isset($config_array['2fa'])) { + $existingPrefs = $this->load(); + if (isset($existingPrefs['config_data']['2fa'])) { + // This is likely a partial save from page settings - merge to preserve 2fa + $config_array = array_merge($existingPrefs['config_data'], $config_array); + } + } + global $dbi; $relationParameters = $this->relation->getRelationParameters(); @@ -155,15 +165,6 @@ class UserPreferences . $dbi->escapeString($relationParameters->user) . '\''; - // Smart merge: If this looks like a partial save (missing 2fa but we have it stored), - // automatically merge to prevent accidental overwrites - if (!isset($config_array['2fa'])) { - $existingPrefs = $this->load(); - if (isset($existingPrefs['config_data']['2fa'])) { - // This is likely a partial save from page settings - merge to preserve 2fa - $config_array = array_merge($existingPrefs['config_data'], $config_array); - } - } $has_config = $dbi->fetchValue($query, 0, DatabaseInterface::CONNECT_CONTROL); $config_data = json_encode($config_array); if ($has_config) { From f7497fd25811b6e6363552ec5ffb2c46425ca6ad Mon Sep 17 00:00:00 2001 From: Alberto Cuevas Date: Mon, 10 Nov 2025 18:44:46 -0600 Subject: [PATCH 05/24] Tests for 2fa preservation on partial User Preferences save() Signed-off-by: Alberto Cuevas --- test/classes/UserPreferencesTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/classes/UserPreferencesTest.php b/test/classes/UserPreferencesTest.php index 949faf4c36..05eed08a83 100644 --- a/test/classes/UserPreferencesTest.php +++ b/test/classes/UserPreferencesTest.php @@ -226,6 +226,23 @@ class UserPreferencesTest extends AbstractNetworkTestCase self::assertInstanceOf(Message::class, $result); self::assertSame('Could not save configuration

err1' . '

The phpMyAdmin configuration storage database could not be accessed.', $result->getMessage()); + + // Test 2fa preservation on partial save + $_SESSION['relation'] = []; + $_SESSION['relation'][$GLOBALS['server']] = RelationParameters::fromArray([])->toArray(); + + // Initial save with 2fa + $initialConfig = ['2fa' => ['backend' => 'application', 'settings' => ['secret' => 'thisisasecret']], 'theme' => 'dark']; + $this->userPreferences->save($initialConfig); + + // Partial save without 2fa + $partialConfig = ['Console/Mode' => 'collapse']; + $this->userPreferences->save($partialConfig); + + // Check that 2fa is still present + $resultConfig = $_SESSION['userconfig']['db']; + self::assertSame('thisisasecret', $resultConfig['2fa']['settings']['secret']); + self::assertSame('collapse', $resultConfig['Console/Mode']); } /** From 0cc6ef9ebfc6c6e4e0bbfbab9540daa41e56b241 Mon Sep 17 00:00:00 2001 From: Alberto Cuevas Date: Mon, 10 Nov 2025 21:03:05 -0600 Subject: [PATCH 06/24] fix: Re-apply JSON syntax highlighting after AJAX updates - Extract JSON highlighting logic into Functions.highlightJson() - Call highlightJson() after display options form submission - Ensures CodeMirror highlighting persists on dynamic content updates Signed-off-by: Alberto Cuevas --- js/src/functions.js | 22 ++++++++++++++++++++++ js/src/sql.js | 1 + js/src/transformations/json.js | 13 +------------ 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/js/src/functions.js b/js/src/functions.js index 449e1e8ba4..ce9532f20c 100644 --- a/js/src/functions.js +++ b/js/src/functions.js @@ -1730,6 +1730,28 @@ Functions.highlightSql = function ($base) { }); }; +/** + * Applies JSON syntax highlighting transformation using CodeMirror + * + * @param {JQuery} $base base element which contains the JSON code blocks + */ +Functions.highlightJson = function ($base) { + var $elm = $base.find('code.json'); + $elm.each(function () { + var $json = $(this); + var $pre = $json.find('pre'); + /* We only care about visible elements to avoid double processing */ + if ($pre.is(':visible')) { + var $highlight = $('
'); + $json.append($highlight); + if (typeof CodeMirror !== 'undefined' && typeof CodeMirror.runMode === 'function') { + CodeMirror.runMode($json.text(), 'application/json', $highlight[0]); + $pre.hide(); + } + } + }); +}; + /** * Updates an element containing code. * diff --git a/js/src/sql.js b/js/src/sql.js index 28e090c5c1..1180842d0f 100644 --- a/js/src/sql.js +++ b/js/src/sql.js @@ -675,6 +675,7 @@ AJAX.registerOnload('sql.js', function () { .html(data.message) .trigger('makeGrid'); Functions.highlightSql($sqlqueryresults); + Functions.highlightJson($sqlqueryresults); }); // end $.post() }); // end displayOptionsForm handler diff --git a/js/src/transformations/json.js b/js/src/transformations/json.js index 4326a2eda3..4e2383656e 100644 --- a/js/src/transformations/json.js +++ b/js/src/transformations/json.js @@ -2,16 +2,5 @@ * JSON syntax highlighting transformation plugin */ AJAX.registerOnload('transformations/json.js', function () { - var $elm = $('#page_content').find('code.json'); - $elm.each(function () { - var $json = $(this); - var $pre = $json.find('pre'); - /* We only care about visible elements to avoid double processing */ - if ($pre.is(':visible')) { - var $highlight = $('
'); - $json.append($highlight); - CodeMirror.runMode($json.text(), 'application/json', $highlight[0]); - $pre.hide(); - } - }); + Functions.highlightJson($('#page_content')); }); From 3b9932622f7a728409097d66985c0e5d0fc95e53 Mon Sep 17 00:00:00 2001 From: Liviu-Mihail Concioiu Date: Mon, 17 Nov 2025 16:31:39 +0100 Subject: [PATCH 07/24] Browse table from first row Signed-off-by: Liviu-Mihail Concioiu --- templates/menu/breadcrumbs.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/menu/breadcrumbs.twig b/templates/menu/breadcrumbs.twig index 6b3b726abe..dcb21b5e36 100644 --- a/templates/menu/breadcrumbs.twig +++ b/templates/menu/breadcrumbs.twig @@ -21,7 +21,7 @@ {% if table is not empty %}