index.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Main loader script
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. use PhpMyAdmin\Charsets;
  9. use PhpMyAdmin\Config;
  10. use PhpMyAdmin\Core;
  11. use PhpMyAdmin\Display\GitRevision;
  12. use PhpMyAdmin\LanguageManager;
  13. use PhpMyAdmin\Message;
  14. use PhpMyAdmin\RecentFavoriteTable;
  15. use PhpMyAdmin\Relation;
  16. use PhpMyAdmin\Response;
  17. use PhpMyAdmin\Sanitize;
  18. use PhpMyAdmin\Server\Select;
  19. use PhpMyAdmin\ThemeManager;
  20. use PhpMyAdmin\Url;
  21. use PhpMyAdmin\Util;
  22. /**
  23. * Gets some core libraries and displays a top message if required
  24. */
  25. require_once 'libraries/common.inc.php';
  26. /**
  27. * pass variables to child pages
  28. */
  29. $drops = array(
  30. 'lang',
  31. 'server',
  32. 'collation_connection',
  33. 'db',
  34. 'table'
  35. );
  36. foreach ($drops as $each_drop) {
  37. if (array_key_exists($each_drop, $_GET)) {
  38. unset($_GET[$each_drop]);
  39. }
  40. }
  41. unset($drops, $each_drop);
  42. /*
  43. * Black list of all scripts to which front-end must submit data.
  44. * Such scripts must not be loaded on home page.
  45. *
  46. */
  47. $target_blacklist = array (
  48. 'import.php', 'export.php'
  49. );
  50. // If we have a valid target, let's load that script instead
  51. if (! empty($_REQUEST['target'])
  52. && is_string($_REQUEST['target'])
  53. && ! preg_match('/^index/', $_REQUEST['target'])
  54. && ! in_array($_REQUEST['target'], $target_blacklist)
  55. && Core::checkPageValidity($_REQUEST['target'], [], true)
  56. ) {
  57. include $_REQUEST['target'];
  58. exit;
  59. }
  60. if (isset($_REQUEST['ajax_request']) && ! empty($_REQUEST['access_time'])) {
  61. exit;
  62. }
  63. // user selected font size
  64. if (isset($_POST['set_fontsize']) && preg_match('/^[0-9.]+(px|em|pt|\%)$/', $_POST['set_fontsize'])) {
  65. $GLOBALS['PMA_Config']->setUserValue(
  66. null,
  67. 'FontSize',
  68. $_POST['set_fontsize'],
  69. '82%'
  70. );
  71. header('Location: index.php' . Url::getCommonRaw());
  72. exit();
  73. }
  74. // if user selected a theme
  75. if (isset($_POST['set_theme'])) {
  76. $tmanager = ThemeManager::getInstance();
  77. $tmanager->setActiveTheme($_POST['set_theme']);
  78. $tmanager->setThemeCookie();
  79. header('Location: index.php' . Url::getCommonRaw());
  80. exit();
  81. }
  82. // Change collation connection
  83. if (isset($_POST['collation_connection'])) {
  84. $GLOBALS['PMA_Config']->setUserValue(
  85. null,
  86. 'DefaultConnectionCollation',
  87. $_POST['collation_connection'],
  88. 'utf8mb4_unicode_ci'
  89. );
  90. header('Location: index.php' . Url::getCommonRaw());
  91. exit();
  92. }
  93. // See FAQ 1.34
  94. if (! empty($_REQUEST['db'])) {
  95. $page = null;
  96. if (! empty($_REQUEST['table'])) {
  97. $page = Util::getScriptNameForOption(
  98. $GLOBALS['cfg']['DefaultTabTable'], 'table'
  99. );
  100. } else {
  101. $page = Util::getScriptNameForOption(
  102. $GLOBALS['cfg']['DefaultTabDatabase'], 'database'
  103. );
  104. }
  105. include $page;
  106. exit;
  107. }
  108. $response = Response::getInstance();
  109. /**
  110. * Check if it is an ajax request to reload the recent tables list.
  111. */
  112. if ($response->isAjax() && ! empty($_REQUEST['recent_table'])) {
  113. $response->addJSON(
  114. 'list',
  115. RecentFavoriteTable::getInstance('recent')->getHtmlList()
  116. );
  117. exit;
  118. }
  119. if ($GLOBALS['PMA_Config']->isGitRevision()) {
  120. if (isset($_REQUEST['git_revision']) && $response->isAjax()) {
  121. GitRevision::display();
  122. exit;
  123. }
  124. echo '<div id="is_git_revision"></div>';
  125. }
  126. // Handles some variables that may have been sent by the calling script
  127. $GLOBALS['db'] = '';
  128. $GLOBALS['table'] = '';
  129. $show_query = '1';
  130. // Any message to display?
  131. if (! empty($message)) {
  132. echo Util::getMessage($message);
  133. unset($message);
  134. }
  135. if (isset($_SESSION['partial_logout'])) {
  136. Message::success(
  137. __('You were logged out from one server, to logout completely from phpMyAdmin, you need to logout from all servers.')
  138. )->display();
  139. unset($_SESSION['partial_logout']);
  140. }
  141. $common_url_query = Url::getCommon();
  142. $mysql_cur_user_and_host = '';
  143. // when $server > 0, a server has been chosen so we can display
  144. // all MySQL-related information
  145. if ($server > 0) {
  146. include 'libraries/server_common.inc.php';
  147. // Use the verbose name of the server instead of the hostname
  148. // if a value is set
  149. $server_info = '';
  150. if (! empty($cfg['Server']['verbose'])) {
  151. $server_info .= htmlspecialchars($cfg['Server']['verbose']);
  152. if ($GLOBALS['cfg']['ShowServerInfo']) {
  153. $server_info .= ' (';
  154. }
  155. }
  156. if ($GLOBALS['cfg']['ShowServerInfo'] || empty($cfg['Server']['verbose'])) {
  157. $server_info .= $GLOBALS['dbi']->getHostInfo();
  158. }
  159. if (! empty($cfg['Server']['verbose']) && $GLOBALS['cfg']['ShowServerInfo']) {
  160. $server_info .= ')';
  161. }
  162. $mysql_cur_user_and_host = $GLOBALS['dbi']->fetchValue('SELECT USER();');
  163. // should we add the port info here?
  164. $short_server_info = (!empty($GLOBALS['cfg']['Server']['verbose'])
  165. ? $GLOBALS['cfg']['Server']['verbose']
  166. : $GLOBALS['cfg']['Server']['host']);
  167. }
  168. echo '<div id="maincontainer">' , "\n";
  169. // Anchor for favorite tables synchronization.
  170. echo RecentFavoriteTable::getInstance('favorite')->getHtmlSyncFavoriteTables();
  171. echo '<div id="main_pane_left">';
  172. if ($server > 0 || count($cfg['Servers']) > 1
  173. ) {
  174. if ($cfg['DBG']['demo']) {
  175. echo '<div class="group">';
  176. echo '<h2>' , __('phpMyAdmin Demo Server') , '</h2>';
  177. echo '<p class="cfg_dbg_demo">';
  178. printf(
  179. __(
  180. 'You are using the demo server. You can do anything here, but '
  181. . 'please do not change root, debian-sys-maint and pma users. '
  182. . 'More information is available at %s.'
  183. ),
  184. '<a href="url.php?url=https://demo.phpmyadmin.net/" target="_blank" rel="noopener noreferrer">demo.phpmyadmin.net</a>'
  185. );
  186. echo '</p>';
  187. echo '</div>';
  188. }
  189. echo '<div class="group">';
  190. echo '<h2>' , __('General settings') , '</h2>';
  191. echo '<ul>';
  192. /**
  193. * Displays the MySQL servers choice form
  194. */
  195. if ($cfg['ServerDefault'] == 0
  196. || (! $cfg['NavigationDisplayServers']
  197. && (count($cfg['Servers']) > 1
  198. || ($server == 0 && count($cfg['Servers']) == 1)))
  199. ) {
  200. echo '<li id="li_select_server" class="no_bullets" >';
  201. echo Util::getImage('s_host') , " "
  202. , Select::render(true, true);
  203. echo '</li>';
  204. }
  205. /**
  206. * Displays the mysql server related links
  207. */
  208. if ($server > 0) {
  209. include_once 'libraries/check_user_privileges.inc.php';
  210. // Logout for advanced authentication
  211. if ($cfg['Server']['auth_type'] != 'config') {
  212. if ($cfg['ShowChgPassword']) {
  213. $conditional_class = 'ajax';
  214. Core::printListItem(
  215. Util::getImage('s_passwd') . "&nbsp;" . __(
  216. 'Change password'
  217. ),
  218. 'li_change_password',
  219. 'user_password.php' . $common_url_query,
  220. null,
  221. null,
  222. 'change_password_anchor',
  223. "no_bullets",
  224. $conditional_class
  225. );
  226. }
  227. } // end if
  228. echo ' <li id="li_select_mysql_collation" class="no_bullets" >';
  229. echo ' <form class="disableAjax" method="post" action="index.php">' , "\n"
  230. . Url::getHiddenInputs(null, null, 4, 'collation_connection')
  231. . ' <label for="select_collation_connection">' . "\n"
  232. . ' ' . Util::getImage('s_asci')
  233. . "&nbsp;" . __('Server connection collation') . "\n"
  234. // put the doc link in the form so that it appears on the same line
  235. . Util::showMySQLDocu('Charset-connection')
  236. . ': ' . "\n"
  237. . ' </label>' . "\n"
  238. . Charsets::getCollationDropdownBox(
  239. $GLOBALS['dbi'],
  240. $GLOBALS['cfg']['Server']['DisableIS'],
  241. 'collation_connection',
  242. 'select_collation_connection',
  243. $collation_connection,
  244. true,
  245. true
  246. )
  247. . ' </form>' . "\n"
  248. . ' </li>' . "\n";
  249. } // end of if ($server > 0)
  250. echo '</ul>';
  251. echo '</div>';
  252. }
  253. echo '<div class="group">';
  254. echo '<h2>' , __('Appearance settings') , '</h2>';
  255. echo ' <ul>';
  256. // Displays language selection combo
  257. $language_manager = LanguageManager::getInstance();
  258. if (empty($cfg['Lang']) && $language_manager->hasChoice()) {
  259. echo '<li id="li_select_lang" class="no_bullets">';
  260. echo Util::getImage('s_lang') , " "
  261. , $language_manager->getSelectorDisplay();
  262. echo '</li>';
  263. }
  264. // ThemeManager if available
  265. if ($GLOBALS['cfg']['ThemeManager']) {
  266. echo '<li id="li_select_theme" class="no_bullets">';
  267. echo Util::getImage('s_theme') , " "
  268. , ThemeManager::getInstance()->getHtmlSelectBox();
  269. echo '</li>';
  270. }
  271. echo '<li id="li_select_fontsize">';
  272. echo Config::getFontsizeForm();
  273. echo '</li>';
  274. echo '</ul>';
  275. // User preferences
  276. if ($server > 0) {
  277. echo '<ul>';
  278. Core::printListItem(
  279. Util::getImage('b_tblops') . "&nbsp;" . __(
  280. 'More settings'
  281. ),
  282. 'li_user_preferences',
  283. 'prefs_manage.php' . $common_url_query,
  284. null,
  285. null,
  286. null,
  287. "no_bullets"
  288. );
  289. echo '</ul>';
  290. }
  291. echo '</div>';
  292. echo '</div>';
  293. echo '<div id="main_pane_right">';
  294. if ($server > 0 && $GLOBALS['cfg']['ShowServerInfo']) {
  295. echo '<div class="group">';
  296. echo '<h2>' , __('Database server') , '</h2>';
  297. echo '<ul>' , "\n";
  298. Core::printListItem(
  299. __('Server:') . ' ' . $server_info,
  300. 'li_server_info'
  301. );
  302. Core::printListItem(
  303. __('Server type:') . ' ' . Util::getServerType(),
  304. 'li_server_type'
  305. );
  306. Core::printListItem(
  307. __('Server connection:') . ' ' . Util::getServerSSL(),
  308. 'li_server_type'
  309. );
  310. Core::printListItem(
  311. __('Server version:')
  312. . ' '
  313. . $GLOBALS['dbi']->getVersionString() . ' - ' . $GLOBALS['dbi']->getVersionComment(),
  314. 'li_server_version'
  315. );
  316. Core::printListItem(
  317. __('Protocol version:') . ' ' . $GLOBALS['dbi']->getProtoInfo(),
  318. 'li_mysql_proto'
  319. );
  320. Core::printListItem(
  321. __('User:') . ' ' . htmlspecialchars($mysql_cur_user_and_host),
  322. 'li_user_info'
  323. );
  324. echo ' <li id="li_select_mysql_charset">';
  325. echo ' ' , __('Server charset:') , ' '
  326. . ' <span lang="en" dir="ltr">';
  327. $unicode = Charsets::$mysql_charset_map['utf-8'];
  328. $charsets = Charsets::getMySQLCharsetsDescriptions(
  329. $GLOBALS['dbi'],
  330. $GLOBALS['cfg']['Server']['DisableIS']
  331. );
  332. echo ' ' , $charsets[$unicode], ' (' . $unicode, ')';
  333. echo ' </span>'
  334. . ' </li>'
  335. . ' </ul>'
  336. . ' </div>';
  337. }
  338. if ($GLOBALS['cfg']['ShowServerInfo'] || $GLOBALS['cfg']['ShowPhpInfo']) {
  339. echo '<div class="group">';
  340. echo '<h2>' , __('Web server') , '</h2>';
  341. echo '<ul>';
  342. if ($GLOBALS['cfg']['ShowServerInfo']) {
  343. Core::printListItem($_SERVER['SERVER_SOFTWARE'], 'li_web_server_software');
  344. if ($server > 0) {
  345. $client_version_str = $GLOBALS['dbi']->getClientInfo();
  346. if (preg_match('#\d+\.\d+\.\d+#', $client_version_str)) {
  347. $client_version_str = 'libmysql - ' . $client_version_str;
  348. }
  349. Core::printListItem(
  350. __('Database client version:') . ' ' . $client_version_str,
  351. 'li_mysql_client_version'
  352. );
  353. $php_ext_string = __('PHP extension:') . ' ';
  354. $extensions = Util::listPHPExtensions();
  355. foreach ($extensions as $extension) {
  356. $php_ext_string .= ' ' . $extension
  357. . Util::showPHPDocu('book.' . $extension . '.php');
  358. }
  359. Core::printListItem(
  360. $php_ext_string,
  361. 'li_used_php_extension'
  362. );
  363. $php_version_string = __('PHP version:') . ' ' . phpversion();
  364. Core::printListItem(
  365. $php_version_string,
  366. 'li_used_php_version'
  367. );
  368. }
  369. }
  370. if ($cfg['ShowPhpInfo']) {
  371. Core::printListItem(
  372. __('Show PHP information'),
  373. 'li_phpinfo',
  374. 'phpinfo.php' . $common_url_query,
  375. null,
  376. '_blank'
  377. );
  378. }
  379. echo ' </ul>';
  380. echo ' </div>';
  381. }
  382. echo '<div class="group pmagroup">';
  383. echo '<h2>phpMyAdmin</h2>';
  384. echo '<ul>';
  385. $class = null;
  386. if ($GLOBALS['cfg']['VersionCheck']) {
  387. $class = 'jsversioncheck';
  388. }
  389. Core::printListItem(
  390. __('Version information:') . ' <span class="version">' . PMA_VERSION . '</span>',
  391. 'li_pma_version',
  392. null,
  393. null,
  394. null,
  395. null,
  396. $class
  397. );
  398. Core::printListItem(
  399. __('Documentation'),
  400. 'li_pma_docs',
  401. Util::getDocuLink('index'),
  402. null,
  403. '_blank'
  404. );
  405. // does not work if no target specified, don't know why
  406. Core::printListItem(
  407. __('Official Homepage'),
  408. 'li_pma_homepage',
  409. Core::linkURL('https://www.phpmyadmin.net/'),
  410. null,
  411. '_blank'
  412. );
  413. Core::printListItem(
  414. __('Contribute'),
  415. 'li_pma_contribute',
  416. Core::linkURL('https://www.phpmyadmin.net/contribute/'),
  417. null,
  418. '_blank'
  419. );
  420. Core::printListItem(
  421. __('Get support'),
  422. 'li_pma_support',
  423. Core::linkURL('https://www.phpmyadmin.net/support/'),
  424. null,
  425. '_blank'
  426. );
  427. Core::printListItem(
  428. __('List of changes'),
  429. 'li_pma_changes',
  430. 'changelog.php' . Url::getCommon(),
  431. null,
  432. '_blank'
  433. );
  434. Core::printListItem(
  435. __('License'),
  436. 'li_pma_license',
  437. 'license.php' . Url::getCommon(),
  438. null,
  439. '_blank'
  440. );
  441. echo ' </ul>';
  442. echo ' </div>';
  443. echo '</div>';
  444. echo '</div>';
  445. /**
  446. * mbstring is used for handling multibytes inside parser, so it is good
  447. * to tell user something might be broken without it, see bug #1063149.
  448. */
  449. if (! extension_loaded('mbstring')) {
  450. trigger_error(
  451. __(
  452. 'The mbstring PHP extension was not found and you seem to be using'
  453. . ' a multibyte charset. Without the mbstring extension phpMyAdmin'
  454. . ' is unable to split strings correctly and it may result in'
  455. . ' unexpected results.'
  456. ),
  457. E_USER_WARNING
  458. );
  459. }
  460. /**
  461. * Missing functionality
  462. */
  463. if (! extension_loaded('curl') && ! ini_get('allow_url_fopen')) {
  464. trigger_error(
  465. __(
  466. 'The curl extension was not found and allow_url_fopen is '
  467. . 'disabled. Due to this some features such as error reporting '
  468. . 'or version check are disabled.'
  469. )
  470. );
  471. }
  472. if ($cfg['LoginCookieValidityDisableWarning'] == false) {
  473. /**
  474. * Check whether session.gc_maxlifetime limits session validity.
  475. */
  476. $gc_time = (int)ini_get('session.gc_maxlifetime');
  477. if ($gc_time < $GLOBALS['cfg']['LoginCookieValidity'] ) {
  478. trigger_error(
  479. __(
  480. 'Your PHP parameter [a@https://secure.php.net/manual/en/session.' .
  481. 'configuration.php#ini.session.gc-maxlifetime@_blank]session.' .
  482. 'gc_maxlifetime[/a] is lower than cookie validity configured ' .
  483. 'in phpMyAdmin, because of this, your login might expire sooner ' .
  484. 'than configured in phpMyAdmin.'
  485. ),
  486. E_USER_WARNING
  487. );
  488. }
  489. }
  490. /**
  491. * Check whether LoginCookieValidity is limited by LoginCookieStore.
  492. */
  493. if ($GLOBALS['cfg']['LoginCookieStore'] != 0
  494. && $GLOBALS['cfg']['LoginCookieStore'] < $GLOBALS['cfg']['LoginCookieValidity']
  495. ) {
  496. trigger_error(
  497. __(
  498. 'Login cookie store is lower than cookie validity configured in ' .
  499. 'phpMyAdmin, because of this, your login will expire sooner than ' .
  500. 'configured in phpMyAdmin.'
  501. ),
  502. E_USER_WARNING
  503. );
  504. }
  505. /**
  506. * Check if user does not have defined blowfish secret and it is being used.
  507. */
  508. if (! empty($_SESSION['encryption_key'])) {
  509. if (empty($GLOBALS['cfg']['blowfish_secret'])) {
  510. trigger_error(
  511. __(
  512. 'The configuration file now needs a secret passphrase (blowfish_secret).'
  513. ),
  514. E_USER_WARNING
  515. );
  516. } elseif (strlen($GLOBALS['cfg']['blowfish_secret']) < 32) {
  517. trigger_error(
  518. __(
  519. 'The secret passphrase in configuration (blowfish_secret) is too short.'
  520. ),
  521. E_USER_WARNING
  522. );
  523. }
  524. }
  525. /**
  526. * Check for existence of config directory which should not exist in
  527. * production environment.
  528. */
  529. if (@file_exists('config')) {
  530. trigger_error(
  531. __(
  532. 'Directory [code]config[/code], which is used by the setup script, ' .
  533. 'still exists in your phpMyAdmin directory. It is strongly ' .
  534. 'recommended to remove it once phpMyAdmin has been configured. ' .
  535. 'Otherwise the security of your server may be compromised by ' .
  536. 'unauthorized people downloading your configuration.'
  537. ),
  538. E_USER_WARNING
  539. );
  540. }
  541. $relation = new Relation();
  542. if ($server > 0) {
  543. $cfgRelation = $relation->getRelationsParam();
  544. if (! $cfgRelation['allworks']
  545. && $cfg['PmaNoRelation_DisableWarning'] == false
  546. ) {
  547. $msg_text = __(
  548. 'The phpMyAdmin configuration storage is not completely '
  549. . 'configured, some extended features have been deactivated. '
  550. . '%sFind out why%s. '
  551. );
  552. if ($cfg['ZeroConf'] == true) {
  553. $msg_text .= '<br>' .
  554. __(
  555. 'Or alternately go to \'Operations\' tab of any database '
  556. . 'to set it up there.'
  557. );
  558. }
  559. $msg = Message::notice($msg_text);
  560. $msg->addParamHtml('<a href="./chk_rel.php' . $common_url_query . '">');
  561. $msg->addParamHtml('</a>');
  562. /* Show error if user has configured something, notice elsewhere */
  563. if (!empty($cfg['Servers'][$server]['pmadb'])) {
  564. $msg->isError(true);
  565. }
  566. $msg->display();
  567. } // end if
  568. }
  569. /**
  570. * Warning about Suhosin only if its simulation mode is not enabled
  571. */
  572. if ($cfg['SuhosinDisableWarning'] == false
  573. && ini_get('suhosin.request.max_value_length')
  574. && ini_get('suhosin.simulation') == '0'
  575. ) {
  576. trigger_error(
  577. sprintf(
  578. __(
  579. 'Server running with Suhosin. Please refer to %sdocumentation%s ' .
  580. 'for possible issues.'
  581. ),
  582. '[doc@faq1-38]',
  583. '[/doc]'
  584. ),
  585. E_USER_WARNING
  586. );
  587. }
  588. /* Missing template cache */
  589. if (is_null($GLOBALS['PMA_Config']->getTempDir('twig'))) {
  590. trigger_error(
  591. sprintf(
  592. __('The $cfg[\'TempDir\'] (%s) is not accessible. phpMyAdmin is not able to cache templates and will be slow because of this.'),
  593. $GLOBALS['PMA_Config']->get('TempDir')
  594. ),
  595. E_USER_WARNING
  596. );
  597. }
  598. /**
  599. * Warning about incomplete translations.
  600. *
  601. * The data file is created while creating release by ./scripts/remove-incomplete-mo
  602. */
  603. if (@file_exists('libraries/language_stats.inc.php')) {
  604. include 'libraries/language_stats.inc.php';
  605. /*
  606. * This message is intentionally not translated, because we're
  607. * handling incomplete translations here and focus on english
  608. * speaking users.
  609. */
  610. if (isset($GLOBALS['language_stats'][$lang])
  611. && $GLOBALS['language_stats'][$lang] < $cfg['TranslationWarningThreshold']
  612. ) {
  613. trigger_error(
  614. 'You are using an incomplete translation, please help to make it '
  615. . 'better by [a@https://www.phpmyadmin.net/translate/'
  616. . '@_blank]contributing[/a].',
  617. E_USER_NOTICE
  618. );
  619. }
  620. }