3 declare(strict_types
=1);
5 namespace PhpMyAdmin\Tests
;
8 use PhpMyAdmin\Config\Settings
;
9 use PhpMyAdmin\DatabaseInterface
;
11 use function array_merge
;
12 use function array_replace_recursive
;
15 use function file_exists
;
16 use function file_put_contents
;
17 use function fileperms
;
18 use function function_exists
;
20 use function mb_strstr
;
21 use function ob_end_clean
;
22 use function ob_get_contents
;
23 use function ob_start
;
25 use function preg_match
;
26 use function realpath
;
27 use function strip_tags
;
29 use function sys_get_temp_dir
;
33 use const DIRECTORY_SEPARATOR
;
34 use const INFO_MODULES
;
39 * @covers \PhpMyAdmin\Config
41 class ConfigTest
extends AbstractTestCase
46 /** @var Config to test file permission */
47 protected $permTestObj;
50 * Sets up the fixture, for example, opens a network connection.
51 * This method is called before a test is executed.
53 protected function setUp(): void
57 $_SERVER['HTTP_USER_AGENT'] = '';
58 $this->object = new Config();
59 $GLOBALS['server'] = 0;
60 $_SESSION['git_location'] = '.git';
61 $_SESSION['is_git_revision'] = true;
62 $GLOBALS['config'] = new Config(CONFIG_FILE
);
63 $GLOBALS['cfg']['ProxyUrl'] = '';
65 //for testing file permissions
66 $this->permTestObj
= new Config(ROOT_PATH
. 'config.sample.inc.php');
70 * Tears down the fixture, for example, closes a network connection.
71 * This method is called after a test is executed.
73 protected function tearDown(): void
77 unset($this->permTestObj
);
83 public function testLoadConfigs(): void
85 $defaultConfig = new Config();
86 $tmpConfig = tempnam('./', 'config.test.inc.php');
87 if ($tmpConfig === false) {
88 $this->markTestSkipped('Creating a temporary file does not work');
91 $this->assertFileExists($tmpConfig);
95 // Test loading an empty file does not change the default config
96 $config = new Config($tmpConfig);
97 $this->assertSame($defaultConfig->settings
, $config->settings
);
99 $contents = '<?php' . PHP_EOL
100 . '$cfg[\'ProtectBinary\'] = true;';
101 file_put_contents($tmpConfig, $contents);
103 // Test loading a config changes the setup
104 $config = new Config($tmpConfig);
105 $defaultConfig->settings
['ProtectBinary'] = true;
106 $this->assertSame($defaultConfig->settings
, $config->settings
);
107 $defaultConfig->settings
['ProtectBinary'] = 'blob';
111 $this->assertFalse(file_exists($tmpConfig));
117 public function testLoadInvalidConfigs(): void
119 $defaultConfig = new Config();
120 $tmpConfig = tempnam('./', 'config.test.inc.php');
121 if ($tmpConfig === false) {
122 $this->markTestSkipped('Creating a temporary file does not work');
125 $this->assertFileExists($tmpConfig);
129 // Test loading an empty file does not change the default config
130 $config = new Config($tmpConfig);
131 $this->assertSame($defaultConfig->settings
, $config->settings
);
133 $contents = '<?php' . PHP_EOL
134 . '$cfg[\'fooBar\'] = true;';
135 file_put_contents($tmpConfig, $contents);
137 // Test loading a custom key config changes the setup
138 $config = new Config($tmpConfig);
139 $defaultConfig->settings
['fooBar'] = true;
140 // Equals because of the key sorting
141 $this->assertEquals($defaultConfig->settings
, $config->settings
);
142 unset($defaultConfig->settings
['fooBar']);
144 $contents = '<?php' . PHP_EOL
145 . '$cfg[\'/InValidKey\'] = true;' . PHP_EOL
146 . '$cfg[\'In/ValidKey\'] = true;' . PHP_EOL
147 . '$cfg[\'/InValid/Key\'] = true;' . PHP_EOL
148 . '$cfg[\'In/Valid/Key\'] = true;' . PHP_EOL
149 . '$cfg[\'ValidKey\'] = true;';
150 file_put_contents($tmpConfig, $contents);
152 // Test loading a custom key config changes the setup
153 $config = new Config($tmpConfig);
154 $defaultConfig->settings
['ValidKey'] = true;
155 // Equals because of the key sorting
156 $this->assertEquals($defaultConfig->settings
, $config->settings
);
157 unset($defaultConfig->settings
['ValidKey']);
161 $this->assertFalse(file_exists($tmpConfig));
165 * Test for CheckSystem
169 public function testCheckSystem(): void
171 $this->object->checkSystem();
173 $this->assertIsBool($this->object->get('PMA_IS_WINDOWS'));
177 * Test for checkOutputCompression
179 public function testCheckOutputCompression(): void
181 $this->object->set('OBGzip', 'auto');
183 $this->object->set('PMA_USR_BROWSER_AGENT', 'IE');
184 $this->object->set('PMA_USR_BROWSER_VER', 6);
185 $this->object->checkOutputCompression();
186 $this->assertTrue($this->object->get('OBGzip'));
188 $this->object->set('OBGzip', 'auto');
189 $this->object->set('PMA_USR_BROWSER_AGENT', 'MOZILLA');
190 $this->object->set('PMA_USR_BROWSER_VER', 5);
191 $this->object->checkOutputCompression();
192 $this->assertTrue($this->object->get('OBGzip'));
196 * Tests client parsing code.
198 * @param string $agent User agent string
199 * @param string $os Expected parsed OS (or null if none)
200 * @param string $browser Expected parsed browser (or null if none)
201 * @param string $version Expected browser version (or null if none)
203 * @dataProvider userAgentProvider
205 public function testCheckClient(string $agent, string $os, ?
string $browser = null, ?
string $version = null): void
207 $_SERVER['HTTP_USER_AGENT'] = $agent;
208 $this->object->checkClient();
209 $this->assertEquals($os, $this->object->get('PMA_USR_OS'));
213 $this->object->get('PMA_USR_BROWSER_AGENT')
217 if ($version == null) {
223 $this->object->get('PMA_USR_BROWSER_VER')
228 * user Agent Provider
232 public function userAgentProvider(): array
236 'Opera/9.80 (X11; Linux x86_64; U; pl) Presto/2.7.62 Version/11.00',
242 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US) AppleWebKit/528.16 OmniWeb/622.8.0.112941',
248 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1)',
254 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)',
260 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)',
266 'Mozilla/5.0 (IE 11.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C; rv:11.0) like Gecko',
272 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; '
273 . '.NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; '
274 . '.NET CLR 3.0.30729; InfoPath.3; rv:11.0) like Gecko',
280 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, '
281 . 'like Gecko) Chrome/25.0.1364.172 Safari/537.22',
287 'Mozilla/5.0 (Unknown; U; Unix BSD/SYSV system; C -) '
288 . 'AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.10.2',
294 'Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.9b) Gecko/20031208',
300 'Mozilla/5.0 (compatible; Konqueror/4.5; NetBSD 5.0.2; X11; amd64; en_US) KHTML/4.5.4 (like Gecko)',
305 'Mozilla/5.0 (X11; Linux x86_64; rv:5.0) Gecko/20100101 Firefox/5.0',
311 'Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/12.0',
317 * @todo Is this version really expected?
320 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.4+ (KHTML, like G'
321 . 'ecko) Version/5.0 Safari/535.4+ SUSE/12.1 (3.2.1) Epiphany/3.2.1',
332 public function testCheckGd2(): void
334 $this->object->set('GD2Available', 'yes');
335 $this->object->checkGd2();
336 $this->assertEquals(1, $this->object->get('PMA_IS_GD2'));
338 $this->object->set('GD2Available', 'no');
339 $this->object->checkGd2();
340 $this->assertEquals(0, $this->object->get('PMA_IS_GD2'));
342 $this->object->set('GD2Available', 'auto');
344 if (! function_exists('imagecreatetruecolor')) {
345 $this->object->checkGd2();
348 $this->object->get('PMA_IS_GD2'),
349 'imagecreatetruecolor does not exist, PMA_IS_GD2 should be 0'
353 if (function_exists('gd_info')) {
354 $this->object->checkGd2();
356 if (mb_strstr($gd_nfo['GD Version'], '2.')) {
359 $this->object->get('PMA_IS_GD2'),
360 'GD Version >= 2, PMA_IS_GD2 should be 1'
365 $this->object->get('PMA_IS_GD2'),
366 'GD Version < 2, PMA_IS_GD2 should be 0'
371 /* Get GD version string from phpinfo output */
373 phpinfo(INFO_MODULES
); /* Only modules */
374 $a = strip_tags((string) ob_get_contents());
377 if (! preg_match('@GD Version[[:space:]]*\(.*\)@', $a, $v)) {
381 if (mb_strstr($v, '2.')) {
384 $this->object->get('PMA_IS_GD2'),
385 'PMA_IS_GD2 should be 1'
390 $this->object->get('PMA_IS_GD2'),
391 'PMA_IS_GD2 should be 0'
397 * Web server detection test
399 * @param string $server Server identification
400 * @param int $iis Whether server should be detected as IIS
402 * @dataProvider serverNames
404 public function testCheckWebServer(string $server, int $iis): void
406 $_SERVER['SERVER_SOFTWARE'] = $server;
407 $this->object->checkWebServer();
408 $this->assertEquals($iis, $this->object->get('PMA_IS_IIS'));
409 unset($_SERVER['SERVER_SOFTWARE']);
413 * return server names
417 public function serverNames(): array
432 * test for CheckWebServerOs
434 public function testCheckWebServerOs(): void
436 $this->object->checkWebServerOs();
438 if (defined('PHP_OS')) {
439 if (stristr(PHP_OS
, 'darwin')) {
440 $this->assertFalse($this->object->get('PMA_IS_WINDOWS'));
441 } elseif (stristr(PHP_OS
, 'win')) {
442 $this->assertTrue($this->object->get('PMA_IS_WINDOWS'));
443 } elseif (stristr(PHP_OS
, 'OS/2')) {
444 $this->assertTrue($this->object->get('PMA_IS_WINDOWS'));
445 } elseif (stristr(PHP_OS
, 'Linux')) {
446 $this->assertFalse($this->object->get('PMA_IS_WINDOWS'));
448 $this->markTestIncomplete('Not known PHP_OS: ' . PHP_OS
);
451 $this->assertEquals(0, $this->object->get('PMA_IS_WINDOWS'));
453 define('PHP_OS', 'Windows');
454 $this->assertTrue($this->object->get('PMA_IS_WINDOWS'));
459 * Tests loading of default values
463 public function testLoadDefaults(): void
465 $this->object->defaultServer
= [];
466 $this->object->default = [];
467 $this->object->settings
= ['is_setup' => false, 'AvailableCharsets' => ['test']];
469 $this->object->loadDefaults();
471 $settings = new Settings([]);
472 $config = $settings->toArray();
474 $this->assertIsArray($config['Servers']);
475 $this->assertEquals($config['Servers'][1], $this->object->defaultServer
);
476 unset($config['Servers']);
477 $this->assertEquals($config, $this->object->default);
479 array_replace_recursive(['is_setup' => false, 'AvailableCharsets' => ['test']], $config),
480 $this->object->settings
485 * test for CheckConfigSource
487 public function testCheckConfigSource(): void
489 $this->object->setSource('unexisted.config.php');
490 $this->assertFalse($this->object->checkConfigSource());
491 $this->assertEquals(0, $this->object->sourceMtime
);
493 $this->object->setSource(ROOT_PATH
. 'test/test_data/config.inc.php');
495 $this->assertNotEmpty($this->object->getSource());
496 $this->assertTrue($this->object->checkConfigSource());
500 * Test getting and setting config values
502 public function testGetAndSet(): void
504 $this->assertNull($this->object->get('unresisting_setting'));
506 $this->object->set('test_setting', 'test_value');
508 $this->assertEquals('test_value', $this->object->get('test_setting'));
512 * Tests setting configuration source
514 public function testGetSetSource(): void
516 echo $this->object->getSource();
518 $this->assertEmpty($this->object->getSource(), 'Source is null by default');
520 $this->object->setSource(ROOT_PATH
. 'config.sample.inc.php');
523 ROOT_PATH
. 'config.sample.inc.php',
524 $this->object->getSource(),
525 'Cant set new source'
532 * @param string $scheme http scheme
533 * @param string $https https
534 * @param string $forwarded forwarded header
535 * @param string $uri request uri
536 * @param string $lb http https from lb
537 * @param string $front http front end https
538 * @param string $proto http x forwarded proto
539 * @param string $protoCloudFront http cloudfront forwarded proto
540 * @param string $pmaAbsoluteUri phpMyAdmin absolute URI
541 * @param int $port server port
542 * @param bool $expected expected result
544 * @dataProvider httpsParams
546 public function testIsHttps(
554 string $protoCloudFront,
555 string $pmaAbsoluteUri,
559 $_SERVER['HTTP_SCHEME'] = $scheme;
560 $_SERVER['HTTPS'] = $https;
561 $_SERVER['HTTP_FORWARDED'] = $forwarded;
562 $_SERVER['REQUEST_URI'] = $uri;
563 $_SERVER['HTTP_HTTPS_FROM_LB'] = $lb;
564 $_SERVER['HTTP_FRONT_END_HTTPS'] = $front;
565 $_SERVER['HTTP_X_FORWARDED_PROTO'] = $proto;
566 $_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO'] = $protoCloudFront;
567 $_SERVER['SERVER_PORT'] = $port;
569 $this->object->set('is_https', null);
570 $this->object->set('PmaAbsoluteUri', $pmaAbsoluteUri);
571 $this->assertEquals($expected, $this->object->isHttps());
575 * Data provider for https detection
579 public function httpsParams(): array
780 'for=12.34.56.78;host=example.com;proto=https, for=23.45.67.89',
794 * Test for getting root path
796 * @param string $request The request URL used for phpMyAdmin
797 * @param string $absolute The absolute URL used for phpMyAdmin
798 * @param string $expected Expected root path
800 * @dataProvider rootUris
802 public function testGetRootPath(string $request, string $absolute, string $expected): void
804 $GLOBALS['PMA_PHP_SELF'] = $request;
805 $this->object->set('PmaAbsoluteUri', $absolute);
806 $this->assertEquals($expected, $this->object->getRootPath());
810 * Data provider for testGetRootPath
812 * @return array data for testGetRootPath
814 public function rootUris(): array
843 '\\path\\to\\index.php',
848 '/foo/bar/phpmyadmin/index.php',
850 '/foo/bar/phpmyadmin/',
853 '/foo/bar/phpmyadmin/',
855 '/foo/bar/phpmyadmin/',
858 'https://example.net/baz/phpmyadmin/',
863 'http://example.net/baz/phpmyadmin/',
868 'http://example.net/phpmyadmin/',
873 'http://example.net/',
878 'http://example.net/',
879 'http://example.net/phpmyadmin/',
883 'http://example.net/',
884 'http://example.net/phpmyadmin',
888 'http://example.net/',
893 'http://example.net/',
901 * Tests loading of config file
903 * @param string $source File name of config to load
904 * @param bool $result Expected result of loading
906 * @dataProvider configPaths
908 public function testLoad(string $source, bool $result): void
911 $this->assertTrue($this->object->load($source));
913 $this->assertFalse($this->object->load($source));
918 * return of config Paths
922 public function configPaths(): array
926 ROOT_PATH
. 'test/test_data/config.inc.php',
930 ROOT_PATH
. 'test/test_data/config-nonexisting.inc.php',
937 * Test for loading user preferences
939 * @todo Test actually preferences loading
940 * @doesNotPerformAssertions
942 public function testLoadUserPreferences(): void
944 $this->object->loadUserPreferences();
948 * Test for setting user config value
950 public function testSetUserValue(): void
952 $this->object->setUserValue(null, 'lang', 'cs', 'en');
953 $this->object->setUserValue('TEST_COOKIE_USER_VAL', '', 'cfg_val_1');
955 $this->object->getUserValue('TEST_COOKIE_USER_VAL', 'fail'),
961 * Test for getting user config value
963 public function testGetUserValue(): void
965 $this->assertEquals($this->object->getUserValue('test_val', 'val'), 'val');
969 * Should test checking of config permissions
971 public function testCheckPermissions(): void
973 //load file permissions for the current permissions file
974 $perms = @fileperms
($this->object->getSource());
975 //testing for permissions for no configuration file
976 $this->assertFalse(! ($perms === false) && ($perms & 2));
978 //load file permissions for the current permissions file
979 $perms = @fileperms
($this->permTestObj
->getSource());
981 if (! ($perms === false) && ($perms & 2)) {
982 $this->assertTrue((bool) $this->permTestObj
->get('PMA_IS_WINDOWS'));
984 $this->assertFalse((bool) $this->permTestObj
->get('PMA_IS_WINDOWS'));
989 * Test for setting cookies
991 public function testSetCookie(): void
993 $this->object->set('is_https', false);
995 $this->object->setCookie(
1003 $this->object->setCookie(
1004 'TEST_CONFIG_COOKIE',
1012 $this->object->setCookie(
1013 'TEST_CONFIG_COOKIE',
1019 $_COOKIE['TEST_MANUAL_COOKIE'] = 'some_test_val';
1021 $this->object->setCookie(
1022 'TEST_MANUAL_COOKIE',
1030 * Test for getTempDir
1032 * @group file-system
1034 public function testGetTempDir(): void
1036 $this->object->set('TempDir', sys_get_temp_dir() . DIRECTORY_SEPARATOR
);
1037 // Check no double slash is here
1038 $this->assertEquals(
1039 sys_get_temp_dir() . DIRECTORY_SEPARATOR
. 'upload',
1040 $this->object->getTempDir('upload')
1045 * Test for getUploadTempDir
1047 * @group file-system
1049 public function testGetUploadTempDir(): void
1051 $this->object->set('TempDir', realpath(sys_get_temp_dir()) . DIRECTORY_SEPARATOR
);
1053 $this->assertEquals(
1054 $this->object->getTempDir('upload'),
1055 $this->object->getUploadTempDir()
1060 * Test for checkServers
1062 * @param array $settings settings array
1063 * @param array $expected expected result
1065 * @dataProvider serverSettingsProvider
1067 public function testCheckServers(array $settings, array $expected): void
1069 $this->object->settings
['Servers'] = $settings;
1070 $this->object->checkServers();
1071 $expected = array_merge($this->object->defaultServer
, $expected);
1073 $this->assertEquals($expected, $this->object->settings
['Servers'][1]);
1077 * Data provider for checkServers test
1081 public function serverSettingsProvider(): array
1089 [1 => ['host' => '127.0.0.1']],
1090 ['host' => '127.0.0.1'],
1093 [1 => ['host' => '']],
1095 'verbose' => 'Server 1',
1103 * @group with-trigger-error
1105 public function testCheckServersWithInvalidServer(): void
1107 $this->expectError();
1108 $this->expectErrorMessage('Invalid server index: invalid');
1110 $this->object->settings
['Servers'] = ['invalid' => ['host' => '127.0.0.1'], 1 => ['host' => '127.0.0.1']];
1111 $this->object->checkServers();
1112 $expected = array_merge($this->object->defaultServer
, ['host' => '127.0.0.1']);
1114 $this->assertEquals($expected, $this->object->settings
['Servers'][1]);
1118 * Test for selectServer
1120 * @param array $settings settings array
1121 * @param string $request request
1122 * @param int $expected expected result
1124 * @dataProvider selectServerProvider
1125 * @depends testCheckServers
1127 public function testSelectServer(array $settings, string $request, int $expected): void
1129 $this->object->settings
['Servers'] = $settings;
1130 $this->object->checkServers();
1131 $_REQUEST['server'] = $request;
1132 $this->assertEquals($expected, $this->object->selectServer());
1136 * Data provider for selectServer test
1140 public function selectServerProvider(): array
1154 [2 => ['host' => '127.0.0.1']],
1161 'verbose' => 'Server 1',
1171 'verbose' => 'Server 1',
1175 '753f173bd4ac8a45eae0fe9a4fbe0fc0',
1178 'nonexisting_string' => [
1192 * Test for getConnectionParams
1194 * @param array $server_cfg Server configuration
1195 * @param int $mode Mode to test
1196 * @param array|null $server Server array to test
1197 * @param array $expected Expected result
1199 * @dataProvider connectionParams
1201 public function testGetConnectionParams(array $server_cfg, int $mode, ?
array $server, array $expected): void
1203 $GLOBALS['cfg']['Server'] = $server_cfg;
1204 $result = Config
::getConnectionParams($mode, $server);
1205 $this->assertEquals($expected, $result);
1209 * Data provider for getConnectionParams test
1213 public function connectionParams(): array
1217 'password' => 'pass',
1219 'controluser' => 'u2',
1220 'controlpass' => 'p2',
1221 'hide_connection_errors' => false,
1225 'password' => 'pass',
1228 'controluser' => 'u2',
1229 'controlpass' => 'p2',
1230 'hide_connection_errors' => false,
1232 $cfg_control_ssl = [
1234 'password' => 'pass',
1236 'control_ssl' => true,
1237 'controluser' => 'u2',
1238 'controlpass' => 'p2',
1239 'hide_connection_errors' => false,
1245 DatabaseInterface
::CONNECT_USER
,
1252 'password' => 'pass',
1253 'host' => 'localhost',
1257 'compress' => false,
1258 'controluser' => 'u2',
1259 'controlpass' => 'p2',
1260 'hide_connection_errors' => false,
1266 DatabaseInterface
::CONNECT_CONTROL
,
1272 'host' => 'localhost',
1276 'compress' => false,
1277 'hide_connection_errors' => false,
1283 DatabaseInterface
::CONNECT_USER
,
1290 'password' => 'pass',
1291 'host' => 'localhost',
1295 'compress' => false,
1296 'controluser' => 'u2',
1297 'controlpass' => 'p2',
1298 'hide_connection_errors' => false,
1304 DatabaseInterface
::CONNECT_CONTROL
,
1310 'host' => 'localhost',
1314 'compress' => false,
1315 'hide_connection_errors' => false,
1321 DatabaseInterface
::CONNECT_USER
,
1328 'password' => 'pass',
1329 'host' => 'localhost',
1333 'compress' => false,
1334 'controluser' => 'u2',
1335 'controlpass' => 'p2',
1336 'control_ssl' => true,
1337 'hide_connection_errors' => false,
1343 DatabaseInterface
::CONNECT_CONTROL
,
1349 'host' => 'localhost',
1353 'compress' => false,
1354 'hide_connection_errors' => false,