index.php 20 KB

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