| Server IP : 3.96.16.70 / Your IP : 216.73.216.15 Web Server : Apache System : Linux ip-172-31-26-103.ca-central-1.compute.internal 6.1.163-186.299.amzn2023.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Feb 24 16:35:42 UTC 2026 x86_64 User : ec2-user ( 1000) PHP Version : 8.4.18 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/html/prod1.wondermakr.com/phpmyadmin/test/classes/Html/ |
Upload File : |
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Tests\Html;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Message;
use PhpMyAdmin\Tests\AbstractTestCase;
use PhpMyAdmin\Tests\Stubs\DbiDummy;
use PhpMyAdmin\Util;
use PhpMyAdmin\Utils\SessionCache;
use function __;
use function _pgettext;
use function call_user_func_array;
use function htmlspecialchars;
use function urlencode;
/**
* @covers \PhpMyAdmin\Html\Generator
*/
class GeneratorTest extends AbstractTestCase
{
/**
* Set up the test.
*/
protected function setUp(): void
{
parent::setUp();
parent::setLanguage();
}
/**
* Test for getDbLink
*
* @group medium
*/
public function testGetDbLinkEmpty(): void
{
$GLOBALS['db'] = null;
self::assertEmpty(Generator::getDbLink());
}
/**
* Test for getDbLink
*
* @group medium
*/
public function testGetDbLinkNull(): void
{
global $cfg;
$GLOBALS['db'] = 'test_db';
$GLOBALS['server'] = 99;
$database = $GLOBALS['db'];
self::assertSame('<a href="'
. Util::getScriptNameForOption(
$GLOBALS['cfg']['DefaultTabDatabase'],
'database'
)
. '&db=' . $database
. '&server=99&lang=en" '
. 'title="Jump to database “'
. htmlspecialchars($database) . '”.">'
. htmlspecialchars($database) . '</a>', Generator::getDbLink());
}
/**
* Test for getDbLink
*/
public function testGetDbLink(): void
{
$GLOBALS['server'] = 99;
$database = 'test_database';
self::assertSame('<a href="' . Util::getScriptNameForOption(
$GLOBALS['cfg']['DefaultTabDatabase'],
'database'
)
. '&db=' . $database
. '&server=99&lang=en" title="Jump to database “'
. htmlspecialchars($database) . '”.">'
. htmlspecialchars($database) . '</a>', Generator::getDbLink($database));
}
/**
* Test for getDbLink
*/
public function testGetDbLinkWithSpecialChars(): void
{
$GLOBALS['server'] = 99;
$database = 'test&data\'base';
self::assertSame('<a href="'
. Util::getScriptNameForOption(
$GLOBALS['cfg']['DefaultTabDatabase'],
'database'
)
. '&db='
. htmlspecialchars(urlencode($database))
. '&server=99&lang=en" title="Jump to database “'
. htmlspecialchars($database) . '”.">'
. htmlspecialchars($database) . '</a>', Generator::getDbLink($database));
}
/**
* Test for Util::getIcon
*/
public function testGetIconWithoutActionLinksMode(): void
{
$GLOBALS['cfg']['ActionLinksMode'] = 'text';
self::assertSame('<span class="text-nowrap"></span>', Generator::getIcon('b_comment'));
}
/**
* Test for Util::getIcon
*/
public function testGetIconWithActionLinksMode(): void
{
$GLOBALS['cfg']['ActionLinksMode'] = 'icons';
self::assertSame(
'<span class="text-nowrap"><img src="themes/dot.gif" title="" alt="" class="icon ic_b_comment"></span>',
Generator::getIcon('b_comment')
);
}
/**
* Test for Util::getIcon
*/
public function testGetIconAlternate(): void
{
$GLOBALS['cfg']['ActionLinksMode'] = 'icons';
$alternate_text = 'alt_str';
self::assertSame('<span class="text-nowrap"><img src="themes/dot.gif" title="'
. $alternate_text . '" alt="' . $alternate_text
. '" class="icon ic_b_comment"></span>', Generator::getIcon('b_comment', $alternate_text));
}
/**
* Test for Util::getIcon
*/
public function testGetIconWithForceText(): void
{
$GLOBALS['cfg']['ActionLinksMode'] = 'icons';
$alternate_text = 'alt_str';
// Here we are checking for an icon embedded inside a span (i.e not a menu
// bar icon
self::assertSame(
'<span class="text-nowrap"><img src="themes/dot.gif" title="'
. $alternate_text . '" alt="' . $alternate_text
. '" class="icon ic_b_comment"> ' . $alternate_text . '</span>',
Generator::getIcon('b_comment', $alternate_text, true, false)
);
}
/**
* Test for showPHPDocumentation
*/
public function testShowPHPDocumentation(): void
{
$GLOBALS['server'] = 99;
$GLOBALS['cfg']['ServerDefault'] = 0;
$target = 'docu';
$lang = _pgettext('PHP documentation language', 'en');
$expected = '<a href="./url.php?url=https%3A%2F%2Fwww.php.net%2Fmanual%2F' . $lang
. '%2F' . $target . '" target="documentation">'
. '<img src="themes/dot.gif" title="' . __('Documentation') . '" alt="'
. __('Documentation') . '" class="icon ic_b_help"></a>';
self::assertSame($expected, Generator::showPHPDocumentation($target));
}
/**
* Test for Generator::linkOrButton
*
* @param array $params params
* @param int $limit limit
* @param string $match match
*
* @dataProvider linksOrButtons
*/
public function testLinkOrButton(array $params, int $limit, string $match): void
{
parent::setGlobalConfig();
$restore = $GLOBALS['cfg']['LinkLengthLimit'] ?? 1000;
$GLOBALS['cfg']['LinkLengthLimit'] = $limit;
try {
$result = call_user_func_array(
[
Generator::class,
'linkOrButton',
],
$params
);
self::assertSame($match, $result);
} finally {
$GLOBALS['cfg']['LinkLengthLimit'] = $restore;
}
}
/**
* Data provider for Generator::linkOrButton test
*
* @return array
*/
public static function linksOrButtons(): array
{
return [
[
[
'index.php',
null,
'text',
],
1000,
'<a href="index.php" >text</a>',
],
[
[
'index.php',
['some' => 'parameter'],
'text',
],
20,
'<a href="index.php" data-post="some=parameter&lang=en">text</a>',
],
[
[
'index.php',
null,
'text',
[],
'target',
],
1000,
'<a href="index.php" target="target">text</a>',
],
[
[
'https://mariadb.org/explain_analyzer/analyze/?client=phpMyAdmin&raw_explain=%2B---%2B',
null,
'text',
[],
'target',
],
10,
// This is not the behavior we want for the analyser feature, next test will disable the limit
'<a href="https://mariadb.org/explain_analyzer/analyze/"'
. ' data-post="client=phpMyAdmin&raw_explain=%2B---%2B" target="target">text</a>',
],
[
[
'https://mariadb.org/explain_analyzer/analyze/?client=phpMyAdmin&raw_explain=%2B---%2B',
null,
'text',
[],
'target',
false,
],
10,
'<a href="https://mariadb.org/explain_analyzer/analyze/?client=phpMyAdmin&raw_explain=%2B---%2B"'
. ' target="target">text</a>',
],
[
[
'url.php?url=http://phpmyadmin.net/',
null,
'text',
[],
'_blank',
],
1000,
'<a href="url.php?url=http://phpmyadmin.net/" target="_blank" rel="noopener noreferrer">text</a>',
],
[
[
'index.php?route=/server/databases',
['some' => 'parameter'],
'text',
],
20,
'<a href="index.php" data-post="route=/server/databases&some=parameter&lang=en">text</a>',
],
[
[
'index.php?route=/server/databases',
null,
'text',
],
20,
'<a href="index.php" data-post="route=/server/databases">text</a>',
],
[
[
'index.php?route=/server/databases',
['some' => 'parameter'],
'text',
],
100,
'<a href="index.php?route=/server/databases&some=parameter&lang=en" >text</a>',
],
[
[
'index.php?route=/server/databases',
null,
'text',
],
100,
'<a href="index.php?route=/server/databases" >text</a>',
],
[
[
'index.php',
null,
'text',
['title' => '"'],
],
100,
'<a href="index.php" title=""">text</a>',
],
];
}
public function testFormatSql(): void
{
self::assertSame('<code class="sql" dir="ltr"><pre>' . "\n"
. 'SELECT 1 < 2' . "\n"
. '</pre></code>', Generator::formatSql('SELECT 1 < 2'));
$GLOBALS['cfg']['MaxCharactersInDisplayedSQL'] = 6;
self::assertSame('<code class="sql" dir="ltr"><pre>' . "\n"
. 'SELECT[...]' . "\n"
. '</pre></code>', Generator::formatSql('SELECT 1 < 2', true));
}
/**
* Test for getServerSSL
*/
public function testGetServerSSL(): void
{
global $cfg;
$sslNotUsed = '<span class="">SSL is not being used</span>'
. ' <a href="./url.php?url=https%3A%2F%2Fdocs.phpmyadmin.net%2Fen%2Flatest%2Fsetup.html%23ssl"'
. ' target="documentation"><img src="themes/dot.gif" title="Documentation" alt="Documentation"'
. ' class="icon ic_b_help"></a>';
$sslNotUsedCaution = '<span class="text-danger">SSL is not being used</span>'
. ' <a href="./url.php?url=https%3A%2F%2Fdocs.phpmyadmin.net%2Fen%2Flatest%2Fsetup.html%23ssl"'
. ' target="documentation"><img src="themes/dot.gif" title="Documentation" alt="Documentation"'
. ' class="icon ic_b_help"></a>';
$cfg['Server'] = [
'ssl' => false,
'host' => '127.0.0.1',
];
self::assertSame($sslNotUsed, Generator::getServerSSL());
$cfg['Server'] = [
'ssl' => false,
'host' => 'custom.host',
];
$cfg['MysqlSslWarningSafeHosts'] = ['localhost', '127.0.0.1'];
self::assertSame($sslNotUsedCaution, Generator::getServerSSL());
$cfg['Server'] = [
'ssl' => false,
'host' => 'custom.host',
];
$cfg['MysqlSslWarningSafeHosts'] = ['localhost', '127.0.0.1', 'custom.host'];
self::assertSame($sslNotUsed, Generator::getServerSSL());
$cfg['Server'] = [
'ssl' => false,
'ssl_verify' => true,
'host' => 'custom.host',
];
self::assertSame($sslNotUsed, Generator::getServerSSL());
$cfg['Server'] = [
'ssl' => true,
'ssl_verify' => false,
'host' => 'custom.host',
];
self::assertSame('<span class="text-danger">SSL is used with disabled verification</span>'
. ' <a href="./url.php?url=https%3A%2F%2Fdocs.phpmyadmin.net%2Fen%2Flatest%2Fsetup.html%23ssl"'
. ' target="documentation"><img src="themes/dot.gif" title="Documentation" alt="Documentation"'
. ' class="icon ic_b_help"></a>', Generator::getServerSSL());
$cfg['Server'] = [
'ssl' => true,
'ssl_verify' => true,
'host' => 'custom.host',
];
self::assertSame('<span class="text-danger">SSL is used without certification authority</span>'
. ' <a href="./url.php?url=https%3A%2F%2Fdocs.phpmyadmin.net%2Fen%2Flatest%2Fsetup.html%23ssl"'
. ' target="documentation"><img src="themes/dot.gif" title="Documentation" alt="Documentation"'
. ' class="icon ic_b_help"></a>', Generator::getServerSSL());
$cfg['Server'] = [
'ssl' => true,
'ssl_verify' => true,
'ssl_ca' => '/etc/ssl/ca.crt',
'host' => 'custom.host',
];
self::assertSame('<span class="">SSL is used</span>'
. ' <a href="./url.php?url=https%3A%2F%2Fdocs.phpmyadmin.net%2Fen%2Flatest%2Fsetup.html%23ssl"'
. ' target="documentation"><img src="themes/dot.gif" title="Documentation" alt="Documentation"'
. ' class="icon ic_b_help"></a>', Generator::getServerSSL());
}
/**
* Test for Generator::getDefaultFunctionForField
*
* @param array $field field settings
* @param bool $insertMode true if insert mode
* @param string $expected expected result
* @psalm-param array<string, string|bool|null> $field
*
* @dataProvider providerForTestGetDefaultFunctionForField
*/
public function testGetDefaultFunctionForField(
array $field,
bool $insertMode,
string $expected
): void {
$result = Generator::getDefaultFunctionForField($field, $insertMode);
self::assertSame($expected, $result);
}
/**
* Data provider for Generator::getDefaultFunctionForField test
*
* @return array
* @psalm-return array<int, array{array<string, string|bool|null>, bool, string}>
*/
public static function providerForTestGetDefaultFunctionForField(): array
{
return [
[
[
'True_Type' => 'GEOMETRY',
'first_timestamp' => false,
'Extra' => null,
'Key' => '',
'Type' => '',
'Null' => 'NO',
],
true,
'ST_GeomFromText',
],
[
[
'True_Type' => 'timestamp',
'first_timestamp' => true,
'Extra' => null,
'Key' => '',
'Type' => '',
'Null' => 'NO',
],
true,
'NOW',
],
[
[
'True_Type' => 'uuid',
'first_timestamp' => false,
'Key' => '',
'Type' => '',
],
true,
'',
],
[
[
'True_Type' => '',
'first_timestamp' => false,
'Key' => 'PRI',
'Type' => 'char(36)',
],
true,
'UUID',
],
];
}
public function testGetMessage(): void
{
$GLOBALS['cfg']['ShowSQL'] = true;
$GLOBALS['display_query'] = null;
$GLOBALS['unparsed_sql'] = null;
$GLOBALS['sql_query'] = 'SELECT 1;';
$usingBookmarkMessage = Message::notice('Bookmark message');
$GLOBALS['using_bookmark_message'] = $usingBookmarkMessage;
$GLOBALS['dbi'] = DatabaseInterface::load(new DbiDummy());
$GLOBALS['db'] = 'test_db';
$GLOBALS['table'] = 'test_table';
$GLOBALS['server'] = 2;
$GLOBALS['special_message'] = 'Message [em]two[/em].';
SessionCache::set('profiling_supported', true);
// phpcs:disable Generic.Files.LineLength.TooLong
$expected = <<<'HTML'
<div class="alert alert-primary" role="alert">
<img src="themes/dot.gif" title="" alt="" class="icon ic_s_notice"> Bookmark message
</div>
<div class="result_query">
<div class="alert alert-primary" role="alert">Message <em>one</em>.Message <em>two</em>.</div><div class="sqlOuter"><code class="sql" dir="ltr"><pre>
SELECT 1;
</pre></code></div><div class="tools d-print-none"><form action="index.php?route=/sql&db=test_db&table=test_table&server=2&lang=en" method="post" class="disableAjax"><input type="hidden" name="db" value="test_db"><input type="hidden" name="table" value="test_table"><input type="hidden" name="server" value="2"><input type="hidden" name="lang" value="en"><input type="hidden" name="token" value="token"><input type="hidden" name="sql_query" value="SELECT 1;"><input type="hidden" name="profiling_form" value="1"><input type="checkbox" name="profiling" id="profilingCheckbox" class="autosubmit"> <label for="profilingCheckbox">Profiling</label></form> [ <a href="#" class="inline_edit_sql">Edit inline</a> ] [ <a href="index.php" data-post="route=/table/sql&db=test_db&table=test_table&sql_query=SELECT+1%3B&show_query=1&server=2&lang=en">Edit</a> ] [ <a href="index.php" data-post="route=/import&db=test_db&table=test_table&sql_query=EXPLAIN+SELECT+1%3B&server=2&lang=en">Explain SQL</a> ] [ <a href="index.php" data-post="route=/import&db=test_db&table=test_table&sql_query=SELECT+1%3B&show_query=1&show_as_php=1&server=2&lang=en">Create PHP code</a> ] [ <a href="index.php" data-post="route=/sql&db=test_db&table=test_table&sql_query=SELECT+1%3B&show_query=1&server=2&lang=en">Refresh</a> ]</div></div>
HTML;
// phpcs:enable
self::assertSame($expected, Generator::getMessage('Message [em]one[/em].'));
self::assertArrayNotHasKey('using_bookmark_message', $GLOBALS);
self::assertArrayNotHasKey('special_message', $GLOBALS);
SessionCache::remove('profiling_supported');
}
public function testGetMessage2(): void
{
$GLOBALS['cfg']['ShowSQL'] = true;
$GLOBALS['cfg']['SQLQuery']['Edit'] = false;
$GLOBALS['cfg']['SQLQuery']['Refresh'] = true;
$GLOBALS['display_query'] = 'EXPLAIN SELECT 1;';
$GLOBALS['unparsed_sql'] = null;
$GLOBALS['sql_query'] = null;
$GLOBALS['dbi'] = DatabaseInterface::load(new DbiDummy());
$GLOBALS['db'] = 'test_db';
$GLOBALS['table'] = 'test_table';
$GLOBALS['server'] = 2;
$GLOBALS['show_as_php'] = true;
$GLOBALS['special_message'] = 'Message [em]two[/em].';
SessionCache::set('profiling_supported', true);
// phpcs:disable Generic.Files.LineLength.TooLong
$expected = <<<'HTML'
<div class="result_query">
<div class="alert alert-success" role="alert">
<img src="themes/dot.gif" title="" alt="" class="icon ic_s_success"> Message <em>one</em>. Message <em>two</em>.
</div>
<div class="sqlOuter"><code class="php" dir="ltr"><pre>
$sql = "EXPLAIN SELECT 1;";
</pre></code></div><div class="tools d-print-none"><form action="index.php?route=/sql&db=test_db&table=test_table&server=2&lang=en" method="post" class="disableAjax"><input type="hidden" name="db" value="test_db"><input type="hidden" name="table" value="test_table"><input type="hidden" name="server" value="2"><input type="hidden" name="lang" value="en"><input type="hidden" name="token" value="token"><input type="hidden" name="sql_query" value="EXPLAIN SELECT 1;"></form> [ <a href="index.php" data-post="route=/import&db=test_db&table=test_table&sql_query=SELECT+1%3B&server=2&lang=en">Skip Explain SQL</a>] [ <a href="index.php" data-post="route=/import&db=test_db&table=test_table&sql_query=EXPLAIN+SELECT+1%3B&show_query=1&server=2&lang=en">Without PHP code</a> ] [ <a href="index.php" data-post="route=/import&db=test_db&table=test_table&sql_query=EXPLAIN+SELECT+1%3B&show_query=1&server=2&lang=en">Submit query</a> ]</div></div>
HTML;
// phpcs:enable
self::assertSame($expected, Generator::getMessage(Message::success('Message [em]one[/em].')));
self::assertArrayNotHasKey('special_message', $GLOBALS);
SessionCache::remove('profiling_supported');
}
}