2 /* vim: set expandtab sw=4 ts=4 sts=4: */
12 require_once './libraries/common.inc.php';
15 * Does the common work
17 $GLOBALS['js_include'][] = 'server_privileges.js';
18 $GLOBALS['js_include'][] = 'functions.js';
19 $GLOBALS['js_include'][] = 'password_generation.js';
20 require './libraries/server_common.inc.php';
23 * Messages are built using the message name
25 $strPrivDescAllPrivileges = __('Includes all privileges except GRANT.');
26 $strPrivDescAlter = __('Allows altering the structure of existing tables.');
27 $strPrivDescAlterRoutine = __('Allows altering and dropping stored routines.');
28 $strPrivDescCreateDb = __('Allows creating new databases and tables.');
29 $strPrivDescCreateRoutine = __('Allows creating stored routines.');
30 $strPrivDescCreateTbl = __('Allows creating new tables.');
31 $strPrivDescCreateTmpTable = __('Allows creating temporary tables.');
32 $strPrivDescCreateUser = __('Allows creating, dropping and renaming user accounts.');
33 $strPrivDescCreateView = __('Allows creating new views.');
34 $strPrivDescDelete = __('Allows deleting data.');
35 $strPrivDescDropDb = __('Allows dropping databases and tables.');
36 $strPrivDescDropTbl = __('Allows dropping tables.');
37 $strPrivDescEvent = __('Allows to set up events for the event scheduler');
38 $strPrivDescExecute = __('Allows executing stored routines.');
39 $strPrivDescFile = __('Allows importing data from and exporting data into files.');
40 $strPrivDescGrant = __('Allows adding users and privileges without reloading the privilege tables.');
41 $strPrivDescIndex = __('Allows creating and dropping indexes.');
42 $strPrivDescInsert = __('Allows inserting and replacing data.');
43 $strPrivDescLockTables = __('Allows locking tables for the current thread.');
44 $strPrivDescMaxConnections = __('Limits the number of new connections the user may open per hour.');
45 $strPrivDescMaxQuestions = __('Limits the number of queries the user may send to the server per hour.');
46 $strPrivDescMaxUpdates = __('Limits the number of commands that change any table or database the user may execute per hour.');
47 $strPrivDescMaxUserConnections = __('Limits the number of simultaneous connections the user may have.');
48 $strPrivDescProcess = __('Allows viewing processes of all users');
49 $strPrivDescReferences = __('Has no effect in this MySQL version.');
50 $strPrivDescReload = __('Allows reloading server settings and flushing the server\'s caches.');
51 $strPrivDescReplClient = __('Allows the user to ask where the slaves / masters are.');
52 $strPrivDescReplSlave = __('Needed for the replication slaves.');
53 $strPrivDescSelect = __('Allows reading data.');
54 $strPrivDescShowDb = __('Gives access to the complete list of databases.');
55 $strPrivDescShowView = __('Allows performing SHOW CREATE VIEW queries.');
56 $strPrivDescShutdown = __('Allows shutting down the server.');
57 $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.');
58 $strPrivDescTrigger = __('Allows creating and dropping triggers');
59 $strPrivDescUpdate = __('Allows changing data.');
60 $strPrivDescUsage = __('No privileges.');
63 * Checks if a dropdown box has been used for selecting a database / table
65 if (PMA_isValid($_REQUEST['pred_tablename'])) {
66 $tablename = $_REQUEST['pred_tablename'];
67 unset($pred_tablename);
68 } elseif (PMA_isValid($_REQUEST['tablename'])) {
69 $tablename = $_REQUEST['tablename'];
74 if (PMA_isValid($_REQUEST['pred_dbname'])) {
75 $dbname = $_REQUEST['pred_dbname'];
77 } elseif (PMA_isValid($_REQUEST['dbname'])) {
78 $dbname = $_REQUEST['dbname'];
85 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
86 if (isset($tablename)) {
87 $db_and_table .= PMA_backquote($tablename);
92 $db_and_table = '*.*';
95 // check if given $dbname is a wildcard or not
97 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
98 if (preg_match('/(?<!\\\\)(?:_|%)/i', $dbname)) {
99 $dbname_is_wildcard = true;
101 $dbname_is_wildcard = false;
106 * Checks if the user is allowed to do what he tries to...
108 if (!$is_superuser) {
109 require './libraries/server_links.inc.php';
111 . PMA_getIcon('b_usrlist.png')
112 . __('Privileges') . "\n"
114 PMA_Message
::error(__('No Privileges'))->display();
115 require_once './libraries/footer.inc.php';
119 * Escapes wildcard in a database+table specification
120 * before using it in a GRANT statement.
122 * Escaping a wildcard character in a GRANT is only accepted at the global
123 * or database level, not at table level; this is why I remove
124 * the escaping character. Internally, in mysql.tables_priv.Db there are
125 * no escaping (for example test_db) but in mysql.db you'll see test\_db
126 * for a db-specific privilege.
128 * @param string $db_and_table
129 * @param string $dbname
130 * @param string $tablename
131 * @return string the escaped (if necessary) $db_and_table
133 function PMA_WildcardEscapeForGrant($db_and_table, $dbname, $tablename) {
135 if (! strlen($dbname)) {
136 $db_and_table = '*.*';
138 if (strlen($tablename)) {
139 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
140 $db_and_table .= PMA_backquote($tablename);
142 $db_and_table = PMA_backquote($dbname) . '.';
143 $db_and_table .= '*';
146 return $db_and_table;
150 * Generates a condition on the user name
152 * @param string the user's initial
153 * @return string the generated condition
155 function PMA_RangeOfUsers($initial = '')
157 // strtolower() is used because the User field
158 // might be BINARY, so LIKE would be case sensitive
159 if (!empty($initial)) {
160 $ret = " WHERE `User` LIKE '" . $initial . "%'"
161 . " OR `User` LIKE '" . strtolower($initial) . "%'";
169 * Extracts the privilege information of a priv table row
171 * @param array $row the row
172 * @param boolean $enableHTML add <dfn> tag with tooltips
174 * @global ressource $user_link the database connection
178 function PMA_extractPrivInfo($row = '', $enableHTML = FALSE)
181 array('Select_priv', 'SELECT', __('Allows reading data.')),
182 array('Insert_priv', 'INSERT', __('Allows inserting and replacing data.')),
183 array('Update_priv', 'UPDATE', __('Allows changing data.')),
184 array('Delete_priv', 'DELETE', __('Allows deleting data.')),
185 array('Create_priv', 'CREATE', __('Allows creating new databases and tables.')),
186 array('Drop_priv', 'DROP', __('Allows dropping databases and tables.')),
187 array('Reload_priv', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.')),
188 array('Shutdown_priv', 'SHUTDOWN', __('Allows shutting down the server.')),
189 array('Process_priv', 'PROCESS', __('Allows viewing processes of all users')),
190 array('File_priv', 'FILE', __('Allows importing data from and exporting data into files.')),
191 array('References_priv', 'REFERENCES', __('Has no effect in this MySQL version.')),
192 array('Index_priv', 'INDEX', __('Allows creating and dropping indexes.')),
193 array('Alter_priv', 'ALTER', __('Allows altering the structure of existing tables.')),
194 array('Show_db_priv', 'SHOW DATABASES', __('Gives access to the complete list of databases.')),
195 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.')),
196 array('Create_tmp_table_priv', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
197 array('Lock_tables_priv', 'LOCK TABLES', __('Allows locking tables for the current thread.')),
198 array('Repl_slave_priv', 'REPLICATION SLAVE', __('Needed for the replication slaves.')),
199 array('Repl_client_priv', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.')),
200 array('Create_view_priv', 'CREATE VIEW', __('Allows creating new views.')),
201 array('Event_priv', 'EVENT', __('Allows to set up events for the event scheduler')),
202 array('Trigger_priv', 'TRIGGER', __('Allows creating and dropping triggers')),
204 array('Create View_priv', 'CREATE VIEW', __('Allows creating new views.')),
205 array('Show_view_priv', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
207 array('Show view_priv', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
208 array('Create_routine_priv', 'CREATE ROUTINE', __('Allows creating stored routines.')),
209 array('Alter_routine_priv', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
210 array('Create_user_priv', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.')),
211 array('Execute_priv', 'EXECUTE', __('Allows executing stored routines.')),
214 if (!empty($row) && isset($row['Table_priv'])) {
215 $row1 = PMA_DBI_fetch_single_row(
216 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
217 'ASSOC', $GLOBALS['userlink']);
218 $av_grants = explode('\',\'', substr($row1['Type'], 5, strlen($row1['Type']) - 7));
220 $users_grants = explode(',', $row['Table_priv']);
221 foreach ($av_grants as $current_grant) {
222 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ?
'Y' : 'N';
224 unset($current_grant);
226 unset($users_grants);
229 $allPrivileges = TRUE;
230 foreach ($grants as $current_grant) {
231 if ((!empty($row) && isset($row[$current_grant[0]]))
232 ||
(empty($row) && isset($GLOBALS[$current_grant[0]]))) {
233 if ((!empty($row) && $row[$current_grant[0]] == 'Y')
235 && ($GLOBALS[$current_grant[0]] == 'Y'
236 ||
(is_array($GLOBALS[$current_grant[0]])
237 && count($GLOBALS[$current_grant[0]]) == $GLOBALS['column_count']
238 && empty($GLOBALS[$current_grant[0] . '_none'])))))
241 $privs[] = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
243 $privs[] = $current_grant[1];
245 } elseif (!empty($GLOBALS[$current_grant[0]])
246 && is_array($GLOBALS[$current_grant[0]])
247 && empty($GLOBALS[$current_grant[0] . '_none'])) {
249 $priv_string = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
251 $priv_string = $current_grant[1];
253 $privs[] = $priv_string . ' (`' . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
255 $allPrivileges = FALSE;
261 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
265 } elseif ($allPrivileges && (!isset($GLOBALS['grant_count']) ||
count($privs) == $GLOBALS['grant_count'])) {
267 $privs = array('<dfn title="' . __('Includes all privileges except GRANT.') . '">ALL PRIVILEGES</dfn>');
269 $privs = array('ALL PRIVILEGES');
273 } // end of the 'PMA_extractPrivInfo()' function
276 * Displays on which column(s) a table-specific privilege is granted
278 function PMA_display_column_privs($columns, $row, $name_for_select,
279 $priv_for_header, $name, $name_for_dfn, $name_for_current)
281 echo ' <div class="item" id="div_item_' . $name . '">' . "\n"
282 . ' <label for="select_' . $name . '_priv">' . "\n"
283 . ' <tt><dfn title="' . $name_for_dfn . '">'
284 . $priv_for_header . '</dfn></tt>' . "\n"
285 . ' </label><br />' . "\n"
286 . ' <select id="select_' . $name . '_priv" name="'
287 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
289 foreach ($columns as $current_column => $current_column_privileges) {
290 echo ' <option value="' . htmlspecialchars($current_column) . '"';
291 if ($row[$name_for_select] == 'Y' ||
$current_column_privileges[$name_for_current]) {
292 echo ' selected="selected"';
294 echo '>' . htmlspecialchars($current_column) . '</option>' . "\n";
297 echo ' </select>' . "\n"
298 . ' <i>' . __('Or') . '</i>' . "\n"
299 . ' <label for="checkbox_' . $name_for_select
300 . '_none"><input type="checkbox"'
301 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
302 . ' name="' . $name_for_select . '_none" id="checkbox_'
303 . $name_for_select . '_none" title="' . _pgettext('None privileges', 'None') . '" />'
304 . _pgettext('None privileges', 'None') . '</label>' . "\n"
310 * Displays the privileges form table
312 * @param string $db the database
313 * @param string $table the table
314 * @param boolean $submit wheather to display the submit button or not
315 * @global array $cfg the phpMyAdmin configuration
316 * @global ressource $user_link the database connection
320 function PMA_displayPrivTable($db = '*', $table = '*', $submit = TRUE)
326 if (isset($GLOBALS['username'])) {
327 $username = $GLOBALS['username'];
328 $hostname = $GLOBALS['hostname'];
331 "SELECT * FROM `mysql`.`user`"
332 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
333 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
334 } elseif ($table == '*') {
336 "SELECT * FROM `mysql`.`db`"
337 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
338 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "'"
339 ." AND '" . PMA_unescape_mysql_wildcards($db) . "'"
343 "SELECT `Table_priv`"
344 ." FROM `mysql`.`tables_priv`"
345 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
346 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "'"
347 ." AND `Db` = '" . PMA_unescape_mysql_wildcards($db) . "'"
348 ." AND `Table_name` = '" . PMA_sqlAddslashes($table) . "';";
350 $row = PMA_DBI_fetch_single_row($sql_query);
355 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
356 } elseif ($table == '*') {
357 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
359 $res = PMA_DBI_query($sql_query);
360 while ($row1 = PMA_DBI_fetch_row($res)) {
361 if (substr($row1[0], 0, 4) == 'max_') {
364 $row[$row1[0]] = 'N';
367 PMA_DBI_free_result($res);
369 $row = array('Table_priv' => '');
372 if (isset($row['Table_priv'])) {
373 $row1 = PMA_DBI_fetch_single_row(
374 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
375 'ASSOC', $GLOBALS['userlink']);
376 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
377 // the View for Create is spelled with uppercase V
378 // the view for Show is spelled with lowercase v
379 // and there is a space between the words
381 $av_grants = explode('\',\'', substr($row1['Type'], strpos($row1['Type'], '(') +
2, strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3));
383 $users_grants = explode(',', $row['Table_priv']);
385 foreach ($av_grants as $current_grant) {
386 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ?
'Y' : 'N';
388 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
391 $res = PMA_DBI_try_query('SHOW COLUMNS FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($db)) . '.' . PMA_backquote($table) . ';');
394 while ($row1 = PMA_DBI_fetch_row($res)) {
395 $columns[$row1[0]] = array(
399 'References' => FALSE
402 PMA_DBI_free_result($res);
406 // t a b l e - s p e c i f i c p r i v i l e g e s
407 if (! empty($columns)) {
408 $res = PMA_DBI_query(
409 'SELECT `Column_name`, `Column_priv`'
410 .' FROM `mysql`.`columns_priv`'
412 .' = \'' . PMA_sqlAddslashes($username) . "'"
414 .' = \'' . PMA_sqlAddslashes($hostname) . "'"
416 .' = \'' . PMA_sqlAddslashes(PMA_unescape_mysql_wildcards($db)) . "'"
418 .' = \'' . PMA_sqlAddslashes($table) . '\';');
420 while ($row1 = PMA_DBI_fetch_row($res)) {
421 $row1[1] = explode(',', $row1[1]);
422 foreach ($row1[1] as $current) {
423 $columns[$row1[0]][$current] = TRUE;
426 PMA_DBI_free_result($res);
427 unset($res, $row1, $current);
429 echo '<input type="hidden" name="grant_count" value="' . count($row) . '" />' . "\n"
430 . '<input type="hidden" name="column_count" value="' . count($columns) . '" />' . "\n"
431 . '<fieldset id="fieldset_user_priv">' . "\n"
432 . ' <legend>' . __('Table-specific privileges')
433 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English '))
434 . '</legend>' . "\n";
438 // privs that are attached to a specific column
439 PMA_display_column_privs($columns, $row, 'Select_priv',
440 'SELECT', 'select', __('Allows reading data.'), 'Select');
442 PMA_display_column_privs($columns, $row, 'Insert_priv',
443 'INSERT', 'insert', __('Allows inserting and replacing data.'), 'Insert');
445 PMA_display_column_privs($columns, $row, 'Update_priv',
446 'UPDATE', 'update', __('Allows changing data.'), 'Update');
448 PMA_display_column_privs($columns, $row, 'References_priv',
449 'REFERENCES', 'references', __('Has no effect in this MySQL version.'), 'References');
451 // privs that are not attached to a specific column
453 echo ' <div class="item">' . "\n";
454 foreach ($row as $current_grant => $current_grant_value) {
455 if (in_array(substr($current_grant, 0, (strlen($current_grant) - 5)),
456 array('Select', 'Insert', 'Update', 'References'))) {
459 // make a substitution to match the messages variables;
460 // also we must substitute the grant we get, because we can't generate
461 // a form variable containing blanks (those would get changed to
462 // an underscore when receiving the POST)
463 if ($current_grant == 'Create View_priv') {
464 $tmp_current_grant = 'CreateView_priv';
465 $current_grant = 'Create_view_priv';
466 } elseif ($current_grant == 'Show view_priv') {
467 $tmp_current_grant = 'ShowView_priv';
468 $current_grant = 'Show_view_priv';
470 $tmp_current_grant = $current_grant;
473 echo ' <div class="item">' . "\n"
474 . ' <input type="checkbox"'
475 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
476 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
478 . ($current_grant_value == 'Y' ?
'checked="checked" ' : '')
481 echo (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
482 ?
$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)) . 'Tbl']) . '"/>' . "\n";
485 echo ' <label for="checkbox_' . $current_grant
486 . '"><tt><dfn title="'
487 . (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
488 ?
$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)) . 'Tbl'])
490 . '">' . strtoupper(substr($current_grant, 0, strlen($current_grant) - 5)) . '</dfn></tt></label>' . "\n"
494 echo ' </div>' . "\n";
496 echo ' <div class="clearfloat"></div>' . "\n";
500 // g l o b a l o r d b - s p e c i f i c
503 $privTable[0] = array(
504 array('Select', 'SELECT', __('Allows reading data.')),
505 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
506 array('Update', 'UPDATE', __('Allows changing data.')),
507 array('Delete', 'DELETE', __('Allows deleting data.'))
510 $privTable[0][] = array('File', 'FILE', __('Allows importing data from and exporting data into files.'));
514 $privTable[1] = array(
515 array('Create', 'CREATE', ($table == '*' ?
__('Allows creating new databases and tables.') : __('Allows creating new tables.'))),
516 array('Alter', 'ALTER', __('Allows altering the structure of existing tables.')),
517 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
518 array('Drop', 'DROP', ($table == '*' ?
__('Allows dropping databases and tables.') : __('Allows dropping tables.'))),
519 array('Create_tmp_table', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
520 array('Show_view', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
521 array('Create_routine', 'CREATE ROUTINE', __('Allows creating stored routines.')),
522 array('Alter_routine', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
523 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
525 // this one is for a db-specific priv: Create_view_priv
526 if (isset($row['Create_view_priv'])) {
527 $privTable[1][] = array('Create_view', 'CREATE VIEW', __('Allows creating new views.'));
529 // this one is for a table-specific priv: Create View_priv
530 if (isset($row['Create View_priv'])) {
531 $privTable[1][] = array('Create View', 'CREATE VIEW', __('Allows creating new views.'));
533 if (isset($row['Event_priv'])) {
535 $privTable[1][] = array('Event', 'EVENT', __('Allows to set up events for the event scheduler'));
536 $privTable[1][] = array('Trigger', 'TRIGGER', __('Allows creating and dropping triggers'));
539 // a d m i n i s t r a t i o n
540 $privTable[2] = array(
541 array('Grant', 'GRANT', __('Allows adding users and privileges without reloading the privilege tables.')),
544 $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.'));
545 $privTable[2][] = array('Process', 'PROCESS', __('Allows viewing processes of all users'));
546 $privTable[2][] = array('Reload', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.'));
547 $privTable[2][] = array('Shutdown', 'SHUTDOWN', __('Allows shutting down the server.'));
548 $privTable[2][] = array('Show_db', 'SHOW DATABASES', __('Gives access to the complete list of databases.'));
550 $privTable[2][] = array('Lock_tables', 'LOCK TABLES', __('Allows locking tables for the current thread.'));
551 $privTable[2][] = array('References', 'REFERENCES', __('Has no effect in this MySQL version.'));
553 $privTable[2][] = array('Repl_client', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.'));
554 $privTable[2][] = array('Repl_slave', 'REPLICATION SLAVE', __('Needed for the replication slaves.'));
555 $privTable[2][] = array('Create_user', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.'));
557 echo '<input type="hidden" name="grant_count" value="'
558 . (count($privTable[0]) +
count($privTable[1]) +
count($privTable[2]) - (isset($row['Grant_priv']) ?
1 : 0))
560 . '<fieldset id="fieldset_user_global_rights">' . "\n"
564 ?
__('Global privileges')
566 ?
__('Database-specific privileges')
567 : __('Table-specific privileges'))) . "\n"
568 . ' (<a href="server_privileges.php?'
569 . $GLOBALS['url_query'] . '&checkall=1" onclick="setCheckboxes(\'usersForm\', true); return false;">'
570 . __('Check All') . '</a> /' . "\n"
571 . ' <a href="server_privileges.php?'
572 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'usersForm\', false); return false;">'
573 . __('Uncheck All') . '</a>)' . "\n"
574 . ' </legend>' . "\n"
575 . ' <p><small><i>' . __(' Note: MySQL privilege names are expressed in English ') . '</i></small></p>' . "\n"
576 . ' <fieldset>' . "\n"
577 . ' <legend>' . __('Data') . '</legend>' . "\n";
578 foreach ($privTable[0] as $priv)
580 echo ' <div class="item">' . "\n"
581 . ' <input type="checkbox"'
582 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
583 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
584 . '_priv" value="Y" '
585 . ($row[$priv[0] . '_priv'] == 'Y' ?
'checked="checked" ' : '')
586 . 'title="' . $priv[2] . '"/>' . "\n"
587 . ' <label for="checkbox_' . $priv[0]
588 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
589 . '</dfn></tt></label>' . "\n"
592 echo ' </fieldset>' . "\n"
593 . ' <fieldset>' . "\n"
594 . ' <legend>' . __('Structure') . '</legend>' . "\n";
595 foreach ($privTable[1] as $priv)
597 echo ' <div class="item">' . "\n"
598 . ' <input type="checkbox"'
599 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
600 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
601 . '_priv" value="Y" '
602 . ($row[$priv[0] . '_priv'] == 'Y' ?
'checked="checked" ' : '')
603 . 'title="' . $priv[2] . '"/>' . "\n"
604 . ' <label for="checkbox_' . $priv[0]
605 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
606 . '</dfn></tt></label>' . "\n"
609 echo ' </fieldset>' . "\n"
610 . ' <fieldset>' . "\n"
611 . ' <legend>' . __('Administration') . '</legend>' . "\n";
612 foreach ($privTable[2] as $priv)
614 echo ' <div class="item">' . "\n"
615 . ' <input type="checkbox"'
616 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
617 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
618 . '_priv" value="Y" '
619 . ($row[$priv[0] . '_priv'] == 'Y' ?
'checked="checked" ' : '')
620 . 'title="' . $priv[2] . '"/>' . "\n"
621 . ' <label for="checkbox_' . $priv[0]
622 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
623 . '</dfn></tt></label>' . "\n"
627 echo ' </fieldset>' . "\n";
628 // The "Resource limits" box is not displayed for db-specific privs
630 echo ' <fieldset>' . "\n"
631 . ' <legend>' . __('Resource limits') . '</legend>' . "\n"
632 . ' <p><small><i>' . __('Note: Setting these options to 0 (zero) removes the limit.') . '</i></small></p>' . "\n"
633 . ' <div class="item">' . "\n"
634 . ' <label for="text_max_questions"><tt><dfn title="'
635 . __('Limits the number of queries the user may send to the server per hour.') . '">MAX QUERIES PER HOUR</dfn></tt></label>' . "\n"
636 . ' <input type="text" name="max_questions" id="text_max_questions" value="'
637 . $row['max_questions'] . '" size="11" maxlength="11" title="' . __('Limits the number of queries the user may send to the server per hour.') . '" />' . "\n"
639 . ' <div class="item">' . "\n"
640 . ' <label for="text_max_updates"><tt><dfn title="'
641 . __('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"
642 . ' <input type="text" name="max_updates" id="text_max_updates" value="'
643 . $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"
645 . ' <div class="item">' . "\n"
646 . ' <label for="text_max_connections"><tt><dfn title="'
647 . __('Limits the number of new connections the user may open per hour.') . '">MAX CONNECTIONS PER HOUR</dfn></tt></label>' . "\n"
648 . ' <input type="text" name="max_connections" id="text_max_connections" value="'
649 . $row['max_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of new connections the user may open per hour.') . '" />' . "\n"
651 . ' <div class="item">' . "\n"
652 . ' <label for="text_max_user_connections"><tt><dfn title="'
653 . __('Limits the number of simultaneous connections the user may have.') . '">MAX USER_CONNECTIONS</dfn></tt></label>' . "\n"
654 . ' <input type="text" name="max_user_connections" id="text_max_user_connections" value="'
655 . $row['max_user_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of simultaneous connections the user may have.') . '" />' . "\n"
657 . ' </fieldset>' . "\n";
660 echo ' <div class="clearfloat"></div>' . "\n";
662 echo '</fieldset>' . "\n";
664 echo '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">' . "\n"
665 . ' <input type="submit" name="update_privs" value="' . __('Go') . '" />' . "\n"
666 . '</fieldset>' . "\n";
668 } // end of the 'PMA_displayPrivTable()' function
672 * Displays the fields used by the "new user" form as well as the
673 * "change login information / copy user" form.
675 * @param string $mode are we creating a new user or are we just
676 * changing one? (allowed values: 'new', 'change')
677 * @global array $cfg the phpMyAdmin configuration
678 * @global ressource $user_link the database connection
682 function PMA_displayLoginInformationFields($mode = 'new')
684 // Get user/host name lengths
685 $fields_info = PMA_DBI_get_fields('mysql', 'user');
686 $username_length = 16;
687 $hostname_length = 41;
688 foreach ($fields_info as $key => $val) {
689 if ($val['Field'] == 'User') {
690 strtok($val['Type'], '()');
693 $username_length = $v;
695 } elseif ($val['Field'] == 'Host') {
696 strtok($val['Type'], '()');
699 $hostname_length = $v;
705 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
706 $GLOBALS['pred_username'] = 'any';
708 echo '<fieldset id="fieldset_add_user_login">' . "\n"
709 . '<legend>' . __('Login Information') . '</legend>' . "\n"
710 . '<div class="item">' . "\n"
711 . '<label for="select_pred_username">' . "\n"
712 . ' ' . __('User name') . ':' . "\n"
714 . '<span class="options">' . "\n"
715 . ' <select name="pred_username" id="select_pred_username" title="' . __('User name') . '"' . "\n"
716 . ' onchange="if (this.value == \'any\') { username.value = \'\'; } else if (this.value == \'userdefined\') { username.focus(); username.select(); }">' . "\n"
717 . ' <option value="any"' . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any') ?
' selected="selected"' : '') . '>' . __('Any user') . '</option>' . "\n"
718 . ' <option value="userdefined"' . ((!isset($GLOBALS['pred_username']) ||
$GLOBALS['pred_username'] == 'userdefined') ?
' selected="selected"' : '') . '>' . __('Use text field') . ':</option>' . "\n"
719 . ' </select>' . "\n"
721 . '<input type="text" name="username" maxlength="'
722 . $username_length . '" title="' . __('User name') . '"'
723 . (empty($GLOBALS['username'])
725 : ' value="' . htmlspecialchars(isset($GLOBALS['new_username'])
726 ?
$GLOBALS['new_username']
727 : $GLOBALS['username']) . '"')
728 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
730 . '<div class="item">' . "\n"
731 . '<label for="select_pred_hostname">' . "\n"
732 . ' ' . __('Host') . ':' . "\n"
734 . '<span class="options">' . "\n"
735 . ' <select name="pred_hostname" id="select_pred_hostname" title="' . __('Host') . '"' . "\n";
736 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
737 if (! empty($_current_user)) {
738 $thishost = str_replace("'", '', substr($_current_user, (strrpos($_current_user, '@') +
1)));
739 if ($thishost == 'localhost' ||
$thishost == '127.0.0.1') {
743 echo ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } else if (this.value == \'localhost\') { hostname.value = \'localhost\'; } '
744 . (empty($thishost) ?
'' : 'else if (this.value == \'thishost\') { hostname.value = \'' . addslashes(htmlspecialchars($thishost)) . '\'; } ')
745 . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } else if (this.value == \'userdefined\') { hostname.focus(); hostname.select(); }">' . "\n";
746 unset($_current_user);
748 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
749 if (!isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
750 switch (strtolower($GLOBALS['hostname'])) {
753 $GLOBALS['pred_hostname'] = 'localhost';
756 $GLOBALS['pred_hostname'] = 'any';
759 $GLOBALS['pred_hostname'] = 'userdefined';
763 echo ' <option value="any"'
764 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
765 ?
' selected="selected"' : '') . '>' . __('Any host')
767 . ' <option value="localhost"'
768 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'localhost')
769 ?
' selected="selected"' : '') . '>' . __('Local')
770 . '</option>' . "\n";
771 if (!empty($thishost)) {
772 echo ' <option value="thishost"'
773 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'thishost')
774 ?
' selected="selected"' : '') . '>' . __('This Host')
775 . '</option>' . "\n";
778 echo ' <option value="hosttable"'
779 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'hosttable')
780 ?
' selected="selected"' : '') . '>' . __('Use Host Table')
782 . ' <option value="userdefined"'
783 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'userdefined')
784 ?
' selected="selected"' : '')
785 . '>' . __('Use text field') . ':</option>' . "\n"
786 . ' </select>' . "\n"
788 . '<input type="text" name="hostname" maxlength="'
789 . $hostname_length . '" value="'
790 . htmlspecialchars(isset($GLOBALS['hostname']) ?
$GLOBALS['hostname'] : '')
791 . '" title="' . __('Host')
792 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
793 . PMA_showHint(__('When Host table is used, this field is ignored and values stored in Host table are used instead.'))
795 . '<div class="item">' . "\n"
796 . '<label for="select_pred_password">' . "\n"
797 . ' ' . __('Password') . ':' . "\n"
799 . '<span class="options">' . "\n"
800 . ' <select name="pred_password" id="select_pred_password" title="'
801 . __('Password') . '"' . "\n"
802 . ' onchange="if (this.value == \'none\') { pma_pw.value = \'\'; pma_pw2.value = \'\'; } else if (this.value == \'userdefined\') { pma_pw.focus(); pma_pw.select(); }">' . "\n"
803 . ($mode == 'change' ?
' <option value="keep" selected="selected">' . __('Do not change the password') . '</option>' . "\n" : '')
804 . ' <option value="none"';
805 if (isset($GLOBALS['username']) && $mode != 'change') {
806 echo ' selected="selected"';
808 echo '>' . __('No Password') . '</option>' . "\n"
809 . ' <option value="userdefined"' . (isset($GLOBALS['username']) ?
'' : ' selected="selected"') . '>' . __('Use text field') . ':</option>' . "\n"
810 . ' </select>' . "\n"
812 . '<input type="password" id="text_pma_pw" name="pma_pw" title="' . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
814 . '<div class="item" id="div_element_before_generate_password">' . "\n"
815 . '<label for="text_pma_pw2">' . "\n"
816 . ' ' . __('Re-type') . ':' . "\n"
818 . '<span class="options"> </span>' . "\n"
819 . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="' . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
821 // Generate password added here via jQuery
822 . '</fieldset>' . "\n";
823 } // end of the 'PMA_displayUserAndHostFields()' function
826 * Changes / copies a user, part I
828 if (isset($_REQUEST['change_copy'])) {
829 $user_host_condition =
831 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
833 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\';';
834 $row = PMA_DBI_fetch_single_row('SELECT * FROM `mysql`.`user` ' . $user_host_condition);
836 PMA_Message
::notice(__('No user found.'))->display();
837 unset($_REQUEST['change_copy']);
839 extract($row, EXTR_OVERWRITE
);
840 // Recent MySQL versions have the field "Password" in mysql.user,
841 // so the previous extract creates $Password but this script
843 if (!isset($password) && isset($Password)) {
844 $password = $Password;
853 * (Changes / copies a user, part II)
855 if (isset($_REQUEST['adduser_submit']) ||
isset($_REQUEST['change_copy'])) {
857 if ($pred_username == 'any') {
860 switch ($pred_hostname) {
865 $hostname = 'localhost';
871 $_user_name = PMA_DBI_fetch_value('SELECT USER()');
872 $hostname = substr($_user_name, (strrpos($_user_name, '@') +
1));
876 $sql = "SELECT '1' FROM `mysql`.`user`"
877 . " WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
878 . " AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
879 if (PMA_DBI_fetch_value($sql) == 1) {
880 $message = PMA_Message
::error(__('The user %s already exists!'));
881 $message->addParam('[i]\'' . $username . '\'@\'' . $hostname . '\'[/i]');
882 $_REQUEST['adduser'] = true;
885 $create_user_real = 'CREATE USER \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
888 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
889 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
890 if ($pred_password != 'none' && $pred_password != 'keep') {
891 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
892 $real_sql_query .= ' IDENTIFIED BY \'' . PMA_sqlAddslashes($pma_pw) . '\'';
893 if (isset($create_user_real)) {
894 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
895 $create_user_real .= ' IDENTIFIED BY \'' . PMA_sqlAddslashes($pma_pw) . '\'';
898 if ($pred_password == 'keep' && !empty($password)) {
899 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
900 if (isset($create_user_real)) {
901 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
904 $sql_query = $real_sql_query;
905 if (isset($create_user_real)) {
906 $create_user_show = $create_user_real;
910 * @todo similar code appears twice in this script
912 if ((isset($Grant_priv) && $Grant_priv == 'Y')
913 ||
(isset($max_questions) ||
isset($max_connections)
914 ||
isset($max_updates) ||
isset($max_user_connections))) {
915 $real_sql_query .= ' WITH';
916 $sql_query .= ' WITH';
917 if (isset($Grant_priv) && $Grant_priv == 'Y') {
918 $real_sql_query .= ' GRANT OPTION';
919 $sql_query .= ' GRANT OPTION';
921 if (isset($max_questions)) {
922 // avoid negative values
923 $max_questions = max(0, (int)$max_questions);
924 $real_sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
925 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
927 if (isset($max_connections)) {
928 $max_connections = max(0, (int)$max_connections);
929 $real_sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
930 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
932 if (isset($max_updates)) {
933 $max_updates = max(0, (int)$max_updates);
934 $real_sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
935 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
937 if (isset($max_user_connections)) {
938 $max_user_connections = max(0, (int)$max_user_connections);
939 $real_sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
940 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
943 if (isset($create_user_real)) {
944 $create_user_real .= ';';
945 $create_user_show .= ';';
947 $real_sql_query .= ';';
949 if (empty($_REQUEST['change_copy'])) {
952 if (isset($create_user_real)) {
953 if (! PMA_DBI_try_query($create_user_real)) {
956 $sql_query = $create_user_show . $sql_query;
959 if ($_error ||
! PMA_DBI_try_query($real_sql_query)) {
960 $_REQUEST['createdb'] = false;
961 $message = PMA_Message
::rawError(PMA_DBI_getError());
963 $message = PMA_Message
::success(__('You have added a new user.'));
966 switch (PMA_ifSetOr($_REQUEST['createdb'], '0')) {
968 // Create database with same name and grant all privileges
969 $q = 'CREATE DATABASE IF NOT EXISTS '
970 . PMA_backquote(PMA_sqlAddslashes($username)) . ';';
972 if (! PMA_DBI_try_query($q)) {
973 $message = PMA_Message
::rawError(PMA_DBI_getError());
976 $GLOBALS['reload'] = TRUE;
977 PMA_reloadNavigation();
979 $q = 'GRANT ALL PRIVILEGES ON '
980 . PMA_backquote(PMA_sqlAddslashes($username)) . '.* TO \''
981 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
983 if (! PMA_DBI_try_query($q)) {
984 $message = PMA_Message
::rawError(PMA_DBI_getError());
988 // Grant all privileges on wildcard name (username\_%)
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 the specified database to the new user
999 $q = 'GRANT ALL PRIVILEGES ON '
1000 . PMA_backquote(PMA_sqlAddslashes($dbname)) . '.* TO \''
1001 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1003 if (! PMA_DBI_try_query($q)) {
1004 $message = PMA_Message
::rawError(PMA_DBI_getError());
1012 if (isset($create_user_real)) {
1013 $queries[] = $create_user_real;
1015 $queries[] = $real_sql_query;
1016 // we put the query containing the hidden password in
1017 // $queries_for_display, at the same position occupied
1018 // by the real query in $queries
1019 $tmp_count = count($queries);
1020 if (isset($create_user_real)) {
1021 $queries_for_display[$tmp_count - 2] = $create_user_show;
1023 $queries_for_display[$tmp_count - 1] = $sql_query;
1025 unset($res, $real_sql_query);
1031 * Changes / copies a user, part III
1033 if (isset($_REQUEST['change_copy'])) {
1034 $user_host_condition =
1036 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1038 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\';';
1039 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1040 while ($row = PMA_DBI_fetch_assoc($res)) {
1042 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1043 .' ON ' . PMA_backquote($row['Db']) . '.*'
1044 .' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1045 . ($row['Grant_priv'] == 'Y' ?
' WITH GRANT OPTION;' : ';');
1047 PMA_DBI_free_result($res);
1048 $res = PMA_DBI_query(
1049 'SELECT `Db`, `Table_name`, `Table_priv`'
1050 .' FROM `mysql`.`tables_priv`' . $user_host_condition,
1051 $GLOBALS['userlink'], PMA_DBI_QUERY_STORE
);
1052 while ($row = PMA_DBI_fetch_assoc($res)) {
1054 $res2 = PMA_DBI_QUERY(
1055 'SELECT `Column_name`, `Column_priv`'
1056 .' FROM `mysql`.`columns_priv`'
1058 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1060 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\''
1062 .' = \'' . PMA_sqlAddslashes($row['Db']) . "'"
1063 .' AND `Table_name`'
1064 .' = \'' . PMA_sqlAddslashes($row['Table_name']) . "'"
1066 null, PMA_DBI_QUERY_STORE
);
1068 $tmp_privs1 = PMA_extractPrivInfo($row);
1069 $tmp_privs2 = array(
1070 'Select' => array(),
1071 'Insert' => array(),
1072 'Update' => array(),
1073 'References' => array()
1076 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1077 $tmp_array = explode(',', $row2['Column_priv']);
1078 if (in_array('Select', $tmp_array)) {
1079 $tmp_privs2['Select'][] = $row2['Column_name'];
1081 if (in_array('Insert', $tmp_array)) {
1082 $tmp_privs2['Insert'][] = $row2['Column_name'];
1084 if (in_array('Update', $tmp_array)) {
1085 $tmp_privs2['Update'][] = $row2['Column_name'];
1087 if (in_array('References', $tmp_array)) {
1088 $tmp_privs2['References'][] = $row2['Column_name'];
1092 if (count($tmp_privs2['Select']) > 0 && !in_array('SELECT', $tmp_privs1)) {
1093 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1095 if (count($tmp_privs2['Insert']) > 0 && !in_array('INSERT', $tmp_privs1)) {
1096 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1098 if (count($tmp_privs2['Update']) > 0 && !in_array('UPDATE', $tmp_privs1)) {
1099 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1101 if (count($tmp_privs2['References']) > 0 && !in_array('REFERENCES', $tmp_privs1)) {
1102 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1106 'GRANT ' . join(', ', $tmp_privs1)
1107 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1108 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1109 . (in_array('Grant', explode(',', $row['Table_priv'])) ?
' WITH GRANT OPTION;' : ';');
1115 * Updates privileges
1117 if (!empty($update_privs)) {
1118 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, (isset($tablename) ?
$tablename : ''));
1121 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1122 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1123 if (!isset($Grant_priv) ||
$Grant_priv != 'Y') {
1125 'REVOKE GRANT OPTION ON ' . $db_and_table
1126 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1131 // Should not do a GRANT USAGE for a table-specific privilege, it
1132 // causes problems later (cannot revoke it)
1133 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1135 'GRANT ' . join(', ', PMA_extractPrivInfo())
1136 . ' ON ' . $db_and_table
1137 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
1140 * @todo similar code appears twice in this script
1142 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1143 ||
(! isset($dbname)
1144 && (isset($max_questions) ||
isset($max_connections)
1145 ||
isset($max_updates) ||
isset($max_user_connections))))
1147 $sql_query2 .= 'WITH';
1148 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1149 $sql_query2 .= ' GRANT OPTION';
1151 if (isset($max_questions)) {
1152 $max_questions = max(0, (int)$max_questions);
1153 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1155 if (isset($max_connections)) {
1156 $max_connections = max(0, (int)$max_connections);
1157 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1159 if (isset($max_updates)) {
1160 $max_updates = max(0, (int)$max_updates);
1161 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1163 if (isset($max_user_connections)) {
1164 $max_user_connections = max(0, (int)$max_user_connections);
1165 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1170 if (! PMA_DBI_try_query($sql_query0)) {
1171 // this query may fail, but this does not matter :o)
1174 if (isset($sql_query1) && !PMA_DBI_try_query($sql_query1)) {
1175 // this one may fail, too...
1178 if (isset($sql_query2)) {
1179 PMA_DBI_query($sql_query2);
1183 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1184 $message = PMA_Message
::success(__('You have updated the privileges for %s.'));
1185 $message->addParam('\'' . $username . '\'@\'' . $hostname . '\'');
1190 * Revokes Privileges
1192 if (isset($_REQUEST['revokeall'])) {
1193 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, isset($tablename) ?
$tablename : '');
1196 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1197 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1199 'REVOKE GRANT OPTION ON ' . $db_and_table
1200 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1202 PMA_DBI_query($sql_query0);
1203 if (! PMA_DBI_try_query($sql_query1)) {
1204 // this one may fail, too...
1207 $sql_query = $sql_query0 . ' ' . $sql_query1;
1208 $message = PMA_Message
::success(__('You have revoked the privileges for %s'));
1209 $message->addParam('\'' . $username . '\'@\'' . $hostname . '\'');
1210 if (! isset($tablename)) {
1219 * Updates the password
1221 if (isset($_REQUEST['change_pw'])) {
1222 // similar logic in user_password.php
1225 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1226 if ($pma_pw != $pma_pw2) {
1227 $message = PMA_Message
::error(__('The passwords aren\'t the same!'));
1228 } elseif (empty($pma_pw) ||
empty($pma_pw2)) {
1229 $message = PMA_Message
::error(__('The password is empty!'));
1233 // here $nopass could be == 1
1234 if (empty($message)) {
1236 $hashing_function = (!empty($pw_hash) && $pw_hash == 'old' ?
'OLD_' : '')
1239 // in $sql_query which will be displayed, hide the password
1240 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ?
'\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1241 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ?
'\'\'' : $hashing_function . '(\'' . PMA_sqlAddslashes($pma_pw) . '\')');
1242 PMA_DBI_try_query($local_query)
1243 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, FALSE, $err_url);
1244 $message = PMA_Message
::success(__('The password for %s was changed successfully.'));
1245 $message->addParam('\'' . $username . '\'@\'' . $hostname . '\'');
1252 * (Changes / copies a user, part IV)
1255 if (isset($_REQUEST['delete']) ||
(isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1256 if (isset($_REQUEST['change_copy'])) {
1257 $selected_usr = array($old_username . '&#27;' . $old_hostname);
1259 $selected_usr = $_REQUEST['selected_usr'];
1262 foreach ($selected_usr as $each_user) {
1263 list($this_user, $this_host) = explode('&#27;', $each_user);
1264 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1265 $queries[] = 'DROP USER \'' . PMA_sqlAddslashes($this_user) . '\'@\'' . PMA_sqlAddslashes($this_host) . '\';';
1267 if (isset($_REQUEST['drop_users_db'])) {
1268 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1269 $GLOBALS['reload'] = TRUE;
1270 PMA_reloadNavigation();
1273 if (empty($_REQUEST['change_copy'])) {
1274 if (empty($queries)) {
1275 $message = PMA_Message
::error(__('No users selected for deleting!'));
1277 if ($_REQUEST['mode'] == 3) {
1278 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1279 $queries[] = 'FLUSH PRIVILEGES;';
1281 $drop_user_error = '';
1282 foreach ($queries as $sql_query) {
1283 if ($sql_query{0} != '#') {
1284 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1285 $drop_user_error .= PMA_DBI_getError() . "\n";
1289 $sql_query = join("\n", $queries);
1290 if (! empty($drop_user_error)) {
1291 $message = PMA_Message
::rawError($drop_user_error);
1293 $message = PMA_Message
::success(__('The selected users have been deleted successfully.'));
1302 * Changes / copies a user, part V
1304 if (isset($_REQUEST['change_copy'])) {
1306 foreach ($queries as $sql_query) {
1307 if ($sql_query{0} != '#') {
1308 PMA_DBI_query($sql_query);
1310 // when there is a query containing a hidden password, take it
1311 // instead of the real query sent
1312 if (isset($queries_for_display[$tmp_count])) {
1313 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1317 $message = PMA_Message
::success();
1318 $sql_query = join("\n", $queries);
1323 * Reloads the privilege tables into memory
1325 if (isset($_REQUEST['flush_privileges'])) {
1326 $sql_query = 'FLUSH PRIVILEGES;';
1327 PMA_DBI_query($sql_query);
1328 $message = PMA_Message
::success(__('The privileges were reloaded successfully.'));
1333 * Displays the links
1335 if (isset($viewing_mode) && $viewing_mode == 'db') {
1337 $url_query .= '&goto=db_operations.php';
1339 // Gets the database structure
1340 $sub_part = '_structure';
1341 require './libraries/db_info.inc.php';
1344 require './libraries/server_links.inc.php';
1349 * defines some standard links
1351 $link_edit = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1352 . '&username=%s'
1353 . '&hostname=%s'
1355 . '&tablename=%s">'
1356 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1359 $link_revoke = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1360 . '&username=%s'
1361 . '&hostname=%s'
1363 . '&tablename=%s'
1364 . '&revokeall=1">'
1365 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1368 $link_export = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1369 . '&username=%s'
1370 . '&hostname=%s'
1373 . PMA_getIcon('b_tblexport.png', __('Export'))
1380 // export user definition
1381 if (isset($_REQUEST['export'])) {
1382 echo '<h2>' . __('User') . ' \'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'</h2>';
1383 echo '<textarea cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1384 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddslashes($username) . "'@'" . PMA_sqlAddslashes($hostname) . "'");
1385 foreach($grants as $one_grant) {
1386 echo $one_grant . ";\n\n";
1389 unset($username, $hostname, $grants, $one_grant);
1392 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) ||
! strlen($checkprivs))) {
1393 if (! isset($username)) {
1394 // No username is given --> display the overview
1396 . PMA_getIcon('b_usrlist.png')
1397 . __('User overview') . "\n"
1402 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1403 ' FROM `mysql`.`user`';
1405 $sql_query .= (isset($initial) ?
PMA_RangeOfUsers($initial) : '');
1407 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1408 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE
);
1411 // the query failed! This may have two reasons:
1412 // - the user does not have enough privileges
1413 // - the privilege tables use a structure of an earlier version.
1414 // so let's try a more simple query
1416 $sql_query = 'SELECT * FROM `mysql`.`user`';
1417 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE
);
1420 PMA_Message
::error(__('No Privileges'))->display();
1421 PMA_DBI_free_result($res);
1424 // This message is hardcoded because I will replace it by
1425 // a automatic repair feature soon.
1426 $raw = 'Your privilege table structure seems to be older than'
1427 . ' this MySQL version!<br />'
1428 . 'Please run the <tt>mysql_upgrade</tt> command'
1429 . '(<tt>mysql_fix_privilege_tables</tt> on older systems)'
1430 . ' that should be included in your MySQL server distribution'
1431 . ' to solve this problem!';
1432 PMA_Message
::rawError($raw)->display();
1436 // we also want users not in table `user` but in other table
1437 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1439 $tables_to_search_for_users = array(
1440 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1443 $db_rights_sqls = array();
1444 foreach ($tables_to_search_for_users as $table_search_in) {
1445 if (in_array($table_search_in, $tables)) {
1446 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ?
PMA_RangeOfUsers($initial) : '');
1450 $user_defaults = array(
1454 'Grant_priv' => 'N',
1455 'privs' => array('USAGE'),
1458 // for all initials, even non A-Z
1459 $array_initials = array();
1461 $db_rights = array();
1463 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1464 .' ORDER BY `User` ASC, `Host` ASC';
1466 $db_rights_result = PMA_DBI_query($db_rights_sql);
1468 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1469 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1470 $db_rights[$db_rights_row['User']][$db_rights_row['Host']] =
1473 PMA_DBI_free_result($db_rights_result);
1474 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1478 * Displays the initials
1481 // initialize to FALSE the letters A-Z
1482 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++
) {
1483 if (! isset($array_initials[chr($letter_counter +
64)])) {
1484 $array_initials[chr($letter_counter +
64)] = FALSE;
1488 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE
);
1489 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1490 $array_initials[$tmp_initial] = TRUE;
1493 // Display the initials, which can be any characters, not
1494 // just letters. For letters A-Z, we add the non-used letters
1497 uksort($array_initials, "strnatcasecmp");
1499 echo '<table cellspacing="5"><tr>';
1500 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1501 if ($initial_was_found) {
1502 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1504 echo '<td>' . $tmp_initial . '</td>';
1507 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&showall=1">[' . __('Show all') . ']</a></td>' . "\n";
1508 echo '</tr></table>';
1511 * Display the user overview
1512 * (if less than 50 users, display them immediately)
1515 if (isset($initial) ||
isset($showall) ||
PMA_DBI_num_rows($res) < 50) {
1517 while ($row = PMA_DBI_fetch_assoc($res)) {
1518 $row['privs'] = PMA_extractPrivInfo($row, true);
1519 $db_rights[$row['User']][$row['Host']] = $row;
1521 @PMA_DBI_free_result
($res);
1524 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1525 . PMA_generate_common_hidden_inputs('', '')
1526 . ' <table id="tableuserrights" class="data">' . "\n"
1528 . ' <tr><th></th>' . "\n"
1529 . ' <th>' . __('User') . '</th>' . "\n"
1530 . ' <th>' . __('Host') . '</th>' . "\n"
1531 . ' <th>' . __('Password') . '</th>' . "\n"
1532 . ' <th>' . __('Global privileges') . ' '
1533 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English ')) . '</th>' . "\n"
1534 . ' <th>' . __('Grant') . '</th>' . "\n"
1535 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1536 echo ' </tr>' . "\n";
1537 echo ' </thead>' . "\n";
1538 echo ' <tbody>' . "\n";
1540 $index_checkbox = -1;
1541 foreach ($db_rights as $user) {
1544 foreach ($user as $host) {
1546 echo ' <tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
1547 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1548 . $index_checkbox . '" value="'
1549 . htmlspecialchars($host['User'] . '&#27;' . $host['Host'])
1551 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
1553 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1554 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1556 switch ($host['Password']) {
1561 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1563 // this happens if this is a definition not coming from mysql.user
1565 echo '--'; // in future version, replace by "not present"
1569 . ' <td><tt>' . "\n"
1570 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1571 . ' </tt></td>' . "\n"
1572 . ' <td>' . ($host['Grant_priv'] == 'Y' ?
__('Yes') : __('No')) . '</td>' . "\n"
1573 . ' <td align="center">';
1574 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1576 echo '<td align="center">';
1577 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ?
$initial : ''));
1580 $odd_row = ! $odd_row;
1584 unset($user, $host, $odd_row);
1585 echo ' </tbody></table>' . "\n"
1586 .'<img class="selectallarrow"'
1587 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1588 .' width="38" height="22"'
1589 .' alt="' . __('With selected:') . '" />' . "\n"
1590 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&checkall=1"'
1591 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1592 . __('Check All') . '</a>' . "\n"
1594 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1595 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1596 . __('Uncheck All') . '</a>' . "\n";
1598 // add/delete user fieldset
1599 echo ' <fieldset id="fieldset_add_user">' . "\n"
1600 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1">' . "\n"
1601 . PMA_getIcon('b_usradd.png')
1602 . ' ' . __('Add a new User') . '</a>' . "\n"
1603 . ' </fieldset>' . "\n"
1604 . ' <fieldset id="fieldset_delete_user">'
1605 . ' <legend>' . "\n"
1606 . PMA_getIcon('b_usrdrop.png')
1607 . ' ' . __('Remove selected users') . '' . "\n"
1608 . ' </legend>' . "\n"
1609 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1610 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1611 . ' <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"
1612 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1613 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1614 . ' </label>' . "\n"
1615 . ' </fieldset>' . "\n"
1616 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1617 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" />' . "\n"
1618 . ' </fieldset>' . "\n"
1623 echo ' <fieldset id="fieldset_add_user">' . "\n"
1624 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1">' . "\n"
1625 . PMA_getIcon('b_usradd.png')
1626 . ' ' . __('Add a new User') . '</a>' . "\n"
1627 . ' </fieldset>' . "\n";
1628 } // end if (display overview)
1629 $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
);
1630 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&flush_privileges=1">', false);
1631 $flushnote->addParam('</a>', false);
1632 $flushnote->display();
1638 // A user was selected -> display the user's properties
1641 . PMA_getIcon('b_usredit.png')
1642 . __('Edit Privileges') . ': '
1645 if (isset($dbname)) {
1646 echo ' <i><a href="server_privileges.php?'
1647 . $GLOBALS['url_query'] . '&username=' . urlencode($username)
1648 . '&hostname=' . urlencode($hostname) . '&dbname=&tablename=">\''
1649 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1650 . '\'</a></i>' . "\n";
1651 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
1653 echo ' - ' . ($dbname_is_wildcard ?
__('Databases') : __('Database') );
1654 if (isset($tablename)) {
1655 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
1656 . '&username=' . urlencode($username) . '&hostname=' . urlencode($hostname)
1657 . '&dbname=' . $url_dbname . '&tablename=">' . htmlspecialchars($dbname) . '</a></i>';
1658 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
1660 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
1664 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1668 echo '</h2>' . "\n";
1671 $sql = "SELECT '1' FROM `mysql`.`user`"
1672 . " WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
1673 . " AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
1674 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
1676 if ($user_does_not_exists) {
1677 PMA_Message
::warning(__('The selected user was not found in the privilege table.'))->display();
1678 PMA_displayLoginInformationFields();
1679 //require_once './libraries/footer.inc.php';
1682 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n";
1684 'username' => $username,
1685 'hostname' => $hostname,
1687 if (isset($dbname)) {
1688 $_params['dbname'] = $dbname;
1689 if (isset($tablename)) {
1690 $_params['tablename'] = $tablename;
1693 echo PMA_generate_common_hidden_inputs($_params);
1695 PMA_displayPrivTable(PMA_ifSetOr($dbname, '*', 'length'),
1696 PMA_ifSetOr($tablename, '*', 'length'));
1698 echo '</form>' . "\n";
1700 if (! isset($tablename) && empty($dbname_is_wildcard)) {
1702 // no table name was given, display all table specific rights
1703 // but only if $dbname contains no wildcards
1706 echo '<form action="server_privileges.php" method="post">' . "\n"
1707 . PMA_generate_common_hidden_inputs('', '')
1708 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
1709 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1710 . '<fieldset>' . "\n"
1711 . '<legend>' . (! isset($dbname) ?
__('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
1712 . '<table class="data">' . "\n"
1714 . '<tr><th>' . (! isset($dbname) ?
__('Database') : __('Table')) . '</th>' . "\n"
1715 . ' <th>' . __('Privileges') . '</th>' . "\n"
1716 . ' <th>' . __('Grant') . '</th>' . "\n"
1717 . ' <th>' . (! isset($dbname) ?
__('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
1718 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
1723 $user_host_condition =
1725 . ' = \'' . PMA_sqlAddslashes($username) . "'"
1727 . ' = \'' . PMA_sqlAddslashes($hostname) . "'";
1732 // we also want privielgs for this user not in table `db` but in other table
1733 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1734 if (! isset($dbname)) {
1736 // no db name given, so we want all privs for the given user
1738 $tables_to_search_for_users = array(
1739 'tables_priv', 'columns_priv',
1742 $db_rights_sqls = array();
1743 foreach ($tables_to_search_for_users as $table_search_in) {
1744 if (in_array($table_search_in, $tables)) {
1745 $db_rights_sqls[] = '
1746 SELECT DISTINCT `Db`
1747 FROM `mysql`.' . PMA_backquote($table_search_in)
1748 . $user_host_condition;
1752 $user_defaults = array(
1754 'Grant_priv' => 'N',
1755 'privs' => array('USAGE'),
1756 'Table_privs' => true,
1760 $db_rights = array();
1762 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1763 .' ORDER BY `Db` ASC';
1765 $db_rights_result = PMA_DBI_query($db_rights_sql);
1767 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1768 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1769 // only Db names in the table `mysql`.`db` uses wildcards
1770 // as we are in the db specific rights display we want
1771 // all db names escaped, also from other sources
1772 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
1773 $db_rights_row['Db']);
1774 $db_rights[$db_rights_row['Db']] = $db_rights_row;
1777 PMA_DBI_free_result($db_rights_result);
1778 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1780 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
1781 $res = PMA_DBI_query($sql_query);
1784 while ($row = PMA_DBI_fetch_assoc($res)) {
1785 if (isset($db_rights[$row['Db']])) {
1786 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
1788 $db_rights[$row['Db']] = $row;
1790 // there are db specific rights for this user
1791 // so we can drop this db rights
1792 $db_rights[$row['Db']]['can_delete'] = true;
1794 PMA_DBI_free_result($res);
1799 // db name was given,
1800 // so we want all user specific rights for this db
1802 $user_host_condition .=
1804 .' LIKE \'' . PMA_sqlAddslashes($dbname) . "'";
1806 $tables_to_search_for_users = array(
1810 $db_rights_sqls = array();
1811 foreach ($tables_to_search_for_users as $table_search_in) {
1812 if (in_array($table_search_in, $tables)) {
1813 $db_rights_sqls[] = '
1814 SELECT DISTINCT `Table_name`
1815 FROM `mysql`.' . PMA_backquote($table_search_in)
1816 . $user_host_condition;
1820 $user_defaults = array(
1822 'Grant_priv' => 'N',
1823 'privs' => array('USAGE'),
1824 'Column_priv' => true,
1828 $db_rights = array();
1830 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1831 .' ORDER BY `Table_name` ASC';
1833 $db_rights_result = PMA_DBI_query($db_rights_sql);
1835 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1836 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1837 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
1839 PMA_DBI_free_result($db_rights_result);
1840 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1843 'SELECT `Table_name`,'
1845 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
1846 .' AS \'Column_priv\''
1847 .' FROM `mysql`.`tables_priv`'
1848 . $user_host_condition
1849 .' ORDER BY `Table_name` ASC;';
1850 $res = PMA_DBI_query($sql_query);
1853 while ($row = PMA_DBI_fetch_assoc($res)) {
1854 if (isset($db_rights[$row['Table_name']])) {
1855 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
1857 $db_rights[$row['Table_name']] = $row;
1860 PMA_DBI_free_result($res);
1866 if (count($db_rights) < 1) {
1867 echo '<tr class="odd">' . "\n"
1868 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
1872 $found_rows = array();
1873 //while ($row = PMA_DBI_fetch_assoc($res)) {
1874 foreach ($db_rights as $row) {
1875 $found_rows[] = (! isset($dbname)) ?
$row['Db'] : $row['Table_name'];
1877 echo '<tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
1878 . ' <td>' . htmlspecialchars((! isset($dbname)) ?
$row['Db'] : $row['Table_name']) . '</td>' . "\n"
1879 . ' <td><tt>' . "\n"
1880 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, TRUE)) . "\n"
1881 . ' </tt></td>' . "\n"
1882 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') ||
(isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ?
__('Yes') : __('No')) . '</td>' . "\n"
1884 if (! empty($row['Table_privs']) ||
! empty ($row['Column_priv'])) {
1891 printf($link_edit, urlencode($username),
1892 urlencode($hostname),
1893 urlencode((! isset($dbname)) ?
$row['Db'] : $dbname),
1894 urlencode((! isset($dbname)) ?
'' : $row['Table_name']));
1897 if (! empty($row['can_delete']) ||
isset($row['Table_name']) && strlen($row['Table_name'])) {
1898 printf($link_revoke, urlencode($username),
1899 urlencode($hostname),
1900 urlencode((! isset($dbname)) ?
$row['Db'] : $dbname),
1901 urlencode((! isset($dbname)) ?
'' : $row['Table_name']));
1905 $odd_row = ! $odd_row;
1909 echo '</tbody>' . "\n"
1910 . '</table>' . "\n";
1912 if (! isset($dbname)) {
1914 // no database name was given, display select db
1916 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
1918 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
1919 if (!empty($pred_db_array)) {
1920 echo ' <select name="pred_dbname" onchange="this.form.submit();">' . "\n"
1921 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
1922 foreach ($pred_db_array as $current_db) {
1923 $current_db = PMA_escape_mysql_wildcards($current_db);
1924 // cannot use array_diff() once, outside of the loop,
1925 // because the list of databases has special characters
1926 // already escaped in $found_rows,
1927 // contrary to the output of SHOW DATABASES
1928 if (empty($found_rows) ||
! in_array($current_db, $found_rows)) {
1929 echo ' <option value="' . htmlspecialchars($current_db) . '">'
1930 . htmlspecialchars($current_db) . '</option>' . "\n";
1933 echo ' </select>' . "\n";
1935 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
1936 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
1938 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
1939 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
1940 if ($res = @PMA_DBI_try_query
('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE
)) {
1941 $pred_tbl_array = array();
1942 while ($row = PMA_DBI_fetch_row($res)) {
1943 if (!isset($found_rows) ||
!in_array($row[0], $found_rows)) {
1944 $pred_tbl_array[] = $row[0];
1947 PMA_DBI_free_result($res);
1949 if (!empty($pred_tbl_array)) {
1950 echo ' <select name="pred_tablename" onchange="this.form.submit();">' . "\n"
1951 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
1952 foreach ($pred_tbl_array as $current_table) {
1953 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
1955 echo ' </select>' . "\n";
1960 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
1962 echo '</fieldset>' . "\n";
1963 echo '<fieldset class="tblFooters">' . "\n"
1964 . ' <input type="submit" value="' . __('Go') . '" />'
1965 . '</fieldset>' . "\n"
1970 // Provide a line with links to the relevant database and table
1971 if (isset($dbname) && empty($dbname_is_wildcard)) {
1972 echo '[ ' . __('Database')
1973 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
1974 . $GLOBALS['url_query'] . '&db=' . $url_dbname . '&reload=1">'
1975 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
1977 if (isset($tablename)) {
1978 echo ' [ ' . __('Table') . ' <a href="'
1979 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
1980 . '&db=' . $url_dbname . '&table=' . urlencode($tablename)
1981 . '&reload=1">' . htmlspecialchars($tablename) . ': '
1982 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
1988 if (! isset($dbname) && ! $user_does_not_exists) {
1989 require_once './libraries/display_change_password.lib.php';
1991 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
1992 . PMA_generate_common_hidden_inputs('', '')
1993 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
1994 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1995 . '<fieldset id="fieldset_change_copy_user">' . "\n"
1996 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
1997 PMA_displayLoginInformationFields('change');
1998 echo ' <fieldset>' . "\n"
1999 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2001 '4' => __('... keep the old one.'),
2002 '1' => __(' ... delete the old one from the user tables.'),
2003 '2' => __(' ... revoke all active privileges from the old one and delete it afterwards.'),
2004 '3' => __(' ... delete the old one from the user tables and reload the privileges afterwards.'));
2005 PMA_display_html_radio('mode', $choices, '4', true);
2008 echo ' </fieldset>' . "\n"
2009 . '</fieldset>' . "\n"
2010 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2011 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2012 . '</fieldset>' . "\n"
2016 } elseif (isset($_REQUEST['adduser'])) {
2018 $GLOBALS['url_query'] .= '&adduser=1';
2020 . PMA_getIcon('b_usradd.png') . __('Add a new User') . "\n"
2022 . '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post" onsubmit="return checkAddUser(this);">' . "\n"
2023 . PMA_generate_common_hidden_inputs('', '');
2024 PMA_displayLoginInformationFields('new');
2025 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2026 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2028 $default_choice = 0;
2030 '0' => _pgettext('Create none database for user', 'None'),
2031 '1' => __('Create database with same name and grant all privileges'),
2032 '2' => __('Grant all privileges on wildcard name (username\\_%)'));
2034 if ( !empty($dbname) ) {
2035 $choices['3'] = sprintf( __('Grant all privileges on database "%s"'), htmlspecialchars($dbname));
2036 $default_choice = 3;
2037 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2040 // 4th parameter set to true to add line breaks
2041 // 5th parameter set to false to avoid htmlspecialchars() escaping in the label
2042 // since we have some HTML in some labels
2043 PMA_display_html_radio('createdb', $choices, $default_choice, true, false);
2045 unset($default_choice);
2047 echo '</fieldset>' . "\n";
2048 PMA_displayPrivTable('*', '*', FALSE);
2049 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2050 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2051 . ' </fieldset>' . "\n"
2054 // check the privileges for a particular database.
2055 echo '<table id="tablespecificuserrights" class="data">' . "\n"
2056 . '<caption class="tblHeaders">' . "\n"
2057 . PMA_getIcon('b_usrcheck.png')
2058 . ' ' . sprintf(__('Users having access to "%s"'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2059 . '</caption>' . "\n"
2061 . ' <tr><th>' . __('User') . '</th>' . "\n"
2062 . ' <th>' . __('Host') . '</th>' . "\n"
2063 . ' <th>' . __('Type') . '</th>' . "\n"
2064 . ' <th>' . __('Privileges') . '</th>' . "\n"
2065 . ' <th>' . __('Grant') . '</th>' . "\n"
2066 . ' <th>' . __('Action') . '</th>' . "\n"
2071 unset($row, $row1, $row2);
2073 // now, we build the table...
2074 $list_of_privileges =
2086 . '`References_priv`, '
2087 . '`Create_tmp_table_priv`, '
2088 . '`Lock_tables_priv`, '
2089 . '`Create_view_priv`, '
2090 . '`Show_view_priv`, '
2091 . '`Create_routine_priv`, '
2092 . '`Alter_routine_priv`, '
2095 $list_of_compared_privileges =
2096 '`Select_priv` = \'N\''
2097 . ' AND `Insert_priv` = \'N\''
2098 . ' AND `Update_priv` = \'N\''
2099 . ' AND `Delete_priv` = \'N\''
2100 . ' AND `Create_priv` = \'N\''
2101 . ' AND `Drop_priv` = \'N\''
2102 . ' AND `Grant_priv` = \'N\''
2103 . ' AND `References_priv` = \'N\''
2104 . ' AND `Create_tmp_table_priv` = \'N\''
2105 . ' AND `Lock_tables_priv` = \'N\''
2106 . ' AND `Create_view_priv` = \'N\''
2107 . ' AND `Show_view_priv` = \'N\''
2108 . ' AND `Create_routine_priv` = \'N\''
2109 . ' AND `Alter_routine_priv` = \'N\''
2110 . ' AND `Execute_priv` = \'N\'';
2112 if (PMA_MYSQL_INT_VERSION
>= 50106) {
2113 $list_of_privileges .=
2116 $list_of_compared_privileges .=
2117 ' AND `Event_priv` = \'N\''
2118 . ' AND `Trigger_priv` = \'N\'';
2122 '(SELECT ' . $list_of_privileges . ', `Db`'
2123 .' FROM `mysql`.`db`'
2124 .' WHERE \'' . PMA_sqlAddslashes($checkprivs) . "'"
2126 .' AND NOT (' . $list_of_compared_privileges. ')) '
2128 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2129 .' FROM `mysql`.`user` '
2130 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2131 .' ORDER BY `User` ASC,'
2134 $res = PMA_DBI_query($sql_query);
2135 $row = PMA_DBI_fetch_assoc($res);
2142 // prepare the current user
2143 $current_privileges = array();
2144 $current_user = $row['User'];
2145 $current_host = $row['Host'];
2146 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2147 $current_privileges[] = $row;
2148 $row = PMA_DBI_fetch_assoc($res);
2150 echo ' <tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
2152 if (count($current_privileges) > 1) {
2153 echo ' rowspan="' . count($current_privileges) . '"';
2155 echo '>' . (empty($current_user) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2158 if (count($current_privileges) > 1) {
2159 echo ' rowspan="' . count($current_privileges) . '"';
2161 echo '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2162 foreach ($current_privileges as $current) {
2165 if (!isset($current['Db']) ||
$current['Db'] == '*') {
2167 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2168 echo __('database-specific');
2170 echo __('wildcard'), ': <tt>' . htmlspecialchars($current['Db']) . '</tt>';
2176 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, TRUE)) . "\n"
2180 . ' ' . ($current['Grant_priv'] == 'Y' ?
__('Yes') : __('No')) . "\n"
2183 printf($link_edit, urlencode($current_user),
2184 urlencode($current_host),
2185 urlencode(! isset($current['Db']) ||
$current['Db'] == '*' ?
'' : $current['Db']),
2190 if (empty($row) && empty($row1) && empty($row2)) {
2193 $odd_row = ! $odd_row;
2196 echo ' <tr class="odd">' . "\n"
2197 . ' <td colspan="6">' . "\n"
2198 . ' ' . __('No user found.') . "\n"
2202 echo '</tbody>' . "\n"
2203 . '</table>' . "\n";
2205 // Offer to create a new user for the current database
2206 echo '<fieldset id="fieldset_add_user">' . "\n"
2207 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1&dbname=' . $checkprivs .'">' . "\n"
2208 . PMA_getIcon('b_usradd.png')
2209 . ' ' . __('Add a new User') . '</a>' . "\n"
2210 . '</fieldset>' . "\n";
2212 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2216 * Displays the footer
2219 require_once './libraries/footer.inc.php';