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';
22 if ($GLOBALS['cfg']['AjaxEnable']) {
23 $conditional_class = 'ajax';
25 $conditional_class = '';
29 * Messages are built using the message name
31 $strPrivDescAllPrivileges = __('Includes all privileges except GRANT.');
32 $strPrivDescAlter = __('Allows altering the structure of existing tables.');
33 $strPrivDescAlterRoutine = __('Allows altering and dropping stored routines.');
34 $strPrivDescCreateDb = __('Allows creating new databases and tables.');
35 $strPrivDescCreateRoutine = __('Allows creating stored routines.');
36 $strPrivDescCreateTbl = __('Allows creating new tables.');
37 $strPrivDescCreateTmpTable = __('Allows creating temporary tables.');
38 $strPrivDescCreateUser = __('Allows creating, dropping and renaming user accounts.');
39 $strPrivDescCreateView = __('Allows creating new views.');
40 $strPrivDescDelete = __('Allows deleting data.');
41 $strPrivDescDropDb = __('Allows dropping databases and tables.');
42 $strPrivDescDropTbl = __('Allows dropping tables.');
43 $strPrivDescEvent = __('Allows to set up events for the event scheduler');
44 $strPrivDescExecute = __('Allows executing stored routines.');
45 $strPrivDescFile = __('Allows importing data from and exporting data into files.');
46 $strPrivDescGrant = __('Allows adding users and privileges without reloading the privilege tables.');
47 $strPrivDescIndex = __('Allows creating and dropping indexes.');
48 $strPrivDescInsert = __('Allows inserting and replacing data.');
49 $strPrivDescLockTables = __('Allows locking tables for the current thread.');
50 $strPrivDescMaxConnections = __('Limits the number of new connections the user may open per hour.');
51 $strPrivDescMaxQuestions = __('Limits the number of queries the user may send to the server per hour.');
52 $strPrivDescMaxUpdates = __('Limits the number of commands that change any table or database the user may execute per hour.');
53 $strPrivDescMaxUserConnections = __('Limits the number of simultaneous connections the user may have.');
54 $strPrivDescProcess = __('Allows viewing processes of all users');
55 $strPrivDescReferences = __('Has no effect in this MySQL version.');
56 $strPrivDescReload = __('Allows reloading server settings and flushing the server\'s caches.');
57 $strPrivDescReplClient = __('Allows the user to ask where the slaves / masters are.');
58 $strPrivDescReplSlave = __('Needed for the replication slaves.');
59 $strPrivDescSelect = __('Allows reading data.');
60 $strPrivDescShowDb = __('Gives access to the complete list of databases.');
61 $strPrivDescShowView = __('Allows performing SHOW CREATE VIEW queries.');
62 $strPrivDescShutdown = __('Allows shutting down the server.');
63 $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.');
64 $strPrivDescTrigger = __('Allows creating and dropping triggers');
65 $strPrivDescUpdate = __('Allows changing data.');
66 $strPrivDescUsage = __('No privileges.');
69 * Checks if a dropdown box has been used for selecting a database / table
71 if (PMA_isValid($_REQUEST['pred_tablename'])) {
72 $tablename = $_REQUEST['pred_tablename'];
73 unset($pred_tablename);
74 } elseif (PMA_isValid($_REQUEST['tablename'])) {
75 $tablename = $_REQUEST['tablename'];
80 if (PMA_isValid($_REQUEST['pred_dbname'])) {
81 $dbname = $_REQUEST['pred_dbname'];
83 } elseif (PMA_isValid($_REQUEST['dbname'])) {
84 $dbname = $_REQUEST['dbname'];
91 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
92 if (isset($tablename)) {
93 $db_and_table .= PMA_backquote($tablename);
98 $db_and_table = '*.*';
101 // check if given $dbname is a wildcard or not
102 if (isset($dbname)) {
103 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
104 if (preg_match('/(?<!\\\\)(?:_|%)/i', $dbname)) {
105 $dbname_is_wildcard = true;
107 $dbname_is_wildcard = false;
112 * Checks if the user is allowed to do what he tries to...
114 if (!$is_superuser) {
115 require './libraries/server_links.inc.php';
117 . PMA_getIcon('b_usrlist.png')
118 . __('Privileges') . "\n"
120 PMA_Message
::error(__('No Privileges'))->display();
121 require './libraries/footer.inc.php';
125 * Escapes wildcard in a database+table specification
126 * before using it in a GRANT statement.
128 * Escaping a wildcard character in a GRANT is only accepted at the global
129 * or database level, not at table level; this is why I remove
130 * the escaping character. Internally, in mysql.tables_priv.Db there are
131 * no escaping (for example test_db) but in mysql.db you'll see test\_db
132 * for a db-specific privilege.
134 * @param string $db_and_table
135 * @param string $dbname
136 * @param string $tablename
137 * @return string the escaped (if necessary) $db_and_table
139 function PMA_WildcardEscapeForGrant($db_and_table, $dbname, $tablename) {
141 if (! strlen($dbname)) {
142 $db_and_table = '*.*';
144 if (strlen($tablename)) {
145 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
146 $db_and_table .= PMA_backquote($tablename);
148 $db_and_table = PMA_backquote($dbname) . '.';
149 $db_and_table .= '*';
152 return $db_and_table;
156 * Generates a condition on the user name
158 * @param string the user's initial
159 * @return string the generated condition
161 function PMA_RangeOfUsers($initial = '')
163 // strtolower() is used because the User field
164 // might be BINARY, so LIKE would be case sensitive
165 if (!empty($initial)) {
166 $ret = " WHERE `User` LIKE '" . $initial . "%'"
167 . " OR `User` LIKE '" . strtolower($initial) . "%'";
175 * Extracts the privilege information of a priv table row
177 * @param array $row the row
178 * @param boolean $enableHTML add <dfn> tag with tooltips
180 * @global ressource $user_link the database connection
184 function PMA_extractPrivInfo($row = '', $enableHTML = FALSE)
187 array('Select_priv', 'SELECT', __('Allows reading data.')),
188 array('Insert_priv', 'INSERT', __('Allows inserting and replacing data.')),
189 array('Update_priv', 'UPDATE', __('Allows changing data.')),
190 array('Delete_priv', 'DELETE', __('Allows deleting data.')),
191 array('Create_priv', 'CREATE', __('Allows creating new databases and tables.')),
192 array('Drop_priv', 'DROP', __('Allows dropping databases and tables.')),
193 array('Reload_priv', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.')),
194 array('Shutdown_priv', 'SHUTDOWN', __('Allows shutting down the server.')),
195 array('Process_priv', 'PROCESS', __('Allows viewing processes of all users')),
196 array('File_priv', 'FILE', __('Allows importing data from and exporting data into files.')),
197 array('References_priv', 'REFERENCES', __('Has no effect in this MySQL version.')),
198 array('Index_priv', 'INDEX', __('Allows creating and dropping indexes.')),
199 array('Alter_priv', 'ALTER', __('Allows altering the structure of existing tables.')),
200 array('Show_db_priv', 'SHOW DATABASES', __('Gives access to the complete list of databases.')),
201 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.')),
202 array('Create_tmp_table_priv', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
203 array('Lock_tables_priv', 'LOCK TABLES', __('Allows locking tables for the current thread.')),
204 array('Repl_slave_priv', 'REPLICATION SLAVE', __('Needed for the replication slaves.')),
205 array('Repl_client_priv', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.')),
206 array('Create_view_priv', 'CREATE VIEW', __('Allows creating new views.')),
207 array('Event_priv', 'EVENT', __('Allows to set up events for the event scheduler')),
208 array('Trigger_priv', 'TRIGGER', __('Allows creating and dropping triggers')),
210 array('Create View_priv', 'CREATE VIEW', __('Allows creating new views.')),
211 array('Show_view_priv', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
213 array('Show view_priv', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
214 array('Create_routine_priv', 'CREATE ROUTINE', __('Allows creating stored routines.')),
215 array('Alter_routine_priv', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
216 array('Create_user_priv', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.')),
217 array('Execute_priv', 'EXECUTE', __('Allows executing stored routines.')),
220 if (!empty($row) && isset($row['Table_priv'])) {
221 $row1 = PMA_DBI_fetch_single_row(
222 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
223 'ASSOC', $GLOBALS['userlink']);
224 $av_grants = explode('\',\'', substr($row1['Type'], 5, strlen($row1['Type']) - 7));
226 $users_grants = explode(',', $row['Table_priv']);
227 foreach ($av_grants as $current_grant) {
228 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ?
'Y' : 'N';
230 unset($current_grant);
232 unset($users_grants);
235 $allPrivileges = TRUE;
236 foreach ($grants as $current_grant) {
237 if ((!empty($row) && isset($row[$current_grant[0]]))
238 ||
(empty($row) && isset($GLOBALS[$current_grant[0]]))) {
239 if ((!empty($row) && $row[$current_grant[0]] == 'Y')
241 && ($GLOBALS[$current_grant[0]] == 'Y'
242 ||
(is_array($GLOBALS[$current_grant[0]])
243 && count($GLOBALS[$current_grant[0]]) == $GLOBALS['column_count']
244 && empty($GLOBALS[$current_grant[0] . '_none'])))))
247 $privs[] = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
249 $privs[] = $current_grant[1];
251 } elseif (!empty($GLOBALS[$current_grant[0]])
252 && is_array($GLOBALS[$current_grant[0]])
253 && empty($GLOBALS[$current_grant[0] . '_none'])) {
255 $priv_string = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
257 $priv_string = $current_grant[1];
259 $privs[] = $priv_string . ' (`' . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
261 $allPrivileges = FALSE;
267 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
271 } elseif ($allPrivileges && (!isset($GLOBALS['grant_count']) ||
count($privs) == $GLOBALS['grant_count'])) {
273 $privs = array('<dfn title="' . __('Includes all privileges except GRANT.') . '">ALL PRIVILEGES</dfn>');
275 $privs = array('ALL PRIVILEGES');
279 } // end of the 'PMA_extractPrivInfo()' function
282 * Displays on which column(s) a table-specific privilege is granted
284 function PMA_display_column_privs($columns, $row, $name_for_select,
285 $priv_for_header, $name, $name_for_dfn, $name_for_current)
287 echo ' <div class="item" id="div_item_' . $name . '">' . "\n"
288 . ' <label for="select_' . $name . '_priv">' . "\n"
289 . ' <tt><dfn title="' . $name_for_dfn . '">'
290 . $priv_for_header . '</dfn></tt>' . "\n"
291 . ' </label><br />' . "\n"
292 . ' <select id="select_' . $name . '_priv" name="'
293 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
295 foreach ($columns as $current_column => $current_column_privileges) {
296 echo ' <option value="' . htmlspecialchars($current_column) . '"';
297 if ($row[$name_for_select] == 'Y' ||
$current_column_privileges[$name_for_current]) {
298 echo ' selected="selected"';
300 echo '>' . htmlspecialchars($current_column) . '</option>' . "\n";
303 echo ' </select>' . "\n"
304 . ' <i>' . __('Or') . '</i>' . "\n"
305 . ' <label for="checkbox_' . $name_for_select
306 . '_none"><input type="checkbox"'
307 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
308 . ' name="' . $name_for_select . '_none" id="checkbox_'
309 . $name_for_select . '_none" title="' . _pgettext('None privileges', 'None') . '" />'
310 . _pgettext('None privileges', 'None') . '</label>' . "\n"
316 * Displays the privileges form table
318 * @param string $db the database
319 * @param string $table the table
320 * @param boolean $submit wheather to display the submit button or not
321 * @global array $cfg the phpMyAdmin configuration
322 * @global ressource $user_link the database connection
326 function PMA_displayPrivTable($db = '*', $table = '*', $submit = TRUE)
332 if (isset($GLOBALS['username'])) {
333 $username = $GLOBALS['username'];
334 $hostname = $GLOBALS['hostname'];
337 "SELECT * FROM `mysql`.`user`"
338 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
339 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
340 } elseif ($table == '*') {
342 "SELECT * FROM `mysql`.`db`"
343 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
344 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "'"
345 ." AND '" . PMA_unescape_mysql_wildcards($db) . "'"
349 "SELECT `Table_priv`"
350 ." FROM `mysql`.`tables_priv`"
351 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
352 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "'"
353 ." AND `Db` = '" . PMA_unescape_mysql_wildcards($db) . "'"
354 ." AND `Table_name` = '" . PMA_sqlAddslashes($table) . "';";
356 $row = PMA_DBI_fetch_single_row($sql_query);
361 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
362 } elseif ($table == '*') {
363 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
365 $res = PMA_DBI_query($sql_query);
366 while ($row1 = PMA_DBI_fetch_row($res)) {
367 if (substr($row1[0], 0, 4) == 'max_') {
370 $row[$row1[0]] = 'N';
373 PMA_DBI_free_result($res);
375 $row = array('Table_priv' => '');
378 if (isset($row['Table_priv'])) {
379 $row1 = PMA_DBI_fetch_single_row(
380 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
381 'ASSOC', $GLOBALS['userlink']);
382 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
383 // the View for Create is spelled with uppercase V
384 // the view for Show is spelled with lowercase v
385 // and there is a space between the words
387 $av_grants = explode('\',\'', substr($row1['Type'], strpos($row1['Type'], '(') +
2, strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3));
389 $users_grants = explode(',', $row['Table_priv']);
391 foreach ($av_grants as $current_grant) {
392 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ?
'Y' : 'N';
394 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
397 $res = PMA_DBI_try_query('SHOW COLUMNS FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($db)) . '.' . PMA_backquote($table) . ';');
400 while ($row1 = PMA_DBI_fetch_row($res)) {
401 $columns[$row1[0]] = array(
405 'References' => FALSE
408 PMA_DBI_free_result($res);
412 // t a b l e - s p e c i f i c p r i v i l e g e s
413 if (! empty($columns)) {
414 $res = PMA_DBI_query(
415 'SELECT `Column_name`, `Column_priv`'
416 .' FROM `mysql`.`columns_priv`'
418 .' = \'' . PMA_sqlAddslashes($username) . "'"
420 .' = \'' . PMA_sqlAddslashes($hostname) . "'"
422 .' = \'' . PMA_sqlAddslashes(PMA_unescape_mysql_wildcards($db)) . "'"
424 .' = \'' . PMA_sqlAddslashes($table) . '\';');
426 while ($row1 = PMA_DBI_fetch_row($res)) {
427 $row1[1] = explode(',', $row1[1]);
428 foreach ($row1[1] as $current) {
429 $columns[$row1[0]][$current] = TRUE;
432 PMA_DBI_free_result($res);
433 unset($res, $row1, $current);
435 echo '<input type="hidden" name="grant_count" value="' . count($row) . '" />' . "\n"
436 . '<input type="hidden" name="column_count" value="' . count($columns) . '" />' . "\n"
437 . '<fieldset id="fieldset_user_priv">' . "\n"
438 . ' <legend>' . __('Table-specific privileges')
439 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English '))
440 . '</legend>' . "\n";
444 // privs that are attached to a specific column
445 PMA_display_column_privs($columns, $row, 'Select_priv',
446 'SELECT', 'select', __('Allows reading data.'), 'Select');
448 PMA_display_column_privs($columns, $row, 'Insert_priv',
449 'INSERT', 'insert', __('Allows inserting and replacing data.'), 'Insert');
451 PMA_display_column_privs($columns, $row, 'Update_priv',
452 'UPDATE', 'update', __('Allows changing data.'), 'Update');
454 PMA_display_column_privs($columns, $row, 'References_priv',
455 'REFERENCES', 'references', __('Has no effect in this MySQL version.'), 'References');
457 // privs that are not attached to a specific column
459 echo ' <div class="item">' . "\n";
460 foreach ($row as $current_grant => $current_grant_value) {
461 if (in_array(substr($current_grant, 0, (strlen($current_grant) - 5)),
462 array('Select', 'Insert', 'Update', 'References'))) {
465 // make a substitution to match the messages variables;
466 // also we must substitute the grant we get, because we can't generate
467 // a form variable containing blanks (those would get changed to
468 // an underscore when receiving the POST)
469 if ($current_grant == 'Create View_priv') {
470 $tmp_current_grant = 'CreateView_priv';
471 $current_grant = 'Create_view_priv';
472 } elseif ($current_grant == 'Show view_priv') {
473 $tmp_current_grant = 'ShowView_priv';
474 $current_grant = 'Show_view_priv';
476 $tmp_current_grant = $current_grant;
479 echo ' <div class="item">' . "\n"
480 . ' <input type="checkbox"'
481 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
482 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
484 . ($current_grant_value == 'Y' ?
'checked="checked" ' : '')
487 echo (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']) . '"/>' . "\n";
491 echo ' <label for="checkbox_' . $current_grant
492 . '"><tt><dfn title="'
493 . (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
494 ?
$GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
495 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl'])
496 . '">' . strtoupper(substr($current_grant, 0, strlen($current_grant) - 5)) . '</dfn></tt></label>' . "\n"
500 echo ' </div>' . "\n";
502 echo ' <div class="clearfloat"></div>' . "\n";
506 // g l o b a l o r d b - s p e c i f i c
509 $privTable[0] = array(
510 array('Select', 'SELECT', __('Allows reading data.')),
511 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
512 array('Update', 'UPDATE', __('Allows changing data.')),
513 array('Delete', 'DELETE', __('Allows deleting data.'))
516 $privTable[0][] = array('File', 'FILE', __('Allows importing data from and exporting data into files.'));
520 $privTable[1] = array(
521 array('Create', 'CREATE', ($table == '*' ?
__('Allows creating new databases and tables.') : __('Allows creating new tables.'))),
522 array('Alter', 'ALTER', __('Allows altering the structure of existing tables.')),
523 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
524 array('Drop', 'DROP', ($table == '*' ?
__('Allows dropping databases and tables.') : __('Allows dropping tables.'))),
525 array('Create_tmp_table', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
526 array('Show_view', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
527 array('Create_routine', 'CREATE ROUTINE', __('Allows creating stored routines.')),
528 array('Alter_routine', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
529 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
531 // this one is for a db-specific priv: Create_view_priv
532 if (isset($row['Create_view_priv'])) {
533 $privTable[1][] = array('Create_view', 'CREATE VIEW', __('Allows creating new views.'));
535 // this one is for a table-specific priv: Create View_priv
536 if (isset($row['Create View_priv'])) {
537 $privTable[1][] = array('Create View', 'CREATE VIEW', __('Allows creating new views.'));
539 if (isset($row['Event_priv'])) {
541 $privTable[1][] = array('Event', 'EVENT', __('Allows to set up events for the event scheduler'));
542 $privTable[1][] = array('Trigger', 'TRIGGER', __('Allows creating and dropping triggers'));
545 // a d m i n i s t r a t i o n
546 $privTable[2] = array(
547 array('Grant', 'GRANT', __('Allows adding users and privileges without reloading the privilege tables.')),
550 $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.'));
551 $privTable[2][] = array('Process', 'PROCESS', __('Allows viewing processes of all users'));
552 $privTable[2][] = array('Reload', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.'));
553 $privTable[2][] = array('Shutdown', 'SHUTDOWN', __('Allows shutting down the server.'));
554 $privTable[2][] = array('Show_db', 'SHOW DATABASES', __('Gives access to the complete list of databases.'));
556 $privTable[2][] = array('Lock_tables', 'LOCK TABLES', __('Allows locking tables for the current thread.'));
557 $privTable[2][] = array('References', 'REFERENCES', __('Has no effect in this MySQL version.'));
559 $privTable[2][] = array('Repl_client', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.'));
560 $privTable[2][] = array('Repl_slave', 'REPLICATION SLAVE', __('Needed for the replication slaves.'));
561 $privTable[2][] = array('Create_user', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.'));
563 echo '<input type="hidden" name="grant_count" value="'
564 . (count($privTable[0]) +
count($privTable[1]) +
count($privTable[2]) - (isset($row['Grant_priv']) ?
1 : 0))
566 . '<fieldset id="fieldset_user_global_rights">' . "\n"
570 ?
__('Global privileges')
572 ?
__('Database-specific privileges')
573 : __('Table-specific privileges'))) . "\n"
574 . ' (<a href="server_privileges.php?'
575 . $GLOBALS['url_query'] . '&checkall=1" onclick="setCheckboxes(\'addUsersForm\', true); return false;">'
576 . __('Check All') . '</a> /' . "\n"
577 . ' <a href="server_privileges.php?'
578 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'addUsersForm\', false); return false;">'
579 . __('Uncheck All') . '</a>)' . "\n"
580 . ' </legend>' . "\n"
581 . ' <p><small><i>' . __(' Note: MySQL privilege names are expressed in English ') . '</i></small></p>' . "\n"
582 . ' <fieldset>' . "\n"
583 . ' <legend>' . __('Data') . '</legend>' . "\n";
584 foreach ($privTable[0] as $priv)
586 echo ' <div class="item">' . "\n"
587 . ' <input type="checkbox"'
588 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
589 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
590 . '_priv" value="Y" '
591 . ($row[$priv[0] . '_priv'] == 'Y' ?
'checked="checked" ' : '')
592 . 'title="' . $priv[2] . '"/>' . "\n"
593 . ' <label for="checkbox_' . $priv[0]
594 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
595 . '</dfn></tt></label>' . "\n"
598 echo ' </fieldset>' . "\n"
599 . ' <fieldset>' . "\n"
600 . ' <legend>' . __('Structure') . '</legend>' . "\n";
601 foreach ($privTable[1] as $priv)
603 echo ' <div class="item">' . "\n"
604 . ' <input type="checkbox"'
605 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
606 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
607 . '_priv" value="Y" '
608 . ($row[$priv[0] . '_priv'] == 'Y' ?
'checked="checked" ' : '')
609 . 'title="' . $priv[2] . '"/>' . "\n"
610 . ' <label for="checkbox_' . $priv[0]
611 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
612 . '</dfn></tt></label>' . "\n"
615 echo ' </fieldset>' . "\n"
616 . ' <fieldset>' . "\n"
617 . ' <legend>' . __('Administration') . '</legend>' . "\n";
618 foreach ($privTable[2] as $priv)
620 echo ' <div class="item">' . "\n"
621 . ' <input type="checkbox"'
622 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
623 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
624 . '_priv" value="Y" '
625 . ($row[$priv[0] . '_priv'] == 'Y' ?
'checked="checked" ' : '')
626 . 'title="' . $priv[2] . '"/>' . "\n"
627 . ' <label for="checkbox_' . $priv[0]
628 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
629 . '</dfn></tt></label>' . "\n"
633 echo ' </fieldset>' . "\n";
634 // The "Resource limits" box is not displayed for db-specific privs
636 echo ' <fieldset>' . "\n"
637 . ' <legend>' . __('Resource limits') . '</legend>' . "\n"
638 . ' <p><small><i>' . __('Note: Setting these options to 0 (zero) removes the limit.') . '</i></small></p>' . "\n"
639 . ' <div class="item">' . "\n"
640 . ' <label for="text_max_questions"><tt><dfn title="'
641 . __('Limits the number of queries the user may send to the server per hour.') . '">MAX QUERIES PER HOUR</dfn></tt></label>' . "\n"
642 . ' <input type="text" name="max_questions" id="text_max_questions" value="'
643 . $row['max_questions'] . '" size="11" maxlength="11" title="' . __('Limits the number of queries the user may send to the server per hour.') . '" />' . "\n"
645 . ' <div class="item">' . "\n"
646 . ' <label for="text_max_updates"><tt><dfn title="'
647 . __('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"
648 . ' <input type="text" name="max_updates" id="text_max_updates" value="'
649 . $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"
651 . ' <div class="item">' . "\n"
652 . ' <label for="text_max_connections"><tt><dfn title="'
653 . __('Limits the number of new connections the user may open per hour.') . '">MAX CONNECTIONS PER HOUR</dfn></tt></label>' . "\n"
654 . ' <input type="text" name="max_connections" id="text_max_connections" value="'
655 . $row['max_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of new connections the user may open per hour.') . '" />' . "\n"
657 . ' <div class="item">' . "\n"
658 . ' <label for="text_max_user_connections"><tt><dfn title="'
659 . __('Limits the number of simultaneous connections the user may have.') . '">MAX USER_CONNECTIONS</dfn></tt></label>' . "\n"
660 . ' <input type="text" name="max_user_connections" id="text_max_user_connections" value="'
661 . $row['max_user_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of simultaneous connections the user may have.') . '" />' . "\n"
663 . ' </fieldset>' . "\n";
666 echo ' <div class="clearfloat"></div>' . "\n";
668 echo '</fieldset>' . "\n";
670 echo '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">' . "\n"
671 . ' <input type="submit" name="update_privs" value="' . __('Go') . '" />' . "\n"
672 . '</fieldset>' . "\n";
674 } // end of the 'PMA_displayPrivTable()' function
678 * Displays the fields used by the "new user" form as well as the
679 * "change login information / copy user" form.
681 * @param string $mode are we creating a new user or are we just
682 * changing one? (allowed values: 'new', 'change')
683 * @global array $cfg the phpMyAdmin configuration
684 * @global ressource $user_link the database connection
688 function PMA_displayLoginInformationFields($mode = 'new')
690 // Get user/host name lengths
691 $fields_info = PMA_DBI_get_fields('mysql', 'user');
692 $username_length = 16;
693 $hostname_length = 41;
694 foreach ($fields_info as $key => $val) {
695 if ($val['Field'] == 'User') {
696 strtok($val['Type'], '()');
699 $username_length = $v;
701 } elseif ($val['Field'] == 'Host') {
702 strtok($val['Type'], '()');
705 $hostname_length = $v;
711 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
712 $GLOBALS['pred_username'] = 'any';
714 echo '<fieldset id="fieldset_add_user_login">' . "\n"
715 . '<legend>' . __('Login Information') . '</legend>' . "\n"
716 . '<div class="item">' . "\n"
717 . '<label for="select_pred_username">' . "\n"
718 . ' ' . __('User name') . ':' . "\n"
720 . '<span class="options">' . "\n"
721 . ' <select name="pred_username" id="select_pred_username" title="' . __('User name') . '"' . "\n"
722 . ' onchange="if (this.value == \'any\') { username.value = \'\'; } else if (this.value == \'userdefined\') { username.focus(); username.select(); }">' . "\n"
723 . ' <option value="any"' . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any') ?
' selected="selected"' : '') . '>' . __('Any user') . '</option>' . "\n"
724 . ' <option value="userdefined"' . ((!isset($GLOBALS['pred_username']) ||
$GLOBALS['pred_username'] == 'userdefined') ?
' selected="selected"' : '') . '>' . __('Use text field') . ':</option>' . "\n"
725 . ' </select>' . "\n"
727 . '<input type="text" name="username" maxlength="'
728 . $username_length . '" title="' . __('User name') . '"'
729 . (empty($GLOBALS['username'])
731 : ' value="' . htmlspecialchars(isset($GLOBALS['new_username'])
732 ?
$GLOBALS['new_username']
733 : $GLOBALS['username']) . '"')
734 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
736 . '<div class="item">' . "\n"
737 . '<label for="select_pred_hostname">' . "\n"
738 . ' ' . __('Host') . ':' . "\n"
740 . '<span class="options">' . "\n"
741 . ' <select name="pred_hostname" id="select_pred_hostname" title="' . __('Host') . '"' . "\n";
742 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
743 if (! empty($_current_user)) {
744 $thishost = str_replace("'", '', substr($_current_user, (strrpos($_current_user, '@') +
1)));
745 if ($thishost == 'localhost' ||
$thishost == '127.0.0.1') {
749 echo ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } else if (this.value == \'localhost\') { hostname.value = \'localhost\'; } '
750 . (empty($thishost) ?
'' : 'else if (this.value == \'thishost\') { hostname.value = \'' . addslashes(htmlspecialchars($thishost)) . '\'; } ')
751 . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } else if (this.value == \'userdefined\') { hostname.focus(); hostname.select(); }">' . "\n";
752 unset($_current_user);
754 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
755 if (!isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
756 switch (strtolower($GLOBALS['hostname'])) {
759 $GLOBALS['pred_hostname'] = 'localhost';
762 $GLOBALS['pred_hostname'] = 'any';
765 $GLOBALS['pred_hostname'] = 'userdefined';
769 echo ' <option value="any"'
770 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
771 ?
' selected="selected"' : '') . '>' . __('Any host')
773 . ' <option value="localhost"'
774 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'localhost')
775 ?
' selected="selected"' : '') . '>' . __('Local')
776 . '</option>' . "\n";
777 if (!empty($thishost)) {
778 echo ' <option value="thishost"'
779 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'thishost')
780 ?
' selected="selected"' : '') . '>' . __('This Host')
781 . '</option>' . "\n";
784 echo ' <option value="hosttable"'
785 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'hosttable')
786 ?
' selected="selected"' : '') . '>' . __('Use Host Table')
788 . ' <option value="userdefined"'
789 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'userdefined')
790 ?
' selected="selected"' : '')
791 . '>' . __('Use text field') . ':</option>' . "\n"
792 . ' </select>' . "\n"
794 . '<input type="text" name="hostname" maxlength="'
795 . $hostname_length . '" value="'
796 . htmlspecialchars(isset($GLOBALS['hostname']) ?
$GLOBALS['hostname'] : '')
797 . '" title="' . __('Host')
798 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
799 . PMA_showHint(__('When Host table is used, this field is ignored and values stored in Host table are used instead.'))
801 . '<div class="item">' . "\n"
802 . '<label for="select_pred_password">' . "\n"
803 . ' ' . __('Password') . ':' . "\n"
805 . '<span class="options">' . "\n"
806 . ' <select name="pred_password" id="select_pred_password" title="'
807 . __('Password') . '"' . "\n"
808 . ' onchange="if (this.value == \'none\') { pma_pw.value = \'\'; pma_pw2.value = \'\'; } else if (this.value == \'userdefined\') { pma_pw.focus(); pma_pw.select(); }">' . "\n"
809 . ($mode == 'change' ?
' <option value="keep" selected="selected">' . __('Do not change the password') . '</option>' . "\n" : '')
810 . ' <option value="none"';
811 if (isset($GLOBALS['username']) && $mode != 'change') {
812 echo ' selected="selected"';
814 echo '>' . __('No Password') . '</option>' . "\n"
815 . ' <option value="userdefined"' . (isset($GLOBALS['username']) ?
'' : ' selected="selected"') . '>' . __('Use text field') . ':</option>' . "\n"
816 . ' </select>' . "\n"
818 . '<input type="password" id="text_pma_pw" name="pma_pw" title="' . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
820 . '<div class="item" id="div_element_before_generate_password">' . "\n"
821 . '<label for="text_pma_pw2">' . "\n"
822 . ' ' . __('Re-type') . ':' . "\n"
824 . '<span class="options"> </span>' . "\n"
825 . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="' . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
827 // Generate password added here via jQuery
828 . '</fieldset>' . "\n";
829 } // end of the 'PMA_displayUserAndHostFields()' function
832 * Changes / copies a user, part I
834 if (isset($_REQUEST['change_copy'])) {
835 $user_host_condition =
837 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
839 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\';';
840 $row = PMA_DBI_fetch_single_row('SELECT * FROM `mysql`.`user` ' . $user_host_condition);
842 PMA_Message
::notice(__('No user found.'))->display();
843 unset($_REQUEST['change_copy']);
845 extract($row, EXTR_OVERWRITE
);
846 // Recent MySQL versions have the field "Password" in mysql.user,
847 // so the previous extract creates $Password but this script
849 if (!isset($password) && isset($Password)) {
850 $password = $Password;
859 * (Changes / copies a user, part II)
861 if (isset($_REQUEST['adduser_submit']) ||
isset($_REQUEST['change_copy'])) {
863 if ($pred_username == 'any') {
866 switch ($pred_hostname) {
871 $hostname = 'localhost';
877 $_user_name = PMA_DBI_fetch_value('SELECT USER()');
878 $hostname = substr($_user_name, (strrpos($_user_name, '@') +
1));
882 $sql = "SELECT '1' FROM `mysql`.`user`"
883 . " WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
884 . " AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
885 if (PMA_DBI_fetch_value($sql) == 1) {
886 $message = PMA_Message
::error(__('The user %s already exists!'));
887 $message->addParam('[i]\'' . $username . '\'@\'' . $hostname . '\'[/i]');
888 $_REQUEST['adduser'] = true;
891 $create_user_real = 'CREATE USER \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
894 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
895 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
896 if ($pred_password != 'none' && $pred_password != 'keep') {
897 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
898 $real_sql_query .= ' IDENTIFIED BY \'' . PMA_sqlAddslashes($pma_pw) . '\'';
899 if (isset($create_user_real)) {
900 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
901 $create_user_real .= ' IDENTIFIED BY \'' . PMA_sqlAddslashes($pma_pw) . '\'';
904 if ($pred_password == 'keep' && !empty($password)) {
905 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
906 if (isset($create_user_real)) {
907 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
910 $sql_query = $real_sql_query;
911 if (isset($create_user_real)) {
912 $create_user_show = $create_user_real;
916 * @todo similar code appears twice in this script
918 if ((isset($Grant_priv) && $Grant_priv == 'Y')
919 ||
(isset($max_questions) ||
isset($max_connections)
920 ||
isset($max_updates) ||
isset($max_user_connections))) {
921 $real_sql_query .= ' WITH';
922 $sql_query .= ' WITH';
923 if (isset($Grant_priv) && $Grant_priv == 'Y') {
924 $real_sql_query .= ' GRANT OPTION';
925 $sql_query .= ' GRANT OPTION';
927 if (isset($max_questions)) {
928 // avoid negative values
929 $max_questions = max(0, (int)$max_questions);
930 $real_sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
931 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
933 if (isset($max_connections)) {
934 $max_connections = max(0, (int)$max_connections);
935 $real_sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
936 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
938 if (isset($max_updates)) {
939 $max_updates = max(0, (int)$max_updates);
940 $real_sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
941 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
943 if (isset($max_user_connections)) {
944 $max_user_connections = max(0, (int)$max_user_connections);
945 $real_sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
946 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
949 if (isset($create_user_real)) {
950 $create_user_real .= ';';
951 $create_user_show .= ';';
953 $real_sql_query .= ';';
955 if (empty($_REQUEST['change_copy'])) {
958 if (isset($create_user_real)) {
959 if (! PMA_DBI_try_query($create_user_real)) {
962 $sql_query = $create_user_show . $sql_query;
965 if ($_error ||
! PMA_DBI_try_query($real_sql_query)) {
966 $_REQUEST['createdb'] = false;
967 $message = PMA_Message
::rawError(PMA_DBI_getError());
969 $message = PMA_Message
::success(__('You have added a new user.'));
972 switch (PMA_ifSetOr($_REQUEST['createdb'], '0')) {
974 // Create database with same name and grant all privileges
975 $q = 'CREATE DATABASE IF NOT EXISTS '
976 . PMA_backquote(PMA_sqlAddslashes($username)) . ';';
978 if (! PMA_DBI_try_query($q)) {
979 $message = PMA_Message
::rawError(PMA_DBI_getError());
985 * If we are not in an Ajax request, we can't reload navigation now
987 if($GLOBALS['is_ajax_request'] != true) {
988 // this is needed in case tracking is on:
989 $GLOBALS['db'] = $username;
990 $GLOBALS['reload'] = TRUE;
991 PMA_reloadNavigation();
994 $q = 'GRANT ALL PRIVILEGES ON '
995 . PMA_backquote(PMA_sqlAddslashes($username)) . '.* TO \''
996 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
998 if (! PMA_DBI_try_query($q)) {
999 $message = PMA_Message
::rawError(PMA_DBI_getError());
1003 // Grant all privileges on wildcard name (username\_%)
1004 $q = 'GRANT ALL PRIVILEGES ON '
1005 . PMA_backquote(PMA_sqlAddslashes($username) . '\_%') . '.* TO \''
1006 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1008 if (! PMA_DBI_try_query($q)) {
1009 $message = PMA_Message
::rawError(PMA_DBI_getError());
1013 // Grant all privileges on the specified database to the new user
1014 $q = 'GRANT ALL PRIVILEGES ON '
1015 . PMA_backquote(PMA_sqlAddslashes($dbname)) . '.* TO \''
1016 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1018 if (! PMA_DBI_try_query($q)) {
1019 $message = PMA_Message
::rawError(PMA_DBI_getError());
1027 if (isset($create_user_real)) {
1028 $queries[] = $create_user_real;
1030 $queries[] = $real_sql_query;
1031 // we put the query containing the hidden password in
1032 // $queries_for_display, at the same position occupied
1033 // by the real query in $queries
1034 $tmp_count = count($queries);
1035 if (isset($create_user_real)) {
1036 $queries_for_display[$tmp_count - 2] = $create_user_show;
1038 $queries_for_display[$tmp_count - 1] = $sql_query;
1040 unset($res, $real_sql_query);
1046 * Changes / copies a user, part III
1048 if (isset($_REQUEST['change_copy'])) {
1049 $user_host_condition =
1051 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1053 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\';';
1054 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1055 while ($row = PMA_DBI_fetch_assoc($res)) {
1057 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1058 .' ON ' . PMA_backquote($row['Db']) . '.*'
1059 .' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1060 . ($row['Grant_priv'] == 'Y' ?
' WITH GRANT OPTION;' : ';');
1062 PMA_DBI_free_result($res);
1063 $res = PMA_DBI_query(
1064 'SELECT `Db`, `Table_name`, `Table_priv`'
1065 .' FROM `mysql`.`tables_priv`' . $user_host_condition,
1066 $GLOBALS['userlink'], PMA_DBI_QUERY_STORE
);
1067 while ($row = PMA_DBI_fetch_assoc($res)) {
1069 $res2 = PMA_DBI_QUERY(
1070 'SELECT `Column_name`, `Column_priv`'
1071 .' FROM `mysql`.`columns_priv`'
1073 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1075 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\''
1077 .' = \'' . PMA_sqlAddslashes($row['Db']) . "'"
1078 .' AND `Table_name`'
1079 .' = \'' . PMA_sqlAddslashes($row['Table_name']) . "'"
1081 null, PMA_DBI_QUERY_STORE
);
1083 $tmp_privs1 = PMA_extractPrivInfo($row);
1084 $tmp_privs2 = array(
1085 'Select' => array(),
1086 'Insert' => array(),
1087 'Update' => array(),
1088 'References' => array()
1091 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1092 $tmp_array = explode(',', $row2['Column_priv']);
1093 if (in_array('Select', $tmp_array)) {
1094 $tmp_privs2['Select'][] = $row2['Column_name'];
1096 if (in_array('Insert', $tmp_array)) {
1097 $tmp_privs2['Insert'][] = $row2['Column_name'];
1099 if (in_array('Update', $tmp_array)) {
1100 $tmp_privs2['Update'][] = $row2['Column_name'];
1102 if (in_array('References', $tmp_array)) {
1103 $tmp_privs2['References'][] = $row2['Column_name'];
1107 if (count($tmp_privs2['Select']) > 0 && !in_array('SELECT', $tmp_privs1)) {
1108 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1110 if (count($tmp_privs2['Insert']) > 0 && !in_array('INSERT', $tmp_privs1)) {
1111 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1113 if (count($tmp_privs2['Update']) > 0 && !in_array('UPDATE', $tmp_privs1)) {
1114 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1116 if (count($tmp_privs2['References']) > 0 && !in_array('REFERENCES', $tmp_privs1)) {
1117 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1121 'GRANT ' . join(', ', $tmp_privs1)
1122 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1123 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1124 . (in_array('Grant', explode(',', $row['Table_priv'])) ?
' WITH GRANT OPTION;' : ';');
1130 * Updates privileges
1132 if (!empty($update_privs)) {
1133 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, (isset($tablename) ?
$tablename : ''));
1136 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1137 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1138 if (!isset($Grant_priv) ||
$Grant_priv != 'Y') {
1140 'REVOKE GRANT OPTION ON ' . $db_and_table
1141 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1146 // Should not do a GRANT USAGE for a table-specific privilege, it
1147 // causes problems later (cannot revoke it)
1148 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1150 'GRANT ' . join(', ', PMA_extractPrivInfo())
1151 . ' ON ' . $db_and_table
1152 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
1155 * @todo similar code appears twice in this script
1157 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1158 ||
(! isset($dbname)
1159 && (isset($max_questions) ||
isset($max_connections)
1160 ||
isset($max_updates) ||
isset($max_user_connections))))
1162 $sql_query2 .= 'WITH';
1163 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1164 $sql_query2 .= ' GRANT OPTION';
1166 if (isset($max_questions)) {
1167 $max_questions = max(0, (int)$max_questions);
1168 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1170 if (isset($max_connections)) {
1171 $max_connections = max(0, (int)$max_connections);
1172 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1174 if (isset($max_updates)) {
1175 $max_updates = max(0, (int)$max_updates);
1176 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1178 if (isset($max_user_connections)) {
1179 $max_user_connections = max(0, (int)$max_user_connections);
1180 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1185 if (! PMA_DBI_try_query($sql_query0)) {
1186 // this query may fail, but this does not matter :o)
1189 if (isset($sql_query1) && !PMA_DBI_try_query($sql_query1)) {
1190 // this one may fail, too...
1193 if (isset($sql_query2)) {
1194 PMA_DBI_query($sql_query2);
1198 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1199 $message = PMA_Message
::success(__('You have updated the privileges for %s.'));
1200 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1205 * Revokes Privileges
1207 if (isset($_REQUEST['revokeall'])) {
1208 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, isset($tablename) ?
$tablename : '');
1211 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1212 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1214 'REVOKE GRANT OPTION ON ' . $db_and_table
1215 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1217 PMA_DBI_query($sql_query0);
1218 if (! PMA_DBI_try_query($sql_query1)) {
1219 // this one may fail, too...
1222 $sql_query = $sql_query0 . ' ' . $sql_query1;
1223 $message = PMA_Message
::success(__('You have revoked the privileges for %s'));
1224 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1225 if (! isset($tablename)) {
1234 * Updates the password
1236 if (isset($_REQUEST['change_pw'])) {
1237 // similar logic in user_password.php
1240 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1241 if ($pma_pw != $pma_pw2) {
1242 $message = PMA_Message
::error(__('The passwords aren\'t the same!'));
1243 } elseif (empty($pma_pw) ||
empty($pma_pw2)) {
1244 $message = PMA_Message
::error(__('The password is empty!'));
1248 // here $nopass could be == 1
1249 if (empty($message)) {
1251 $hashing_function = (!empty($pw_hash) && $pw_hash == 'old' ?
'OLD_' : '')
1254 // in $sql_query which will be displayed, hide the password
1255 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ?
'\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1256 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ?
'\'\'' : $hashing_function . '(\'' . PMA_sqlAddslashes($pma_pw) . '\')');
1257 PMA_DBI_try_query($local_query)
1258 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, FALSE, $err_url);
1259 $message = PMA_Message
::success(__('The password for %s was changed successfully.'));
1260 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1267 * (Changes / copies a user, part IV)
1270 if (isset($_REQUEST['delete']) ||
(isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1271 if (isset($_REQUEST['change_copy'])) {
1272 $selected_usr = array($old_username . '&#27;' . $old_hostname);
1274 $selected_usr = $_REQUEST['selected_usr'];
1277 foreach ($selected_usr as $each_user) {
1278 list($this_user, $this_host) = explode('&#27;', $each_user);
1279 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1280 $queries[] = 'DROP USER \'' . PMA_sqlAddslashes($this_user) . '\'@\'' . PMA_sqlAddslashes($this_host) . '\';';
1282 if (isset($_REQUEST['drop_users_db'])) {
1283 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1284 $GLOBALS['reload'] = TRUE;
1286 if($GLOBALS['is_ajax_request'] != true) {
1287 PMA_reloadNavigation();
1291 if (empty($_REQUEST['change_copy'])) {
1292 if (empty($queries)) {
1293 $message = PMA_Message
::error(__('No users selected for deleting!'));
1295 if ($_REQUEST['mode'] == 3) {
1296 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1297 $queries[] = 'FLUSH PRIVILEGES;';
1299 $drop_user_error = '';
1300 foreach ($queries as $sql_query) {
1301 if ($sql_query{0} != '#') {
1302 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1303 $drop_user_error .= PMA_DBI_getError() . "\n";
1307 // tracking sets this, causing the deleted db to be shown in navi
1308 unset($GLOBALS['db']);
1310 $sql_query = join("\n", $queries);
1311 if (! empty($drop_user_error)) {
1312 $message = PMA_Message
::rawError($drop_user_error);
1314 $message = PMA_Message
::success(__('The selected users have been deleted successfully.'));
1323 * Changes / copies a user, part V
1325 if (isset($_REQUEST['change_copy'])) {
1327 foreach ($queries as $sql_query) {
1328 if ($sql_query{0} != '#') {
1329 PMA_DBI_query($sql_query);
1331 // when there is a query containing a hidden password, take it
1332 // instead of the real query sent
1333 if (isset($queries_for_display[$tmp_count])) {
1334 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1338 $message = PMA_Message
::success();
1339 $sql_query = join("\n", $queries);
1344 * Reloads the privilege tables into memory
1346 if (isset($_REQUEST['flush_privileges'])) {
1347 $sql_query = 'FLUSH PRIVILEGES;';
1348 PMA_DBI_query($sql_query);
1349 $message = PMA_Message
::success(__('The privileges were reloaded successfully.'));
1353 * defines some standard links
1355 $link_edit = '<a class="edit_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . $GLOBALS['url_query']
1356 . '&username=%s'
1357 . '&hostname=%s'
1359 . '&tablename=%s">'
1360 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1363 $link_revoke = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1364 . '&username=%s'
1365 . '&hostname=%s'
1367 . '&tablename=%s'
1368 . '&revokeall=1">'
1369 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1372 $link_export = '<a class="export_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . $GLOBALS['url_query']
1373 . '&username=%s'
1374 . '&hostname=%s'
1377 . PMA_getIcon('b_tblexport.png', __('Export'))
1381 * If we are in an Ajax request for Create User/Edit User/Revoke User/Flush Privileges,
1382 * show $message and exit.
1384 if( $GLOBALS['is_ajax_request'] && !isset($_REQUEST['export']) && !isset($_REQUEST['adduser']) && !isset($_REQUEST['initial']) && !isset($_REQUEST['showall']) && !isset($_REQUEST['edit_user_dialog'])) {
1386 if(isset($sql_query)) {
1387 $extra_data['sql_query'] = PMA_showMessage(NULL, $sql_query);
1390 if(isset($_REQUEST['adduser_submit']) ||
isset($_REQUEST['change_copy'])) {
1392 * generate html on the fly for the new user that was just created.
1394 $new_user_string = '<tr>'."\n"
1395 .'<td> <input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_" value="' . htmlspecialchars($username) . '&#27;' . htmlspecialchars($hostname) . '" /> </td>'."\n"
1396 .'<td><label for="checkbox_sel_users_">' . (empty($username) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($username) ) . '</label></td>' . "\n"
1397 .'<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
1398 $new_user_string .= '<td>';
1400 if(!empty($password) ||
isset($pma_pw)) {
1401 $new_user_string .= __('Yes');
1404 $new_user_string .= '<span style="color: #FF0000">' . __('No') . '</span>';
1407 $new_user_string .= '</td>'."\n";
1408 $new_user_string .= '<td><tt>' . join(', ', PMA_extractPrivInfo('', true)) . '</tt></td>'; //Fill in privileges here
1409 $new_user_string .= '<td>';
1411 if((isset($Grant_priv) && $Grant_priv == 'Y')) {
1412 $new_user_string .= __('Yes');
1415 $new_user_string .= __('No');
1418 $new_user_string .='</td>';
1420 $new_user_string .= '<td>'.sprintf($link_edit, urlencode($username), urlencode($hostname), '', '' ).'</td>'."\n";
1421 $new_user_string .= '<td>'.sprintf($link_export, urlencode($username), urlencode($hostname), (isset($initial) ?
$initial : '')).'</td>'."\n";
1423 $new_user_string .= '</tr>';
1425 $extra_data['new_user_string'] = $new_user_string;
1428 * Generate the string for this alphabet's initial, to update the user
1431 $new_user_initial = strtoupper(substr($username, 0, 1));
1432 $new_user_initial_string = '<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . $new_user_initial
1433 .'>' . $new_user_initial . '</a>';
1434 $extra_data['new_user_initial'] = $new_user_initial;
1435 $extra_data['new_user_initial_string'] = $new_user_initial_string;
1438 if(isset($update_privs)) {
1439 $new_privileges = join(', ', PMA_extractPrivInfo('', true));
1441 $extra_data['new_privileges'] = $new_privileges;
1444 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
1448 * Displays the links
1450 if (isset($viewing_mode) && $viewing_mode == 'db') {
1452 $url_query .= '&goto=db_operations.php';
1454 // Gets the database structure
1455 $sub_part = '_structure';
1456 require './libraries/db_info.inc.php';
1459 require './libraries/server_links.inc.php';
1467 // export user definition
1468 if (isset($_REQUEST['export'])) {
1469 echo '<h2>' . __('User') . ' \'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'</h2>';
1470 echo '<textarea cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1471 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddslashes($username) . "'@'" . PMA_sqlAddslashes($hostname) . "'");
1472 foreach($grants as $one_grant) {
1473 echo $one_grant . ";\n\n";
1476 unset($username, $hostname, $grants, $one_grant);
1477 if( $GLOBALS['is_ajax_request']) {
1482 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) ||
! strlen($checkprivs))) {
1483 if (! isset($username)) {
1484 // No username is given --> display the overview
1486 . PMA_getIcon('b_usrlist.png')
1487 . __('User overview') . "\n"
1492 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1493 ' FROM `mysql`.`user`';
1495 $sql_query .= (isset($initial) ?
PMA_RangeOfUsers($initial) : '');
1497 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1498 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE
);
1501 // the query failed! This may have two reasons:
1502 // - the user does not have enough privileges
1503 // - the privilege tables use a structure of an earlier version.
1504 // so let's try a more simple query
1506 $sql_query = 'SELECT * FROM `mysql`.`user`';
1507 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE
);
1510 PMA_Message
::error(__('No Privileges'))->display();
1511 PMA_DBI_free_result($res);
1514 // This message is hardcoded because I will replace it by
1515 // a automatic repair feature soon.
1516 $raw = 'Your privilege table structure seems to be older than'
1517 . ' this MySQL version!<br />'
1518 . 'Please run the <tt>mysql_upgrade</tt> command'
1519 . '(<tt>mysql_fix_privilege_tables</tt> on older systems)'
1520 . ' that should be included in your MySQL server distribution'
1521 . ' to solve this problem!';
1522 PMA_Message
::rawError($raw)->display();
1526 // we also want users not in table `user` but in other table
1527 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1529 $tables_to_search_for_users = array(
1530 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1533 $db_rights_sqls = array();
1534 foreach ($tables_to_search_for_users as $table_search_in) {
1535 if (in_array($table_search_in, $tables)) {
1536 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ?
PMA_RangeOfUsers($initial) : '');
1540 $user_defaults = array(
1544 'Grant_priv' => 'N',
1545 'privs' => array('USAGE'),
1548 // for all initials, even non A-Z
1549 $array_initials = array();
1551 $db_rights = array();
1553 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1554 .' ORDER BY `User` ASC, `Host` ASC';
1556 $db_rights_result = PMA_DBI_query($db_rights_sql);
1558 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1559 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1560 $db_rights[$db_rights_row['User']][$db_rights_row['Host']] =
1563 PMA_DBI_free_result($db_rights_result);
1564 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1568 * Displays the initials
1569 * In an Ajax request, we don't need to show this
1572 if( $GLOBALS['is_ajax_request'] != true ) {
1574 // initialize to FALSE the letters A-Z
1575 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++
) {
1576 if (! isset($array_initials[chr($letter_counter +
64)])) {
1577 $array_initials[chr($letter_counter +
64)] = FALSE;
1581 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE
);
1582 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1583 $array_initials[$tmp_initial] = TRUE;
1586 // Display the initials, which can be any characters, not
1587 // just letters. For letters A-Z, we add the non-used letters
1590 uksort($array_initials, "strnatcasecmp");
1592 echo '<table id="initials_table" class="' . $conditional_class . '" <cellspacing="5"><tr>';
1593 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1594 if ($initial_was_found) {
1595 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1597 echo '<td>' . $tmp_initial . '</td>';
1600 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&showall=1">[' . __('Show all') . ']</a></td>' . "\n";
1601 echo '</tr></table>';
1605 * Display the user overview
1606 * (if less than 50 users, display them immediately)
1609 if (isset($initial) ||
isset($showall) ||
PMA_DBI_num_rows($res) < 50) {
1611 while ($row = PMA_DBI_fetch_assoc($res)) {
1612 $row['privs'] = PMA_extractPrivInfo($row, true);
1613 $db_rights[$row['User']][$row['Host']] = $row;
1615 @PMA_DBI_free_result
($res);
1618 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1619 . PMA_generate_common_hidden_inputs('', '')
1620 . ' <table id="tableuserrights" class="data">' . "\n"
1622 . ' <tr><th></th>' . "\n"
1623 . ' <th>' . __('User') . '</th>' . "\n"
1624 . ' <th>' . __('Host') . '</th>' . "\n"
1625 . ' <th>' . __('Password') . '</th>' . "\n"
1626 . ' <th>' . __('Global privileges') . ' '
1627 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English ')) . '</th>' . "\n"
1628 . ' <th>' . __('Grant') . '</th>' . "\n"
1629 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1630 echo ' </tr>' . "\n";
1631 echo ' </thead>' . "\n";
1632 echo ' <tbody>' . "\n";
1634 $index_checkbox = -1;
1635 foreach ($db_rights as $user) {
1638 foreach ($user as $host) {
1640 echo ' <tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
1641 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1642 . $index_checkbox . '" value="'
1643 . htmlspecialchars($host['User'] . '&#27;' . $host['Host'])
1645 . (empty($GLOBALS['checkall']) ?
'' : ' checked="checked"')
1647 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1648 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1650 switch ($host['Password']) {
1655 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1657 // this happens if this is a definition not coming from mysql.user
1659 echo '--'; // in future version, replace by "not present"
1663 . ' <td><tt>' . "\n"
1664 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1665 . ' </tt></td>' . "\n"
1666 . ' <td>' . ($host['Grant_priv'] == 'Y' ?
__('Yes') : __('No')) . '</td>' . "\n"
1667 . ' <td align="center">';
1668 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1670 echo '<td align="center">';
1671 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ?
$initial : ''));
1674 $odd_row = ! $odd_row;
1678 unset($user, $host, $odd_row);
1679 echo ' </tbody></table>' . "\n"
1680 .'<img class="selectallarrow"'
1681 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1682 .' width="38" height="22"'
1683 .' alt="' . __('With selected:') . '" />' . "\n"
1684 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&checkall=1"'
1685 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1686 . __('Check All') . '</a>' . "\n"
1688 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1689 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1690 . __('Uncheck All') . '</a>' . "\n";
1692 // add/delete user fieldset
1693 echo ' <fieldset id="fieldset_add_user">' . "\n"
1694 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1" class="' . $conditional_class . '">' . "\n"
1695 . PMA_getIcon('b_usradd.png')
1696 . ' ' . __('Add a new User') . '</a>' . "\n"
1697 . ' </fieldset>' . "\n"
1698 . ' <fieldset id="fieldset_delete_user">'
1699 . ' <legend>' . "\n"
1700 . PMA_getIcon('b_usrdrop.png')
1701 . ' ' . __('Remove selected users') . '' . "\n"
1702 . ' </legend>' . "\n"
1703 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1704 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1705 . ' <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"
1706 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1707 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1708 . ' </label>' . "\n"
1709 . ' </fieldset>' . "\n"
1710 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1711 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" class="' . $conditional_class . '"/>' . "\n"
1712 . ' </fieldset>' . "\n"
1717 echo ' <fieldset id="fieldset_add_user">' . "\n"
1718 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1">' . "\n"
1719 . PMA_getIcon('b_usradd.png')
1720 . ' ' . __('Add a new User') . '</a>' . "\n"
1721 . ' </fieldset>' . "\n";
1722 } // end if (display overview)
1724 if( $GLOBALS['is_ajax_request'] ) {
1728 $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
);
1729 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&flush_privileges=1" id="reload_privileges_anchor" class="' . $conditional_class . '">', false);
1730 $flushnote->addParam('</a>', false);
1731 $flushnote->display();
1737 // A user was selected -> display the user's properties
1739 // In an Ajax request, prevent cached values from showing
1740 if($GLOBALS['is_ajax_request'] == true) {
1741 header('Cache-Control: no-cache');
1745 . PMA_getIcon('b_usredit.png')
1746 . __('Edit Privileges') . ': '
1749 if (isset($dbname)) {
1750 echo ' <i><a href="server_privileges.php?'
1751 . $GLOBALS['url_query'] . '&username=' . htmlspecialchars(urlencode($username))
1752 . '&hostname=' . htmlspecialchars(urlencode($hostname)) . '&dbname=&tablename=">\''
1753 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1754 . '\'</a></i>' . "\n";
1755 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
1757 echo ' - ' . ($dbname_is_wildcard ?
__('Databases') : __('Database') );
1758 if (isset($tablename)) {
1759 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
1760 . '&username=' . htmlspecialchars(urlencode($username)) . '&hostname=' . htmlspecialchars(urlencode($hostname))
1761 . '&dbname=' . htmlspecialchars($url_dbname) . '&tablename=">' . htmlspecialchars($dbname) . '</a></i>';
1762 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
1764 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
1768 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1772 echo '</h2>' . "\n";
1775 $sql = "SELECT '1' FROM `mysql`.`user`"
1776 . " WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
1777 . " AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
1778 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
1780 if ($user_does_not_exists) {
1781 PMA_Message
::warning(__('The selected user was not found in the privilege table.'))->display();
1782 PMA_displayLoginInformationFields();
1783 //require './libraries/footer.inc.php';
1786 echo '<form name="usersForm" id="addUsersForm" action="server_privileges.php" method="post">' . "\n";
1788 'username' => $username,
1789 'hostname' => $hostname,
1791 if (isset($dbname)) {
1792 $_params['dbname'] = $dbname;
1793 if (isset($tablename)) {
1794 $_params['tablename'] = $tablename;
1797 echo PMA_generate_common_hidden_inputs($_params);
1799 PMA_displayPrivTable(PMA_ifSetOr($dbname, '*', 'length'),
1800 PMA_ifSetOr($tablename, '*', 'length'));
1802 echo '</form>' . "\n";
1804 if (! isset($tablename) && empty($dbname_is_wildcard)) {
1806 // no table name was given, display all table specific rights
1807 // but only if $dbname contains no wildcards
1810 echo '<form action="server_privileges.php" method="post">' . "\n"
1811 . PMA_generate_common_hidden_inputs('', '')
1812 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
1813 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1814 . '<fieldset>' . "\n"
1815 . '<legend>' . (! isset($dbname) ?
__('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
1816 . '<table class="data">' . "\n"
1818 . '<tr><th>' . (! isset($dbname) ?
__('Database') : __('Table')) . '</th>' . "\n"
1819 . ' <th>' . __('Privileges') . '</th>' . "\n"
1820 . ' <th>' . __('Grant') . '</th>' . "\n"
1821 . ' <th>' . (! isset($dbname) ?
__('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
1822 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
1827 $user_host_condition =
1829 . ' = \'' . PMA_sqlAddslashes($username) . "'"
1831 . ' = \'' . PMA_sqlAddslashes($hostname) . "'";
1836 // we also want privielgs for this user not in table `db` but in other table
1837 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1838 if (! isset($dbname)) {
1840 // no db name given, so we want all privs for the given user
1842 $tables_to_search_for_users = array(
1843 'tables_priv', 'columns_priv',
1846 $db_rights_sqls = array();
1847 foreach ($tables_to_search_for_users as $table_search_in) {
1848 if (in_array($table_search_in, $tables)) {
1849 $db_rights_sqls[] = '
1850 SELECT DISTINCT `Db`
1851 FROM `mysql`.' . PMA_backquote($table_search_in)
1852 . $user_host_condition;
1856 $user_defaults = array(
1858 'Grant_priv' => 'N',
1859 'privs' => array('USAGE'),
1860 'Table_privs' => true,
1864 $db_rights = array();
1866 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1867 .' ORDER BY `Db` ASC';
1869 $db_rights_result = PMA_DBI_query($db_rights_sql);
1871 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1872 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1873 // only Db names in the table `mysql`.`db` uses wildcards
1874 // as we are in the db specific rights display we want
1875 // all db names escaped, also from other sources
1876 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
1877 $db_rights_row['Db']);
1878 $db_rights[$db_rights_row['Db']] = $db_rights_row;
1881 PMA_DBI_free_result($db_rights_result);
1882 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1884 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
1885 $res = PMA_DBI_query($sql_query);
1888 while ($row = PMA_DBI_fetch_assoc($res)) {
1889 if (isset($db_rights[$row['Db']])) {
1890 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
1892 $db_rights[$row['Db']] = $row;
1894 // there are db specific rights for this user
1895 // so we can drop this db rights
1896 $db_rights[$row['Db']]['can_delete'] = true;
1898 PMA_DBI_free_result($res);
1903 // db name was given,
1904 // so we want all user specific rights for this db
1906 $user_host_condition .=
1908 .' LIKE \'' . PMA_sqlAddslashes($dbname) . "'";
1910 $tables_to_search_for_users = array(
1914 $db_rights_sqls = array();
1915 foreach ($tables_to_search_for_users as $table_search_in) {
1916 if (in_array($table_search_in, $tables)) {
1917 $db_rights_sqls[] = '
1918 SELECT DISTINCT `Table_name`
1919 FROM `mysql`.' . PMA_backquote($table_search_in)
1920 . $user_host_condition;
1924 $user_defaults = array(
1926 'Grant_priv' => 'N',
1927 'privs' => array('USAGE'),
1928 'Column_priv' => true,
1932 $db_rights = array();
1934 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1935 .' ORDER BY `Table_name` ASC';
1937 $db_rights_result = PMA_DBI_query($db_rights_sql);
1939 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1940 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1941 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
1943 PMA_DBI_free_result($db_rights_result);
1944 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1947 'SELECT `Table_name`,'
1949 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
1950 .' AS \'Column_priv\''
1951 .' FROM `mysql`.`tables_priv`'
1952 . $user_host_condition
1953 .' ORDER BY `Table_name` ASC;';
1954 $res = PMA_DBI_query($sql_query);
1957 while ($row = PMA_DBI_fetch_assoc($res)) {
1958 if (isset($db_rights[$row['Table_name']])) {
1959 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
1961 $db_rights[$row['Table_name']] = $row;
1964 PMA_DBI_free_result($res);
1970 if (count($db_rights) < 1) {
1971 echo '<tr class="odd">' . "\n"
1972 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
1976 $found_rows = array();
1977 //while ($row = PMA_DBI_fetch_assoc($res)) {
1978 foreach ($db_rights as $row) {
1979 $found_rows[] = (! isset($dbname)) ?
$row['Db'] : $row['Table_name'];
1981 echo '<tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
1982 . ' <td>' . htmlspecialchars((! isset($dbname)) ?
$row['Db'] : $row['Table_name']) . '</td>' . "\n"
1983 . ' <td><tt>' . "\n"
1984 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, TRUE)) . "\n"
1985 . ' </tt></td>' . "\n"
1986 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') ||
(isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ?
__('Yes') : __('No')) . '</td>' . "\n"
1988 if (! empty($row['Table_privs']) ||
! empty ($row['Column_priv'])) {
1995 printf($link_edit, htmlspecialchars(urlencode($username)),
1996 urlencode(htmlspecialchars($hostname)),
1997 urlencode((! isset($dbname)) ?
$row['Db'] : htmlspecialchars($dbname)),
1998 urlencode((! isset($dbname)) ?
'' : $row['Table_name']));
2001 if (! empty($row['can_delete']) ||
isset($row['Table_name']) && strlen($row['Table_name'])) {
2002 printf($link_revoke, htmlspecialchars(urlencode($username)),
2003 urlencode(htmlspecialchars($hostname)),
2004 urlencode((! isset($dbname)) ?
$row['Db'] : htmlspecialchars($dbname)),
2005 urlencode((! isset($dbname)) ?
'' : $row['Table_name']));
2009 $odd_row = ! $odd_row;
2013 echo '</tbody>' . "\n"
2014 . '</table>' . "\n";
2016 if (! isset($dbname)) {
2018 // no database name was given, display select db
2020 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
2022 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
2023 if (!empty($pred_db_array)) {
2024 echo ' <select name="pred_dbname" onchange="this.form.submit();">' . "\n"
2025 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2026 foreach ($pred_db_array as $current_db) {
2027 $current_db = PMA_escape_mysql_wildcards($current_db);
2028 // cannot use array_diff() once, outside of the loop,
2029 // because the list of databases has special characters
2030 // already escaped in $found_rows,
2031 // contrary to the output of SHOW DATABASES
2032 if (empty($found_rows) ||
! in_array($current_db, $found_rows)) {
2033 echo ' <option value="' . htmlspecialchars($current_db) . '">'
2034 . htmlspecialchars($current_db) . '</option>' . "\n";
2037 echo ' </select>' . "\n";
2039 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
2040 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
2042 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
2043 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
2044 if ($res = @PMA_DBI_try_query
('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE
)) {
2045 $pred_tbl_array = array();
2046 while ($row = PMA_DBI_fetch_row($res)) {
2047 if (!isset($found_rows) ||
!in_array($row[0], $found_rows)) {
2048 $pred_tbl_array[] = $row[0];
2051 PMA_DBI_free_result($res);
2053 if (!empty($pred_tbl_array)) {
2054 echo ' <select name="pred_tablename" onchange="this.form.submit();">' . "\n"
2055 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2056 foreach ($pred_tbl_array as $current_table) {
2057 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
2059 echo ' </select>' . "\n";
2064 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
2066 echo '</fieldset>' . "\n";
2067 echo '<fieldset class="tblFooters">' . "\n"
2068 . ' <input type="submit" value="' . __('Go') . '" />'
2069 . '</fieldset>' . "\n"
2074 // Provide a line with links to the relevant database and table
2075 if (isset($dbname) && empty($dbname_is_wildcard)) {
2076 echo '[ ' . __('Database')
2077 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
2078 . $GLOBALS['url_query'] . '&db=' . $url_dbname . '&reload=1">'
2079 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
2081 if (isset($tablename)) {
2082 echo ' [ ' . __('Table') . ' <a href="'
2083 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
2084 . '&db=' . $url_dbname . '&table=' . htmlspecialchars(urlencode($tablename))
2085 . '&reload=1">' . htmlspecialchars($tablename) . ': '
2086 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
2092 if (! isset($dbname) && ! $user_does_not_exists) {
2093 require_once './libraries/display_change_password.lib.php';
2095 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
2096 . PMA_generate_common_hidden_inputs('', '')
2097 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
2098 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
2099 . '<fieldset id="fieldset_change_copy_user">' . "\n"
2100 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
2101 PMA_displayLoginInformationFields('change');
2102 echo ' <fieldset>' . "\n"
2103 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2105 '4' => __('... keep the old one.'),
2106 '1' => __(' ... delete the old one from the user tables.'),
2107 '2' => __(' ... revoke all active privileges from the old one and delete it afterwards.'),
2108 '3' => __(' ... delete the old one from the user tables and reload the privileges afterwards.'));
2109 PMA_display_html_radio('mode', $choices, '4', true);
2112 echo ' </fieldset>' . "\n"
2113 . '</fieldset>' . "\n"
2114 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2115 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2116 . '</fieldset>' . "\n"
2120 } elseif (isset($_REQUEST['adduser'])) {
2123 $GLOBALS['url_query'] .= '&adduser=1';
2125 . PMA_getIcon('b_usradd.png') . __('Add a new User') . "\n"
2127 . '<form name="usersForm" id="addUsersForm" action="server_privileges.php" method="post">' . "\n"
2128 . PMA_generate_common_hidden_inputs('', '');
2129 PMA_displayLoginInformationFields('new');
2130 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2131 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2133 $default_choice = 0;
2135 '0' => _pgettext('Create none database for user', 'None'),
2136 '1' => __('Create database with same name and grant all privileges'),
2137 '2' => __('Grant all privileges on wildcard name (username\\_%)'));
2139 if ( !empty($dbname) ) {
2140 $choices['3'] = sprintf( __('Grant all privileges on database "%s"'), htmlspecialchars($dbname));
2141 $default_choice = 3;
2142 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2145 // 4th parameter set to true to add line breaks
2146 // 5th parameter set to false to avoid htmlspecialchars() escaping in the label
2147 // since we have some HTML in some labels
2148 PMA_display_html_radio('createdb', $choices, $default_choice, true, false);
2150 unset($default_choice);
2152 echo '</fieldset>' . "\n";
2153 PMA_displayPrivTable('*', '*', FALSE);
2154 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2155 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2156 . ' </fieldset>' . "\n"
2159 // check the privileges for a particular database.
2160 echo '<table id="tablespecificuserrights" class="data">' . "\n"
2161 . '<caption class="tblHeaders">' . "\n"
2162 . PMA_getIcon('b_usrcheck.png')
2163 . ' ' . sprintf(__('Users having access to "%s"'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2164 . '</caption>' . "\n"
2166 . ' <tr><th>' . __('User') . '</th>' . "\n"
2167 . ' <th>' . __('Host') . '</th>' . "\n"
2168 . ' <th>' . __('Type') . '</th>' . "\n"
2169 . ' <th>' . __('Privileges') . '</th>' . "\n"
2170 . ' <th>' . __('Grant') . '</th>' . "\n"
2171 . ' <th>' . __('Action') . '</th>' . "\n"
2176 unset($row, $row1, $row2);
2178 // now, we build the table...
2179 $list_of_privileges =
2191 . '`References_priv`, '
2192 . '`Create_tmp_table_priv`, '
2193 . '`Lock_tables_priv`, '
2194 . '`Create_view_priv`, '
2195 . '`Show_view_priv`, '
2196 . '`Create_routine_priv`, '
2197 . '`Alter_routine_priv`, '
2200 $list_of_compared_privileges =
2201 '`Select_priv` = \'N\''
2202 . ' AND `Insert_priv` = \'N\''
2203 . ' AND `Update_priv` = \'N\''
2204 . ' AND `Delete_priv` = \'N\''
2205 . ' AND `Create_priv` = \'N\''
2206 . ' AND `Drop_priv` = \'N\''
2207 . ' AND `Grant_priv` = \'N\''
2208 . ' AND `References_priv` = \'N\''
2209 . ' AND `Create_tmp_table_priv` = \'N\''
2210 . ' AND `Lock_tables_priv` = \'N\''
2211 . ' AND `Create_view_priv` = \'N\''
2212 . ' AND `Show_view_priv` = \'N\''
2213 . ' AND `Create_routine_priv` = \'N\''
2214 . ' AND `Alter_routine_priv` = \'N\''
2215 . ' AND `Execute_priv` = \'N\'';
2217 if (PMA_MYSQL_INT_VERSION
>= 50106) {
2218 $list_of_privileges .=
2221 $list_of_compared_privileges .=
2222 ' AND `Event_priv` = \'N\''
2223 . ' AND `Trigger_priv` = \'N\'';
2227 '(SELECT ' . $list_of_privileges . ', `Db`'
2228 .' FROM `mysql`.`db`'
2229 .' WHERE \'' . PMA_sqlAddslashes($checkprivs) . "'"
2231 .' AND NOT (' . $list_of_compared_privileges. ')) '
2233 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2234 .' FROM `mysql`.`user` '
2235 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2236 .' ORDER BY `User` ASC,'
2239 $res = PMA_DBI_query($sql_query);
2240 $row = PMA_DBI_fetch_assoc($res);
2247 // prepare the current user
2248 $current_privileges = array();
2249 $current_user = $row['User'];
2250 $current_host = $row['Host'];
2251 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2252 $current_privileges[] = $row;
2253 $row = PMA_DBI_fetch_assoc($res);
2255 echo ' <tr class="' . ($odd_row ?
'odd' : 'even') . '">' . "\n"
2257 if (count($current_privileges) > 1) {
2258 echo ' rowspan="' . count($current_privileges) . '"';
2260 echo '>' . (empty($current_user) ?
'<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2263 if (count($current_privileges) > 1) {
2264 echo ' rowspan="' . count($current_privileges) . '"';
2266 echo '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2267 foreach ($current_privileges as $current) {
2270 if (!isset($current['Db']) ||
$current['Db'] == '*') {
2272 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2273 echo __('database-specific');
2275 echo __('wildcard'), ': <tt>' . htmlspecialchars($current['Db']) . '</tt>';
2281 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, TRUE)) . "\n"
2285 . ' ' . ($current['Grant_priv'] == 'Y' ?
__('Yes') : __('No')) . "\n"
2288 printf($link_edit, urlencode($current_user),
2289 urlencode($current_host),
2290 urlencode(! isset($current['Db']) ||
$current['Db'] == '*' ?
'' : $current['Db']),
2295 if (empty($row) && empty($row1) && empty($row2)) {
2298 $odd_row = ! $odd_row;
2301 echo ' <tr class="odd">' . "\n"
2302 . ' <td colspan="6">' . "\n"
2303 . ' ' . __('No user found.') . "\n"
2307 echo '</tbody>' . "\n"
2308 . '</table>' . "\n";
2310 // Offer to create a new user for the current database
2311 echo '<fieldset id="fieldset_add_user">' . "\n"
2312 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&adduser=1&dbname=' . htmlspecialchars($checkprivs) .'">' . "\n"
2313 . PMA_getIcon('b_usradd.png')
2314 . ' ' . __('Add a new User') . '</a>' . "\n"
2315 . '</fieldset>' . "\n";
2317 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2321 * Displays the footer
2324 require './libraries/footer.inc.php';