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';
19 $_add_user_error = false;
21 require './libraries/server_common.inc.php';
23 if ($GLOBALS['cfg']['AjaxEnable']) {
24 $conditional_class = 'ajax';
26 $conditional_class = '';
30 * Messages are built using the message name
32 $strPrivDescAllPrivileges = __('Includes all privileges except GRANT.');
33 $strPrivDescAlter = __('Allows altering the structure of existing tables.');
34 $strPrivDescAlterRoutine = __('Allows altering and dropping stored routines.');
35 $strPrivDescCreateDb = __('Allows creating new databases and tables.');
36 $strPrivDescCreateRoutine = __('Allows creating stored routines.');
37 $strPrivDescCreateTbl = __('Allows creating new tables.');
38 $strPrivDescCreateTmpTable = __('Allows creating temporary tables.');
39 $strPrivDescCreateUser = __('Allows creating, dropping and renaming user accounts.');
40 $strPrivDescCreateView = __('Allows creating new views.');
41 $strPrivDescDelete = __('Allows deleting data.');
42 $strPrivDescDropDb = __('Allows dropping databases and tables.');
43 $strPrivDescDropTbl = __('Allows dropping tables.');
44 $strPrivDescEvent = __('Allows to set up events for the event scheduler');
45 $strPrivDescExecute = __('Allows executing stored routines.');
46 $strPrivDescFile = __('Allows importing data from and exporting data into files.');
47 $strPrivDescGrant = __('Allows adding users and privileges without reloading the privilege tables.');
48 $strPrivDescIndex = __('Allows creating and dropping indexes.');
49 $strPrivDescInsert = __('Allows inserting and replacing data.');
50 $strPrivDescLockTables = __('Allows locking tables for the current thread.');
51 $strPrivDescMaxConnections = __('Limits the number of new connections the user may open per hour.');
52 $strPrivDescMaxQuestions = __('Limits the number of queries the user may send to the server per hour.');
53 $strPrivDescMaxUpdates = __('Limits the number of commands that change any table or database the user may execute per hour.');
54 $strPrivDescMaxUserConnections = __('Limits the number of simultaneous connections the user may have.');
55 $strPrivDescProcess = __('Allows viewing processes of all users');
56 $strPrivDescReferences = __('Has no effect in this MySQL version.');
57 $strPrivDescReload = __('Allows reloading server settings and flushing the server\'s caches.');
58 $strPrivDescReplClient = __('Allows the user to ask where the slaves / masters are.');
59 $strPrivDescReplSlave = __('Needed for the replication slaves.');
60 $strPrivDescSelect = __('Allows reading data.');
61 $strPrivDescShowDb = __('Gives access to the complete list of databases.');
62 $strPrivDescShowView = __('Allows performing SHOW CREATE VIEW queries.');
63 $strPrivDescShutdown = __('Allows shutting down the server.');
64 $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.');
65 $strPrivDescTrigger = __('Allows creating and dropping triggers');
66 $strPrivDescUpdate = __('Allows changing data.');
67 $strPrivDescUsage = __('No privileges.');
70 * Checks if a dropdown box has been used for selecting a database / table
72 if (PMA_isValid($_REQUEST['pred_tablename'])) {
73 $tablename = $_REQUEST['pred_tablename'];
74 unset($pred_tablename);
75 } elseif (PMA_isValid($_REQUEST['tablename'])) {
76 $tablename = $_REQUEST['tablename'];
81 if (PMA_isValid($_REQUEST['pred_dbname'])) {
82 $dbname = $_REQUEST['pred_dbname'];
84 } elseif (PMA_isValid($_REQUEST['dbname'])) {
85 $dbname = $_REQUEST['dbname'];
92 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
93 if (isset($tablename)) {
94 $db_and_table .= PMA_backquote($tablename);
99 $db_and_table = '*.*';
102 // check if given $dbname is a wildcard or not
103 if (isset($dbname)) {
104 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
105 if (preg_match('/(?<!\\\\)(?:_|%)/i', $dbname)) {
106 $dbname_is_wildcard = true;
108 $dbname_is_wildcard = false;
113 * Checks if the user is allowed to do what he tries to...
115 if (!$is_superuser) {
116 require './libraries/server_links.inc.php';
118 . PMA_getIcon('b_usrlist.png')
119 . __('Privileges') . "\n"
121 PMA_Message
::error(__('No Privileges'))->display();
122 require './libraries/footer.inc.php';
125 $random_n = mt_rand(0,1000000); // a random number that will be appended to the id of the user forms
128 * Escapes wildcard in a database+table specification
129 * before using it in a GRANT statement.
131 * Escaping a wildcard character in a GRANT is only accepted at the global
132 * or database level, not at table level; this is why I remove
133 * the escaping character. Internally, in mysql.tables_priv.Db there are
134 * no escaping (for example test_db) but in mysql.db you'll see test\_db
135 * for a db-specific privilege.
137 * @param string $dbname Database name
138 * @param string $tablename Table name
139 * @return string the escaped (if necessary) database.table
141 function PMA_wildcardEscapeForGrant($dbname, $tablename)
144 if (! strlen($dbname)) {
145 $db_and_table = '*.*';
147 if (strlen($tablename)) {
148 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
149 $db_and_table .= PMA_backquote($tablename);
151 $db_and_table = PMA_backquote($dbname) . '.';
152 $db_and_table .= '*';
155 return $db_and_table;
159 * Generates a condition on the user name
161 * @param string the user's initial
162 * @return string the generated condition
164 function PMA_rangeOfUsers($initial = '')
166 // strtolower() is used because the User field
167 // might be BINARY, so LIKE would be case sensitive
168 if (!empty($initial)) {
169 $ret = " WHERE `User` LIKE '" . PMA_sqlAddSlashes($initial, true) . "%'"
170 . " OR `User` LIKE '" . PMA_sqlAddSlashes(strtolower($initial), true) . "%'";
178 * Extracts the privilege information of a priv table row
180 * @param array $row the row
181 * @param boolean $enableHTML add <dfn> tag with tooltips
183 * @global resource $user_link the database connection
187 function PMA_extractPrivInfo($row = '', $enableHTML = false)
193 __('Allows reading data.')),
197 __('Allows inserting and replacing data.')),
201 __('Allows changing data.')),
205 __('Allows deleting data.')),
209 __('Allows creating new databases and tables.')),
213 __('Allows dropping databases and tables.')),
217 __('Allows reloading server settings and flushing the server\'s caches.')),
221 __('Allows shutting down the server.')),
225 __('Allows viewing processes of all users')),
229 __('Allows importing data from and exporting data into files.')),
233 __('Has no effect in this MySQL version.')),
237 __('Allows creating and dropping indexes.')),
241 __('Allows altering the structure of existing tables.')),
245 __('Gives access to the complete list of databases.')),
249 __('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.')),
251 'Create_tmp_table_priv',
252 'CREATE TEMPORARY TABLES',
253 __('Allows creating temporary tables.')),
257 __('Allows locking tables for the current thread.')),
261 __('Needed for the replication slaves.')),
264 'REPLICATION CLIENT',
265 __('Allows the user to ask where the slaves / masters are.')),
269 __('Allows creating new views.')),
273 __('Allows to set up events for the event scheduler')),
277 __('Allows creating and dropping triggers')),
282 __('Allows creating new views.')),
286 __('Allows performing SHOW CREATE VIEW queries.')),
291 __('Allows performing SHOW CREATE VIEW queries.')),
293 'Create_routine_priv',
295 __('Allows creating stored routines.')),
297 'Alter_routine_priv',
299 __('Allows altering and dropping stored routines.')),
303 __('Allows creating, dropping and renaming user accounts.')),
307 __('Allows executing stored routines.')),
310 if (!empty($row) && isset($row['Table_priv'])) {
311 $row1 = PMA_DBI_fetch_single_row(
312 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
313 'ASSOC', $GLOBALS['userlink']);
314 $av_grants = explode('\',\'', substr($row1['Type'], 5, strlen($row1['Type']) - 7));
316 $users_grants = explode(',', $row['Table_priv']);
317 foreach ($av_grants as $current_grant) {
318 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ?
'Y' : 'N';
320 unset($current_grant);
322 unset($users_grants);
325 $allPrivileges = true;
326 foreach ($grants as $current_grant) {
327 if ((!empty($row) && isset($row[$current_grant[0]]))
328 ||
(empty($row) && isset($GLOBALS[$current_grant[0]]))) {
329 if ((!empty($row) && $row[$current_grant[0]] == 'Y')
331 && ($GLOBALS[$current_grant[0]] == 'Y'
332 ||
(is_array($GLOBALS[$current_grant[0]])
333 && count($GLOBALS[$current_grant[0]]) == $GLOBALS['column_count']
334 && empty($GLOBALS[$current_grant[0] . '_none'])))))
337 $privs[] = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
339 $privs[] = $current_grant[1];
341 } elseif (!empty($GLOBALS[$current_grant[0]])
342 && is_array($GLOBALS[$current_grant[0]])
343 && empty($GLOBALS[$current_grant[0] . '_none'])) {
345 $priv_string = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
347 $priv_string = $current_grant[1];
349 $privs[] = $priv_string . ' (`' . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
351 $allPrivileges = false;
357 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
361 } elseif ($allPrivileges && (! isset($GLOBALS['grant_count']) ||
count($privs) == $GLOBALS['grant_count'])) {
363 $privs = array('<dfn title="' . __('Includes all privileges except GRANT.') . '">ALL PRIVILEGES</dfn>');
365 $privs = array('ALL PRIVILEGES');
369 } // end of the 'PMA_extractPrivInfo()' function
372 * Displays on which column(s) a table-specific privilege is granted
374 function PMA_display_column_privs($columns, $row, $name_for_select,
375 $priv_for_header, $name, $name_for_dfn, $name_for_current)
377 echo ' <div class="item" id="div_item_' . $name . '">' . "\n"
378 . ' <label for="select_' . $name . '_priv">' . "\n"
379 . ' <tt><dfn title="' . $name_for_dfn . '">'
380 . $priv_for_header . '</dfn></tt>' . "\n"
381 . ' </label><br />' . "\n"
382 . ' <select id="select_' . $name . '_priv" name="'
383 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
385 foreach ($columns as $current_column => $current_column_privileges) {
386 echo ' <option value="' . htmlspecialchars($current_column) . '"';
387 if ($row[$name_for_select] == 'Y' ||
$current_column_privileges[$name_for_current]) {
388 echo ' selected="selected"';
390 echo '>' . htmlspecialchars($current_column) . '</option>' . "\n";
393 echo ' </select>' . "\n"
394 . ' <i>' . __('Or') . '</i>' . "\n"
395 . ' <label for="checkbox_' . $name_for_select
396 . '_none"><input type="checkbox"'
397 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
398 . ' name="' . $name_for_select . '_none" id="checkbox_'
399 . $name_for_select . '_none" title="' . _pgettext('None privileges', 'None') . '" />'
400 . _pgettext('None privileges', 'None') . '</label>' . "\n"
406 * Displays the privileges form table
408 * @param string $db the database
409 * @param string $table the table
410 * @param boolean $submit wheather to display the submit button or not
411 * @global array $cfg the phpMyAdmin configuration
412 * @global ressource $user_link the database connection
416 function PMA_displayPrivTable($db = '*', $table = '*', $submit = true)
424 if (isset($GLOBALS['username'])) {
425 $username = $GLOBALS['username'];
426 $hostname = $GLOBALS['hostname'];
429 "SELECT * FROM `mysql`.`user`"
430 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
431 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
432 } elseif ($table == '*') {
434 "SELECT * FROM `mysql`.`db`"
435 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
436 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
437 ." AND '" . PMA_unescape_mysql_wildcards($db) . "'"
441 "SELECT `Table_priv`"
442 ." FROM `mysql`.`tables_priv`"
443 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
444 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
445 ." AND `Db` = '" . PMA_unescape_mysql_wildcards($db) . "'"
446 ." AND `Table_name` = '" . PMA_sqlAddSlashes($table) . "';";
448 $row = PMA_DBI_fetch_single_row($sql_query);
453 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
454 } elseif ($table == '*') {
455 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
457 $res = PMA_DBI_query($sql_query);
458 while ($row1 = PMA_DBI_fetch_row($res)) {
459 if (substr($row1[0], 0, 4) == 'max_') {
462 $row[$row1[0]] = 'N';
465 PMA_DBI_free_result($res);
467 $row = array('Table_priv' => '');
470 if (isset($row['Table_priv'])) {
471 $row1 = PMA_DBI_fetch_single_row(
472 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
473 'ASSOC', $GLOBALS['userlink']);
474 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
475 // the View for Create is spelled with uppercase V
476 // the view for Show is spelled with lowercase v
477 // and there is a space between the words
479 $av_grants = explode('\',\'', substr($row1['Type'], strpos($row1['Type'], '(') +
2, strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3));
481 $users_grants = explode(',', $row['Table_priv']);
483 foreach ($av_grants as $current_grant) {
484 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ?
'Y' : 'N';
486 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
489 $res = PMA_DBI_try_query('SHOW COLUMNS FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($db)) . '.' . PMA_backquote($table) . ';');
492 while ($row1 = PMA_DBI_fetch_row($res)) {
493 $columns[$row1[0]] = array(
497 'References' => false
500 PMA_DBI_free_result($res);
504 // t a b l e - s p e c i f i c p r i v i l e g e s
505 if (! empty($columns)) {
506 $res = PMA_DBI_query(
507 'SELECT `Column_name`, `Column_priv`'
508 .' FROM `mysql`.`columns_priv`'
510 .' = \'' . PMA_sqlAddSlashes($username) . "'"
512 .' = \'' . PMA_sqlAddSlashes($hostname) . "'"
514 .' = \'' . PMA_sqlAddSlashes(PMA_unescape_mysql_wildcards($db)) . "'"
516 .' = \'' . PMA_sqlAddSlashes($table) . '\';');
518 while ($row1 = PMA_DBI_fetch_row($res)) {
519 $row1[1] = explode(',', $row1[1]);
520 foreach ($row1[1] as $current) {
521 $columns[$row1[0]][$current] = true;
524 PMA_DBI_free_result($res);
525 unset($res, $row1, $current);
527 echo '<input type="hidden" name="grant_count" value="' . count($row) . '" />' . "\n"
528 . '<input type="hidden" name="column_count" value="' . count($columns) . '" />' . "\n"
529 . '<fieldset id="fieldset_user_priv">' . "\n"
530 . ' <legend>' . __('Table-specific privileges')
531 . PMA_showHint(__('Note: MySQL privilege names are expressed in English'))
532 . '</legend>' . "\n";
536 // privs that are attached to a specific column
537 PMA_display_column_privs($columns, $row, 'Select_priv',
538 'SELECT', 'select', __('Allows reading data.'), 'Select');
540 PMA_display_column_privs($columns, $row, 'Insert_priv',
541 'INSERT', 'insert', __('Allows inserting and replacing data.'), 'Insert');
543 PMA_display_column_privs($columns, $row, 'Update_priv',
544 'UPDATE', 'update', __('Allows changing data.'), 'Update');
546 PMA_display_column_privs($columns, $row, 'References_priv',
547 'REFERENCES', 'references', __('Has no effect in this MySQL version.'), 'References');
549 // privs that are not attached to a specific column
551 echo ' <div class="item">' . "\n";
552 foreach ($row as $current_grant => $current_grant_value) {
553 if (in_array(substr($current_grant, 0, (strlen($current_grant) - 5)),
554 array('Select', 'Insert', 'Update', 'References'))) {
557 // make a substitution to match the messages variables;
558 // also we must substitute the grant we get, because we can't generate
559 // a form variable containing blanks (those would get changed to
560 // an underscore when receiving the POST)
561 if ($current_grant == 'Create View_priv') {
562 $tmp_current_grant = 'CreateView_priv';
563 $current_grant = 'Create_view_priv';
564 } elseif ($current_grant == 'Show view_priv') {
565 $tmp_current_grant = 'ShowView_priv';
566 $current_grant = 'Show_view_priv';
568 $tmp_current_grant = $current_grant;
571 echo ' <div class="item">' . "\n"
572 . ' <input type="checkbox"'
573 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
574 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
576 . ($current_grant_value == 'Y' ?
'checked="checked" ' : '')
579 echo (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
580 ?
$GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
581 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl']) . '"/>' . "\n";
583 echo ' <label for="checkbox_' . $current_grant
584 . '"><tt><dfn title="'
585 . (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
586 ?
$GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
587 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl'])
588 . '">' . strtoupper(substr($current_grant, 0, strlen($current_grant) - 5)) . '</dfn></tt></label>' . "\n"
592 echo ' </div>' . "\n";
594 echo ' <div class="clearfloat"></div>' . "\n";
598 // g l o b a l o r d b - s p e c i f i c
600 $privTable_names = array(0 => __('Data'), 1 => __('Structure'), 2 => __('Administration'));
603 $privTable[0] = array(
604 array('Select', 'SELECT', __('Allows reading data.')),
605 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
606 array('Update', 'UPDATE', __('Allows changing data.')),
607 array('Delete', 'DELETE', __('Allows deleting data.'))
610 $privTable[0][] = array('File', 'FILE', __('Allows importing data from and exporting data into files.'));
614 $privTable[1] = array(
615 array('Create', 'CREATE', ($table == '*' ?
__('Allows creating new databases and tables.') : __('Allows creating new tables.'))),
616 array('Alter', 'ALTER', __('Allows altering the structure of existing tables.')),
617 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
618 array('Drop', 'DROP', ($table == '*' ?
__('Allows dropping databases and tables.') : __('Allows dropping tables.'))),
619 array('Create_tmp_table', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
620 array('Show_view', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
621 array('Create_routine', 'CREATE ROUTINE', __('Allows creating stored routines.')),
622 array('Alter_routine', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
623 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
625 // this one is for a db-specific priv: Create_view_priv
626 if (isset($row['Create_view_priv'])) {
627 $privTable[1][] = array('Create_view', 'CREATE VIEW', __('Allows creating new views.'));
629 // this one is for a table-specific priv: Create View_priv
630 if (isset($row['Create View_priv'])) {
631 $privTable[1][] = array('Create View', 'CREATE VIEW', __('Allows creating new views.'));
633 if (isset($row['Event_priv'])) {
635 $privTable[1][] = array('Event', 'EVENT', __('Allows to set up events for the event scheduler'));
636 $privTable[1][] = array('Trigger', 'TRIGGER', __('Allows creating and dropping triggers'));
639 // a d m i n i s t r a t i o n
640 $privTable[2] = array(
641 array('Grant', 'GRANT', __('Allows adding users and privileges without reloading the privilege tables.')),
644 $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.'));
645 $privTable[2][] = array('Process', 'PROCESS', __('Allows viewing processes of all users'));
646 $privTable[2][] = array('Reload', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.'));
647 $privTable[2][] = array('Shutdown', 'SHUTDOWN', __('Allows shutting down the server.'));
648 $privTable[2][] = array('Show_db', 'SHOW DATABASES', __('Gives access to the complete list of databases.'));
650 $privTable[2][] = array('Lock_tables', 'LOCK TABLES', __('Allows locking tables for the current thread.'));
651 $privTable[2][] = array('References', 'REFERENCES', __('Has no effect in this MySQL version.'));
653 $privTable[2][] = array('Repl_client', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.'));
654 $privTable[2][] = array('Repl_slave', 'REPLICATION SLAVE', __('Needed for the replication slaves.'));
655 $privTable[2][] = array('Create_user', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.'));
657 echo '<input type="hidden" name="grant_count" value="'
658 . (count($privTable[0]) +
count($privTable[1]) +
count($privTable[2]) - (isset($row['Grant_priv']) ?
1 : 0))
660 . '<fieldset id="fieldset_user_global_rights">' . "\n"
664 ?
__('Global privileges')
666 ?
__('Database-specific privileges')
667 : __('Table-specific privileges'))) . "\n"
668 . ' (<a href="server_privileges.php?'
669 . $GLOBALS['url_query'] . '&checkall=1" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', true); return false;">'
670 . __('Check All') . '</a> /' . "\n"
671 . ' <a href="server_privileges.php?'
672 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', false); return false;">'
673 . __('Uncheck All') . '</a>)' . "\n"
674 . ' </legend>' . "\n"
675 . ' <p><small><i>' . __('Note: MySQL privilege names are expressed in English') . '</i></small></p>' . "\n";
677 // Output the Global privilege tables with checkboxes
678 foreach ($privTable as $i => $table) {
679 echo ' <fieldset>' . "\n"
680 . ' <legend>' . __($privTable_names[$i]) . '</legend>' . "\n";
681 foreach ($table as $priv)
683 echo ' <div class="item">' . "\n"
684 . ' <input type="checkbox"'
685 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0] . '_priv"'
686 . ' value="Y" title="' . $priv[2] . '"'
687 . ((!empty($GLOBALS['checkall']) ||
$row[$priv[0] . '_priv'] == 'Y') ?
' checked="checked"' : '')
689 . ' <label for="checkbox_' . $priv[0] . '_priv"><tt><dfn title="' . $priv[2] . '">'
690 . $priv[1] . '</dfn></tt></label>' . "\n"
693 echo ' </fieldset>' . "\n";
696 // The "Resource limits" box is not displayed for db-specific privs
698 echo ' <fieldset>' . "\n"
699 . ' <legend>' . __('Resource limits') . '</legend>' . "\n"
700 . ' <p><small><i>' . __('Note: Setting these options to 0 (zero) removes the limit.') . '</i></small></p>' . "\n"
701 . ' <div class="item">' . "\n"
702 . ' <label for="text_max_questions"><tt><dfn title="'
703 . __('Limits the number of queries the user may send to the server per hour.') . '">MAX QUERIES PER HOUR</dfn></tt></label>' . "\n"
704 . ' <input type="text" name="max_questions" id="text_max_questions" value="'
705 . $row['max_questions'] . '" size="11" maxlength="11" title="' . __('Limits the number of queries the user may send to the server per hour.') . '" />' . "\n"
707 . ' <div class="item">' . "\n"
708 . ' <label for="text_max_updates"><tt><dfn title="'
709 . __('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"
710 . ' <input type="text" name="max_updates" id="text_max_updates" value="'
711 . $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"
713 . ' <div class="item">' . "\n"
714 . ' <label for="text_max_connections"><tt><dfn title="'
715 . __('Limits the number of new connections the user may open per hour.') . '">MAX CONNECTIONS PER HOUR</dfn></tt></label>' . "\n"
716 . ' <input type="text" name="max_connections" id="text_max_connections" value="'
717 . $row['max_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of new connections the user may open per hour.') . '" />' . "\n"
719 . ' <div class="item">' . "\n"
720 . ' <label for="text_max_user_connections"><tt><dfn title="'
721 . __('Limits the number of simultaneous connections the user may have.') . '">MAX USER_CONNECTIONS</dfn></tt></label>' . "\n"
722 . ' <input type="text" name="max_user_connections" id="text_max_user_connections" value="'
723 . $row['max_user_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of simultaneous connections the user may have.') . '" />' . "\n"
725 . ' </fieldset>' . "\n";
728 echo ' <div class="clearfloat"></div>' . "\n";
730 echo '</fieldset>' . "\n";
732 echo '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">' . "\n"
733 . ' <input type="submit" name="update_privs" value="' . __('Go') . '" />' . "\n"
734 . '</fieldset>' . "\n";
736 } // end of the 'PMA_displayPrivTable()' function
740 * Displays the fields used by the "new user" form as well as the
741 * "change login information / copy user" form.
743 * @param string $mode are we creating a new user or are we just
744 * changing one? (allowed values: 'new', 'change')
745 * @global array $cfg the phpMyAdmin configuration
746 * @global ressource $user_link the database connection
750 function PMA_displayLoginInformationFields($mode = 'new')
752 // Get user/host name lengths
753 $fields_info = PMA_DBI_get_columns('mysql', 'user', true);
754 $username_length = 16;
755 $hostname_length = 41;
756 foreach ($fields_info as $val) {
757 if ($val['Field'] == 'User') {
758 strtok($val['Type'], '()');
761 $username_length = $v;
763 } elseif ($val['Field'] == 'Host') {
764 strtok($val['Type'], '()');
767 $hostname_length = $v;
773 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
774 $GLOBALS['pred_username'] = 'any';
776 echo '<fieldset id="fieldset_add_user_login">' . "\n"
777 . '<legend>' . __('Login Information') . '</legend>' . "\n"
778 . '<div class="item">' . "\n"
779 . '<label for="select_pred_username">' . "\n"
780 . ' ' . __('User name') . ':' . "\n"
782 . '<span class="options">' . "\n"
783 . ' <select name="pred_username" id="select_pred_username" title="' . __('User name') . '"' . "\n"
784 . ' onchange="if (this.value == \'any\') { username.value = \'\'; } else if (this.value == \'userdefined\') { username.focus(); username.select(); }">' . "\n"
785 . ' <option value="any"' . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any') ?
' selected="selected"' : '') . '>' . __('Any user') . '</option>' . "\n"
786 . ' <option value="userdefined"' . ((! isset($GLOBALS['pred_username']) ||
$GLOBALS['pred_username'] == 'userdefined') ?
' selected="selected"' : '') . '>' . __('Use text field') . ':</option>' . "\n"
787 . ' </select>' . "\n"
789 . '<input type="text" name="username" maxlength="'
790 . $username_length . '" title="' . __('User name') . '"'
791 . (empty($GLOBALS['username'])
793 : ' value="' . htmlspecialchars(isset($GLOBALS['new_username'])
794 ?
$GLOBALS['new_username']
795 : $GLOBALS['username']) . '"')
796 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
798 . '<div class="item">' . "\n"
799 . '<label for="select_pred_hostname">' . "\n"
800 . ' ' . __('Host') . ':' . "\n"
802 . '<span class="options">' . "\n"
803 . ' <select name="pred_hostname" id="select_pred_hostname" title="' . __('Host') . '"' . "\n";
804 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
805 if (! empty($_current_user)) {
806 $thishost = str_replace("'", '', substr($_current_user, (strrpos($_current_user, '@') +
1)));
807 if ($thishost == 'localhost' ||
$thishost == '127.0.0.1') {
811 echo ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } else if (this.value == \'localhost\') { hostname.value = \'localhost\'; } '
812 . (empty($thishost) ?
'' : 'else if (this.value == \'thishost\') { hostname.value = \'' . addslashes(htmlspecialchars($thishost)) . '\'; } ')
813 . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } else if (this.value == \'userdefined\') { hostname.focus(); hostname.select(); }">' . "\n";
814 unset($_current_user);
816 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
817 if (! isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
818 switch (strtolower($GLOBALS['hostname'])) {
821 $GLOBALS['pred_hostname'] = 'localhost';
824 $GLOBALS['pred_hostname'] = 'any';
827 $GLOBALS['pred_hostname'] = 'userdefined';
831 echo ' <option value="any"'
832 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
833 ?
' selected="selected"' : '') . '>' . __('Any host')
835 . ' <option value="localhost"'
836 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'localhost')
837 ?
' selected="selected"' : '') . '>' . __('Local')
838 . '</option>' . "\n";
839 if (!empty($thishost)) {
840 echo ' <option value="thishost"'
841 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'thishost')
842 ?
' selected="selected"' : '') . '>' . __('This Host')
843 . '</option>' . "\n";
846 echo ' <option value="hosttable"'
847 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'hosttable')
848 ?
' selected="selected"' : '') . '>' . __('Use Host Table')
850 . ' <option value="userdefined"'
851 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'userdefined')
852 ?
' selected="selected"' : '')
853 . '>' . __('Use text field') . ':</option>' . "\n"
854 . ' </select>' . "\n"
856 . '<input type="text" name="hostname" maxlength="'
857 . $hostname_length . '" value="'
858 . htmlspecialchars(isset($GLOBALS['hostname']) ?
$GLOBALS['hostname'] : '')
859 . '" title="' . __('Host')
860 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
861 . PMA_showHint(__('When Host table is used, this field is ignored and values stored in Host table are used instead.'))
863 . '<div class="item">' . "\n"
864 . '<label for="select_pred_password">' . "\n"
865 . ' ' . __('Password') . ':' . "\n"
867 . '<span class="options">' . "\n"
868 . ' <select name="pred_password" id="select_pred_password" title="'
869 . __('Password') . '"' . "\n"
870 . ' onchange="if (this.value == \'none\') { pma_pw.value = \'\'; pma_pw2.value = \'\'; } else if (this.value == \'userdefined\') { pma_pw.focus(); pma_pw.select(); }">' . "\n"
871 . ($mode == 'change' ?
' <option value="keep" selected="selected">' . __('Do not change the password') . '</option>' . "\n" : '')
872 . ' <option value="none"';
873 if (isset($GLOBALS['username']) && $mode != 'change') {
874 echo ' selected="selected"';
876 echo '>' . __('No Password') . '</option>' . "\n"
877 . ' <option value="userdefined"' . (isset($GLOBALS['username']) ?
'' : ' selected="selected"') . '>' . __('Use text field') . ':</option>' . "\n"
878 . ' </select>' . "\n"
880 . '<input type="password" id="text_pma_pw" name="pma_pw" title="' . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
882 . '<div class="item" id="div_element_before_generate_password">' . "\n"
883 . '<label for="text_pma_pw2">' . "\n"
884 . ' ' . __('Re-type') . ':' . "\n"
886 . '<span class="options"> </span>' . "\n"
887 . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="' . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
889 // Generate password added here via jQuery
890 . '</fieldset>' . "\n";
891 } // end of the 'PMA_displayUserAndHostFields()' function
894 * Changes / copies a user, part I
896 if (isset($_REQUEST['change_copy'])) {
897 $user_host_condition =
899 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
901 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
902 $row = PMA_DBI_fetch_single_row('SELECT * FROM `mysql`.`user` ' . $user_host_condition);
904 PMA_Message
::notice(__('No user found.'))->display();
905 unset($_REQUEST['change_copy']);
907 extract($row, EXTR_OVERWRITE
);
908 // Recent MySQL versions have the field "Password" in mysql.user,
909 // so the previous extract creates $Password but this script
911 if (! isset($password) && isset($Password)) {
912 $password = $Password;
921 * (Changes / copies a user, part II)
923 if (isset($_REQUEST['adduser_submit']) ||
isset($_REQUEST['change_copy'])) {
925 if ($pred_username == 'any') {
928 switch ($pred_hostname) {
933 $hostname = 'localhost';
939 $_user_name = PMA_DBI_fetch_value('SELECT USER()');
940 $hostname = substr($_user_name, (strrpos($_user_name, '@') +
1));
944 $sql = "SELECT '1' FROM `mysql`.`user`"
945 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
946 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
947 if (PMA_DBI_fetch_value($sql) == 1) {
948 $message = PMA_Message
::error(__('The user %s already exists!'));
949 $message->addParam('[i]\'' . $username . '\'@\'' . $hostname . '\'[/i]');
950 $_REQUEST['adduser'] = true;
951 $_add_user_error = true;
954 $create_user_real = 'CREATE USER \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
957 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
958 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
959 if ($pred_password != 'none' && $pred_password != 'keep') {
960 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
961 $real_sql_query .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
962 if (isset($create_user_real)) {
963 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
964 $create_user_real .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
967 if ($pred_password == 'keep' && !empty($password)) {
968 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
969 if (isset($create_user_real)) {
970 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
973 $sql_query = $real_sql_query;
974 if (isset($create_user_real)) {
975 $create_user_show = $create_user_real;
979 * @todo similar code appears twice in this script
981 if ((isset($Grant_priv) && $Grant_priv == 'Y')
982 ||
(isset($max_questions) ||
isset($max_connections)
983 ||
isset($max_updates) ||
isset($max_user_connections))) {
984 $real_sql_query .= ' WITH';
985 $sql_query .= ' WITH';
986 if (isset($Grant_priv) && $Grant_priv == 'Y') {
987 $real_sql_query .= ' GRANT OPTION';
988 $sql_query .= ' GRANT OPTION';
990 if (isset($max_questions)) {
991 // avoid negative values
992 $max_questions = max(0, (int)$max_questions);
993 $real_sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
994 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
996 if (isset($max_connections)) {
997 $max_connections = max(0, (int)$max_connections);
998 $real_sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
999 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1001 if (isset($max_updates)) {
1002 $max_updates = max(0, (int)$max_updates);
1003 $real_sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1004 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1006 if (isset($max_user_connections)) {
1007 $max_user_connections = max(0, (int)$max_user_connections);
1008 $real_sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1009 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1012 if (isset($create_user_real)) {
1013 $create_user_real .= ';';
1014 $create_user_show .= ';';
1016 $real_sql_query .= ';';
1018 if (empty($_REQUEST['change_copy'])) {
1021 if (isset($create_user_real)) {
1022 if (! PMA_DBI_try_query($create_user_real)) {
1025 $sql_query = $create_user_show . $sql_query;
1028 if ($_error ||
! PMA_DBI_try_query($real_sql_query)) {
1029 $_REQUEST['createdb'] = false;
1030 $message = PMA_Message
::rawError(PMA_DBI_getError());
1032 $message = PMA_Message
::success(__('You have added a new user.'));
1035 switch (PMA_ifSetOr($_REQUEST['createdb'], '0')) {
1037 // Create database with same name and grant all privileges
1038 $q = 'CREATE DATABASE IF NOT EXISTS '
1039 . PMA_backquote(PMA_sqlAddSlashes($username)) . ';';
1041 if (! PMA_DBI_try_query($q)) {
1042 $message = PMA_Message
::rawError(PMA_DBI_getError());
1048 * If we are not in an Ajax request, we can't reload navigation now
1050 if ($GLOBALS['is_ajax_request'] != true) {
1051 // this is needed in case tracking is on:
1052 $GLOBALS['db'] = $username;
1053 $GLOBALS['reload'] = true;
1054 PMA_reloadNavigation();
1057 $q = 'GRANT ALL PRIVILEGES ON '
1058 . PMA_backquote(PMA_sqlAddSlashes($username)) . '.* TO \''
1059 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1061 if (! PMA_DBI_try_query($q)) {
1062 $message = PMA_Message
::rawError(PMA_DBI_getError());
1066 // Grant all privileges on wildcard name (username\_%)
1067 $q = 'GRANT ALL PRIVILEGES ON '
1068 . PMA_backquote(PMA_sqlAddSlashes($username) . '\_%') . '.* TO \''
1069 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1071 if (! PMA_DBI_try_query($q)) {
1072 $message = PMA_Message
::rawError(PMA_DBI_getError());
1076 // Grant all privileges on the specified database to the new user
1077 $q = 'GRANT ALL PRIVILEGES ON '
1078 . PMA_backquote(PMA_sqlAddSlashes($dbname)) . '.* TO \''
1079 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1081 if (! PMA_DBI_try_query($q)) {
1082 $message = PMA_Message
::rawError(PMA_DBI_getError());
1090 if (isset($create_user_real)) {
1091 $queries[] = $create_user_real;
1093 $queries[] = $real_sql_query;
1094 // we put the query containing the hidden password in
1095 // $queries_for_display, at the same position occupied
1096 // by the real query in $queries
1097 $tmp_count = count($queries);
1098 if (isset($create_user_real)) {
1099 $queries_for_display[$tmp_count - 2] = $create_user_show;
1101 $queries_for_display[$tmp_count - 1] = $sql_query;
1103 unset($res, $real_sql_query);
1109 * Changes / copies a user, part III
1111 if (isset($_REQUEST['change_copy'])) {
1112 $user_host_condition =
1114 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1116 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
1117 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1118 while ($row = PMA_DBI_fetch_assoc($res)) {
1120 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1121 .' ON ' . PMA_backquote($row['Db']) . '.*'
1122 .' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1123 . ($row['Grant_priv'] == 'Y' ?
' WITH GRANT OPTION;' : ';');
1125 PMA_DBI_free_result($res);
1126 $res = PMA_DBI_query(
1127 'SELECT `Db`, `Table_name`, `Table_priv`'
1128 .' FROM `mysql`.`tables_priv`' . $user_host_condition,
1129 $GLOBALS['userlink'], PMA_DBI_QUERY_STORE
);
1130 while ($row = PMA_DBI_fetch_assoc($res)) {
1132 $res2 = PMA_DBI_QUERY(
1133 'SELECT `Column_name`, `Column_priv`'
1134 .' FROM `mysql`.`columns_priv`'
1136 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1138 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\''
1140 .' = \'' . PMA_sqlAddSlashes($row['Db']) . "'"
1141 .' AND `Table_name`'
1142 .' = \'' . PMA_sqlAddSlashes($row['Table_name']) . "'"
1144 null, PMA_DBI_QUERY_STORE
);
1146 $tmp_privs1 = PMA_extractPrivInfo($row);
1147 $tmp_privs2 = array(
1148 'Select' => array(),
1149 'Insert' => array(),
1150 'Update' => array(),
1151 'References' => array()
1154 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1155 $tmp_array = explode(',', $row2['Column_priv']);
1156 if (in_array('Select', $tmp_array)) {
1157 $tmp_privs2['Select'][] = $row2['Column_name'];
1159 if (in_array('Insert', $tmp_array)) {
1160 $tmp_privs2['Insert'][] = $row2['Column_name'];
1162 if (in_array('Update', $tmp_array)) {
1163 $tmp_privs2['Update'][] = $row2['Column_name'];
1165 if (in_array('References', $tmp_array)) {
1166 $tmp_privs2['References'][] = $row2['Column_name'];
1170 if (count($tmp_privs2['Select']) > 0 && !in_array('SELECT', $tmp_privs1)) {
1171 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1173 if (count($tmp_privs2['Insert']) > 0 && !in_array('INSERT', $tmp_privs1)) {
1174 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1176 if (count($tmp_privs2['Update']) > 0 && !in_array('UPDATE', $tmp_privs1)) {
1177 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1179 if (count($tmp_privs2['References']) > 0 && !in_array('REFERENCES', $tmp_privs1)) {
1180 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1184 'GRANT ' . join(', ', $tmp_privs1)
1185 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1186 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1187 . (in_array('Grant', explode(',', $row['Table_priv'])) ?
' WITH GRANT OPTION;' : ';');
1193 * Updates privileges
1195 if (!empty($update_privs)) {
1196 $db_and_table = PMA_wildcardEscapeForGrant($dbname, (isset($tablename) ?
$tablename : ''));
1199 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1200 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1201 if (! isset($Grant_priv) ||
$Grant_priv != 'Y') {
1203 'REVOKE GRANT OPTION ON ' . $db_and_table
1204 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1209 // Should not do a GRANT USAGE for a table-specific privilege, it
1210 // causes problems later (cannot revoke it)
1211 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1213 'GRANT ' . join(', ', PMA_extractPrivInfo())
1214 . ' ON ' . $db_and_table
1215 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
1218 * @todo similar code appears twice in this script
1220 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1221 ||
(! isset($dbname)
1222 && (isset($max_questions) ||
isset($max_connections)
1223 ||
isset($max_updates) ||
isset($max_user_connections))))
1225 $sql_query2 .= 'WITH';
1226 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1227 $sql_query2 .= ' GRANT OPTION';
1229 if (isset($max_questions)) {
1230 $max_questions = max(0, (int)$max_questions);
1231 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1233 if (isset($max_connections)) {
1234 $max_connections = max(0, (int)$max_connections);
1235 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1237 if (isset($max_updates)) {
1238 $max_updates = max(0, (int)$max_updates);
1239 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1241 if (isset($max_user_connections)) {
1242 $max_user_connections = max(0, (int)$max_user_connections);
1243 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1248 if (! PMA_DBI_try_query($sql_query0)) {
1249 // This might fail when the executing user does not have ALL PRIVILEGES himself.
1250 // See https://sourceforge.net/tracker/index.php?func=detail&aid=3285929&group_id=23067&atid=377408
1253 if (isset($sql_query1) && !PMA_DBI_try_query($sql_query1)) {
1254 // this one may fail, too...
1257 if (isset($sql_query2)) {
1258 PMA_DBI_query($sql_query2);
1262 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1263 $message = PMA_Message
::success(__('You have updated the privileges for %s.'));
1264 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1269 * Revokes Privileges
1271 if (isset($_REQUEST['revokeall'])) {
1272 $db_and_table = PMA_wildcardEscapeForGrant($dbname, isset($tablename) ?
$tablename : '');
1275 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1276 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1278 'REVOKE GRANT OPTION ON ' . $db_and_table
1279 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1281 PMA_DBI_query($sql_query0);
1282 if (! PMA_DBI_try_query($sql_query1)) {
1283 // this one may fail, too...
1286 $sql_query = $sql_query0 . ' ' . $sql_query1;
1287 $message = PMA_Message
::success(__('You have revoked the privileges for %s'));
1288 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1289 if (! isset($tablename)) {
1298 * Updates the password
1300 if (isset($_REQUEST['change_pw'])) {
1301 // similar logic in user_password.php
1304 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1305 if ($pma_pw != $pma_pw2) {
1306 $message = PMA_Message
::error(__('The passwords aren\'t the same!'));
1307 } elseif (empty($pma_pw) ||
empty($pma_pw2)) {
1308 $message = PMA_Message
::error(__('The password is empty!'));
1312 // here $nopass could be == 1
1313 if (empty($message)) {
1315 $hashing_function = (!empty($pw_hash) && $pw_hash == 'old' ?
'OLD_' : '')
1318 // in $sql_query which will be displayed, hide the password
1319 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ?
'\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1320 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ?
'\'\'' : $hashing_function . '(\'' . PMA_sqlAddSlashes($pma_pw) . '\')');
1321 PMA_DBI_try_query($local_query)
1322 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, false, $err_url);
1323 $message = PMA_Message
::success(__('The password for %s was changed successfully.'));
1324 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1331 * (Changes / copies a user, part IV)
1334 if (isset($_REQUEST['delete']) ||
(isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1335 if (isset($_REQUEST['change_copy'])) {
1336 $selected_usr = array($old_username . '&#27;' . $old_hostname);
1338 $selected_usr = $_REQUEST['selected_usr'];
1341 foreach ($selected_usr as $each_user) {
1342 list($this_user, $this_host) = explode('&#27;', $each_user);
1343 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1344 $queries[] = 'DROP USER \'' . PMA_sqlAddSlashes($this_user) . '\'@\'' . PMA_sqlAddSlashes($this_host) . '\';';
1346 if (isset($_REQUEST['drop_users_db'])) {
1347 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1348 $GLOBALS['reload'] = true;
1350 if ($GLOBALS['is_ajax_request'] != true) {
1351 PMA_reloadNavigation();
1355 if (empty($_REQUEST['change_copy'])) {
1356 if (empty($queries)) {
1357 $message = PMA_Message
::error(__('No users selected for deleting!'));
1359 if ($_REQUEST['mode'] == 3) {
1360 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1361 $queries[] = 'FLUSH PRIVILEGES;';
1363 $drop_user_error = '';
1364 foreach ($queries as $sql_query) {
1365 if ($sql_query{0} != '#') {
1366 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1367 $drop_user_error .= PMA_DBI_getError() . "\n";
1371 // tracking sets this, causing the deleted db to be shown in navi
1372 unset($GLOBALS['db']);
1374 $sql_query = join("\n", $queries);
1375 if (! empty($drop_user_error)) {
1376 $message = PMA_Message
::rawError($drop_user_error);
1378 $message = PMA_Message
::success(__('The selected users have been deleted successfully.'));
1387 * Changes / copies a user, part V
1389 if (isset($_REQUEST['change_copy'])) {
1391 foreach ($queries as $sql_query) {
1392 if ($sql_query{0} != '#') {
1393 PMA_DBI_query($sql_query);
1395 // when there is a query containing a hidden password, take it
1396 // instead of the real query sent
1397 if (isset($queries_for_display[$tmp_count])) {
1398 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1402 $message = PMA_Message
::success();
1403 $sql_query = join("\n", $queries);
1408 * Reloads the privilege tables into memory
1410 if (isset($_REQUEST['flush_privileges'])) {
1411 $sql_query = 'FLUSH PRIVILEGES;';
1412 PMA_DBI_query($sql_query);
1413 $message = PMA_Message
::success(__('The privileges were reloaded successfully.'));
1417 * defines some standard links
1419 $link_edit = '<a class="edit_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . $GLOBALS['url_query']
1420 . '&username=%s'
1421 . '&hostname=%s'
1423 . '&tablename=%s">'
1424 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1427 $link_revoke = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1428 . '&username=%s'
1429 . '&hostname=%s'
1431 . '&tablename=%s'
1432 . '&revokeall=1">'
1433 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1436 $link_export = '<a class="export_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . $GLOBALS['url_query']
1437 . '&username=%s'
1438 . '&hostname=%s'
1441 . PMA_getIcon('b_tblexport.png', __('Export'))
1445 * If we are in an Ajax request for Create User/Edit User/Revoke User/Flush Privileges,
1446 * show $message and exit.
1448 if ($GLOBALS['is_ajax_request'] && ! isset($_REQUEST['export']) && (! isset($_REQUEST['adduser']) ||
$_add_user_error) && ! isset($_REQUEST['initial']) && ! isset($_REQUEST['showall']) && ! isset($_REQUEST['edit_user_dialog']) && ! isset($_REQUEST['db_specific'])) {
1450 if (isset($sql_query)) {
1451 $extra_data['sql_query'] = PMA_showMessage(NULL, $sql_query);
1454 if (isset($_REQUEST['adduser_submit']) ||
isset($_REQUEST['change_copy'])) {
1456 * generate html on the fly for the new user that was just created.
1458 $new_user_string = '<tr>'."\n"
1459 .'<td> <input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_" value="' . htmlspecialchars($username) . '&#27;' . htmlspecialchars($hostname) . '" /> </td>'."\n"
1460 .'<td><label for="checkbox_sel_users_">' . (empty($username) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($username) ) . '</label></td>' . "\n"
1461 .'<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
1462 $new_user_string .= '<td>';
1464 if (!empty($password) ||
isset($pma_pw)) {
1465 $new_user_string .= __('Yes');
1468 $new_user_string .= '<span style="color: #FF0000">' . __('No') . '</span>';
1471 $new_user_string .= '</td>'."\n";
1472 $new_user_string .= '<td><tt>' . join(', ', PMA_extractPrivInfo('', true)) . '</tt></td>'; //Fill in privileges here
1473 $new_user_string .= '<td>';
1475 if ((isset($Grant_priv) && $Grant_priv == 'Y')) {
1476 $new_user_string .= __('Yes');
1479 $new_user_string .= __('No');
1482 $new_user_string .='</td>';
1484 $new_user_string .= '<td>'.sprintf($link_edit, urlencode($username), urlencode($hostname), '', '' ).'</td>'."\n";
1485 $new_user_string .= '<td>'.sprintf($link_export, urlencode($username), urlencode($hostname), (isset($initial) ?
$initial : '')).'</td>'."\n";
1487 $new_user_string .= '</tr>';
1489 $extra_data['new_user_string'] = $new_user_string;
1492 * Generate the string for this alphabet's initial, to update the user
1495 $new_user_initial = strtoupper(substr($username, 0, 1));
1496 $new_user_initial_string = '<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . $new_user_initial
1497 .'">' . $new_user_initial . '</a>';
1498 $extra_data['new_user_initial'] = $new_user_initial;
1499 $extra_data['new_user_initial_string'] = $new_user_initial_string;
1502 if (isset($update_privs)) {
1503 $extra_data['db_specific_privs'] = false;
1504 if (isset($dbname_is_wildcard)) {
1505 $extra_data['db_specific_privs'] = !$dbname_is_wildcard;
1507 $new_privileges = join(', ', PMA_extractPrivInfo('', true));
1509 $extra_data['new_privileges'] = $new_privileges;
1512 if ($message instanceof PMA_Message
) {
1513 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
1518 * Displays the links
1520 if (isset($viewing_mode) && $viewing_mode == 'db') {
1522 $url_query .= '&goto=db_operations.php';
1524 // Gets the database structure
1525 $sub_part = '_structure';
1526 require './libraries/db_info.inc.php';
1529 require './libraries/server_links.inc.php';
1537 // export user definition
1538 if (isset($_REQUEST['export'])) {
1539 echo '<h2>' . __('User') . ' \'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'</h2>';
1540 echo '<textarea cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1541 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddSlashes($username) . "'@'" . PMA_sqlAddSlashes($hostname) . "'");
1542 foreach ($grants as $one_grant) {
1543 echo $one_grant . ";\n\n";
1546 unset($username, $hostname, $grants, $one_grant);
1547 if ($GLOBALS['is_ajax_request']) {
1552 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) ||
! strlen($checkprivs))) {
1553 if (! isset($username)) {
1554 // No username is given --> display the overview
1556 . PMA_getIcon('b_usrlist.png')
1557 . __('User overview') . "\n"
1562 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1563 ' FROM `mysql`.`user`';
1565 $sql_query .= (isset($initial) ?
PMA_rangeOfUsers($initial) : '');
1567 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1568 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE
);
1571 // the query failed! This may have two reasons:
1572 // - the user does not have enough privileges
1573 // - the privilege tables use a structure of an earlier version.
1574 // so let's try a more simple query
1576 $sql_query = 'SELECT * FROM `mysql`.`user`';
1577 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE
);
1580 PMA_Message
::error(__('No Privileges'))->display();
1581 PMA_DBI_free_result($res);
1584 // This message is hardcoded because I will replace it by
1585 // a automatic repair feature soon.
1586 $raw = 'Your privilege table structure seems to be older than'
1587 . ' this MySQL version!<br />'
1588 . 'Please run the <tt>mysql_upgrade</tt> command'
1589 . '(<tt>mysql_fix_privilege_tables</tt> on older systems)'
1590 . ' that should be included in your MySQL server distribution'
1591 . ' to solve this problem!';
1592 PMA_Message
::rawError($raw)->display();
1596 // we also want users not in table `user` but in other table
1597 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1599 $tables_to_search_for_users = array(
1600 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1603 $db_rights_sqls = array();
1604 foreach ($tables_to_search_for_users as $table_search_in) {
1605 if (in_array($table_search_in, $tables)) {
1606 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ?
PMA_rangeOfUsers($initial) : '');
1610 $user_defaults = array(
1614 'Grant_priv' => 'N',
1615 'privs' => array('USAGE'),
1618 // for all initials, even non A-Z
1619 $array_initials = array();
1621 $db_rights = array();
1623 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1624 .' ORDER BY `User` ASC, `Host` ASC';
1626 $db_rights_result = PMA_DBI_query($db_rights_sql);
1628 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1629 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1630 $db_rights[$db_rights_row['User']][$db_rights_row['Host']] =
1633 PMA_DBI_free_result($db_rights_result);
1634 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1638 * Displays the initials
1639 * In an Ajax request, we don't need to show this. Also not necassary if there is less than 20 privileges
1642 if ($GLOBALS['is_ajax_request'] != true && PMA_DBI_num_rows($res) > 20 ) {
1644 // initialize to false the letters A-Z
1645 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++
) {
1646 if (! isset($array_initials[chr($letter_counter +
64)])) {
1647 $array_initials[chr($letter_counter +
64)] = false;
1651 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE
);
1652 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1653 $array_initials[$tmp_initial] = true;
1656 // Display the initials, which can be any characters, not
1657 // just letters. For letters A-Z, we add the non-used letters
1660 uksort($array_initials, "strnatcasecmp");
1662 echo '<table id="initials_table" class="' . $conditional_class . '" <cellspacing="5"><tr>';
1663 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1664 if ($initial_was_found) {
1665 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1667 echo '<td>' . $tmp_initial . '</td>';
1670 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&showall=1" class="nowrap">[' . __('Show all') . ']</a></td>' . "\n";
1671 echo '</tr></table>';
1675 * Display the user overview
1676 * (if less than 50 users, display them immediately)
1679 if (isset($initial) ||
isset($showall) ||
PMA_DBI_num_rows($res) < 50) {
1681 while ($row = PMA_DBI_fetch_assoc($res)) {
1682 $row['privs'] = PMA_extractPrivInfo($row, true);
1683 $db_rights[$row['User']][$row['Host']] = $row;
1685 @PMA_DBI_free_result
($res);
1688 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1689 . PMA_generate_common_hidden_inputs('', '')
1690 . ' <table id="tableuserrights" class="data">' . "\n"
1692 . ' <tr><th></th>' . "\n"
1693 . ' <th>' . __('User') . '</th>' . "\n"
1694 . ' <th>' . __('Host') . '</th>' . "\n"
1695 . ' <th>' . __('Password') . '</th>' . "\n"
1696 . ' <th>' . __('Global privileges') . ' '
1697 . PMA_showHint(__('Note: MySQL privilege names are expressed in English')) . '</th>' . "\n"
1698 . ' <th>' . __('Grant') . '</th>' . "\n"
1699 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1700 echo ' </tr>' . "\n";
1701 echo ' </thead>' . "\n";
1702 echo ' <tbody>' . "\n";
1704 $index_checkbox = -1;
1705 foreach ($db_rights as $user) {
1708 foreach ($user as $host) {
1710 echo ' <tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
1711 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1712 . $index_checkbox . '" value="'
1713 . htmlspecialchars($host['User'] . '&#27;' . $host['Host'])
1715 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
1717 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1718 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1720 switch ($host['Password']) {
1725 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1727 // this happens if this is a definition not coming from mysql.user
1729 echo '--'; // in future version, replace by "not present"
1733 . ' <td><tt>' . "\n"
1734 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1735 . ' </tt></td>' . "\n"
1736 . ' <td>' . ($host['Grant_priv'] == 'Y' ?
__('Yes') : __('No')) . '</td>' . "\n"
1737 . ' <td align="center">';
1738 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1740 echo '<td align="center">';
1741 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ?
$initial : ''));
1744 $odd_row = ! $odd_row;
1748 unset($user, $host, $odd_row);
1749 echo ' </tbody></table>' . "\n"
1750 .'<img class="selectallarrow"'
1751 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1752 .' width="38" height="22"'
1753 .' alt="' . __('With selected:') . '" />' . "\n"
1754 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&checkall=1"'
1755 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1756 . __('Check All') . '</a>' . "\n"
1758 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1759 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1760 . __('Uncheck All') . '</a>' . "\n";
1762 // add/delete user fieldset
1763 echo ' <fieldset id="fieldset_add_user">' . "\n"
1764 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1" class="' . $conditional_class . '">' . "\n"
1765 . PMA_getIcon('b_usradd.png')
1766 . ' ' . __('Add user') . '</a>' . "\n"
1767 . ' </fieldset>' . "\n"
1768 . ' <fieldset id="fieldset_delete_user">'
1769 . ' <legend>' . "\n"
1770 . PMA_getIcon('b_usrdrop.png')
1771 . ' ' . __('Remove selected users') . '' . "\n"
1772 . ' </legend>' . "\n"
1773 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1774 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1775 . ' <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"
1776 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1777 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1778 . ' </label>' . "\n"
1779 . ' </fieldset>' . "\n"
1780 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1781 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" class="' . $conditional_class . '"/>' . "\n"
1782 . ' </fieldset>' . "\n"
1787 echo ' <fieldset id="fieldset_add_user">' . "\n"
1788 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1" class="' . $conditional_class . '">' . "\n"
1789 . PMA_getIcon('b_usradd.png')
1790 . ' ' . __('Add user') . '</a>' . "\n"
1791 . ' </fieldset>' . "\n";
1792 } // end if (display overview)
1794 if ($GLOBALS['is_ajax_request']) {
1798 $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
);
1799 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&flush_privileges=1" id="reload_privileges_anchor" class="' . $conditional_class . '">', false);
1800 $flushnote->addParam('</a>', false);
1801 $flushnote->display();
1807 // A user was selected -> display the user's properties
1809 // In an Ajax request, prevent cached values from showing
1810 if ($GLOBALS['is_ajax_request'] == true) {
1811 header('Cache-Control: no-cache');
1815 . PMA_getIcon('b_usredit.png')
1816 . __('Edit Privileges') . ': '
1819 if (isset($dbname)) {
1820 echo ' <i><a href="server_privileges.php?'
1821 . $GLOBALS['url_query'] . '&username=' . htmlspecialchars(urlencode($username))
1822 . '&hostname=' . htmlspecialchars(urlencode($hostname)) . '&dbname=&tablename=">\''
1823 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1824 . '\'</a></i>' . "\n";
1825 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
1827 echo ' - ' . ($dbname_is_wildcard ?
__('Databases') : __('Database') );
1828 if (isset($tablename)) {
1829 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
1830 . '&username=' . htmlspecialchars(urlencode($username)) . '&hostname=' . htmlspecialchars(urlencode($hostname))
1831 . '&dbname=' . htmlspecialchars($url_dbname) . '&tablename=">' . htmlspecialchars($dbname) . '</a></i>';
1832 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
1834 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
1838 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1842 echo '</h2>' . "\n";
1845 $sql = "SELECT '1' FROM `mysql`.`user`"
1846 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
1847 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
1848 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
1850 if ($user_does_not_exists) {
1851 PMA_Message
::error(__('The selected user was not found in the privilege table.'))->display();
1852 PMA_displayLoginInformationFields();
1853 //require './libraries/footer.inc.php';
1856 echo '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n";
1858 'username' => $username,
1859 'hostname' => $hostname,
1861 if (isset($dbname)) {
1862 $_params['dbname'] = $dbname;
1863 if (isset($tablename)) {
1864 $_params['tablename'] = $tablename;
1867 echo PMA_generate_common_hidden_inputs($_params);
1869 PMA_displayPrivTable(PMA_ifSetOr($dbname, '*', 'length'),
1870 PMA_ifSetOr($tablename, '*', 'length'));
1872 echo '</form>' . "\n";
1874 if (! isset($tablename) && empty($dbname_is_wildcard)) {
1876 // no table name was given, display all table specific rights
1877 // but only if $dbname contains no wildcards
1880 echo '<form action="server_privileges.php" method="post">' . "\n"
1881 . PMA_generate_common_hidden_inputs('', '')
1882 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
1883 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1884 . '<fieldset>' . "\n"
1885 . '<legend>' . (! isset($dbname) ?
__('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
1886 . '<table class="data">' . "\n"
1888 . '<tr><th>' . (! isset($dbname) ?
__('Database') : __('Table')) . '</th>' . "\n"
1889 . ' <th>' . __('Privileges') . '</th>' . "\n"
1890 . ' <th>' . __('Grant') . '</th>' . "\n"
1891 . ' <th>' . (! isset($dbname) ?
__('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
1892 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
1897 $user_host_condition =
1899 . ' = \'' . PMA_sqlAddSlashes($username) . "'"
1901 . ' = \'' . PMA_sqlAddSlashes($hostname) . "'";
1906 // we also want privielgs for this user not in table `db` but in other table
1907 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1908 if (! isset($dbname)) {
1910 // no db name given, so we want all privs for the given user
1912 $tables_to_search_for_users = array(
1913 'tables_priv', 'columns_priv',
1916 $db_rights_sqls = array();
1917 foreach ($tables_to_search_for_users as $table_search_in) {
1918 if (in_array($table_search_in, $tables)) {
1919 $db_rights_sqls[] = '
1920 SELECT DISTINCT `Db`
1921 FROM `mysql`.' . PMA_backquote($table_search_in)
1922 . $user_host_condition;
1926 $user_defaults = array(
1928 'Grant_priv' => 'N',
1929 'privs' => array('USAGE'),
1930 'Table_privs' => true,
1934 $db_rights = array();
1936 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1937 .' ORDER BY `Db` ASC';
1939 $db_rights_result = PMA_DBI_query($db_rights_sql);
1941 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1942 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1943 // only Db names in the table `mysql`.`db` uses wildcards
1944 // as we are in the db specific rights display we want
1945 // all db names escaped, also from other sources
1946 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
1947 $db_rights_row['Db']);
1948 $db_rights[$db_rights_row['Db']] = $db_rights_row;
1951 PMA_DBI_free_result($db_rights_result);
1952 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1954 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
1955 $res = PMA_DBI_query($sql_query);
1958 while ($row = PMA_DBI_fetch_assoc($res)) {
1959 if (isset($db_rights[$row['Db']])) {
1960 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
1962 $db_rights[$row['Db']] = $row;
1964 // there are db specific rights for this user
1965 // so we can drop this db rights
1966 $db_rights[$row['Db']]['can_delete'] = true;
1968 PMA_DBI_free_result($res);
1973 // db name was given,
1974 // so we want all user specific rights for this db
1976 $user_host_condition .=
1978 .' LIKE \'' . PMA_sqlAddSlashes($dbname, true) . "'";
1980 $tables_to_search_for_users = array(
1984 $db_rights_sqls = array();
1985 foreach ($tables_to_search_for_users as $table_search_in) {
1986 if (in_array($table_search_in, $tables)) {
1987 $db_rights_sqls[] = '
1988 SELECT DISTINCT `Table_name`
1989 FROM `mysql`.' . PMA_backquote($table_search_in)
1990 . $user_host_condition;
1994 $user_defaults = array(
1996 'Grant_priv' => 'N',
1997 'privs' => array('USAGE'),
1998 'Column_priv' => true,
2002 $db_rights = array();
2004 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
2005 .' ORDER BY `Table_name` ASC';
2007 $db_rights_result = PMA_DBI_query($db_rights_sql);
2009 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
2010 $db_rights_row = array_merge($user_defaults, $db_rights_row);
2011 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
2013 PMA_DBI_free_result($db_rights_result);
2014 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
2017 'SELECT `Table_name`,'
2019 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
2020 .' AS \'Column_priv\''
2021 .' FROM `mysql`.`tables_priv`'
2022 . $user_host_condition
2023 .' ORDER BY `Table_name` ASC;';
2024 $res = PMA_DBI_query($sql_query);
2027 while ($row = PMA_DBI_fetch_assoc($res)) {
2028 if (isset($db_rights[$row['Table_name']])) {
2029 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
2031 $db_rights[$row['Table_name']] = $row;
2034 PMA_DBI_free_result($res);
2040 if (count($db_rights) < 1) {
2041 echo '<tr class="odd">' . "\n"
2042 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
2046 $found_rows = array();
2047 //while ($row = PMA_DBI_fetch_assoc($res)) {
2048 foreach ($db_rights as $row) {
2049 $found_rows[] = (! isset($dbname)) ?
$row['Db'] : $row['Table_name'];
2051 echo '<tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
2052 . ' <td>' . htmlspecialchars((! isset($dbname)) ?
$row['Db'] : $row['Table_name']) . '</td>' . "\n"
2053 . ' <td><tt>' . "\n"
2054 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, true)) . "\n"
2055 . ' </tt></td>' . "\n"
2056 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') ||
(isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ?
__('Yes') : __('No')) . '</td>' . "\n"
2058 if (! empty($row['Table_privs']) ||
! empty ($row['Column_priv'])) {
2065 printf($link_edit, htmlspecialchars(urlencode($username)),
2066 urlencode(htmlspecialchars($hostname)),
2067 urlencode((! isset($dbname)) ?
$row['Db'] : htmlspecialchars($dbname)),
2068 urlencode((! isset($dbname)) ?
'' : $row['Table_name']));
2071 if (! empty($row['can_delete']) ||
isset($row['Table_name']) && strlen($row['Table_name'])) {
2072 printf($link_revoke, htmlspecialchars(urlencode($username)),
2073 urlencode(htmlspecialchars($hostname)),
2074 urlencode((! isset($dbname)) ?
$row['Db'] : htmlspecialchars($dbname)),
2075 urlencode((! isset($dbname)) ?
'' : $row['Table_name']));
2079 $odd_row = ! $odd_row;
2083 echo '</tbody>' . "\n"
2084 . '</table>' . "\n";
2086 if (! isset($dbname)) {
2088 // no database name was given, display select db
2090 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
2092 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
2093 if (!empty($pred_db_array)) {
2094 echo ' <select name="pred_dbname" class="autosubmit">' . "\n"
2095 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2096 foreach ($pred_db_array as $current_db) {
2097 $current_db = PMA_escape_mysql_wildcards($current_db);
2098 // cannot use array_diff() once, outside of the loop,
2099 // because the list of databases has special characters
2100 // already escaped in $found_rows,
2101 // contrary to the output of SHOW DATABASES
2102 if (empty($found_rows) ||
! in_array($current_db, $found_rows)) {
2103 echo ' <option value="' . htmlspecialchars($current_db) . '">'
2104 . htmlspecialchars($current_db) . '</option>' . "\n";
2107 echo ' </select>' . "\n";
2109 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
2110 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
2112 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
2113 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
2114 if ($res = @PMA_DBI_try_query
('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE
)) {
2115 $pred_tbl_array = array();
2116 while ($row = PMA_DBI_fetch_row($res)) {
2117 if (! isset($found_rows) ||
!in_array($row[0], $found_rows)) {
2118 $pred_tbl_array[] = $row[0];
2121 PMA_DBI_free_result($res);
2123 if (!empty($pred_tbl_array)) {
2124 echo ' <select name="pred_tablename" class="autosubmit">' . "\n"
2125 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2126 foreach ($pred_tbl_array as $current_table) {
2127 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
2129 echo ' </select>' . "\n";
2134 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
2136 echo '</fieldset>' . "\n";
2137 echo '<fieldset class="tblFooters">' . "\n"
2138 . ' <input type="submit" value="' . __('Go') . '" />'
2139 . '</fieldset>' . "\n"
2144 // Provide a line with links to the relevant database and table
2145 if (isset($dbname) && empty($dbname_is_wildcard)) {
2146 echo '[ ' . __('Database')
2147 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
2148 . $GLOBALS['url_query'] . '&db=' . $url_dbname . '&reload=1">'
2149 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
2151 if (isset($tablename)) {
2152 echo ' [ ' . __('Table') . ' <a href="'
2153 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
2154 . '&db=' . $url_dbname . '&table=' . htmlspecialchars(urlencode($tablename))
2155 . '&reload=1">' . htmlspecialchars($tablename) . ': '
2156 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
2162 if (! isset($dbname) && ! $user_does_not_exists) {
2163 require_once './libraries/display_change_password.lib.php';
2165 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
2166 . PMA_generate_common_hidden_inputs('', '')
2167 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
2168 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
2169 . '<fieldset id="fieldset_change_copy_user">' . "\n"
2170 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
2171 PMA_displayLoginInformationFields('change');
2172 echo ' <fieldset>' . "\n"
2173 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2175 '4' => __('... keep the old one.'),
2176 '1' => __('... delete the old one from the user tables.'),
2177 '2' => __('... revoke all active privileges from the old one and delete it afterwards.'),
2178 '3' => __('... delete the old one from the user tables and reload the privileges afterwards.'));
2179 PMA_display_html_radio('mode', $choices, '4', true);
2182 echo ' </fieldset>' . "\n"
2183 . '</fieldset>' . "\n"
2184 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2185 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2186 . '</fieldset>' . "\n"
2190 } elseif (isset($_REQUEST['adduser'])) {
2193 $GLOBALS['url_query'] .= '&adduser=1';
2195 . PMA_getIcon('b_usradd.png') . __('Add user') . "\n"
2197 . '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n"
2198 . PMA_generate_common_hidden_inputs('', '');
2199 PMA_displayLoginInformationFields('new');
2200 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2201 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2203 $default_choice = 0;
2205 '0' => _pgettext('Create none database for user', 'None'),
2206 '1' => __('Create database with same name and grant all privileges'),
2207 '2' => __('Grant all privileges on wildcard name (username\\_%)'));
2209 if (! empty($dbname) ) {
2210 $choices['3'] = sprintf( __('Grant all privileges on database "%s"'), htmlspecialchars($dbname));
2211 $default_choice = 3;
2212 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2215 // 4th parameter set to true to add line breaks
2216 // 5th parameter set to false to avoid htmlspecialchars() escaping in the label
2217 // since we have some HTML in some labels
2218 PMA_display_html_radio('createdb', $choices, $default_choice, true, false);
2220 unset($default_choice);
2222 echo '</fieldset>' . "\n";
2223 PMA_displayPrivTable('*', '*', false);
2224 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2225 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2226 . ' </fieldset>' . "\n"
2229 // check the privileges for a particular database.
2230 $user_form = '<form id="usersForm"><table id="dbspecificuserrights" class="data">' . "\n"
2231 . '<caption class="tblHeaders">' . "\n"
2232 . PMA_getIcon('b_usrcheck.png')
2233 . ' ' . sprintf(__('Users having access to "%s"'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2234 . '</caption>' . "\n"
2236 . ' <tr><th>' . __('User') . '</th>' . "\n"
2237 . ' <th>' . __('Host') . '</th>' . "\n"
2238 . ' <th>' . __('Type') . '</th>' . "\n"
2239 . ' <th>' . __('Privileges') . '</th>' . "\n"
2240 . ' <th>' . __('Grant') . '</th>' . "\n"
2241 . ' <th>' . __('Action') . '</th>' . "\n"
2246 unset($row, $row1, $row2);
2248 // now, we build the table...
2249 $list_of_privileges =
2261 . '`References_priv`, '
2262 . '`Create_tmp_table_priv`, '
2263 . '`Lock_tables_priv`, '
2264 . '`Create_view_priv`, '
2265 . '`Show_view_priv`, '
2266 . '`Create_routine_priv`, '
2267 . '`Alter_routine_priv`, '
2270 $list_of_compared_privileges =
2271 '`Select_priv` = \'N\''
2272 . ' AND `Insert_priv` = \'N\''
2273 . ' AND `Update_priv` = \'N\''
2274 . ' AND `Delete_priv` = \'N\''
2275 . ' AND `Create_priv` = \'N\''
2276 . ' AND `Drop_priv` = \'N\''
2277 . ' AND `Grant_priv` = \'N\''
2278 . ' AND `References_priv` = \'N\''
2279 . ' AND `Create_tmp_table_priv` = \'N\''
2280 . ' AND `Lock_tables_priv` = \'N\''
2281 . ' AND `Create_view_priv` = \'N\''
2282 . ' AND `Show_view_priv` = \'N\''
2283 . ' AND `Create_routine_priv` = \'N\''
2284 . ' AND `Alter_routine_priv` = \'N\''
2285 . ' AND `Execute_priv` = \'N\'';
2287 if (PMA_MYSQL_INT_VERSION
>= 50106) {
2288 $list_of_privileges .=
2291 $list_of_compared_privileges .=
2292 ' AND `Event_priv` = \'N\''
2293 . ' AND `Trigger_priv` = \'N\'';
2297 '(SELECT ' . $list_of_privileges . ', `Db`'
2298 .' FROM `mysql`.`db`'
2299 .' WHERE \'' . PMA_sqlAddSlashes($checkprivs) . "'"
2301 .' AND NOT (' . $list_of_compared_privileges. ')) '
2303 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2304 .' FROM `mysql`.`user` '
2305 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2306 .' ORDER BY `User` ASC,'
2309 $res = PMA_DBI_query($sql_query);
2310 $row = PMA_DBI_fetch_assoc($res);
2317 // prepare the current user
2318 $current_privileges = array();
2319 $current_user = $row['User'];
2320 $current_host = $row['Host'];
2321 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2322 $current_privileges[] = $row;
2323 $row = PMA_DBI_fetch_assoc($res);
2325 $user_form .= ' <tr class="noclick ' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
2327 if (count($current_privileges) > 1) {
2328 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2330 $user_form .= '>' . (empty($current_user) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2333 if (count($current_privileges) > 1) {
2334 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2336 $user_form .= '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2337 foreach ($current_privileges as $current) {
2338 $user_form .= ' <td>' . "\n"
2340 if (! isset($current['Db']) ||
$current['Db'] == '*') {
2341 $user_form .= __('global');
2342 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2343 $user_form .= __('database-specific');
2345 $user_form .= __('wildcard'). ': <tt>' . htmlspecialchars($current['Db']) . '</tt>';
2351 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, true)) . "\n"
2355 . ' ' . ($current['Grant_priv'] == 'Y' ?
__('Yes') : __('No')) . "\n"
2358 $user_form .= sprintf($link_edit, urlencode($current_user),
2359 urlencode($current_host),
2360 urlencode(! isset($current['Db']) ||
$current['Db'] == '*' ?
'' : $current['Db']),
2362 $user_form .= '</td>' . "\n"
2365 if (empty($row) && empty($row1) && empty($row2)) {
2368 $odd_row = ! $odd_row;
2371 $user_form .= ' <tr class="odd">' . "\n"
2372 . ' <td colspan="6">' . "\n"
2373 . ' ' . __('No user found.') . "\n"
2377 $user_form .= '</tbody>' . "\n"
2378 . '</table></form>' . "\n";
2380 if ($GLOBALS['is_ajax_request'] == true) {
2381 $extra_data['user_form'] = $user_form;
2382 $message = PMA_Message
::success(__('User has been added.'));
2383 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
2385 // Offer to create a new user for the current database
2386 $user_form .= '<fieldset id="fieldset_add_user">' . "\n"
2387 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1&dbname=' . htmlspecialchars($checkprivs) .'" val="'.'checkprivs='.htmlspecialchars($checkprivs). '&'.$GLOBALS['url_query'] . '" class="'.$conditional_class.'" name="db_specific">' . "\n"
2388 . PMA_getIcon('b_usradd.png')
2389 . ' ' . __('Add user') . '</a>' . "\n"
2390 . '</fieldset>' . "\n";
2394 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2398 * Displays the footer
2401 require './libraries/footer.inc.php';