Merge branch 'QA_5_2'

Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
This commit is contained in:
Maurício Meneghini Fauth 2023-02-08 14:09:59 -03:00
commit 0819043d0e
No known key found for this signature in database
GPG Key ID: 6A16FD38AFC89CC8
14 changed files with 148 additions and 47 deletions

View File

@ -5,6 +5,11 @@ phpMyAdmin - ChangeLog
- issue #17842 Change js.cookie.js to js.cookie.min.js
- issue #17632 Improve tab keypress to text fields on the login form
5.2.2 (not yet released)
- issue #17028 Fix total count of rows in not accurate
- issue #17683 Fix total count of rows in not accurate
- issue #17766 Allow to open in a new tab copy and edit row actions
5.2.1 (2023-02-07)
- issue #17522 Fix case where the routes cache file is invalid
- issue #17506 Fix error when configuring 2FA without XMLWriter or Imagick

View File

@ -134,7 +134,7 @@ var DragDropImport = {
var filename = $this.parent('span').attr('data-filename');
$('body').append('<div class="pma_drop_result"><h2>' +
window.Messages.dropImportImportResultHeader + ' - ' +
Functions.escapeHtml(filename) + '<span class="close">x</span></h2>' + value.message + '</div>');
escapeHtml(filename) + '<span class="close">x</span></h2>' + value.message + '</div>');
$('.pma_drop_result').draggable(); // to make this dialog draggable
}
});

View File

@ -7,6 +7,7 @@ namespace PhpMyAdmin\Controllers\Table;
use PhpMyAdmin\Config\PageSettings;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\Core;
use PhpMyAdmin\DbTableExists;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Http\ServerRequest;
@ -82,6 +83,12 @@ class ChangeController extends AbstractController
DbTableExists::check($GLOBALS['db'], $GLOBALS['table']);
if (isset($_GET['where_clause'], $_GET['where_clause_signature'])) {
if (Core::checkSqlQuerySignature($_GET['where_clause'], $_GET['where_clause_signature'])) {
$where_clause = $_GET['where_clause'];
}
}
/**
* Determine whether Insert or Edit and set global variables
*/

View File

@ -290,7 +290,7 @@ final class ReplaceController extends AbstractController
$valueSets[] = implode(', ', $queryValues);
} else {
// build update query
$clauseIsUnique = $_POST['clause_is_unique'] ?? '';// Should contain 0 or 1
$clauseIsUnique = $_POST['clause_is_unique'] ?? $_GET['clause_is_unique'] ?? '';// Should contain 0 or 1
$GLOBALS['query'][] = 'UPDATE ' . Util::backquote($GLOBALS['table'])
. ' SET ' . implode(', ', $queryValues)
. ' WHERE ' . $where_clause

View File

@ -2735,8 +2735,10 @@ class Results
'db' => $this->properties['db'],
'table' => $this->properties['table'],
'where_clause' => $whereClause,
'where_clause_signature' => Core::signSqlQuery($whereClause),
'clause_is_unique' => $clauseIsUnique,
'sql_query' => $urlSqlQuery,
'sql_signature' => Core::signSqlQuery($urlSqlQuery),
'goto' => Url::getFromRoute('/sql'),
];

View File

