diff --git a/ChangeLog b/ChangeLog index a79e19f98a..69066c417f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,6 +25,7 @@ phpMyAdmin - ChangeLog - [core] Dropped support for PHP 5.2. + rfe #487 and rfe #1405 Find and Replacing column wise + rfe #1373 Use same create view dialog for editing a view ++ rfe #316 Configurable menus; allow user groups with customized menus per group 4.0.5.0 (not yet released) - bug #3977 Not detected configuration storage @@ -35,6 +36,7 @@ phpMyAdmin - ChangeLog - bug #3985 Call to undefined function mb_detect_encoding - bug #4007 Analyze option not shown for InnoDB tables - bug #4015 Forcing a storage engine for configuration storage +- bug Incorrect Drizzle 7 detection 4.0.4.1 (2013-06-30) - [security] Global variables scope injection vulnerability (see PMASA-2013-7) diff --git a/config.sample.inc.php b/config.sample.inc.php index 37a2f099b5..7c40fb40e3 100644 --- a/config.sample.inc.php +++ b/config.sample.inc.php @@ -59,6 +59,8 @@ $cfg['Servers'][$i]['AllowNoPassword'] = false; // $cfg['Servers'][$i]['designer_coords'] = 'pma__designer_coords'; // $cfg['Servers'][$i]['userconfig'] = 'pma__userconfig'; // $cfg['Servers'][$i]['recent'] = 'pma__recent'; +// $cfg['Servers'][$i]['users'] = 'pma__users'; +// $cfg['Servers'][$i]['usergroups'] = 'pma__usergroups'; /* Contrib / Swekey authentication */ // $cfg['Servers'][$i]['auth_swekey_config'] = '/etc/swekey-pma.conf'; diff --git a/doc/config.rst b/doc/config.rst index 5b9657c8c7..e97b6596ba 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -110,7 +110,7 @@ Basic settings column names match with words which are MySQL reserved. If you want to turn off this warning, you can set it to ``true`` and - warning will not longer be displayed + warning will no longer be displayed. .. config:option:: $cfg['TranslationWarningThreshold'] @@ -649,6 +649,29 @@ Server connection settings * put the table name in :config:option:`$cfg['Servers'][$i]['table\_uiprefs']` (e.g. ``pma__table_uiprefs``) +.. _configurablemenus: +.. config:option:: $cfg['Servers'][$i]['users'] + + :type: string + :default: ``''`` + +.. config:option:: $cfg['Servers'][$i]['usergroups'] + + :type: string + :default: ``''`` + + Since release 4.1.0 you can create different user groups with menu items + attached to them. Users can be assigned to these groups and the logged in + user would only see menu items configured to the usergroup he is assigned to. + To do this it needs two tables "usergroups" (storing allowed menu items for each + user group) and "users" (storing users and their assignments to user groups). + + To allow the usage of this functionality: + + * set up :config:option:`$cfg['Servers'][$i]['pmadb']` and the phpMyAdmin configuration storage + * put the correct table names in + :config:option:`$cfg['Servers'][$i]['users']` (e.g. ``pma__users``) and + :config:option:`$cfg['Servers'][$i]['usergroups']` (e.g. ``pma__usergroups``) .. _tracking: .. config:option:: $cfg['Servers'][$i]['tracking'] diff --git a/examples/config.manyhosts.inc.php b/examples/config.manyhosts.inc.php index 1395ecc3d0..b9165355ee 100644 --- a/examples/config.manyhosts.inc.php +++ b/examples/config.manyhosts.inc.php @@ -45,4 +45,6 @@ foreach ($hosts as $host) { $cfg['Servers'][$i]['designer_coords'] = 'pma__designer_coords'; $cfg['Servers'][$i]['userconfig'] = 'pma__userconfig'; $cfg['Servers'][$i]['recent'] = 'pma__recent'; + $cfg['Servers'][$i]['users'] = 'pma__users'; + $cfg['Servers'][$i]['usergroups'] = 'pma__usergroups'; } diff --git a/examples/create_tables.sql b/examples/create_tables.sql index 723334c776..ae2c81408c 100644 --- a/examples/create_tables.sql +++ b/examples/create_tables.sql @@ -239,3 +239,66 @@ CREATE TABLE IF NOT EXISTS `pma__userconfig` ( ) COMMENT='User preferences storage for phpMyAdmin' DEFAULT CHARACTER SET utf8 COLLATE utf8_bin; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `pma__users` +-- + +CREATE TABLE IF NOT EXISTS `pma__users` ( + `username` varchar(64) NOT NULL, + `usergroup` varchar(64) NOT NULL, + PRIMARY KEY (`username`,`usergroup`) +) + COMMENT='Users and their assignments to user groups' + DEFAULT CHARACTER SET utf8 COLLATE utf8_bin; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `pma__usergroups` +-- + +CREATE TABLE IF NOT EXISTS `pma__usergroups` ( + `usergroup` varchar(64) NOT NULL, + `server_databases` enum('Y','N') NOT NULL DEFAULT 'N', + `server_sql` enum('Y','N') NOT NULL DEFAULT 'N', + `server_status` enum('Y','N') NOT NULL DEFAULT 'N', + `server_rights` enum('Y','N') NOT NULL DEFAULT 'N', + `server_export` enum('Y','N') NOT NULL DEFAULT 'N', + `server_import` enum('Y','N') NOT NULL DEFAULT 'N', + `server_settings` enum('Y','N') NOT NULL DEFAULT 'N', + `server_binlog` enum('Y','N') NOT NULL DEFAULT 'N', + `server_replication` enum('Y','N') NOT NULL DEFAULT 'N', + `server_vars` enum('Y','N') NOT NULL DEFAULT 'N', + `server_charset` enum('Y','N') NOT NULL DEFAULT 'N', + `server_plugins` enum('Y','N') NOT NULL DEFAULT 'N', + `server_engine` enum('Y','N') NOT NULL DEFAULT 'N', + `db_structure` enum('Y','N') NOT NULL DEFAULT 'N', + `db_sql` enum('Y','N') NOT NULL DEFAULT 'N', + `db_search` enum('Y','N') NOT NULL DEFAULT 'N', + `db_qbe` enum('Y','N') NOT NULL DEFAULT 'N', + `db_export` enum('Y','N') NOT NULL DEFAULT 'N', + `db_import` enum('Y','N') NOT NULL DEFAULT 'N', + `db_operation` enum('Y','N') NOT NULL DEFAULT 'N', + `db_privileges` enum('Y','N') NOT NULL DEFAULT 'N', + `db_routines` enum('Y','N') NOT NULL DEFAULT 'N', + `db_events` enum('Y','N') NOT NULL DEFAULT 'N', + `db_triggers` enum('Y','N') NOT NULL DEFAULT 'N', + `db_tracking` enum('Y','N') NOT NULL DEFAULT 'N', + `db_designer` enum('Y','N') NOT NULL DEFAULT 'N', + `table_browse` enum('Y','N') NOT NULL DEFAULT 'N', + `table_structure` enum('Y','N') NOT NULL DEFAULT 'N', + `table_sql` enum('Y','N') NOT NULL DEFAULT 'N', + `table_search` enum('Y','N') NOT NULL DEFAULT 'N', + `table_insert` enum('Y','N') NOT NULL DEFAULT 'N', + `table_export` enum('Y','N') NOT NULL DEFAULT 'N', + `table_import` enum('Y','N') NOT NULL DEFAULT 'N', + `table_operation` enum('Y','N') NOT NULL DEFAULT 'N', + `table_tracking` enum('Y','N') NOT NULL DEFAULT 'N', + `table_triggers` enum('Y','N') NOT NULL DEFAULT 'N', + PRIMARY KEY (`usergroup`) +) + COMMENT='User groups with configured menu items' + DEFAULT CHARACTER SET utf8 COLLATE utf8_bin; diff --git a/examples/create_tables_drizzle.sql b/examples/create_tables_drizzle.sql index 92de90afec..257018815a 100644 --- a/examples/create_tables_drizzle.sql +++ b/examples/create_tables_drizzle.sql @@ -225,3 +225,66 @@ CREATE TABLE IF NOT EXISTS `pma__userconfig` ( ) COMMENT='User preferences storage for phpMyAdmin' COLLATE utf8_bin; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `pma__users` +-- + +CREATE TABLE IF NOT EXISTS `pma__users` ( + `username` varchar(64) NOT NULL, + `usergroup` varchar(64) NOT NULL, + PRIMARY KEY (`username`,`usergroup`) +) + COMMENT='Users and their assignments to user groups' + COLLATE utf8_bin; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `pma__usergroups` +-- + +CREATE TABLE IF NOT EXISTS `pma__usergroups` ( + `usergroup` varchar(64) NOT NULL, + `server_databases` enum('Y','N') NOT NULL DEFAULT 'N', + `server_sql` enum('Y','N') NOT NULL DEFAULT 'N', + `server_status` enum('Y','N') NOT NULL DEFAULT 'N', + `server_rights` enum('Y','N') NOT NULL DEFAULT 'N', + `server_export` enum('Y','N') NOT NULL DEFAULT 'N', + `server_import` enum('Y','N') NOT NULL DEFAULT 'N', + `server_settings` enum('Y','N') NOT NULL DEFAULT 'N', + `server_binlog` enum('Y','N') NOT NULL DEFAULT 'N', + `server_replication` enum('Y','N') NOT NULL DEFAULT 'N', + `server_vars` enum('Y','N') NOT NULL DEFAULT 'N', + `server_charset` enum('Y','N') NOT NULL DEFAULT 'N', + `server_plugins` enum('Y','N') NOT NULL DEFAULT 'N', + `server_engine` enum('Y','N') NOT NULL DEFAULT 'N', + `db_structure` enum('Y','N') NOT NULL DEFAULT 'N', + `db_sql` enum('Y','N') NOT NULL DEFAULT 'N', + `db_search` enum('Y','N') NOT NULL DEFAULT 'N', + `db_qbe` enum('Y','N') NOT NULL DEFAULT 'N', + `db_export` enum('Y','N') NOT NULL DEFAULT 'N', + `db_import` enum('Y','N') NOT NULL DEFAULT 'N', + `db_operation` enum('Y','N') NOT NULL DEFAULT 'N', + `db_privileges` enum('Y','N') NOT NULL DEFAULT 'N', + `db_routines` enum('Y','N') NOT NULL DEFAULT 'N', + `db_events` enum('Y','N') NOT NULL DEFAULT 'N', + `db_triggers` enum('Y','N') NOT NULL DEFAULT 'N', + `db_tracking` enum('Y','N') NOT NULL DEFAULT 'N', + `db_designer` enum('Y','N') NOT NULL DEFAULT 'N', + `table_browse` enum('Y','N') NOT NULL DEFAULT 'N', + `table_structure` enum('Y','N') NOT NULL DEFAULT 'N', + `table_sql` enum('Y','N') NOT NULL DEFAULT 'N', + `table_search` enum('Y','N') NOT NULL DEFAULT 'N', + `table_insert` enum('Y','N') NOT NULL DEFAULT 'N', + `table_export` enum('Y','N') NOT NULL DEFAULT 'N', + `table_import` enum('Y','N') NOT NULL DEFAULT 'N', + `table_operation` enum('Y','N') NOT NULL DEFAULT 'N', + `table_tracking` enum('Y','N') NOT NULL DEFAULT 'N', + `table_triggers` enum('Y','N') NOT NULL DEFAULT 'N', + PRIMARY KEY (`usergroup`) +) + COMMENT='User groups with configured menu items' + COLLATE utf8_bin; diff --git a/js/server_privileges.js b/js/server_privileges.js index 7f31c93392..935c99f0c5 100644 --- a/js/server_privileges.js +++ b/js/server_privileges.js @@ -172,6 +172,7 @@ AJAX.registerTeardown('server_privileges.js', function () { $('form[name=usersForm]').unbind('submit'); $("#fieldset_delete_user_footer #buttonGo.ajax").die('click'); $("a.edit_user_anchor.ajax").die('click'); + $("a.edit_user_group_anchor.ajax").die('click'); $("#edit_user_dialog").find("form.ajax").die('submit'); $("button.mult_submit[value=export]").die('click'); $("a.export_user_anchor.ajax").die('click'); @@ -300,6 +301,75 @@ AJAX.registerOnload('server_privileges.js', function () { }); // end $.post() }); // end Revoke User + $("a.edit_user_group_anchor.ajax").live('click', function (event) { + event.preventDefault(); + $(this).parents('tr').addClass('current_row'); + var token = $(this).parents('form').find('input[name="token"]').val(); + var $msg = PMA_ajaxShowMessage(); + $.get( + $(this).attr('href'), + { + 'ajax_request': true, + 'edit_user_group_dialog': true, + 'token': token + }, + function (data) { + if (data.success === true) { + PMA_ajaxRemoveMessage($msg); + var buttonOptions = {}; + buttonOptions[PMA_messages.strGo] = function () { + var usrGroup = $('#changeUserGroupDialog') + .find('select[name="userGroup"]') + .val(); + var $message = PMA_ajaxShowMessage(); + $.get( + 'server_privileges.php', + $('#changeUserGroupDialog').find('form').serialize() + '&ajax_request=1', + function (data) { + PMA_ajaxRemoveMessage($message); + if (data.success === true) { + $("#usersForm") + .find('.current_row') + .removeClass('current_row') + .find('.usrGroup') + .text(usrGroup); + } else { + PMA_ajaxShowMessage(data.error, false); + $("#usersForm") + .find('.current_row') + .removeClass('current_row'); + } + } + ); + $(this).dialog("close"); + }; + buttonOptions[PMA_messages.strClose] = function () { + $(this).dialog("close"); + }; + var $dialog = $('
') + .attr('id', 'changeUserGroupDialog') + .append(data.message) + .dialog({ + width: 500, + minWidth: 300, + modal: true, + buttons: buttonOptions, + title: $('legend', $(data.message)).text(), + close: function () { + $(this).remove(); + } + }); + $dialog.find('legend').remove(); + } else { + PMA_ajaxShowMessage(data.error, false); + $("#usersForm") + .find('.current_row') + .removeClass('current_row'); + } + } + ); + }); + /** * AJAX handler for 'Edit User' * diff --git a/libraries/Menu.class.php b/libraries/Menu.class.php index 687c20332a..cb48a2a6d4 100644 --- a/libraries/Menu.class.php +++ b/libraries/Menu.class.php @@ -99,17 +99,65 @@ class PMA_Menu { $tabs = array(); $url_params = array('db' => $this->_db); + $level = ''; + if (strlen($this->_table)) { $tabs = $this->_getTableTabs(); $url_params['table'] = $this->_table; + $level = 'table'; } else if (strlen($this->_db)) { $tabs = $this->_getDbTabs(); + $level = 'db'; } else { $tabs = $this->_getServerTabs(); + $level = 'server'; + } + + $allowedTabs = $this->_getAllowedTabs($level); + foreach ($tabs as $key => $value) { + if (! array_key_exists($key, $allowedTabs)) { + unset($tabs[$key]); + } } return PMA_Util::getHtmlTabs($tabs, $url_params, 'topmenu', true); } + /** + * Returns a list of allowed tabs for the current user for the given level + * + * @param string $level 'server', 'db' or 'table' level + * + * @return array list of allowed tabs + */ + private function _getAllowedTabs($level) + { + $allowedTabs = PMA_Util::getMenuTabList($level); + $cfgRelation = PMA_getRelationsParam(); + if ($cfgRelation['menuswork']) { + $groupTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb']) + . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['usergroups']); + $userTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb']) + . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['users']); + + $sql_query = "SELECT * FROM " . $groupTable + . " WHERE `usergroup` = (SELECT usergroup FROM " + . $userTable . " WHERE `username` = '" + . PMA_Util::sqlAddSlashes($GLOBALS['cfg']['Server']['user']) . "')"; + + $result = PMA_queryAsControlUser($sql_query, false); + if ($result) { + $row = $GLOBALS['dbi']->fetchAssoc($result); + foreach ($allowedTabs as $key => $tab) { + $colName = $level . '_' . $key; + if (isset($row[$colName]) && $row[$colName] == 'N') { + unset($allowedTabs[$key]); + } + } + } + } + return $allowedTabs; + } + /** * Returns the breadcrumbs as HTML * @@ -130,21 +178,13 @@ class PMA_Menu $item = ''; - if (in_array( - $GLOBALS['cfg']['TabsMode'], - array('text', 'both') - ) - ) { + if (in_array($GLOBALS['cfg']['TabsMode'], array('text', 'both'))) { $item .= '%4$s: '; } $item .= '%3$s'; $retval .= "
"; $retval .= "
"; - if (in_array( - $GLOBALS['cfg']['TabsMode'], - array('icons', 'both') - ) - ) { + if (in_array($GLOBALS['cfg']['TabsMode'], array('icons', 'both'))) { $retval .= PMA_Util::getImage( 's_host.png', '', @@ -161,11 +201,7 @@ class PMA_Menu if (strlen($this->_db)) { $retval .= $separator; - if (in_array( - $GLOBALS['cfg']['TabsMode'], - array('icons', 'both') - ) - ) { + if (in_array($GLOBALS['cfg']['TabsMode'], array('icons', 'both'))) { $retval .= PMA_Util::getImage( 's_db.png', '', @@ -187,11 +223,7 @@ class PMA_Menu include './libraries/tbl_info.inc.php'; $retval .= $separator; - if (in_array( - $GLOBALS['cfg']['TabsMode'], - array('icons', 'both') - ) - ) { + if (in_array($GLOBALS['cfg']['TabsMode'], array('icons', 'both'))) { $icon = $tbl_is_view ? 'b_views.png' : 's_tbl.png'; $retval .= PMA_Util::getImage( $icon, @@ -444,11 +476,9 @@ class PMA_Menu { $is_superuser = isset($GLOBALS['dbi']) && $GLOBALS['dbi']->isSuperuser(); $binary_logs = null; - if (isset($GLOBALS['dbi']) - && (! defined('PMA_DRIZZLE') - || (defined('PMA_DRIZZLE') && ! PMA_DRIZZLE) - ) - ) { + $notDrizzle = ! defined('PMA_DRIZZLE') + || (defined('PMA_DRIZZLE') && ! PMA_DRIZZLE); + if (isset($GLOBALS['dbi']) && $notDrizzle) { $binary_logs = $GLOBALS['dbi']->fetchResult( 'SHOW MASTER LOGS', 'Log_name', @@ -486,6 +516,10 @@ class PMA_Menu $tabs['rights']['icon'] = 's_rights.png'; $tabs['rights']['link'] = 'server_privileges.php'; $tabs['rights']['text'] = __('Users'); + $tabs['rights']['active'] = in_array( + basename($GLOBALS['PMA_PHP_SELF']), + array('server_privileges.php', 'server_user_groups.php') + ); } $tabs['export']['icon'] = 'b_export.png'; diff --git a/libraries/Util.class.php b/libraries/Util.class.php index f4ce701e97..5b229ab4aa 100644 --- a/libraries/Util.class.php +++ b/libraries/Util.class.php @@ -4153,6 +4153,69 @@ class PMA_Util return $regex; } + /** + * Return the list of tabs for the menu with corresponding names + * + * @param string $level 'server', 'db' or 'table' level + * + * @return array list of tabs for the menu + */ + public static function getMenuTabList($level = null) + { + $tabList = array( + 'server' => array( + 'databases' => __('Databases'), + 'sql' => __('SQL'), + 'status' => __('Status'), + 'rights' => __('Users'), + 'export' => __('Export'), + 'import' => __('Import'), + 'settings' => __('Settings'), + 'binlog' => __('Binary log'), + 'replication' => __('Replication'), + 'vars' => __('Variables'), + 'charset' => __('Charsets'), + 'plugins' => __('Plugins'), + 'engine' => __('Engines') + ), + 'db' => array( + 'structure' => __('Structure'), + 'sql' => __('SQL'), + 'search' => __('Search'), + 'qbe' => __('Query'), + 'export' => __('Export'), + 'import' => __('Import'), + 'operation' => __('Operations'), + 'privileges' => __('Privileges'), + 'routines' => __('Routines'), + 'events' => __('Events'), + 'triggers' => __('Triggers'), + 'tracking' => __('Tracking'), + 'designer' => __('Designer') + ), + 'table' => array( + 'browse' => __('Browse'), + 'structure' => __('Structure'), + 'sql' => __('SQL'), + 'search' => __('Search'), + 'insert' => __('Insert'), + 'export' => __('Export'), + 'import' => __('Import'), + 'operation' => __('Operations'), + 'tracking' => __('Tracking'), + 'triggers' => __('Triggers'), + ) + ); + + if ($level == null) { + return $tabList; + } else if (array_key_exists($level, $tabList)) { + return $tabList[$level]; + } else { + return null; + } + } + /** * Returns information with latest version from phpmyadmin.net * @@ -4191,9 +4254,8 @@ class PMA_Util $cfg['VersionCheckProxyUser'] . ':' . $cfg['VersionCheckProxyPass'] ); - $context['http']['header'] = - 'Proxy-Authorization: Basic ' - . $auth; + $context['http']['header'] + = 'Proxy-Authorization: Basic ' . $auth; } } $response = file_get_contents( diff --git a/libraries/config.default.php b/libraries/config.default.php index 39ba514a95..e8d2130565 100644 --- a/libraries/config.default.php +++ b/libraries/config.default.php @@ -402,6 +402,24 @@ $cfg['Servers'][$i]['tracking'] = ''; */ $cfg['Servers'][$i]['userconfig'] = ''; +/** + * table to store users and their assignment to user groups + * - leave blank to disable configurable menus feature + * SUGGESTED: 'pma__users' + * + * @global string $cfg['Servers'][$i]['users'] + */ +$cfg['Servers'][$i]['users'] = ''; + +/** + * table to store allowed menu items for each user group + * - leave blank to disable configurable menus feature + * SUGGESTED: 'pma__usergroups' + * + * @global string $cfg['Servers'][$i]['usergroups'] + */ +$cfg['Servers'][$i]['usergroups'] = ''; + /** * Maximum number of records saved in $cfg['Servers'][$i]['table_uiprefs'] table. * diff --git a/libraries/config/messages.inc.php b/libraries/config/messages.inc.php index e419953d86..d0db72b4b7 100644 --- a/libraries/config/messages.inc.php +++ b/libraries/config/messages.inc.php @@ -450,6 +450,10 @@ $strConfigServers_tracking_version_auto_create_desc = __('Whether the tracking m $strConfigServers_tracking_version_auto_create_name = __('Automatically create versions'); $strConfigServers_userconfig_desc = __('Leave blank for no user preferences storage in database, suggested: [kbd]pma__userconfig[/kbd]'); $strConfigServers_userconfig_name = __('User preferences storage table'); +$strConfigServers_users_desc = __('Leave blank to disable configurable menus feature, suggested: [kbd]pma__users[/kbd]'); +$strConfigServers_users_name = __('Users table'); +$strConfigServers_usergroups_desc = __('Leave blank to disable configurable menus feature, suggested: [kbd]pma__usergroups[/kbd]'); +$strConfigServers_usergroups_name = __('User groups table'); $strConfigServers_user_desc = __('Leave empty if not using config auth'); $strConfigServers_user_name = __('User for config auth'); $strConfigServers_verbose_desc = __('A user-friendly description of this server. Leave blank to display the hostname instead.'); diff --git a/libraries/config/setup.forms.php b/libraries/config/setup.forms.php index d2f5e4d6c6..da81bd0a55 100644 --- a/libraries/config/setup.forms.php +++ b/libraries/config/setup.forms.php @@ -70,6 +70,8 @@ $forms['Servers']['Server_pmadb'] = array('Servers' => array(1 => array( 'bookmarktable' => 'pma__bookmark', 'relation' => 'pma__relation', 'userconfig' => 'pma__userconfig', + 'users' => 'pma__users', + 'usergroups' => 'pma__usergroups', 'table_info' => 'pma__table_info', 'column_info' => 'pma__column_info', 'history' => 'pma__history', diff --git a/libraries/plugins/auth/AuthenticationConfig.class.php b/libraries/plugins/auth/AuthenticationConfig.class.php index b33ebe570a..5e33a07f1a 100644 --- a/libraries/plugins/auth/AuthenticationConfig.class.php +++ b/libraries/plugins/auth/AuthenticationConfig.class.php @@ -153,7 +153,9 @@ class AuthenticationConfig extends AuthenticationPlugin echo '' . "\n"; } echo '' . "\n"; - exit; + if (!defined('TESTSUITE')) { + exit; + } return true; } diff --git a/libraries/plugins/auth/AuthenticationCookie.class.php b/libraries/plugins/auth/AuthenticationCookie.class.php index b1a0c08bb8..2b68f358ab 100644 --- a/libraries/plugins/auth/AuthenticationCookie.class.php +++ b/libraries/plugins/auth/AuthenticationCookie.class.php @@ -102,7 +102,11 @@ class AuthenticationCookie extends AuthenticationPlugin ) ); } - exit; + if (defined('TESTSUITE')) { + return true; + } else { + exit; + } } /* Perform logout to custom URL */ @@ -110,7 +114,11 @@ class AuthenticationCookie extends AuthenticationPlugin && ! empty($GLOBALS['cfg']['Server']['LogoutURL']) ) { PMA_sendHeaderLocation($GLOBALS['cfg']['Server']['LogoutURL']); - exit; + if (defined('TESTSUITE')) { + return true; + } else { + exit; + } } // No recall if blowfish secret is not configured as it would produce @@ -301,7 +309,11 @@ class AuthenticationCookie extends AuthenticationPlugin if (file_exists(CUSTOM_FOOTER_FILE)) { include CUSTOM_FOOTER_FILE; } - exit; + if (! defined('TESTSUITE')) { + exit; + } else { + return true; + } } /** @@ -408,7 +420,9 @@ class AuthenticationCookie extends AuthenticationPlugin // according to the PHP manual we should do this before the destroy: //$_SESSION = array(); - session_destroy(); + if (! defined('TESTSUITE')) { + session_destroy(); + } // -> delete password cookie(s) if ($GLOBALS['cfg']['LoginCookieDeleteAll']) { foreach ($GLOBALS['cfg']['Servers'] as $key => $val) { @@ -478,7 +492,11 @@ class AuthenticationCookie extends AuthenticationPlugin PMA_Util::cacheUnset('dbs_where_create_table_allowed', true); $GLOBALS['no_activity'] = true; $this->authFails(); - exit; + if (! defined('TESTSUITE')) { + exit; + } else { + return false; + } } // password @@ -625,7 +643,11 @@ class AuthenticationCookie extends AuthenticationPlugin $redirect_url . PMA_generate_common_url($url_params, '&'), true ); - exit; + if (! defined('TESTSUITE')) { + exit; + } else { + return false; + } } // end if return true; diff --git a/libraries/relation.lib.php b/libraries/relation.lib.php index b684161a42..c3b83c3d40 100644 --- a/libraries/relation.lib.php +++ b/libraries/relation.lib.php @@ -248,6 +248,23 @@ function PMA_getRelationsParamDiagnostic($cfgRelation) 'userconfigwork', $messages ); + $retval .= PMA_getDiagMessageForParameter( + 'users', + isset($cfgRelation['users']), + $messages, + 'users' + ); + $retval .= PMA_getDiagMessageForParameter( + 'usergroups', + isset($cfgRelation['usergroups']), + $messages, + 'usergroups' + ); + $retval .= PMA_getDiagMessageForFeature( + __('Configurable menus'), + 'menuswork', + $messages + ); $retval .= '' . "\n"; $retval .= '

