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 require './libraries/server_common.inc.php';
22 * Messages are built using the message name
24 $strPrivDescAllPrivileges = __('Includes all privileges except GRANT.');
25 $strPrivDescAlter = __('Allows altering the structure of existing tables.');
26 $strPrivDescAlterRoutine = __('Allows altering and dropping stored routines.');
27 $strPrivDescCreateDb = __('Allows creating new databases and tables.');
28 $strPrivDescCreateRoutine = __('Allows creating stored routines.');
29 $strPrivDescCreateTbl = __('Allows creating new tables.');
30 $strPrivDescCreateTmpTable = __('Allows creating temporary tables.');
31 $strPrivDescCreateUser = __('Allows creating, dropping and renaming user accounts.');
32 $strPrivDescCreateView = __('Allows creating new views.');
33 $strPrivDescDelete = __('Allows deleting data.');
34 $strPrivDescDropDb = __('Allows dropping databases and tables.');
35 $strPrivDescDropTbl = __('Allows dropping tables.');
36 $strPrivDescEvent = __('Allows to set up events for the event scheduler');
37 $strPrivDescExecute = __('Allows executing stored routines.');
38 $strPrivDescFile = __('Allows importing data from and exporting data into files.');
39 $strPrivDescGrant = __('Allows adding users and privileges without reloading the privilege tables.');
40 $strPrivDescIndex = __('Allows creating and dropping indexes.');
41 $strPrivDescInsert = __('Allows inserting and replacing data.');
42 $strPrivDescLockTables = __('Allows locking tables for the current thread.');
43 $strPrivDescMaxConnections = __('Limits the number of new connections the user may open per hour.');
44 $strPrivDescMaxQuestions = __('Limits the number of queries the user may send to the server per hour.');
45 $strPrivDescMaxUpdates = __('Limits the number of commands that change any table or database the user may execute per hour.');
46 $strPrivDescMaxUserConnections = __('Limits the number of simultaneous connections the user may have.');
47 $strPrivDescProcess = __('Allows viewing processes of all users');
48 $strPrivDescReferences = __('Has no effect in this MySQL version.');
49 $strPrivDescReload = __('Allows reloading server settings and flushing the server\'s caches.');
50 $strPrivDescReplClient = __('Allows the user to ask where the slaves / masters are.');
51 $strPrivDescReplSlave = __('Needed for the replication slaves.');
52 $strPrivDescSelect = __('Allows reading data.');
53 $strPrivDescShowDb = __('Gives access to the complete list of databases.');
54 $strPrivDescShowView = __('Allows performing SHOW CREATE VIEW queries.');
55 $strPrivDescShutdown = __('Allows shutting down the server.');
56 $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.');
57 $strPrivDescTrigger = __('Allows creating and dropping triggers');
58 $strPrivDescUpdate = __('Allows changing data.');
59 $strPrivDescUsage = __('No privileges.');
62 * Checks if a dropdown box has been used for selecting a database / table
64 if (PMA_isValid($_REQUEST['pred_tablename'])) {
65 $tablename = $_REQUEST['pred_tablename'];
66 unset($pred_tablename);
67 } elseif (PMA_isValid($_REQUEST['tablename'])) {
68 $tablename = $_REQUEST['tablename'];
73 if (PMA_isValid($_REQUEST['pred_dbname'])) {
74 $dbname = $_REQUEST['pred_dbname'];
76 } elseif (PMA_isValid($_REQUEST['dbname'])) {
77 $dbname = $_REQUEST['dbname'];
84 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
85 if (isset($tablename)) {
86 $db_and_table .= PMA_backquote($tablename);
91 $db_and_table = '*.*';
94 // check if given $dbname is a wildcard or not
96 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
97 if (preg_match('/(?<!\\\\)(?:_|%)/i', $dbname)) {
98 $dbname_is_wildcard = true;
100 $dbname_is_wildcard = false;
105 * Checks if the user is allowed to do what he tries to...
107 if (!$is_superuser) {
108 require './libraries/server_links.inc.php';
110 . PMA_getIcon('b_usrlist.png')
111 . __('Privileges') . "\n"
113 PMA_Message
::error(__('No Privileges'))->display();
114 require_once './libraries/footer.inc.php';
118 * Escapes wildcard in a database+table specification
119 * before using it in a GRANT statement.
121 * Escaping a wildcard character in a GRANT is only accepted at the global
122 * or database level, not at table level; this is why I remove
123 * the escaping character. Internally, in mysql.tables_priv.Db there are
124 * no escaping (for example test_db) but in mysql.db you'll see test\_db
125 * for a db-specific privilege.
127 * @param string $db_and_table
128 * @param string $dbname
129 * @param string $tablename
130 * @return string the escaped (if necessary) $db_and_table
132 function PMA_WildcardEscapeForGrant($db_and_table, $dbname, $tablename) {
134 if (! strlen($dbname)) {
135 $db_and_table = '*.*';
137 if (strlen($tablename)) {
138 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
139 $db_and_table .= PMA_backquote($tablename);
141 $db_and_table = PMA_backquote($dbname) . '.';
142 $db_and_table .= '*';
145 return $db_and_table;
149 * Generates a condition on the user name
151 * @param string the user's initial
152 * @return string the generated condition
154 function PMA_RangeOfUsers($initial = '')
156 // strtolower() is used because the User field
157 // might be BINARY, so LIKE would be case sensitive
158 if (!empty($initial)) {
159 $ret = " WHERE `User` LIKE '" . $initial . "%'"
160 . " OR `User` LIKE '" . strtolower($initial) . "%'";
168 * Extracts the privilege information of a priv table row
170 * @param array $row the row
171 * @param boolean $enableHTML add <dfn> tag with tooltips
173 * @global ressource $user_link the database connection
177 function PMA_extractPrivInfo($row = '', $enableHTML = FALSE)
180 array('Select_priv', 'SELECT', __('Allows reading data.')),
181 array('Insert_priv', 'INSERT', __('Allows inserting and replacing data.')),
182 array('Update_priv', 'UPDATE', __('Allows changing data.')),
183 array('Delete_priv', 'DELETE', __('Allows deleting data.')),
184 array('Create_priv', 'CREATE', __('Allows creating new databases and tables.')),
185 array('Drop_priv', 'DROP', __('Allows dropping databases and tables.')),
186 array('Reload_priv', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.')),
187 array('Shutdown_priv', 'SHUTDOWN', __('Allows shutting down the server.')),
188 array('Process_priv', 'PROCESS', __('Allows viewing processes of all users')),
189 array('File_priv', 'FILE', __('Allows importing data from and exporting data into files.')),
190 array('References_priv', 'REFERENCES', __('Has no effect in this MySQL version.')),
191 array('Index_priv', 'INDEX', __('Allows creating and dropping indexes.')),
192 array('Alter_priv', 'ALTER', __('Allows altering the structure of existing tables.')),
193 array('Show_db_priv', 'SHOW DATABASES', __('Gives access to the complete list of databases.')),
194 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.')),
195 array('Create_tmp_table_priv', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
196 array('Lock_tables_priv', 'LOCK TABLES', __('Allows locking tables for the current thread.')),
197 array('Repl_slave_priv', 'REPLICATION SLAVE', __('Needed for the replication slaves.')),
198 array('Repl_client_priv', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.')),
199 array('Create_view_priv', 'CREATE VIEW', __('Allows creating new views.')),
200 array('Event_priv', 'EVENT', __('Allows to set up events for the event scheduler')),
201 array('Trigger_priv', 'TRIGGER', __('Allows creating and dropping triggers')),
203 array('Create View_priv', 'CREATE VIEW', __('Allows creating new views.')),
204 array('Show_view_priv', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
206 array('Show view_priv', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
207 array('Create_routine_priv', 'CREATE ROUTINE', __('Allows creating stored routines.')),
208 array('Alter_routine_priv', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
209 array('Create_user_priv', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.')),
210 array('Execute_priv', 'EXECUTE', __('Allows executing stored routines.')),
213 if (!empty($row) && isset($row['Table_priv'])) {
214 $row1 = PMA_DBI_fetch_single_row(
215 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
216 'ASSOC', $GLOBALS['userlink']);
217 $av_grants = explode('\',\'', substr($row1['Type'], 5, strlen($row1['Type']) - 7));
219 $users_grants = explode(',', $row['Table_priv']);
220 foreach ($av_grants as $current_grant) {
221 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ?
'Y' : 'N';
223 unset($current_grant);
225 unset($users_grants);
228 $allPrivileges = TRUE;
229 foreach ($grants as $current_grant) {
230 if ((!empty($row) && isset($row[$current_grant[0]]))
231 ||
(empty($row) && isset($GLOBALS[$current_grant[0]]))) {
232 if ((!empty($row) && $row[$current_grant[0]] == 'Y')
234 && ($GLOBALS[$current_grant[0]] == 'Y'
235 ||
(is_array($GLOBALS[$current_grant[0]])
236 && count($GLOBALS[$current_grant[0]]) == $GLOBALS['column_count']
237 && empty($GLOBALS[$current_grant[0] . '_none'])))))
240 $privs[] = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
242 $privs[] = $current_grant[1];
244 } elseif (!empty($GLOBALS[$current_grant[0]])
245 && is_array($GLOBALS[$current_grant[0]])
246 && empty($GLOBALS[$current_grant[0] . '_none'])) {
248 $priv_string = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
250 $priv_string = $current_grant[1];
252 $privs[] = $priv_string . ' (`' . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
254 $allPrivileges = FALSE;
260 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
264 } elseif ($allPrivileges && (!isset($GLOBALS['grant_count']) ||
count($privs) == $GLOBALS['grant_count'])) {
266 $privs = array('<dfn title="' . __('Includes all privileges except GRANT.') . '">ALL PRIVILEGES</dfn>');
268 $privs = array('ALL PRIVILEGES');
272 } // end of the 'PMA_extractPrivInfo()' function
275 * Displays on which column(s) a table-specific privilege is granted
277 function PMA_display_column_privs($columns, $row, $name_for_select,
278 $priv_for_header, $name, $name_for_dfn, $name_for_current)
280 echo ' <div class="item" id="div_item_' . $name . '">' . "\n"
281 . ' <label for="select_' . $name . '_priv">' . "\n"
282 . ' <tt><dfn title="' . $name_for_dfn . '">'
283 . $priv_for_header . '</dfn></tt>' . "\n"
284 . ' </label><br />' . "\n"
285 . ' <select id="select_' . $name . '_priv" name="'
286 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
288 foreach ($columns as $current_column => $current_column_privileges) {
289 echo ' <option value="' . htmlspecialchars($current_column) . '"';
290 if ($row[$name_for_select] == 'Y' ||
$current_column_privileges[$name_for_current]) {
291 echo ' selected="selected"';
293 echo '>' . htmlspecialchars($current_column) . '</option>' . "\n";
296 echo ' </select>' . "\n"
297 . ' <i>' . __('Or') . '</i>' . "\n"
298 . ' <label for="checkbox_' . $name_for_select
299 . '_none"><input type="checkbox"'
300 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
301 . ' name="' . $name_for_select . '_none" id="checkbox_'
302 . $name_for_select . '_none" title="' . _pgettext('None privileges', 'None') . '" />'
303 . _pgettext('None privileges', 'None') . '</label>' . "\n"
309 * Displays the privileges form table
311 * @param string $db the database
312 * @param string $table the table
313 * @param boolean $submit wheather to display the submit button or not
314 * @global array $cfg the phpMyAdmin configuration
315 * @global ressource $user_link the database connection
319 function PMA_displayPrivTable($db = '*', $table = '*', $submit = TRUE)
325 if (isset($GLOBALS['username'])) {
326 $username = $GLOBALS['username'];
327 $hostname = $GLOBALS['hostname'];
330 "SELECT * FROM `mysql`.`user`"
331 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
332 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
333 } elseif ($table == '*') {
335 "SELECT * FROM `mysql`.`db`"
336 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
337 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "'"
338 ." AND '" . PMA_unescape_mysql_wildcards($db) . "'"
342 "SELECT `Table_priv`"
343 ." FROM `mysql`.`tables_priv`"
344 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
345 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "'"
346 ." AND `Db` = '" . PMA_unescape_mysql_wildcards($db) . "'"
347 ." AND `Table_name` = '" . PMA_sqlAddslashes($table) . "';";
349 $row = PMA_DBI_fetch_single_row($sql_query);
354 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
355 } elseif ($table == '*') {
356 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
358 $res = PMA_DBI_query($sql_query);
359 while ($row1 = PMA_DBI_fetch_row($res)) {
360 if (substr($row1[0], 0, 4) == 'max_') {
363 $row[$row1[0]] = 'N';
366 PMA_DBI_free_result($res);
368 $row = array('Table_priv' => '');
371 if (isset($row['Table_priv'])) {
372 $row1 = PMA_DBI_fetch_single_row(
373 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
374 'ASSOC', $GLOBALS['userlink']);
375 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
376 // the View for Create is spelled with uppercase V
377 // the view for Show is spelled with lowercase v
378 // and there is a space between the words
380 $av_grants = explode('\',\'', substr($row1['Type'], strpos($row1['Type'], '(') +
2, strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3));
382 $users_grants = explode(',', $row['Table_priv']);
384 foreach ($av_grants as $current_grant) {
385 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ?
'Y' : 'N';
387 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
390 $res = PMA_DBI_try_query('SHOW COLUMNS FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($db)) . '.' . PMA_backquote($table) . ';');
393 while ($row1 = PMA_DBI_fetch_row($res)) {
394 $columns[$row1[0]] = array(
398 'References' => FALSE
401 PMA_DBI_free_result($res);
405 // t a b l e - s p e c i f i c p r i v i l e g e s
406 if (! empty($columns)) {
407 $res = PMA_DBI_query(
408 'SELECT `Column_name`, `Column_priv`'
409 .' FROM `mysql`.`columns_priv`'
411 .' = \'' . PMA_sqlAddslashes($username) . "'"
413 .' = \'' . PMA_sqlAddslashes($hostname) . "'"
415 .' = \'' . PMA_sqlAddslashes(PMA_unescape_mysql_wildcards($db)) . "'"
417 .' = \'' . PMA_sqlAddslashes($table) . '\';');
419 while ($row1 = PMA_DBI_fetch_row($res)) {
420 $row1[1] = explode(',', $row1[1]);
421 foreach ($row1[1] as $current) {
422 $columns[$row1[0]][$current] = TRUE;
425 PMA_DBI_free_result($res);
426 unset($res, $row1, $current);
428 echo '<input type="hidden" name="grant_count" value="' . count($row) . '" />' . "\n"
429 . '<input type="hidden" name="column_count" value="' . count($columns) . '" />' . "\n"
430 . '<fieldset id="fieldset_user_priv">' . "\n"
431 . ' <legend>' . __('Table-specific privileges')
432 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English '))
433 . '</legend>' . "\n";
437 // privs that are attached to a specific column
438 PMA_display_column_privs($columns, $row, 'Select_priv',
439 'SELECT', 'select', __('Allows reading data.'), 'Select');
441 PMA_display_column_privs($columns, $row, 'Insert_priv',
442 'INSERT', 'insert', __('Allows inserting and replacing data.'), 'Insert');
444 PMA_display_column_privs($columns, $row, 'Update_priv',
445 'UPDATE', 'update', __('Allows changing data.'), 'Update');
447 PMA_display_column_privs($columns, $row, 'References_priv',
448 'REFERENCES', 'references', __('Has no effect in this MySQL version.'), 'References');
450 // privs that are not attached to a specific column
452 echo ' <div class="item">' . "\n";
453 foreach ($row as $current_grant => $current_grant_value) {
454 if (in_array(substr($current_grant, 0, (strlen($current_grant) - 5)),
455 array('Select', 'Insert', 'Update', 'References'))) {
458 // make a substitution to match the messages variables;
459 // also we must substitute the grant we get, because we can't generate
460 // a form variable containing blanks (those would get changed to
461 // an underscore when receiving the POST)
462 if ($current_grant == 'Create View_priv') {
463 $tmp_current_grant = 'CreateView_priv';
464 $current_grant = 'Create_view_priv';
465 } elseif ($current_grant == 'Show view_priv') {
466 $tmp_current_grant = 'ShowView_priv';
467 $current_grant = 'Show_view_priv';
469 $tmp_current_grant = $current_grant;
472 echo ' <div class="item">' . "\n"
473 . ' <input type="checkbox"'
474 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
475 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
477 . ($current_grant_value == 'Y' ?
'checked="checked" ' : '')
480 echo (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
481 ?
$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)) . 'Tbl']) . '"/>' . "\n";
484 echo ' <label for="checkbox_' . $current_grant
485 . '"><tt><dfn title="'
486 . (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
487 ?
$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)) . 'Tbl'])
489 . '">' . strtoupper(substr($current_grant, 0, strlen($current_grant) - 5)) . '</dfn></tt></label>' . "\n"
493 echo ' </div>' . "\n";
495 echo ' <div class="clearfloat"></div>' . "\n";
499 // g l o b a l o r d b - s p e c i f i c
502 $privTable[0] = array(
503 array('Select', 'SELECT', __('Allows reading data.')),
504 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
505 array('Update', 'UPDATE', __('Allows changing data.')),
506 array('Delete', 'DELETE', __('Allows deleting data.'))
509 $privTable[0][] = array('File', 'FILE', __('Allows importing data from and exporting data into files.'));
513 $privTable[1] = array(
514 array('Create', 'CREATE', ($table == '*' ?
__('Allows creating new databases and tables.') : __('Allows creating new tables.'))),
515 array('Alter', 'ALTER', __('Allows altering the structure of existing tables.')),
516 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
517 array('Drop', 'DROP', ($table == '*' ?
__('Allows dropping databases and tables.') : __('Allows dropping tables.'))),
518 array('Create_tmp_table', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
519 array('Show_view', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
520 array('Create_routine', 'CREATE ROUTINE', __('Allows creating stored routines.')),
521 array('Alter_routine', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
522 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
524 // this one is for a db-specific priv: Create_view_priv
525 if (isset($row['Create_view_priv'])) {
526 $privTable[1][] = array('Create_view', 'CREATE VIEW', __('Allows creating new views.'));
528 // this one is for a table-specific priv: Create View_priv
529 if (isset($row['Create View_priv'])) {
530 $privTable[1][] = array('Create View', 'CREATE VIEW', __('Allows creating new views.'));
532 if (isset($row['Event_priv'])) {
534 $privTable[1][] = array('Event', 'EVENT', __('Allows to set up events for the event scheduler'));
535 $privTable[1][] = array('Trigger', 'TRIGGER', __('Allows creating and dropping triggers'));
538 // a d m i n i s t r a t i o n
539 $privTable[2] = array(
540 array('Grant', 'GRANT', __('Allows adding users and privileges without reloading the privilege tables.')),
543 $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.'));
544 $privTable[2][] = array('Process', 'PROCESS', __('Allows viewing processes of all users'));
545 $privTable[2][] = array('Reload', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.'));
546 $privTable[2][] = array('Shutdown', 'SHUTDOWN', __('Allows shutting down the server.'));
547 $privTable[2][] = array('Show_db', 'SHOW DATABASES', __('Gives access to the complete list of databases.'));
549 $privTable[2][] = array('Lock_tables', 'LOCK TABLES', __('Allows locking tables for the current thread.'));
550 $privTable[2][] = array('References', 'REFERENCES', __('Has no effect in this MySQL version.'));
552 $privTable[2][] = array('Repl_client', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.'));
553 $privTable[2][] = array('Repl_slave', 'REPLICATION SLAVE', __('Needed for the replication slaves.'));
554 $privTable[2][] = array('Create_user', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.'));
556 echo '<input type="hidden" name="grant_count" value="'
557 . (count($privTable[0]) +
count($privTable[1]) +
count($privTable[2]) - (isset($row['Grant_priv']) ?
1 : 0))
559 . '<fieldset id="fieldset_user_global_rights">' . "\n"
563 ?
__('Global privileges')
565 ?
__('Database-specific privileges')
566 : __('Table-specific privileges'))) . "\n"
567 . ' (<a href="server_privileges.php?'
568 . $GLOBALS['url_query'] . '&checkall=1" onclick="setCheckboxes(\'usersForm\', true); return false;">'
569 . __('Check All') . '</a> /' . "\n"
570 . ' <a href="server_privileges.php?'
571 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'usersForm\', false); return false;">'
572 . __('Uncheck All') . '</a>)' . "\n"
573 . ' </legend>' . "\n"
574 . ' <p><small><i>' . __(' Note: MySQL privilege names are expressed in English ') . '</i></small></p>' . "\n"
575 . ' <fieldset>' . "\n"
576 . ' <legend>' . __('Data') . '</legend>' . "\n";
577 foreach ($privTable[0] as $priv)
579 echo ' <div class="item">' . "\n"
580 . ' <input type="checkbox"'
581 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
582 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
583 . '_priv" value="Y" '
584 . ($row[$priv[0] . '_priv'] == 'Y' ?
'checked="checked" ' : '')
585 . 'title="' . $priv[2] . '"/>' . "\n"
586 . ' <label for="checkbox_' . $priv[0]
587 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
588 . '</dfn></tt></label>' . "\n"
591 echo ' </fieldset>' . "\n"
592 . ' <fieldset>' . "\n"
593 . ' <legend>' . __('Structure') . '</legend>' . "\n";
594 foreach ($privTable[1] as $priv)
596 echo ' <div class="item">' . "\n"
597 . ' <input type="checkbox"'
598 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
599 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
600 . '_priv" value="Y" '
601 . ($row[$priv[0] . '_priv'] == 'Y' ?
'checked="checked" ' : '')
602 . 'title="' . $priv[2] . '"/>' . "\n"
603 . ' <label for="checkbox_' . $priv[0]
604 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
605 . '</dfn></tt></label>' . "\n"
608 echo ' </fieldset>' . "\n"
609 . ' <fieldset>' . "\n"
610 . ' <legend>' . __('Administration') . '</legend>' . "\n";
611 foreach ($privTable[2] as $priv)
613 echo ' <div class="item">' . "\n"
614 . ' <input type="checkbox"'
615 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
616 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
617 . '_priv" value="Y" '
618 . ($row[$priv[0] . '_priv'] == 'Y' ?
'checked="checked" ' : '')
619 . 'title="' . $priv[2] . '"/>' . "\n"
620 . ' <label for="checkbox_' . $priv[0]
621 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
622 . '</dfn></tt></label>' . "\n"
626 echo ' </fieldset>' . "\n";
627 // The "Resource limits" box is not displayed for db-specific privs
629 echo ' <fieldset>' . "\n"
630 . ' <legend>' . __('Resource limits') . '</legend>' . "\n"
631 . ' <p><small><i>' . __('Note: Setting these options to 0 (zero) removes the limit.') . '</i></small></p>' . "\n"
632 . ' <div class="item">' . "\n"
633 . ' <label for="text_max_questions"><tt><dfn title="'
634 . __('Limits the number of queries the user may send to the server per hour.') . '">MAX QUERIES PER HOUR</dfn></tt></label>' . "\n"
635 . ' <input type="text" name="max_questions" id="text_max_questions" value="'
636 . $row['max_questions'] . '" size="11" maxlength="11" title="' . __('Limits the number of queries the user may send to the server per hour.') . '" />' . "\n"
638 . ' <div class="item">' . "\n"
639 . ' <label for="text_max_updates"><tt><dfn title="'
640 . __('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"
641 . ' <input type="text" name="max_updates" id="text_max_updates" value="'
642 . $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"
644 . ' <div class="item">' . "\n"
645 . ' <label for="text_max_connections"><tt><dfn title="'
646 . __('Limits the number of new connections the user may open per hour.') . '">MAX CONNECTIONS PER HOUR</dfn></tt></label>' . "\n"
647 . ' <input type="text" name="max_connections" id="text_max_connections" value="'
648 . $row['max_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of new connections the user may open per hour.') . '" />' . "\n"
650 . ' <div class="item">' . "\n"
651 . ' <label for="text_max_user_connections"><tt><dfn title="'
652 . __('Limits the number of simultaneous connections the user may have.') . '">MAX USER_CONNECTIONS</dfn></tt></label>' . "\n"
653 . ' <input type="text" name="max_user_connections" id="text_max_user_connections" value="'
654 . $row['max_user_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of simultaneous connections the user may have.') . '" />' . "\n"
656 . ' </fieldset>' . "\n";
659 echo ' <div class="clearfloat"></div>' . "\n";
661 echo '</fieldset>' . "\n";
663 echo '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">' . "\n"
664 . ' <input type="submit" name="update_privs" value="' . __('Go') . '" />' . "\n"
665 . '</fieldset>' . "\n";
667 } // end of the 'PMA_displayPrivTable()' function
671 * Displays the fields used by the "new user" form as well as the
672 * "change login information / copy user" form.
674 * @param string $mode are we creating a new user or are we just
675 * changing one? (allowed values: 'new', 'change')
676 * @global array $cfg the phpMyAdmin configuration
677 * @global ressource $user_link the database connection
681 function PMA_displayLoginInformationFields($mode = 'new')
683 // Get user/host name lengths
684 $fields_info = PMA_DBI_get_fields('mysql', 'user');
685 $username_length = 16;
686 $hostname_length = 41;
687 foreach ($fields_info as $key => $val) {
688 if ($val['Field'] == 'User') {
689 strtok($val['Type'], '()');
692 $username_length = $v;
694 } elseif ($val['Field'] == 'Host') {
695 strtok($val['Type'], '()');
698 $hostname_length = $v;
704 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
705 $GLOBALS['pred_username'] = 'any';
707 echo '<fieldset id="fieldset_add_user_login">' . "\n"
708 . '<legend>' . __('Login Information') . '</legend>' . "\n"
709 . '<div class="item">' . "\n"
710 . '<label for="select_pred_username">' . "\n"
711 . ' ' . __('User name') . ':' . "\n"
713 . '<span class="options">' . "\n"
714 . ' <select name="pred_username" id="select_pred_username" title="' . __('User name') . '"' . "\n"
715 . ' onchange="if (this.value == \'any\') { username.value = \'\'; } else if (this.value == \'userdefined\') { username.focus(); username.select(); }">' . "\n"
716 . ' <option value="any"' . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any') ?
' selected="selected"' : '') . '>' . __('Any user') . '</option>' . "\n"
717 . ' <option value="userdefined"' . ((!isset($GLOBALS['pred_username']) ||
$GLOBALS['pred_username'] == 'userdefined') ?
' selected="selected"' : '') . '>' . __('Use text field') . ':</option>' . "\n"
718 . ' </select>' . "\n"
720 . '<input type="text" name="username" maxlength="'
721 . $username_length . '" title="' . __('User name') . '"'
722 . (empty($GLOBALS['username'])
724 : ' value="' . htmlspecialchars(isset($GLOBALS['new_username'])
725 ?
$GLOBALS['new_username']
726 : $GLOBALS['username']) . '"')
727 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
729 . '<div class="item">' . "\n"
730 . '<label for="select_pred_hostname">' . "\n"
731 . ' ' . __('Host') . ':' . "\n"
733 . '<span class="options">' . "\n"
734 . ' <select name="pred_hostname" id="select_pred_hostname" title="' . __('Host') . '"' . "\n";
735 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
736 if (! empty($_current_user)) {
737 $thishost = str_replace("'", '', substr($_current_user, (strrpos($_current_user, '@') +
1)));
738 if ($thishost == 'localhost' ||
$thishost == '127.0.0.1') {
742 echo ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } else if (this.value == \'localhost\') { hostname.value = \'localhost\'; } '
743 . (empty($thishost) ?
'' : 'else if (this.value == \'thishost\') { hostname.value = \'' . addslashes(htmlspecialchars($thishost)) . '\'; } ')
744 . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } else if (this.value == \'userdefined\') { hostname.focus(); hostname.select(); }">' . "\n";
745 unset($_current_user);
747 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
748 if (!isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
749 switch (strtolower($GLOBALS['hostname'])) {
752 $GLOBALS['pred_hostname'] = 'localhost';
755 $GLOBALS['pred_hostname'] = 'any';
758 $GLOBALS['pred_hostname'] = 'userdefined';
762 echo ' <option value="any"'
763 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
764 ?
' selected="selected"' : '') . '>' . __('Any host')
766 . ' <option value="localhost"'
767 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'localhost')
768 ?
' selected="selected"' : '') . '>' . __('Local')
769 . '</option>' . "\n";
770 if (!empty($thishost)) {
771 echo ' <option value="thishost"'
772 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'thishost')
773 ?
' selected="selected"' : '') . '>' . __('This Host')
774 . '</option>' . "\n";
777 echo ' <option value="hosttable"'
778 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'hosttable')
779 ?
' selected="selected"' : '') . '>' . __('Use Host Table')
781 . ' <option value="userdefined"'
782 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'userdefined')
783 ?
' selected="selected"' : '')
784 . '>' . __('Use text field') . ':</option>' . "\n"
785 . ' </select>' . "\n"
787 . '<input type="text" name="hostname" maxlength="'
788 . $hostname_length . '" value="'
789 . htmlspecialchars(isset($GLOBALS['hostname']) ?
$GLOBALS['hostname'] : '')
790 . '" title="' . __('Host')
791 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
792 . PMA_showHint(__('When Host table is used, this field is ignored and values stored in Host table are used instead.'))
794 . '<div class="item">' . "\n"
795 . '<label for="select_pred_password">' . "\n"
796 . ' ' . __('Password') . ':' . "\n"
798 . '<span class="options">' . "\n"
799 . ' <select name="pred_password" id="select_pred_password" title="'
800 . __('Password') . '"' . "\n"
801 . ' onchange="if (this.value == \'none\') { pma_pw.value = \'\'; pma_pw2.value = \'\'; } else if (this.value == \'userdefined\') { pma_pw.focus(); pma_pw.select(); }">' . "\n"
802 . ($mode == 'change' ?
' <option value="keep" selected="selected">' . __('Do not change the password') . '</option>' . "\n" : '')
803 . ' <option value="none"';
804 if (isset($GLOBALS['username']) && $mode != 'change') {
805 echo ' selected="selected"';
807 echo '>' . __('No Password') . '</option>' . "\n"
808 . ' <option value="userdefined"' . (isset($GLOBALS['username']) ?
'' : ' selected="selected"') . '>' . __('Use text field') . ':</option>' . "\n"
809 . ' </select>' . "\n"
811 . '<input type="password" id="text_pma_pw" name="pma_pw" title="' . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
813 . '<div class="item">' . "\n"
814 . '<label for="text_pma_pw2">' . "\n"
815 . ' ' . __('Re-type') . ':' . "\n"
817 . '<span class="options"> </span>' . "\n"
818 . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="' . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
820 . '<div class="item">' . "\n"
821 . '<label for="button_generate_password">' . "\n"
822 . ' ' . __('Generate Password') . ':' . "\n"
824 . '<span class="options">' . "\n"
825 . ' <input type="button" id="button_generate_password" value="' . __('Generate') . '" onclick="suggestPassword(this.form)" />' . "\n"
827 . '<input type="text" name="generated_pw" id="generated_pw" />' . "\n"
829 . '</fieldset>' . "\n";
830 } // end of the 'PMA_displayUserAndHostFields()' function
833 * Changes / copies a user, part I
835 if (isset($_REQUEST['change_copy'])) {
836 $user_host_condition =
838 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
840 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\';';
841 $row = PMA_DBI_fetch_single_row('SELECT * FROM `mysql`.`user` ' . $user_host_condition);
843 PMA_Message
::notice(__('No user found.'))->display();
844 unset($_REQUEST['change_copy']);
846 extract($row, EXTR_OVERWRITE
);
847 // Recent MySQL versions have the field "Password" in mysql.user,
848 // so the previous extract creates $Password but this script
850 if (!isset($password) && isset($Password)) {
851 $password = $Password;
860 * (Changes / copies a user, part II)
862 if (isset($_REQUEST['adduser_submit']) ||
isset($_REQUEST['change_copy'])) {
864 if ($pred_username == 'any') {
867 switch ($pred_hostname) {
872 $hostname = 'localhost';
878 $_user_name = PMA_DBI_fetch_value('SELECT USER()');
879 $hostname = substr($_user_name, (strrpos($_user_name, '@') +
1));
883 $sql = "SELECT '1' FROM `mysql`.`user`"
884 . " WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
885 . " AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
886 if (PMA_DBI_fetch_value($sql) == 1) {
887 $message = PMA_Message
::error(__('The user %s already exists!'));
888 $message->addParam('[i]\'' . $username . '\'@\'' . $hostname . '\'[/i]');
889 $_REQUEST['adduser'] = true;
892 $create_user_real = 'CREATE USER \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
895 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
896 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
897 if ($pred_password != 'none' && $pred_password != 'keep') {
898 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
899 $real_sql_query .= ' IDENTIFIED BY \'' . PMA_sqlAddslashes($pma_pw) . '\'';
900 if (isset($create_user_real)) {
901 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
902 $create_user_real .= ' IDENTIFIED BY \'' . PMA_sqlAddslashes($pma_pw) . '\'';
905 if ($pred_password == 'keep' && !empty($password)) {
906 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
907 if (isset($create_user_real)) {
908 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
911 $sql_query = $real_sql_query;
912 if (isset($create_user_real)) {
913 $create_user_show = $create_user_real;
917 * @todo similar code appears twice in this script
919 if ((isset($Grant_priv) && $Grant_priv == 'Y')
920 ||
(isset($max_questions) ||
isset($max_connections)
921 ||
isset($max_updates) ||
isset($max_user_connections))) {
922 $real_sql_query .= ' WITH';
923 $sql_query .= ' WITH';
924 if (isset($Grant_priv) && $Grant_priv == 'Y') {
925 $real_sql_query .= ' GRANT OPTION';
926 $sql_query .= ' GRANT OPTION';
928 if (isset($max_questions)) {
929 // avoid negative values
930 $max_questions = max(0, (int)$max_questions);
931 $real_sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
932 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
934 if (isset($max_connections)) {
935 $max_connections = max(0, (int)$max_connections);
936 $real_sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
937 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
939 if (isset($max_updates)) {
940 $max_updates = max(0, (int)$max_updates);
941 $real_sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
942 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
944 if (isset($max_user_connections)) {
945 $max_user_connections = max(0, (int)$max_user_connections);
946 $real_sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
947 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
950 if (isset($create_user_real)) {
951 $create_user_real .= ';';
952 $create_user_show .= ';';
954 $real_sql_query .= ';';
956 if (empty($_REQUEST['change_copy'])) {
959 if (isset($create_user_real)) {
960 if (! PMA_DBI_try_query($create_user_real)) {
963 $sql_query = $create_user_show . $sql_query;
966 if ($_error ||
! PMA_DBI_try_query($real_sql_query)) {
967 $_REQUEST['createdb'] = false;
968 $message = PMA_Message
::rawError(PMA_DBI_getError());
970 $message = PMA_Message
::success(__('You have added a new user.'));
973 switch (PMA_ifSetOr($_REQUEST['createdb'], '0')) {
975 // Create database with same name and grant all privileges
976 $q = 'CREATE DATABASE IF NOT EXISTS '
977 . PMA_backquote(PMA_sqlAddslashes($username)) . ';';
979 if (! PMA_DBI_try_query($q)) {
980 $message = PMA_Message
::rawError(PMA_DBI_getError());
983 $GLOBALS['reload'] = TRUE;
984 PMA_reloadNavigation();
986 $q = 'GRANT ALL PRIVILEGES ON '
987 . PMA_backquote(PMA_sqlAddslashes($username)) . '.* TO \''
988 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
990 if (! PMA_DBI_try_query($q)) {
991 $message = PMA_Message
::rawError(PMA_DBI_getError());
995 // Grant all privileges on wildcard name (username\_%)
996 $q = 'GRANT ALL PRIVILEGES ON '
997 . PMA_backquote(PMA_sqlAddslashes($username) . '\_%') . '.* TO \''
998 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1000 if (! PMA_DBI_try_query($q)) {
1001 $message = PMA_Message
::rawError(PMA_DBI_getError());
1005 // Grant all privileges on the specified database to the new user
1006 $q = 'GRANT ALL PRIVILEGES ON '
1007 . PMA_backquote(PMA_sqlAddslashes($dbname)) . '.* TO \''
1008 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1010 if (! PMA_DBI_try_query($q)) {
1011 $message = PMA_Message
::rawError(PMA_DBI_getError());
1019 if (isset($create_user_real)) {
1020 $queries[] = $create_user_real;
1022 $queries[] = $real_sql_query;
1023 // we put the query containing the hidden password in
1024 // $queries_for_display, at the same position occupied
1025 // by the real query in $queries
1026 $tmp_count = count($queries);
1027 if (isset($create_user_real)) {
1028 $queries_for_display[$tmp_count - 2] = $create_user_show;
1030 $queries_for_display[$tmp_count - 1] = $sql_query;
1032 unset($res, $real_sql_query);
1038 * Changes / copies a user, part III
1040 if (isset($_REQUEST['change_copy'])) {
1041 $user_host_condition =
1043 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1045 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\';';
1046 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1047 while ($row = PMA_DBI_fetch_assoc($res)) {
1049 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1050 .' ON ' . PMA_backquote($row['Db']) . '.*'
1051 .' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1052 . ($row['Grant_priv'] == 'Y' ?
' WITH GRANT OPTION;' : ';');
1054 PMA_DBI_free_result($res);
1055 $res = PMA_DBI_query(
1056 'SELECT `Db`, `Table_name`, `Table_priv`'
1057 .' FROM `mysql`.`tables_priv`' . $user_host_condition,
1058 $GLOBALS['userlink'], PMA_DBI_QUERY_STORE
);
1059 while ($row = PMA_DBI_fetch_assoc($res)) {
1061 $res2 = PMA_DBI_QUERY(
1062 'SELECT `Column_name`, `Column_priv`'
1063 .' FROM `mysql`.`columns_priv`'
1065 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1067 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\''
1069 .' = \'' . PMA_sqlAddslashes($row['Db']) . "'"
1070 .' AND `Table_name`'
1071 .' = \'' . PMA_sqlAddslashes($row['Table_name']) . "'"
1073 null, PMA_DBI_QUERY_STORE
);
1075 $tmp_privs1 = PMA_extractPrivInfo($row);
1076 $tmp_privs2 = array(
1077 'Select' => array(),
1078 'Insert' => array(),
1079 'Update' => array(),
1080 'References' => array()
1083 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1084 $tmp_array = explode(',', $row2['Column_priv']);
1085 if (in_array('Select', $tmp_array)) {
1086 $tmp_privs2['Select'][] = $row2['Column_name'];
1088 if (in_array('Insert', $tmp_array)) {
1089 $tmp_privs2['Insert'][] = $row2['Column_name'];
1091 if (in_array('Update', $tmp_array)) {
1092 $tmp_privs2['Update'][] = $row2['Column_name'];
1094 if (in_array('References', $tmp_array)) {
1095 $tmp_privs2['References'][] = $row2['Column_name'];
1099 if (count($tmp_privs2['Select']) > 0 && !in_array('SELECT', $tmp_privs1)) {
1100 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1102 if (count($tmp_privs2['Insert']) > 0 && !in_array('INSERT', $tmp_privs1)) {
1103 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1105 if (count($tmp_privs2['Update']) > 0 && !in_array('UPDATE', $tmp_privs1)) {
1106 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1108 if (count($tmp_privs2['References']) > 0 && !in_array('REFERENCES', $tmp_privs1)) {
1109 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1113 'GRANT ' . join(', ', $tmp_privs1)
1114 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1115 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1116 . (in_array('Grant', explode(',', $row['Table_priv'])) ?
' WITH GRANT OPTION;' : ';');
1122 * Updates privileges
1124 if (!empty($update_privs)) {
1125 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, (isset($tablename) ?
$tablename : ''));
1128 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1129 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1130 if (!isset($Grant_priv) ||
$Grant_priv != 'Y') {
1132 'REVOKE GRANT OPTION ON ' . $db_and_table
1133 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1138 // Should not do a GRANT USAGE for a table-specific privilege, it
1139 // causes problems later (cannot revoke it)
1140 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1142 'GRANT ' . join(', ', PMA_extractPrivInfo())
1143 . ' ON ' . $db_and_table
1144 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
1147 * @todo similar code appears twice in this script
1149 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1150 ||
(! isset($dbname)
1151 && (isset($max_questions) ||
isset($max_connections)
1152 ||
isset($max_updates) ||
isset($max_user_connections))))
1154 $sql_query2 .= 'WITH';
1155 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1156 $sql_query2 .= ' GRANT OPTION';
1158 if (isset($max_questions)) {
1159 $max_questions = max(0, (int)$max_questions);
1160 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1162 if (isset($max_connections)) {
1163 $max_connections = max(0, (int)$max_connections);
1164 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1166 if (isset($max_updates)) {
1167 $max_updates = max(0, (int)$max_updates);
1168 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1170 if (isset($max_user_connections)) {
1171 $max_user_connections = max(0, (int)$max_user_connections);
1172 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1177 if (! PMA_DBI_try_query($sql_query0)) {
1178 // this query may fail, but this does not matter :o)
1181 if (isset($sql_query1) && !PMA_DBI_try_query($sql_query1)) {
1182 // this one may fail, too...
1185 if (isset($sql_query2)) {
1186 PMA_DBI_query($sql_query2);
1190 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1191 $message = PMA_Message
::success(__('You have updated the privileges for %s.'));
1192 $message->addParam('\'' . $username . '\'@\'' . $hostname . '\'');
1197 * Revokes Privileges
1199 if (isset($_REQUEST['revokeall'])) {
1200 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, isset($tablename) ?
$tablename : '');
1203 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1204 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1206 'REVOKE GRANT OPTION ON ' . $db_and_table
1207 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1209 PMA_DBI_query($sql_query0);
1210 if (! PMA_DBI_try_query($sql_query1)) {
1211 // this one may fail, too...
1214 $sql_query = $sql_query0 . ' ' . $sql_query1;
1215 $message = PMA_Message
::success(__('You have revoked the privileges for %s'));
1216 $message->addParam('\'' . $username . '\'@\'' . $hostname . '\'');
1217 if (! isset($tablename)) {
1226 * Updates the password
1228 if (isset($_REQUEST['change_pw'])) {
1229 // similar logic in user_password.php
1232 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1233 if ($pma_pw != $pma_pw2) {
1234 $message = PMA_Message
::error(__('The passwords aren\'t the same!'));
1235 } elseif (empty($pma_pw) ||
empty($pma_pw2)) {
1236 $message = PMA_Message
::error(__('The password is empty!'));
1240 // here $nopass could be == 1
1241 if (empty($message)) {
1243 $hashing_function = (!empty($pw_hash) && $pw_hash == 'old' ?
'OLD_' : '')
1246 // in $sql_query which will be displayed, hide the password
1247 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ?
'\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1248 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ?
'\'\'' : $hashing_function . '(\'' . PMA_sqlAddslashes($pma_pw) . '\')');
1249 PMA_DBI_try_query($local_query)
1250 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, FALSE, $err_url);
1251 $message = PMA_Message
::success(__('The password for %s was changed successfully.'));
1252 $message->addParam('\'' . $username . '\'@\'' . $hostname . '\'');
1259 * (Changes / copies a user, part IV)
1262 if (isset($_REQUEST['delete']) ||
(isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1263 if (isset($_REQUEST['change_copy'])) {
1264 $selected_usr = array($old_username . '&#27;' . $old_hostname);
1266 $selected_usr = $_REQUEST['selected_usr'];
1269 foreach ($selected_usr as $each_user) {
1270 list($this_user, $this_host) = explode('&#27;', $each_user);
1271 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1272 $queries[] = 'DROP USER \'' . PMA_sqlAddslashes($this_user) . '\'@\'' . PMA_sqlAddslashes($this_host) . '\';';
1274 if (isset($_REQUEST['drop_users_db'])) {
1275 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1276 $GLOBALS['reload'] = TRUE;
1277 PMA_reloadNavigation();
1280 if (empty($_REQUEST['change_copy'])) {
1281 if (empty($queries)) {
1282 $message = PMA_Message
::error(__('No users selected for deleting!'));
1284 if ($_REQUEST['mode'] == 3) {
1285 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1286 $queries[] = 'FLUSH PRIVILEGES;';
1288 $drop_user_error = '';
1289 foreach ($queries as $sql_query) {
1290 if ($sql_query{0} != '#') {
1291 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1292 $drop_user_error .= PMA_DBI_getError() . "\n";
1296 $sql_query = join("\n", $queries);
1297 if (! empty($drop_user_error)) {
1298 $message = PMA_Message
::rawError($drop_user_error);
1300 $message = PMA_Message
::success(__('The selected users have been deleted successfully.'));
1309 * Changes / copies a user, part V
1311 if (isset($_REQUEST['change_copy'])) {
1313 foreach ($queries as $sql_query) {
1314 if ($sql_query{0} != '#') {
1315 PMA_DBI_query($sql_query);
1317 // when there is a query containing a hidden password, take it
1318 // instead of the real query sent
1319 if (isset($queries_for_display[$tmp_count])) {
1320 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1324 $message = PMA_Message
::success();
1325 $sql_query = join("\n", $queries);
1330 * Reloads the privilege tables into memory
1332 if (isset($_REQUEST['flush_privileges'])) {
1333 $sql_query = 'FLUSH PRIVILEGES;';
1334 PMA_DBI_query($sql_query);
1335 $message = PMA_Message
::success(__('The privileges were reloaded successfully.'));
1340 * Displays the links
1342 if (isset($viewing_mode) && $viewing_mode == 'db') {
1344 $url_query .= '&goto=db_operations.php';
1346 // Gets the database structure
1347 $sub_part = '_structure';
1348 require './libraries/db_info.inc.php';
1351 require './libraries/server_links.inc.php';
1356 * defines some standard links
1358 $link_edit = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1359 . '&username=%s'
1360 . '&hostname=%s'
1362 . '&tablename=%s">'
1363 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1366 $link_revoke = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1367 . '&username=%s'
1368 . '&hostname=%s'
1370 . '&tablename=%s'
1371 . '&revokeall=1">'
1372 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1375 $link_export = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1376 . '&username=%s'
1377 . '&hostname=%s'
1380 . PMA_getIcon('b_tblexport.png', __('Export'))
1387 // export user definition
1388 if (isset($_REQUEST['export'])) {
1389 echo '<h2>' . __('User') . ' \'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'</h2>';
1390 echo '<textarea cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1391 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddslashes($username) . "'@'" . PMA_sqlAddslashes($hostname) . "'");
1392 foreach($grants as $one_grant) {
1393 echo $one_grant . ";\n\n";
1396 unset($username, $hostname, $grants, $one_grant);
1399 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) ||
! strlen($checkprivs))) {
1400 if (! isset($username)) {
1401 // No username is given --> display the overview
1403 . PMA_getIcon('b_usrlist.png')
1404 . __('User overview') . "\n"
1409 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1410 ' FROM `mysql`.`user`';
1412 $sql_query .= (isset($initial) ?
PMA_RangeOfUsers($initial) : '');
1414 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1415 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE
);
1418 // the query failed! This may have two reasons:
1419 // - the user does not have enough privileges
1420 // - the privilege tables use a structure of an earlier version.
1421 // so let's try a more simple query
1423 $sql_query = 'SELECT * FROM `mysql`.`user`';
1424 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE
);
1427 PMA_Message
::error(__('No Privileges'))->display();
1428 PMA_DBI_free_result($res);
1431 // This message is hardcoded because I will replace it by
1432 // a automatic repair feature soon.
1433 $raw = 'Your privilege table structure seems to be older than'
1434 . ' this MySQL version!<br />'
1435 . 'Please run the <tt>mysql_upgrade</tt> command'
1436 . '(<tt>mysql_fix_privilege_tables</tt> on older systems)'
1437 . ' that should be included in your MySQL server distribution'
1438 . ' to solve this problem!';
1439 PMA_Message
::rawError($raw)->display();
1443 // we also want users not in table `user` but in other table
1444 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1446 $tables_to_search_for_users = array(
1447 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1450 $db_rights_sqls = array();
1451 foreach ($tables_to_search_for_users as $table_search_in) {
1452 if (in_array($table_search_in, $tables)) {
1453 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ?
PMA_RangeOfUsers($initial) : '');
1457 $user_defaults = array(
1461 'Grant_priv' => 'N',
1462 'privs' => array('USAGE'),
1465 // for all initials, even non A-Z
1466 $array_initials = array();
1468 $db_rights = array();
1470 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1471 .' ORDER BY `User` ASC, `Host` ASC';
1473 $db_rights_result = PMA_DBI_query($db_rights_sql);
1475 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1476 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1477 $db_rights[$db_rights_row['User']][$db_rights_row['Host']] =
1480 PMA_DBI_free_result($db_rights_result);
1481 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1485 * Displays the initials
1488 // initialize to FALSE the letters A-Z
1489 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++
) {
1490 if (! isset($array_initials[chr($letter_counter +
64)])) {
1491 $array_initials[chr($letter_counter +
64)] = FALSE;
1495 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE
);
1496 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1497 $array_initials[$tmp_initial] = TRUE;
1500 // Display the initials, which can be any characters, not
1501 // just letters. For letters A-Z, we add the non-used letters
1504 uksort($array_initials, "strnatcasecmp");
1506 echo '<table cellspacing="5"><tr>';
1507 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1508 if ($initial_was_found) {
1509 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1511 echo '<td>' . $tmp_initial . '</td>';
1514 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&showall=1">[' . __('Show all') . ']</a></td>' . "\n";
1515 echo '</tr></table>';
1518 * Display the user overview
1519 * (if less than 50 users, display them immediately)
1522 if (isset($initial) ||
isset($showall) ||
PMA_DBI_num_rows($res) < 50) {
1524 while ($row = PMA_DBI_fetch_assoc($res)) {
1525 $row['privs'] = PMA_extractPrivInfo($row, true);
1526 $db_rights[$row['User']][$row['Host']] = $row;
1528 @PMA_DBI_free_result
($res);
1531 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1532 . PMA_generate_common_hidden_inputs('', '')
1533 . ' <table id="tableuserrights" class="data">' . "\n"
1535 . ' <tr><th></th>' . "\n"
1536 . ' <th>' . __('User') . '</th>' . "\n"
1537 . ' <th>' . __('Host') . '</th>' . "\n"
1538 . ' <th>' . __('Password') . '</th>' . "\n"
1539 . ' <th>' . __('Global privileges') . ' '
1540 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English ')) . '</th>' . "\n"
1541 . ' <th>' . __('Grant') . '</th>' . "\n"
1542 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1543 echo ' </tr>' . "\n";
1544 echo ' </thead>' . "\n";
1545 echo ' <tbody>' . "\n";
1547 $index_checkbox = -1;
1548 foreach ($db_rights as $user) {
1551 foreach ($user as $host) {
1553 echo ' <tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
1554 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1555 . $index_checkbox . '" value="'
1556 . htmlspecialchars($host['User'] . '&#27;' . $host['Host'])
1558 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
1560 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1561 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1563 switch ($host['Password']) {
1568 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1570 // this happens if this is a definition not coming from mysql.user
1572 echo '--'; // in future version, replace by "not present"
1576 . ' <td><tt>' . "\n"
1577 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1578 . ' </tt></td>' . "\n"
1579 . ' <td>' . ($host['Grant_priv'] == 'Y' ?
__('Yes') : __('No')) . '</td>' . "\n"
1580 . ' <td align="center">';
1581 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1583 echo '<td align="center">';
1584 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ?
$initial : ''));
1587 $odd_row = ! $odd_row;
1591 unset($user, $host, $odd_row);
1592 echo ' </tbody></table>' . "\n"
1593 .'<img class="selectallarrow"'
1594 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1595 .' width="38" height="22"'
1596 .' alt="' . __('With selected:') . '" />' . "\n"
1597 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&checkall=1"'
1598 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1599 . __('Check All') . '</a>' . "\n"
1601 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1602 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1603 . __('Uncheck All') . '</a>' . "\n";
1605 // add/delete user fieldset
1606 echo ' <fieldset id="fieldset_add_user">' . "\n"
1607 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1">' . "\n"
1608 . PMA_getIcon('b_usradd.png')
1609 . ' ' . __('Add a new User') . '</a>' . "\n"
1610 . ' </fieldset>' . "\n"
1611 . ' <fieldset id="fieldset_delete_user">'
1612 . ' <legend>' . "\n"
1613 . PMA_getIcon('b_usrdrop.png')
1614 . ' ' . __('Remove selected users') . '' . "\n"
1615 . ' </legend>' . "\n"
1616 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1617 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1618 . ' <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"
1619 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1620 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1621 . ' </label>' . "\n"
1622 . ' </fieldset>' . "\n"
1623 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1624 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" />' . "\n"
1625 . ' </fieldset>' . "\n"
1630 echo ' <fieldset id="fieldset_add_user">' . "\n"
1631 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1">' . "\n"
1632 . PMA_getIcon('b_usradd.png')
1633 . ' ' . __('Add a new User') . '</a>' . "\n"
1634 . ' </fieldset>' . "\n";
1635 } // end if (display overview)
1636 $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
);
1637 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&flush_privileges=1">', false);
1638 $flushnote->addParam('</a>', false);
1639 $flushnote->display();
1645 // A user was selected -> display the user's properties
1648 . PMA_getIcon('b_usredit.png')
1649 . __('Edit Privileges') . ': '
1652 if (isset($dbname)) {
1653 echo ' <i><a href="server_privileges.php?'
1654 . $GLOBALS['url_query'] . '&username=' . urlencode($username)
1655 . '&hostname=' . urlencode($hostname) . '&dbname=&tablename=">\''
1656 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1657 . '\'</a></i>' . "\n";
1658 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
1660 echo ' - ' . ($dbname_is_wildcard ?
__('Databases') : __('Database') );
1661 if (isset($tablename)) {
1662 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
1663 . '&username=' . urlencode($username) . '&hostname=' . urlencode($hostname)
1664 . '&dbname=' . $url_dbname . '&tablename=">' . htmlspecialchars($dbname) . '</a></i>';
1665 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
1667 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
1671 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1675 echo '</h2>' . "\n";
1678 $sql = "SELECT '1' FROM `mysql`.`user`"
1679 . " WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
1680 . " AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
1681 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
1683 if ($user_does_not_exists) {
1684 PMA_Message
::warning(__('The selected user was not found in the privilege table.'))->display();
1685 PMA_displayLoginInformationFields();
1686 //require_once './libraries/footer.inc.php';
1689 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n";
1691 'username' => $username,
1692 'hostname' => $hostname,
1694 if (isset($dbname)) {
1695 $_params['dbname'] = $dbname;
1696 if (isset($tablename)) {
1697 $_params['tablename'] = $tablename;
1700 echo PMA_generate_common_hidden_inputs($_params);
1702 PMA_displayPrivTable(PMA_ifSetOr($dbname, '*', 'length'),
1703 PMA_ifSetOr($tablename, '*', 'length'));
1705 echo '</form>' . "\n";
1707 if (! isset($tablename) && empty($dbname_is_wildcard)) {
1709 // no table name was given, display all table specific rights
1710 // but only if $dbname contains no wildcards
1713 echo '<form action="server_privileges.php" method="post">' . "\n"
1714 . PMA_generate_common_hidden_inputs('', '')
1715 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
1716 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1717 . '<fieldset>' . "\n"
1718 . '<legend>' . (! isset($dbname) ?
__('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
1719 . '<table class="data">' . "\n"
1721 . '<tr><th>' . (! isset($dbname) ?
__('Database') : __('Table')) . '</th>' . "\n"
1722 . ' <th>' . __('Privileges') . '</th>' . "\n"
1723 . ' <th>' . __('Grant') . '</th>' . "\n"
1724 . ' <th>' . (! isset($dbname) ?
__('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
1725 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
1730 $user_host_condition =
1732 . ' = \'' . PMA_sqlAddslashes($username) . "'"
1734 . ' = \'' . PMA_sqlAddslashes($hostname) . "'";
1739 // we also want privielgs for this user not in table `db` but in other table
1740 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1741 if (! isset($dbname)) {
1743 // no db name given, so we want all privs for the given user
1745 $tables_to_search_for_users = array(
1746 'tables_priv', 'columns_priv',
1749 $db_rights_sqls = array();
1750 foreach ($tables_to_search_for_users as $table_search_in) {
1751 if (in_array($table_search_in, $tables)) {
1752 $db_rights_sqls[] = '
1753 SELECT DISTINCT `Db`
1754 FROM `mysql`.' . PMA_backquote($table_search_in)
1755 . $user_host_condition;
1759 $user_defaults = array(
1761 'Grant_priv' => 'N',
1762 'privs' => array('USAGE'),
1763 'Table_privs' => true,
1767 $db_rights = array();
1769 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1770 .' ORDER BY `Db` ASC';
1772 $db_rights_result = PMA_DBI_query($db_rights_sql);
1774 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1775 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1776 // only Db names in the table `mysql`.`db` uses wildcards
1777 // as we are in the db specific rights display we want
1778 // all db names escaped, also from other sources
1779 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
1780 $db_rights_row['Db']);
1781 $db_rights[$db_rights_row['Db']] = $db_rights_row;
1784 PMA_DBI_free_result($db_rights_result);
1785 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1787 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
1788 $res = PMA_DBI_query($sql_query);
1791 while ($row = PMA_DBI_fetch_assoc($res)) {
1792 if (isset($db_rights[$row['Db']])) {
1793 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
1795 $db_rights[$row['Db']] = $row;
1797 // there are db specific rights for this user
1798 // so we can drop this db rights
1799 $db_rights[$row['Db']]['can_delete'] = true;
1801 PMA_DBI_free_result($res);
1806 // db name was given,
1807 // so we want all user specific rights for this db
1809 $user_host_condition .=
1811 .' LIKE \'' . PMA_sqlAddslashes($dbname) . "'";
1813 $tables_to_search_for_users = array(
1817 $db_rights_sqls = array();
1818 foreach ($tables_to_search_for_users as $table_search_in) {
1819 if (in_array($table_search_in, $tables)) {
1820 $db_rights_sqls[] = '
1821 SELECT DISTINCT `Table_name`
1822 FROM `mysql`.' . PMA_backquote($table_search_in)
1823 . $user_host_condition;
1827 $user_defaults = array(
1829 'Grant_priv' => 'N',
1830 'privs' => array('USAGE'),
1831 'Column_priv' => true,
1835 $db_rights = array();
1837 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1838 .' ORDER BY `Table_name` ASC';
1840 $db_rights_result = PMA_DBI_query($db_rights_sql);
1842 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1843 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1844 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
1846 PMA_DBI_free_result($db_rights_result);
1847 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1850 'SELECT `Table_name`,'
1852 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
1853 .' AS \'Column_priv\''
1854 .' FROM `mysql`.`tables_priv`'
1855 . $user_host_condition
1856 .' ORDER BY `Table_name` ASC;';
1857 $res = PMA_DBI_query($sql_query);
1860 while ($row = PMA_DBI_fetch_assoc($res)) {
1861 if (isset($db_rights[$row['Table_name']])) {
1862 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
1864 $db_rights[$row['Table_name']] = $row;
1867 PMA_DBI_free_result($res);
1873 if (count($db_rights) < 1) {
1874 echo '<tr class="odd">' . "\n"
1875 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
1879 $found_rows = array();
1880 //while ($row = PMA_DBI_fetch_assoc($res)) {
1881 foreach ($db_rights as $row) {
1882 $found_rows[] = (! isset($dbname)) ?
$row['Db'] : $row['Table_name'];
1884 echo '<tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
1885 . ' <td>' . htmlspecialchars((! isset($dbname)) ?
$row['Db'] : $row['Table_name']) . '</td>' . "\n"
1886 . ' <td><tt>' . "\n"
1887 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, TRUE)) . "\n"
1888 . ' </tt></td>' . "\n"
1889 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') ||
(isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ?
__('Yes') : __('No')) . '</td>' . "\n"
1891 if (! empty($row['Table_privs']) ||
! empty ($row['Column_priv'])) {
1898 printf($link_edit, urlencode($username),
1899 urlencode($hostname),
1900 urlencode((! isset($dbname)) ?
$row['Db'] : $dbname),
1901 urlencode((! isset($dbname)) ?
'' : $row['Table_name']));
1904 if (! empty($row['can_delete']) ||
isset($row['Table_name']) && strlen($row['Table_name'])) {
1905 printf($link_revoke, urlencode($username),
1906 urlencode($hostname),
1907 urlencode((! isset($dbname)) ?
$row['Db'] : $dbname),
1908 urlencode((! isset($dbname)) ?
'' : $row['Table_name']));
1912 $odd_row = ! $odd_row;
1916 echo '</tbody>' . "\n"
1917 . '</table>' . "\n";
1919 if (! isset($dbname)) {
1921 // no database name was given, display select db
1923 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
1925 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
1926 if (!empty($pred_db_array)) {
1927 echo ' <select name="pred_dbname" onchange="this.form.submit();">' . "\n"
1928 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
1929 foreach ($pred_db_array as $current_db) {
1930 $current_db = PMA_escape_mysql_wildcards($current_db);
1931 // cannot use array_diff() once, outside of the loop,
1932 // because the list of databases has special characters
1933 // already escaped in $found_rows,
1934 // contrary to the output of SHOW DATABASES
1935 if (empty($found_rows) ||
! in_array($current_db, $found_rows)) {
1936 echo ' <option value="' . htmlspecialchars($current_db) . '">'
1937 . htmlspecialchars($current_db) . '</option>' . "\n";
1940 echo ' </select>' . "\n";
1942 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
1943 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
1945 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
1946 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
1947 if ($res = @PMA_DBI_try_query
('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE
)) {
1948 $pred_tbl_array = array();
1949 while ($row = PMA_DBI_fetch_row($res)) {
1950 if (!isset($found_rows) ||
!in_array($row[0], $found_rows)) {
1951 $pred_tbl_array[] = $row[0];
1954 PMA_DBI_free_result($res);
1956 if (!empty($pred_tbl_array)) {
1957 echo ' <select name="pred_tablename" onchange="this.form.submit();">' . "\n"
1958 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
1959 foreach ($pred_tbl_array as $current_table) {
1960 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
1962 echo ' </select>' . "\n";
1967 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
1969 echo '</fieldset>' . "\n";
1970 echo '<fieldset class="tblFooters">' . "\n"
1971 . ' <input type="submit" value="' . __('Go') . '" />'
1972 . '</fieldset>' . "\n"
1977 // Provide a line with links to the relevant database and table
1978 if (isset($dbname) && empty($dbname_is_wildcard)) {
1979 echo '[ ' . __('Database')
1980 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
1981 . $GLOBALS['url_query'] . '&db=' . $url_dbname . '&reload=1">'
1982 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
1984 if (isset($tablename)) {
1985 echo ' [ ' . __('Table') . ' <a href="'
1986 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
1987 . '&db=' . $url_dbname . '&table=' . urlencode($tablename)
1988 . '&reload=1">' . htmlspecialchars($tablename) . ': '
1989 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
1995 if (! isset($dbname) && ! $user_does_not_exists) {
1996 require_once './libraries/display_change_password.lib.php';
1998 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
1999 . PMA_generate_common_hidden_inputs('', '')
2000 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
2001 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
2002 . '<fieldset id="fieldset_change_copy_user">' . "\n"
2003 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
2004 PMA_displayLoginInformationFields('change');
2005 echo ' <fieldset>' . "\n"
2006 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2008 '4' => __('... keep the old one.'),
2009 '1' => __(' ... delete the old one from the user tables.'),
2010 '2' => __(' ... revoke all active privileges from the old one and delete it afterwards.'),
2011 '3' => __(' ... delete the old one from the user tables and reload the privileges afterwards.'));
2012 PMA_display_html_radio('mode', $choices, '4', true);
2015 echo ' </fieldset>' . "\n"
2016 . '</fieldset>' . "\n"
2017 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2018 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2019 . '</fieldset>' . "\n"
2023 } elseif (isset($_REQUEST['adduser'])) {
2025 $GLOBALS['url_query'] .= '&adduser=1';
2027 . PMA_getIcon('b_usradd.png') . __('Add a new User') . "\n"
2029 . '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post" onsubmit="return checkAddUser(this);">' . "\n"
2030 . PMA_generate_common_hidden_inputs('', '');
2031 PMA_displayLoginInformationFields('new');
2032 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2033 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2035 $default_choice = 0;
2037 '0' => _pgettext('Create none database for user', 'None'),
2038 '1' => __('Create database with same name and grant all privileges'),
2039 '2' => __('Grant all privileges on wildcard name (username\\_%)'));
2041 if ( !empty($dbname) ) {
2042 $choices['3'] = sprintf( __('Grant all privileges on database "%s"'), htmlspecialchars($dbname));
2043 $default_choice = 3;
2044 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2047 // 4th parameter set to true to add line breaks
2048 // 5th parameter set to false to avoid htmlspecialchars() escaping in the label
2049 // since we have some HTML in some labels
2050 PMA_display_html_radio('createdb', $choices, $default_choice, true, false);
2052 unset($default_choice);
2054 echo '</fieldset>' . "\n";
2055 PMA_displayPrivTable('*', '*', FALSE);
2056 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2057 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2058 . ' </fieldset>' . "\n"
2061 // check the privileges for a particular database.
2062 echo '<table id="tablespecificuserrights" class="data">' . "\n"
2063 . '<caption class="tblHeaders">' . "\n"
2064 . PMA_getIcon('b_usrcheck.png')
2065 . ' ' . sprintf(__('Users having access to "%s"'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2066 . '</caption>' . "\n"
2068 . ' <tr><th>' . __('User') . '</th>' . "\n"
2069 . ' <th>' . __('Host') . '</th>' . "\n"
2070 . ' <th>' . __('Type') . '</th>' . "\n"
2071 . ' <th>' . __('Privileges') . '</th>' . "\n"
2072 . ' <th>' . __('Grant') . '</th>' . "\n"
2073 . ' <th>' . __('Action') . '</th>' . "\n"
2078 unset($row, $row1, $row2);
2080 // now, we build the table...
2081 $list_of_privileges =
2093 . '`References_priv`, '
2094 . '`Create_tmp_table_priv`, '
2095 . '`Lock_tables_priv`, '
2096 . '`Create_view_priv`, '
2097 . '`Show_view_priv`, '
2098 . '`Create_routine_priv`, '
2099 . '`Alter_routine_priv`, '
2102 $list_of_compared_privileges =
2103 '`Select_priv` = \'N\''
2104 . ' AND `Insert_priv` = \'N\''
2105 . ' AND `Update_priv` = \'N\''
2106 . ' AND `Delete_priv` = \'N\''
2107 . ' AND `Create_priv` = \'N\''
2108 . ' AND `Drop_priv` = \'N\''
2109 . ' AND `Grant_priv` = \'N\''
2110 . ' AND `References_priv` = \'N\''
2111 . ' AND `Create_tmp_table_priv` = \'N\''
2112 . ' AND `Lock_tables_priv` = \'N\''
2113 . ' AND `Create_view_priv` = \'N\''
2114 . ' AND `Show_view_priv` = \'N\''
2115 . ' AND `Create_routine_priv` = \'N\''
2116 . ' AND `Alter_routine_priv` = \'N\''
2117 . ' AND `Execute_priv` = \'N\'';
2119 if (PMA_MYSQL_INT_VERSION
>= 50106) {
2120 $list_of_privileges .=
2123 $list_of_compared_privileges .=
2124 ' AND `Event_priv` = \'N\''
2125 . ' AND `Trigger_priv` = \'N\'';
2129 '(SELECT ' . $list_of_privileges . ', `Db`'
2130 .' FROM `mysql`.`db`'
2131 .' WHERE \'' . PMA_sqlAddslashes($checkprivs) . "'"
2133 .' AND NOT (' . $list_of_compared_privileges. ')) '
2135 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2136 .' FROM `mysql`.`user` '
2137 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2138 .' ORDER BY `User` ASC,'
2141 $res = PMA_DBI_query($sql_query);
2142 $row = PMA_DBI_fetch_assoc($res);
2149 // prepare the current user
2150 $current_privileges = array();
2151 $current_user = $row['User'];
2152 $current_host = $row['Host'];
2153 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2154 $current_privileges[] = $row;
2155 $row = PMA_DBI_fetch_assoc($res);
2157 echo ' <tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
2159 if (count($current_privileges) > 1) {
2160 echo ' rowspan="' . count($current_privileges) . '"';
2162 echo '>' . (empty($current_user) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2165 if (count($current_privileges) > 1) {
2166 echo ' rowspan="' . count($current_privileges) . '"';
2168 echo '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2169 foreach ($current_privileges as $current) {
2172 if (!isset($current['Db']) ||
$current['Db'] == '*') {
2174 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2175 echo __('database-specific');
2177 echo __('wildcard'), ': <tt>' . htmlspecialchars($current['Db']) . '</tt>';
2183 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, TRUE)) . "\n"
2187 . ' ' . ($current['Grant_priv'] == 'Y' ?
__('Yes') : __('No')) . "\n"
2190 printf($link_edit, urlencode($current_user),
2191 urlencode($current_host),
2192 urlencode(! isset($current['Db']) ||
$current['Db'] == '*' ?
'' : $current['Db']),
2197 if (empty($row) && empty($row1) && empty($row2)) {
2200 $odd_row = ! $odd_row;
2203 echo ' <tr class="odd">' . "\n"
2204 . ' <td colspan="6">' . "\n"
2205 . ' ' . __('No user found.') . "\n"
2209 echo '</tbody>' . "\n"
2210 . '</table>' . "\n";
2212 // Offer to create a new user for the current database
2213 echo '<fieldset id="fieldset_add_user">' . "\n"
2214 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1&dbname=' . $checkprivs .'">' . "\n"
2215 . PMA_getIcon('b_usradd.png')
2216 . ' ' . __('Add a new User') . '</a>' . "\n"
2217 . '</fieldset>' . "\n";
2219 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2223 * Displays the footer
2226 require_once './libraries/footer.inc.php';