Merge branch 'QA_5_1' into QA_5_2
Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
This commit is contained in:
commit
2653b2942b
2
.gitignore
vendored
2
.gitignore
vendored
@ -62,3 +62,5 @@ phpstan.neon
|
||||
# Infection
|
||||
infection.json
|
||||
infection.log
|
||||
/js/vendor/openlayers/OpenLayers.js.LICENSE.txt
|
||||
/setup/styles.rtl.css
|
||||
|
||||
@ -36,6 +36,9 @@ phpMyAdmin - ChangeLog
|
||||
- issue #16769 Fix create index form accepting too many columns
|
||||
- issue #16816 Disable editing to system schemas
|
||||
- issue #16853 Add better error handling when IndexedDB is not working
|
||||
- issue Fixed incorrect escaping of special MySQL characters on some pages
|
||||
- issue #17188 Fix GIS visualization with an edited query
|
||||
- issue #17418 Remove the use of the deprecated `strftime` function in OpenDocument exports
|
||||
|
||||
5.1.3 (2022-02-10)
|
||||
- issue #17308 Fix broken pagination links in the navigation sidebar
|
||||
|
||||
@ -93,7 +93,7 @@
|
||||
"php-webdriver/webdriver": "^1.11",
|
||||
"phpmyadmin/coding-standard": "^3.0.0",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan": "^1.4.5",
|
||||
"phpstan/phpstan": "^1.4.8",
|
||||
"phpstan/phpstan-phpunit": "^1.0",
|
||||
"phpstan/phpstan-webmozart-assert": "^1.0",
|
||||
"phpunit/phpunit": "^8.5 || ^9.5",
|
||||
@ -102,7 +102,7 @@
|
||||
"roave/security-advisories": "dev-latest",
|
||||
"symfony/console": "^5.2.3",
|
||||
"tecnickcom/tcpdf": "^6.4.4",
|
||||
"vimeo/psalm": "^4.19"
|
||||
"vimeo/psalm": "^4.22"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
@ -110,19 +110,22 @@
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"phpcbf": "phpcbf",
|
||||
"phpcs": "phpcs",
|
||||
"phpstan": "phpstan analyse",
|
||||
"psalm": "psalm --no-diff",
|
||||
"phpunit": "phpunit --color=always",
|
||||
"phpcbf": "@php phpcbf",
|
||||
"phpcs": "@php phpcs",
|
||||
"phpstan": "@php phpstan analyse",
|
||||
"psalm": "@php psalm --no-diff",
|
||||
"phpunit": "@php phpunit --color=always",
|
||||
"test": [
|
||||
"@phpcs",
|
||||
"@phpstan",
|
||||
"@psalm",
|
||||
"@phpunit"
|
||||
],
|
||||
"update:baselines": "phpstan analyse --generate-baseline && psalm --set-baseline=psalm-baseline.xml",
|
||||
"twig-lint": "php scripts/console lint:twig --ansi --show-deprecations"
|
||||
"update:baselines": [
|
||||
"@php phpstan analyse --generate-baseline",
|
||||
"@php psalm --set-baseline=psalm-baseline.xml"
|
||||
],
|
||||
"twig-lint": "@php scripts/console lint:twig --ansi --show-deprecations"
|
||||
},
|
||||
"config":{
|
||||
"sort-packages": true,
|
||||
|
||||
2
js/vendor/openlayers/OpenLayers.js
vendored
2
js/vendor/openlayers/OpenLayers.js
vendored
@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* OpenLayers v6.9.0 (https://openlayers.org/)
|
||||
* OpenLayers v6.13.0 (https://openlayers.org/)
|
||||
* Copyright 2005-present, OpenLayers Contributors All rights reserved.
|
||||
* Licensed under BSD 2-Clause License (https://github.com/openlayers/openlayers/blob/main/LICENSE.md)
|
||||
*
|
||||
|
||||
170
js/vendor/zxcvbn-ts.js
vendored
170
js/vendor/zxcvbn-ts.js
vendored
@ -424,7 +424,7 @@ this.zxcvbnts.core = (function (exports) {
|
||||
this.matchers = {};
|
||||
this.l33tTable = l33tTable;
|
||||
this.dictionary = {
|
||||
userInput: []
|
||||
userInputs: []
|
||||
};
|
||||
this.rankedDictionaries = {};
|
||||
this.translations = translationKeys;
|
||||
@ -480,31 +480,45 @@ this.zxcvbnts.core = (function (exports) {
|
||||
setRankedDictionaries() {
|
||||
const rankedDictionaries = {};
|
||||
Object.keys(this.dictionary).forEach(name => {
|
||||
const list = this.dictionary[name];
|
||||
|
||||
if (name === 'userInputs') {
|
||||
const sanitizedInputs = [];
|
||||
list.forEach(input => {
|
||||
const inputType = typeof input;
|
||||
|
||||
if (inputType === 'string' || inputType === 'number' || inputType === 'boolean') {
|
||||
sanitizedInputs.push(input.toString().toLowerCase());
|
||||
}
|
||||
});
|
||||
rankedDictionaries[name] = buildRankedDictionary(sanitizedInputs);
|
||||
} else {
|
||||
rankedDictionaries[name] = buildRankedDictionary(list);
|
||||
}
|
||||
rankedDictionaries[name] = this.getRankedDictionary(name);
|
||||
});
|
||||
this.rankedDictionaries = rankedDictionaries;
|
||||
}
|
||||
|
||||
addMatcher(name, matcher) {
|
||||
if (this.matchers[name]) {
|
||||
throw new Error('Matcher already exists');
|
||||
getRankedDictionary(name) {
|
||||
const list = this.dictionary[name];
|
||||
|
||||
if (name === 'userInputs') {
|
||||
const sanitizedInputs = [];
|
||||
list.forEach(input => {
|
||||
const inputType = typeof input;
|
||||
|
||||
if (inputType === 'string' || inputType === 'number' || inputType === 'boolean') {
|
||||
sanitizedInputs.push(input.toString().toLowerCase());
|
||||
}
|
||||
});
|
||||
return buildRankedDictionary(sanitizedInputs);
|
||||
}
|
||||
|
||||
this.matchers[name] = matcher;
|
||||
return buildRankedDictionary(list);
|
||||
}
|
||||
|
||||
extendUserInputsDictionary(dictionary) {
|
||||
if (this.dictionary.userInputs) {
|
||||
this.dictionary.userInputs = [...this.dictionary.userInputs, ...dictionary];
|
||||
} else {
|
||||
this.dictionary.userInputs = dictionary;
|
||||
}
|
||||
|
||||
this.rankedDictionaries.userInputs = this.getRankedDictionary('userInputs');
|
||||
}
|
||||
|
||||
addMatcher(name, matcher) {
|
||||
if (this.matchers[name]) {
|
||||
console.info('Matcher already exists');
|
||||
} else {
|
||||
this.matchers[name] = matcher;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1283,7 +1297,8 @@ this.zxcvbnts.core = (function (exports) {
|
||||
const optimalMatchSequence = [];
|
||||
let k = passwordLength - 1; // find the final best sequence length and score
|
||||
|
||||
let sequenceLength = 0;
|
||||
let sequenceLength = 0; // eslint-disable-next-line no-loss-of-precision
|
||||
|
||||
let g = 2e308;
|
||||
const temp = this.optimal.g[k]; // safety check for empty passwords
|
||||
|
||||
@ -1414,6 +1429,7 @@ this.zxcvbnts.core = (function (exports) {
|
||||
*/
|
||||
|
||||
class MatchRepeat {
|
||||
// eslint-disable-next-line max-statements
|
||||
match({
|
||||
password,
|
||||
omniMatch
|
||||
@ -1437,20 +1453,45 @@ this.zxcvbnts.core = (function (exports) {
|
||||
if (match) {
|
||||
const j = match.index + match[0].length - 1;
|
||||
const baseGuesses = this.getBaseGuesses(baseToken, omniMatch);
|
||||
matches.push({
|
||||
pattern: 'repeat',
|
||||
i: match.index,
|
||||
j,
|
||||
token: match[0],
|
||||
baseToken,
|
||||
baseGuesses,
|
||||
repeatCount: match[0].length / baseToken.length
|
||||
});
|
||||
matches.push(this.normalizeMatch(baseToken, j, match, baseGuesses));
|
||||
lastIndex = j + 1;
|
||||
}
|
||||
}
|
||||
|
||||
const hasPromises = matches.some(match => {
|
||||
return match instanceof Promise;
|
||||
});
|
||||
|
||||
if (hasPromises) {
|
||||
return Promise.all(matches);
|
||||
}
|
||||
|
||||
return matches;
|
||||
} // eslint-disable-next-line max-params
|
||||
|
||||
|
||||
normalizeMatch(baseToken, j, match, baseGuesses) {
|
||||
const baseMatch = {
|
||||
pattern: 'repeat',
|
||||
i: match.index,
|
||||
j,
|
||||
token: match[0],
|
||||
baseToken,
|
||||
baseGuesses: 0,
|
||||
repeatCount: match[0].length / baseToken.length
|
||||
};
|
||||
|
||||
if (baseGuesses instanceof Promise) {
|
||||
return baseGuesses.then(resolvedBaseGuesses => {
|
||||
return { ...baseMatch,
|
||||
baseGuesses: resolvedBaseGuesses
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return { ...baseMatch,
|
||||
baseGuesses
|
||||
};
|
||||
}
|
||||
|
||||
getGreedyMatch(password, lastIndex) {
|
||||
@ -1502,7 +1543,16 @@ this.zxcvbnts.core = (function (exports) {
|
||||
}
|
||||
|
||||
getBaseGuesses(baseToken, omniMatch) {
|
||||
const baseAnalysis = scoring.mostGuessableMatchSequence(baseToken, omniMatch.match(baseToken));
|
||||
const matches = omniMatch.match(baseToken);
|
||||
|
||||
if (matches instanceof Promise) {
|
||||
return matches.then(resolvedMatches => {
|
||||
const baseAnalysis = scoring.mostGuessableMatchSequence(baseToken, resolvedMatches);
|
||||
return baseAnalysis.guesses;
|
||||
});
|
||||
}
|
||||
|
||||
const baseAnalysis = scoring.mostGuessableMatchSequence(baseToken, matches);
|
||||
return baseAnalysis.guesses;
|
||||
}
|
||||
|
||||
@ -1758,6 +1808,7 @@ this.zxcvbnts.core = (function (exports) {
|
||||
date: MatchDate,
|
||||
dictionary: MatchDictionary,
|
||||
regex: MatchRegex,
|
||||
// @ts-ignore => TODO resolve this type issue. This is because it is possible to be async
|
||||
repeat: MatchRepeat,
|
||||
sequence: MatchSequence,
|
||||
spatial: MatchSpatial
|
||||
@ -1766,6 +1817,7 @@ this.zxcvbnts.core = (function (exports) {
|
||||
|
||||
match(password) {
|
||||
const matches = [];
|
||||
const promises = [];
|
||||
const matchers = [...Object.keys(this.matchers), ...Object.keys(Options$1.matchers)];
|
||||
matchers.forEach(key => {
|
||||
if (!this.matchers[key] && !Options$1.matchers[key]) {
|
||||
@ -1774,11 +1826,29 @@ this.zxcvbnts.core = (function (exports) {
|
||||
|
||||
const Matcher = this.matchers[key] ? this.matchers[key] : Options$1.matchers[key].Matching;
|
||||
const usedMatcher = new Matcher();
|
||||
extend(matches, usedMatcher.match({
|
||||
const result = usedMatcher.match({
|
||||
password,
|
||||
omniMatch: this
|
||||
}));
|
||||
});
|
||||
|
||||
if (result instanceof Promise) {
|
||||
result.then(response => {
|
||||
extend(matches, response);
|
||||
});
|
||||
promises.push(result);
|
||||
} else {
|
||||
extend(matches, result);
|
||||
}
|
||||
});
|
||||
|
||||
if (promises.length > 0) {
|
||||
return new Promise(resolve => {
|
||||
Promise.all(promises).then(() => {
|
||||
resolve(sorted(matches));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return sorted(matches);
|
||||
}
|
||||
|
||||
@ -1827,7 +1897,12 @@ this.zxcvbnts.core = (function (exports) {
|
||||
offlineSlowHashing1e4PerSecond: guesses / 1e4,
|
||||
offlineFastHashing1e10PerSecond: guesses / 1e10
|
||||
};
|
||||
const crackTimesDisplay = {};
|
||||
const crackTimesDisplay = {
|
||||
onlineThrottling100PerHour: '',
|
||||
onlineNoThrottling10PerSecond: '',
|
||||
offlineSlowHashing1e4PerSecond: '',
|
||||
offlineFastHashing1e10PerSecond: ''
|
||||
};
|
||||
Object.keys(crackTimesSeconds).forEach(scenario => {
|
||||
const seconds = crackTimesSeconds[scenario];
|
||||
crackTimesDisplay[scenario] = this.displayTime(seconds);
|
||||
@ -2113,13 +2188,10 @@ this.zxcvbnts.core = (function (exports) {
|
||||
|
||||
const time = () => new Date().getTime();
|
||||
|
||||
const zxcvbn = password => {
|
||||
const createReturnValue = (resolvedMatches, password, start) => {
|
||||
const feedback = new Feedback();
|
||||
const matching = new Matching();
|
||||
const timeEstimates = new TimeEstimates();
|
||||
const start = time();
|
||||
const matches = matching.match(password);
|
||||
const matchSequence = scoring.mostGuessableMatchSequence(password, matches);
|
||||
const matchSequence = scoring.mostGuessableMatchSequence(password, resolvedMatches);
|
||||
const calcTime = time() - start;
|
||||
const attackTimes = timeEstimates.estimateAttackTimes(matchSequence.guesses);
|
||||
return {
|
||||
@ -2130,6 +2202,24 @@ this.zxcvbnts.core = (function (exports) {
|
||||
};
|
||||
};
|
||||
|
||||
const zxcvbn = (password, userInputs) => {
|
||||
if (userInputs) {
|
||||
Options$1.extendUserInputsDictionary(userInputs);
|
||||
}
|
||||
|
||||
const matching = new Matching();
|
||||
const start = time();
|
||||
const matches = matching.match(password);
|
||||
|
||||
if (matches instanceof Promise) {
|
||||
return matches.then(resolvedMatches => {
|
||||
return createReturnValue(resolvedMatches, password, start);
|
||||
});
|
||||
}
|
||||
|
||||
return createReturnValue(matches, password, start);
|
||||
};
|
||||
|
||||
exports.ZxcvbnOptions = Options$1;
|
||||
exports.zxcvbn = zxcvbn;
|
||||
|
||||
@ -2137,5 +2227,5 @@ this.zxcvbnts.core = (function (exports) {
|
||||
|
||||
return exports;
|
||||
|
||||
}({}));
|
||||
})({});
|
||||
//# sourceMappingURL=zxcvbn-ts.js.map
|
||||
|
||||
2
js/vendor/zxcvbn-ts.js.map
vendored
2
js/vendor/zxcvbn-ts.js.map
vendored
File diff suppressed because one or more lines are too long
@ -54,6 +54,7 @@ use function stripos;
|
||||
use function strlen;
|
||||
use function strtolower;
|
||||
use function strtoupper;
|
||||
use function strtr;
|
||||
use function substr;
|
||||
use function syslog;
|
||||
use function trigger_error;
|
||||
@ -505,9 +506,7 @@ class DatabaseInterface implements DbalInterface
|
||||
) . '\')';
|
||||
} else {
|
||||
$sql .= " `Name` LIKE '"
|
||||
. Util::escapeMysqlWildcards(
|
||||
$this->escapeString($table, $link)
|
||||
)
|
||||
. $this->escapeMysqlLikeString($table, $link)
|
||||
. "%'";
|
||||
}
|
||||
|
||||
@ -905,7 +904,7 @@ class DatabaseInterface implements DbalInterface
|
||||
$sql = QueryGenerator::getColumnsSql(
|
||||
$database,
|
||||
$table,
|
||||
Util::escapeMysqlWildcards($this->escapeString($column)),
|
||||
$this->escapeMysqlLikeString($column),
|
||||
$full
|
||||
);
|
||||
/** @var array<string, array> $fields */
|
||||
@ -2137,6 +2136,19 @@ class DatabaseInterface implements DbalInterface
|
||||
return $this->extension->escapeString($this->links[$link], $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns properly escaped string for use in MySQL LIKE clauses
|
||||
*
|
||||
* @param string $str string to be escaped
|
||||
* @param int $link optional database link to use
|
||||
*
|
||||
* @return string a MySQL escaped LIKE string
|
||||
*/
|
||||
public function escapeMysqlLikeString(string $str, int $link = self::CONNECT_USER)
|
||||
{
|
||||
return $this->escapeString(strtr($str, ['\\' => '\\\\', '_' => '\\_', '%' => '\\%']), $link);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this database server is running on Amazon RDS.
|
||||
*/
|
||||
|
||||
@ -635,6 +635,16 @@ interface DbalInterface
|
||||
*/
|
||||
public function escapeString(string $str, $link = DatabaseInterface::CONNECT_USER);
|
||||
|
||||
/**
|
||||
* returns properly escaped string for use in MySQL LIKE clauses
|
||||
*
|
||||
* @param string $str string to be escaped
|
||||
* @param int $link optional database link to use
|
||||
*
|
||||
* @return string a MySQL escaped LIKE string
|
||||
*/
|
||||
public function escapeMysqlLikeString(string $str, int $link = DatabaseInterface::CONNECT_USER);
|
||||
|
||||
/**
|
||||
* Checks if this database server is running on Amazon RDS.
|
||||
*/
|
||||
|
||||
@ -25,6 +25,7 @@ use function mb_strtolower;
|
||||
use function mb_substr;
|
||||
use function ob_get_clean;
|
||||
use function ob_start;
|
||||
use function rtrim;
|
||||
|
||||
use const PNG_ALL_FILTERS;
|
||||
|
||||
@ -220,7 +221,7 @@ class GisVisualization
|
||||
. ') AS ' . Util::backquote('srid') . ' ';
|
||||
|
||||
// Append the original query as the inner query
|
||||
$modified_query .= 'FROM (' . $sql_query . ') AS '
|
||||
$modified_query .= 'FROM (' . rtrim($sql_query, ';') . ') AS '
|
||||
. Util::backquote('temp_gis');
|
||||
|
||||
// LIMIT clause
|
||||
|
||||
@ -7,10 +7,12 @@ declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin;
|
||||
|
||||
use function date;
|
||||
use DateTime;
|
||||
|
||||
use const DATE_W3C;
|
||||
|
||||
/**
|
||||
* Simplfied OpenDocument creator class
|
||||
* Simplified OpenDocument creator class
|
||||
*/
|
||||
class OpenDocument
|
||||
{
|
||||
@ -33,6 +35,9 @@ EOT;
|
||||
*/
|
||||
public static function create($mime, $data)
|
||||
{
|
||||
// Use the same date method as other PHP libs
|
||||
// https://github.com/PHPOffice/PhpSpreadsheet/blob/1.22.0/src/PhpSpreadsheet/Writer/Ods/Meta.php#L49
|
||||
$dateTimeCreation = (new DateTime())->format(DATE_W3C);
|
||||
$data = [
|
||||
$mime,
|
||||
$data,
|
||||
@ -45,7 +50,7 @@ EOT;
|
||||
. '<meta:generator>phpMyAdmin ' . Version::VERSION . '</meta:generator>'
|
||||
. '<meta:initial-creator>phpMyAdmin ' . Version::VERSION
|
||||
. '</meta:initial-creator>'
|
||||
. '<meta:creation-date>' . date('Y-m-d\TH:i:s')
|
||||
. '<meta:creation-date>' . $dateTimeCreation
|
||||
. '</meta:creation-date>'
|
||||
. '</office:meta>'
|
||||
. '</office:document-meta>',
|
||||
|
||||
@ -3349,9 +3349,7 @@ class Privileges
|
||||
if ($createDb1) {
|
||||
// Create database with same name and grant all privileges
|
||||
$query = 'CREATE DATABASE IF NOT EXISTS '
|
||||
. Util::backquote(
|
||||
$this->dbi->escapeString($username)
|
||||
) . ';';
|
||||
. Util::backquote($username) . ';';
|
||||
$sqlQuery .= $query;
|
||||
if (! $this->dbi->tryQuery($query)) {
|
||||
$message = Message::rawError($this->dbi->getError());
|
||||
@ -3365,9 +3363,7 @@ class Privileges
|
||||
|
||||
$query = 'GRANT ALL PRIVILEGES ON '
|
||||
. Util::backquote(
|
||||
Util::escapeMysqlWildcards(
|
||||
$this->dbi->escapeString($username)
|
||||
)
|
||||
Util::escapeMysqlWildcards($username)
|
||||
) . '.* TO \''
|
||||
. $this->dbi->escapeString($username)
|
||||
. '\'@\'' . $this->dbi->escapeString($hostname) . '\';';
|
||||
@ -3381,9 +3377,7 @@ class Privileges
|
||||
// Grant all privileges on wildcard name (username\_%)
|
||||
$query = 'GRANT ALL PRIVILEGES ON '
|
||||
. Util::backquote(
|
||||
Util::escapeMysqlWildcards(
|
||||
$this->dbi->escapeString($username)
|
||||
) . '\_%'
|
||||
Util::escapeMysqlWildcards($username) . '\_%'
|
||||
) . '.* TO \''
|
||||
. $this->dbi->escapeString($username)
|
||||
. '\'@\'' . $this->dbi->escapeString($hostname) . '\';';
|
||||
|
||||
@ -2342,8 +2342,8 @@ class Util
|
||||
&& is_scalar($_REQUEST['tbl_group'])
|
||||
&& strlen((string) $_REQUEST['tbl_group']) > 0
|
||||
) {
|
||||
$group = self::escapeMysqlWildcards((string) $_REQUEST['tbl_group']);
|
||||
$groupWithSeparator = self::escapeMysqlWildcards(
|
||||
$group = $dbi->escapeMysqlLikeString((string) $_REQUEST['tbl_group']);
|
||||
$groupWithSeparator = $dbi->escapeMysqlLikeString(
|
||||
$_REQUEST['tbl_group']
|
||||
. $GLOBALS['cfg']['NavigationTreeTableSeparator']
|
||||
);
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
<exclude-pattern>*/tmp/*</exclude-pattern>
|
||||
<exclude-pattern>*/twig-templates/*</exclude-pattern>
|
||||
<exclude-pattern>*/vendor/*</exclude-pattern>
|
||||
<exclude-pattern>*/.git/*</exclude-pattern>
|
||||
|
||||
<rule ref="PhpMyAdmin"/>
|
||||
|
||||
|
||||
@ -120,6 +120,21 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/CheckUserPrivileges.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getExtension\\(\\) on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Command/CacheWarmupCommand.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getPathname\\(\\) on mixed\\.$#"
|
||||
count: 2
|
||||
path: libraries/classes/Command/CacheWarmupCommand.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method isFile\\(\\) on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Command/CacheWarmupCommand.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpMyAdmin\\\\Command\\\\TwigLintCommand\\:\\:display\\(\\) has parameter \\$filesInfo with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
@ -151,7 +166,7 @@ parameters:
|
||||
path: libraries/classes/Common.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$value of method Symfony\\\\Component\\\\DependencyInjection\\\\Container\\:\\:setParameter\\(\\) expects array\\|bool\\|float\\|int\\|string\\|null, mixed given\\.$#"
|
||||
message: "#^Parameter \\#2 \\$value of method Symfony\\\\Component\\\\DependencyInjection\\\\Container\\:\\:setParameter\\(\\) expects array\\|bool\\|float\\|int\\|string\\|UnitEnum\\|null, mixed given\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Common.php
|
||||
|
||||
@ -1285,6 +1300,11 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Controllers/Import/ImportController.php
|
||||
|
||||
-
|
||||
message: "#^Left side of \\|\\| is always true\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Controllers/Import/ImportController.php
|
||||
|
||||
-
|
||||
message: "#^Negated boolean expression is always true\\.$#"
|
||||
count: 1
|
||||
@ -1770,6 +1790,11 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Controllers/Transformation/WrapperController.php
|
||||
|
||||
-
|
||||
message: "#^Variable \\$mime_type on left side of \\?\\? always exists and is not nullable\\.$#"
|
||||
count: 2
|
||||
path: libraries/classes/Controllers/Transformation/WrapperController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$string of function substr expects string, mixed given\\.$#"
|
||||
count: 1
|
||||
@ -1915,6 +1940,11 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Database/CentralColumns.php
|
||||
|
||||
-
|
||||
message: "#^Right side of \\|\\| is always false\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/CentralColumns.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpMyAdmin\\\\Database\\\\Designer\\:\\:getDatabaseTables\\(\\) has parameter \\$tab_column with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
@ -2700,6 +2730,11 @@ parameters:
|
||||
count: 2
|
||||
path: libraries/classes/DatabaseInterface.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$link of method PhpMyAdmin\\\\DatabaseInterface\\:\\:escapeMysqlLikeString\\(\\) expects int, mixed given\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/DatabaseInterface.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$table of method PhpMyAdmin\\\\Query\\\\Cache\\:\\:cacheTableData\\(\\) expects bool\\|string, array\\|string given\\.$#"
|
||||
count: 1
|
||||
@ -2845,19 +2880,9 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Dbal/DbiMysqli.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpMyAdmin\\\\Dbal\\\\MysqliResult\\:\\:__construct\\(\\) has parameter \\$result with no value type specified in iterable type mysqli_result\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Dbal/MysqliResult.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpMyAdmin\\\\Dbal\\\\MysqliResult\\:\\:fetchAllKeyPair\\(\\) should return array\\<string, string\\|null\\> but returns array\\<int\\|string, mixed\\>\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Dbal/MysqliResult.php
|
||||
|
||||
-
|
||||
message: "#^Property PhpMyAdmin\\\\Dbal\\\\MysqliResult\\:\\:\\$result type has no value type specified in iterable type mysqli_result\\.$#"
|
||||
count: 1
|
||||
count: 2
|
||||
path: libraries/classes/Dbal/MysqliResult.php
|
||||
|
||||
-
|
||||
@ -3215,11 +3240,6 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Display/Results.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:setParamForLinkForeignKeyRelatedTables\\(\\) should return array\\<string, array\\<string\\>\\> but returns array\\<int\\|string, array\\>\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Display/Results.php
|
||||
|
||||
-
|
||||
message: "#^Offset 3 does not exist on array\\{string\\|null, string\\|null, string\\|null\\}\\.$#"
|
||||
count: 1
|
||||
@ -5325,6 +5345,11 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Navigation/NavigationTree.php
|
||||
|
||||
-
|
||||
message: "#^Right side of \\|\\| is always false\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Navigation/NavigationTree.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpMyAdmin\\\\Navigation\\\\NodeFactory\\:\\:getInstance\\(\\) has parameter \\$name with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
@ -5685,6 +5710,11 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Pdf.php
|
||||
|
||||
-
|
||||
message: "#^Left side of \\|\\| is always false\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Plugins.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpMyAdmin\\\\Plugins\\:\\:getPlugins\\(\\) return type has no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
@ -5695,6 +5725,11 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Plugins.php
|
||||
|
||||
-
|
||||
message: "#^Right side of \\|\\| is always false\\.$#"
|
||||
count: 3
|
||||
path: libraries/classes/Plugins.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$remoteIp of method ReCaptcha\\\\ReCaptcha\\:\\:verify\\(\\) expects string\\|null, bool\\|string given\\.$#"
|
||||
count: 1
|
||||
@ -6390,11 +6425,6 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Plugins/Schema/Dia/Dia.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$masterField of method PhpMyAdmin\\\\Plugins\\\\Schema\\\\Dia\\\\DiaRelationSchema\\:\\:addRelation\\(\\) expects string, int\\|string given\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Plugins/Schema/Dia/DiaRelationSchema.php
|
||||
|
||||
-
|
||||
message: "#^Binary operation \"\\+\" between int\\|string\\|false and 12 results in an error\\.$#"
|
||||
count: 4
|
||||
@ -6415,11 +6445,6 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Plugins/Schema/Eps/EpsRelationSchema.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#4 \\$masterField of method PhpMyAdmin\\\\Plugins\\\\Schema\\\\Eps\\\\EpsRelationSchema\\:\\:addRelation\\(\\) expects string, int\\|string given\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Plugins/Schema/Eps/EpsRelationSchema.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method object\\:\\:line\\(\\)\\.$#"
|
||||
count: 7
|
||||
@ -6475,11 +6500,6 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Plugins/Schema/Pdf/PdfRelationSchema.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$masterField of method PhpMyAdmin\\\\Plugins\\\\Schema\\\\Pdf\\\\PdfRelationSchema\\:\\:addRelation\\(\\) expects string, int\\|string given\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Plugins/Schema/Pdf/PdfRelationSchema.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$master_table of class PhpMyAdmin\\\\Plugins\\\\Schema\\\\Pdf\\\\RelationStatsPdf constructor expects string, PhpMyAdmin\\\\Plugins\\\\Schema\\\\Pdf\\\\TableStatsPdf given\\.$#"
|
||||
count: 1
|
||||
@ -6530,6 +6550,11 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Plugins/Schema/Pdf/TableStatsPdf.php
|
||||
|
||||
-
|
||||
message: "#^Binary operation \"\\+\" between int\\|string\\|false and 1\\.5 results in an error\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Plugins/Schema/RelationStats.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpMyAdmin\\\\Plugins\\\\Schema\\\\RelationStats\\:\\:getXy\\(\\) return type has no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
@ -6585,11 +6610,6 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Plugins/Schema/Svg/SvgRelationSchema.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#4 \\$masterField of method PhpMyAdmin\\\\Plugins\\\\Schema\\\\Svg\\\\SvgRelationSchema\\:\\:addRelation\\(\\) expects string, int\\|string given\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Plugins/Schema/Svg/SvgRelationSchema.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#4 \\$y of method PhpMyAdmin\\\\Plugins\\\\Schema\\\\Svg\\\\Svg\\:\\:startSvgDoc\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
@ -8305,6 +8325,11 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Table.php
|
||||
|
||||
-
|
||||
message: "#^Right side of \\|\\| is always false\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Table.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpMyAdmin\\\\Table\\\\ColumnsDefinition\\:\\:displayForm\\(\\) has parameter \\$fields_meta with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<files psalm-version="4.21.0@d8bec4c7aaee111a532daec32fb09de5687053d1">
|
||||
<files psalm-version="4.22.0@fc2c6ab4d5fa5d644d8617089f012f3bb84b8703">
|
||||
<file src="index.php">
|
||||
<InvalidGlobal occurrences="1">
|
||||
<code>global $route, $containerBuilder, $request;</code>
|
||||
@ -5396,7 +5396,7 @@
|
||||
<InvalidReturnType occurrences="1">
|
||||
<code>int|bool</code>
|
||||
</InvalidReturnType>
|
||||
<MixedArgument occurrences="50">
|
||||
<MixedArgument occurrences="51">
|
||||
<code>$_SERVER['SCRIPT_NAME']</code>
|
||||
<code>$a</code>
|
||||
<code>$arrayKeys</code>
|
||||
@ -5419,6 +5419,7 @@
|
||||
<code>$link</code>
|
||||
<code>$link</code>
|
||||
<code>$link</code>
|
||||
<code>$link</code>
|
||||
<code>$one_database_tables</code>
|
||||
<code>$one_database_tables</code>
|
||||
<code>$one_table_name</code>
|
||||
@ -15016,12 +15017,16 @@
|
||||
</NonInvariantDocblockPropertyType>
|
||||
</file>
|
||||
<file src="test/classes/Gis/GisVisualizationTest.php">
|
||||
<MixedAssignment occurrences="5">
|
||||
<MixedAssignment occurrences="9">
|
||||
<code>$dataSet</code>
|
||||
<code>$queryString</code>
|
||||
<code>$queryString</code>
|
||||
<code>$queryString</code>
|
||||
<code>$queryString</code>
|
||||
<code>$queryString</code>
|
||||
<code>$queryString</code>
|
||||
<code>$queryString</code>
|
||||
<code>$queryString</code>
|
||||
</MixedAssignment>
|
||||
</file>
|
||||
<file src="test/classes/GitTest.php">
|
||||
@ -15330,6 +15335,14 @@
|
||||
<code>assertIsArray</code>
|
||||
</RedundantConditionGivenDocblockType>
|
||||
</file>
|
||||
<file src="test/classes/OpenDocumentTest.php">
|
||||
<MixedArgument occurrences="1">
|
||||
<code>$zipExtension->getContents($tmpFile, '/meta\.xml/')['data']</code>
|
||||
</MixedArgument>
|
||||
<RedundantConditionGivenDocblockType occurrences="1">
|
||||
<code>assertNotFalse</code>
|
||||
</RedundantConditionGivenDocblockType>
|
||||
</file>
|
||||
<file src="test/classes/PdfTest.php">
|
||||
<MixedArgument occurrences="3">
|
||||
<code>$arr->getPDFData()</code>
|
||||
|
||||
@ -188,6 +188,7 @@ cleanup_composer_vendors() {
|
||||
vendor/twig/twig/.editorconfig \
|
||||
vendor/twig/twig/.php_cs.dist \
|
||||
vendor/twig/twig/drupal_test.sh \
|
||||
vendor/twig/twig/.php-cs-fixer.dist.php \
|
||||
vendor/webmozart/assert/.editorconfig \
|
||||
vendor/webmozart/assert/.github/ \
|
||||
vendor/webmozart/assert/.php_cs \
|
||||
|
||||
@ -71,11 +71,11 @@ echo 'Updating OpenLayers'
|
||||
cp ./node_modules/ol/ol.css ./js/vendor/openlayers/theme/ol.css
|
||||
npx webpack-cli --config ./js/config/ol/webpack.config.js
|
||||
echo "/*!
|
||||
* OpenLayers v$(yarn -s info ol version) (https://openlayers.org/)
|
||||
* OpenLayers v$(yarn info -s ol version) (https://openlayers.org/)
|
||||
* Copyright 2005-present, OpenLayers Contributors All rights reserved.
|
||||
* Licensed under BSD 2-Clause License (https://github.com/openlayers/openlayers/blob/main/LICENSE.md)
|
||||
*
|
||||
* @license $(yarn -s info ol license)
|
||||
* @license $(yarn info -s ol license)
|
||||
*/
|
||||
$(cat ./js/vendor/openlayers/OpenLayers.js)" > ./js/vendor/openlayers/OpenLayers.js
|
||||
echo 'Updating sprintf'
|
||||
|
||||
@ -131,6 +131,106 @@ class GisVisualizationTest extends AbstractTestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the query for an MySQL 8.0 version and trim the SQL end character
|
||||
*/
|
||||
public function testModifyQueryTrimSqlEnd(): void
|
||||
{
|
||||
$queryString = $this->callFunction(
|
||||
GisVisualization::getByData([], [
|
||||
'mysqlVersion' => 80000,
|
||||
'spatialColumn' => 'abc',
|
||||
'isMariaDB' => false,
|
||||
]),
|
||||
GisVisualization::class,
|
||||
'modifySqlQuery',
|
||||
[
|
||||
'SELECT 1 FROM foo;',
|
||||
0,
|
||||
0,
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'SELECT ST_ASTEXT(`abc`) AS `abc`, ST_SRID(`abc`) AS `srid` FROM (SELECT 1 FROM foo) AS `temp_gis`',
|
||||
$queryString
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the query for an MySQL 8.0 version using a label column
|
||||
*/
|
||||
public function testModifyQueryLabelColumn(): void
|
||||
{
|
||||
$queryString = $this->callFunction(
|
||||
GisVisualization::getByData([], [
|
||||
'mysqlVersion' => 80000,
|
||||
'spatialColumn' => 'country_geom',
|
||||
'labelColumn' => 'country name',
|
||||
'isMariaDB' => false,
|
||||
]),
|
||||
GisVisualization::class,
|
||||
'modifySqlQuery',
|
||||
[
|
||||
'',
|
||||
0,
|
||||
0,
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'SELECT `country name`, ST_ASTEXT(`country_geom`) AS `country_geom`,'
|
||||
. ' ST_SRID(`country_geom`) AS `srid` FROM () AS `temp_gis`',
|
||||
$queryString
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the query for an MySQL 8.0 version adding a LIMIT statement
|
||||
*/
|
||||
public function testModifyQueryWithLimit(): void
|
||||
{
|
||||
$queryString = $this->callFunction(
|
||||
GisVisualization::getByData([], [
|
||||
'mysqlVersion' => 80000,
|
||||
'spatialColumn' => 'abc',
|
||||
'isMariaDB' => false,
|
||||
]),
|
||||
GisVisualization::class,
|
||||
'modifySqlQuery',
|
||||
[
|
||||
'',
|
||||
10,// 10 rows
|
||||
0,
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'SELECT ST_ASTEXT(`abc`) AS `abc`, ST_SRID(`abc`) AS `srid` FROM () AS `temp_gis` LIMIT 0, 10',
|
||||
$queryString
|
||||
);
|
||||
|
||||
$queryString = $this->callFunction(
|
||||
GisVisualization::getByData([], [
|
||||
'mysqlVersion' => 80000,
|
||||
'spatialColumn' => 'abc',
|
||||
'isMariaDB' => false,
|
||||
]),
|
||||
GisVisualization::class,
|
||||
'modifySqlQuery',
|
||||
[
|
||||
'',
|
||||
15,// 15 rows
|
||||
10,// position 10
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'SELECT ST_ASTEXT(`abc`) AS `abc`, ST_SRID(`abc`) AS `srid` FROM () AS `temp_gis` LIMIT 10, 15',
|
||||
$queryString
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the query for an MySQL 8.0.1 version
|
||||
*/
|
||||
|
||||
53
test/classes/OpenDocumentTest.php
Normal file
53
test/classes/OpenDocumentTest.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Tests;
|
||||
|
||||
use DateTime;
|
||||
use PhpMyAdmin\OpenDocument;
|
||||
use PhpMyAdmin\ZipExtension;
|
||||
use ZipArchive;
|
||||
|
||||
use function file_put_contents;
|
||||
use function tempnam;
|
||||
use function unlink;
|
||||
|
||||
/**
|
||||
* @requires extension zip
|
||||
*/
|
||||
class OpenDocumentTest extends AbstractTestCase
|
||||
{
|
||||
public function testCreateDocument(): void
|
||||
{
|
||||
$document = OpenDocument::create(
|
||||
'application/vnd.oasis.opendocument.text',
|
||||
'<data>'
|
||||
);
|
||||
$this->assertNotFalse($document);
|
||||
|
||||
$tmpFile = (string) tempnam('./', 'open-document-test');
|
||||
$this->assertNotFalse(file_put_contents($tmpFile, $document), 'The temp file should be written');
|
||||
|
||||
$zipExtension = new ZipExtension(new ZipArchive());
|
||||
$this->assertSame([
|
||||
'error' => '',
|
||||
'data' => 'application/vnd.oasis.opendocument.text',
|
||||
], $zipExtension->getContents($tmpFile));
|
||||
|
||||
$this->assertSame([
|
||||
'error' => '',
|
||||
'data' => '<data>',
|
||||
], $zipExtension->getContents($tmpFile, '/content\.xml/'));
|
||||
|
||||
$dateTimeCreation = (new DateTime())->format('Y-m-d\TH:i');
|
||||
$this->assertStringContainsString(
|
||||
// Do not use a full version or seconds could be out of sync and cause flaky test failures
|
||||
'<meta:creation-date>' . $dateTimeCreation,
|
||||
$zipExtension->getContents($tmpFile, '/meta\.xml/')['data']
|
||||
);
|
||||
|
||||
$this->assertSame(5, $zipExtension->getNumberOfFiles($tmpFile));
|
||||
$this->assertTrue(unlink($tmpFile));
|
||||
}
|
||||
}
|
||||
@ -1768,7 +1768,7 @@ class DbiDummy implements DbiExtension
|
||||
'result' => [],
|
||||
],
|
||||
[
|
||||
'query' => "SHOW TABLE STATUS FROM `my_dataset` WHERE `Name` LIKE 'company\_users%'",
|
||||
'query' => "SHOW TABLE STATUS FROM `my_dataset` WHERE `Name` LIKE 'company\\\\_users%'",
|
||||
'result' => [],
|
||||
],
|
||||
[
|
||||
@ -2389,7 +2389,7 @@ class DbiDummy implements DbiExtension
|
||||
'result' => [['1']],
|
||||
],
|
||||
[
|
||||
'query' => 'SHOW TABLE STATUS FROM `PMA_db` WHERE `Name` LIKE \'PMA\_table%\'',
|
||||
'query' => 'SHOW TABLE STATUS FROM `PMA_db` WHERE `Name` LIKE \'PMA\\\\_table%\'',
|
||||
'columns' => ['Name', 'Engine'],
|
||||
'result' => [['PMA_table', 'InnoDB']],
|
||||
],
|
||||
@ -2443,7 +2443,7 @@ class DbiDummy implements DbiExtension
|
||||
],
|
||||
],
|
||||
[
|
||||
'query' => 'SHOW FULL COLUMNS FROM `testdb`.`mytable` LIKE \'\_id\'',
|
||||
'query' => 'SHOW FULL COLUMNS FROM `testdb`.`mytable` LIKE \'\\\\_id\'',
|
||||
'columns' => ['Field', 'Type', 'Collation', 'Null', 'Key', 'Default', 'Extra', 'Privileges', 'Comment'],
|
||||
'result' => [
|
||||
[
|
||||
@ -2548,7 +2548,7 @@ class DbiDummy implements DbiExtension
|
||||
],
|
||||
],
|
||||
[
|
||||
'query' => 'SHOW TABLE STATUS FROM `test_db` WHERE `Name` LIKE \'test\_table%\'',
|
||||
'query' => 'SHOW TABLE STATUS FROM `test_db` WHERE `Name` LIKE \'test\\\\_table%\'',
|
||||
'columns' => ['Name', 'Engine', 'Rows'],
|
||||
'result' => [['test_table', 'InnoDB', '3']],
|
||||
],
|
||||
@ -2713,7 +2713,7 @@ class DbiDummy implements DbiExtension
|
||||
'result' => [],
|
||||
],
|
||||
[
|
||||
'query' => 'SHOW TABLE STATUS FROM `my_db` WHERE `Name` LIKE \'test\_tbl%\'',
|
||||
'query' => 'SHOW TABLE STATUS FROM `my_db` WHERE `Name` LIKE \'test\\\\_tbl%\'',
|
||||
'result' => [],
|
||||
],
|
||||
[
|
||||
|
||||
Loading…
Reference in New Issue
Block a user