2 /* vim: set expandtab sw=4 ts=4 sts=4: */
11 require_once './libraries/common.inc.php';
14 * Does the common work
16 $GLOBALS['js_include'][] = 'server_privileges.js';
17 $GLOBALS['js_include'][] = 'functions.js';
18 $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js';
20 $GLOBALS['js_include'][] = 'password_generation.js';
21 require './libraries/server_common.inc.php';
24 * Messages are built using the message name
26 $strPrivDescAllPrivileges = __('Includes all privileges except GRANT.');
27 $strPrivDescAlter = __('Allows altering the structure of existing tables.');
28 $strPrivDescAlterRoutine = __('Allows altering and dropping stored routines.');
29 $strPrivDescCreateDb = __('Allows creating new databases and tables.');
30 $strPrivDescCreateRoutine = __('Allows creating stored routines.');
31 $strPrivDescCreateTbl = __('Allows creating new tables.');
32 $strPrivDescCreateTmpTable = __('Allows creating temporary tables.');
33 $strPrivDescCreateUser = __('Allows creating, dropping and renaming user accounts.');
34 $strPrivDescCreateView = __('Allows creating new views.');
35 $strPrivDescDelete = __('Allows deleting data.');
36 $strPrivDescDropDb = __('Allows dropping databases and tables.');
37 $strPrivDescDropTbl = __('Allows dropping tables.');
38 $strPrivDescEvent = __('Allows to set up events for the event scheduler');
39 $strPrivDescExecute = __('Allows executing stored routines.');
40 $strPrivDescFile = __('Allows importing data from and exporting data into files.');
41 $strPrivDescGrant = __('Allows adding users and privileges without reloading the privilege tables.');
42 $strPrivDescIndex = __('Allows creating and dropping indexes.');
43 $strPrivDescInsert = __('Allows inserting and replacing data.');
44 $strPrivDescLockTables = __('Allows locking tables for the current thread.');
45 $strPrivDescMaxConnections = __('Limits the number of new connections the user may open per hour.');
46 $strPrivDescMaxQuestions = __('Limits the number of queries the user may send to the server per hour.');
47 $strPrivDescMaxUpdates = __('Limits the number of commands that change any table or database the user may execute per hour.');
48 $strPrivDescMaxUserConnections = __('Limits the number of simultaneous connections the user may have.');
49 $strPrivDescProcess = __('Allows viewing processes of all users');
50 $strPrivDescReferences = __('Has no effect in this MySQL version.');
51 $strPrivDescReload = __('Allows reloading server settings and flushing the server\'s caches.');
52 $strPrivDescReplClient = __('Allows the user to ask where the slaves / masters are.');
53 $strPrivDescReplSlave = __('Needed for the replication slaves.');
54 $strPrivDescSelect = __('Allows reading data.');
55 $strPrivDescShowDb = __('Gives access to the complete list of databases.');
56 $strPrivDescShowView = __('Allows performing SHOW CREATE VIEW queries.');
57 $strPrivDescShutdown = __('Allows shutting down the server.');
58 $strPrivDescSuper = __('Allows connecting, even if maximum number of connections is reached; required for most administrative operations like setting global variables or killing threads of other users.');
59 $strPrivDescTrigger = __('Allows creating and dropping triggers');
60 $strPrivDescUpdate = __('Allows changing data.');
61 $strPrivDescUsage = __('No privileges.');
64 * Checks if a dropdown box has been used for selecting a database / table
66 if (PMA_isValid($_REQUEST['pred_tablename'])) {
67 $tablename = $_REQUEST['pred_tablename'];
68 unset($pred_tablename);
69 } elseif (PMA_isValid($_REQUEST['tablename'])) {
70 $tablename = $_REQUEST['tablename'];
75 if (PMA_isValid($_REQUEST['pred_dbname'])) {
76 $dbname = $_REQUEST['pred_dbname'];
78 } elseif (PMA_isValid($_REQUEST['dbname'])) {
79 $dbname = $_REQUEST['dbname'];
86 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
87 if (isset($tablename)) {
88 $db_and_table .= PMA_backquote($tablename);
93 $db_and_table = '*.*';
96 // check if given $dbname is a wildcard or not
98 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
99 if (preg_match('/(?<!\\\\)(?:_|%)/i', $dbname)) {
100 $dbname_is_wildcard = true;
102 $dbname_is_wildcard = false;
107 * Checks if the user is allowed to do what he tries to...
109 if (!$is_superuser) {
110 require './libraries/server_links.inc.php';
112 . PMA_getIcon('b_usrlist.png')
113 . __('Privileges') . "\n"
115 PMA_Message
::error(__('No Privileges'))->display();
116 require './libraries/footer.inc.php';
120 * Escapes wildcard in a database+table specification
121 * before using it in a GRANT statement.
123 * Escaping a wildcard character in a GRANT is only accepted at the global
124 * or database level, not at table level; this is why I remove
125 * the escaping character. Internally, in mysql.tables_priv.Db there are
126 * no escaping (for example test_db) but in mysql.db you'll see test\_db
127 * for a db-specific privilege.
129 * @param string $db_and_table
130 * @param string $dbname
131 * @param string $tablename
132 * @return string the escaped (if necessary) $db_and_table
134 function PMA_WildcardEscapeForGrant($db_and_table, $dbname, $tablename) {
136 if (! strlen($dbname)) {
137 $db_and_table = '*.*';
139 if (strlen($tablename)) {
140 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
141 $db_and_table .= PMA_backquote($tablename);
143 $db_and_table = PMA_backquote($dbname) . '.';
144 $db_and_table .= '*';
147 return $db_and_table;
151 * Generates a condition on the user name
153 * @param string the user's initial
154 * @return string the generated condition
156 function PMA_RangeOfUsers($initial = '')
158 // strtolower() is used because the User field
159 // might be BINARY, so LIKE would be case sensitive
160 if (!empty($initial)) {
161 $ret = " WHERE `User` LIKE '" . $initial . "%'"
162 . " OR `User` LIKE '" . strtolower($initial) . "%'";
170 * Extracts the privilege information of a priv table row
172 * @param array $row the row
173 * @param boolean $enableHTML add <dfn> tag with tooltips
175 * @global ressource $user_link the database connection
179 function PMA_extractPrivInfo($row = '', $enableHTML = FALSE)
182 array('Select_priv', 'SELECT', __('Allows reading data.')),
183 array('Insert_priv', 'INSERT', __('Allows inserting and replacing data.')),
184 array('Update_priv', 'UPDATE', __('Allows changing data.')),
185 array('Delete_priv', 'DELETE', __('Allows deleting data.')),
186 array('Create_priv', 'CREATE', __('Allows creating new databases and tables.')),
187 array('Drop_priv', 'DROP', __('Allows dropping databases and tables.')),
188 array('Reload_priv', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.')),
189 array('Shutdown_priv', 'SHUTDOWN', __('Allows shutting down the server.')),
190 array('Process_priv', 'PROCESS', __('Allows viewing processes of all users')),
191 array('File_priv', 'FILE', __('Allows importing data from and exporting data into files.')),
192 array('References_priv', 'REFERENCES', __('Has no effect in this MySQL version.')),
193 array('Index_priv', 'INDEX', __('Allows creating and dropping indexes.')),
194 array('Alter_priv', 'ALTER', __('Allows altering the structure of existing tables.')),
195 array('Show_db_priv', 'SHOW DATABASES', __('Gives access to the complete list of databases.')),
196 array('Super_priv', 'SUPER', __('Allows connecting, even if maximum number of connections is reached; required for most administrative operations like setting global variables or killing threads of other users.')),
197 array('Create_tmp_table_priv', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
198 array('Lock_tables_priv', 'LOCK TABLES', __('Allows locking tables for the current thread.')),
199 array('Repl_slave_priv', 'REPLICATION SLAVE', __('Needed for the replication slaves.')),
200 array('Repl_client_priv', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.')),
201 array('Create_view_priv', 'CREATE VIEW', __('Allows creating new views.')),
202 array('Event_priv', 'EVENT', __('Allows to set up events for the event scheduler')),
203 array('Trigger_priv', 'TRIGGER', __('Allows creating and dropping triggers')),
205 array('Create View_priv', 'CREATE VIEW', __('Allows creating new views.')),
206 array('Show_view_priv', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
208 array('Show view_priv', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
209 array('Create_routine_priv', 'CREATE ROUTINE', __('Allows creating stored routines.')),
210 array('Alter_routine_priv', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
211 array('Create_user_priv', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.')),
212 array('Execute_priv', 'EXECUTE', __('Allows executing stored routines.')),
215 if (!empty($row) && isset($row['Table_priv'])) {
216 $row1 = PMA_DBI_fetch_single_row(
217 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
218 'ASSOC', $GLOBALS['userlink']);
219 $av_grants = explode('\',\'', substr($row1['Type'], 5, strlen($row1['Type']) - 7));
221 $users_grants = explode(',', $row['Table_priv']);
222 foreach ($av_grants as $current_grant) {
223 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ?
'Y' : 'N';
225 unset($current_grant);
227 unset($users_grants);
230 $allPrivileges = TRUE;
231 foreach ($grants as $current_grant) {
232 if ((!empty($row) && isset($row[$current_grant[0]]))
233 ||
(empty($row) && isset($GLOBALS[$current_grant[0]]))) {
234 if ((!empty($row) && $row[$current_grant[0]] == 'Y')
236 && ($GLOBALS[$current_grant[0]] == 'Y'
237 ||
(is_array($GLOBALS[$current_grant[0]])
238 && count($GLOBALS[$current_grant[0]]) == $GLOBALS['column_count']
239 && empty($GLOBALS[$current_grant[0] . '_none'])))))
242 $privs[] = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
244 $privs[] = $current_grant[1];
246 } elseif (!empty($GLOBALS[$current_grant[0]])
247 && is_array($GLOBALS[$current_grant[0]])
248 && empty($GLOBALS[$current_grant[0] . '_none'])) {
250 $priv_string = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
252 $priv_string = $current_grant[1];
254 $privs[] = $priv_string . ' (`' . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
256 $allPrivileges = FALSE;
262 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
266 } elseif ($allPrivileges && (!isset($GLOBALS['grant_count']) ||
count($privs) == $GLOBALS['grant_count'])) {
268 $privs = array('<dfn title="' . __('Includes all privileges except GRANT.') . '">ALL PRIVILEGES</dfn>');
270 $privs = array('ALL PRIVILEGES');
274 } // end of the 'PMA_extractPrivInfo()' function
277 * Displays on which column(s) a table-specific privilege is granted
279 function PMA_display_column_privs($columns, $row, $name_for_select,
280 $priv_for_header, $name, $name_for_dfn, $name_for_current)
282 echo ' <div class="item" id="div_item_' . $name . '">' . "\n"
283 . ' <label for="select_' . $name . '_priv">' . "\n"
284 . ' <tt><dfn title="' . $name_for_dfn . '">'
285 . $priv_for_header . '</dfn></tt>' . "\n"
286 . ' </label><br />' . "\n"
287 . ' <select id="select_' . $name . '_priv" name="'
288 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
290 foreach ($columns as $current_column => $current_column_privileges) {
291 echo ' <option value="' . htmlspecialchars($current_column) . '"';
292 if ($row[$name_for_select] == 'Y' ||
$current_column_privileges[$name_for_current]) {
293 echo ' selected="selected"';
295 echo '>' . htmlspecialchars($current_column) . '</option>' . "\n";
298 echo ' </select>' . "\n"
299 . ' <i>' . __('Or') . '</i>' . "\n"
300 . ' <label for="checkbox_' . $name_for_select
301 . '_none"><input type="checkbox"'
302 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
303 . ' name="' . $name_for_select . '_none" id="checkbox_'
304 . $name_for_select . '_none" title="' . _pgettext('None privileges', 'None') . '" />'
305 . _pgettext('None privileges', 'None') . '</label>' . "\n"
311 * Displays the privileges form table
313 * @param string $db the database
314 * @param string $table the table
315 * @param boolean $submit wheather to display the submit button or not
316 * @global array $cfg the phpMyAdmin configuration
317 * @global ressource $user_link the database connection
321 function PMA_displayPrivTable($db = '*', $table = '*', $submit = TRUE)
327 if (isset($GLOBALS['username'])) {
328 $username = $GLOBALS['username'];
329 $hostname = $GLOBALS['hostname'];
332 "SELECT * FROM `mysql`.`user`"
333 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
334 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
335 } elseif ($table == '*') {
337 "SELECT * FROM `mysql`.`db`"
338 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
339 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "'"
340 ." AND '" . PMA_unescape_mysql_wildcards($db) . "'"
344 "SELECT `Table_priv`"
345 ." FROM `mysql`.`tables_priv`"
346 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
347 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "'"
348 ." AND `Db` = '" . PMA_unescape_mysql_wildcards($db) . "'"
349 ." AND `Table_name` = '" . PMA_sqlAddslashes($table) . "';";
351 $row = PMA_DBI_fetch_single_row($sql_query);
356 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
357 } elseif ($table == '*') {
358 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
360 $res = PMA_DBI_query($sql_query);
361 while ($row1 = PMA_DBI_fetch_row($res)) {
362 if (substr($row1[0], 0, 4) == 'max_') {
365 $row[$row1[0]] = 'N';
368 PMA_DBI_free_result($res);
370 $row = array('Table_priv' => '');
373 if (isset($row['Table_priv'])) {
374 $row1 = PMA_DBI_fetch_single_row(
375 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
376 'ASSOC', $GLOBALS['userlink']);
377 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
378 // the View for Create is spelled with uppercase V
379 // the view for Show is spelled with lowercase v
380 // and there is a space between the words
382 $av_grants = explode('\',\'', substr($row1['Type'], strpos($row1['Type'], '(') +
2, strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3));
384 $users_grants = explode(',', $row['Table_priv']);
386 foreach ($av_grants as $current_grant) {
387 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ?
'Y' : 'N';
389 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
392 $res = PMA_DBI_try_query('SHOW COLUMNS FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($db)) . '.' . PMA_backquote($table) . ';');
395 while ($row1 = PMA_DBI_fetch_row($res)) {
396 $columns[$row1[0]] = array(
400 'References' => FALSE
403 PMA_DBI_free_result($res);
407 // t a b l e - s p e c i f i c p r i v i l e g e s
408 if (! empty($columns)) {
409 $res = PMA_DBI_query(
410 'SELECT `Column_name`, `Column_priv`'
411 .' FROM `mysql`.`columns_priv`'
413 .' = \'' . PMA_sqlAddslashes($username) . "'"
415 .' = \'' . PMA_sqlAddslashes($hostname) . "'"
417 .' = \'' . PMA_sqlAddslashes(PMA_unescape_mysql_wildcards($db)) . "'"
419 .' = \'' . PMA_sqlAddslashes($table) . '\';');
421 while ($row1 = PMA_DBI_fetch_row($res)) {
422 $row1[1] = explode(',', $row1[1]);
423 foreach ($row1[1] as $current) {
424 $columns[$row1[0]][$current] = TRUE;
427 PMA_DBI_free_result($res);
428 unset($res, $row1, $current);
430 echo '<input type="hidden" name="grant_count" value="' . count($row) . '" />' . "\n"
431 . '<input type="hidden" name="column_count" value="' . count($columns) . '" />' . "\n"
432 . '<fieldset id="fieldset_user_priv">' . "\n"
433 . ' <legend>' . __('Table-specific privileges')
434 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English '))
435 . '</legend>' . "\n";
439 // privs that are attached to a specific column
440 PMA_display_column_privs($columns, $row, 'Select_priv',
441 'SELECT', 'select', __('Allows reading data.'), 'Select');
443 PMA_display_column_privs($columns, $row, 'Insert_priv',
444 'INSERT', 'insert', __('Allows inserting and replacing data.'), 'Insert');
446 PMA_display_column_privs($columns, $row, 'Update_priv',
447 'UPDATE', 'update', __('Allows changing data.'), 'Update');
449 PMA_display_column_privs($columns, $row, 'References_priv',
450 'REFERENCES', 'references', __('Has no effect in this MySQL version.'), 'References');
452 // privs that are not attached to a specific column
454 echo ' <div class="item">' . "\n";
455 foreach ($row as $current_grant => $current_grant_value) {
456 if (in_array(substr($current_grant, 0, (strlen($current_grant) - 5)),
457 array('Select', 'Insert', 'Update', 'References'))) {
460 // make a substitution to match the messages variables;
461 // also we must substitute the grant we get, because we can't generate
462 // a form variable containing blanks (those would get changed to
463 // an underscore when receiving the POST)
464 if ($current_grant == 'Create View_priv') {
465 $tmp_current_grant = 'CreateView_priv';
466 $current_grant = 'Create_view_priv';
467 } elseif ($current_grant == 'Show view_priv') {
468 $tmp_current_grant = 'ShowView_priv';
469 $current_grant = 'Show_view_priv';
471 $tmp_current_grant = $current_grant;
474 echo ' <div class="item">' . "\n"
475 . ' <input type="checkbox"'
476 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
477 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
479 . ($current_grant_value == 'Y' ?
'checked="checked" ' : '')
482 echo (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
483 ?
$GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
484 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl']) . '"/>' . "\n";
486 echo ' <label for="checkbox_' . $current_grant
487 . '"><tt><dfn title="'
488 . (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
489 ?
$GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
490 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl'])
491 . '">' . strtoupper(substr($current_grant, 0, strlen($current_grant) - 5)) . '</dfn></tt></label>' . "\n"
495 echo ' </div>' . "\n";
497 echo ' <div class="clearfloat"></div>' . "\n";
501 // g l o b a l o r d b - s p e c i f i c
504 $privTable[0] = array(
505 array('Select', 'SELECT', __('Allows reading data.')),
506 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
507 array('Update', 'UPDATE', __('Allows changing data.')),
508 array('Delete', 'DELETE', __('Allows deleting data.'))
511 $privTable[0][] = array('File', 'FILE', __('Allows importing data from and exporting data into files.'));
515 $privTable[1] = array(
516 array('Create', 'CREATE', ($table == '*' ?
__('Allows creating new databases and tables.') : __('Allows creating new tables.'))),
517 array('Alter', 'ALTER', __('Allows altering the structure of existing tables.')),
518 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
519 array('Drop', 'DROP', ($table == '*' ?
__('Allows dropping databases and tables.') : __('Allows dropping tables.'))),
520 array('Create_tmp_table', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
521 array('Show_view', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
522 array('Create_routine', 'CREATE ROUTINE', __('Allows creating stored routines.')),
523 array('Alter_routine', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
524 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
526 // this one is for a db-specific priv: Create_view_priv
527 if (isset($row['Create_view_priv'])) {
528 $privTable[1][] = array('Create_view', 'CREATE VIEW', __('Allows creating new views.'));
530 // this one is for a table-specific priv: Create View_priv
531 if (isset($row['Create View_priv'])) {
532 $privTable[1][] = array('Create View', 'CREATE VIEW', __('Allows creating new views.'));
534 if (isset($row['Event_priv'])) {
536 $privTable[1][] = array('Event', 'EVENT', __('Allows to set up events for the event scheduler'));
537 $privTable[1][] = array('Trigger', 'TRIGGER', __('Allows creating and dropping triggers'));
540 // a d m i n i s t r a t i o n
541 $privTable[2] = array(
542 array('Grant', 'GRANT', __('Allows adding users and privileges without reloading the privilege tables.')),
545 $privTable[2][] = array('Super', 'SUPER', __('Allows connecting, even if maximum number of connections is reached; required for most administrative operations like setting global variables or killing threads of other users.'));
546 $privTable[2][] = array('Process', 'PROCESS', __('Allows viewing processes of all users'));
547 $privTable[2][] = array('Reload', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.'));
548 $privTable[2][] = array('Shutdown', 'SHUTDOWN', __('Allows shutting down the server.'));
549 $privTable[2][] = array('Show_db', 'SHOW DATABASES', __('Gives access to the complete list of databases.'));
551 $privTable[2][] = array('Lock_tables', 'LOCK TABLES', __('Allows locking tables for the current thread.'));
552 $privTable[2][] = array('References', 'REFERENCES', __('Has no effect in this MySQL version.'));
554 $privTable[2][] = array('Repl_client', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.'));
555 $privTable[2][] = array('Repl_slave', 'REPLICATION SLAVE', __('Needed for the replication slaves.'));
556 $privTable[2][] = array('Create_user', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.'));
558 echo '<input type="hidden" name="grant_count" value="'
559 . (count($privTable[0]) +
count($privTable[1]) +
count($privTable[2]) - (isset($row['Grant_priv']) ?
1 : 0))
561 . '<fieldset id="fieldset_user_global_rights">' . "\n"
565 ?
__('Global privileges')
567 ?
__('Database-specific privileges')
568 : __('Table-specific privileges'))) . "\n"
569 . ' (<a href="server_privileges.php?'
570 . $GLOBALS['url_query'] . '&checkall=1" onclick="setCheckboxes(\'addUsersForm\', true); return false;">'
571 . __('Check All') . '</a> /' . "\n"
572 . ' <a href="server_privileges.php?'
573 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'addUsersForm\', false); return false;">'
574 . __('Uncheck All') . '</a>)' . "\n"
575 . ' </legend>' . "\n"
576 . ' <p><small><i>' . __(' Note: MySQL privilege names are expressed in English ') . '</i></small></p>' . "\n"
577 . ' <fieldset>' . "\n"
578 . ' <legend>' . __('Data') . '</legend>' . "\n";
579 foreach ($privTable[0] as $priv)
581 echo ' <div class="item">' . "\n"
582 . ' <input type="checkbox"'
583 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
584 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
585 . '_priv" value="Y" '
586 . ($row[$priv[0] . '_priv'] == 'Y' ?
'checked="checked" ' : '')
587 . 'title="' . $priv[2] . '"/>' . "\n"
588 . ' <label for="checkbox_' . $priv[0]
589 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
590 . '</dfn></tt></label>' . "\n"
593 echo ' </fieldset>' . "\n"
594 . ' <fieldset>' . "\n"
595 . ' <legend>' . __('Structure') . '</legend>' . "\n";
596 foreach ($privTable[1] as $priv)
598 echo ' <div class="item">' . "\n"
599 . ' <input type="checkbox"'
600 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
601 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
602 . '_priv" value="Y" '
603 . ($row[$priv[0] . '_priv'] == 'Y' ?
'checked="checked" ' : '')
604 . 'title="' . $priv[2] . '"/>' . "\n"
605 . ' <label for="checkbox_' . $priv[0]
606 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
607 . '</dfn></tt></label>' . "\n"
610 echo ' </fieldset>' . "\n"
611 . ' <fieldset>' . "\n"
612 . ' <legend>' . __('Administration') . '</legend>' . "\n";
613 foreach ($privTable[2] as $priv)
615 echo ' <div class="item">' . "\n"
616 . ' <input type="checkbox"'
617 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
618 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
619 . '_priv" value="Y" '
620 . ($row[$priv[0] . '_priv'] == 'Y' ?
'checked="checked" ' : '')
621 . 'title="' . $priv[2] . '"/>' . "\n"
622 . ' <label for="checkbox_' . $priv[0]
623 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
624 . '</dfn></tt></label>' . "\n"
628 echo ' </fieldset>' . "\n";
629 // The "Resource limits" box is not displayed for db-specific privs
631 echo ' <fieldset>' . "\n"
632 . ' <legend>' . __('Resource limits') . '</legend>' . "\n"
633 . ' <p><small><i>' . __('Note: Setting these options to 0 (zero) removes the limit.') . '</i></small></p>' . "\n"
634 . ' <div class="item">' . "\n"
635 . ' <label for="text_max_questions"><tt><dfn title="'
636 . __('Limits the number of queries the user may send to the server per hour.') . '">MAX QUERIES PER HOUR</dfn></tt></label>' . "\n"
637 . ' <input type="text" name="max_questions" id="text_max_questions" value="'
638 . $row['max_questions'] . '" size="11" maxlength="11" title="' . __('Limits the number of queries the user may send to the server per hour.') . '" />' . "\n"
640 . ' <div class="item">' . "\n"
641 . ' <label for="text_max_updates"><tt><dfn title="'
642 . __('Limits the number of commands that change any table or database the user may execute per hour.') . '">MAX UPDATES PER HOUR</dfn></tt></label>' . "\n"
643 . ' <input type="text" name="max_updates" id="text_max_updates" value="'
644 . $row['max_updates'] . '" size="11" maxlength="11" title="' . __('Limits the number of commands that change any table or database the user may execute per hour.') . '" />' . "\n"
646 . ' <div class="item">' . "\n"
647 . ' <label for="text_max_connections"><tt><dfn title="'
648 . __('Limits the number of new connections the user may open per hour.') . '">MAX CONNECTIONS PER HOUR</dfn></tt></label>' . "\n"
649 . ' <input type="text" name="max_connections" id="text_max_connections" value="'
650 . $row['max_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of new connections the user may open per hour.') . '" />' . "\n"
652 . ' <div class="item">' . "\n"
653 . ' <label for="text_max_user_connections"><tt><dfn title="'
654 . __('Limits the number of simultaneous connections the user may have.') . '">MAX USER_CONNECTIONS</dfn></tt></label>' . "\n"
655 . ' <input type="text" name="max_user_connections" id="text_max_user_connections" value="'
656 . $row['max_user_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of simultaneous connections the user may have.') . '" />' . "\n"
658 . ' </fieldset>' . "\n";
661 echo ' <div class="clearfloat"></div>' . "\n";
663 echo '</fieldset>' . "\n";
665 echo '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">' . "\n"
666 . ' <input type="submit" name="update_privs" value="' . __('Go') . '" />' . "\n"
667 . '</fieldset>' . "\n";
669 } // end of the 'PMA_displayPrivTable()' function
673 * Displays the fields used by the "new user" form as well as the
674 * "change login information / copy user" form.
676 * @param string $mode are we creating a new user or are we just
677 * changing one? (allowed values: 'new', 'change')
678 * @global array $cfg the phpMyAdmin configuration
679 * @global ressource $user_link the database connection
683 function PMA_displayLoginInformationFields($mode = 'new')
685 // Get user/host name lengths
686 $fields_info = PMA_DBI_get_fields('mysql', 'user');
687 $username_length = 16;
688 $hostname_length = 41;
689 foreach ($fields_info as $key => $val) {
690 if ($val['Field'] == 'User') {
691 strtok($val['Type'], '()');
694 $username_length = $v;
696 } elseif ($val['Field'] == 'Host') {
697 strtok($val['Type'], '()');
700 $hostname_length = $v;
706 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
707 $GLOBALS['pred_username'] = 'any';
709 echo '<fieldset id="fieldset_add_user_login">' . "\n"
710 . '<legend>' . __('Login Information') . '</legend>' . "\n"
711 . '<div class="item">' . "\n"
712 . '<label for="select_pred_username">' . "\n"
713 . ' ' . __('User name') . ':' . "\n"
715 . '<span class="options">' . "\n"
716 . ' <select name="pred_username" id="select_pred_username" title="' . __('User name') . '"' . "\n"
717 . ' onchange="if (this.value == \'any\') { username.value = \'\'; } else if (this.value == \'userdefined\') { username.focus(); username.select(); }">' . "\n"
718 . ' <option value="any"' . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any') ?
' selected="selected"' : '') . '>' . __('Any user') . '</option>' . "\n"
719 . ' <option value="userdefined"' . ((!isset($GLOBALS['pred_username']) ||
$GLOBALS['pred_username'] == 'userdefined') ?
' selected="selected"' : '') . '>' . __('Use text field') . ':</option>' . "\n"
720 . ' </select>' . "\n"
722 . '<input type="text" name="username" maxlength="'
723 . $username_length . '" title="' . __('User name') . '"'
724 . (empty($GLOBALS['username'])
726 : ' value="' . htmlspecialchars(isset($GLOBALS['new_username'])
727 ?
$GLOBALS['new_username']
728 : $GLOBALS['username']) . '"')
729 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
731 . '<div class="item">' . "\n"
732 . '<label for="select_pred_hostname">' . "\n"
733 . ' ' . __('Host') . ':' . "\n"
735 . '<span class="options">' . "\n"
736 . ' <select name="pred_hostname" id="select_pred_hostname" title="' . __('Host') . '"' . "\n";
737 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
738 if (! empty($_current_user)) {
739 $thishost = str_replace("'", '', substr($_current_user, (strrpos($_current_user, '@') +
1)));
740 if ($thishost == 'localhost' ||
$thishost == '127.0.0.1') {
744 echo ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } else if (this.value == \'localhost\') { hostname.value = \'localhost\'; } '
745 . (empty($thishost) ?
'' : 'else if (this.value == \'thishost\') { hostname.value = \'' . addslashes(htmlspecialchars($thishost)) . '\'; } ')
746 . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } else if (this.value == \'userdefined\') { hostname.focus(); hostname.select(); }">' . "\n";
747 unset($_current_user);
749 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
750 if (!isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
751 switch (strtolower($GLOBALS['hostname'])) {
754 $GLOBALS['pred_hostname'] = 'localhost';
757 $GLOBALS['pred_hostname'] = 'any';
760 $GLOBALS['pred_hostname'] = 'userdefined';
764 echo ' <option value="any"'
765 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
766 ?
' selected="selected"' : '') . '>' . __('Any host')
768 . ' <option value="localhost"'
769 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'localhost')
770 ?
' selected="selected"' : '') . '>' . __('Local')
771 . '</option>' . "\n";
772 if (!empty($thishost)) {
773 echo ' <option value="thishost"'
774 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'thishost')
775 ?
' selected="selected"' : '') . '>' . __('This Host')
776 . '</option>' . "\n";
779 echo ' <option value="hosttable"'
780 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'hosttable')
781 ?
' selected="selected"' : '') . '>' . __('Use Host Table')
783 . ' <option value="userdefined"'
784 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'userdefined')
785 ?
' selected="selected"' : '')
786 . '>' . __('Use text field') . ':</option>' . "\n"
787 . ' </select>' . "\n"
789 . '<input type="text" name="hostname" maxlength="'
790 . $hostname_length . '" value="'
791 . htmlspecialchars(isset($GLOBALS['hostname']) ?
$GLOBALS['hostname'] : '')
792 . '" title="' . __('Host')
793 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
794 . PMA_showHint(__('When Host table is used, this field is ignored and values stored in Host table are used instead.'))
796 . '<div class="item">' . "\n"
797 . '<label for="select_pred_password">' . "\n"
798 . ' ' . __('Password') . ':' . "\n"
800 . '<span class="options">' . "\n"
801 . ' <select name="pred_password" id="select_pred_password" title="'
802 . __('Password') . '"' . "\n"
803 . ' onchange="if (this.value == \'none\') { pma_pw.value = \'\'; pma_pw2.value = \'\'; } else if (this.value == \'userdefined\') { pma_pw.focus(); pma_pw.select(); }">' . "\n"
804 . ($mode == 'change' ?
' <option value="keep" selected="selected">' . __('Do not change the password') . '</option>' . "\n" : '')
805 . ' <option value="none"';
806 if (isset($GLOBALS['username']) && $mode != 'change') {
807 echo ' selected="selected"';
809 echo '>' . __('No Password') . '</option>' . "\n"
810 . ' <option value="userdefined"' . (isset($GLOBALS['username']) ?
'' : ' selected="selected"') . '>' . __('Use text field') . ':</option>' . "\n"
811 . ' </select>' . "\n"
813 . '<input type="password" id="text_pma_pw" name="pma_pw" title="' . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
815 . '<div class="item" id="div_element_before_generate_password">' . "\n"
816 . '<label for="text_pma_pw2">' . "\n"
817 . ' ' . __('Re-type') . ':' . "\n"
819 . '<span class="options"> </span>' . "\n"
820 . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="' . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
822 // Generate password added here via jQuery
823 . '</fieldset>' . "\n";
824 } // end of the 'PMA_displayUserAndHostFields()' function
827 * Changes / copies a user, part I
829 if (isset($_REQUEST['change_copy'])) {
830 $user_host_condition =
832 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
834 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\';';
835 $row = PMA_DBI_fetch_single_row('SELECT * FROM `mysql`.`user` ' . $user_host_condition);
837 PMA_Message
::notice(__('No user found.'))->display();
838 unset($_REQUEST['change_copy']);
840 extract($row, EXTR_OVERWRITE
);
841 // Recent MySQL versions have the field "Password" in mysql.user,
842 // so the previous extract creates $Password but this script
844 if (!isset($password) && isset($Password)) {
845 $password = $Password;
854 * (Changes / copies a user, part II)
856 if (isset($_REQUEST['adduser_submit']) ||
isset($_REQUEST['change_copy'])) {
858 if ($pred_username == 'any') {
861 switch ($pred_hostname) {
866 $hostname = 'localhost';
872 $_user_name = PMA_DBI_fetch_value('SELECT USER()');
873 $hostname = substr($_user_name, (strrpos($_user_name, '@') +
1));
877 $sql = "SELECT '1' FROM `mysql`.`user`"
878 . " WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
879 . " AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
880 if (PMA_DBI_fetch_value($sql) == 1) {
881 $message = PMA_Message
::error(__('The user %s already exists!'));
882 $message->addParam('[i]\'' . $username . '\'@\'' . $hostname . '\'[/i]');
883 $_REQUEST['adduser'] = true;
886 $create_user_real = 'CREATE USER \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
889 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
890 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
891 if ($pred_password != 'none' && $pred_password != 'keep') {
892 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
893 $real_sql_query .= ' IDENTIFIED BY \'' . PMA_sqlAddslashes($pma_pw) . '\'';
894 if (isset($create_user_real)) {
895 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
896 $create_user_real .= ' IDENTIFIED BY \'' . PMA_sqlAddslashes($pma_pw) . '\'';
899 if ($pred_password == 'keep' && !empty($password)) {
900 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
901 if (isset($create_user_real)) {
902 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
905 $sql_query = $real_sql_query;
906 if (isset($create_user_real)) {
907 $create_user_show = $create_user_real;
911 * @todo similar code appears twice in this script
913 if ((isset($Grant_priv) && $Grant_priv == 'Y')
914 ||
(isset($max_questions) ||
isset($max_connections)
915 ||
isset($max_updates) ||
isset($max_user_connections))) {
916 $real_sql_query .= ' WITH';
917 $sql_query .= ' WITH';
918 if (isset($Grant_priv) && $Grant_priv == 'Y') {
919 $real_sql_query .= ' GRANT OPTION';
920 $sql_query .= ' GRANT OPTION';
922 if (isset($max_questions)) {
923 // avoid negative values
924 $max_questions = max(0, (int)$max_questions);
925 $real_sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
926 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
928 if (isset($max_connections)) {
929 $max_connections = max(0, (int)$max_connections);
930 $real_sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
931 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
933 if (isset($max_updates)) {
934 $max_updates = max(0, (int)$max_updates);
935 $real_sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
936 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
938 if (isset($max_user_connections)) {
939 $max_user_connections = max(0, (int)$max_user_connections);
940 $real_sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
941 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
944 if (isset($create_user_real)) {
945 $create_user_real .= ';';
946 $create_user_show .= ';';
948 $real_sql_query .= ';';
950 if (empty($_REQUEST['change_copy'])) {
953 if (isset($create_user_real)) {
954 if (! PMA_DBI_try_query($create_user_real)) {
957 $sql_query = $create_user_show . $sql_query;
960 if ($_error ||
! PMA_DBI_try_query($real_sql_query)) {
961 $_REQUEST['createdb'] = false;
962 $message = PMA_Message
::rawError(PMA_DBI_getError());
964 $message = PMA_Message
::success(__('You have added a new user.'));
967 switch (PMA_ifSetOr($_REQUEST['createdb'], '0')) {
969 // Create database with same name and grant all privileges
970 $q = 'CREATE DATABASE IF NOT EXISTS '
971 . PMA_backquote(PMA_sqlAddslashes($username)) . ';';
973 if (! PMA_DBI_try_query($q)) {
974 $message = PMA_Message
::rawError(PMA_DBI_getError());
980 * If we are not in an Ajax request, we can't reload navigation now
982 if($GLOBALS['is_ajax_request'] != true) {
983 // this is needed in case tracking is on:
984 $GLOBALS['db'] = $username;
985 $GLOBALS['reload'] = TRUE;
986 PMA_reloadNavigation();
989 $q = 'GRANT ALL PRIVILEGES ON '
990 . PMA_backquote(PMA_sqlAddslashes($username)) . '.* TO \''
991 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
993 if (! PMA_DBI_try_query($q)) {
994 $message = PMA_Message
::rawError(PMA_DBI_getError());
998 // Grant all privileges on wildcard name (username\_%)
999 $q = 'GRANT ALL PRIVILEGES ON '
1000 . PMA_backquote(PMA_sqlAddslashes($username) . '\_%') . '.* TO \''
1001 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1003 if (! PMA_DBI_try_query($q)) {
1004 $message = PMA_Message
::rawError(PMA_DBI_getError());
1008 // Grant all privileges on the specified database to the new user
1009 $q = 'GRANT ALL PRIVILEGES ON '
1010 . PMA_backquote(PMA_sqlAddslashes($dbname)) . '.* TO \''
1011 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1013 if (! PMA_DBI_try_query($q)) {
1014 $message = PMA_Message
::rawError(PMA_DBI_getError());
1022 if (isset($create_user_real)) {
1023 $queries[] = $create_user_real;
1025 $queries[] = $real_sql_query;
1026 // we put the query containing the hidden password in
1027 // $queries_for_display, at the same position occupied
1028 // by the real query in $queries
1029 $tmp_count = count($queries);
1030 if (isset($create_user_real)) {
1031 $queries_for_display[$tmp_count - 2] = $create_user_show;
1033 $queries_for_display[$tmp_count - 1] = $sql_query;
1035 unset($res, $real_sql_query);
1041 * Changes / copies a user, part III
1043 if (isset($_REQUEST['change_copy'])) {
1044 $user_host_condition =
1046 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1048 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\';';
1049 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1050 while ($row = PMA_DBI_fetch_assoc($res)) {
1052 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1053 .' ON ' . PMA_backquote($row['Db']) . '.*'
1054 .' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1055 . ($row['Grant_priv'] == 'Y' ?
' WITH GRANT OPTION;' : ';');
1057 PMA_DBI_free_result($res);
1058 $res = PMA_DBI_query(
1059 'SELECT `Db`, `Table_name`, `Table_priv`'
1060 .' FROM `mysql`.`tables_priv`' . $user_host_condition,
1061 $GLOBALS['userlink'], PMA_DBI_QUERY_STORE
);
1062 while ($row = PMA_DBI_fetch_assoc($res)) {
1064 $res2 = PMA_DBI_QUERY(
1065 'SELECT `Column_name`, `Column_priv`'
1066 .' FROM `mysql`.`columns_priv`'
1068 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1070 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\''
1072 .' = \'' . PMA_sqlAddslashes($row['Db']) . "'"
1073 .' AND `Table_name`'
1074 .' = \'' . PMA_sqlAddslashes($row['Table_name']) . "'"
1076 null, PMA_DBI_QUERY_STORE
);
1078 $tmp_privs1 = PMA_extractPrivInfo($row);
1079 $tmp_privs2 = array(
1080 'Select' => array(),
1081 'Insert' => array(),
1082 'Update' => array(),
1083 'References' => array()
1086 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1087 $tmp_array = explode(',', $row2['Column_priv']);
1088 if (in_array('Select', $tmp_array)) {
1089 $tmp_privs2['Select'][] = $row2['Column_name'];
1091 if (in_array('Insert', $tmp_array)) {
1092 $tmp_privs2['Insert'][] = $row2['Column_name'];
1094 if (in_array('Update', $tmp_array)) {
1095 $tmp_privs2['Update'][] = $row2['Column_name'];
1097 if (in_array('References', $tmp_array)) {
1098 $tmp_privs2['References'][] = $row2['Column_name'];
1102 if (count($tmp_privs2['Select']) > 0 && !in_array('SELECT', $tmp_privs1)) {
1103 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1105 if (count($tmp_privs2['Insert']) > 0 && !in_array('INSERT', $tmp_privs1)) {
1106 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1108 if (count($tmp_privs2['Update']) > 0 && !in_array('UPDATE', $tmp_privs1)) {
1109 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1111 if (count($tmp_privs2['References']) > 0 && !in_array('REFERENCES', $tmp_privs1)) {
1112 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1116 'GRANT ' . join(', ', $tmp_privs1)
1117 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1118 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1119 . (in_array('Grant', explode(',', $row['Table_priv'])) ?
' WITH GRANT OPTION;' : ';');
1125 * Updates privileges
1127 if (!empty($update_privs)) {
1128 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, (isset($tablename) ?
$tablename : ''));
1131 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1132 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1133 if (!isset($Grant_priv) ||
$Grant_priv != 'Y') {
1135 'REVOKE GRANT OPTION ON ' . $db_and_table
1136 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1141 // Should not do a GRANT USAGE for a table-specific privilege, it
1142 // causes problems later (cannot revoke it)
1143 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1145 'GRANT ' . join(', ', PMA_extractPrivInfo())
1146 . ' ON ' . $db_and_table
1147 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
1150 * @todo similar code appears twice in this script
1152 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1153 ||
(! isset($dbname)
1154 && (isset($max_questions) ||
isset($max_connections)
1155 ||
isset($max_updates) ||
isset($max_user_connections))))
1157 $sql_query2 .= 'WITH';
1158 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1159 $sql_query2 .= ' GRANT OPTION';
1161 if (isset($max_questions)) {
1162 $max_questions = max(0, (int)$max_questions);
1163 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1165 if (isset($max_connections)) {
1166 $max_connections = max(0, (int)$max_connections);
1167 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1169 if (isset($max_updates)) {
1170 $max_updates = max(0, (int)$max_updates);
1171 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1173 if (isset($max_user_connections)) {
1174 $max_user_connections = max(0, (int)$max_user_connections);
1175 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1180 if (! PMA_DBI_try_query($sql_query0)) {
1181 // this query may fail, but this does not matter :o)
1184 if (isset($sql_query1) && !PMA_DBI_try_query($sql_query1)) {
1185 // this one may fail, too...
1188 if (isset($sql_query2)) {
1189 PMA_DBI_query($sql_query2);
1193 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1194 $message = PMA_Message
::success(__('You have updated the privileges for %s.'));
1195 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1200 * Revokes Privileges
1202 if (isset($_REQUEST['revokeall'])) {
1203 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, isset($tablename) ?
$tablename : '');
1206 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1207 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1209 'REVOKE GRANT OPTION ON ' . $db_and_table
1210 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1212 PMA_DBI_query($sql_query0);
1213 if (! PMA_DBI_try_query($sql_query1)) {
1214 // this one may fail, too...
1217 $sql_query = $sql_query0 . ' ' . $sql_query1;
1218 $message = PMA_Message
::success(__('You have revoked the privileges for %s'));
1219 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1220 if (! isset($tablename)) {
1229 * Updates the password
1231 if (isset($_REQUEST['change_pw'])) {
1232 // similar logic in user_password.php
1235 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1236 if ($pma_pw != $pma_pw2) {
1237 $message = PMA_Message
::error(__('The passwords aren\'t the same!'));
1238 } elseif (empty($pma_pw) ||
empty($pma_pw2)) {
1239 $message = PMA_Message
::error(__('The password is empty!'));
1243 // here $nopass could be == 1
1244 if (empty($message)) {
1246 $hashing_function = (!empty($pw_hash) && $pw_hash == 'old' ?
'OLD_' : '')
1249 // in $sql_query which will be displayed, hide the password
1250 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ?
'\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1251 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ?
'\'\'' : $hashing_function . '(\'' . PMA_sqlAddslashes($pma_pw) . '\')');
1252 PMA_DBI_try_query($local_query)
1253 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, FALSE, $err_url);
1254 $message = PMA_Message
::success(__('The password for %s was changed successfully.'));
1255 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1262 * (Changes / copies a user, part IV)
1265 if (isset($_REQUEST['delete']) ||
(isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1266 if (isset($_REQUEST['change_copy'])) {
1267 $selected_usr = array($old_username . '&#27;' . $old_hostname);
1269 $selected_usr = $_REQUEST['selected_usr'];
1272 foreach ($selected_usr as $each_user) {
1273 list($this_user, $this_host) = explode('&#27;', $each_user);
1274 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1275 $queries[] = 'DROP USER \'' . PMA_sqlAddslashes($this_user) . '\'@\'' . PMA_sqlAddslashes($this_host) . '\';';
1277 if (isset($_REQUEST['drop_users_db'])) {
1278 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1279 $GLOBALS['reload'] = TRUE;
1281 if($GLOBALS['is_ajax_request'] != true) {
1282 PMA_reloadNavigation();
1286 if (empty($_REQUEST['change_copy'])) {
1287 if (empty($queries)) {
1288 $message = PMA_Message
::error(__('No users selected for deleting!'));
1290 if ($_REQUEST['mode'] == 3) {
1291 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1292 $queries[] = 'FLUSH PRIVILEGES;';
1294 $drop_user_error = '';
1295 foreach ($queries as $sql_query) {
1296 if ($sql_query{0} != '#') {
1297 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1298 $drop_user_error .= PMA_DBI_getError() . "\n";
1302 // tracking sets this, causing the deleted db to be shown in navi
1303 unset($GLOBALS['db']);
1305 $sql_query = join("\n", $queries);
1306 if (! empty($drop_user_error)) {
1307 $message = PMA_Message
::rawError($drop_user_error);
1309 $message = PMA_Message
::success(__('The selected users have been deleted successfully.'));
1318 * Changes / copies a user, part V
1320 if (isset($_REQUEST['change_copy'])) {
1322 foreach ($queries as $sql_query) {
1323 if ($sql_query{0} != '#') {
1324 PMA_DBI_query($sql_query);
1326 // when there is a query containing a hidden password, take it
1327 // instead of the real query sent
1328 if (isset($queries_for_display[$tmp_count])) {
1329 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1333 $message = PMA_Message
::success();
1334 $sql_query = join("\n", $queries);
1339 * Reloads the privilege tables into memory
1341 if (isset($_REQUEST['flush_privileges'])) {
1342 $sql_query = 'FLUSH PRIVILEGES;';
1343 PMA_DBI_query($sql_query);
1344 $message = PMA_Message
::success(__('The privileges were reloaded successfully.'));
1348 * defines some standard links
1350 $link_edit = '<a class="edit_user_anchor" href="server_privileges.php?' . $GLOBALS['url_query']
1351 . '&username=%s'
1352 . '&hostname=%s'
1354 . '&tablename=%s">'
1355 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1358 $link_revoke = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1359 . '&username=%s'
1360 . '&hostname=%s'
1362 . '&tablename=%s'
1363 . '&revokeall=1">'
1364 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1367 $link_export = '<a class="export_user_anchor" href="server_privileges.php?' . $GLOBALS['url_query']
1368 . '&username=%s'
1369 . '&hostname=%s'
1372 . PMA_getIcon('b_tblexport.png', __('Export'))
1376 * If we are in an Ajax request for Create User/Edit User/Revoke User/Flush Privileges,
1377 * show $message and exit.
1379 if( $GLOBALS['is_ajax_request'] && !isset($_REQUEST['export']) && !isset($_REQUEST['adduser']) && !isset($_REQUEST['initial']) && !isset($_REQUEST['showall']) && !isset($_REQUEST['edit_user_dialog'])) {
1381 if(isset($sql_query)) {
1382 $extra_data['sql_query'] = PMA_showMessage(NULL, $sql_query);
1385 if(isset($_REQUEST['adduser_submit']) ||
isset($_REQUEST['change_copy'])) {
1387 * generate html on the fly for the new user that was just created.
1389 $new_user_string = '<tr>'."\n"
1390 .'<td> <input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_" value="' . htmlspecialchars($username) . '&#27;' . htmlspecialchars($hostname) . '" /> </td>'."\n"
1391 .'<td><label for="checkbox_sel_users_">' . (empty($username) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($username) ) . '</label></td>' . "\n"
1392 .'<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
1393 $new_user_string .= '<td>';
1395 if(!empty($password) ||
isset($pma_pw)) {
1396 $new_user_string .= __('Yes');
1399 $new_user_string .= '<span style="color: #FF0000">' . __('No') . '</span>';
1402 $new_user_string .= '</td>'."\n";
1403 $new_user_string .= '<td><tt>' . join(', ', PMA_extractPrivInfo('', true)) . '</tt></td>'; //Fill in privileges here
1404 $new_user_string .= '<td>';
1406 if((isset($Grant_priv) && $Grant_priv == 'Y')) {
1407 $new_user_string .= __('Yes');
1410 $new_user_string .= __('No');
1413 $new_user_string .='</td>';
1415 $new_user_string .= '<td>'.sprintf($link_edit, urlencode($username), urlencode($host), '', '' ).'</td>'."\n";
1416 $new_user_string .= '<td>'.sprintf($link_export, urlencode($username), urlencode($hostname), (isset($initial) ?
$initial : '')).'</td>'."\n";
1418 $new_user_string .= '</tr>';
1420 $extra_data['new_user_string'] = $new_user_string;
1423 * Generate the string for this alphabet's initial, to update the user
1426 $new_user_initial = strtoupper(substr($username, 0, 1));
1427 $new_user_initial_string = '<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . $new_user_initial
1428 .'>' . $new_user_initial . '</a>';
1429 $extra_data['new_user_initial'] = $new_user_initial;
1430 $extra_data['new_user_initial_string'] = $new_user_initial_string;
1433 if(isset($update_privs)) {
1434 $new_privileges = join(', ', PMA_extractPrivInfo('', true));
1436 $extra_data['new_privileges'] = $new_privileges;
1439 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
1443 * Displays the links
1445 if (isset($viewing_mode) && $viewing_mode == 'db') {
1447 $url_query .= '&goto=db_operations.php';
1449 // Gets the database structure
1450 $sub_part = '_structure';
1451 require './libraries/db_info.inc.php';
1454 require './libraries/server_links.inc.php';
1462 // export user definition
1463 if (isset($_REQUEST['export'])) {
1464 echo '<h2>' . __('User') . ' \'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'</h2>';
1465 echo '<textarea cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1466 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddslashes($username) . "'@'" . PMA_sqlAddslashes($hostname) . "'");
1467 foreach($grants as $one_grant) {
1468 echo $one_grant . ";\n\n";
1471 unset($username, $hostname, $grants, $one_grant);
1472 if( $GLOBALS['is_ajax_request']) {
1477 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) ||
! strlen($checkprivs))) {
1478 if (! isset($username)) {
1479 // No username is given --> display the overview
1481 . PMA_getIcon('b_usrlist.png')
1482 . __('User overview') . "\n"
1487 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1488 ' FROM `mysql`.`user`';
1490 $sql_query .= (isset($initial) ?
PMA_RangeOfUsers($initial) : '');
1492 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1493 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE
);
1496 // the query failed! This may have two reasons:
1497 // - the user does not have enough privileges
1498 // - the privilege tables use a structure of an earlier version.
1499 // so let's try a more simple query
1501 $sql_query = 'SELECT * FROM `mysql`.`user`';
1502 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE
);
1505 PMA_Message
::error(__('No Privileges'))->display();
1506 PMA_DBI_free_result($res);
1509 // This message is hardcoded because I will replace it by
1510 // a automatic repair feature soon.
1511 $raw = 'Your privilege table structure seems to be older than'
1512 . ' this MySQL version!<br />'
1513 . 'Please run the <tt>mysql_upgrade</tt> command'
1514 . '(<tt>mysql_fix_privilege_tables</tt> on older systems)'
1515 . ' that should be included in your MySQL server distribution'
1516 . ' to solve this problem!';
1517 PMA_Message
::rawError($raw)->display();
1521 // we also want users not in table `user` but in other table
1522 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1524 $tables_to_search_for_users = array(
1525 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1528 $db_rights_sqls = array();
1529 foreach ($tables_to_search_for_users as $table_search_in) {
1530 if (in_array($table_search_in, $tables)) {
1531 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ?
PMA_RangeOfUsers($initial) : '');
1535 $user_defaults = array(
1539 'Grant_priv' => 'N',
1540 'privs' => array('USAGE'),
1543 // for all initials, even non A-Z
1544 $array_initials = array();
1546 $db_rights = array();
1548 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1549 .' ORDER BY `User` ASC, `Host` ASC';
1551 $db_rights_result = PMA_DBI_query($db_rights_sql);
1553 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1554 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1555 $db_rights[$db_rights_row['User']][$db_rights_row['Host']] =
1558 PMA_DBI_free_result($db_rights_result);
1559 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1563 * Displays the initials
1564 * In an Ajax request, we don't need to show this
1567 if( $GLOBALS['is_ajax_request'] != true ) {
1569 // initialize to FALSE the letters A-Z
1570 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++
) {
1571 if (! isset($array_initials[chr($letter_counter +
64)])) {
1572 $array_initials[chr($letter_counter +
64)] = FALSE;
1576 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE
);
1577 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1578 $array_initials[$tmp_initial] = TRUE;
1581 // Display the initials, which can be any characters, not
1582 // just letters. For letters A-Z, we add the non-used letters
1585 uksort($array_initials, "strnatcasecmp");
1587 echo '<table id="initials_table" cellspacing="5"><tr>';
1588 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1589 if ($initial_was_found) {
1590 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1592 echo '<td>' . $tmp_initial . '</td>';
1595 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&showall=1">[' . __('Show all') . ']</a></td>' . "\n";
1596 echo '</tr></table>';
1600 * Display the user overview
1601 * (if less than 50 users, display them immediately)
1604 if (isset($initial) ||
isset($showall) ||
PMA_DBI_num_rows($res) < 50) {
1606 while ($row = PMA_DBI_fetch_assoc($res)) {
1607 $row['privs'] = PMA_extractPrivInfo($row, true);
1608 $db_rights[$row['User']][$row['Host']] = $row;
1610 @PMA_DBI_free_result
($res);
1613 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1614 . PMA_generate_common_hidden_inputs('', '')
1615 . ' <table id="tableuserrights" class="data">' . "\n"
1617 . ' <tr><th></th>' . "\n"
1618 . ' <th>' . __('User') . '</th>' . "\n"
1619 . ' <th>' . __('Host') . '</th>' . "\n"
1620 . ' <th>' . __('Password') . '</th>' . "\n"
1621 . ' <th>' . __('Global privileges') . ' '
1622 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English ')) . '</th>' . "\n"
1623 . ' <th>' . __('Grant') . '</th>' . "\n"
1624 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1625 echo ' </tr>' . "\n";
1626 echo ' </thead>' . "\n";
1627 echo ' <tbody>' . "\n";
1629 $index_checkbox = -1;
1630 foreach ($db_rights as $user) {
1633 foreach ($user as $host) {
1635 echo ' <tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
1636 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1637 . $index_checkbox . '" value="'
1638 . htmlspecialchars($host['User'] . '&#27;' . $host['Host'])
1640 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
1642 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1643 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1645 switch ($host['Password']) {
1650 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1652 // this happens if this is a definition not coming from mysql.user
1654 echo '--'; // in future version, replace by "not present"
1658 . ' <td><tt>' . "\n"
1659 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1660 . ' </tt></td>' . "\n"
1661 . ' <td>' . ($host['Grant_priv'] == 'Y' ?
__('Yes') : __('No')) . '</td>' . "\n"
1662 . ' <td align="center">';
1663 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1665 echo '<td align="center">';
1666 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ?
$initial : ''));
1669 $odd_row = ! $odd_row;
1673 unset($user, $host, $odd_row);
1674 echo ' </tbody></table>' . "\n"
1675 .'<img class="selectallarrow"'
1676 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1677 .' width="38" height="22"'
1678 .' alt="' . __('With selected:') . '" />' . "\n"
1679 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&checkall=1"'
1680 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1681 . __('Check All') . '</a>' . "\n"
1683 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1684 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1685 . __('Uncheck All') . '</a>' . "\n";
1687 // add/delete user fieldset
1688 echo ' <fieldset id="fieldset_add_user">' . "\n"
1689 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1">' . "\n"
1690 . PMA_getIcon('b_usradd.png')
1691 . ' ' . __('Add a new User') . '</a>' . "\n"
1692 . ' </fieldset>' . "\n"
1693 . ' <fieldset id="fieldset_delete_user">'
1694 . ' <legend>' . "\n"
1695 . PMA_getIcon('b_usrdrop.png')
1696 . ' ' . __('Remove selected users') . '' . "\n"
1697 . ' </legend>' . "\n"
1698 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1699 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1700 . ' <input type="checkbox" title="' . __('Drop the databases that have the same names as the users.') . '" name="drop_users_db" id="checkbox_drop_users_db" />' . "\n"
1701 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1702 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1703 . ' </label>' . "\n"
1704 . ' </fieldset>' . "\n"
1705 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1706 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" />' . "\n"
1707 . ' </fieldset>' . "\n"
1712 echo ' <fieldset id="fieldset_add_user">' . "\n"
1713 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1">' . "\n"
1714 . PMA_getIcon('b_usradd.png')
1715 . ' ' . __('Add a new User') . '</a>' . "\n"
1716 . ' </fieldset>' . "\n";
1717 } // end if (display overview)
1719 if( $GLOBALS['is_ajax_request'] ) {
1723 $flushnote = new PMA_Message(__('Note: phpMyAdmin gets the users\' privileges directly from MySQL\'s privilege tables. The content of these tables may differ from the privileges the server uses, if they have been changed manually. In this case, you should %sreload the privileges%s before you continue.'), PMA_Message
::NOTICE
);
1724 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&flush_privileges=1" id="reload_privileges_anchor">', false);
1725 $flushnote->addParam('</a>', false);
1726 $flushnote->display();
1732 // A user was selected -> display the user's properties
1735 . PMA_getIcon('b_usredit.png')
1736 . __('Edit Privileges') . ': '
1739 if (isset($dbname)) {
1740 echo ' <i><a href="server_privileges.php?'
1741 . $GLOBALS['url_query'] . '&username=' . htmlspecialchars(urlencode($username))
1742 . '&hostname=' . htmlspecialchars(urlencode($hostname)) . '&dbname=&tablename=">\''
1743 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1744 . '\'</a></i>' . "\n";
1745 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
1747 echo ' - ' . ($dbname_is_wildcard ?
__('Databases') : __('Database') );
1748 if (isset($tablename)) {
1749 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
1750 . '&username=' . htmlspecialchars(urlencode($username)) . '&hostname=' . htmlspecialchars(urlencode($hostname))
1751 . '&dbname=' . htmlspecialchars($url_dbname) . '&tablename=">' . htmlspecialchars($dbname) . '</a></i>';
1752 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
1754 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
1758 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1762 echo '</h2>' . "\n";
1765 $sql = "SELECT '1' FROM `mysql`.`user`"
1766 . " WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
1767 . " AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
1768 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
1770 if ($user_does_not_exists) {
1771 PMA_Message
::warning(__('The selected user was not found in the privilege table.'))->display();
1772 PMA_displayLoginInformationFields();
1773 //require './libraries/footer.inc.php';
1776 echo '<form name="usersForm" id="addUsersForm" action="server_privileges.php" method="post">' . "\n";
1778 'username' => $username,
1779 'hostname' => $hostname,
1781 if (isset($dbname)) {
1782 $_params['dbname'] = $dbname;
1783 if (isset($tablename)) {
1784 $_params['tablename'] = $tablename;
1787 echo PMA_generate_common_hidden_inputs($_params);
1789 PMA_displayPrivTable(PMA_ifSetOr($dbname, '*', 'length'),
1790 PMA_ifSetOr($tablename, '*', 'length'));
1792 echo '</form>' . "\n";
1794 if (! isset($tablename) && empty($dbname_is_wildcard)) {
1796 // no table name was given, display all table specific rights
1797 // but only if $dbname contains no wildcards
1800 echo '<form action="server_privileges.php" method="post">' . "\n"
1801 . PMA_generate_common_hidden_inputs('', '')
1802 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
1803 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1804 . '<fieldset>' . "\n"
1805 . '<legend>' . (! isset($dbname) ?
__('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
1806 . '<table class="data">' . "\n"
1808 . '<tr><th>' . (! isset($dbname) ?
__('Database') : __('Table')) . '</th>' . "\n"
1809 . ' <th>' . __('Privileges') . '</th>' . "\n"
1810 . ' <th>' . __('Grant') . '</th>' . "\n"
1811 . ' <th>' . (! isset($dbname) ?
__('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
1812 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
1817 $user_host_condition =
1819 . ' = \'' . PMA_sqlAddslashes($username) . "'"
1821 . ' = \'' . PMA_sqlAddslashes($hostname) . "'";
1826 // we also want privielgs for this user not in table `db` but in other table
1827 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1828 if (! isset($dbname)) {
1830 // no db name given, so we want all privs for the given user
1832 $tables_to_search_for_users = array(
1833 'tables_priv', 'columns_priv',
1836 $db_rights_sqls = array();
1837 foreach ($tables_to_search_for_users as $table_search_in) {
1838 if (in_array($table_search_in, $tables)) {
1839 $db_rights_sqls[] = '
1840 SELECT DISTINCT `Db`
1841 FROM `mysql`.' . PMA_backquote($table_search_in)
1842 . $user_host_condition;
1846 $user_defaults = array(
1848 'Grant_priv' => 'N',
1849 'privs' => array('USAGE'),
1850 'Table_privs' => true,
1854 $db_rights = array();
1856 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1857 .' ORDER BY `Db` ASC';
1859 $db_rights_result = PMA_DBI_query($db_rights_sql);
1861 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1862 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1863 // only Db names in the table `mysql`.`db` uses wildcards
1864 // as we are in the db specific rights display we want
1865 // all db names escaped, also from other sources
1866 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
1867 $db_rights_row['Db']);
1868 $db_rights[$db_rights_row['Db']] = $db_rights_row;
1871 PMA_DBI_free_result($db_rights_result);
1872 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1874 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
1875 $res = PMA_DBI_query($sql_query);
1878 while ($row = PMA_DBI_fetch_assoc($res)) {
1879 if (isset($db_rights[$row['Db']])) {
1880 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
1882 $db_rights[$row['Db']] = $row;
1884 // there are db specific rights for this user
1885 // so we can drop this db rights
1886 $db_rights[$row['Db']]['can_delete'] = true;
1888 PMA_DBI_free_result($res);
1893 // db name was given,
1894 // so we want all user specific rights for this db
1896 $user_host_condition .=
1898 .' LIKE \'' . PMA_sqlAddslashes($dbname) . "'";
1900 $tables_to_search_for_users = array(
1904 $db_rights_sqls = array();
1905 foreach ($tables_to_search_for_users as $table_search_in) {
1906 if (in_array($table_search_in, $tables)) {
1907 $db_rights_sqls[] = '
1908 SELECT DISTINCT `Table_name`
1909 FROM `mysql`.' . PMA_backquote($table_search_in)
1910 . $user_host_condition;
1914 $user_defaults = array(
1916 'Grant_priv' => 'N',
1917 'privs' => array('USAGE'),
1918 'Column_priv' => true,
1922 $db_rights = array();
1924 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1925 .' ORDER BY `Table_name` ASC';
1927 $db_rights_result = PMA_DBI_query($db_rights_sql);
1929 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1930 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1931 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
1933 PMA_DBI_free_result($db_rights_result);
1934 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1937 'SELECT `Table_name`,'
1939 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
1940 .' AS \'Column_priv\''
1941 .' FROM `mysql`.`tables_priv`'
1942 . $user_host_condition
1943 .' ORDER BY `Table_name` ASC;';
1944 $res = PMA_DBI_query($sql_query);
1947 while ($row = PMA_DBI_fetch_assoc($res)) {
1948 if (isset($db_rights[$row['Table_name']])) {
1949 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
1951 $db_rights[$row['Table_name']] = $row;
1954 PMA_DBI_free_result($res);
1960 if (count($db_rights) < 1) {
1961 echo '<tr class="odd">' . "\n"
1962 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
1966 $found_rows = array();
1967 //while ($row = PMA_DBI_fetch_assoc($res)) {
1968 foreach ($db_rights as $row) {
1969 $found_rows[] = (! isset($dbname)) ?
$row['Db'] : $row['Table_name'];
1971 echo '<tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
1972 . ' <td>' . htmlspecialchars((! isset($dbname)) ?
$row['Db'] : $row['Table_name']) . '</td>' . "\n"
1973 . ' <td><tt>' . "\n"
1974 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, TRUE)) . "\n"
1975 . ' </tt></td>' . "\n"
1976 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') ||
(isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ?
__('Yes') : __('No')) . '</td>' . "\n"
1978 if (! empty($row['Table_privs']) ||
! empty ($row['Column_priv'])) {
1985 printf($link_edit, htmlspecialchars(urlencode($username)),
1986 urlencode(htmlspecialchars($hostname)),
1987 urlencode((! isset($dbname)) ?
$row['Db'] : htmlspecialchars($dbname)),
1988 urlencode((! isset($dbname)) ?
'' : $row['Table_name']));
1991 if (! empty($row['can_delete']) ||
isset($row['Table_name']) && strlen($row['Table_name'])) {
1992 printf($link_revoke, htmlspecialchars(urlencode($username)),
1993 urlencode(htmlspecialchars($hostname)),
1994 urlencode((! isset($dbname)) ?
$row['Db'] : htmlspecialchars($dbname)),
1995 urlencode((! isset($dbname)) ?
'' : $row['Table_name']));
1999 $odd_row = ! $odd_row;
2003 echo '</tbody>' . "\n"
2004 . '</table>' . "\n";
2006 if (! isset($dbname)) {
2008 // no database name was given, display select db
2010 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
2012 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
2013 if (!empty($pred_db_array)) {
2014 echo ' <select name="pred_dbname" onchange="this.form.submit();">' . "\n"
2015 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2016 foreach ($pred_db_array as $current_db) {
2017 $current_db = PMA_escape_mysql_wildcards($current_db);
2018 // cannot use array_diff() once, outside of the loop,
2019 // because the list of databases has special characters
2020 // already escaped in $found_rows,
2021 // contrary to the output of SHOW DATABASES
2022 if (empty($found_rows) ||
! in_array($current_db, $found_rows)) {
2023 echo ' <option value="' . htmlspecialchars($current_db) . '">'
2024 . htmlspecialchars($current_db) . '</option>' . "\n";
2027 echo ' </select>' . "\n";
2029 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
2030 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
2032 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
2033 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
2034 if ($res = @PMA_DBI_try_query
('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE
)) {
2035 $pred_tbl_array = array();
2036 while ($row = PMA_DBI_fetch_row($res)) {
2037 if (!isset($found_rows) ||
!in_array($row[0], $found_rows)) {
2038 $pred_tbl_array[] = $row[0];
2041 PMA_DBI_free_result($res);
2043 if (!empty($pred_tbl_array)) {
2044 echo ' <select name="pred_tablename" onchange="this.form.submit();">' . "\n"
2045 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2046 foreach ($pred_tbl_array as $current_table) {
2047 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
2049 echo ' </select>' . "\n";
2054 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
2056 echo '</fieldset>' . "\n";
2057 echo '<fieldset class="tblFooters">' . "\n"
2058 . ' <input type="submit" value="' . __('Go') . '" />'
2059 . '</fieldset>' . "\n"
2064 // Provide a line with links to the relevant database and table
2065 if (isset($dbname) && empty($dbname_is_wildcard)) {
2066 echo '[ ' . __('Database')
2067 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
2068 . $GLOBALS['url_query'] . '&db=' . $url_dbname . '&reload=1">'
2069 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
2071 if (isset($tablename)) {
2072 echo ' [ ' . __('Table') . ' <a href="'
2073 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
2074 . '&db=' . $url_dbname . '&table=' . htmlspecialchars(urlencode($tablename))
2075 . '&reload=1">' . htmlspecialchars($tablename) . ': '
2076 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
2082 if (! isset($dbname) && ! $user_does_not_exists) {
2083 require_once './libraries/display_change_password.lib.php';
2085 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
2086 . PMA_generate_common_hidden_inputs('', '')
2087 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
2088 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
2089 . '<fieldset id="fieldset_change_copy_user">' . "\n"
2090 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
2091 PMA_displayLoginInformationFields('change');
2092 echo ' <fieldset>' . "\n"
2093 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2095 '4' => __('... keep the old one.'),
2096 '1' => __(' ... delete the old one from the user tables.'),
2097 '2' => __(' ... revoke all active privileges from the old one and delete it afterwards.'),
2098 '3' => __(' ... delete the old one from the user tables and reload the privileges afterwards.'));
2099 PMA_display_html_radio('mode', $choices, '4', true);
2102 echo ' </fieldset>' . "\n"
2103 . '</fieldset>' . "\n"
2104 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2105 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2106 . '</fieldset>' . "\n"
2110 } elseif (isset($_REQUEST['adduser'])) {
2113 $GLOBALS['url_query'] .= '&adduser=1';
2115 . PMA_getIcon('b_usradd.png') . __('Add a new User') . "\n"
2117 . '<form name="usersForm" id="addUsersForm" action="server_privileges.php" method="post">' . "\n"
2118 . PMA_generate_common_hidden_inputs('', '');
2119 PMA_displayLoginInformationFields('new');
2120 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2121 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2123 $default_choice = 0;
2125 '0' => _pgettext('Create none database for user', 'None'),
2126 '1' => __('Create database with same name and grant all privileges'),
2127 '2' => __('Grant all privileges on wildcard name (username\\_%)'));
2129 if ( !empty($dbname) ) {
2130 $choices['3'] = sprintf( __('Grant all privileges on database "%s"'), htmlspecialchars($dbname));
2131 $default_choice = 3;
2132 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2135 // 4th parameter set to true to add line breaks
2136 // 5th parameter set to false to avoid htmlspecialchars() escaping in the label
2137 // since we have some HTML in some labels
2138 PMA_display_html_radio('createdb', $choices, $default_choice, true, false);
2140 unset($default_choice);
2142 echo '</fieldset>' . "\n";
2143 PMA_displayPrivTable('*', '*', FALSE);
2144 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2145 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2146 . ' </fieldset>' . "\n"
2149 // check the privileges for a particular database.
2150 echo '<table id="tablespecificuserrights" class="data">' . "\n"
2151 . '<caption class="tblHeaders">' . "\n"
2152 . PMA_getIcon('b_usrcheck.png')
2153 . ' ' . sprintf(__('Users having access to "%s"'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2154 . '</caption>' . "\n"
2156 . ' <tr><th>' . __('User') . '</th>' . "\n"
2157 . ' <th>' . __('Host') . '</th>' . "\n"
2158 . ' <th>' . __('Type') . '</th>' . "\n"
2159 . ' <th>' . __('Privileges') . '</th>' . "\n"
2160 . ' <th>' . __('Grant') . '</th>' . "\n"
2161 . ' <th>' . __('Action') . '</th>' . "\n"
2166 unset($row, $row1, $row2);
2168 // now, we build the table...
2169 $list_of_privileges =
2181 . '`References_priv`, '
2182 . '`Create_tmp_table_priv`, '
2183 . '`Lock_tables_priv`, '
2184 . '`Create_view_priv`, '
2185 . '`Show_view_priv`, '
2186 . '`Create_routine_priv`, '
2187 . '`Alter_routine_priv`, '
2190 $list_of_compared_privileges =
2191 '`Select_priv` = \'N\''
2192 . ' AND `Insert_priv` = \'N\''
2193 . ' AND `Update_priv` = \'N\''
2194 . ' AND `Delete_priv` = \'N\''
2195 . ' AND `Create_priv` = \'N\''
2196 . ' AND `Drop_priv` = \'N\''
2197 . ' AND `Grant_priv` = \'N\''
2198 . ' AND `References_priv` = \'N\''
2199 . ' AND `Create_tmp_table_priv` = \'N\''
2200 . ' AND `Lock_tables_priv` = \'N\''
2201 . ' AND `Create_view_priv` = \'N\''
2202 . ' AND `Show_view_priv` = \'N\''
2203 . ' AND `Create_routine_priv` = \'N\''
2204 . ' AND `Alter_routine_priv` = \'N\''
2205 . ' AND `Execute_priv` = \'N\'';
2207 if (PMA_MYSQL_INT_VERSION
>= 50106) {
2208 $list_of_privileges .=
2211 $list_of_compared_privileges .=
2212 ' AND `Event_priv` = \'N\''
2213 . ' AND `Trigger_priv` = \'N\'';
2217 '(SELECT ' . $list_of_privileges . ', `Db`'
2218 .' FROM `mysql`.`db`'
2219 .' WHERE \'' . PMA_sqlAddslashes($checkprivs) . "'"
2221 .' AND NOT (' . $list_of_compared_privileges. ')) '
2223 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2224 .' FROM `mysql`.`user` '
2225 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2226 .' ORDER BY `User` ASC,'
2229 $res = PMA_DBI_query($sql_query);
2230 $row = PMA_DBI_fetch_assoc($res);
2237 // prepare the current user
2238 $current_privileges = array();
2239 $current_user = $row['User'];
2240 $current_host = $row['Host'];
2241 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2242 $current_privileges[] = $row;
2243 $row = PMA_DBI_fetch_assoc($res);
2245 echo ' <tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
2247 if (count($current_privileges) > 1) {
2248 echo ' rowspan="' . count($current_privileges) . '"';
2250 echo '>' . (empty($current_user) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2253 if (count($current_privileges) > 1) {
2254 echo ' rowspan="' . count($current_privileges) . '"';
2256 echo '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2257 foreach ($current_privileges as $current) {
2260 if (!isset($current['Db']) ||
$current['Db'] == '*') {
2262 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2263 echo __('database-specific');
2265 echo __('wildcard'), ': <tt>' . htmlspecialchars($current['Db']) . '</tt>';
2271 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, TRUE)) . "\n"
2275 . ' ' . ($current['Grant_priv'] == 'Y' ?
__('Yes') : __('No')) . "\n"
2278 printf($link_edit, urlencode($current_user),
2279 urlencode($current_host),
2280 urlencode(! isset($current['Db']) ||
$current['Db'] == '*' ?
'' : $current['Db']),
2285 if (empty($row) && empty($row1) && empty($row2)) {
2288 $odd_row = ! $odd_row;
2291 echo ' <tr class="odd">' . "\n"
2292 . ' <td colspan="6">' . "\n"
2293 . ' ' . __('No user found.') . "\n"
2297 echo '</tbody>' . "\n"
2298 . '</table>' . "\n";
2300 // Offer to create a new user for the current database
2301 echo '<fieldset id="fieldset_add_user">' . "\n"
2302 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1&dbname=' . htmlspecialchars($checkprivs) .'">' . "\n"
2303 . PMA_getIcon('b_usradd.png')
2304 . ' ' . __('Add a new User') . '</a>' . "\n"
2305 . '</fieldset>' . "\n";
2307 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2311 * Displays the footer
2314 require './libraries/footer.inc.php';