' . __('Quick steps to setup advanced features:') . '

'; @@ -347,22 +364,23 @@ function PMA_getDiagMessageForParameter($parameter, */ function PMA_checkRelationsParam() { - $cfgRelation = array(); - $cfgRelation['relwork'] = false; - $cfgRelation['displaywork'] = false; - $cfgRelation['bookmarkwork']= false; - $cfgRelation['pdfwork'] = false; - $cfgRelation['commwork'] = false; - $cfgRelation['mimework'] = false; - $cfgRelation['historywork'] = false; - $cfgRelation['recentwork'] = false; - $cfgRelation['uiprefswork'] = false; - $cfgRelation['trackingwork'] = false; - $cfgRelation['designerwork'] = false; + $cfgRelation = array(); + $cfgRelation['relwork'] = false; + $cfgRelation['displaywork'] = false; + $cfgRelation['bookmarkwork'] = false; + $cfgRelation['pdfwork'] = false; + $cfgRelation['commwork'] = false; + $cfgRelation['mimework'] = false; + $cfgRelation['historywork'] = false; + $cfgRelation['recentwork'] = false; + $cfgRelation['uiprefswork'] = false; + $cfgRelation['trackingwork'] = false; + $cfgRelation['designerwork'] = false; $cfgRelation['userconfigwork'] = false; - $cfgRelation['allworks'] = false; - $cfgRelation['user'] = null; - $cfgRelation['db'] = null; + $cfgRelation['menuswork'] = false; + $cfgRelation['allworks'] = false; + $cfgRelation['user'] = null; + $cfgRelation['db'] = null; if ($GLOBALS['server'] == 0 || empty($GLOBALS['cfg']['Server']['pmadb']) @@ -408,21 +426,25 @@ function PMA_checkRelationsParam() } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['table_coords']) { $cfgRelation['table_coords'] = $curr_table[0]; } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['designer_coords']) { - $cfgRelation['designer_coords'] = $curr_table[0]; + $cfgRelation['designer_coords'] = $curr_table[0]; } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['column_info']) { - $cfgRelation['column_info'] = $curr_table[0]; + $cfgRelation['column_info'] = $curr_table[0]; } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['pdf_pages']) { $cfgRelation['pdf_pages'] = $curr_table[0]; } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['history']) { - $cfgRelation['history'] = $curr_table[0]; + $cfgRelation['history'] = $curr_table[0]; } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['recent']) { - $cfgRelation['recent'] = $curr_table[0]; + $cfgRelation['recent'] = $curr_table[0]; } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['table_uiprefs']) { - $cfgRelation['table_uiprefs'] = $curr_table[0]; + $cfgRelation['table_uiprefs'] = $curr_table[0]; } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['tracking']) { - $cfgRelation['tracking'] = $curr_table[0]; + $cfgRelation['tracking'] = $curr_table[0]; } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['userconfig']) { - $cfgRelation['userconfig'] = $curr_table[0]; + $cfgRelation['userconfig'] = $curr_table[0]; + } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['users']) { + $cfgRelation['users'] = $curr_table[0]; + } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['usergroups']) { + $cfgRelation['usergroups'] = $curr_table[0]; } } // end while $GLOBALS['dbi']->freeResult($tab_rs); @@ -430,7 +452,7 @@ function PMA_checkRelationsParam() if (isset($cfgRelation['relation'])) { $cfgRelation['relwork'] = true; if (isset($cfgRelation['table_info'])) { - $cfgRelation['displaywork'] = true; + $cfgRelation['displaywork'] = true; } } @@ -473,12 +495,17 @@ function PMA_checkRelationsParam() $cfgRelation['bookmarkwork'] = true; } + if (isset($cfgRelation['users']) && isset($cfgRelation['usergroups'])) { + $cfgRelation['menuswork'] = true; + } + if ($cfgRelation['relwork'] && $cfgRelation['displaywork'] && $cfgRelation['pdfwork'] && $cfgRelation['commwork'] && $cfgRelation['mimework'] && $cfgRelation['historywork'] && $cfgRelation['recentwork'] && $cfgRelation['uiprefswork'] && $cfgRelation['trackingwork'] && $cfgRelation['userconfigwork'] && $cfgRelation['bookmarkwork'] && $cfgRelation['designerwork'] + && $cfgRelation['menuswork'] ) { $cfgRelation['allworks'] = true; } diff --git a/libraries/server_privileges.lib.php b/libraries/server_privileges.lib.php index 46a35c6970..543c121b21 100644 --- a/libraries/server_privileges.lib.php +++ b/libraries/server_privileges.lib.php @@ -390,6 +390,103 @@ function PMA_getSqlQueryForDisplayPrivTable($db, $table, $username, $hostname) ." AND `Db` = '" . PMA_Util::unescapeMysqlWildcards($db) . "'" ." AND `Table_name` = '" . PMA_Util::sqlAddSlashes($table) . "';"; } + +/** + * Displays a dropdown to select the user group + * with menu items configured to each of them. + * + * @param string $username username + * + * @return string html to select the user group + */ +function PMA_getHtmlToChoseUserGroup($username) +{ + $html_output = '
'; + $params = array('username' => $username); + $html_output .= PMA_generate_common_hidden_inputs($params); + $html_output .= '
'; + $html_output .= '' . __('User group') . ''; + + $groupTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb']) + . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['usergroups']); + $userTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb']) + . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['users']); + + $userGroups = array(); + $sql_query = "SELECT `usergroup` FROM " . $groupTable; + $result = PMA_queryAsControlUser($sql_query, false); + if ($result) { + while ($row = $GLOBALS['dbi']->fetchRow($result)) { + $userGroups[] = $row[0]; + } + } + $GLOBALS['dbi']->freeResult($result); + + $userGroup = ''; + if (isset($GLOBALS['username'])) { + $sql_query = "SELECT `usergroup` FROM " . $userTable + . " WHERE `username` = '" . PMA_Util::sqlAddSlashes($username) . "'"; + $userGroup = $GLOBALS['dbi']->fetchValue( + $sql_query, 0, 0, $GLOBALS['controllink'] + ); + } + + $html_output .= __('User group') . ': '; + $html_output .= ''; + $html_output .= ''; + $html_output .= '
'; + $html_output .= '
'; + return $html_output; +} + +/** + * Sets the user group from request values + * + * @param string $username username + * @param string $userGroup user group to set + * + * @return void + */ +function PMA_setUserGroup($username, $userGroup) +{ + $userTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb']) + . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['users']); + + $sql_query = "SELECT `usergroup` FROM " . $userTable + . " WHERE `username` = '" . PMA_Util::sqlAddSlashes($username) . "'"; + $oldUserGroup = $GLOBALS['dbi']->fetchValue( + $sql_query, 0, 0, $GLOBALS['controllink'] + ); + + if ($oldUserGroup === false) { + $upd_query = "INSERT INTO " . $userTable . "(`username`, `usergroup`)" + . " VALUES ('" . PMA_Util::sqlAddSlashes($username) . "', " + . "'" . PMA_Util::sqlAddSlashes($userGroup) . "')"; + } else { + if (empty($userGroup)) { + $upd_query = "DELETE FROM " . $userTable + . " WHERE `username`='" . PMA_Util::sqlAddSlashes($username) . "'"; + } elseif ($oldUserGroup != $userGroup) { + $upd_query = "UPDATE " . $userTable + . " SET `usergroup`='" . PMA_Util::sqlAddSlashes($userGroup) . "'" + . " WHERE `username`='" . PMA_Util::sqlAddSlashes($username) . "'"; + } + } + if (isset($upd_query)) { + PMA_queryAsControlUser($upd_query); + } +} + /** * Displays the privileges form table * @@ -591,7 +688,7 @@ function PMA_getHtmlForDisplayResourceLimits($row) * @param string $db the database * @param string $table the table * @param boolean $columns columns array - * @param $row current privileges row + * @param array $row current privileges row * * @return string $html_output */ @@ -2429,9 +2526,12 @@ function PMA_getUsersOverview($result, $db_rights, $link_edit, $pmaThemeImage, . PMA_Util::showHint( __('Note: MySQL privilege names are expressed in English') ) - . '' . "\n" - . '' . __('Grant') . '' . "\n" - . '' . __('Action') . '' . "\n" + . '' . "\n"; + if ($GLOBALS['cfgRelation']['menuswork']) { + $html_output .= '' . __('User group') . '' . "\n"; + } + $html_output .= '' . __('Grant') . '' . "\n" + . '' . __('Action') . '' . "\n" . '' . "\n" . '' . "\n"; @@ -2479,6 +2579,27 @@ function PMA_getUsersOverview($result, $db_rights, $link_edit, $pmaThemeImage, */ function PMA_getTableBodyForUserRightsTable($db_rights, $link_edit, $link_export) { + if ($GLOBALS['cfgRelation']['menuswork']) { + $usersTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb']) + . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['users']); + $sqlQuery = "SELECT * FROM " . $usersTable; + $result = PMA_queryAsControlUser($sqlQuery, false); + $groupAssignment = array(); + if ($result) { + while ($row = $GLOBALS['dbi']->fetchAssoc($result)) { + $groupAssignment[$row['username']] = $row['usergroup']; + } + } + $GLOBALS['dbi']->freeResult($result); + + $link_edit_user_group = '' + . PMA_Util::getIcon('b_usrlist.png', __('Edit user group')) + . ''; + } + $odd_row = true; $index_checkbox = 0; $html_output = ''; @@ -2521,28 +2642,48 @@ function PMA_getTableBodyForUserRightsTable($db_rights, $link_edit, $link_export $html_output .= '' . "\n" . '' . implode(',' . "\n" . ' ', $host['privs']) . "\n" - . '' . "\n" - . '' + . '' . "\n"; + if ($GLOBALS['cfgRelation']['menuswork']) { + $html_output .= '' . "\n" + . (isset($groupAssignment[$host['User']]) + ? $groupAssignment[$host['User']] + : '' + ) + . '' . "\n"; + } + $html_output .= '' . ($host['Grant_priv'] == 'Y' ? __('Yes') : __('No')) - . '' . "\n" - . '' + . '' . "\n"; + + $html_output .= '' . sprintf( $link_edit, urlencode($host['User']), urlencode($host['Host']), '', '' - ); - $html_output .= ''; - - $html_output .= ''; - $html_output .= sprintf( - $link_export, - urlencode($host['User']), - urlencode($host['Host']), - (isset($_GET['initial']) ? $_GET['initial'] : '') - ); - $html_output .= ''; + ) + . ''; + if ($GLOBALS['cfgRelation']['menuswork']) { + if (empty($host['User'])) { + $html_output .= ''; + } else { + $html_output .= '' + . sprintf( + $link_edit_user_group, + urlencode($host['User']) + ) + . ''; + } + } + $html_output .= '' + . sprintf( + $link_export, + urlencode($host['User']), + urlencode($host['Host']), + (isset($_GET['initial']) ? $_GET['initial'] : '') + ) + . ''; $html_output .= ''; $odd_row = ! $odd_row; } @@ -3028,8 +3169,324 @@ function PMA_getHtmlForDisplayUserOverviewPage($link_edit, $pmaThemeImage, $flushnote->addParam('', false); $html_output .= $flushnote->getDisplay(); } - return $html_output; } + + return $html_output; +} + +/** + * Return HTML to list the users belonging to a given user group + * + * @param string $userGroup user group name + * + * @return HTML to list the users belonging to a given user group + */ +function PMA_getHtmlForListingUsersofAGroup($userGroup) +{ + $html_output = '

' + . sprintf(__('Users of \'%s\' user group'), htmlspecialchars($userGroup)) + . '

'; + + $usersTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb']) + . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['users']); + $sql_query = "SELECT `username` FROM " . $usersTable + . " WHERE `usergroup`='" . PMA_Util::sqlAddSlashes($userGroup) . "'"; + $result = PMA_queryAsControlUser($sql_query, false); + if ($result) { + if ($GLOBALS['dbi']->numRows($result) == 0) { + $html_output .= '

' + . __('No users were found belonging to this user group') + . '

'; + } else { + $html_output .= '' + . '' + . ''; + $i = 0; + while ($row = $GLOBALS['dbi']->fetchRow($result)) { + $i++; + $html_output .= '' + . '' + . '' + . ''; + } + $html_output .= '' + . '
#' . __('User') . '
' . $i . ' ' . htmlspecialchars($row[0]) . '
'; + } + } + $GLOBALS['dbi']->freeResult($result); + return $html_output; +} + +/** + * Returns HTML for the 'user groups' table + * + * @return string HTML for the 'user groups' table + */ +function PMA_getHtmlForUserGroupsTable() +{ + $tabs = PMA_Util::getMenuTabList(); + + $html_output = '

' . __('User groups') . '

'; + $html_output .= '
'; + $html_output .= PMA_generate_common_hidden_inputs(); + $html_output .= ''; + $html_output .= ''; + $html_output .= ''; + $html_output .= ''; + $html_output .= ''; + $html_output .= ''; + $html_output .= ''; + $html_output .= ''; + $html_output .= ''; + + $groupTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb']) + . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['usergroups']); + $sql_query = "SELECT * FROM " . $groupTable; + $result = PMA_queryAsControlUser($sql_query, false); + if ($result) { + $odd = true; + while ($row = $GLOBALS['dbi']->fetchAssoc($result)) { + $html_output .= ''; + $html_output .= ''; + $html_output .= ''; + $html_output .= ''; + $html_output .= ''; + + $html_output .= ''; + + $html_output .= ''; + + $odd = ! $odd; + } + } + $GLOBALS['dbi']->freeResult($result); + + $html_output .= ''; + $html_output .= '
' . __('User group') . '' . __('Server level tabs') . '' . __('Database level tabs') . '' . __('Table level tabs') . '' . __('Action') . '
' . htmlspecialchars($row['usergroup']) . '' . _getAllowedTabNames($row, 'server') . '' . _getAllowedTabNames($row, 'db') . '' . _getAllowedTabNames($row, 'table') . ''; + $html_output .= '' + . PMA_Util::getIcon('b_usrlist.png', __('View users')) . ''; + $html_output .= '  '; + $html_output .= '' + . PMA_Util::getIcon('b_edit.png', __('Edit')) . ''; + $html_output .= '  '; + $html_output .= '' + . PMA_Util::getIcon('b_drop.png', __('Delete')) . ''; + $html_output .= '
'; + $html_output .= '
'; + + $html_output .= '
'; + $html_output .= '' + . PMA_Util::getIcon('b_usradd.png') + . __('Add user group') . ''; + $html_output .= '
'; + + return $html_output; +} + +/** + * Returns the list of allowed menu tab names + * based on a data row from usergroup table. + * + * @param array $row row of usergroup table + * @param string $level 'server', 'db' or 'table' + * + * @return string comma seperated list of allowed menu tab names + */ +function _getAllowedTabNames($row, $level) +{ + $tabNames = array(); + $tabs = PMA_Util::getMenuTabList($level); + foreach ($tabs as $tab => $tabName) { + if (! isset($row[$level . '_' . $tab]) + || $row[$level . '_' . $tab] == 'Y' + ) { + $tabNames[] = $tabName; + } + } + return implode(', ', $tabNames); +} + +/** + * Deletes a user group + * + * @param string $userGroup user group name + * + * @return void + */ +function PMA_deleteUserGroup($userGroup) +{ + $groupTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb']) + . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['usergroups']); + $sql_query = "DELETE FROM " . $groupTable + . " WHERE `usergroup`='" . PMA_Util::sqlAddSlashes($userGroup) . "'"; + PMA_queryAsControlUser($sql_query, true); +} + +/** + * Returns HTML for add/edit user group dialog + * + * @param string $userGroup name of the user group in case of editing + * + * @return string HTML for add/edit user group dialog + */ +function PMA_getHtmlToEditUserGroup($userGroup = null) +{ + $html_output = ''; + if ($userGroup == null) { + $html_output .= '

' . __('Add user group') . '

'; + } else { + $html_output .= '

' + . sprintf(__('Edit user group: \'%s\''), htmlspecialchars($userGroup)) + . '