@ -135,6 +135,13 @@ class InsertEdit
'err_url' => $errorUrl,
'sql_query' => $_POST['sql_query'] ?? '',
];
if ($formParams['sql_query'] === '' && isset($_GET['sql_query'], $_GET['sql_signature'])) {
if (Core::checkSqlQuerySignature($_GET['sql_query'], $_GET['sql_signature'])) {
$formParams['sql_query'] = $_GET['sql_query'];
}
}
if (isset($whereClauses)) {
foreach ($whereClauseArray as $keyId => $whereClause) {
$formParams['where_clause[' . $keyId . ']'] = trim($whereClause);
@ -143,6 +150,8 @@ class InsertEdit
if (isset($_POST['clause_is_unique'])) {
$formParams['clause_is_unique'] = $_POST['clause_is_unique'];
} elseif (isset($_GET['clause_is_unique'])) {
$formParams['clause_is_unique'] = $_GET['clause_is_unique'];
}
return $formParams;

View File

@ -15,6 +15,7 @@ use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Html\MySQLDocumentation;
use PhpMyAdmin\Query\Generator as QueryGenerator;
use PhpMyAdmin\Query\Utilities;
use PhpMyAdmin\SqlParser\Components\Expression;
use PhpMyAdmin\SqlParser\Statements\AlterStatement;
use PhpMyAdmin\SqlParser\Statements\DropStatement;
use PhpMyAdmin\SqlParser\Statements\SelectStatement;
@ -707,24 +708,24 @@ class Sql
}
} else {
$statement = $statementInfo->statement;
$tokenList = $statementInfo->parser->list;
$replaces = [
// Remove ORDER BY to decrease unnecessary sorting time
[
'ORDER BY',
'',
],
// Removes LIMIT clause that might have been added
[
'LIMIT',
'',
],
];
$countQuery = 'SELECT COUNT(*) FROM (' . Query::replaceClauses(
$statement,
$tokenList,
$replaces
) . ') as cnt';
// Remove ORDER BY to decrease unnecessary sorting time
if ($statementInfo->order !== false) {
$statement->order = null;
}
// Removes LIMIT clause that might have been added
if ($statementInfo->limit !== null) {
$statement->limit = null;
}
if ($statementInfo->isGroup === false && count($statement->expr) === 1) {
$statement->expr[0] = new Expression();
$statement->expr[0]->expr = '1';
}
$countQuery = 'SELECT COUNT(*) FROM (' . $statement->build() . ' ) as cnt';
$unlimNumRows = $this->dbi->fetchValue($countQuery);
if ($unlimNumRows === false) {
$unlimNumRows = 0;

View File

@ -7960,6 +7960,21 @@ parameters:
count: 1
path: libraries/classes/Setup/Index.php
-
message: "#^Access to an undefined property PhpMyAdmin\\\\SqlParser\\\\Statement\\:\\:\\$expr\\.$#"
count: 2
path: libraries/classes/Sql.php
-
message: "#^Access to an undefined property PhpMyAdmin\\\\SqlParser\\\\Statement\\:\\:\\$limit\\.$#"
count: 1
path: libraries/classes/Sql.php
-
message: "#^Access to an undefined property PhpMyAdmin\\\\SqlParser\\\\Statement\\:\\:\\$order\\.$#"
count: 1
path: libraries/classes/Sql.php
-
message: "#^Method PhpMyAdmin\\\\Sql\\:\\:countQueryResults\\(\\) should return int\\|numeric\\-string but returns mixed\\.$#"
count: 1
@ -8100,11 +8115,6 @@ parameters:
count: 2
path: libraries/classes/Sql.php
-
message: "#^Parameter \\#2 \\$list of static method PhpMyAdmin\\\\SqlParser\\\\Utils\\\\Query\\:\\:replaceClauses\\(\\) expects PhpMyAdmin\\\\SqlParser\\\\TokensList, PhpMyAdmin\\\\SqlParser\\\\TokensList\\|null given\\.$#"
count: 1
path: libraries/classes/Sql.php
-
message: "#^Parameter \\#2 \\$table of method PhpMyAdmin\\\\Sql\\:\\:handleSortOrder\\(\\) expects string, string\\|null given\\.$#"
count: 1

View File

@ -2874,9 +2874,15 @@
<MixedOperand occurrences="1">
<code>$GLOBALS['biggest_max_file_size']</code>
</MixedOperand>
<PossiblyInvalidArgument occurrences="1">
<PossiblyInvalidArgument occurrences="3">
<code>$GLOBALS['current_result']</code>
<code>$_GET['where_clause']</code>
<code>$_GET['where_clause_signature']</code>
</PossiblyInvalidArgument>
<PossiblyInvalidCast occurrences="2">
<code>$_GET['where_clause']</code>
<code>$_GET['where_clause_signature']</code>
</PossiblyInvalidCast>
<PossiblyNullArgument occurrences="2">
<code>$GLOBALS['text_dir']</code>
<code>$isUpload</code>
@ -2884,6 +2890,9 @@
<TypeDoesNotContainType occurrences="1">
<code>$GLOBALS['biggest_max_file_size'] &gt; 0</code>
</TypeDoesNotContainType>
<UnusedVariable occurrences="1">
<code>$where_clause</code>
</UnusedVariable>
</file>
<file src="libraries/classes/Controllers/Table/ChangeRowsController.php">
<MixedAssignment occurrences="2">
@ -7594,14 +7603,18 @@
</MixedOperand>
<MixedReturnStatement occurrences="1"/>
<MoreSpecificReturnType occurrences="1"/>
<PossiblyInvalidArgument occurrences="2">
<PossiblyInvalidArgument occurrences="4">
<code>$_GET['sql_query']</code>
<code>$_GET['sql_signature']</code>
<code>$whereClause</code>
<code>$whereClause</code>
</PossiblyInvalidArgument>
<PossiblyInvalidArrayOffset occurrences="1">
<code>$_POST['fields']['multi_edit']</code>
</PossiblyInvalidArrayOffset>
<PossiblyInvalidCast occurrences="1">
<PossiblyInvalidCast occurrences="3">
<code>$_GET['sql_query']</code>
<code>$_GET['sql_signature']</code>
<code>$whereClause</code>
</PossiblyInvalidCast>
<PossiblyInvalidOperand occurrences="1">
@ -12175,6 +12188,11 @@
<code>$row['#']</code>
</PossiblyNullOperand>
</file>
<file src="libraries/classes/Server/Status/Processes.php">
<RedundantCondition occurrences="1">
<code>0 !== --$sortableColCount</code>
</RedundantCondition>
</file>
<file src="libraries/classes/Session.php">
<MixedArgument occurrences="3">
<code>$config-&gt;getCookie('phpMyAdmin')</code>
@ -12276,7 +12294,7 @@
<LessSpecificReturnStatement occurrences="1">
<code>$unlimNumRows</code>
</LessSpecificReturnStatement>
<MixedArgument occurrences="11">
<MixedArgument occurrences="12">
<code>$columns[$indexColumnName]['Extra']</code>
<code>$extraData['error']</code>
<code>$fieldInfoResult[0]['Type']</code>
@ -12285,6 +12303,7 @@
<code>$oneResult['Duration']</code>
<code>$oneResult['Status']</code>
<code>$sortCol</code>
<code>$statement-&gt;expr</code>
<code>$unlimNumRows</code>
<code>$unlimNumRows</code>
<code>Message::sanitize($warning)</code>
@ -12311,9 +12330,10 @@
<code>$oneResult['Status']</code>
<code>$statementInfo-&gt;statement-&gt;where[0]</code>
</MixedArrayAccess>
<MixedArrayAssignment occurrences="2">
<MixedArrayAssignment occurrences="3">
<code>$_SESSION['tmpval']['pos']</code>
<code>$_SESSION['tmpval']['possible_as_geometry']</code>
<code>$statement-&gt;expr[0]</code>
</MixedArrayAssignment>
<MixedAssignment occurrences="16">
<code>$maxRows</code>
@ -12384,18 +12404,28 @@
<PossiblyInvalidPropertyFetch occurrences="1">
<code>$statement-&gt;altered[0]-&gt;field-&gt;column</code>
</PossiblyInvalidPropertyFetch>
<PossiblyNullArgument occurrences="7">
<PossiblyNullArgument occurrences="6">
<code>$result</code>
<code>$row[0]</code>
<code>$statementInfo-&gt;parser-&gt;list</code>
<code>$statementInfo-&gt;parser-&gt;list</code>
<code>$statementInfo-&gt;parser-&gt;list</code>
<code>$table</code>
<code>$tokenList</code>
</PossiblyNullArgument>
<RedundantCast occurrences="1">
<code>(bool) $GLOBALS['cfg']['ShowSQL']</code>
</RedundantCast>
<RedundantConditionGivenDocblockType occurrences="1">
<code>$statementInfo-&gt;limit !== null</code>
</RedundantConditionGivenDocblockType>
<UndefinedPropertyAssignment occurrences="3">
<code>$statement-&gt;expr</code>
<code>$statement-&gt;limit</code>
<code>$statement-&gt;order</code>
</UndefinedPropertyAssignment>
<UndefinedPropertyFetch occurrences="1">
<code>$statement-&gt;expr</code>
</UndefinedPropertyFetch>
</file>
<file src="libraries/classes/SqlQueryForm.php">
<MixedArgument occurrences="1"/>

View File

@ -14,9 +14,9 @@ use function class_exists;
use function sort;
use const DIRECTORY_SEPARATOR;
use const ROOT_PATH;
use const SORT_NATURAL;
use const SORT_REGULAR;
use const TEST_PATH;
/**
* @covers \PhpMyAdmin\Command\TwigLintCommand
@ -42,7 +42,7 @@ class TwigLintCommandTest extends AbstractTestCase
public function testGetTemplateContents(): void
{
$contents = $this->callFunction($this->command, TwigLintCommand::class, 'getTemplateContents', [
ROOT_PATH . 'test/classes/_data/file_listing/subfolder/one.ini',
TEST_PATH . 'test/classes/_data/file_listing/subfolder/one.ini',
]);
$this->assertSame('key=value' . "\n", $contents);
@ -50,7 +50,7 @@ class TwigLintCommandTest extends AbstractTestCase
public function testFindFiles(): void
{
$path = ROOT_PATH . 'test/classes/_data/file_listing';
$path = TEST_PATH . 'test/classes/_data/file_listing';
$filesFound = $this->callFunction($this->command, TwigLintCommand::class, 'findFiles', [$path]);
// Sort results to avoid file system test specific failures
@ -66,7 +66,7 @@ class TwigLintCommandTest extends AbstractTestCase
public function testGetFilesInfo(): void
{
$path = ROOT_PATH . 'test/classes/_data/file_listing';
$path = TEST_PATH . 'test/classes/_data/file_listing';
$filesInfos = $this->callFunction($this->command, TwigLintCommand::class, 'getFilesInfo', [$path]);
// Sort results to avoid file system test specific failures
@ -120,7 +120,7 @@ class TwigLintCommandTest extends AbstractTestCase
->willReturnOnConsecutiveCalls('{{ file }}', '{{ file }');
$filesFound = $this->callFunction($command, TwigLintCommand::class, 'getFilesInfo', [
ROOT_PATH . 'test/classes/_data/file_listing',
TEST_PATH . 'test/classes/_data/file_listing',
]);
$this->assertEquals([

View File

@ -153,6 +153,43 @@ class InsertEditTest extends AbstractTestCase
);
}
/**
* Test for getFormParametersForInsertForm
*/
public function testGetFormParametersForInsertFormGet(): void
{
$where_clause = [
'foo' => 'bar ',
'1' => ' test',
];
$_GET['clause_is_unique'] = false;
$_GET['sql_query'] = 'SELECT a';
$_GET['sql_signature'] = Core::signSqlQuery($_GET['sql_query']);
$GLOBALS['goto'] = 'index.php';
$result = $this->insertEdit->getFormParametersForInsertForm(
'dbname',
'tablename',
[],
$where_clause,
'localhost'
);
$this->assertEquals(
[
'db' => 'dbname',
'table' => 'tablename',
'goto' => 'index.php',
'err_url' => 'localhost',
'sql_query' => 'SELECT a',
'where_clause[foo]' => 'bar',
'where_clause[1]' => 'test',
'clause_is_unique' => false,
],
$result
);
}
/**
* Test for getWhereClauseArray
*/

View File

@ -371,9 +371,9 @@ class SqlTest extends AbstractTestCase
164056,
50,
false,
'SELECT COUNT(*) FROM (select * from game_auth_logs l join ('
'SELECT COUNT(*) FROM (SELECT 1 FROM game_auth_logs AS `l` JOIN ('
. ' select al.user_id, max(al.id) as id from game_auth_logs al '
. 'where al.successfull = 1 group by al.user_id ) last_log on last_log.id = l.id'
. 'where al.successfull = 1 group by al.user_id ) AS `last_log` ON last_log.id = l.id'
. ' ) as cnt',
],
'join on SELECT results with alias.*' => [
@ -385,9 +385,9 @@ class SqlTest extends AbstractTestCase
267,
50,
false,
'SELECT COUNT(*) FROM (select l.* from game_auth_logs l join ('
'SELECT COUNT(*) FROM (SELECT 1 FROM game_auth_logs AS `l` JOIN ('
. ' select al.user_id, max(al.id) as id from game_auth_logs al '
. 'where al.successfull = 1 group by al.user_id ) last_log on last_log.id = l.id'
. 'where al.successfull = 1 group by al.user_id ) AS `last_log` ON last_log.id = l.id'
. ' ) as cnt',
],
[

View File

@ -2742,17 +2742,17 @@ class DbiDummy implements DbiExtension
'result' => [['hostname', 'username', 'password']],
],
[
'query' => 'SELECT COUNT(*) FROM (SELECT * FROM company_users WHERE not_working_count != 0 ) as cnt',
'query' => 'SELECT COUNT(*) FROM (SELECT 1 FROM company_users WHERE not_working_count != 0 ) as cnt',
'result' => false,
],
[
'query' => 'SELECT COUNT(*) FROM (SELECT * FROM company_users ) as cnt',
'query' => 'SELECT COUNT(*) FROM (SELECT 1 FROM company_users ) as cnt',
'result' => [
[4],
],
],
[
'query' => 'SELECT COUNT(*) FROM (SELECT * FROM company_users WHERE working_count = 0 ) as cnt',
'query' => 'SELECT COUNT(*) FROM (SELECT 1 FROM company_users WHERE working_count = 0 ) as cnt',
'result' => [
[15],
],
@ -2765,8 +2765,8 @@ class DbiDummy implements DbiExtension
],
[
'query' => 'SELECT COUNT(*) FROM ('
. 'SELECT *, 1, (SELECT COUNT(*) FROM tbl1) as c1, '
. '(SELECT 1 FROM tbl2) as c2 FROM company_users WHERE subquery_case = 0 ) as cnt',
. 'SELECT *, 1, (SELECT COUNT(*) FROM tbl1) AS `c1`, '
. '(SELECT 1 FROM tbl2) AS `c2` FROM company_users WHERE subquery_case = 0 ) as cnt',
'result' => [
[42],
],

View File

@ -65,7 +65,7 @@ class ThemeTest extends AbstractTestCase
*/
public function testCheckImgPathIncorrect(): void
{
$this->object->setPath(ROOT_PATH . 'test/classes/_data/incorrect_theme');
$this->object->setPath(TEST_PATH . 'test/classes/_data/incorrect_theme');
$this->assertFalse(
$this->object->loadInfo(),
'Theme name is not properly set'