Bug #3302457 - Inline edit and $cfg['PropertiesIconic']
[phpmyadmin/crack.git] / server_privileges.php
blob19effc7db66cff85048f15639df634ee3c472b74
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
5 * @package phpMyAdmin
6 */
8 /**
11 require_once './libraries/common.inc.php';
13 /**
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';
24 } else {
25 $conditional_class = '';
28 /**
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.');
68 /**
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'];
76 } else {
77 unset($tablename);
80 if (PMA_isValid($_REQUEST['pred_dbname'])) {
81 $dbname = $_REQUEST['pred_dbname'];
82 unset($pred_dbname);
83 } elseif (PMA_isValid($_REQUEST['dbname'])) {
84 $dbname = $_REQUEST['dbname'];
85 } else {
86 unset($dbname);
87 unset($tablename);
90 if (isset($dbname)) {
91 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
92 if (isset($tablename)) {
93 $db_and_table .= PMA_backquote($tablename);
94 } else {
95 $db_and_table .= '*';
97 } else {
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;
106 } else {
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';
116 echo '<h2>' . "\n"
117 . PMA_getIcon('b_usrlist.png')
118 . __('Privileges') . "\n"
119 . '</h2>' . "\n";
120 PMA_Message::error(__('No Privileges'))->display();
121 require './libraries/footer.inc.php';
124 $random_n = mt_rand(0,1000000); // a random number that will be appended to the id of the user forms
127 * Escapes wildcard in a database+table specification
128 * before using it in a GRANT statement.
130 * Escaping a wildcard character in a GRANT is only accepted at the global
131 * or database level, not at table level; this is why I remove
132 * the escaping character. Internally, in mysql.tables_priv.Db there are
133 * no escaping (for example test_db) but in mysql.db you'll see test\_db
134 * for a db-specific privilege.
136 * @param string $db_and_table
137 * @param string $dbname
138 * @param string $tablename
139 * @return string the escaped (if necessary) $db_and_table
141 function PMA_WildcardEscapeForGrant($db_and_table, $dbname, $tablename) {
143 if (! strlen($dbname)) {
144 $db_and_table = '*.*';
145 } else {
146 if (strlen($tablename)) {
147 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
148 $db_and_table .= PMA_backquote($tablename);
149 } else {
150 $db_and_table = PMA_backquote($dbname) . '.';
151 $db_and_table .= '*';
154 return $db_and_table;
158 * Generates a condition on the user name
160 * @param string the user's initial
161 * @return string the generated condition
163 function PMA_RangeOfUsers($initial = '')
165 // strtolower() is used because the User field
166 // might be BINARY, so LIKE would be case sensitive
167 if (!empty($initial)) {
168 $ret = " WHERE `User` LIKE '" . PMA_sqlAddslashes($initial) . "%'"
169 . " OR `User` LIKE '" . PMA_sqlAddslashes(strtolower($initial)) . "%'";
170 } else {
171 $ret = '';
173 return $ret;
174 } // end function
177 * Extracts the privilege information of a priv table row
179 * @param array $row the row
180 * @param boolean $enableHTML add <dfn> tag with tooltips
182 * @global resource $user_link the database connection
184 * @return array
186 function PMA_extractPrivInfo($row = '', $enableHTML = FALSE)
188 $grants = array(
189 array('Select_priv', 'SELECT', __('Allows reading data.')),
190 array('Insert_priv', 'INSERT', __('Allows inserting and replacing data.')),
191 array('Update_priv', 'UPDATE', __('Allows changing data.')),
192 array('Delete_priv', 'DELETE', __('Allows deleting data.')),
193 array('Create_priv', 'CREATE', __('Allows creating new databases and tables.')),
194 array('Drop_priv', 'DROP', __('Allows dropping databases and tables.')),
195 array('Reload_priv', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.')),
196 array('Shutdown_priv', 'SHUTDOWN', __('Allows shutting down the server.')),
197 array('Process_priv', 'PROCESS', __('Allows viewing processes of all users')),
198 array('File_priv', 'FILE', __('Allows importing data from and exporting data into files.')),
199 array('References_priv', 'REFERENCES', __('Has no effect in this MySQL version.')),
200 array('Index_priv', 'INDEX', __('Allows creating and dropping indexes.')),
201 array('Alter_priv', 'ALTER', __('Allows altering the structure of existing tables.')),
202 array('Show_db_priv', 'SHOW DATABASES', __('Gives access to the complete list of databases.')),
203 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.')),
204 array('Create_tmp_table_priv', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
205 array('Lock_tables_priv', 'LOCK TABLES', __('Allows locking tables for the current thread.')),
206 array('Repl_slave_priv', 'REPLICATION SLAVE', __('Needed for the replication slaves.')),
207 array('Repl_client_priv', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.')),
208 array('Create_view_priv', 'CREATE VIEW', __('Allows creating new views.')),
209 array('Event_priv', 'EVENT', __('Allows to set up events for the event scheduler')),
210 array('Trigger_priv', 'TRIGGER', __('Allows creating and dropping triggers')),
211 // for table privs:
212 array('Create View_priv', 'CREATE VIEW', __('Allows creating new views.')),
213 array('Show_view_priv', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
214 // for table privs:
215 array('Show view_priv', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
216 array('Create_routine_priv', 'CREATE ROUTINE', __('Allows creating stored routines.')),
217 array('Alter_routine_priv', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
218 array('Create_user_priv', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.')),
219 array('Execute_priv', 'EXECUTE', __('Allows executing stored routines.')),
222 if (!empty($row) && isset($row['Table_priv'])) {
223 $row1 = PMA_DBI_fetch_single_row(
224 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
225 'ASSOC', $GLOBALS['userlink']);
226 $av_grants = explode('\',\'', substr($row1['Type'], 5, strlen($row1['Type']) - 7));
227 unset($row1);
228 $users_grants = explode(',', $row['Table_priv']);
229 foreach ($av_grants as $current_grant) {
230 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
232 unset($current_grant);
233 unset($av_grants);
234 unset($users_grants);
236 $privs = array();
237 $allPrivileges = TRUE;
238 foreach ($grants as $current_grant) {
239 if ((!empty($row) && isset($row[$current_grant[0]]))
240 || (empty($row) && isset($GLOBALS[$current_grant[0]]))) {
241 if ((!empty($row) && $row[$current_grant[0]] == 'Y')
242 || (empty($row)
243 && ($GLOBALS[$current_grant[0]] == 'Y'
244 || (is_array($GLOBALS[$current_grant[0]])
245 && count($GLOBALS[$current_grant[0]]) == $GLOBALS['column_count']
246 && empty($GLOBALS[$current_grant[0] . '_none'])))))
248 if ($enableHTML) {
249 $privs[] = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
250 } else {
251 $privs[] = $current_grant[1];
253 } elseif (!empty($GLOBALS[$current_grant[0]])
254 && is_array($GLOBALS[$current_grant[0]])
255 && empty($GLOBALS[$current_grant[0] . '_none'])) {
256 if ($enableHTML) {
257 $priv_string = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
258 } else {
259 $priv_string = $current_grant[1];
261 $privs[] = $priv_string . ' (`' . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
262 } else {
263 $allPrivileges = FALSE;
267 if (empty($privs)) {
268 if ($enableHTML) {
269 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
270 } else {
271 $privs[] = 'USAGE';
273 } elseif ($allPrivileges && (!isset($GLOBALS['grant_count']) || count($privs) == $GLOBALS['grant_count'])) {
274 if ($enableHTML) {
275 $privs = array('<dfn title="' . __('Includes all privileges except GRANT.') . '">ALL PRIVILEGES</dfn>');
276 } else {
277 $privs = array('ALL PRIVILEGES');
280 return $privs;
281 } // end of the 'PMA_extractPrivInfo()' function
284 * Displays on which column(s) a table-specific privilege is granted
286 function PMA_display_column_privs($columns, $row, $name_for_select,
287 $priv_for_header, $name, $name_for_dfn, $name_for_current)
289 echo ' <div class="item" id="div_item_' . $name . '">' . "\n"
290 . ' <label for="select_' . $name . '_priv">' . "\n"
291 . ' <tt><dfn title="' . $name_for_dfn . '">'
292 . $priv_for_header . '</dfn></tt>' . "\n"
293 . ' </label><br />' . "\n"
294 . ' <select id="select_' . $name . '_priv" name="'
295 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
297 foreach ($columns as $current_column => $current_column_privileges) {
298 echo ' <option value="' . htmlspecialchars($current_column) . '"';
299 if ($row[$name_for_select] == 'Y' || $current_column_privileges[$name_for_current]) {
300 echo ' selected="selected"';
302 echo '>' . htmlspecialchars($current_column) . '</option>' . "\n";
305 echo ' </select>' . "\n"
306 . ' <i>' . __('Or') . '</i>' . "\n"
307 . ' <label for="checkbox_' . $name_for_select
308 . '_none"><input type="checkbox"'
309 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
310 . ' name="' . $name_for_select . '_none" id="checkbox_'
311 . $name_for_select . '_none" title="' . _pgettext('None privileges', 'None') . '" />'
312 . _pgettext('None privileges', 'None') . '</label>' . "\n"
313 . ' </div>' . "\n";
314 } // end function
318 * Displays the privileges form table
320 * @param string $db the database
321 * @param string $table the table
322 * @param boolean $submit wheather to display the submit button or not
323 * @global array $cfg the phpMyAdmin configuration
324 * @global ressource $user_link the database connection
326 * @return void
328 function PMA_displayPrivTable($db = '*', $table = '*', $submit = TRUE)
330 global $random_n;
332 if ($db == '*') {
333 $table = '*';
336 if (isset($GLOBALS['username'])) {
337 $username = $GLOBALS['username'];
338 $hostname = $GLOBALS['hostname'];
339 if ($db == '*') {
340 $sql_query =
341 "SELECT * FROM `mysql`.`user`"
342 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
343 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
344 } elseif ($table == '*') {
345 $sql_query =
346 "SELECT * FROM `mysql`.`db`"
347 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
348 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "'"
349 ." AND '" . PMA_unescape_mysql_wildcards($db) . "'"
350 ." LIKE `Db`;";
351 } else {
352 $sql_query =
353 "SELECT `Table_priv`"
354 ." FROM `mysql`.`tables_priv`"
355 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
356 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "'"
357 ." AND `Db` = '" . PMA_unescape_mysql_wildcards($db) . "'"
358 ." AND `Table_name` = '" . PMA_sqlAddslashes($table) . "';";
360 $row = PMA_DBI_fetch_single_row($sql_query);
362 if (empty($row)) {
363 if ($table == '*') {
364 if ($db == '*') {
365 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
366 } elseif ($table == '*') {
367 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
369 $res = PMA_DBI_query($sql_query);
370 while ($row1 = PMA_DBI_fetch_row($res)) {
371 if (substr($row1[0], 0, 4) == 'max_') {
372 $row[$row1[0]] = 0;
373 } else {
374 $row[$row1[0]] = 'N';
377 PMA_DBI_free_result($res);
378 } else {
379 $row = array('Table_priv' => '');
382 if (isset($row['Table_priv'])) {
383 $row1 = PMA_DBI_fetch_single_row(
384 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
385 'ASSOC', $GLOBALS['userlink']);
386 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
387 // the View for Create is spelled with uppercase V
388 // the view for Show is spelled with lowercase v
389 // and there is a space between the words
391 $av_grants = explode('\',\'', substr($row1['Type'], strpos($row1['Type'], '(') + 2, strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3));
392 unset($row1);
393 $users_grants = explode(',', $row['Table_priv']);
395 foreach ($av_grants as $current_grant) {
396 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
398 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
400 // get collumns
401 $res = PMA_DBI_try_query('SHOW COLUMNS FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($db)) . '.' . PMA_backquote($table) . ';');
402 $columns = array();
403 if ($res) {
404 while ($row1 = PMA_DBI_fetch_row($res)) {
405 $columns[$row1[0]] = array(
406 'Select' => FALSE,
407 'Insert' => FALSE,
408 'Update' => FALSE,
409 'References' => FALSE
412 PMA_DBI_free_result($res);
414 unset($res, $row1);
416 // t a b l e - s p e c i f i c p r i v i l e g e s
417 if (! empty($columns)) {
418 $res = PMA_DBI_query(
419 'SELECT `Column_name`, `Column_priv`'
420 .' FROM `mysql`.`columns_priv`'
421 .' WHERE `User`'
422 .' = \'' . PMA_sqlAddslashes($username) . "'"
423 .' AND `Host`'
424 .' = \'' . PMA_sqlAddslashes($hostname) . "'"
425 .' AND `Db`'
426 .' = \'' . PMA_sqlAddslashes(PMA_unescape_mysql_wildcards($db)) . "'"
427 .' AND `Table_name`'
428 .' = \'' . PMA_sqlAddslashes($table) . '\';');
430 while ($row1 = PMA_DBI_fetch_row($res)) {
431 $row1[1] = explode(',', $row1[1]);
432 foreach ($row1[1] as $current) {
433 $columns[$row1[0]][$current] = TRUE;
436 PMA_DBI_free_result($res);
437 unset($res, $row1, $current);
439 echo '<input type="hidden" name="grant_count" value="' . count($row) . '" />' . "\n"
440 . '<input type="hidden" name="column_count" value="' . count($columns) . '" />' . "\n"
441 . '<fieldset id="fieldset_user_priv">' . "\n"
442 . ' <legend>' . __('Table-specific privileges')
443 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English '))
444 . '</legend>' . "\n";
448 // privs that are attached to a specific column
449 PMA_display_column_privs($columns, $row, 'Select_priv',
450 'SELECT', 'select', __('Allows reading data.'), 'Select');
452 PMA_display_column_privs($columns, $row, 'Insert_priv',
453 'INSERT', 'insert', __('Allows inserting and replacing data.'), 'Insert');
455 PMA_display_column_privs($columns, $row, 'Update_priv',
456 'UPDATE', 'update', __('Allows changing data.'), 'Update');
458 PMA_display_column_privs($columns, $row, 'References_priv',
459 'REFERENCES', 'references', __('Has no effect in this MySQL version.'), 'References');
461 // privs that are not attached to a specific column
463 echo ' <div class="item">' . "\n";
464 foreach ($row as $current_grant => $current_grant_value) {
465 if (in_array(substr($current_grant, 0, (strlen($current_grant) - 5)),
466 array('Select', 'Insert', 'Update', 'References'))) {
467 continue;
469 // make a substitution to match the messages variables;
470 // also we must substitute the grant we get, because we can't generate
471 // a form variable containing blanks (those would get changed to
472 // an underscore when receiving the POST)
473 if ($current_grant == 'Create View_priv') {
474 $tmp_current_grant = 'CreateView_priv';
475 $current_grant = 'Create_view_priv';
476 } elseif ($current_grant == 'Show view_priv') {
477 $tmp_current_grant = 'ShowView_priv';
478 $current_grant = 'Show_view_priv';
479 } else {
480 $tmp_current_grant = $current_grant;
483 echo ' <div class="item">' . "\n"
484 . ' <input type="checkbox"'
485 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
486 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
487 . '" value="Y" '
488 . ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
489 . 'title="';
491 echo (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
492 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
493 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl']) . '"/>' . "\n";
495 echo ' <label for="checkbox_' . $current_grant
496 . '"><tt><dfn title="'
497 . (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
498 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
499 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl'])
500 . '">' . strtoupper(substr($current_grant, 0, strlen($current_grant) - 5)) . '</dfn></tt></label>' . "\n"
501 . ' </div>' . "\n";
502 } // end foreach ()
504 echo ' </div>' . "\n";
505 // for Safari 2.0.2
506 echo ' <div class="clearfloat"></div>' . "\n";
508 } else {
510 // g l o b a l o r d b - s p e c i f i c
512 $privTable_names = array(0 => __('Data'), 1 => __('Structure'), 2 => __('Administration'));
514 // d a t a
515 $privTable[0] = array(
516 array('Select', 'SELECT', __('Allows reading data.')),
517 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
518 array('Update', 'UPDATE', __('Allows changing data.')),
519 array('Delete', 'DELETE', __('Allows deleting data.'))
521 if ($db == '*') {
522 $privTable[0][] = array('File', 'FILE', __('Allows importing data from and exporting data into files.'));
525 // s t r u c t u r e
526 $privTable[1] = array(
527 array('Create', 'CREATE', ($table == '*' ? __('Allows creating new databases and tables.') : __('Allows creating new tables.'))),
528 array('Alter', 'ALTER', __('Allows altering the structure of existing tables.')),
529 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
530 array('Drop', 'DROP', ($table == '*' ? __('Allows dropping databases and tables.') : __('Allows dropping tables.'))),
531 array('Create_tmp_table', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
532 array('Show_view', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
533 array('Create_routine', 'CREATE ROUTINE', __('Allows creating stored routines.')),
534 array('Alter_routine', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
535 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
537 // this one is for a db-specific priv: Create_view_priv
538 if (isset($row['Create_view_priv'])) {
539 $privTable[1][] = array('Create_view', 'CREATE VIEW', __('Allows creating new views.'));
541 // this one is for a table-specific priv: Create View_priv
542 if (isset($row['Create View_priv'])) {
543 $privTable[1][] = array('Create View', 'CREATE VIEW', __('Allows creating new views.'));
545 if (isset($row['Event_priv'])) {
546 // MySQL 5.1.6
547 $privTable[1][] = array('Event', 'EVENT', __('Allows to set up events for the event scheduler'));
548 $privTable[1][] = array('Trigger', 'TRIGGER', __('Allows creating and dropping triggers'));
551 // a d m i n i s t r a t i o n
552 $privTable[2] = array(
553 array('Grant', 'GRANT', __('Allows adding users and privileges without reloading the privilege tables.')),
555 if ($db == '*') {
556 $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.'));
557 $privTable[2][] = array('Process', 'PROCESS', __('Allows viewing processes of all users'));
558 $privTable[2][] = array('Reload', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.'));
559 $privTable[2][] = array('Shutdown', 'SHUTDOWN', __('Allows shutting down the server.'));
560 $privTable[2][] = array('Show_db', 'SHOW DATABASES', __('Gives access to the complete list of databases.'));
562 $privTable[2][] = array('Lock_tables', 'LOCK TABLES', __('Allows locking tables for the current thread.'));
563 $privTable[2][] = array('References', 'REFERENCES', __('Has no effect in this MySQL version.'));
564 if ($db == '*') {
565 $privTable[2][] = array('Repl_client', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.'));
566 $privTable[2][] = array('Repl_slave', 'REPLICATION SLAVE', __('Needed for the replication slaves.'));
567 $privTable[2][] = array('Create_user', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.'));
569 echo '<input type="hidden" name="grant_count" value="'
570 . (count($privTable[0]) + count($privTable[1]) + count($privTable[2]) - (isset($row['Grant_priv']) ? 1 : 0))
571 . '" />' . "\n"
572 . '<fieldset id="fieldset_user_global_rights">' . "\n"
573 . ' <legend>' . "\n"
574 . ' '
575 . ($db == '*'
576 ? __('Global privileges')
577 : ($table == '*'
578 ? __('Database-specific privileges')
579 : __('Table-specific privileges'))) . "\n"
580 . ' (<a href="server_privileges.php?'
581 . $GLOBALS['url_query'] . '&amp;checkall=1" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', true); return false;">'
582 . __('Check All') . '</a> /' . "\n"
583 . ' <a href="server_privileges.php?'
584 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', false); return false;">'
585 . __('Uncheck All') . '</a>)' . "\n"
586 . ' </legend>' . "\n"
587 . ' <p><small><i>' . __(' Note: MySQL privilege names are expressed in English ') . '</i></small></p>' . "\n";
589 // Output the Global privilege tables with checkboxes
590 foreach($privTable as $i => $table) {
591 echo ' <fieldset>' . "\n"
592 . ' <legend>' . __($privTable_names[$i]) . '</legend>' . "\n";
593 foreach ($table as $priv)
595 echo ' <div class="item">' . "\n"
596 . ' <input type="checkbox"'
597 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0] . '_priv"'
598 . ' value="Y" title="' . $priv[2] . '"'
599 . ((!empty($GLOBALS['checkall']) || $row[$priv[0] . '_priv'] == 'Y') ? ' checked="checked"' : '')
600 . '/>' . "\n"
601 . ' <label for="checkbox_' . $priv[0] . '_priv"><tt><dfn title="' . $priv[2] . '">'
602 . $priv[1] . '</dfn></tt></label>' . "\n"
603 . ' </div>' . "\n";
605 echo ' </fieldset>' . "\n";
608 // The "Resource limits" box is not displayed for db-specific privs
609 if ($db == '*') {
610 echo ' <fieldset>' . "\n"
611 . ' <legend>' . __('Resource limits') . '</legend>' . "\n"
612 . ' <p><small><i>' . __('Note: Setting these options to 0 (zero) removes the limit.') . '</i></small></p>' . "\n"
613 . ' <div class="item">' . "\n"
614 . ' <label for="text_max_questions"><tt><dfn title="'
615 . __('Limits the number of queries the user may send to the server per hour.') . '">MAX QUERIES PER HOUR</dfn></tt></label>' . "\n"
616 . ' <input type="text" name="max_questions" id="text_max_questions" value="'
617 . $row['max_questions'] . '" size="11" maxlength="11" title="' . __('Limits the number of queries the user may send to the server per hour.') . '" />' . "\n"
618 . ' </div>' . "\n"
619 . ' <div class="item">' . "\n"
620 . ' <label for="text_max_updates"><tt><dfn title="'
621 . __('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"
622 . ' <input type="text" name="max_updates" id="text_max_updates" value="'
623 . $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"
624 . ' </div>' . "\n"
625 . ' <div class="item">' . "\n"
626 . ' <label for="text_max_connections"><tt><dfn title="'
627 . __('Limits the number of new connections the user may open per hour.') . '">MAX CONNECTIONS PER HOUR</dfn></tt></label>' . "\n"
628 . ' <input type="text" name="max_connections" id="text_max_connections" value="'
629 . $row['max_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of new connections the user may open per hour.') . '" />' . "\n"
630 . ' </div>' . "\n"
631 . ' <div class="item">' . "\n"
632 . ' <label for="text_max_user_connections"><tt><dfn title="'
633 . __('Limits the number of simultaneous connections the user may have.') . '">MAX USER_CONNECTIONS</dfn></tt></label>' . "\n"
634 . ' <input type="text" name="max_user_connections" id="text_max_user_connections" value="'
635 . $row['max_user_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of simultaneous connections the user may have.') . '" />' . "\n"
636 . ' </div>' . "\n"
637 . ' </fieldset>' . "\n";
639 // for Safari 2.0.2
640 echo ' <div class="clearfloat"></div>' . "\n";
642 echo '</fieldset>' . "\n";
643 if ($submit) {
644 echo '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">' . "\n"
645 . ' <input type="submit" name="update_privs" value="' . __('Go') . '" />' . "\n"
646 . '</fieldset>' . "\n";
648 } // end of the 'PMA_displayPrivTable()' function
652 * Displays the fields used by the "new user" form as well as the
653 * "change login information / copy user" form.
655 * @param string $mode are we creating a new user or are we just
656 * changing one? (allowed values: 'new', 'change')
657 * @global array $cfg the phpMyAdmin configuration
658 * @global ressource $user_link the database connection
660 * @return void
662 function PMA_displayLoginInformationFields($mode = 'new')
664 // Get user/host name lengths
665 $fields_info = PMA_DBI_get_fields('mysql', 'user');
666 $username_length = 16;
667 $hostname_length = 41;
668 foreach ($fields_info as $key => $val) {
669 if ($val['Field'] == 'User') {
670 strtok($val['Type'], '()');
671 $v = strtok('()');
672 if (is_int($v)) {
673 $username_length = $v;
675 } elseif ($val['Field'] == 'Host') {
676 strtok($val['Type'], '()');
677 $v = strtok('()');
678 if (is_int($v)) {
679 $hostname_length = $v;
683 unset($fields_info);
685 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
686 $GLOBALS['pred_username'] = 'any';
688 echo '<fieldset id="fieldset_add_user_login">' . "\n"
689 . '<legend>' . __('Login Information') . '</legend>' . "\n"
690 . '<div class="item">' . "\n"
691 . '<label for="select_pred_username">' . "\n"
692 . ' ' . __('User name') . ':' . "\n"
693 . '</label>' . "\n"
694 . '<span class="options">' . "\n"
695 . ' <select name="pred_username" id="select_pred_username" title="' . __('User name') . '"' . "\n"
696 . ' onchange="if (this.value == \'any\') { username.value = \'\'; } else if (this.value == \'userdefined\') { username.focus(); username.select(); }">' . "\n"
697 . ' <option value="any"' . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any') ? ' selected="selected"' : '') . '>' . __('Any user') . '</option>' . "\n"
698 . ' <option value="userdefined"' . ((!isset($GLOBALS['pred_username']) || $GLOBALS['pred_username'] == 'userdefined') ? ' selected="selected"' : '') . '>' . __('Use text field') . ':</option>' . "\n"
699 . ' </select>' . "\n"
700 . '</span>' . "\n"
701 . '<input type="text" name="username" maxlength="'
702 . $username_length . '" title="' . __('User name') . '"'
703 . (empty($GLOBALS['username'])
704 ? ''
705 : ' value="' . htmlspecialchars(isset($GLOBALS['new_username'])
706 ? $GLOBALS['new_username']
707 : $GLOBALS['username']) . '"')
708 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
709 . '</div>' . "\n"
710 . '<div class="item">' . "\n"
711 . '<label for="select_pred_hostname">' . "\n"
712 . ' ' . __('Host') . ':' . "\n"
713 . '</label>' . "\n"
714 . '<span class="options">' . "\n"
715 . ' <select name="pred_hostname" id="select_pred_hostname" title="' . __('Host') . '"' . "\n";
716 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
717 if (! empty($_current_user)) {
718 $thishost = str_replace("'", '', substr($_current_user, (strrpos($_current_user, '@') + 1)));
719 if ($thishost == 'localhost' || $thishost == '127.0.0.1') {
720 unset($thishost);
723 echo ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } else if (this.value == \'localhost\') { hostname.value = \'localhost\'; } '
724 . (empty($thishost) ? '' : 'else if (this.value == \'thishost\') { hostname.value = \'' . addslashes(htmlspecialchars($thishost)) . '\'; } ')
725 . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } else if (this.value == \'userdefined\') { hostname.focus(); hostname.select(); }">' . "\n";
726 unset($_current_user);
728 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
729 if (!isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
730 switch (strtolower($GLOBALS['hostname'])) {
731 case 'localhost':
732 case '127.0.0.1':
733 $GLOBALS['pred_hostname'] = 'localhost';
734 break;
735 case '%':
736 $GLOBALS['pred_hostname'] = 'any';
737 break;
738 default:
739 $GLOBALS['pred_hostname'] = 'userdefined';
740 break;
743 echo ' <option value="any"'
744 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
745 ? ' selected="selected"' : '') . '>' . __('Any host')
746 . '</option>' . "\n"
747 . ' <option value="localhost"'
748 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'localhost')
749 ? ' selected="selected"' : '') . '>' . __('Local')
750 . '</option>' . "\n";
751 if (!empty($thishost)) {
752 echo ' <option value="thishost"'
753 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'thishost')
754 ? ' selected="selected"' : '') . '>' . __('This Host')
755 . '</option>' . "\n";
757 unset($thishost);
758 echo ' <option value="hosttable"'
759 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'hosttable')
760 ? ' selected="selected"' : '') . '>' . __('Use Host Table')
761 . '</option>' . "\n"
762 . ' <option value="userdefined"'
763 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'userdefined')
764 ? ' selected="selected"' : '')
765 . '>' . __('Use text field') . ':</option>' . "\n"
766 . ' </select>' . "\n"
767 . '</span>' . "\n"
768 . '<input type="text" name="hostname" maxlength="'
769 . $hostname_length . '" value="'
770 . htmlspecialchars(isset($GLOBALS['hostname']) ? $GLOBALS['hostname'] : '')
771 . '" title="' . __('Host')
772 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
773 . PMA_showHint(__('When Host table is used, this field is ignored and values stored in Host table are used instead.'))
774 . '</div>' . "\n"
775 . '<div class="item">' . "\n"
776 . '<label for="select_pred_password">' . "\n"
777 . ' ' . __('Password') . ':' . "\n"
778 . '</label>' . "\n"
779 . '<span class="options">' . "\n"
780 . ' <select name="pred_password" id="select_pred_password" title="'
781 . __('Password') . '"' . "\n"
782 . ' onchange="if (this.value == \'none\') { pma_pw.value = \'\'; pma_pw2.value = \'\'; } else if (this.value == \'userdefined\') { pma_pw.focus(); pma_pw.select(); }">' . "\n"
783 . ($mode == 'change' ? ' <option value="keep" selected="selected">' . __('Do not change the password') . '</option>' . "\n" : '')
784 . ' <option value="none"';
785 if (isset($GLOBALS['username']) && $mode != 'change') {
786 echo ' selected="selected"';
788 echo '>' . __('No Password') . '</option>' . "\n"
789 . ' <option value="userdefined"' . (isset($GLOBALS['username']) ? '' : ' selected="selected"') . '>' . __('Use text field') . ':</option>' . "\n"
790 . ' </select>' . "\n"
791 . '</span>' . "\n"
792 . '<input type="password" id="text_pma_pw" name="pma_pw" title="' . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
793 . '</div>' . "\n"
794 . '<div class="item" id="div_element_before_generate_password">' . "\n"
795 . '<label for="text_pma_pw2">' . "\n"
796 . ' ' . __('Re-type') . ':' . "\n"
797 . '</label>' . "\n"
798 . '<span class="options">&nbsp;</span>' . "\n"
799 . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="' . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
800 . '</div>' . "\n"
801 // Generate password added here via jQuery
802 . '</fieldset>' . "\n";
803 } // end of the 'PMA_displayUserAndHostFields()' function
806 * Changes / copies a user, part I
808 if (isset($_REQUEST['change_copy'])) {
809 $user_host_condition =
810 ' WHERE `User`'
811 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
812 .' AND `Host`'
813 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\';';
814 $row = PMA_DBI_fetch_single_row('SELECT * FROM `mysql`.`user` ' . $user_host_condition);
815 if (! $row) {
816 PMA_Message::notice(__('No user found.'))->display();
817 unset($_REQUEST['change_copy']);
818 } else {
819 extract($row, EXTR_OVERWRITE);
820 // Recent MySQL versions have the field "Password" in mysql.user,
821 // so the previous extract creates $Password but this script
822 // uses $password
823 if (!isset($password) && isset($Password)) {
824 $password = $Password;
826 $queries = array();
832 * Adds a user
833 * (Changes / copies a user, part II)
835 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
836 $sql_query = '';
837 if ($pred_username == 'any') {
838 $username = '';
840 switch ($pred_hostname) {
841 case 'any':
842 $hostname = '%';
843 break;
844 case 'localhost':
845 $hostname = 'localhost';
846 break;
847 case 'hosttable':
848 $hostname = '';
849 break;
850 case 'thishost':
851 $_user_name = PMA_DBI_fetch_value('SELECT USER()');
852 $hostname = substr($_user_name, (strrpos($_user_name, '@') + 1));
853 unset($_user_name);
854 break;
856 $sql = "SELECT '1' FROM `mysql`.`user`"
857 . " WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
858 . " AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
859 if (PMA_DBI_fetch_value($sql) == 1) {
860 $message = PMA_Message::error(__('The user %s already exists!'));
861 $message->addParam('[i]\'' . $username . '\'@\'' . $hostname . '\'[/i]');
862 $_REQUEST['adduser'] = true;
863 $_add_user_error = true;
864 } else {
866 $create_user_real = 'CREATE USER \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
868 $real_sql_query =
869 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
870 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
871 if ($pred_password != 'none' && $pred_password != 'keep') {
872 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
873 $real_sql_query .= ' IDENTIFIED BY \'' . PMA_sqlAddslashes($pma_pw) . '\'';
874 if (isset($create_user_real)) {
875 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
876 $create_user_real .= ' IDENTIFIED BY \'' . PMA_sqlAddslashes($pma_pw) . '\'';
878 } else {
879 if ($pred_password == 'keep' && !empty($password)) {
880 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
881 if (isset($create_user_real)) {
882 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
885 $sql_query = $real_sql_query;
886 if (isset($create_user_real)) {
887 $create_user_show = $create_user_real;
891 * @todo similar code appears twice in this script
893 if ((isset($Grant_priv) && $Grant_priv == 'Y')
894 || (isset($max_questions) || isset($max_connections)
895 || isset($max_updates) || isset($max_user_connections))) {
896 $real_sql_query .= ' WITH';
897 $sql_query .= ' WITH';
898 if (isset($Grant_priv) && $Grant_priv == 'Y') {
899 $real_sql_query .= ' GRANT OPTION';
900 $sql_query .= ' GRANT OPTION';
902 if (isset($max_questions)) {
903 // avoid negative values
904 $max_questions = max(0, (int)$max_questions);
905 $real_sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
906 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
908 if (isset($max_connections)) {
909 $max_connections = max(0, (int)$max_connections);
910 $real_sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
911 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
913 if (isset($max_updates)) {
914 $max_updates = max(0, (int)$max_updates);
915 $real_sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
916 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
918 if (isset($max_user_connections)) {
919 $max_user_connections = max(0, (int)$max_user_connections);
920 $real_sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
921 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
924 if (isset($create_user_real)) {
925 $create_user_real .= ';';
926 $create_user_show .= ';';
928 $real_sql_query .= ';';
929 $sql_query .= ';';
930 if (empty($_REQUEST['change_copy'])) {
931 $_error = false;
933 if (isset($create_user_real)) {
934 if (! PMA_DBI_try_query($create_user_real)) {
935 $_error = true;
937 $sql_query = $create_user_show . $sql_query;
940 if ($_error || ! PMA_DBI_try_query($real_sql_query)) {
941 $_REQUEST['createdb'] = false;
942 $message = PMA_Message::rawError(PMA_DBI_getError());
943 } else {
944 $message = PMA_Message::success(__('You have added a new user.'));
947 switch (PMA_ifSetOr($_REQUEST['createdb'], '0')) {
948 case '1' :
949 // Create database with same name and grant all privileges
950 $q = 'CREATE DATABASE IF NOT EXISTS '
951 . PMA_backquote(PMA_sqlAddslashes($username)) . ';';
952 $sql_query .= $q;
953 if (! PMA_DBI_try_query($q)) {
954 $message = PMA_Message::rawError(PMA_DBI_getError());
955 break;
960 * If we are not in an Ajax request, we can't reload navigation now
962 if($GLOBALS['is_ajax_request'] != true) {
963 // this is needed in case tracking is on:
964 $GLOBALS['db'] = $username;
965 $GLOBALS['reload'] = TRUE;
966 PMA_reloadNavigation();
969 $q = 'GRANT ALL PRIVILEGES ON '
970 . PMA_backquote(PMA_sqlAddslashes($username)) . '.* TO \''
971 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
972 $sql_query .= $q;
973 if (! PMA_DBI_try_query($q)) {
974 $message = PMA_Message::rawError(PMA_DBI_getError());
976 break;
977 case '2' :
978 // Grant all privileges on wildcard name (username\_%)
979 $q = 'GRANT ALL PRIVILEGES ON '
980 . PMA_backquote(PMA_sqlAddslashes($username) . '\_%') . '.* TO \''
981 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
982 $sql_query .= $q;
983 if (! PMA_DBI_try_query($q)) {
984 $message = PMA_Message::rawError(PMA_DBI_getError());
986 break;
987 case '3' :
988 // Grant all privileges on the specified database to the new user
989 $q = 'GRANT ALL PRIVILEGES ON '
990 . PMA_backquote(PMA_sqlAddslashes($dbname)) . '.* TO \''
991 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
992 $sql_query .= $q;
993 if (! PMA_DBI_try_query($q)) {
994 $message = PMA_Message::rawError(PMA_DBI_getError());
996 break;
997 case '0' :
998 default :
999 break;
1001 } else {
1002 if (isset($create_user_real)) {
1003 $queries[] = $create_user_real;
1005 $queries[] = $real_sql_query;
1006 // we put the query containing the hidden password in
1007 // $queries_for_display, at the same position occupied
1008 // by the real query in $queries
1009 $tmp_count = count($queries);
1010 if (isset($create_user_real)) {
1011 $queries_for_display[$tmp_count - 2] = $create_user_show;
1013 $queries_for_display[$tmp_count - 1] = $sql_query;
1015 unset($res, $real_sql_query);
1021 * Changes / copies a user, part III
1023 if (isset($_REQUEST['change_copy'])) {
1024 $user_host_condition =
1025 ' WHERE `User`'
1026 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1027 .' AND `Host`'
1028 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\';';
1029 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1030 while ($row = PMA_DBI_fetch_assoc($res)) {
1031 $queries[] =
1032 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1033 .' ON ' . PMA_backquote($row['Db']) . '.*'
1034 .' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1035 . ($row['Grant_priv'] == 'Y' ? ' WITH GRANT OPTION;' : ';');
1037 PMA_DBI_free_result($res);
1038 $res = PMA_DBI_query(
1039 'SELECT `Db`, `Table_name`, `Table_priv`'
1040 .' FROM `mysql`.`tables_priv`' . $user_host_condition,
1041 $GLOBALS['userlink'], PMA_DBI_QUERY_STORE);
1042 while ($row = PMA_DBI_fetch_assoc($res)) {
1044 $res2 = PMA_DBI_QUERY(
1045 'SELECT `Column_name`, `Column_priv`'
1046 .' FROM `mysql`.`columns_priv`'
1047 .' WHERE `User`'
1048 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1049 .' AND `Host`'
1050 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\''
1051 .' AND `Db`'
1052 .' = \'' . PMA_sqlAddslashes($row['Db']) . "'"
1053 .' AND `Table_name`'
1054 .' = \'' . PMA_sqlAddslashes($row['Table_name']) . "'"
1055 .';',
1056 null, PMA_DBI_QUERY_STORE);
1058 $tmp_privs1 = PMA_extractPrivInfo($row);
1059 $tmp_privs2 = array(
1060 'Select' => array(),
1061 'Insert' => array(),
1062 'Update' => array(),
1063 'References' => array()
1066 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1067 $tmp_array = explode(',', $row2['Column_priv']);
1068 if (in_array('Select', $tmp_array)) {
1069 $tmp_privs2['Select'][] = $row2['Column_name'];
1071 if (in_array('Insert', $tmp_array)) {
1072 $tmp_privs2['Insert'][] = $row2['Column_name'];
1074 if (in_array('Update', $tmp_array)) {
1075 $tmp_privs2['Update'][] = $row2['Column_name'];
1077 if (in_array('References', $tmp_array)) {
1078 $tmp_privs2['References'][] = $row2['Column_name'];
1080 unset($tmp_array);
1082 if (count($tmp_privs2['Select']) > 0 && !in_array('SELECT', $tmp_privs1)) {
1083 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1085 if (count($tmp_privs2['Insert']) > 0 && !in_array('INSERT', $tmp_privs1)) {
1086 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1088 if (count($tmp_privs2['Update']) > 0 && !in_array('UPDATE', $tmp_privs1)) {
1089 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1091 if (count($tmp_privs2['References']) > 0 && !in_array('REFERENCES', $tmp_privs1)) {
1092 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1094 unset($tmp_privs2);
1095 $queries[] =
1096 'GRANT ' . join(', ', $tmp_privs1)
1097 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1098 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1099 . (in_array('Grant', explode(',', $row['Table_priv'])) ? ' WITH GRANT OPTION;' : ';');
1105 * Updates privileges
1107 if (!empty($update_privs)) {
1108 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, (isset($tablename) ? $tablename : ''));
1110 $sql_query0 =
1111 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1112 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1113 if (!isset($Grant_priv) || $Grant_priv != 'Y') {
1114 $sql_query1 =
1115 'REVOKE GRANT OPTION ON ' . $db_and_table
1116 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1117 } else {
1118 $sql_query1 = '';
1121 // Should not do a GRANT USAGE for a table-specific privilege, it
1122 // causes problems later (cannot revoke it)
1123 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1124 $sql_query2 =
1125 'GRANT ' . join(', ', PMA_extractPrivInfo())
1126 . ' ON ' . $db_and_table
1127 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
1130 * @todo similar code appears twice in this script
1132 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1133 || (! isset($dbname)
1134 && (isset($max_questions) || isset($max_connections)
1135 || isset($max_updates) || isset($max_user_connections))))
1137 $sql_query2 .= 'WITH';
1138 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1139 $sql_query2 .= ' GRANT OPTION';
1141 if (isset($max_questions)) {
1142 $max_questions = max(0, (int)$max_questions);
1143 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1145 if (isset($max_connections)) {
1146 $max_connections = max(0, (int)$max_connections);
1147 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1149 if (isset($max_updates)) {
1150 $max_updates = max(0, (int)$max_updates);
1151 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1153 if (isset($max_user_connections)) {
1154 $max_user_connections = max(0, (int)$max_user_connections);
1155 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1158 $sql_query2 .= ';';
1160 if (! PMA_DBI_query($sql_query0)) {
1161 // This might fail when the executing user does not have ALL PRIVILEGES himself.
1162 // See https://sourceforge.net/tracker/index.php?func=detail&aid=3285929&group_id=23067&atid=377408
1163 $sql_query0 = '';
1165 if (isset($sql_query1) && !PMA_DBI_try_query($sql_query1)) {
1166 // this one may fail, too...
1167 $sql_query1 = '';
1169 if (isset($sql_query2)) {
1170 PMA_DBI_query($sql_query2);
1171 } else {
1172 $sql_query2 = '';
1174 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1175 $message = PMA_Message::success(__('You have updated the privileges for %s.'));
1176 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1181 * Revokes Privileges
1183 if (isset($_REQUEST['revokeall'])) {
1184 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, isset($tablename) ? $tablename : '');
1186 $sql_query0 =
1187 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1188 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1189 $sql_query1 =
1190 'REVOKE GRANT OPTION ON ' . $db_and_table
1191 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1193 PMA_DBI_query($sql_query0);
1194 if (! PMA_DBI_try_query($sql_query1)) {
1195 // this one may fail, too...
1196 $sql_query1 = '';
1198 $sql_query = $sql_query0 . ' ' . $sql_query1;
1199 $message = PMA_Message::success(__('You have revoked the privileges for %s'));
1200 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1201 if (! isset($tablename)) {
1202 unset($dbname);
1203 } else {
1204 unset($tablename);
1210 * Updates the password
1212 if (isset($_REQUEST['change_pw'])) {
1213 // similar logic in user_password.php
1214 $message = '';
1216 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1217 if ($pma_pw != $pma_pw2) {
1218 $message = PMA_Message::error(__('The passwords aren\'t the same!'));
1219 } elseif (empty($pma_pw) || empty($pma_pw2)) {
1220 $message = PMA_Message::error(__('The password is empty!'));
1222 } // end if
1224 // here $nopass could be == 1
1225 if (empty($message)) {
1227 $hashing_function = (!empty($pw_hash) && $pw_hash == 'old' ? 'OLD_' : '')
1228 . 'PASSWORD';
1230 // in $sql_query which will be displayed, hide the password
1231 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1232 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . PMA_sqlAddslashes($pma_pw) . '\')');
1233 PMA_DBI_try_query($local_query)
1234 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, FALSE, $err_url);
1235 $message = PMA_Message::success(__('The password for %s was changed successfully.'));
1236 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1242 * Deletes users
1243 * (Changes / copies a user, part IV)
1246 if (isset($_REQUEST['delete']) || (isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1247 if (isset($_REQUEST['change_copy'])) {
1248 $selected_usr = array($old_username . '&amp;#27;' . $old_hostname);
1249 } else {
1250 $selected_usr = $_REQUEST['selected_usr'];
1251 $queries = array();
1253 foreach ($selected_usr as $each_user) {
1254 list($this_user, $this_host) = explode('&amp;#27;', $each_user);
1255 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1256 $queries[] = 'DROP USER \'' . PMA_sqlAddslashes($this_user) . '\'@\'' . PMA_sqlAddslashes($this_host) . '\';';
1258 if (isset($_REQUEST['drop_users_db'])) {
1259 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1260 $GLOBALS['reload'] = TRUE;
1262 if($GLOBALS['is_ajax_request'] != true) {
1263 PMA_reloadNavigation();
1267 if (empty($_REQUEST['change_copy'])) {
1268 if (empty($queries)) {
1269 $message = PMA_Message::error(__('No users selected for deleting!'));
1270 } else {
1271 if ($_REQUEST['mode'] == 3) {
1272 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1273 $queries[] = 'FLUSH PRIVILEGES;';
1275 $drop_user_error = '';
1276 foreach ($queries as $sql_query) {
1277 if ($sql_query{0} != '#') {
1278 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1279 $drop_user_error .= PMA_DBI_getError() . "\n";
1283 // tracking sets this, causing the deleted db to be shown in navi
1284 unset($GLOBALS['db']);
1286 $sql_query = join("\n", $queries);
1287 if (! empty($drop_user_error)) {
1288 $message = PMA_Message::rawError($drop_user_error);
1289 } else {
1290 $message = PMA_Message::success(__('The selected users have been deleted successfully.'));
1293 unset($queries);
1299 * Changes / copies a user, part V
1301 if (isset($_REQUEST['change_copy'])) {
1302 $tmp_count = 0;
1303 foreach ($queries as $sql_query) {
1304 if ($sql_query{0} != '#') {
1305 PMA_DBI_query($sql_query);
1307 // when there is a query containing a hidden password, take it
1308 // instead of the real query sent
1309 if (isset($queries_for_display[$tmp_count])) {
1310 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1312 $tmp_count++;
1314 $message = PMA_Message::success();
1315 $sql_query = join("\n", $queries);
1320 * Reloads the privilege tables into memory
1322 if (isset($_REQUEST['flush_privileges'])) {
1323 $sql_query = 'FLUSH PRIVILEGES;';
1324 PMA_DBI_query($sql_query);
1325 $message = PMA_Message::success(__('The privileges were reloaded successfully.'));
1329 * defines some standard links
1331 $link_edit = '<a class="edit_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . $GLOBALS['url_query']
1332 . '&amp;username=%s'
1333 . '&amp;hostname=%s'
1334 . '&amp;dbname=%s'
1335 . '&amp;tablename=%s">'
1336 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1337 . '</a>';
1339 $link_revoke = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1340 . '&amp;username=%s'
1341 . '&amp;hostname=%s'
1342 . '&amp;dbname=%s'
1343 . '&amp;tablename=%s'
1344 . '&amp;revokeall=1">'
1345 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1346 . '</a>';
1348 $link_export = '<a class="export_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . $GLOBALS['url_query']
1349 . '&amp;username=%s'
1350 . '&amp;hostname=%s'
1351 . '&amp;initial=%s'
1352 . '&amp;export=1">'
1353 . PMA_getIcon('b_tblexport.png', __('Export'))
1354 . '</a>';
1357 * If we are in an Ajax request for Create User/Edit User/Revoke User/Flush Privileges,
1358 * show $message and exit.
1360 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'])) {
1362 if(isset($sql_query)) {
1363 $extra_data['sql_query'] = PMA_showMessage(NULL, $sql_query);
1366 if(isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
1368 * generate html on the fly for the new user that was just created.
1370 $new_user_string = '<tr>'."\n"
1371 .'<td> <input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_" value="' . htmlspecialchars($username) . '&amp;#27;' . htmlspecialchars($hostname) . '" /> </td>'."\n"
1372 .'<td><label for="checkbox_sel_users_">' . (empty($username) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($username) ) . '</label></td>' . "\n"
1373 .'<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
1374 $new_user_string .= '<td>';
1376 if(!empty($password) || isset($pma_pw)) {
1377 $new_user_string .= __('Yes');
1379 else {
1380 $new_user_string .= '<span style="color: #FF0000">' . __('No') . '</span>';
1383 $new_user_string .= '</td>'."\n";
1384 $new_user_string .= '<td><tt>' . join(', ', PMA_extractPrivInfo('', true)) . '</tt></td>'; //Fill in privileges here
1385 $new_user_string .= '<td>';
1387 if((isset($Grant_priv) && $Grant_priv == 'Y')) {
1388 $new_user_string .= __('Yes');
1390 else {
1391 $new_user_string .= __('No');
1394 $new_user_string .='</td>';
1396 $new_user_string .= '<td>'.sprintf($link_edit, urlencode($username), urlencode($hostname), '', '' ).'</td>'."\n";
1397 $new_user_string .= '<td>'.sprintf($link_export, urlencode($username), urlencode($hostname), (isset($initial) ? $initial : '')).'</td>'."\n";
1399 $new_user_string .= '</tr>';
1401 $extra_data['new_user_string'] = $new_user_string;
1404 * Generate the string for this alphabet's initial, to update the user
1405 * pagination
1407 $new_user_initial = strtoupper(substr($username, 0, 1));
1408 $new_user_initial_string = '<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . $new_user_initial
1409 .'">' . $new_user_initial . '</a>';
1410 $extra_data['new_user_initial'] = $new_user_initial;
1411 $extra_data['new_user_initial_string'] = $new_user_initial_string;
1414 if(isset($update_privs)) {
1415 $extra_data['db_specific_privs'] = false;
1416 if (isset($dbname_is_wildcard)) {
1417 $extra_data['db_specific_privs'] = !$dbname_is_wildcard;
1419 $new_privileges = join(', ', PMA_extractPrivInfo('', true));
1421 $extra_data['new_privileges'] = $new_privileges;
1424 if ($message instanceof PMA_Message) {
1425 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
1430 * Displays the links
1432 if (isset($viewing_mode) && $viewing_mode == 'db') {
1433 $db = $checkprivs;
1434 $url_query .= '&amp;goto=db_operations.php';
1436 // Gets the database structure
1437 $sub_part = '_structure';
1438 require './libraries/db_info.inc.php';
1439 echo "\n";
1440 } else {
1441 require './libraries/server_links.inc.php';
1446 * Displays the page
1449 // export user definition
1450 if (isset($_REQUEST['export'])) {
1451 echo '<h2>' . __('User') . ' \'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'</h2>';
1452 echo '<textarea cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1453 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddslashes($username) . "'@'" . PMA_sqlAddslashes($hostname) . "'");
1454 foreach($grants as $one_grant) {
1455 echo $one_grant . ";\n\n";
1457 echo '</textarea>';
1458 unset($username, $hostname, $grants, $one_grant);
1459 if( $GLOBALS['is_ajax_request']) {
1460 exit;
1464 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs))) {
1465 if (! isset($username)) {
1466 // No username is given --> display the overview
1467 echo '<h2>' . "\n"
1468 . PMA_getIcon('b_usrlist.png')
1469 . __('User overview') . "\n"
1470 . '</h2>' . "\n";
1472 $sql_query =
1473 'SELECT *,' .
1474 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1475 ' FROM `mysql`.`user`';
1477 $sql_query .= (isset($initial) ? PMA_RangeOfUsers($initial) : '');
1479 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1480 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1482 if (! $res) {
1483 // the query failed! This may have two reasons:
1484 // - the user does not have enough privileges
1485 // - the privilege tables use a structure of an earlier version.
1486 // so let's try a more simple query
1488 $sql_query = 'SELECT * FROM `mysql`.`user`';
1489 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1491 if (!$res) {
1492 PMA_Message::error(__('No Privileges'))->display();
1493 PMA_DBI_free_result($res);
1494 unset($res);
1495 } else {
1496 // This message is hardcoded because I will replace it by
1497 // a automatic repair feature soon.
1498 $raw = 'Your privilege table structure seems to be older than'
1499 . ' this MySQL version!<br />'
1500 . 'Please run the <tt>mysql_upgrade</tt> command'
1501 . '(<tt>mysql_fix_privilege_tables</tt> on older systems)'
1502 . ' that should be included in your MySQL server distribution'
1503 . ' to solve this problem!';
1504 PMA_Message::rawError($raw)->display();
1506 } else {
1508 // we also want users not in table `user` but in other table
1509 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1511 $tables_to_search_for_users = array(
1512 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1515 $db_rights_sqls = array();
1516 foreach ($tables_to_search_for_users as $table_search_in) {
1517 if (in_array($table_search_in, $tables)) {
1518 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ? PMA_RangeOfUsers($initial) : '');
1522 $user_defaults = array(
1523 'User' => '',
1524 'Host' => '%',
1525 'Password' => '?',
1526 'Grant_priv' => 'N',
1527 'privs' => array('USAGE'),
1530 // for all initials, even non A-Z
1531 $array_initials = array();
1532 // for the rights
1533 $db_rights = array();
1535 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1536 .' ORDER BY `User` ASC, `Host` ASC';
1538 $db_rights_result = PMA_DBI_query($db_rights_sql);
1540 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1541 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1542 $db_rights[$db_rights_row['User']][$db_rights_row['Host']] =
1543 $db_rights_row;
1545 PMA_DBI_free_result($db_rights_result);
1546 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1547 ksort($db_rights);
1550 * Displays the initials
1551 * In an Ajax request, we don't need to show this
1554 if( $GLOBALS['is_ajax_request'] != true ) {
1556 // initialize to FALSE the letters A-Z
1557 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++) {
1558 if (! isset($array_initials[chr($letter_counter + 64)])) {
1559 $array_initials[chr($letter_counter + 64)] = FALSE;
1563 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE);
1564 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1565 $array_initials[$tmp_initial] = TRUE;
1568 // Display the initials, which can be any characters, not
1569 // just letters. For letters A-Z, we add the non-used letters
1570 // as greyed out.
1572 uksort($array_initials, "strnatcasecmp");
1574 echo '<table id="initials_table" class="' . $conditional_class . '" <cellspacing="5"><tr>';
1575 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1576 if ($initial_was_found) {
1577 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1578 } else {
1579 echo '<td>' . $tmp_initial . '</td>';
1582 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;showall=1">[' . __('Show all') . ']</a></td>' . "\n";
1583 echo '</tr></table>';
1587 * Display the user overview
1588 * (if less than 50 users, display them immediately)
1591 if (isset($initial) || isset($showall) || PMA_DBI_num_rows($res) < 50) {
1593 while ($row = PMA_DBI_fetch_assoc($res)) {
1594 $row['privs'] = PMA_extractPrivInfo($row, true);
1595 $db_rights[$row['User']][$row['Host']] = $row;
1597 @PMA_DBI_free_result($res);
1598 unset($res);
1600 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1601 . PMA_generate_common_hidden_inputs('', '')
1602 . ' <table id="tableuserrights" class="data">' . "\n"
1603 . ' <thead>' . "\n"
1604 . ' <tr><th></th>' . "\n"
1605 . ' <th>' . __('User') . '</th>' . "\n"
1606 . ' <th>' . __('Host') . '</th>' . "\n"
1607 . ' <th>' . __('Password') . '</th>' . "\n"
1608 . ' <th>' . __('Global privileges') . ' '
1609 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English ')) . '</th>' . "\n"
1610 . ' <th>' . __('Grant') . '</th>' . "\n"
1611 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1612 echo ' </tr>' . "\n";
1613 echo ' </thead>' . "\n";
1614 echo ' <tbody>' . "\n";
1615 $odd_row = true;
1616 $index_checkbox = -1;
1617 foreach ($db_rights as $user) {
1618 $index_checkbox++;
1619 ksort($user);
1620 foreach ($user as $host) {
1621 $index_checkbox++;
1622 echo ' <tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
1623 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1624 . $index_checkbox . '" value="'
1625 . htmlspecialchars($host['User'] . '&amp;#27;' . $host['Host'])
1626 . '"'
1627 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
1628 . ' /></td>' . "\n"
1629 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1630 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1631 echo ' <td>';
1632 switch ($host['Password']) {
1633 case 'Y':
1634 echo __('Yes');
1635 break;
1636 case 'N':
1637 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1638 break;
1639 // this happens if this is a definition not coming from mysql.user
1640 default:
1641 echo '--'; // in future version, replace by "not present"
1642 break;
1643 } // end switch
1644 echo '</td>' . "\n"
1645 . ' <td><tt>' . "\n"
1646 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1647 . ' </tt></td>' . "\n"
1648 . ' <td>' . ($host['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . '</td>' . "\n"
1649 . ' <td align="center">';
1650 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1651 echo '</td>';
1652 echo '<td align="center">';
1653 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ? $initial : ''));
1654 echo '</td>';
1655 echo '</tr>';
1656 $odd_row = ! $odd_row;
1660 unset($user, $host, $odd_row);
1661 echo ' </tbody></table>' . "\n"
1662 .'<img class="selectallarrow"'
1663 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1664 .' width="38" height="22"'
1665 .' alt="' . __('With selected:') . '" />' . "\n"
1666 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;checkall=1"'
1667 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1668 . __('Check All') . '</a>' . "\n"
1669 .'/' . "\n"
1670 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1671 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1672 . __('Uncheck All') . '</a>' . "\n";
1674 // add/delete user fieldset
1675 echo ' <fieldset id="fieldset_add_user">' . "\n"
1676 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1677 . PMA_getIcon('b_usradd.png')
1678 . ' ' . __('Add a new User') . '</a>' . "\n"
1679 . ' </fieldset>' . "\n"
1680 . ' <fieldset id="fieldset_delete_user">'
1681 . ' <legend>' . "\n"
1682 . PMA_getIcon('b_usrdrop.png')
1683 . ' ' . __('Remove selected users') . '' . "\n"
1684 . ' </legend>' . "\n"
1685 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1686 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1687 . ' <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"
1688 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1689 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1690 . ' </label>' . "\n"
1691 . ' </fieldset>' . "\n"
1692 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1693 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" class="' . $conditional_class . '"/>' . "\n"
1694 . ' </fieldset>' . "\n"
1695 . '</form>' . "\n";
1696 } else {
1698 unset ($row);
1699 echo ' <fieldset id="fieldset_add_user">' . "\n"
1700 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1">' . "\n"
1701 . PMA_getIcon('b_usradd.png')
1702 . ' ' . __('Add a new User') . '</a>' . "\n"
1703 . ' </fieldset>' . "\n";
1704 } // end if (display overview)
1706 if( $GLOBALS['is_ajax_request'] ) {
1707 exit;
1710 $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);
1711 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;flush_privileges=1" id="reload_privileges_anchor" class="' . $conditional_class . '">', false);
1712 $flushnote->addParam('</a>', false);
1713 $flushnote->display();
1717 } else {
1719 // A user was selected -> display the user's properties
1721 // In an Ajax request, prevent cached values from showing
1722 if($GLOBALS['is_ajax_request'] == true) {
1723 header('Cache-Control: no-cache');
1726 echo '<h2>' . "\n"
1727 . PMA_getIcon('b_usredit.png')
1728 . __('Edit Privileges') . ': '
1729 . __('User') ;
1731 if (isset($dbname)) {
1732 echo ' <i><a href="server_privileges.php?'
1733 . $GLOBALS['url_query'] . '&amp;username=' . htmlspecialchars(urlencode($username))
1734 . '&amp;hostname=' . htmlspecialchars(urlencode($hostname)) . '&amp;dbname=&amp;tablename=">\''
1735 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1736 . '\'</a></i>' . "\n";
1737 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
1739 echo ' - ' . ($dbname_is_wildcard ? __('Databases') : __('Database') );
1740 if (isset($tablename)) {
1741 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
1742 . '&amp;username=' . htmlspecialchars(urlencode($username)) . '&amp;hostname=' . htmlspecialchars(urlencode($hostname))
1743 . '&amp;dbname=' . htmlspecialchars($url_dbname) . '&amp;tablename=">' . htmlspecialchars($dbname) . '</a></i>';
1744 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
1745 } else {
1746 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
1749 } else {
1750 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1751 . '\'</i>' . "\n";
1754 echo '</h2>' . "\n";
1757 $sql = "SELECT '1' FROM `mysql`.`user`"
1758 . " WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
1759 . " AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
1760 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
1761 unset($sql);
1762 if ($user_does_not_exists) {
1763 PMA_Message::error(__('The selected user was not found in the privilege table.'))->display();
1764 PMA_displayLoginInformationFields();
1765 //require './libraries/footer.inc.php';
1768 echo '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n";
1769 $_params = array(
1770 'username' => $username,
1771 'hostname' => $hostname,
1773 if (isset($dbname)) {
1774 $_params['dbname'] = $dbname;
1775 if (isset($tablename)) {
1776 $_params['tablename'] = $tablename;
1779 echo PMA_generate_common_hidden_inputs($_params);
1781 PMA_displayPrivTable(PMA_ifSetOr($dbname, '*', 'length'),
1782 PMA_ifSetOr($tablename, '*', 'length'));
1784 echo '</form>' . "\n";
1786 if (! isset($tablename) && empty($dbname_is_wildcard)) {
1788 // no table name was given, display all table specific rights
1789 // but only if $dbname contains no wildcards
1791 // table header
1792 echo '<form action="server_privileges.php" method="post">' . "\n"
1793 . PMA_generate_common_hidden_inputs('', '')
1794 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
1795 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1796 . '<fieldset>' . "\n"
1797 . '<legend>' . (! isset($dbname) ? __('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
1798 . '<table class="data">' . "\n"
1799 . '<thead>' . "\n"
1800 . '<tr><th>' . (! isset($dbname) ? __('Database') : __('Table')) . '</th>' . "\n"
1801 . ' <th>' . __('Privileges') . '</th>' . "\n"
1802 . ' <th>' . __('Grant') . '</th>' . "\n"
1803 . ' <th>' . (! isset($dbname) ? __('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
1804 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
1805 . '</tr>' . "\n"
1806 . '</thead>' . "\n"
1807 . '<tbody>' . "\n";
1809 $user_host_condition =
1810 ' WHERE `User`'
1811 . ' = \'' . PMA_sqlAddslashes($username) . "'"
1812 . ' AND `Host`'
1813 . ' = \'' . PMA_sqlAddslashes($hostname) . "'";
1815 // table body
1816 // get data
1818 // we also want privielgs for this user not in table `db` but in other table
1819 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1820 if (! isset($dbname)) {
1822 // no db name given, so we want all privs for the given user
1824 $tables_to_search_for_users = array(
1825 'tables_priv', 'columns_priv',
1828 $db_rights_sqls = array();
1829 foreach ($tables_to_search_for_users as $table_search_in) {
1830 if (in_array($table_search_in, $tables)) {
1831 $db_rights_sqls[] = '
1832 SELECT DISTINCT `Db`
1833 FROM `mysql`.' . PMA_backquote($table_search_in)
1834 . $user_host_condition;
1838 $user_defaults = array(
1839 'Db' => '',
1840 'Grant_priv' => 'N',
1841 'privs' => array('USAGE'),
1842 'Table_privs' => true,
1845 // for the rights
1846 $db_rights = array();
1848 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1849 .' ORDER BY `Db` ASC';
1851 $db_rights_result = PMA_DBI_query($db_rights_sql);
1853 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1854 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1855 // only Db names in the table `mysql`.`db` uses wildcards
1856 // as we are in the db specific rights display we want
1857 // all db names escaped, also from other sources
1858 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
1859 $db_rights_row['Db']);
1860 $db_rights[$db_rights_row['Db']] = $db_rights_row;
1863 PMA_DBI_free_result($db_rights_result);
1864 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1866 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
1867 $res = PMA_DBI_query($sql_query);
1868 $sql_query = '';
1870 while ($row = PMA_DBI_fetch_assoc($res)) {
1871 if (isset($db_rights[$row['Db']])) {
1872 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
1873 } else {
1874 $db_rights[$row['Db']] = $row;
1876 // there are db specific rights for this user
1877 // so we can drop this db rights
1878 $db_rights[$row['Db']]['can_delete'] = true;
1880 PMA_DBI_free_result($res);
1881 unset($row, $res);
1883 } else {
1885 // db name was given,
1886 // so we want all user specific rights for this db
1888 $user_host_condition .=
1889 ' AND `Db`'
1890 .' LIKE \'' . PMA_sqlAddslashes($dbname) . "'";
1892 $tables_to_search_for_users = array(
1893 'columns_priv',
1896 $db_rights_sqls = array();
1897 foreach ($tables_to_search_for_users as $table_search_in) {
1898 if (in_array($table_search_in, $tables)) {
1899 $db_rights_sqls[] = '
1900 SELECT DISTINCT `Table_name`
1901 FROM `mysql`.' . PMA_backquote($table_search_in)
1902 . $user_host_condition;
1906 $user_defaults = array(
1907 'Table_name' => '',
1908 'Grant_priv' => 'N',
1909 'privs' => array('USAGE'),
1910 'Column_priv' => true,
1913 // for the rights
1914 $db_rights = array();
1916 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1917 .' ORDER BY `Table_name` ASC';
1919 $db_rights_result = PMA_DBI_query($db_rights_sql);
1921 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1922 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1923 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
1925 PMA_DBI_free_result($db_rights_result);
1926 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1928 $sql_query =
1929 'SELECT `Table_name`,'
1930 .' `Table_priv`,'
1931 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
1932 .' AS \'Column_priv\''
1933 .' FROM `mysql`.`tables_priv`'
1934 . $user_host_condition
1935 .' ORDER BY `Table_name` ASC;';
1936 $res = PMA_DBI_query($sql_query);
1937 $sql_query = '';
1939 while ($row = PMA_DBI_fetch_assoc($res)) {
1940 if (isset($db_rights[$row['Table_name']])) {
1941 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
1942 } else {
1943 $db_rights[$row['Table_name']] = $row;
1946 PMA_DBI_free_result($res);
1947 unset($row, $res);
1949 ksort($db_rights);
1951 // display rows
1952 if (count($db_rights) < 1) {
1953 echo '<tr class="odd">' . "\n"
1954 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
1955 . '</tr>' . "\n";
1956 } else {
1957 $odd_row = true;
1958 $found_rows = array();
1959 //while ($row = PMA_DBI_fetch_assoc($res)) {
1960 foreach ($db_rights as $row) {
1961 $found_rows[] = (! isset($dbname)) ? $row['Db'] : $row['Table_name'];
1963 echo '<tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
1964 . ' <td>' . htmlspecialchars((! isset($dbname)) ? $row['Db'] : $row['Table_name']) . '</td>' . "\n"
1965 . ' <td><tt>' . "\n"
1966 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, TRUE)) . "\n"
1967 . ' </tt></td>' . "\n"
1968 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') || (isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ? __('Yes') : __('No')) . '</td>' . "\n"
1969 . ' <td>';
1970 if (! empty($row['Table_privs']) || ! empty ($row['Column_priv'])) {
1971 echo __('Yes');
1972 } else {
1973 echo __('No');
1975 echo '</td>' . "\n"
1976 . ' <td>';
1977 printf($link_edit, htmlspecialchars(urlencode($username)),
1978 urlencode(htmlspecialchars($hostname)),
1979 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
1980 urlencode((! isset($dbname)) ? '' : $row['Table_name']));
1981 echo '</td>' . "\n"
1982 . ' <td>';
1983 if (! empty($row['can_delete']) || isset($row['Table_name']) && strlen($row['Table_name'])) {
1984 printf($link_revoke, htmlspecialchars(urlencode($username)),
1985 urlencode(htmlspecialchars($hostname)),
1986 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
1987 urlencode((! isset($dbname)) ? '' : $row['Table_name']));
1989 echo '</td>' . "\n"
1990 . '</tr>' . "\n";
1991 $odd_row = ! $odd_row;
1992 } // end while
1994 unset($row);
1995 echo '</tbody>' . "\n"
1996 . '</table>' . "\n";
1998 if (! isset($dbname)) {
2000 // no database name was given, display select db
2002 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
2004 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
2005 if (!empty($pred_db_array)) {
2006 echo ' <select name="pred_dbname" onchange="this.form.submit();">' . "\n"
2007 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2008 foreach ($pred_db_array as $current_db) {
2009 $current_db = PMA_escape_mysql_wildcards($current_db);
2010 // cannot use array_diff() once, outside of the loop,
2011 // because the list of databases has special characters
2012 // already escaped in $found_rows,
2013 // contrary to the output of SHOW DATABASES
2014 if (empty($found_rows) || ! in_array($current_db, $found_rows)) {
2015 echo ' <option value="' . htmlspecialchars($current_db) . '">'
2016 . htmlspecialchars($current_db) . '</option>' . "\n";
2019 echo ' </select>' . "\n";
2021 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
2022 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
2023 } else {
2024 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
2025 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
2026 if ($res = @PMA_DBI_try_query('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE)) {
2027 $pred_tbl_array = array();
2028 while ($row = PMA_DBI_fetch_row($res)) {
2029 if (!isset($found_rows) || !in_array($row[0], $found_rows)) {
2030 $pred_tbl_array[] = $row[0];
2033 PMA_DBI_free_result($res);
2034 unset($res, $row);
2035 if (!empty($pred_tbl_array)) {
2036 echo ' <select name="pred_tablename" onchange="this.form.submit();">' . "\n"
2037 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2038 foreach ($pred_tbl_array as $current_table) {
2039 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
2041 echo ' </select>' . "\n";
2043 } else {
2044 unset($res);
2046 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
2048 echo '</fieldset>' . "\n";
2049 echo '<fieldset class="tblFooters">' . "\n"
2050 . ' <input type="submit" value="' . __('Go') . '" />'
2051 . '</fieldset>' . "\n"
2052 . '</form>' . "\n";
2056 // Provide a line with links to the relevant database and table
2057 if (isset($dbname) && empty($dbname_is_wildcard)) {
2058 echo '[ ' . __('Database')
2059 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
2060 . $GLOBALS['url_query'] . '&amp;db=' . $url_dbname . '&amp;reload=1">'
2061 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
2063 if (isset($tablename)) {
2064 echo ' [ ' . __('Table') . ' <a href="'
2065 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
2066 . '&amp;db=' . $url_dbname . '&amp;table=' . htmlspecialchars(urlencode($tablename))
2067 . '&amp;reload=1">' . htmlspecialchars($tablename) . ': '
2068 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
2069 . "</a> ]\n";
2071 unset($url_dbname);
2074 if (! isset($dbname) && ! $user_does_not_exists) {
2075 require_once './libraries/display_change_password.lib.php';
2077 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
2078 . PMA_generate_common_hidden_inputs('', '')
2079 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
2080 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
2081 . '<fieldset id="fieldset_change_copy_user">' . "\n"
2082 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
2083 PMA_displayLoginInformationFields('change');
2084 echo ' <fieldset>' . "\n"
2085 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2086 $choices = array(
2087 '4' => __('... keep the old one.'),
2088 '1' => __(' ... delete the old one from the user tables.'),
2089 '2' => __(' ... revoke all active privileges from the old one and delete it afterwards.'),
2090 '3' => __(' ... delete the old one from the user tables and reload the privileges afterwards.'));
2091 PMA_display_html_radio('mode', $choices, '4', true);
2092 unset($choices);
2094 echo ' </fieldset>' . "\n"
2095 . '</fieldset>' . "\n"
2096 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2097 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2098 . '</fieldset>' . "\n"
2099 . '</form>' . "\n";
2102 } elseif (isset($_REQUEST['adduser'])) {
2104 // Add a new user
2105 $GLOBALS['url_query'] .= '&amp;adduser=1';
2106 echo '<h2>' . "\n"
2107 . PMA_getIcon('b_usradd.png') . __('Add a new User') . "\n"
2108 . '</h2>' . "\n"
2109 . '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n"
2110 . PMA_generate_common_hidden_inputs('', '');
2111 PMA_displayLoginInformationFields('new');
2112 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2113 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2115 $default_choice = 0;
2116 $choices = array(
2117 '0' => _pgettext('Create none database for user', 'None'),
2118 '1' => __('Create database with same name and grant all privileges'),
2119 '2' => __('Grant all privileges on wildcard name (username\\_%)'));
2121 if ( !empty($dbname) ) {
2122 $choices['3'] = sprintf( __('Grant all privileges on database &quot;%s&quot;'), htmlspecialchars($dbname));
2123 $default_choice = 3;
2124 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2127 // 4th parameter set to true to add line breaks
2128 // 5th parameter set to false to avoid htmlspecialchars() escaping in the label
2129 // since we have some HTML in some labels
2130 PMA_display_html_radio('createdb', $choices, $default_choice, true, false);
2131 unset($choices);
2132 unset($default_choice);
2134 echo '</fieldset>' . "\n";
2135 PMA_displayPrivTable('*', '*', FALSE);
2136 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2137 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2138 . ' </fieldset>' . "\n"
2139 . '</form>' . "\n";
2140 } else {
2141 // check the privileges for a particular database.
2142 echo '<form id="usersForm"><table id="dbspecificuserrights" class="data">' . "\n"
2143 . '<caption class="tblHeaders">' . "\n"
2144 . PMA_getIcon('b_usrcheck.png')
2145 . ' ' . sprintf(__('Users having access to &quot;%s&quot;'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2146 . '</caption>' . "\n"
2147 . '<thead>' . "\n"
2148 . ' <tr><th>' . __('User') . '</th>' . "\n"
2149 . ' <th>' . __('Host') . '</th>' . "\n"
2150 . ' <th>' . __('Type') . '</th>' . "\n"
2151 . ' <th>' . __('Privileges') . '</th>' . "\n"
2152 . ' <th>' . __('Grant') . '</th>' . "\n"
2153 . ' <th>' . __('Action') . '</th>' . "\n"
2154 . ' </tr>' . "\n"
2155 . '</thead>' . "\n"
2156 . '<tbody>' . "\n";
2157 $odd_row = TRUE;
2158 unset($row, $row1, $row2);
2160 // now, we build the table...
2161 $list_of_privileges =
2162 '`User`, '
2163 . '`Host`, '
2164 . '`Select_priv`, '
2165 . '`Insert_priv`, '
2166 . '`Update_priv`, '
2167 . '`Delete_priv`, '
2168 . '`Create_priv`, '
2169 . '`Drop_priv`, '
2170 . '`Grant_priv`, '
2171 . '`Index_priv`, '
2172 . '`Alter_priv`, '
2173 . '`References_priv`, '
2174 . '`Create_tmp_table_priv`, '
2175 . '`Lock_tables_priv`, '
2176 . '`Create_view_priv`, '
2177 . '`Show_view_priv`, '
2178 . '`Create_routine_priv`, '
2179 . '`Alter_routine_priv`, '
2180 . '`Execute_priv`';
2182 $list_of_compared_privileges =
2183 '`Select_priv` = \'N\''
2184 . ' AND `Insert_priv` = \'N\''
2185 . ' AND `Update_priv` = \'N\''
2186 . ' AND `Delete_priv` = \'N\''
2187 . ' AND `Create_priv` = \'N\''
2188 . ' AND `Drop_priv` = \'N\''
2189 . ' AND `Grant_priv` = \'N\''
2190 . ' AND `References_priv` = \'N\''
2191 . ' AND `Create_tmp_table_priv` = \'N\''
2192 . ' AND `Lock_tables_priv` = \'N\''
2193 . ' AND `Create_view_priv` = \'N\''
2194 . ' AND `Show_view_priv` = \'N\''
2195 . ' AND `Create_routine_priv` = \'N\''
2196 . ' AND `Alter_routine_priv` = \'N\''
2197 . ' AND `Execute_priv` = \'N\'';
2199 if (PMA_MYSQL_INT_VERSION >= 50106) {
2200 $list_of_privileges .=
2201 ', `Event_priv`, '
2202 . '`Trigger_priv`';
2203 $list_of_compared_privileges .=
2204 ' AND `Event_priv` = \'N\''
2205 . ' AND `Trigger_priv` = \'N\'';
2208 $sql_query =
2209 '(SELECT ' . $list_of_privileges . ', `Db`'
2210 .' FROM `mysql`.`db`'
2211 .' WHERE \'' . PMA_sqlAddslashes($checkprivs) . "'"
2212 .' LIKE `Db`'
2213 .' AND NOT (' . $list_of_compared_privileges. ')) '
2214 .'UNION '
2215 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2216 .' FROM `mysql`.`user` '
2217 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2218 .' ORDER BY `User` ASC,'
2219 .' `Host` ASC,'
2220 .' `Db` ASC;';
2221 $res = PMA_DBI_query($sql_query);
2222 $row = PMA_DBI_fetch_assoc($res);
2223 if ($row) {
2224 $found = TRUE;
2227 if ($found) {
2228 while (TRUE) {
2229 // prepare the current user
2230 $current_privileges = array();
2231 $current_user = $row['User'];
2232 $current_host = $row['Host'];
2233 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2234 $current_privileges[] = $row;
2235 $row = PMA_DBI_fetch_assoc($res);
2237 echo ' <tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2238 . ' <td';
2239 if (count($current_privileges) > 1) {
2240 echo ' rowspan="' . count($current_privileges) . '"';
2242 echo '>' . (empty($current_user) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2243 . ' </td>' . "\n"
2244 . ' <td';
2245 if (count($current_privileges) > 1) {
2246 echo ' rowspan="' . count($current_privileges) . '"';
2248 echo '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2249 foreach ($current_privileges as $current) {
2250 echo ' <td>' . "\n"
2251 . ' ';
2252 if (!isset($current['Db']) || $current['Db'] == '*') {
2253 echo __('global');
2254 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2255 echo __('database-specific');
2256 } else {
2257 echo __('wildcard'), ': <tt>' . htmlspecialchars($current['Db']) . '</tt>';
2259 echo "\n"
2260 . ' </td>' . "\n"
2261 . ' <td>' . "\n"
2262 . ' <tt>' . "\n"
2263 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, TRUE)) . "\n"
2264 . ' </tt>' . "\n"
2265 . ' </td>' . "\n"
2266 . ' <td>' . "\n"
2267 . ' ' . ($current['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . "\n"
2268 . ' </td>' . "\n"
2269 . ' <td>' . "\n";
2270 printf($link_edit, urlencode($current_user),
2271 urlencode($current_host),
2272 urlencode(! isset($current['Db']) || $current['Db'] == '*' ? '' : $current['Db']),
2273 '');
2274 echo '</td>' . "\n"
2275 . ' </tr>' . "\n";
2277 if (empty($row) && empty($row1) && empty($row2)) {
2278 break;
2280 $odd_row = ! $odd_row;
2282 } else {
2283 echo ' <tr class="odd">' . "\n"
2284 . ' <td colspan="6">' . "\n"
2285 . ' ' . __('No user found.') . "\n"
2286 . ' </td>' . "\n"
2287 . ' </tr>' . "\n";
2289 echo '</tbody>' . "\n"
2290 . '</table></form>' . "\n";
2292 // Offer to create a new user for the current database
2293 echo '<fieldset id="fieldset_add_user">' . "\n"
2294 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1&amp;dbname=' . htmlspecialchars($checkprivs) .'">' . "\n"
2295 . PMA_getIcon('b_usradd.png')
2296 . ' ' . __('Add a new User') . '</a>' . "\n"
2297 . '</fieldset>' . "\n";
2299 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2303 * Displays the footer
2305 echo "\n\n";
2306 require './libraries/footer.inc.php';