2 /* vim: set expandtab sw=4 ts=4 sts=4: */
11 require_once './libraries/common.inc.php';
14 * Does the common work
16 $GLOBALS['js_include'][] = 'server_privileges.js';
17 $GLOBALS['js_include'][] = 'functions.js';
18 $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js';
20 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 './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(\'addUsersForm\', true); return false;">'
570 . __('Check All') . '</a> /' . "\n"
571 . ' <a href="server_privileges.php?'
572 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'addUsersForm\', 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());
979 * If we are not in an Ajax request, we can't reload navigation now
981 if($GLOBALS['is_ajax_request'] != true) {
982 // this is needed in case tracking is on:
983 $GLOBALS['db'] = $username;
984 $GLOBALS['reload'] = TRUE;
985 PMA_reloadNavigation();
988 $q = 'GRANT ALL PRIVILEGES ON '
989 . PMA_backquote(PMA_sqlAddslashes($username)) . '.* TO \''
990 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
992 if (! PMA_DBI_try_query($q)) {
993 $message = PMA_Message
::rawError(PMA_DBI_getError());
997 // Grant all privileges on wildcard name (username\_%)
998 $q = 'GRANT ALL PRIVILEGES ON '
999 . PMA_backquote(PMA_sqlAddslashes($username) . '\_%') . '.* TO \''
1000 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1002 if (! PMA_DBI_try_query($q)) {
1003 $message = PMA_Message
::rawError(PMA_DBI_getError());
1007 // Grant all privileges on the specified database to the new user
1008 $q = 'GRANT ALL PRIVILEGES ON '
1009 . PMA_backquote(PMA_sqlAddslashes($dbname)) . '.* TO \''
1010 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1012 if (! PMA_DBI_try_query($q)) {
1013 $message = PMA_Message
::rawError(PMA_DBI_getError());
1021 if (isset($create_user_real)) {
1022 $queries[] = $create_user_real;
1024 $queries[] = $real_sql_query;
1025 // we put the query containing the hidden password in
1026 // $queries_for_display, at the same position occupied
1027 // by the real query in $queries
1028 $tmp_count = count($queries);
1029 if (isset($create_user_real)) {
1030 $queries_for_display[$tmp_count - 2] = $create_user_show;
1032 $queries_for_display[$tmp_count - 1] = $sql_query;
1034 unset($res, $real_sql_query);
1040 * Changes / copies a user, part III
1042 if (isset($_REQUEST['change_copy'])) {
1043 $user_host_condition =
1045 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1047 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\';';
1048 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1049 while ($row = PMA_DBI_fetch_assoc($res)) {
1051 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1052 .' ON ' . PMA_backquote($row['Db']) . '.*'
1053 .' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1054 . ($row['Grant_priv'] == 'Y' ?
' WITH GRANT OPTION;' : ';');
1056 PMA_DBI_free_result($res);
1057 $res = PMA_DBI_query(
1058 'SELECT `Db`, `Table_name`, `Table_priv`'
1059 .' FROM `mysql`.`tables_priv`' . $user_host_condition,
1060 $GLOBALS['userlink'], PMA_DBI_QUERY_STORE
);
1061 while ($row = PMA_DBI_fetch_assoc($res)) {
1063 $res2 = PMA_DBI_QUERY(
1064 'SELECT `Column_name`, `Column_priv`'
1065 .' FROM `mysql`.`columns_priv`'
1067 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1069 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\''
1071 .' = \'' . PMA_sqlAddslashes($row['Db']) . "'"
1072 .' AND `Table_name`'
1073 .' = \'' . PMA_sqlAddslashes($row['Table_name']) . "'"
1075 null, PMA_DBI_QUERY_STORE
);
1077 $tmp_privs1 = PMA_extractPrivInfo($row);
1078 $tmp_privs2 = array(
1079 'Select' => array(),
1080 'Insert' => array(),
1081 'Update' => array(),
1082 'References' => array()
1085 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1086 $tmp_array = explode(',', $row2['Column_priv']);
1087 if (in_array('Select', $tmp_array)) {
1088 $tmp_privs2['Select'][] = $row2['Column_name'];
1090 if (in_array('Insert', $tmp_array)) {
1091 $tmp_privs2['Insert'][] = $row2['Column_name'];
1093 if (in_array('Update', $tmp_array)) {
1094 $tmp_privs2['Update'][] = $row2['Column_name'];
1096 if (in_array('References', $tmp_array)) {
1097 $tmp_privs2['References'][] = $row2['Column_name'];
1101 if (count($tmp_privs2['Select']) > 0 && !in_array('SELECT', $tmp_privs1)) {
1102 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1104 if (count($tmp_privs2['Insert']) > 0 && !in_array('INSERT', $tmp_privs1)) {
1105 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1107 if (count($tmp_privs2['Update']) > 0 && !in_array('UPDATE', $tmp_privs1)) {
1108 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1110 if (count($tmp_privs2['References']) > 0 && !in_array('REFERENCES', $tmp_privs1)) {
1111 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1115 'GRANT ' . join(', ', $tmp_privs1)
1116 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1117 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1118 . (in_array('Grant', explode(',', $row['Table_priv'])) ?
' WITH GRANT OPTION;' : ';');
1124 * Updates privileges
1126 if (!empty($update_privs)) {
1127 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, (isset($tablename) ?
$tablename : ''));
1130 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1131 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1132 if (!isset($Grant_priv) ||
$Grant_priv != 'Y') {
1134 'REVOKE GRANT OPTION ON ' . $db_and_table
1135 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1140 // Should not do a GRANT USAGE for a table-specific privilege, it
1141 // causes problems later (cannot revoke it)
1142 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1144 'GRANT ' . join(', ', PMA_extractPrivInfo())
1145 . ' ON ' . $db_and_table
1146 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
1149 * @todo similar code appears twice in this script
1151 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1152 ||
(! isset($dbname)
1153 && (isset($max_questions) ||
isset($max_connections)
1154 ||
isset($max_updates) ||
isset($max_user_connections))))
1156 $sql_query2 .= 'WITH';
1157 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1158 $sql_query2 .= ' GRANT OPTION';
1160 if (isset($max_questions)) {
1161 $max_questions = max(0, (int)$max_questions);
1162 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1164 if (isset($max_connections)) {
1165 $max_connections = max(0, (int)$max_connections);
1166 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1168 if (isset($max_updates)) {
1169 $max_updates = max(0, (int)$max_updates);
1170 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1172 if (isset($max_user_connections)) {
1173 $max_user_connections = max(0, (int)$max_user_connections);
1174 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1179 if (! PMA_DBI_try_query($sql_query0)) {
1180 // this query may fail, but this does not matter :o)
1183 if (isset($sql_query1) && !PMA_DBI_try_query($sql_query1)) {
1184 // this one may fail, too...
1187 if (isset($sql_query2)) {
1188 PMA_DBI_query($sql_query2);
1192 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1193 $message = PMA_Message
::success(__('You have updated the privileges for %s.'));
1194 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1199 * Revokes Privileges
1201 if (isset($_REQUEST['revokeall'])) {
1202 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, isset($tablename) ?
$tablename : '');
1205 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1206 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1208 'REVOKE GRANT OPTION ON ' . $db_and_table
1209 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1211 PMA_DBI_query($sql_query0);
1212 if (! PMA_DBI_try_query($sql_query1)) {
1213 // this one may fail, too...
1216 $sql_query = $sql_query0 . ' ' . $sql_query1;
1217 $message = PMA_Message
::success(__('You have revoked the privileges for %s'));
1218 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1219 if (! isset($tablename)) {
1228 * Updates the password
1230 if (isset($_REQUEST['change_pw'])) {
1231 // similar logic in user_password.php
1234 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1235 if ($pma_pw != $pma_pw2) {
1236 $message = PMA_Message
::error(__('The passwords aren\'t the same!'));
1237 } elseif (empty($pma_pw) ||
empty($pma_pw2)) {
1238 $message = PMA_Message
::error(__('The password is empty!'));
1242 // here $nopass could be == 1
1243 if (empty($message)) {
1245 $hashing_function = (!empty($pw_hash) && $pw_hash == 'old' ?
'OLD_' : '')
1248 // in $sql_query which will be displayed, hide the password
1249 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ?
'\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1250 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ?
'\'\'' : $hashing_function . '(\'' . PMA_sqlAddslashes($pma_pw) . '\')');
1251 PMA_DBI_try_query($local_query)
1252 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, FALSE, $err_url);
1253 $message = PMA_Message
::success(__('The password for %s was changed successfully.'));
1254 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1261 * (Changes / copies a user, part IV)
1264 if (isset($_REQUEST['delete']) ||
(isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1265 if (isset($_REQUEST['change_copy'])) {
1266 $selected_usr = array($old_username . '&#27;' . $old_hostname);
1268 $selected_usr = $_REQUEST['selected_usr'];
1271 foreach ($selected_usr as $each_user) {
1272 list($this_user, $this_host) = explode('&#27;', $each_user);
1273 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1274 $queries[] = 'DROP USER \'' . PMA_sqlAddslashes($this_user) . '\'@\'' . PMA_sqlAddslashes($this_host) . '\';';
1276 if (isset($_REQUEST['drop_users_db'])) {
1277 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1278 $GLOBALS['reload'] = TRUE;
1280 if($GLOBALS['is_ajax_request'] != true) {
1281 PMA_reloadNavigation();
1285 if (empty($_REQUEST['change_copy'])) {
1286 if (empty($queries)) {
1287 $message = PMA_Message
::error(__('No users selected for deleting!'));
1289 if ($_REQUEST['mode'] == 3) {
1290 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1291 $queries[] = 'FLUSH PRIVILEGES;';
1293 $drop_user_error = '';
1294 foreach ($queries as $sql_query) {
1295 if ($sql_query{0} != '#') {
1296 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1297 $drop_user_error .= PMA_DBI_getError() . "\n";
1301 // tracking sets this, causing the deleted db to be shown in navi
1302 unset($GLOBALS['db']);
1304 $sql_query = join("\n", $queries);
1305 if (! empty($drop_user_error)) {
1306 $message = PMA_Message
::rawError($drop_user_error);
1308 $message = PMA_Message
::success(__('The selected users have been deleted successfully.'));
1317 * Changes / copies a user, part V
1319 if (isset($_REQUEST['change_copy'])) {
1321 foreach ($queries as $sql_query) {
1322 if ($sql_query{0} != '#') {
1323 PMA_DBI_query($sql_query);
1325 // when there is a query containing a hidden password, take it
1326 // instead of the real query sent
1327 if (isset($queries_for_display[$tmp_count])) {
1328 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1332 $message = PMA_Message
::success();
1333 $sql_query = join("\n", $queries);
1338 * Reloads the privilege tables into memory
1340 if (isset($_REQUEST['flush_privileges'])) {
1341 $sql_query = 'FLUSH PRIVILEGES;';
1342 PMA_DBI_query($sql_query);
1343 $message = PMA_Message
::success(__('The privileges were reloaded successfully.'));
1347 * defines some standard links
1349 $link_edit = '<a class="edit_user_anchor" href="server_privileges.php?' . $GLOBALS['url_query']
1350 . '&username=%s'
1351 . '&hostname=%s'
1353 . '&tablename=%s">'
1354 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1357 $link_revoke = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1358 . '&username=%s'
1359 . '&hostname=%s'
1361 . '&tablename=%s'
1362 . '&revokeall=1">'
1363 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1366 $link_export = '<a class="export_user_anchor" href="server_privileges.php?' . $GLOBALS['url_query']
1367 . '&username=%s'
1368 . '&hostname=%s'
1371 . PMA_getIcon('b_tblexport.png', __('Export'))
1375 * If we are in an Ajax request for Create User/Edit User/Revoke User/Flush Privileges,
1376 * show $message and exit.
1378 if( $GLOBALS['is_ajax_request'] && !isset($_REQUEST['export']) && !isset($_REQUEST['adduser']) && !isset($_REQUEST['initial']) && !isset($_REQUEST['showall']) && !isset($_REQUEST['edit_user_dialog'])) {
1380 if(isset($sql_query)) {
1381 $extra_data['sql_query'] = PMA_showMessage(NULL, $sql_query);
1384 if(isset($_REQUEST['adduser_submit']) ||
isset($_REQUEST['change_copy'])) {
1386 * generate html on the fly for the new user that was just created.
1388 $new_user_string = '<tr>'."\n"
1389 .'<td> <input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_" value="' . htmlspecialchars($username) . '&#27;' . htmlspecialchars($hostname) . '" /> </td>'."\n"
1390 .'<td><label for="checkbox_sel_users_">' . (empty($username) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($username) ) . '</label></td>' . "\n"
1391 .'<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
1392 $new_user_string .= '<td>';
1394 if(!empty($password) ||
isset($pma_pw)) {
1395 $new_user_string .= __('Yes');
1398 $new_user_string .= '<span style="color: #FF0000">' . __('No') . '</span>';
1401 $new_user_string .= '</td>'."\n";
1402 $new_user_string .= '<td><tt>' . join(', ', PMA_extractPrivInfo('', true)) . '</tt></td>'; //Fill in privileges here
1403 $new_user_string .= '<td>';
1405 if((isset($Grant_priv) && $Grant_priv == 'Y')) {
1406 $new_user_string .= __('Yes');
1409 $new_user_string .= __('No');
1412 $new_user_string .='</td>';
1414 $new_user_string .= '<td>'.sprintf($link_edit, urlencode($username), urlencode($hostname), '', '' ).'</td>'."\n";
1415 $new_user_string .= '<td>'.sprintf($link_export, urlencode($username), urlencode($hostname), (isset($initial) ?
$initial : '')).'</td>'."\n";
1417 $new_user_string .= '</tr>';
1419 $extra_data['new_user_string'] = $new_user_string;
1422 * Generate the string for this alphabet's initial, to update the user
1425 $new_user_initial = strtoupper(substr($username, 0, 1));
1426 $new_user_initial_string = '<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . $new_user_initial
1427 .'>' . $new_user_initial . '</a>';
1428 $extra_data['new_user_initial'] = $new_user_initial;
1429 $extra_data['new_user_initial_string'] = $new_user_initial_string;
1432 if(isset($update_privs)) {
1433 $new_privileges = join(', ', PMA_extractPrivInfo('', true));
1435 $extra_data['new_privileges'] = $new_privileges;
1438 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
1442 * Displays the links
1444 if (isset($viewing_mode) && $viewing_mode == 'db') {
1446 $url_query .= '&goto=db_operations.php';
1448 // Gets the database structure
1449 $sub_part = '_structure';
1450 require './libraries/db_info.inc.php';
1453 require './libraries/server_links.inc.php';
1461 // export user definition
1462 if (isset($_REQUEST['export'])) {
1463 echo '<h2>' . __('User') . ' \'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'</h2>';
1464 echo '<textarea cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1465 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddslashes($username) . "'@'" . PMA_sqlAddslashes($hostname) . "'");
1466 foreach($grants as $one_grant) {
1467 echo $one_grant . ";\n\n";
1470 unset($username, $hostname, $grants, $one_grant);
1471 if( $GLOBALS['is_ajax_request']) {
1476 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) ||
! strlen($checkprivs))) {
1477 if (! isset($username)) {
1478 // No username is given --> display the overview
1480 . PMA_getIcon('b_usrlist.png')
1481 . __('User overview') . "\n"
1486 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1487 ' FROM `mysql`.`user`';
1489 $sql_query .= (isset($initial) ?
PMA_RangeOfUsers($initial) : '');
1491 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1492 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE
);
1495 // the query failed! This may have two reasons:
1496 // - the user does not have enough privileges
1497 // - the privilege tables use a structure of an earlier version.
1498 // so let's try a more simple query
1500 $sql_query = 'SELECT * FROM `mysql`.`user`';
1501 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE
);
1504 PMA_Message
::error(__('No Privileges'))->display();
1505 PMA_DBI_free_result($res);
1508 // This message is hardcoded because I will replace it by
1509 // a automatic repair feature soon.
1510 $raw = 'Your privilege table structure seems to be older than'
1511 . ' this MySQL version!<br />'
1512 . 'Please run the <tt>mysql_upgrade</tt> command'
1513 . '(<tt>mysql_fix_privilege_tables</tt> on older systems)'
1514 . ' that should be included in your MySQL server distribution'
1515 . ' to solve this problem!';
1516 PMA_Message
::rawError($raw)->display();
1520 // we also want users not in table `user` but in other table
1521 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1523 $tables_to_search_for_users = array(
1524 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1527 $db_rights_sqls = array();
1528 foreach ($tables_to_search_for_users as $table_search_in) {
1529 if (in_array($table_search_in, $tables)) {
1530 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ?
PMA_RangeOfUsers($initial) : '');
1534 $user_defaults = array(
1538 'Grant_priv' => 'N',
1539 'privs' => array('USAGE'),
1542 // for all initials, even non A-Z
1543 $array_initials = array();
1545 $db_rights = array();
1547 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1548 .' ORDER BY `User` ASC, `Host` ASC';
1550 $db_rights_result = PMA_DBI_query($db_rights_sql);
1552 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1553 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1554 $db_rights[$db_rights_row['User']][$db_rights_row['Host']] =
1557 PMA_DBI_free_result($db_rights_result);
1558 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1562 * Displays the initials
1563 * In an Ajax request, we don't need to show this
1566 if( $GLOBALS['is_ajax_request'] != true ) {
1568 // initialize to FALSE the letters A-Z
1569 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++
) {
1570 if (! isset($array_initials[chr($letter_counter +
64)])) {
1571 $array_initials[chr($letter_counter +
64)] = FALSE;
1575 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE
);
1576 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1577 $array_initials[$tmp_initial] = TRUE;
1580 // Display the initials, which can be any characters, not
1581 // just letters. For letters A-Z, we add the non-used letters
1584 uksort($array_initials, "strnatcasecmp");
1586 echo '<table id="initials_table" cellspacing="5"><tr>';
1587 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1588 if ($initial_was_found) {
1589 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1591 echo '<td>' . $tmp_initial . '</td>';
1594 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&showall=1">[' . __('Show all') . ']</a></td>' . "\n";
1595 echo '</tr></table>';
1599 * Display the user overview
1600 * (if less than 50 users, display them immediately)
1603 if (isset($initial) ||
isset($showall) ||
PMA_DBI_num_rows($res) < 50) {
1605 while ($row = PMA_DBI_fetch_assoc($res)) {
1606 $row['privs'] = PMA_extractPrivInfo($row, true);
1607 $db_rights[$row['User']][$row['Host']] = $row;
1609 @PMA_DBI_free_result
($res);
1612 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1613 . PMA_generate_common_hidden_inputs('', '')
1614 . ' <table id="tableuserrights" class="data">' . "\n"
1616 . ' <tr><th></th>' . "\n"
1617 . ' <th>' . __('User') . '</th>' . "\n"
1618 . ' <th>' . __('Host') . '</th>' . "\n"
1619 . ' <th>' . __('Password') . '</th>' . "\n"
1620 . ' <th>' . __('Global privileges') . ' '
1621 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English ')) . '</th>' . "\n"
1622 . ' <th>' . __('Grant') . '</th>' . "\n"
1623 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1624 echo ' </tr>' . "\n";
1625 echo ' </thead>' . "\n";
1626 echo ' <tbody>' . "\n";
1628 $index_checkbox = -1;
1629 foreach ($db_rights as $user) {
1632 foreach ($user as $host) {
1634 echo ' <tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
1635 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1636 . $index_checkbox . '" value="'
1637 . htmlspecialchars($host['User'] . '&#27;' . $host['Host'])
1639 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
1641 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1642 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1644 switch ($host['Password']) {
1649 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1651 // this happens if this is a definition not coming from mysql.user
1653 echo '--'; // in future version, replace by "not present"
1657 . ' <td><tt>' . "\n"
1658 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1659 . ' </tt></td>' . "\n"
1660 . ' <td>' . ($host['Grant_priv'] == 'Y' ?
__('Yes') : __('No')) . '</td>' . "\n"
1661 . ' <td align="center">';
1662 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1664 echo '<td align="center">';
1665 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ?
$initial : ''));
1668 $odd_row = ! $odd_row;
1672 unset($user, $host, $odd_row);
1673 echo ' </tbody></table>' . "\n"
1674 .'<img class="selectallarrow"'
1675 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1676 .' width="38" height="22"'
1677 .' alt="' . __('With selected:') . '" />' . "\n"
1678 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&checkall=1"'
1679 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1680 . __('Check All') . '</a>' . "\n"
1682 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1683 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1684 . __('Uncheck All') . '</a>' . "\n";
1686 // add/delete user fieldset
1687 echo ' <fieldset id="fieldset_add_user">' . "\n"
1688 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1">' . "\n"
1689 . PMA_getIcon('b_usradd.png')
1690 . ' ' . __('Add a new User') . '</a>' . "\n"
1691 . ' </fieldset>' . "\n"
1692 . ' <fieldset id="fieldset_delete_user">'
1693 . ' <legend>' . "\n"
1694 . PMA_getIcon('b_usrdrop.png')
1695 . ' ' . __('Remove selected users') . '' . "\n"
1696 . ' </legend>' . "\n"
1697 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1698 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1699 . ' <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"
1700 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1701 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1702 . ' </label>' . "\n"
1703 . ' </fieldset>' . "\n"
1704 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1705 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" />' . "\n"
1706 . ' </fieldset>' . "\n"
1711 echo ' <fieldset id="fieldset_add_user">' . "\n"
1712 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1">' . "\n"
1713 . PMA_getIcon('b_usradd.png')
1714 . ' ' . __('Add a new User') . '</a>' . "\n"
1715 . ' </fieldset>' . "\n";
1716 } // end if (display overview)
1718 if( $GLOBALS['is_ajax_request'] ) {
1722 $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
);
1723 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&flush_privileges=1" id="reload_privileges_anchor">', false);
1724 $flushnote->addParam('</a>', false);
1725 $flushnote->display();
1731 // A user was selected -> display the user's properties
1733 // In an Ajax request, prevent cached values from showing
1734 if($GLOBALS['is_ajax_request'] == true) {
1735 header('Cache-Control: no-cache');
1739 . PMA_getIcon('b_usredit.png')
1740 . __('Edit Privileges') . ': '
1743 if (isset($dbname)) {
1744 echo ' <i><a href="server_privileges.php?'
1745 . $GLOBALS['url_query'] . '&username=' . htmlspecialchars(urlencode($username))
1746 . '&hostname=' . htmlspecialchars(urlencode($hostname)) . '&dbname=&tablename=">\''
1747 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1748 . '\'</a></i>' . "\n";
1749 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
1751 echo ' - ' . ($dbname_is_wildcard ?
__('Databases') : __('Database') );
1752 if (isset($tablename)) {
1753 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
1754 . '&username=' . htmlspecialchars(urlencode($username)) . '&hostname=' . htmlspecialchars(urlencode($hostname))
1755 . '&dbname=' . htmlspecialchars($url_dbname) . '&tablename=">' . htmlspecialchars($dbname) . '</a></i>';
1756 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
1758 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
1762 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1766 echo '</h2>' . "\n";
1769 $sql = "SELECT '1' FROM `mysql`.`user`"
1770 . " WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
1771 . " AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
1772 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
1774 if ($user_does_not_exists) {
1775 PMA_Message
::warning(__('The selected user was not found in the privilege table.'))->display();
1776 PMA_displayLoginInformationFields();
1777 //require './libraries/footer.inc.php';
1780 echo '<form name="usersForm" id="addUsersForm" action="server_privileges.php" method="post">' . "\n";
1782 'username' => $username,
1783 'hostname' => $hostname,
1785 if (isset($dbname)) {
1786 $_params['dbname'] = $dbname;
1787 if (isset($tablename)) {
1788 $_params['tablename'] = $tablename;
1791 echo PMA_generate_common_hidden_inputs($_params);
1793 PMA_displayPrivTable(PMA_ifSetOr($dbname, '*', 'length'),
1794 PMA_ifSetOr($tablename, '*', 'length'));
1796 echo '</form>' . "\n";
1798 if (! isset($tablename) && empty($dbname_is_wildcard)) {
1800 // no table name was given, display all table specific rights
1801 // but only if $dbname contains no wildcards
1804 echo '<form action="server_privileges.php" method="post">' . "\n"
1805 . PMA_generate_common_hidden_inputs('', '')
1806 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
1807 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1808 . '<fieldset>' . "\n"
1809 . '<legend>' . (! isset($dbname) ?
__('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
1810 . '<table class="data">' . "\n"
1812 . '<tr><th>' . (! isset($dbname) ?
__('Database') : __('Table')) . '</th>' . "\n"
1813 . ' <th>' . __('Privileges') . '</th>' . "\n"
1814 . ' <th>' . __('Grant') . '</th>' . "\n"
1815 . ' <th>' . (! isset($dbname) ?
__('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
1816 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
1821 $user_host_condition =
1823 . ' = \'' . PMA_sqlAddslashes($username) . "'"
1825 . ' = \'' . PMA_sqlAddslashes($hostname) . "'";
1830 // we also want privielgs for this user not in table `db` but in other table
1831 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1832 if (! isset($dbname)) {
1834 // no db name given, so we want all privs for the given user
1836 $tables_to_search_for_users = array(
1837 'tables_priv', 'columns_priv',
1840 $db_rights_sqls = array();
1841 foreach ($tables_to_search_for_users as $table_search_in) {
1842 if (in_array($table_search_in, $tables)) {
1843 $db_rights_sqls[] = '
1844 SELECT DISTINCT `Db`
1845 FROM `mysql`.' . PMA_backquote($table_search_in)
1846 . $user_host_condition;
1850 $user_defaults = array(
1852 'Grant_priv' => 'N',
1853 'privs' => array('USAGE'),
1854 'Table_privs' => true,
1858 $db_rights = array();
1860 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1861 .' ORDER BY `Db` ASC';
1863 $db_rights_result = PMA_DBI_query($db_rights_sql);
1865 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1866 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1867 // only Db names in the table `mysql`.`db` uses wildcards
1868 // as we are in the db specific rights display we want
1869 // all db names escaped, also from other sources
1870 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
1871 $db_rights_row['Db']);
1872 $db_rights[$db_rights_row['Db']] = $db_rights_row;
1875 PMA_DBI_free_result($db_rights_result);
1876 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1878 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
1879 $res = PMA_DBI_query($sql_query);
1882 while ($row = PMA_DBI_fetch_assoc($res)) {
1883 if (isset($db_rights[$row['Db']])) {
1884 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
1886 $db_rights[$row['Db']] = $row;
1888 // there are db specific rights for this user
1889 // so we can drop this db rights
1890 $db_rights[$row['Db']]['can_delete'] = true;
1892 PMA_DBI_free_result($res);
1897 // db name was given,
1898 // so we want all user specific rights for this db
1900 $user_host_condition .=
1902 .' LIKE \'' . PMA_sqlAddslashes($dbname) . "'";
1904 $tables_to_search_for_users = array(
1908 $db_rights_sqls = array();
1909 foreach ($tables_to_search_for_users as $table_search_in) {
1910 if (in_array($table_search_in, $tables)) {
1911 $db_rights_sqls[] = '
1912 SELECT DISTINCT `Table_name`
1913 FROM `mysql`.' . PMA_backquote($table_search_in)
1914 . $user_host_condition;
1918 $user_defaults = array(
1920 'Grant_priv' => 'N',
1921 'privs' => array('USAGE'),
1922 'Column_priv' => true,
1926 $db_rights = array();
1928 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1929 .' ORDER BY `Table_name` ASC';
1931 $db_rights_result = PMA_DBI_query($db_rights_sql);
1933 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1934 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1935 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
1937 PMA_DBI_free_result($db_rights_result);
1938 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1941 'SELECT `Table_name`,'
1943 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
1944 .' AS \'Column_priv\''
1945 .' FROM `mysql`.`tables_priv`'
1946 . $user_host_condition
1947 .' ORDER BY `Table_name` ASC;';
1948 $res = PMA_DBI_query($sql_query);
1951 while ($row = PMA_DBI_fetch_assoc($res)) {
1952 if (isset($db_rights[$row['Table_name']])) {
1953 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
1955 $db_rights[$row['Table_name']] = $row;
1958 PMA_DBI_free_result($res);
1964 if (count($db_rights) < 1) {
1965 echo '<tr class="odd">' . "\n"
1966 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
1970 $found_rows = array();
1971 //while ($row = PMA_DBI_fetch_assoc($res)) {
1972 foreach ($db_rights as $row) {
1973 $found_rows[] = (! isset($dbname)) ?
$row['Db'] : $row['Table_name'];
1975 echo '<tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
1976 . ' <td>' . htmlspecialchars((! isset($dbname)) ?
$row['Db'] : $row['Table_name']) . '</td>' . "\n"
1977 . ' <td><tt>' . "\n"
1978 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, TRUE)) . "\n"
1979 . ' </tt></td>' . "\n"
1980 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') ||
(isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ?
__('Yes') : __('No')) . '</td>' . "\n"
1982 if (! empty($row['Table_privs']) ||
! empty ($row['Column_priv'])) {
1989 printf($link_edit, htmlspecialchars(urlencode($username)),
1990 urlencode(htmlspecialchars($hostname)),
1991 urlencode((! isset($dbname)) ?
$row['Db'] : htmlspecialchars($dbname)),
1992 urlencode((! isset($dbname)) ?
'' : $row['Table_name']));
1995 if (! empty($row['can_delete']) ||
isset($row['Table_name']) && strlen($row['Table_name'])) {
1996 printf($link_revoke, htmlspecialchars(urlencode($username)),
1997 urlencode(htmlspecialchars($hostname)),
1998 urlencode((! isset($dbname)) ?
$row['Db'] : htmlspecialchars($dbname)),
1999 urlencode((! isset($dbname)) ?
'' : $row['Table_name']));
2003 $odd_row = ! $odd_row;
2007 echo '</tbody>' . "\n"
2008 . '</table>' . "\n";
2010 if (! isset($dbname)) {
2012 // no database name was given, display select db
2014 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
2016 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
2017 if (!empty($pred_db_array)) {
2018 echo ' <select name="pred_dbname" onchange="this.form.submit();">' . "\n"
2019 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2020 foreach ($pred_db_array as $current_db) {
2021 $current_db = PMA_escape_mysql_wildcards($current_db);
2022 // cannot use array_diff() once, outside of the loop,
2023 // because the list of databases has special characters
2024 // already escaped in $found_rows,
2025 // contrary to the output of SHOW DATABASES
2026 if (empty($found_rows) ||
! in_array($current_db, $found_rows)) {
2027 echo ' <option value="' . htmlspecialchars($current_db) . '">'
2028 . htmlspecialchars($current_db) . '</option>' . "\n";
2031 echo ' </select>' . "\n";
2033 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
2034 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
2036 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
2037 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
2038 if ($res = @PMA_DBI_try_query
('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE
)) {
2039 $pred_tbl_array = array();
2040 while ($row = PMA_DBI_fetch_row($res)) {
2041 if (!isset($found_rows) ||
!in_array($row[0], $found_rows)) {
2042 $pred_tbl_array[] = $row[0];
2045 PMA_DBI_free_result($res);
2047 if (!empty($pred_tbl_array)) {
2048 echo ' <select name="pred_tablename" onchange="this.form.submit();">' . "\n"
2049 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2050 foreach ($pred_tbl_array as $current_table) {
2051 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
2053 echo ' </select>' . "\n";
2058 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
2060 echo '</fieldset>' . "\n";
2061 echo '<fieldset class="tblFooters">' . "\n"
2062 . ' <input type="submit" value="' . __('Go') . '" />'
2063 . '</fieldset>' . "\n"
2068 // Provide a line with links to the relevant database and table
2069 if (isset($dbname) && empty($dbname_is_wildcard)) {
2070 echo '[ ' . __('Database')
2071 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
2072 . $GLOBALS['url_query'] . '&db=' . $url_dbname . '&reload=1">'
2073 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
2075 if (isset($tablename)) {
2076 echo ' [ ' . __('Table') . ' <a href="'
2077 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
2078 . '&db=' . $url_dbname . '&table=' . htmlspecialchars(urlencode($tablename))
2079 . '&reload=1">' . htmlspecialchars($tablename) . ': '
2080 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
2086 if (! isset($dbname) && ! $user_does_not_exists) {
2087 require_once './libraries/display_change_password.lib.php';
2089 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
2090 . PMA_generate_common_hidden_inputs('', '')
2091 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
2092 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
2093 . '<fieldset id="fieldset_change_copy_user">' . "\n"
2094 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
2095 PMA_displayLoginInformationFields('change');
2096 echo ' <fieldset>' . "\n"
2097 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2099 '4' => __('... keep the old one.'),
2100 '1' => __(' ... delete the old one from the user tables.'),
2101 '2' => __(' ... revoke all active privileges from the old one and delete it afterwards.'),
2102 '3' => __(' ... delete the old one from the user tables and reload the privileges afterwards.'));
2103 PMA_display_html_radio('mode', $choices, '4', true);
2106 echo ' </fieldset>' . "\n"
2107 . '</fieldset>' . "\n"
2108 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2109 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2110 . '</fieldset>' . "\n"
2114 } elseif (isset($_REQUEST['adduser'])) {
2117 $GLOBALS['url_query'] .= '&adduser=1';
2119 . PMA_getIcon('b_usradd.png') . __('Add a new User') . "\n"
2121 . '<form name="usersForm" id="addUsersForm" action="server_privileges.php" method="post">' . "\n"
2122 . PMA_generate_common_hidden_inputs('', '');
2123 PMA_displayLoginInformationFields('new');
2124 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2125 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2127 $default_choice = 0;
2129 '0' => _pgettext('Create none database for user', 'None'),
2130 '1' => __('Create database with same name and grant all privileges'),
2131 '2' => __('Grant all privileges on wildcard name (username\\_%)'));
2133 if ( !empty($dbname) ) {
2134 $choices['3'] = sprintf( __('Grant all privileges on database "%s"'), htmlspecialchars($dbname));
2135 $default_choice = 3;
2136 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2139 // 4th parameter set to true to add line breaks
2140 // 5th parameter set to false to avoid htmlspecialchars() escaping in the label
2141 // since we have some HTML in some labels
2142 PMA_display_html_radio('createdb', $choices, $default_choice, true, false);
2144 unset($default_choice);
2146 echo '</fieldset>' . "\n";
2147 PMA_displayPrivTable('*', '*', FALSE);
2148 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2149 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2150 . ' </fieldset>' . "\n"
2153 // check the privileges for a particular database.
2154 echo '<table id="tablespecificuserrights" class="data">' . "\n"
2155 . '<caption class="tblHeaders">' . "\n"
2156 . PMA_getIcon('b_usrcheck.png')
2157 . ' ' . sprintf(__('Users having access to "%s"'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2158 . '</caption>' . "\n"
2160 . ' <tr><th>' . __('User') . '</th>' . "\n"
2161 . ' <th>' . __('Host') . '</th>' . "\n"
2162 . ' <th>' . __('Type') . '</th>' . "\n"
2163 . ' <th>' . __('Privileges') . '</th>' . "\n"
2164 . ' <th>' . __('Grant') . '</th>' . "\n"
2165 . ' <th>' . __('Action') . '</th>' . "\n"
2170 unset($row, $row1, $row2);
2172 // now, we build the table...
2173 $list_of_privileges =
2185 . '`References_priv`, '
2186 . '`Create_tmp_table_priv`, '
2187 . '`Lock_tables_priv`, '
2188 . '`Create_view_priv`, '
2189 . '`Show_view_priv`, '
2190 . '`Create_routine_priv`, '
2191 . '`Alter_routine_priv`, '
2194 $list_of_compared_privileges =
2195 '`Select_priv` = \'N\''
2196 . ' AND `Insert_priv` = \'N\''
2197 . ' AND `Update_priv` = \'N\''
2198 . ' AND `Delete_priv` = \'N\''
2199 . ' AND `Create_priv` = \'N\''
2200 . ' AND `Drop_priv` = \'N\''
2201 . ' AND `Grant_priv` = \'N\''
2202 . ' AND `References_priv` = \'N\''
2203 . ' AND `Create_tmp_table_priv` = \'N\''
2204 . ' AND `Lock_tables_priv` = \'N\''
2205 . ' AND `Create_view_priv` = \'N\''
2206 . ' AND `Show_view_priv` = \'N\''
2207 . ' AND `Create_routine_priv` = \'N\''
2208 . ' AND `Alter_routine_priv` = \'N\''
2209 . ' AND `Execute_priv` = \'N\'';
2211 if (PMA_MYSQL_INT_VERSION
>= 50106) {
2212 $list_of_privileges .=
2215 $list_of_compared_privileges .=
2216 ' AND `Event_priv` = \'N\''
2217 . ' AND `Trigger_priv` = \'N\'';
2221 '(SELECT ' . $list_of_privileges . ', `Db`'
2222 .' FROM `mysql`.`db`'
2223 .' WHERE \'' . PMA_sqlAddslashes($checkprivs) . "'"
2225 .' AND NOT (' . $list_of_compared_privileges. ')) '
2227 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2228 .' FROM `mysql`.`user` '
2229 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2230 .' ORDER BY `User` ASC,'
2233 $res = PMA_DBI_query($sql_query);
2234 $row = PMA_DBI_fetch_assoc($res);
2241 // prepare the current user
2242 $current_privileges = array();
2243 $current_user = $row['User'];
2244 $current_host = $row['Host'];
2245 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2246 $current_privileges[] = $row;
2247 $row = PMA_DBI_fetch_assoc($res);
2249 echo ' <tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
2251 if (count($current_privileges) > 1) {
2252 echo ' rowspan="' . count($current_privileges) . '"';
2254 echo '>' . (empty($current_user) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2257 if (count($current_privileges) > 1) {
2258 echo ' rowspan="' . count($current_privileges) . '"';
2260 echo '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2261 foreach ($current_privileges as $current) {
2264 if (!isset($current['Db']) ||
$current['Db'] == '*') {
2266 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2267 echo __('database-specific');
2269 echo __('wildcard'), ': <tt>' . htmlspecialchars($current['Db']) . '</tt>';
2275 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, TRUE)) . "\n"
2279 . ' ' . ($current['Grant_priv'] == 'Y' ?
__('Yes') : __('No')) . "\n"
2282 printf($link_edit, urlencode($current_user),
2283 urlencode($current_host),
2284 urlencode(! isset($current['Db']) ||
$current['Db'] == '*' ?
'' : $current['Db']),
2289 if (empty($row) && empty($row1) && empty($row2)) {
2292 $odd_row = ! $odd_row;
2295 echo ' <tr class="odd">' . "\n"
2296 . ' <td colspan="6">' . "\n"
2297 . ' ' . __('No user found.') . "\n"
2301 echo '</tbody>' . "\n"
2302 . '</table>' . "\n";
2304 // Offer to create a new user for the current database
2305 echo '<fieldset id="fieldset_add_user">' . "\n"
2306 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1&dbname=' . htmlspecialchars($checkprivs) .'">' . "\n"
2307 . PMA_getIcon('b_usradd.png')
2308 . ' ' . __('Add a new User') . '</a>' . "\n"
2309 . '</fieldset>' . "\n";
2311 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2315 * Displays the footer
2318 require './libraries/footer.inc.php';