'; + } + + $html_output .= '
'; + $urlParams = array(); + if ($userGroup != null) { + $urlParams['userGroup'] = $userGroup; + $urlParams['editUserGroupSubmit'] = '1'; + } else { + $urlParams['addUserGroupSubmit'] = '1'; + } + $html_output .= PMA_generate_common_hidden_inputs($urlParams); + + $html_output .= '
'; + $html_output .= '' . __('User group privileges') + . '   ' + . '' + . '' + . ''; + + if ($userGroup == null) { + $html_output .= ''; + $html_output .= ''; + $html_output .= '
'; + } + + $allowedTabs = array( + 'server' => array(), + 'db' => array(), + 'table' => array() + ); + if ($userGroup != null) { + $groupTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb']) + . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['usergroups']); + $sql_query = "SELECT * FROM " . $groupTable + . " WHERE `usergroup`='" . PMA_Util::sqlAddSlashes($userGroup) . "'"; + $result = PMA_queryAsControlUser($sql_query, false); + if ($result) { + $row = $GLOBALS['dbi']->fetchAssoc($result); + foreach ($row as $key => $value) { + if (substr($key, 0, 7) == 'server_' && $value == 'Y') { + $allowedTabs['server'][] = substr($key, 7); + } elseif (substr($key, 0, 3) == 'db_' && $value == 'Y') { + $allowedTabs['db'][] = substr($key, 3); + } elseif (substr($key, 0, 6) == 'table_' && $value == 'Y') { + $allowedTabs['table'][] = substr($key, 6); + } + } + } + $GLOBALS['dbi']->freeResult($result); + } + + $html_output .= _getTabList( + __('Sever level tabs'), 'server', $allowedTabs['server'] + ); + $html_output .= _getTabList( + __('Database level tabs'), 'db', $allowedTabs['db'] + ); + $html_output .= _getTabList( + __('Table level tabs'), 'table', $allowedTabs['table'] + ); + + $html_output .= '
'; + + $html_output .= ''; + + return $html_output; +} + +/** + * Returns HTML for checkbox groups to choose + * tabs of 'server', 'db' or 'table' levels. + * + * @param string $title title of the checkbox group + * @param string $level 'server', 'db' or 'table' + * @param array $selected array of selected allowed tabs + * + * @return string HTML for checkbox groups + */ +function _getTabList($title, $level, $selected) +{ + $tabs = PMA_Util::getMenuTabList($level); + $html_output = '
'; + $html_output .= '' . $title . ''; + foreach ($tabs as $tab => $tabName) { + $html_output .= '
'; + $html_output .= ''; + $html_output .= ''; + $html_output .= '
'; + } + $html_output .= '
'; + return $html_output; +} + +/** + * Add/update a user group with allowed menu tabs. + * + * @param string $userGroup user group name + * @param boolean $new whether this is a new user group + * + * @return void + */ +function PMA_editUserGroup($userGroup, $new = false) +{ + $tabs = PMA_Util::getMenuTabList(); + $groupTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb']) + . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['usergroups']); + + $cols = ""; + $vals = ""; + $colsNvals = ""; + foreach ($tabs as $tabGroupName => $tabGroup) { + foreach ($tabs[$tabGroupName] as $tab => $tabName) { + $colName = $tabGroupName . '_' . $tab; + $cols .= "," . PMA_Util::backquote($colName); + if (isset($_REQUEST[$colName])&& $_REQUEST[$colName] == 'Y') { + $vals .= ",'Y'"; + $colsNvals .= "," . PMA_Util::backquote($colName) . "='Y'"; + } else { + $vals .= ",'N'"; + $colsNvals .= "," . PMA_Util::backquote($colName) . "='N'"; + } + } + } + if ($new) { + $sql_query = "INSERT INTO " . $groupTable + . "(`usergroup`" . $cols . ")" + . " VALUES" + . " ('" . PMA_Util::sqlAddSlashes($userGroup) . "'" . $vals . ")"; + } else { + $sql_query = "UPDATE " . $groupTable . " SET " . substr($colsNvals, 1) + . " WHERE `usergroup`='" . PMA_Util::sqlAddSlashes($userGroup) . "'"; + } + PMA_queryAsControlUser($sql_query, true); } /** @@ -3068,9 +3525,6 @@ function PMA_getHtmlForDisplayUserProperties($dbname_is_wildcard,$url_dbname, } $class = ' class="ajax"'; - $html_output .= '' . "\n"; - $_params = array( 'username' => $username, 'hostname' => $hostname, @@ -3081,8 +3535,10 @@ function PMA_getHtmlForDisplayUserProperties($dbname_is_wildcard,$url_dbname, $_params['tablename'] = $tablename; } } - $html_output .= PMA_generate_common_hidden_inputs($_params); + $html_output .= '' . "\n"; + $html_output .= PMA_generate_common_hidden_inputs($_params); $html_output .= PMA_getHtmlToDisplayPrivilegesTable( PMA_ifSetOr($dbname, '*', 'length'), PMA_ifSetOr($tablename, '*', 'length') @@ -3402,4 +3858,44 @@ function PMA_getSqlQueriesForDisplayAndAddUser($username, $hostname, $password) $sql_query ); } + +/** + * Get HTML for secondary level menu tabs on 'Users' page + * + * @param string $selfUrl Url of the file + * + * @return string HTML for secondary level menu tabs on 'Users' page + */ +function PMA_getHtmlForSubMenusOnUsersPage($selfUrl) +{ + $url_params = PMA_generate_common_url(); + $items = array( + array( + 'name' => __('Users overview'), + 'url' => 'server_privileges.php' + ), + array( + 'name' => __('User groups'), + 'url' => 'server_user_groups.php' + ) + ); + + $retval = '
    '; + foreach ($items as $item) { + $class = ''; + if ($item['url'] === $selfUrl) { + $class = ' class="tabactive"'; + } + $retval .= '
  • '; + $retval .= ''; + $retval .= $item['name']; + $retval .= ''; + $retval .= '
  • '; + } + $retval .= '
'; + $retval .= '
'; + + return $retval; +} ?> diff --git a/libraries/server_status.lib.php b/libraries/server_status.lib.php new file mode 100644 index 0000000000..3f2dbd79d1 --- /dev/null +++ b/libraries/server_status.lib.php @@ -0,0 +1,554 @@ +fetchValue( + 'SELECT UNIX_TIMESTAMP() - ' . $ServerStatusData->status['Uptime'] + ); + + $retval = '

'; + $bytes_received = $ServerStatusData->status['Bytes_received']; + $bytes_sent = $ServerStatusData->status['Bytes_sent']; + $retval .= sprintf( + __('Network traffic since startup: %s'), + implode( + ' ', + PMA_Util::formatByteDown( + $bytes_received + $bytes_sent, + 3, + 1 + ) + ) + ); + $retval .= '

'; + $retval .= '

'; + $retval .= sprintf( + __('This MySQL server has been running for %1$s. It started up on %2$s.'), + PMA_Util::timespanFormat($ServerStatusData->status['Uptime']), + PMA_Util::localisedDate($start_time) + ) . "\n"; + $retval .= '

'; + + if ($GLOBALS['server_master_status'] || $GLOBALS['server_slave_status']) { + $retval .= '

'; + if ($GLOBALS['server_master_status'] && $GLOBALS['server_slave_status']) { + $retval .= __( + 'This MySQL server works as master and ' + . 'slave in replication process.' + ); + } elseif ($GLOBALS['server_master_status']) { + $retval .= __( + 'This MySQL server works as master ' + . 'in replication process.' + ); + } elseif ($GLOBALS['server_slave_status']) { + $retval .= __( + 'This MySQL server works as slave ' + . 'in replication process.' + ); + } + $retval .= '

'; + } + + /* + * if the server works as master or slave in replication process, + * display useful information + */ + if ($GLOBALS['server_master_status'] || $GLOBALS['server_slave_status']) { + $retval .= '
'; + $retval .= '

'; + $retval .= __('Replication status'); + $retval .= '

'; + foreach ($GLOBALS['replication_types'] as $type) { + if (isset(${"server_{$type}_status"}) && ${"server_{$type}_status"}) { + $retval .= PMA_getHtmlForReplicationStatusTable($type); + } + } + } + + return $retval; +} + +/** + * Prints server state traffic information + * + * @param Object $ServerStatusData An instance of the PMA_ServerStatusData class + * + * @return string + */ +function PMA_getHtmlForServerStateTraffic($ServerStatusData) +{ + $hour_factor = 3600 / $ServerStatusData->status['Uptime']; + $retval = ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= '
'; + $retval .= __('Traffic') . ' '; + $retval .= PMA_Util::showHint( + __( + 'On a busy server, the byte counters may overrun, so those statistics ' + . 'as reported by the MySQL server may be incorrect.' + ) + ); + $retval .= 'ø ' . __('per hour') . '
' . __('Received') . ''; + $retval .= implode( + ' ', + PMA_Util::formatByteDown( + $ServerStatusData->status['Bytes_received'], 3, 1 + ) + ); + $retval .= ''; + $retval .= implode( + ' ', + PMA_Util::formatByteDown( + $ServerStatusData->status['Bytes_received'] * $hour_factor, 3, 1 + ) + ); + $retval .= '
' . __('Sent') . ''; + $retval .= implode( + ' ', + PMA_Util::formatByteDown( + $ServerStatusData->status['Bytes_sent'], 3, 1 + ) + ); + $retval .= 'status['Bytes_sent'] * $hour_factor, 3, 1 + ) + ); + $retval .= '
' . __('Total') . ''; + $bytes_received = $ServerStatusData->status['Bytes_received']; + $bytes_sent = $ServerStatusData->status['Bytes_sent']; + $retval .= implode( + ' ', + PMA_Util::formatByteDown( + $bytes_received + $bytes_sent, 3, 1 + ) + ); + $retval .= ''; + $bytes_received = $ServerStatusData->status['Bytes_received']; + $bytes_sent = $ServerStatusData->status['Bytes_sent']; + $retval .= implode( + ' ', + PMA_Util::formatByteDown( + ($bytes_received + $bytes_sent) * $hour_factor, 3, 1 + ) + ); + $retval .= '
'; + return $retval; +} + +/** + * Prints server state connections information + * + * @param Object $ServerStatusData An instance of the PMA_ServerStatusData class + * + * @return string + */ +function PMA_getHtmlForServerStateConnections($ServerStatusData) +{ + $hour_factor = 3600 / $ServerStatusData->status['Uptime']; + $retval = ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= '
' . __('Connections') . 'ø ' . __('per hour') . '%
' . __('max. concurrent connections') . ''; + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Max_used_connections'], 0 + ); + $retval .= '--- ---
' . __('Failed attempts') . ''; + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Aborted_connects'], 4, 1, true + ); + $retval .= ''; + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Aborted_connects'] * $hour_factor, 4, 2, true + ); + $retval .= ''; + if ($ServerStatusData->status['Connections'] > 0) { + $abortNum = $ServerStatusData->status['Aborted_connects']; + $connectNum = $ServerStatusData->status['Connections']; + + $retval .= PMA_Util::formatNumber( + $abortNum * 100 / $connectNum, + 0, 2, true + ); + $retval .= '%'; + } else { + $retval .= '--- '; + } + $retval .= '
' . __('Aborted') . ''; + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Aborted_clients'], 4, 1, true + ); + $retval .= ''; + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Aborted_clients'] * $hour_factor, 4, 2, true + ); + $retval .= ''; + if ($ServerStatusData->status['Connections'] > 0) { + $abortNum = $ServerStatusData->status['Aborted_clients']; + $connectNum = $ServerStatusData->status['Connections']; + + $retval .= PMA_Util::formatNumber( + $abortNum * 100 / $connectNum, + 0, 2, true + ); + $retval .= '%'; + } else { + $retval .= '--- '; + } + $retval .= '
' . __('Total') . ''; + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Connections'], 4, 0 + ); + $retval .= ''; + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Connections'] * $hour_factor, 4, 2 + ); + $retval .= ''; + $retval .= PMA_Util::formatNumber(100, 0, 2); + $retval .= '%
'; + + return $retval; +} + +/** + * Prints Server Process list + * + * @param Object $ServerStatusData An instance of the PMA_ServerStatusData class + * + * @return string + */ +function PMA_getHtmlForServerProcesslist($ServerStatusData) +{ + $url_params = array(); + + $show_full_sql = ! empty($_REQUEST['full']); + if ($show_full_sql) { + $url_params['full'] = 1; + $full_text_link = 'server_status.php' . PMA_generate_common_url( + array(), 'html', '?' + ); + } else { + $full_text_link = 'server_status.php' . PMA_generate_common_url( + array('full' => 1) + ); + } + + // This array contains display name and real column name of each + // sortable column in the table + $sortable_columns = array( + array( + 'column_name' => __('ID'), + 'order_by_field' => 'Id' + ), + array( + 'column_name' => __('User'), + 'order_by_field' => 'User' + ), + array( + 'column_name' => __('Host'), + 'order_by_field' => 'Host' + ), + array( + 'column_name' => __('Database'), + 'order_by_field' => 'db' + ), + array( + 'column_name' => __('Command'), + 'order_by_field' => 'Command' + ), + array( + 'column_name' => __('Time'), + 'order_by_field' => 'Time' + ), + array( + 'column_name' => __('Status'), + 'order_by_field' => 'State' + ), + array( + 'column_name' => __('SQL query'), + 'order_by_field' => 'Info' + ) + ); + $sortable_columns_count = count($sortable_columns); + + if (PMA_DRIZZLE) { + $left_str = 'left(p.info, ' + . (int)$GLOBALS['cfg']['MaxCharactersInDisplayedSQL'] . ')'; + $sql_query = "SELECT + p.id AS Id, + p.username AS User, + p.host AS Host, + p.db AS db, + p.command AS Command, + p.time AS Time, + p.state AS State," + . ($show_full_sql ? 's.query' : $left_str ) + . " AS Info FROM data_dictionary.PROCESSLIST p " + . ($show_full_sql + ? 'LEFT JOIN data_dictionary.SESSIONS s ON s.session_id = p.id' + : ''); + if (! empty($_REQUEST['order_by_field']) + && ! empty($_REQUEST['sort_order']) + ) { + $sql_query .= ' ORDER BY p.' . $_REQUEST['order_by_field'] . ' ' + . $_REQUEST['sort_order']; + } + } else { + $sql_query = $show_full_sql + ? 'SHOW FULL PROCESSLIST' + : 'SHOW PROCESSLIST'; + if (! empty($_REQUEST['order_by_field']) + && ! empty($_REQUEST['sort_order']) + ) { + $sql_query = 'SELECT * FROM `INFORMATION_SCHEMA`.`PROCESSLIST` ' + . 'ORDER BY `' + . $_REQUEST['order_by_field'] . '` ' . $_REQUEST['sort_order']; + } + } + + $result = $GLOBALS['dbi']->query($sql_query); + + $retval = ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + foreach ($sortable_columns as $column) { + + $is_sorted = ! empty($_REQUEST['order_by_field']) + && ! empty($_REQUEST['sort_order']) + && ($_REQUEST['order_by_field'] == $column['order_by_field']); + + $column['sort_order'] = 'ASC'; + if ($is_sorted && $_REQUEST['sort_order'] === 'ASC') { + $column['sort_order'] = 'DESC'; + } + + if ($is_sorted) { + if ($_REQUEST['sort_order'] == 'ASC') { + $asc_display_style = 'inline'; + $desc_display_style = 'none'; + } elseif ($_REQUEST['sort_order'] == 'DESC') { + $desc_display_style = 'inline'; + $asc_display_style = 'none'; + } + } + + $retval .= ''; + } + + $retval .= ''; + $retval .= ''; + $retval .= ''; + + $odd_row = true; + while ($process = $GLOBALS['dbi']->fetchAssoc($result)) { + $retval .= PMA_getHtmlForServerProcessItem( + $process, + $odd_row, + $show_full_sql + ); + $odd_row = ! $odd_row; + } + $retval .= ''; + $retval .= '
' . __('Processes') . ''; + $columnUrl = PMA_generate_common_url($column); + $retval .= ''; + $retval .= ''
+                . __('Ascending') . ''; + } + + $retval .= ''; + + if (! PMA_DRIZZLE && (0 === --$sortable_columns_count)) { + $retval .= ''; + if ($show_full_sql) { + $retval .= PMA_Util::getImage( + 's_partialtext.png', + __('Truncate Shown Queries') + ); + } else { + $retval .= PMA_Util::getImage( + 's_fulltext.png', + __('Show Full Queries') + ); + } + $retval .= ''; + } + $retval .= '
'; + + return $retval; +} + +/** + * Prints Every Item of Server Process + * + * @param Array $process data of Every Item of Server Process + * @param bool $odd_row display odd row or not + * @param bool $show_full_sql show full sql or not + * + * @return string + */ +function PMA_getHtmlForServerProcessItem($process, $odd_row, $show_full_sql) +{ + // Array keys need to modify due to the way it has used + // to display column values + if (! empty($_REQUEST['order_by_field']) && ! empty($_REQUEST['sort_order']) ) { + foreach (array_keys($process) as $key) { + $new_key = ucfirst(strtolower($key)); + $process[$new_key] = $process[$key]; + unset($process[$key]); + } + } + + $url_params['kill'] = $process['Id']; + $kill_process = 'server_status.php' . PMA_generate_common_url($url_params); + + $retval = ''; + $retval .= '' . __('Kill') . ''; + $retval .= '' . $process['Id'] . ''; + $retval .= '' . $process['User'] . ''; + $retval .= '' . $process['Host'] . ''; + $retval .= '' . ((! isset($process['db']) || ! strlen($process['db'])) + ? '' . __('None') . '' + : $process['db']) . ''; + $retval .= '' . $process['Command'] . ''; + $retval .= '' . $process['Time'] . ''; + $processStatusStr = empty($process['State']) ? '---' : $process['State']; + $retval .= '' . $processStatusStr . ''; + $retval .= ''; + + if (empty($process['Info'])) { + $retval .= '---'; + } else { + $cfg_maxDisplaySQL = $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']; + if (! $show_full_sql && strlen($process['Info']) > $cfg_maxDisplaySQL) { + $info = substr($process['Info'], 0, $cfg_maxDisplaySQL); + $retval .= htmlspecialchars($info) . '[...]'; + } else { + $retval .= '
'
+                    . $process['Info']
+                    . '
'; + } + } + $retval .= ''; + $retval .= ''; + + return $retval; +} + +?> + + diff --git a/libraries/sql.lib.php b/libraries/sql.lib.php index e32fb9c4e5..6ec9efa841 100644 --- a/libraries/sql.lib.php +++ b/libraries/sql.lib.php @@ -69,7 +69,6 @@ function PMA_getTableNameBySQL($sql, $tables) * @param array $sql_data information about SQL statement * @param string $goto URL to go back in case of errors * @param string $pmaThemeImage path for theme images directory - * @param string $text_dir text direction * @param string $printview whether printview is enabled * @param string $url_query URL query * @param array $disp_mode the display mode @@ -80,7 +79,7 @@ function PMA_getTableNameBySQL($sql, $tables) */ function PMA_getTableHtmlForMultipleQueries( $displayResultsObject, $db, $sql_data, $goto, $pmaThemeImage, - $text_dir, $printview, $url_query, $disp_mode, $sql_limit_to_append, + $printview, $url_query, $disp_mode, $sql_limit_to_append, $editable ) { $table_html = ''; @@ -187,8 +186,8 @@ function PMA_getTableHtmlForMultipleQueries( $displayResultsObject->setProperties( $unlim_num_rows, $fields_meta, $is_count, $is_export, $is_func, $is_analyse, $num_rows, $fields_cnt, $querytime, $pmaThemeImage, - $text_dir, $is_maint, $is_explain, $is_show, $showtable, - $printview, $url_query, $editable + $GLOBALS['text_dir'], $is_maint, $is_explain, $is_show, + $showtable, $printview, $url_query, $editable ); } @@ -1808,7 +1807,6 @@ function PMA_getBookmarkCreatedMessage() * @param string $db current database * @param string $goto goto page url * @param string $pmaThemeImage theme image uri - * @param string $text_dir text directory * @param string $url_query url query * @param string $disp_mode display mode * @param string $sql_limit_to_append sql limit to append @@ -1819,21 +1817,22 @@ function PMA_getBookmarkCreatedMessage() * @param object $result result of the executed query * @param int $querytime query execution time * @param array $analyzed_sql_results analyzed sql results - * @param bool $is_procedure whether it is a procedure call or not * * @return type */ function PMA_getHtmlForSqlQueryResultsTable($sql_data, $displayResultsObject, $db, - $goto, $pmaThemeImage, $text_dir, $url_query, $disp_mode, $sql_limit_to_append, + $goto, $pmaThemeImage, $url_query, $disp_mode, $sql_limit_to_append, $editable, $unlim_num_rows, $num_rows, $showtable, $result, $querytime, - $analyzed_sql_results, $is_procedure + $analyzed_sql_results ) { $printview = isset($_REQUEST['printview']) ? $_REQUEST['printview'] : null; - if (! empty($sql_data) && ($sql_data['valid_queries'] > 1) || $is_procedure) { + if (! empty($sql_data) && ($sql_data['valid_queries'] > 1) + || $analyzed_sql_results['is_procedure'] + ) { $_SESSION['is_multi_query'] = true; $table_html = PMA_getTableHtmlForMultipleQueries( $displayResultsObject, $db, $sql_data, $goto, - $pmaThemeImage, $text_dir, $printview, $url_query, + $pmaThemeImage, $printview, $url_query, $disp_mode, $sql_limit_to_append, $editable ); } else { @@ -1846,7 +1845,7 @@ function PMA_getHtmlForSqlQueryResultsTable($sql_data, $displayResultsObject, $d $unlim_num_rows, $fields_meta, $analyzed_sql_results['is_count'], $analyzed_sql_results['is_export'], $analyzed_sql_results['is_func'], $analyzed_sql_results['is_analyse'], $num_rows, - $fields_cnt, $querytime, $pmaThemeImage, $text_dir, + $fields_cnt, $querytime, $pmaThemeImage, $GLOBALS['text_dir'], $analyzed_sql_results['is_maint'], $analyzed_sql_results['is_explain'], $analyzed_sql_results['is_show'], $showtable, $printview, $url_query, $editable @@ -1964,4 +1963,174 @@ function PMA_getHtmlForPrintButton() return $print_button_html; } + +/** + * Function to display results when the executed query returns non empty results + * + * @param array $result executed query results + * @param bool $justBrowsing whether just browsing or not + * @param array $analyzed_sql_results analysed sql results + * @param string $db current database + * @param string $table current table + * @param string $disp_mode display mode + * @param string $message message to show + * @param array $sql_data sql data + * @param object $displayResultsObject Instance of DisplyResults.class + * @param string $goto goto page url + * @param string $pmaThemeImage uri of the theme image + * @param string $sql_limit_to_append sql limit to append + * @param int $unlim_num_rows unlimited number of rows + * @param int $num_rows number of rows + * @param int $querytime query time + * @param string $full_sql_query full sql query + * @param string $disp_query display query + * @param string $disp_message display message + * @param array $profiling_results profiling results + * @param string $query_type query type + * @param bool $selected selected + * @param string $sql_query sql query + * @param string $complete_query complete sql query + * @param array $cfg configuration + * + * @return void + */ +function PMA_sendResponseForResultsReturned($result, $justBrowsing, + $analyzed_sql_results, $db, $table, $disp_mode, $message, $sql_data, + $displayResultsObject, $goto, $pmaThemeImage, $sql_limit_to_append, + $unlim_num_rows, $num_rows, $querytime, $full_sql_query, $disp_query, + $disp_message, $profiling_results, $query_type, $selected, $sql_query, + $complete_query, $cfg +) { + // If we are retrieving the full value of a truncated field or the original + // value of a transformed field, show it here + if (isset($_REQUEST['grid_edit']) && $_REQUEST['grid_edit'] == true) { + PMA_sendResponseForGridEdit($result); + } + + // Gets the list of fields properties + if (isset($result) && $result) { + $fields_meta = $GLOBALS['dbi']->getFieldsMeta($result); + } + + // Should be initialized these parameters before parsing + $showtable = isset($showtable) ? $showtable : null; + $url_query = isset($url_query) ? $url_query : null; + + $response = PMA_Response::getInstance(); + $header = $response->getHeader(); + $scripts = $header->getScripts(); + + // hide edit and delete links: + // - for information_schema + // - if the result set does not contain all the columns of a unique key + // and we are not just browing all the columns of an updatable view + $updatableView + = $justBrowsing + && trim($analyzed_sql_results['analyzed_sql'][0]['select_expr_clause']) == '*' + && PMA_Table::isUpdatableView($db, $table); + + $has_unique = PMA_resultSetContainsUniqueKey( + $db, $table, $fields_meta + ); + + $editable = $has_unique || $updatableView; + + // Displays the results in a table + if (empty($disp_mode)) { + // see the "PMA_setDisplayMode()" function in + // libraries/DisplayResults.class.php + $disp_mode = 'urdr111101'; + } + if (!empty($table) && ($GLOBALS['dbi']->isSystemSchema($db) || !$editable)) { + $disp_mode = 'nnnn110111'; + } + if ( isset($_REQUEST['printview']) && $_REQUEST['printview'] == '1') { + $disp_mode = 'nnnn000000'; + } + + if (isset($_REQUEST['table_maintenance'])) { + $scripts->addFile('makegrid.js'); + $scripts->addFile('sql.js'); + if (isset($message)) { + $message = PMA_Message::success($message); + $table_maintenance_html = PMA_Util::getMessage( + $message, $GLOBALS['sql_query'], 'success' + ); + } + $table_maintenance_html .= PMA_getHtmlForSqlQueryResultsTable( + isset($sql_data) ? $sql_data : null, $displayResultsObject, $db, $goto, + $pmaThemeImage, $url_query, $disp_mode, $sql_limit_to_append, + false, $unlim_num_rows, $num_rows, $showtable, $result, $querytime, + $analyzed_sql_results, false + ); + if (empty($sql_data) || ($sql_data['valid_queries'] = 1)) { + $response->addHTML($table_maintenance_html); + exit(); + } + } + + if (!isset($_REQUEST['printview']) || $_REQUEST['printview'] != '1') { + $scripts->addFile('makegrid.js'); + $scripts->addFile('sql.js'); + unset($message); + //we don't need to buffer the output in getMessage here. + //set a global variable and check against it in the function + $GLOBALS['buffer_message'] = false; + } + + $print_view_header_html = PMA_getHtmlForPrintViewHeader( + $db, $full_sql_query, $num_rows + ); + + $previous_update_query_html = PMA_getHtmlForPreviousUpdateQuery( + isset($disp_query) ? $disp_query : null, + $cfg['ShowSQL'], isset($sql_data) ? $sql_data : null, + isset($disp_message) ? $disp_message : null + ); + + $profiling_chart_html = PMA_getHtmlForProfilingChart( + $disp_mode, $db, isset($profiling_results) ? $profiling_results : null + ); + + $missing_unique_column_msg = PMA_getMessageIfMissingColumnIndex( + $table, $db, $editable, $disp_mode + ); + + $bookmark_created_msg = PMA_getBookmarkCreatedMessage(); + + $table_html = PMA_getHtmlForSqlQueryResultsTable( + isset($sql_data) ? $sql_data : null, $displayResultsObject, $db, $goto, + $pmaThemeImage, $url_query, $disp_mode, $sql_limit_to_append, + $editable, $unlim_num_rows, $num_rows, $showtable, $result, $querytime, + $analyzed_sql_results + ); + + $indexes_problems_html = PMA_getHtmlForIndexesProblems( + isset($query_type) ? $query_type : null, + isset($selected) ? $selected : null + ); + + $bookmark_support_html = PMA_getHtmlForBookmark( + $disp_mode, isset($cfg['Bookmark']) ? $cfg['Bookmark'] : '', $sql_query, + $db, $table, isset($complete_query) ? $complete_query : $sql_query, + $cfg['Bookmark']['user'] + ); + + $print_button_html = PMA_getHtmlForPrintButton(); + + $html_output = isset($table_maintenance_html) ? $table_maintenance_html : ''; + + $html_output .= isset($print_view_header_html) ? $print_view_header_html : ''; + + $html_output .= PMA_getHtmlForSqlQueryResults( + $previous_update_query_html, $profiling_chart_html, + $missing_unique_column_msg, $bookmark_created_msg, + $table_html, $indexes_problems_html, $bookmark_support_html, + $print_button_html + ); + + $response->addHTML($html_output); + + exit(); +} ?> diff --git a/po/he.po b/po/he.po index 9d785bde27..39ded29533 100644 --- a/po/he.po +++ b/po/he.po @@ -4,10 +4,9 @@ msgstr "" "Project-Id-Version: phpMyAdmin 4.1-dev\n" "Report-Msgid-Bugs-To: phpmyadmin-devel@lists.sourceforge.net\n" "POT-Creation-Date: 2013-07-12 16:06+0200\n" -"PO-Revision-Date: 2013-06-03 10:24+0200\n" -"Last-Translator: Michal Čihař \n" -"Language-Team: Hebrew \n" +"PO-Revision-Date: 2013-07-15 21:08+0200\n" +"Last-Translator: Bug Me Not \n" +"Language-Team: Hebrew \n" "Language: he\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -829,13 +828,14 @@ msgid "" "Login cookie store is lower than cookie validity configured in phpMyAdmin, " "because of this, your login will expire sooner than configured in phpMyAdmin." msgstr "" +"חנות עוגיית כניסה נמוכה מתוקף עוגייה המוגדר בphpMyAdmin, בגלל זה, הכניסה שלך " +"תפוג מוקדם יותר מאשר מוגדרת בphpMyAdmin." #: index.php:468 msgid "The configuration file now needs a secret passphrase (blowfish_secret)." msgstr "קובץ התצורה צריכה ביטוי סיסמה סודית (blowfish_secret)." #: index.php:479 -#, fuzzy #| msgid "" #| "Directory [code]config[/code], which is used by the setup script, still " #| "exists in your phpMyAdmin directory. You should remove it once phpMyAdmin " diff --git a/po/pt_BR.po b/po/pt_BR.po index b714ac14e2..1d3e5930a0 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -4,15 +4,15 @@ msgstr "" "Project-Id-Version: phpMyAdmin 4.1-dev\n" "Report-Msgid-Bugs-To: phpmyadmin-devel@lists.sourceforge.net\n" "POT-Creation-Date: 2013-07-12 16:06+0200\n" -"PO-Revision-Date: 2013-07-01 20:58+0200\n" -"Last-Translator: Jean Nunes \n" -"Language-Team: Portuguese (Brazil) \n" +"PO-Revision-Date: 2013-07-17 21:47+0200\n" +"Last-Translator: Rodrigo Souza \n" +"Language-Team: Portuguese (Brazil) " +"\n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n > 1;\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 1.6-dev\n" #: browse_foreigners.php:51 browse_foreigners.php:75 js/messages.php:339 @@ -1735,16 +1735,14 @@ msgid "Show search criteria" msgstr "Exibir critério de pesquisa" #: js/messages.php:278 -#, fuzzy #| msgid "Hide search criteria" msgid "Hide find and replace criteria" -msgstr "Ocultar critério de pesquisa" +msgstr "Ocultar critério de substituição" #: js/messages.php:279 -#, fuzzy #| msgid "Show search criteria" msgid "Show find and replace criteria" -msgstr "Exibir critério de pesquisa" +msgstr "Exibir critério de substituição" #: js/messages.php:282 libraries/TableSearch.class.php:212 msgid "Zoom Search" @@ -3254,7 +3252,7 @@ msgstr "Pesquisa de tabela" #: libraries/TableSearch.class.php:217 libraries/TableSearch.class.php:1172 msgid "Find and Replace" -msgstr "" +msgstr "Pesquisar e Substituir" #: libraries/TableSearch.class.php:239 libraries/insert_edit.lib.php:1352 msgid "Edit/Insert" @@ -3321,38 +3319,33 @@ msgid "Reset zoom" msgstr "Resetar zoom" #: libraries/TableSearch.class.php:1281 -#, fuzzy #| msgid "Replace NULL with" msgid "Replace with:" -msgstr "Substituir NULL com" +msgstr "Substituir com:" #: libraries/TableSearch.class.php:1341 msgid "Find and replace - preview" -msgstr "" +msgstr "Pesquisar e substituir - preview" #: libraries/TableSearch.class.php:1345 -#, fuzzy #| msgid "Column" msgid "Count" -msgstr "Coluna" +msgstr "Contagem" #: libraries/TableSearch.class.php:1346 -#, fuzzy #| msgid "Original position" msgid "Original string" -msgstr "Posição original" +msgstr "String original" #: libraries/TableSearch.class.php:1347 -#, fuzzy #| msgid "Related Links" msgid "Replaced string" -msgstr "Links relacionados" +msgstr "String substituída" #: libraries/TableSearch.class.php:1371 -#, fuzzy #| msgid "Replicated" msgid "Replace" -msgstr "Replicado" +msgstr "Substituir" #: libraries/Theme.class.php:170 #, php-format diff --git a/server_privileges.php b/server_privileges.php index a74f213709..3136e9a8b3 100644 --- a/server_privileges.php +++ b/server_privileges.php @@ -16,6 +16,8 @@ require_once 'libraries/common.inc.php'; require_once 'libraries/display_change_password.lib.php'; require_once 'libraries/server_privileges.lib.php'; +$cfgRelation = PMA_getRelationsParam(); + /** * Does the common work */ @@ -24,6 +26,11 @@ $header = $response->getHeader(); $scripts = $header->getScripts(); $scripts->addFile('server_privileges.js'); +if ($GLOBALS['cfgRelation']['menuswork']) { + $response->addHTML('
'); + $response->addHTML(PMA_getHtmlForSubMenusOnUsersPage('server_privileges.php')); +} + $_add_user_error = false; if (isset ($_REQUEST['username'])) { @@ -228,6 +235,9 @@ if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) { $_error, $real_sql_query, $sql_query, $username, $hostname, isset($dbname) ? $dbname : null ); + if (! empty($_REQUEST['userGroup']) && $cfgRelation['menuswork']) { + PMA_setUserGroup($GLOBALS['username'], $_REQUEST['userGroup']); + } } else { if (isset($create_user_real)) { @@ -268,6 +278,14 @@ if (! empty($_POST['update_privs'])) { ); } +/** + * Assign users to user groups + */ +if (! empty($_REQUEST['changeUserGroup']) && $cfgRelation['menuswork']) { + PMA_setUserGroup($username, $_REQUEST['userGroup']); + $message = PMA_Message::success(); +} + /** * Revokes Privileges */ @@ -378,6 +396,7 @@ if ($GLOBALS['is_ajax_request'] && (! isset($_REQUEST['initial']) || empty($_REQUEST['initial'])) && ! isset($_REQUEST['showall']) && ! isset($_REQUEST['edit_user_dialog']) + && ! isset($_REQUEST['edit_user_group_dialog']) && ! isset($_REQUEST['db_specific']) ) { $extra_data = PMA_getExtraDataForAjaxBehavior( @@ -424,6 +443,18 @@ if (isset($_REQUEST['viewing_mode']) && $_REQUEST['viewing_mode'] == 'db') { * Displays the page */ + +if (! empty($_REQUEST['edit_user_group_dialog']) && $cfgRelation['menuswork']) { + $dialog = PMA_getHtmlToChoseUserGroup($username); + $response = PMA_Response::getInstance(); + if ($GLOBALS['is_ajax_request']) { + $response->addJSON('message', $dialog); + exit; + } else { + $response->addHTML($dialog); + } +} + // export user definition if (isset($_REQUEST['export']) || (isset($_REQUEST['submit_mult']) && $_REQUEST['submit_mult'] == 'export') @@ -491,4 +522,8 @@ if (empty($_REQUEST['adduser']) ); } // end if (empty($_REQUEST['adduser']) && empty($checkprivs))... elseif... else... +if ($GLOBALS['cfgRelation']['menuswork']) { + $response->addHTML('
'); +} + ?> diff --git a/server_status.php b/server_status.php index 68562e308a..c2ef016a36 100644 --- a/server_status.php +++ b/server_status.php @@ -9,6 +9,7 @@ require_once 'libraries/common.inc.php'; require_once 'libraries/server_common.inc.php'; require_once 'libraries/ServerStatusData.class.php'; +require_once 'libraries/server_status.lib.php'; /** * Replication library @@ -46,513 +47,9 @@ if (! empty($_REQUEST['kill'])) { $response = PMA_Response::getInstance(); $response->addHTML('
'); $response->addHTML($ServerStatusData->getMenuHtml()); -$response->addHTML(PMA_getServerStatusHtml($ServerStatusData)); +$response->addHTML(PMA_getHtmlForServerStatus($ServerStatusData)); $response->addHTML('
'); exit; -/** - * Prints server status information: processes, connections and traffic - * - * @param Object $ServerStatusData An instance of the PMA_ServerStatusData class - * - * @return string - */ -function PMA_getServerStatusHtml($ServerStatusData) -{ - //display the server state General Information - $retval = PMA_getServerStateGeneralInfoHtml($ServerStatusData); - - //display the server state traffic information - $retval .= PMA_getServerStateTrafficHtml($ServerStatusData); - - //display the server state connection information - $retval .= PMA_getServerStateConnectionsHtml($ServerStatusData); - - //display the server Process List information - $retval .= PMA_getServerProcesslistHtml($ServerStatusData); - - return $retval; -} - -/** - * Prints server state General information - * - * @param Object $ServerStatusData An instance of the PMA_ServerStatusData class - * - * @return string - */ -function PMA_getServerStateGeneralInfoHtml($ServerStatusData) -{ - $start_time = $GLOBALS['dbi']->fetchValue( - 'SELECT UNIX_TIMESTAMP() - ' . $ServerStatusData->status['Uptime'] - ); - - $retval = '

'; - $retval .= sprintf( - __('Network traffic since startup: %s'), - implode( - ' ', - PMA_Util::formatByteDown( - $ServerStatusData->status['Bytes_received'] + $ServerStatusData->status['Bytes_sent'], - 3, - 1 - ) - ) - ); - $retval .= '

'; - $retval .= '

'; - $retval .= sprintf( - __('This MySQL server has been running for %1$s. It started up on %2$s.'), - PMA_Util::timespanFormat($ServerStatusData->status['Uptime']), - PMA_Util::localisedDate($start_time) - ) . "\n"; - $retval .= '

'; - - if ($GLOBALS['server_master_status'] || $GLOBALS['server_slave_status']) { - $retval .= '

'; - if ($GLOBALS['server_master_status'] && $GLOBALS['server_slave_status']) { - $retval .= __( - 'This MySQL server works as master and ' - . 'slave in replication process.' - ); - } elseif ($GLOBALS['server_master_status']) { - $retval .= __( - 'This MySQL server works as master ' - . 'in replication process.' - ); - } elseif ($GLOBALS['server_slave_status']) { - $retval .= __( - 'This MySQL server works as slave ' - . 'in replication process.' - ); - } - $retval .= '

'; - } - - /* - * if the server works as master or slave in replication process, - * display useful information - */ - if ($GLOBALS['server_master_status'] || $GLOBALS['server_slave_status']) { - $retval .= '
'; - $retval .= '

'; - $retval .= __('Replication status'); - $retval .= '

'; - foreach ($GLOBALS['replication_types'] as $type) { - if (isset(${"server_{$type}_status"}) && ${"server_{$type}_status"}) { - $retval .= PMA_getHtmlForReplicationStatusTable($type); - } - } - } - - return $retval; -} - -/** - * Prints server state traffic information - * - * @param Object $ServerStatusData An instance of the PMA_ServerStatusData class - * - * @return string - */ -function PMA_getServerStateTrafficHtml($ServerStatusData) -{ - $hour_factor = 3600 / $ServerStatusData->status['Uptime']; - $retval = ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= '
'; - $retval .= __('Traffic') . ' '; - $retval .= PMA_Util::showHint( - __( - 'On a busy server, the byte counters may overrun, so those statistics ' - . 'as reported by the MySQL server may be incorrect.' - ) - ); - $retval .= 'ø ' . __('per hour') . '
' . __('Received') . ''; - $retval .= implode( - ' ', - PMA_Util::formatByteDown( - $ServerStatusData->status['Bytes_received'], 3, 1 - ) - ); - $retval .= ''; - $retval .= implode( - ' ', - PMA_Util::formatByteDown( - $ServerStatusData->status['Bytes_received'] * $hour_factor, 3, 1 - ) - ); - $retval .= '
' . __('Sent') . ''; - $retval .= implode( - ' ', - PMA_Util::formatByteDown( - $ServerStatusData->status['Bytes_sent'], 3, 1 - ) - ); - $retval .= 'status['Bytes_sent'] * $hour_factor, 3, 1 - ) - ); - $retval .= '
' . __('Total') . ''; - $retval .= implode( - ' ', - PMA_Util::formatByteDown( - $ServerStatusData->status['Bytes_received'] + $ServerStatusData->status['Bytes_sent'], 3, 1 - ) - ); - $retval .= ''; - $retval .= implode( - ' ', - PMA_Util::formatByteDown( - ($ServerStatusData->status['Bytes_received'] + $ServerStatusData->status['Bytes_sent']) - * $hour_factor, 3, 1 - ) - ); - $retval .= '
'; - return $retval; -} - -/** - * Prints server state connections information - * - * @param Object $ServerStatusData An instance of the PMA_ServerStatusData class - * - * @return string - */ -function PMA_getServerStateConnectionsHtml($ServerStatusData) -{ - $hour_factor = 3600 / $ServerStatusData->status['Uptime']; - $retval = ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= '
' . __('Connections') . 'ø ' . __('per hour') . '%
' . __('max. concurrent connections') . ''; - $retval .= PMA_Util::formatNumber( - $ServerStatusData->status['Max_used_connections'], 0 - ); - $retval .= '--- ---
' . __('Failed attempts') . ''; - $retval .= PMA_Util::formatNumber( - $ServerStatusData->status['Aborted_connects'], 4, 1, true - ); - $retval .= ''; - $retval .= PMA_Util::formatNumber( - $ServerStatusData->status['Aborted_connects'] * $hour_factor, 4, 2, true - ); - $retval .= ''; - if ($ServerStatusData->status['Connections'] > 0) { - $retval .= PMA_Util::formatNumber( - $ServerStatusData->status['Aborted_connects'] * 100 / $ServerStatusData->status['Connections'], - 0, 2, true - ); - $retval .= '%'; - } else { - $retval .= '--- '; - } - $retval .= '
' . __('Aborted') . ''; - $retval .= PMA_Util::formatNumber( - $ServerStatusData->status['Aborted_clients'], 4, 1, true - ); - $retval .= ''; - $retval .= PMA_Util::formatNumber( - $ServerStatusData->status['Aborted_clients'] * $hour_factor, 4, 2, true - ); - $retval .= ''; - if ($ServerStatusData->status['Connections'] > 0) { - $retval .= PMA_Util::formatNumber( - $ServerStatusData->status['Aborted_clients'] * 100 / $ServerStatusData->status['Connections'], - 0, 2, true - ); - $retval .= '%'; - } else { - $retval .= '--- '; - } - $retval .= '
' . __('Total') . ''; - $retval .= PMA_Util::formatNumber( - $ServerStatusData->status['Connections'], 4, 0 - ); - $retval .= ''; - $retval .= PMA_Util::formatNumber( - $ServerStatusData->status['Connections'] * $hour_factor, 4, 2 - ); - $retval .= ''; - $retval .= PMA_Util::formatNumber(100, 0, 2); - $retval .= '%
'; - - return $retval; -} - -/** - * Prints Server Process list - * - * @param Object $ServerStatusData An instance of the PMA_ServerStatusData class - * - * @return string - */ -function PMA_getServerProcesslistHtml($ServerStatusData) -{ - $url_params = array(); - - $show_full_sql = ! empty($_REQUEST['full']); - if ($show_full_sql) { - $url_params['full'] = 1; - $full_text_link = 'server_status.php' . PMA_generate_common_url( - array(), 'html', '?' - ); - } else { - $full_text_link = 'server_status.php' . PMA_generate_common_url( - array('full' => 1) - ); - } - - // This array contains display name and real column name of each - // sortable column in the table - $sortable_columns = array( - array( - 'column_name' => __('ID'), - 'order_by_field' => 'Id' - ), - array( - 'column_name' => __('User'), - 'order_by_field' => 'User' - ), - array( - 'column_name' => __('Host'), - 'order_by_field' => 'Host' - ), - array( - 'column_name' => __('Database'), - 'order_by_field' => 'db' - ), - array( - 'column_name' => __('Command'), - 'order_by_field' => 'Command' - ), - array( - 'column_name' => __('Time'), - 'order_by_field' => 'Time' - ), - array( - 'column_name' => __('Status'), - 'order_by_field' => 'State' - ), - array( - 'column_name' => __('SQL query'), - 'order_by_field' => 'Info' - ) - ); - $sortable_columns_count = count($sortable_columns); - - if (PMA_DRIZZLE) { - $left_str = 'left(p.info, ' - . (int)$GLOBALS['cfg']['MaxCharactersInDisplayedSQL'] . ')'; - $sql_query = "SELECT - p.id AS Id, - p.username AS User, - p.host AS Host, - p.db AS db, - p.command AS Command, - p.time AS Time, - p.state AS State," - . ($show_full_sql ? 's.query' : $left_str ) - . " AS Info FROM data_dictionary.PROCESSLIST p " - . ($show_full_sql - ? 'LEFT JOIN data_dictionary.SESSIONS s ON s.session_id = p.id' - : ''); - if (! empty($_REQUEST['order_by_field']) - && ! empty($_REQUEST['sort_order']) - ) { - $sql_query .= ' ORDER BY p.' . $_REQUEST['order_by_field'] . ' ' - . $_REQUEST['sort_order']; - } - } else { - $sql_query = $show_full_sql - ? 'SHOW FULL PROCESSLIST' - : 'SHOW PROCESSLIST'; - if (! empty($_REQUEST['order_by_field']) - && ! empty($_REQUEST['sort_order']) - ) { - $sql_query = 'SELECT * FROM `INFORMATION_SCHEMA`.`PROCESSLIST` ORDER BY `' - . $_REQUEST['order_by_field'] . '` ' . $_REQUEST['sort_order']; - } - } - - $result = $GLOBALS['dbi']->query($sql_query); - - $retval = ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - foreach ($sortable_columns as $column) { - - $is_sorted = ! empty($_REQUEST['order_by_field']) - && ! empty($_REQUEST['sort_order']) - && ($_REQUEST['order_by_field'] == $column['order_by_field']); - - $column['sort_order'] = 'ASC'; - if ($is_sorted && $_REQUEST['sort_order'] === 'ASC') { - $column['sort_order'] = 'DESC'; - } - - if ($is_sorted) { - if ($_REQUEST['sort_order'] == 'ASC') { - $asc_display_style = 'inline'; - $desc_display_style = 'none'; - } elseif ($_REQUEST['sort_order'] == 'DESC') { - $desc_display_style = 'inline'; - $asc_display_style = 'none'; - } - } - - $retval .= ''; - } - - $retval .= ''; - $retval .= ''; - $retval .= ''; - - $odd_row = true; - while ($process = $GLOBALS['dbi']->fetchAssoc($result)) { - - // Array keys need to modify due to the way it has used - // to display column values - if (! empty($_REQUEST['order_by_field']) - && ! empty($_REQUEST['sort_order']) - ) { - foreach (array_keys($process) as $key) { - $new_key = ucfirst(strtolower($key)); - $process[$new_key] = $process[$key]; - unset($process[$key]); - } - } - - $url_params['kill'] = $process['Id']; - $kill_process = 'server_status.php' . PMA_generate_common_url($url_params); - - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $retval .= ''; - $odd_row = ! $odd_row; - } - $retval .= ''; - $retval .= '
' . __('Processes') . ''; - $retval .= ''; - $retval .= ''
-                . __('Ascending') . ''; - } - - $retval .= ''; - - if (! PMA_DRIZZLE && (0 === --$sortable_columns_count)) { - $retval .= ''; - if ($show_full_sql) { - $retval .= PMA_Util::getImage( - 's_partialtext.png', - __('Truncate Shown Queries') - ); - } else { - $retval .= PMA_Util::getImage( - 's_fulltext.png', - __('Show Full Queries') - ); - } - $retval .= ''; - } - $retval .= '
' . __('Kill') . '' . $process['Id'] . '' . $process['User'] . '' . $process['Host'] . '' . ((! isset($process['db']) || ! strlen($process['db'])) - ? '' . __('None') . '' - : $process['db']) . '' . $process['Command'] . '' . $process['Time'] . '' . (empty($process['State']) ? '---' : $process['State']) . ''; - - if (empty($process['Info'])) { - $retval .= '---'; - } else { - if (! $show_full_sql && strlen($process['Info']) > $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) { - $retval .= htmlspecialchars(substr($process['Info'], 0, $GLOBALS['cfg']['MaxCharactersInDisplayedSQL'])) - . '[...]'; - } else { - $retval .= '
' 
-                    . $process['Info'] 
-                    . '
'; - } - } - $retval .= '
'; - - return $retval; -} - ?> diff --git a/server_user_groups.php b/server_user_groups.php new file mode 100644 index 0000000000..4099afc539 --- /dev/null +++ b/server_user_groups.php @@ -0,0 +1,59 @@ +addHTML('
'); +$response->addHTML(PMA_getHtmlForSubMenusOnUsersPage('server_user_groups.php')); + +/** + * Delete user group + */ +if (! empty($_REQUEST['deleteUserGroup'])) { + PMA_deleteUserGroup($_REQUEST['userGroup']); +} + +/** + * Add a new user group + */ +if (! empty($_REQUEST['addUserGroupSubmit'])) { + PMA_editUserGroup($_REQUEST['userGroup'], true); +} + +/** + * Update a user group + */ +if (! empty($_REQUEST['editUserGroupSubmit'])) { + PMA_editUserGroup($_REQUEST['userGroup']); +} + +if (isset($_REQUEST['viewUsers'])) { + // Display users belonging to a user group + $response->addHTML(PMA_getHtmlForListingUsersofAGroup($_REQUEST['userGroup'])); +} + +if (isset($_REQUEST['addUserGroup'])) { + // Display add user group dialog + $response->addHTML(PMA_getHtmlToEditUserGroup()); +} elseif (isset($_REQUEST['editUserGroup'])) { + // Display edit user group dialog + $response->addHTML(PMA_getHtmlToEditUserGroup($_REQUEST['userGroup'])); +} else { + // Display user groups table + $response->addHTML(PMA_getHtmlForUserGroupsTable()); +} + +$response->addHTML('
'); +?> \ No newline at end of file diff --git a/sql.php b/sql.php index f97c16f294..19053ad1b5 100644 --- a/sql.php +++ b/sql.php @@ -219,135 +219,19 @@ if ((0 == $num_rows && 0 == $unlim_num_rows) || $is_affected) { ); } else { - // At least one row is returned -> displays a table with results - // If we are retrieving the full value of a truncated field or the original - // value of a transformed field, show it here and exit - if ($_REQUEST['grid_edit'] == true) { - PMA_sendResponseForGridEdit($result); - } - - // Gets the list of fields properties - if (isset($result) && $result) { - $fields_meta = $GLOBALS['dbi']->getFieldsMeta($result); - } - - // Should be initialized these parameters before parsing - $showtable = isset($showtable) ? $showtable : null; - $url_query = isset($url_query) ? $url_query : null; - - $response = PMA_Response::getInstance(); - $header = $response->getHeader(); - $scripts = $header->getScripts(); - - // hide edit and delete links: - // - for information_schema - // - if the result set does not contain all the columns of a unique key - // and we are not just browing all the columns of an updatable view - $updatableView - = $justBrowsing - && trim($analyzed_sql[0]['select_expr_clause']) == '*' - && PMA_Table::isUpdatableView($db, $table); - - $has_unique = PMA_resultSetContainsUniqueKey( - $db, $table, $fields_meta - ); - - $editable = $has_unique || $updatableView; - - // Displays the results in a table - if (empty($disp_mode)) { - // see the "PMA_setDisplayMode()" function in - // libraries/DisplayResults.class.php - $disp_mode = 'urdr111101'; - } - if (!empty($table) && ($GLOBALS['dbi']->isSystemSchema($db) || !$editable)) { - $disp_mode = 'nnnn110111'; - } - if ( isset($_REQUEST['printview']) && $_REQUEST['printview'] == '1') { - $disp_mode = 'nnnn000000'; - } - - if (isset($_REQUEST['table_maintenance'])) { - $scripts->addFile('makegrid.js'); - $scripts->addFile('sql.js'); - if (isset($message)) { - $message = PMA_Message::success($message); - $table_maintenance_html = PMA_Util::getMessage( - $message, $GLOBALS['sql_query'], 'success' - ); - } - $table_maintenance_html .= PMA_getHtmlForSqlQueryResultsTable( - isset($sql_data) ? $sql_data : null, $displayResultsObject, $db, $goto, - $pmaThemeImage, $text_dir, $url_query, $disp_mode, $sql_limit_to_append, - false, $unlim_num_rows, $num_rows, $showtable, $result, $querytime, - $analyzed_sql_results, false - ); - if (empty($sql_data) || ($sql_data['valid_queries'] = 1)) { - $response->addHTML($table_maintenance_html); - exit(); - } - } - - if (!isset($_REQUEST['printview']) || $_REQUEST['printview'] != '1') { - $scripts->addFile('makegrid.js'); - $scripts->addFile('sql.js'); - unset($message); - //we don't need to buffer the output in getMessage here. - //set a global variable and check against it in the function - $GLOBALS['buffer_message'] = false; - } - - $print_view_header_html = PMA_getHtmlForPrintViewHeader( - $db, $full_sql_query, $num_rows - ); - - $previous_update_query_html = PMA_getHtmlForPreviousUpdateQuery( + // At least one row is returned -> displays a table with results + PMA_sendResponseForResultsReturned( + isset($result) ? $result : null, $justBrowsing, $analyzed_sql_results, + $db, $table, isset($disp_mode) ? $disp_mode : null, + isset($message) ? $message : null, isset($sql_data) ? $sql_data : null, + $displayResultsObject, $goto, $pmaThemeImage, + $sql_limit_to_append, $unlim_num_rows, + $num_rows, $querytime, $full_sql_query, isset($disp_query) ? $disp_query : null, - $cfg['ShowSQL'], isset($sql_data) ? $sql_data : null, - isset($disp_message) ? $disp_message : null - ); - - $profiling_chart_html = PMA_getHtmlForProfilingChart( - $disp_mode, $db, isset($profiling_results) ? $profiling_results : null - ); - - $missing_unique_column_msg = PMA_getMessageIfMissingColumnIndex( - $table, $db, $editable, $disp_mode - ); - - $bookmark_created_msg = PMA_getBookmarkCreatedMessage(); - - $table_html = PMA_getHtmlForSqlQueryResultsTable( - isset($sql_data) ? $sql_data : null, $displayResultsObject, $db, $goto, - $pmaThemeImage, $text_dir, $url_query, $disp_mode, $sql_limit_to_append, - $editable, $unlim_num_rows, $num_rows, $showtable, $result, $querytime, - $analyzed_sql_results, $is_procedure - ); - - $indexes_problems_html = PMA_getHtmlForIndexesProblems( + isset($disp_message) ? $disp_message : null, $profiling_results, isset($query_type) ? $query_type : null, - isset($selected) ? $selected : null + isset($selected) ? $selected : null, $sql_query, + isset($complete_query) ? $complete_query : null, $cfg ); - - $bookmark_support_html = PMA_getHtmlForBookmark( - $disp_mode, isset($cfg['Bookmark']) ? $cfg['Bookmark'] : '', $sql_query, - $db, $table, isset($complete_query) ? $complete_query : $sql_query, - $cfg['Bookmark']['user'] - ); - - $print_button_html = PMA_getHtmlForPrintButton(); - - $html_output = isset($table_maintenance_html) ? $table_maintenance_html : ''; - - $html_output .= isset($print_view_header_html) ? $print_view_header_html : ''; - - $html_output .= PMA_getHtmlForSqlQueryResults( - $previous_update_query_html, $profiling_chart_html, - $missing_unique_column_msg, $bookmark_created_msg, - $table_html, $indexes_problems_html, $bookmark_support_html, - $print_button_html - ); - - $response->addHTML($html_output); } // end rows returned ?> diff --git a/test/bootstrap-dist.php b/test/bootstrap-dist.php index 0edf05e329..95cca261bd 100644 --- a/test/bootstrap-dist.php +++ b/test/bootstrap-dist.php @@ -71,4 +71,31 @@ if (PMA_HAS_RUNKIT && $GLOBALS['runkit_internal_override']) { echo "Please install runkit and enable runkit.internal_override!\n"; } +/** + * Return the tag array to be used with assertTag by parsing + * a given HTML element + * + * @param string $elementHTML HTML for element to be parsed + * @param array $arr Additional array elements like content, parent + * + * @return array Tag array to be used with assertTag + */ +function PMA_getTagArray($elementHTML, $arr = array()) +{ + + // get attributes + preg_match_all("/\s+(.*?)\=\s*\"(.*?)\"/is", $elementHTML, $matches); + foreach ($matches[1] as $key => $val) { + $arr['attributes'][trim($val)] = trim($matches[2][$key]); + } + $matches = array(); + + // get tag + preg_match("/^\<(.*?)(\s|\>)/i", $elementHTML, $matches); + if (isset($matches[1])) { + $arr['tag'] = trim($matches[1]); + } + + return $arr; +} ?> diff --git a/test/classes/plugin/auth/PMA_AuthenticationConfig_test.php b/test/classes/plugin/auth/PMA_AuthenticationConfig_test.php new file mode 100644 index 0000000000..fe40806f77 --- /dev/null +++ b/test/classes/plugin/auth/PMA_AuthenticationConfig_test.php @@ -0,0 +1,143 @@ +enableBc(); + $GLOBALS['server'] = 0; + $this->object = new AuthenticationConfig(null); + } + + /** + * tearDown for test cases + * + * @return void + */ + public function tearDown() + { + unset($this->object); + } + + /** + * Test for AuthenticationConfig::auth + * + * @return void + */ + public function testAuth() + { + $this->assertTrue( + $this->object->auth() + ); + } + + /** + * Test for AuthenticationConfig::authCheck + * + * @return void + */ + public function testAuthCheck() + { + $this->assertTrue( + $this->object->authCheck() + ); + } + + /** + * Test for AuthenticationConfig::authSetUser + * + * @return void + */ + public function testAuthSetUser() + { + $this->assertTrue( + $this->object->authSetUser() + ); + } + + /** + * Test for AuthenticationConfig::authFails + * + * @return void + */ + public function testAuthFails() + { + $removeConstant = false; + $GLOBALS['error_handler'] = new PMA_Error_Handler; + $GLOBALS['cfg']['Servers'] = array(1); + $GLOBALS['allowDeny_forbidden'] = false; + if (!defined('PMA_USR_BROWSER_AGENT')) { + define('PMA_USR_BROWSER_AGENT', 'chrome'); + + $removeConstant = true; + + if (! PMA_HAS_RUNKIT) { + $this->markTestSkipped('Cannot remove constant'); + } + } + + ob_start(); + $result = $this->object->authFails(); + $html = ob_get_clean(); + + $this->assertTrue( + $result + ); + + $this->assertContains( + 'You probably did not create a configuration file. You might want ' . + 'to use the setup script to create one.', + $html + ); + + $this->assertContains( + 'MySQL said: ' . + 'Documentation', + $html + ); + + $this->assertContains( + 'Cannot connect: invalid settings.', + $html + ); + + $this->assertContains( + 'Retry to connect', + $html + ); + if ($removeConstant) { + runkit_constant_remove('PMA_USR_BROWSER_AGENT'); + } + } +} +?> diff --git a/test/classes/plugin/auth/PMA_AuthenticationCookie_test.php b/test/classes/plugin/auth/PMA_AuthenticationCookie_test.php new file mode 100644 index 0000000000..53e7b76bf9 --- /dev/null +++ b/test/classes/plugin/auth/PMA_AuthenticationCookie_test.php @@ -0,0 +1,1109 @@ +enableBc(); + $GLOBALS['server'] = 0; + $this->object = new AuthenticationCookie(null); + } + + /** + * tearDown for test cases + * + * @return void + */ + public function tearDown() + { + unset($this->object); + } + + /** + * Test for AuthenticationConfig::auth + * + * @return void + */ + public function testAuth() + { + $restoreInstance = PMA_Response::getInstance(); + // Case 1 + + $mockResponse = $this->getMockBuilder('PMA_Response') + ->disableOriginalConstructor() + ->setMethods(array('isAjax', 'isSuccess', 'addJSON')) + ->getMock(); + + $mockResponse->expects($this->once()) + ->method('isAjax') + ->with() + ->will($this->returnValue(true)); + + $mockResponse->expects($this->once()) + ->method('isSuccess') + ->with(false); + + $mockResponse->expects($this->once()) + ->method('addJSON') + ->with( + 'message', + PMA_Message::error( + '1

[ Log in ]' + ) + ); + + $attrInstance = new ReflectionProperty('PMA_Response', '_instance'); + $attrInstance->setAccessible(true); + $attrInstance->setValue(null, $mockResponse); + $GLOBALS['conn_error'] = true; + $GLOBALS['cfg']['PmaAbsoluteUri'] = 'https://phpmyadmin.net/'; + $this->assertTrue( + $this->object->auth() + ); + // Case 2 + + $mockResponse = $this->getMockBuilder('PMA_Response') + ->disableOriginalConstructor() + ->setMethods(array('isAjax', 'isSuccess', 'addJSON')) + ->getMock(); + + $mockResponse->expects($this->once()) + ->method('isAjax') + ->with() + ->will($this->returnValue(true)); + + $mockResponse->expects($this->once()) + ->method('isSuccess') + ->with(false); + + $mockResponse->expects($this->once()) + ->method('addJSON') + ->with( + 'message', + PMA_Message::error( + 'Your session has expired. Please log in again.' . + '

[ Log in ]' + ) + ); + + $attrInstance = new ReflectionProperty('PMA_Response', '_instance'); + $attrInstance->setAccessible(true); + $attrInstance->setValue(null, $mockResponse); + $GLOBALS['conn_error'] = ''; + + $this->assertTrue( + $this->object->auth() + ); + + // case 3 + + $mockResponse = $this->getMockBuilder('PMA_Response') + ->disableOriginalConstructor() + ->setMethods(array('isAjax', 'getFooter', 'getHeader')) + ->getMock(); + + $mockResponse->expects($this->once()) + ->method('isAjax') + ->with() + ->will($this->returnValue(false)); + + + + $_REQUEST['old_usr'] = ''; + $GLOBALS['cfg']['LoginCookieRecall'] = true; + $GLOBALS['cfg']['blowfish_secret'] = 'secret'; + $GLOBALS['PHP_AUTH_USER'] = 'pmauser'; + $GLOBALS['pma_auth_server'] = 'localhost'; + + // mock footer + $mockFooter = $this->getMockBuilder('PMA_Footer') + ->disableOriginalConstructor() + ->setMethods(array('setMinimal')) + ->getMock(); + + $mockFooter->expects($this->once()) + ->method('setMinimal') + ->with(); + + // mock header + + $mockHeader = $this->getMockBuilder('PMA_Header') + ->disableOriginalConstructor() + ->setMethods( + array('setBodyId', 'setTitle', 'disableMenu', 'disableWarnings') + ) + ->getMock(); + + $mockHeader->expects($this->once()) + ->method('setBodyId') + ->with('loginform'); + + $mockHeader->expects($this->once()) + ->method('setTitle') + ->with('phpMyAdmin'); + + $mockHeader->expects($this->once()) + ->method('disableMenu') + ->with(); + + $mockHeader->expects($this->once()) + ->method('disableWarnings') + ->with(); + + // set mocked headers and footers + + $mockResponse->expects($this->once()) + ->method('getFooter') + ->with() + ->will($this->returnValue($mockFooter)); + + $mockResponse->expects($this->once()) + ->method('getHeader') + ->with() + ->will($this->returnValue($mockHeader)); + + $attrInstance = new ReflectionProperty('PMA_Response', '_instance'); + $attrInstance->setAccessible(true); + $attrInstance->setValue(null, $mockResponse); + + $GLOBALS['pmaThemeImage'] = 'test'; + $GLOBALS['conn_error'] = true; + $GLOBALS['cfg']['Lang'] = 'en'; + $GLOBALS['cfg']['AllowArbitraryServer'] = true; + $GLOBALS['cfg']['Servers'] = array(1, 2); + $_SESSION['last_valid_captcha'] = true; + $GLOBALS['target'] = 'testTarget'; + $GLOBALS['db'] = 'testDb'; + $GLOBALS['table'] = 'testTable'; + + file_put_contents('testlogo_right.png', ''); + + // mock error handler + + $mockErrorHandler = $this->getMockBuilder('PMA_Error_Handler') + ->disableOriginalConstructor() + ->setMethods(array('hasDisplayErrors', 'dispErrors')) + ->getMock(); + + $mockErrorHandler->expects($this->once()) + ->method('hasDisplayErrors') + ->with() + ->will($this->returnValue(true)); + + $mockErrorHandler->expects($this->once()) + ->method('dispErrors') + ->with(); + + $GLOBALS['error_handler'] = $mockErrorHandler; + + ob_start(); + $this->object->auth(); + $result = ob_get_clean(); + + // assertions + + $this->assertTag( + PMA_getTagArray( + 'assertTag( + PMA_getTagArray( + '
' + ), + $result + ); + + $this->assertTag( + PMA_getTagArray( + '' + ), + $result + ); + + $this->assertTag( + PMA_getTagArray( + 'assertTag( + PMA_getTagArray( + '' + ), + $result + ); + + $this->assertTag( + PMA_getTagArray( + '' + ), + $result + ); + + $this->assertTag( + PMA_getTagArray( + '' + ), + $result + ); + + $this->assertTag( + PMA_getTagArray( + '' + ), + $result + ); + + $this->assertTag( + PMA_getTagArray( + '' + ), + $result + ); + + @unlink('testlogo_right.png'); + + // case 4 + + $mockResponse = $this->getMockBuilder('PMA_Response') + ->disableOriginalConstructor() + ->setMethods(array('isAjax', 'getFooter', 'getHeader')) + ->getMock(); + + $mockResponse->expects($this->once()) + ->method('isAjax') + ->with() + ->will($this->returnValue(false)); + + $mockResponse->expects($this->once()) + ->method('getFooter') + ->with() + ->will($this->returnValue(new PMA_Footer())); + + $mockResponse->expects($this->once()) + ->method('getHeader') + ->with() + ->will($this->returnValue(new PMA_Header())); + + $_REQUEST['old_usr'] = ''; + $GLOBALS['cfg']['LoginCookieRecall'] = false; + + $attrInstance = new ReflectionProperty('PMA_Response', '_instance'); + $attrInstance->setAccessible(true); + $attrInstance->setValue(null, $mockResponse); + + $GLOBALS['pmaThemeImage'] = 'test'; + $GLOBALS['cfg']['Lang'] = ''; + $GLOBALS['cfg']['AllowArbitraryServer'] = false; + $GLOBALS['cfg']['Servers'] = array(1); + $_SESSION['last_valid_captcha'] = false; + $GLOBALS['cfg']['CaptchaLoginPrivateKey'] = 'testprivkey'; + $GLOBALS['cfg']['CaptchaLoginPublicKey'] = 'testpubkey'; + $GLOBALS['server'] = 0; + + $GLOBALS['error_handler'] = new PMA_Error_Handler; + + ob_start(); + $this->object->auth(); + $result = ob_get_clean(); + + // assertions + + $this->assertTag( + PMA_getTagArray( + 'assertTag( + PMA_getTagArray( + '' + ), + $result + ); + + $this->assertContains( + 'src="https://www.google.com/recaptcha/api/challenge?k=testpubkey">', + $result + ); + + $this->assertContains( + 'iframe src="https://www.google.com/recaptcha/api/noscript' . + '?k=testpubkey"', + $result + ); + + $this->assertContains( + '