patch #3038312 [export] JSON export
[phpmyadmin.git] / server_privileges.php
blobcd5afe75a1e204b4095d44a035ef5cb249298aa4
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'][] = 'password_generation.js';
18 require './libraries/server_common.inc.php';
20 /**
21 * Messages are built using the message name
23 $strPrivDescAllPrivileges = __('Includes all privileges except GRANT.');
24 $strPrivDescAlter = __('Allows altering the structure of existing tables.');
25 $strPrivDescAlterRoutine = __('Allows altering and dropping stored routines.');
26 $strPrivDescCreateDb = __('Allows creating new databases and tables.');
27 $strPrivDescCreateRoutine = __('Allows creating stored routines.');
28 $strPrivDescCreateTbl = __('Allows creating new tables.');
29 $strPrivDescCreateTmpTable = __('Allows creating temporary tables.');
30 $strPrivDescCreateUser = __('Allows creating, dropping and renaming user accounts.');
31 $strPrivDescCreateView = __('Allows creating new views.');
32 $strPrivDescDelete = __('Allows deleting data.');
33 $strPrivDescDropDb = __('Allows dropping databases and tables.');
34 $strPrivDescDropTbl = __('Allows dropping tables.');
35 $strPrivDescEvent = __('Allows to set up events for the event scheduler');
36 $strPrivDescExecute = __('Allows executing stored routines.');
37 $strPrivDescFile = __('Allows importing data from and exporting data into files.');
38 $strPrivDescGrant = __('Allows adding users and privileges without reloading the privilege tables.');
39 $strPrivDescIndex = __('Allows creating and dropping indexes.');
40 $strPrivDescInsert = __('Allows inserting and replacing data.');
41 $strPrivDescLockTables = __('Allows locking tables for the current thread.');
42 $strPrivDescMaxConnections = __('Limits the number of new connections the user may open per hour.');
43 $strPrivDescMaxQuestions = __('Limits the number of queries the user may send to the server per hour.');
44 $strPrivDescMaxUpdates = __('Limits the number of commands that change any table or database the user may execute per hour.');
45 $strPrivDescMaxUserConnections = __('Limits the number of simultaneous connections the user may have.');
46 $strPrivDescProcess = __('Allows viewing processes of all users');
47 $strPrivDescReferences = __('Has no effect in this MySQL version.');
48 $strPrivDescReload = __('Allows reloading server settings and flushing the server\'s caches.');
49 $strPrivDescReplClient = __('Allows the user to ask where the slaves / masters are.');
50 $strPrivDescReplSlave = __('Needed for the replication slaves.');
51 $strPrivDescSelect = __('Allows reading data.');
52 $strPrivDescShowDb = __('Gives access to the complete list of databases.');
53 $strPrivDescShowView = __('Allows performing SHOW CREATE VIEW queries.');
54 $strPrivDescShutdown = __('Allows shutting down the server.');
55 $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.');
56 $strPrivDescTrigger = __('Allows creating and dropping triggers');
57 $strPrivDescUpdate = __('Allows changing data.');
58 $strPrivDescUsage = __('No privileges.');
60 /**
61 * Checks if a dropdown box has been used for selecting a database / table
63 if (PMA_isValid($_REQUEST['pred_tablename'])) {
64 $tablename = $_REQUEST['pred_tablename'];
65 unset($pred_tablename);
66 } elseif (PMA_isValid($_REQUEST['tablename'])) {
67 $tablename = $_REQUEST['tablename'];
68 } else {
69 unset($tablename);
72 if (PMA_isValid($_REQUEST['pred_dbname'])) {
73 $dbname = $_REQUEST['pred_dbname'];
74 unset($pred_dbname);
75 } elseif (PMA_isValid($_REQUEST['dbname'])) {
76 $dbname = $_REQUEST['dbname'];
77 } else {
78 unset($dbname);
79 unset($tablename);
82 if (isset($dbname)) {
83 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
84 if (isset($tablename)) {
85 $db_and_table .= PMA_backquote($tablename);
86 } else {
87 $db_and_table .= '*';
89 } else {
90 $db_and_table = '*.*';
93 // check if given $dbname is a wildcard or not
94 if (isset($dbname)) {
95 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
96 if (preg_match('/(?<!\\\\)(?:_|%)/i', $dbname)) {
97 $dbname_is_wildcard = true;
98 } else {
99 $dbname_is_wildcard = false;
104 * Checks if the user is allowed to do what he tries to...
106 if (!$is_superuser) {
107 require './libraries/server_links.inc.php';
108 echo '<h2>' . "\n"
109 . PMA_getIcon('b_usrlist.png')
110 . __('Privileges') . "\n"
111 . '</h2>' . "\n";
112 PMA_Message::error(__('No Privileges'))->display();
113 require './libraries/footer.inc.php';
117 * Escapes wildcard in a database+table specification
118 * before using it in a GRANT statement.
120 * Escaping a wildcard character in a GRANT is only accepted at the global
121 * or database level, not at table level; this is why I remove
122 * the escaping character. Internally, in mysql.tables_priv.Db there are
123 * no escaping (for example test_db) but in mysql.db you'll see test\_db
124 * for a db-specific privilege.
126 * @param string $db_and_table
127 * @param string $dbname
128 * @param string $tablename
129 * @return string the escaped (if necessary) $db_and_table
131 function PMA_WildcardEscapeForGrant($db_and_table, $dbname, $tablename) {
133 if (! strlen($dbname)) {
134 $db_and_table = '*.*';
135 } else {
136 if (strlen($tablename)) {
137 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
138 $db_and_table .= PMA_backquote($tablename);
139 } else {
140 $db_and_table = PMA_backquote($dbname) . '.';
141 $db_and_table .= '*';
144 return $db_and_table;
148 * Generates a condition on the user name
150 * @param string the user's initial
151 * @return string the generated condition
153 function PMA_RangeOfUsers($initial = '')
155 // strtolower() is used because the User field
156 // might be BINARY, so LIKE would be case sensitive
157 if (!empty($initial)) {
158 $ret = " WHERE `User` LIKE '" . $initial . "%'"
159 . " OR `User` LIKE '" . strtolower($initial) . "%'";
160 } else {
161 $ret = '';
163 return $ret;
164 } // end function
167 * Extracts the privilege information of a priv table row
169 * @param array $row the row
170 * @param boolean $enableHTML add <dfn> tag with tooltips
172 * @global ressource $user_link the database connection
174 * @return array
176 function PMA_extractPrivInfo($row = '', $enableHTML = FALSE)
178 $grants = array(
179 array('Select_priv', 'SELECT', __('Allows reading data.')),
180 array('Insert_priv', 'INSERT', __('Allows inserting and replacing data.')),
181 array('Update_priv', 'UPDATE', __('Allows changing data.')),
182 array('Delete_priv', 'DELETE', __('Allows deleting data.')),
183 array('Create_priv', 'CREATE', __('Allows creating new databases and tables.')),
184 array('Drop_priv', 'DROP', __('Allows dropping databases and tables.')),
185 array('Reload_priv', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.')),
186 array('Shutdown_priv', 'SHUTDOWN', __('Allows shutting down the server.')),
187 array('Process_priv', 'PROCESS', __('Allows viewing processes of all users')),
188 array('File_priv', 'FILE', __('Allows importing data from and exporting data into files.')),
189 array('References_priv', 'REFERENCES', __('Has no effect in this MySQL version.')),
190 array('Index_priv', 'INDEX', __('Allows creating and dropping indexes.')),
191 array('Alter_priv', 'ALTER', __('Allows altering the structure of existing tables.')),
192 array('Show_db_priv', 'SHOW DATABASES', __('Gives access to the complete list of databases.')),
193 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.')),
194 array('Create_tmp_table_priv', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
195 array('Lock_tables_priv', 'LOCK TABLES', __('Allows locking tables for the current thread.')),
196 array('Repl_slave_priv', 'REPLICATION SLAVE', __('Needed for the replication slaves.')),
197 array('Repl_client_priv', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.')),
198 array('Create_view_priv', 'CREATE VIEW', __('Allows creating new views.')),
199 array('Event_priv', 'EVENT', __('Allows to set up events for the event scheduler')),
200 array('Trigger_priv', 'TRIGGER', __('Allows creating and dropping triggers')),
201 // for table privs:
202 array('Create View_priv', 'CREATE VIEW', __('Allows creating new views.')),
203 array('Show_view_priv', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
204 // for table privs:
205 array('Show view_priv', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
206 array('Create_routine_priv', 'CREATE ROUTINE', __('Allows creating stored routines.')),
207 array('Alter_routine_priv', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
208 array('Create_user_priv', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.')),
209 array('Execute_priv', 'EXECUTE', __('Allows executing stored routines.')),
212 if (!empty($row) && isset($row['Table_priv'])) {
213 $row1 = PMA_DBI_fetch_single_row(
214 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
215 'ASSOC', $GLOBALS['userlink']);
216 $av_grants = explode('\',\'', substr($row1['Type'], 5, strlen($row1['Type']) - 7));
217 unset($row1);
218 $users_grants = explode(',', $row['Table_priv']);
219 foreach ($av_grants as $current_grant) {
220 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
222 unset($current_grant);
223 unset($av_grants);
224 unset($users_grants);
226 $privs = array();
227 $allPrivileges = TRUE;
228 foreach ($grants as $current_grant) {
229 if ((!empty($row) && isset($row[$current_grant[0]]))
230 || (empty($row) && isset($GLOBALS[$current_grant[0]]))) {
231 if ((!empty($row) && $row[$current_grant[0]] == 'Y')
232 || (empty($row)
233 && ($GLOBALS[$current_grant[0]] == 'Y'
234 || (is_array($GLOBALS[$current_grant[0]])
235 && count($GLOBALS[$current_grant[0]]) == $GLOBALS['column_count']
236 && empty($GLOBALS[$current_grant[0] . '_none'])))))
238 if ($enableHTML) {
239 $privs[] = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
240 } else {
241 $privs[] = $current_grant[1];
243 } elseif (!empty($GLOBALS[$current_grant[0]])
244 && is_array($GLOBALS[$current_grant[0]])
245 && empty($GLOBALS[$current_grant[0] . '_none'])) {
246 if ($enableHTML) {
247 $priv_string = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
248 } else {
249 $priv_string = $current_grant[1];
251 $privs[] = $priv_string . ' (`' . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
252 } else {
253 $allPrivileges = FALSE;
257 if (empty($privs)) {
258 if ($enableHTML) {
259 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
260 } else {
261 $privs[] = 'USAGE';
263 } elseif ($allPrivileges && (!isset($GLOBALS['grant_count']) || count($privs) == $GLOBALS['grant_count'])) {
264 if ($enableHTML) {
265 $privs = array('<dfn title="' . __('Includes all privileges except GRANT.') . '">ALL PRIVILEGES</dfn>');
266 } else {
267 $privs = array('ALL PRIVILEGES');
270 return $privs;
271 } // end of the 'PMA_extractPrivInfo()' function
274 * Displays on which column(s) a table-specific privilege is granted
276 function PMA_display_column_privs($columns, $row, $name_for_select,
277 $priv_for_header, $name, $name_for_dfn, $name_for_current)
279 echo ' <div class="item" id="div_item_' . $name . '">' . "\n"
280 . ' <label for="select_' . $name . '_priv">' . "\n"
281 . ' <tt><dfn title="' . $name_for_dfn . '">'
282 . $priv_for_header . '</dfn></tt>' . "\n"
283 . ' </label><br />' . "\n"
284 . ' <select id="select_' . $name . '_priv" name="'
285 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
287 foreach ($columns as $current_column => $current_column_privileges) {
288 echo ' <option value="' . htmlspecialchars($current_column) . '"';
289 if ($row[$name_for_select] == 'Y' || $current_column_privileges[$name_for_current]) {
290 echo ' selected="selected"';
292 echo '>' . htmlspecialchars($current_column) . '</option>' . "\n";
295 echo ' </select>' . "\n"
296 . ' <i>' . __('Or') . '</i>' . "\n"
297 . ' <label for="checkbox_' . $name_for_select
298 . '_none"><input type="checkbox"'
299 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
300 . ' name="' . $name_for_select . '_none" id="checkbox_'
301 . $name_for_select . '_none" title="' . _pgettext('None privileges', 'None') . '" />'
302 . _pgettext('None privileges', 'None') . '</label>' . "\n"
303 . ' </div>' . "\n";
304 } // end function
308 * Displays the privileges form table
310 * @param string $db the database
311 * @param string $table the table
312 * @param boolean $submit wheather to display the submit button or not
313 * @global array $cfg the phpMyAdmin configuration
314 * @global ressource $user_link the database connection
316 * @return void
318 function PMA_displayPrivTable($db = '*', $table = '*', $submit = TRUE)
320 if ($db == '*') {
321 $table = '*';
324 if (isset($GLOBALS['username'])) {
325 $username = $GLOBALS['username'];
326 $hostname = $GLOBALS['hostname'];
327 if ($db == '*') {
328 $sql_query =
329 "SELECT * FROM `mysql`.`user`"
330 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
331 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
332 } elseif ($table == '*') {
333 $sql_query =
334 "SELECT * FROM `mysql`.`db`"
335 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
336 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "'"
337 ." AND '" . PMA_unescape_mysql_wildcards($db) . "'"
338 ." LIKE `Db`;";
339 } else {
340 $sql_query =
341 "SELECT `Table_priv`"
342 ." FROM `mysql`.`tables_priv`"
343 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
344 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "'"
345 ." AND `Db` = '" . PMA_unescape_mysql_wildcards($db) . "'"
346 ." AND `Table_name` = '" . PMA_sqlAddslashes($table) . "';";
348 $row = PMA_DBI_fetch_single_row($sql_query);
350 if (empty($row)) {
351 if ($table == '*') {
352 if ($db == '*') {
353 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
354 } elseif ($table == '*') {
355 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
357 $res = PMA_DBI_query($sql_query);
358 while ($row1 = PMA_DBI_fetch_row($res)) {
359 if (substr($row1[0], 0, 4) == 'max_') {
360 $row[$row1[0]] = 0;
361 } else {
362 $row[$row1[0]] = 'N';
365 PMA_DBI_free_result($res);
366 } else {
367 $row = array('Table_priv' => '');
370 if (isset($row['Table_priv'])) {
371 $row1 = PMA_DBI_fetch_single_row(
372 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
373 'ASSOC', $GLOBALS['userlink']);
374 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
375 // the View for Create is spelled with uppercase V
376 // the view for Show is spelled with lowercase v
377 // and there is a space between the words
379 $av_grants = explode('\',\'', substr($row1['Type'], strpos($row1['Type'], '(') + 2, strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3));
380 unset($row1);
381 $users_grants = explode(',', $row['Table_priv']);
383 foreach ($av_grants as $current_grant) {
384 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
386 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
388 // get collumns
389 $res = PMA_DBI_try_query('SHOW COLUMNS FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($db)) . '.' . PMA_backquote($table) . ';');
390 $columns = array();
391 if ($res) {
392 while ($row1 = PMA_DBI_fetch_row($res)) {
393 $columns[$row1[0]] = array(
394 'Select' => FALSE,
395 'Insert' => FALSE,
396 'Update' => FALSE,
397 'References' => FALSE
400 PMA_DBI_free_result($res);
402 unset($res, $row1);
404 // t a b l e - s p e c i f i c p r i v i l e g e s
405 if (! empty($columns)) {
406 $res = PMA_DBI_query(
407 'SELECT `Column_name`, `Column_priv`'
408 .' FROM `mysql`.`columns_priv`'
409 .' WHERE `User`'
410 .' = \'' . PMA_sqlAddslashes($username) . "'"
411 .' AND `Host`'
412 .' = \'' . PMA_sqlAddslashes($hostname) . "'"
413 .' AND `Db`'
414 .' = \'' . PMA_sqlAddslashes(PMA_unescape_mysql_wildcards($db)) . "'"
415 .' AND `Table_name`'
416 .' = \'' . PMA_sqlAddslashes($table) . '\';');
418 while ($row1 = PMA_DBI_fetch_row($res)) {
419 $row1[1] = explode(',', $row1[1]);
420 foreach ($row1[1] as $current) {
421 $columns[$row1[0]][$current] = TRUE;
424 PMA_DBI_free_result($res);
425 unset($res, $row1, $current);
427 echo '<input type="hidden" name="grant_count" value="' . count($row) . '" />' . "\n"
428 . '<input type="hidden" name="column_count" value="' . count($columns) . '" />' . "\n"
429 . '<fieldset id="fieldset_user_priv">' . "\n"
430 . ' <legend>' . __('Table-specific privileges')
431 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English '))
432 . '</legend>' . "\n";
436 // privs that are attached to a specific column
437 PMA_display_column_privs($columns, $row, 'Select_priv',
438 'SELECT', 'select', __('Allows reading data.'), 'Select');
440 PMA_display_column_privs($columns, $row, 'Insert_priv',
441 'INSERT', 'insert', __('Allows inserting and replacing data.'), 'Insert');
443 PMA_display_column_privs($columns, $row, 'Update_priv',
444 'UPDATE', 'update', __('Allows changing data.'), 'Update');
446 PMA_display_column_privs($columns, $row, 'References_priv',
447 'REFERENCES', 'references', __('Has no effect in this MySQL version.'), 'References');
449 // privs that are not attached to a specific column
451 echo ' <div class="item">' . "\n";
452 foreach ($row as $current_grant => $current_grant_value) {
453 if (in_array(substr($current_grant, 0, (strlen($current_grant) - 5)),
454 array('Select', 'Insert', 'Update', 'References'))) {
455 continue;
457 // make a substitution to match the messages variables;
458 // also we must substitute the grant we get, because we can't generate
459 // a form variable containing blanks (those would get changed to
460 // an underscore when receiving the POST)
461 if ($current_grant == 'Create View_priv') {
462 $tmp_current_grant = 'CreateView_priv';
463 $current_grant = 'Create_view_priv';
464 } elseif ($current_grant == 'Show view_priv') {
465 $tmp_current_grant = 'ShowView_priv';
466 $current_grant = 'Show_view_priv';
467 } else {
468 $tmp_current_grant = $current_grant;
471 echo ' <div class="item">' . "\n"
472 . ' <input type="checkbox"'
473 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
474 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
475 . '" value="Y" '
476 . ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
477 . 'title="';
479 echo (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
480 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
481 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl']) . '"/>' . "\n";
483 echo ' <label for="checkbox_' . $current_grant
484 . '"><tt><dfn title="'
485 . (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
486 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
487 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl'])
488 . '">' . strtoupper(substr($current_grant, 0, strlen($current_grant) - 5)) . '</dfn></tt></label>' . "\n"
489 . ' </div>' . "\n";
490 } // end foreach ()
492 echo ' </div>' . "\n";
493 // for Safari 2.0.2
494 echo ' <div class="clearfloat"></div>' . "\n";
496 } else {
498 // g l o b a l o r d b - s p e c i f i c
500 // d a t a
501 $privTable[0] = array(
502 array('Select', 'SELECT', __('Allows reading data.')),
503 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
504 array('Update', 'UPDATE', __('Allows changing data.')),
505 array('Delete', 'DELETE', __('Allows deleting data.'))
507 if ($db == '*') {
508 $privTable[0][] = array('File', 'FILE', __('Allows importing data from and exporting data into files.'));
511 // s t r u c t u r e
512 $privTable[1] = array(
513 array('Create', 'CREATE', ($table == '*' ? __('Allows creating new databases and tables.') : __('Allows creating new tables.'))),
514 array('Alter', 'ALTER', __('Allows altering the structure of existing tables.')),
515 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
516 array('Drop', 'DROP', ($table == '*' ? __('Allows dropping databases and tables.') : __('Allows dropping tables.'))),
517 array('Create_tmp_table', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
518 array('Show_view', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
519 array('Create_routine', 'CREATE ROUTINE', __('Allows creating stored routines.')),
520 array('Alter_routine', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
521 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
523 // this one is for a db-specific priv: Create_view_priv
524 if (isset($row['Create_view_priv'])) {
525 $privTable[1][] = array('Create_view', 'CREATE VIEW', __('Allows creating new views.'));
527 // this one is for a table-specific priv: Create View_priv
528 if (isset($row['Create View_priv'])) {
529 $privTable[1][] = array('Create View', 'CREATE VIEW', __('Allows creating new views.'));
531 if (isset($row['Event_priv'])) {
532 // MySQL 5.1.6
533 $privTable[1][] = array('Event', 'EVENT', __('Allows to set up events for the event scheduler'));
534 $privTable[1][] = array('Trigger', 'TRIGGER', __('Allows creating and dropping triggers'));
537 // a d m i n i s t r a t i o n
538 $privTable[2] = array(
539 array('Grant', 'GRANT', __('Allows adding users and privileges without reloading the privilege tables.')),
541 if ($db == '*') {
542 $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.'));
543 $privTable[2][] = array('Process', 'PROCESS', __('Allows viewing processes of all users'));
544 $privTable[2][] = array('Reload', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.'));
545 $privTable[2][] = array('Shutdown', 'SHUTDOWN', __('Allows shutting down the server.'));
546 $privTable[2][] = array('Show_db', 'SHOW DATABASES', __('Gives access to the complete list of databases.'));
548 $privTable[2][] = array('Lock_tables', 'LOCK TABLES', __('Allows locking tables for the current thread.'));
549 $privTable[2][] = array('References', 'REFERENCES', __('Has no effect in this MySQL version.'));
550 if ($db == '*') {
551 $privTable[2][] = array('Repl_client', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.'));
552 $privTable[2][] = array('Repl_slave', 'REPLICATION SLAVE', __('Needed for the replication slaves.'));
553 $privTable[2][] = array('Create_user', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.'));
555 echo '<input type="hidden" name="grant_count" value="'
556 . (count($privTable[0]) + count($privTable[1]) + count($privTable[2]) - (isset($row['Grant_priv']) ? 1 : 0))
557 . '" />' . "\n"
558 . '<fieldset id="fieldset_user_global_rights">' . "\n"
559 . ' <legend>' . "\n"
560 . ' '
561 . ($db == '*'
562 ? __('Global privileges')
563 : ($table == '*'
564 ? __('Database-specific privileges')
565 : __('Table-specific privileges'))) . "\n"
566 . ' (<a href="server_privileges.php?'
567 . $GLOBALS['url_query'] . '&amp;checkall=1" onclick="setCheckboxes(\'usersForm\', true); return false;">'
568 . __('Check All') . '</a> /' . "\n"
569 . ' <a href="server_privileges.php?'
570 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'usersForm\', false); return false;">'
571 . __('Uncheck All') . '</a>)' . "\n"
572 . ' </legend>' . "\n"
573 . ' <p><small><i>' . __(' Note: MySQL privilege names are expressed in English ') . '</i></small></p>' . "\n"
574 . ' <fieldset>' . "\n"
575 . ' <legend>' . __('Data') . '</legend>' . "\n";
576 foreach ($privTable[0] as $priv)
578 echo ' <div class="item">' . "\n"
579 . ' <input type="checkbox"'
580 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
581 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
582 . '_priv" value="Y" '
583 . ($row[$priv[0] . '_priv'] == 'Y' ? 'checked="checked" ' : '')
584 . 'title="' . $priv[2] . '"/>' . "\n"
585 . ' <label for="checkbox_' . $priv[0]
586 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
587 . '</dfn></tt></label>' . "\n"
588 . ' </div>' . "\n";
590 echo ' </fieldset>' . "\n"
591 . ' <fieldset>' . "\n"
592 . ' <legend>' . __('Structure') . '</legend>' . "\n";
593 foreach ($privTable[1] as $priv)
595 echo ' <div class="item">' . "\n"
596 . ' <input type="checkbox"'
597 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
598 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
599 . '_priv" value="Y" '
600 . ($row[$priv[0] . '_priv'] == 'Y' ? 'checked="checked" ' : '')
601 . 'title="' . $priv[2] . '"/>' . "\n"
602 . ' <label for="checkbox_' . $priv[0]
603 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
604 . '</dfn></tt></label>' . "\n"
605 . ' </div>' . "\n";
607 echo ' </fieldset>' . "\n"
608 . ' <fieldset>' . "\n"
609 . ' <legend>' . __('Administration') . '</legend>' . "\n";
610 foreach ($privTable[2] as $priv)
612 echo ' <div class="item">' . "\n"
613 . ' <input type="checkbox"'
614 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
615 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
616 . '_priv" value="Y" '
617 . ($row[$priv[0] . '_priv'] == 'Y' ? 'checked="checked" ' : '')
618 . 'title="' . $priv[2] . '"/>' . "\n"
619 . ' <label for="checkbox_' . $priv[0]
620 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
621 . '</dfn></tt></label>' . "\n"
622 . ' </div>' . "\n";
625 echo ' </fieldset>' . "\n";
626 // The "Resource limits" box is not displayed for db-specific privs
627 if ($db == '*') {
628 echo ' <fieldset>' . "\n"
629 . ' <legend>' . __('Resource limits') . '</legend>' . "\n"
630 . ' <p><small><i>' . __('Note: Setting these options to 0 (zero) removes the limit.') . '</i></small></p>' . "\n"
631 . ' <div class="item">' . "\n"
632 . ' <label for="text_max_questions"><tt><dfn title="'
633 . __('Limits the number of queries the user may send to the server per hour.') . '">MAX QUERIES PER HOUR</dfn></tt></label>' . "\n"
634 . ' <input type="text" name="max_questions" id="text_max_questions" value="'
635 . $row['max_questions'] . '" size="11" maxlength="11" title="' . __('Limits the number of queries the user may send to the server per hour.') . '" />' . "\n"
636 . ' </div>' . "\n"
637 . ' <div class="item">' . "\n"
638 . ' <label for="text_max_updates"><tt><dfn title="'
639 . __('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"
640 . ' <input type="text" name="max_updates" id="text_max_updates" value="'
641 . $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"
642 . ' </div>' . "\n"
643 . ' <div class="item">' . "\n"
644 . ' <label for="text_max_connections"><tt><dfn title="'
645 . __('Limits the number of new connections the user may open per hour.') . '">MAX CONNECTIONS PER HOUR</dfn></tt></label>' . "\n"
646 . ' <input type="text" name="max_connections" id="text_max_connections" value="'
647 . $row['max_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of new connections the user may open per hour.') . '" />' . "\n"
648 . ' </div>' . "\n"
649 . ' <div class="item">' . "\n"
650 . ' <label for="text_max_user_connections"><tt><dfn title="'
651 . __('Limits the number of simultaneous connections the user may have.') . '">MAX USER_CONNECTIONS</dfn></tt></label>' . "\n"
652 . ' <input type="text" name="max_user_connections" id="text_max_user_connections" value="'
653 . $row['max_user_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of simultaneous connections the user may have.') . '" />' . "\n"
654 . ' </div>' . "\n"
655 . ' </fieldset>' . "\n";
657 // for Safari 2.0.2
658 echo ' <div class="clearfloat"></div>' . "\n";
660 echo '</fieldset>' . "\n";
661 if ($submit) {
662 echo '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">' . "\n"
663 . ' <input type="submit" name="update_privs" value="' . __('Go') . '" />' . "\n"
664 . '</fieldset>' . "\n";
666 } // end of the 'PMA_displayPrivTable()' function
670 * Displays the fields used by the "new user" form as well as the
671 * "change login information / copy user" form.
673 * @param string $mode are we creating a new user or are we just
674 * changing one? (allowed values: 'new', 'change')
675 * @global array $cfg the phpMyAdmin configuration
676 * @global ressource $user_link the database connection
678 * @return void
680 function PMA_displayLoginInformationFields($mode = 'new')
682 // Get user/host name lengths
683 $fields_info = PMA_DBI_get_fields('mysql', 'user');
684 $username_length = 16;
685 $hostname_length = 41;
686 foreach ($fields_info as $key => $val) {
687 if ($val['Field'] == 'User') {
688 strtok($val['Type'], '()');
689 $v = strtok('()');
690 if (is_int($v)) {
691 $username_length = $v;
693 } elseif ($val['Field'] == 'Host') {
694 strtok($val['Type'], '()');
695 $v = strtok('()');
696 if (is_int($v)) {
697 $hostname_length = $v;
701 unset($fields_info);
703 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
704 $GLOBALS['pred_username'] = 'any';
706 echo '<fieldset id="fieldset_add_user_login">' . "\n"
707 . '<legend>' . __('Login Information') . '</legend>' . "\n"
708 . '<div class="item">' . "\n"
709 . '<label for="select_pred_username">' . "\n"
710 . ' ' . __('User name') . ':' . "\n"
711 . '</label>' . "\n"
712 . '<span class="options">' . "\n"
713 . ' <select name="pred_username" id="select_pred_username" title="' . __('User name') . '"' . "\n"
714 . ' onchange="if (this.value == \'any\') { username.value = \'\'; } else if (this.value == \'userdefined\') { username.focus(); username.select(); }">' . "\n"
715 . ' <option value="any"' . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any') ? ' selected="selected"' : '') . '>' . __('Any user') . '</option>' . "\n"
716 . ' <option value="userdefined"' . ((!isset($GLOBALS['pred_username']) || $GLOBALS['pred_username'] == 'userdefined') ? ' selected="selected"' : '') . '>' . __('Use text field') . ':</option>' . "\n"
717 . ' </select>' . "\n"
718 . '</span>' . "\n"
719 . '<input type="text" name="username" maxlength="'
720 . $username_length . '" title="' . __('User name') . '"'
721 . (empty($GLOBALS['username'])
722 ? ''
723 : ' value="' . htmlspecialchars(isset($GLOBALS['new_username'])
724 ? $GLOBALS['new_username']
725 : $GLOBALS['username']) . '"')
726 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
727 . '</div>' . "\n"
728 . '<div class="item">' . "\n"
729 . '<label for="select_pred_hostname">' . "\n"
730 . ' ' . __('Host') . ':' . "\n"
731 . '</label>' . "\n"
732 . '<span class="options">' . "\n"
733 . ' <select name="pred_hostname" id="select_pred_hostname" title="' . __('Host') . '"' . "\n";
734 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
735 if (! empty($_current_user)) {
736 $thishost = str_replace("'", '', substr($_current_user, (strrpos($_current_user, '@') + 1)));
737 if ($thishost == 'localhost' || $thishost == '127.0.0.1') {
738 unset($thishost);
741 echo ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } else if (this.value == \'localhost\') { hostname.value = \'localhost\'; } '
742 . (empty($thishost) ? '' : 'else if (this.value == \'thishost\') { hostname.value = \'' . addslashes(htmlspecialchars($thishost)) . '\'; } ')
743 . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } else if (this.value == \'userdefined\') { hostname.focus(); hostname.select(); }">' . "\n";
744 unset($_current_user);
746 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
747 if (!isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
748 switch (strtolower($GLOBALS['hostname'])) {
749 case 'localhost':
750 case '127.0.0.1':
751 $GLOBALS['pred_hostname'] = 'localhost';
752 break;
753 case '%':
754 $GLOBALS['pred_hostname'] = 'any';
755 break;
756 default:
757 $GLOBALS['pred_hostname'] = 'userdefined';
758 break;
761 echo ' <option value="any"'
762 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
763 ? ' selected="selected"' : '') . '>' . __('Any host')
764 . '</option>' . "\n"
765 . ' <option value="localhost"'
766 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'localhost')
767 ? ' selected="selected"' : '') . '>' . __('Local')
768 . '</option>' . "\n";
769 if (!empty($thishost)) {
770 echo ' <option value="thishost"'
771 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'thishost')
772 ? ' selected="selected"' : '') . '>' . __('This Host')
773 . '</option>' . "\n";
775 unset($thishost);
776 echo ' <option value="hosttable"'
777 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'hosttable')
778 ? ' selected="selected"' : '') . '>' . __('Use Host Table')
779 . '</option>' . "\n"
780 . ' <option value="userdefined"'
781 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'userdefined')
782 ? ' selected="selected"' : '')
783 . '>' . __('Use text field') . ':</option>' . "\n"
784 . ' </select>' . "\n"
785 . '</span>' . "\n"
786 . '<input type="text" name="hostname" maxlength="'
787 . $hostname_length . '" value="'
788 . htmlspecialchars(isset($GLOBALS['hostname']) ? $GLOBALS['hostname'] : '')
789 . '" title="' . __('Host')
790 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
791 . PMA_showHint(__('When Host table is used, this field is ignored and values stored in Host table are used instead.'))
792 . '</div>' . "\n"
793 . '<div class="item">' . "\n"
794 . '<label for="select_pred_password">' . "\n"
795 . ' ' . __('Password') . ':' . "\n"
796 . '</label>' . "\n"
797 . '<span class="options">' . "\n"
798 . ' <select name="pred_password" id="select_pred_password" title="'
799 . __('Password') . '"' . "\n"
800 . ' onchange="if (this.value == \'none\') { pma_pw.value = \'\'; pma_pw2.value = \'\'; } else if (this.value == \'userdefined\') { pma_pw.focus(); pma_pw.select(); }">' . "\n"
801 . ($mode == 'change' ? ' <option value="keep" selected="selected">' . __('Do not change the password') . '</option>' . "\n" : '')
802 . ' <option value="none"';
803 if (isset($GLOBALS['username']) && $mode != 'change') {
804 echo ' selected="selected"';
806 echo '>' . __('No Password') . '</option>' . "\n"
807 . ' <option value="userdefined"' . (isset($GLOBALS['username']) ? '' : ' selected="selected"') . '>' . __('Use text field') . ':</option>' . "\n"
808 . ' </select>' . "\n"
809 . '</span>' . "\n"
810 . '<input type="password" id="text_pma_pw" name="pma_pw" title="' . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
811 . '</div>' . "\n"
812 . '<div class="item" id="div_element_before_generate_password">' . "\n"
813 . '<label for="text_pma_pw2">' . "\n"
814 . ' ' . __('Re-type') . ':' . "\n"
815 . '</label>' . "\n"
816 . '<span class="options">&nbsp;</span>' . "\n"
817 . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="' . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
818 . '</div>' . "\n"
819 // Generate password added here via jQuery
820 . '</fieldset>' . "\n";
821 } // end of the 'PMA_displayUserAndHostFields()' function
824 * Changes / copies a user, part I
826 if (isset($_REQUEST['change_copy'])) {
827 $user_host_condition =
828 ' WHERE `User`'
829 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
830 .' AND `Host`'
831 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\';';
832 $row = PMA_DBI_fetch_single_row('SELECT * FROM `mysql`.`user` ' . $user_host_condition);
833 if (! $row) {
834 PMA_Message::notice(__('No user found.'))->display();
835 unset($_REQUEST['change_copy']);
836 } else {
837 extract($row, EXTR_OVERWRITE);
838 // Recent MySQL versions have the field "Password" in mysql.user,
839 // so the previous extract creates $Password but this script
840 // uses $password
841 if (!isset($password) && isset($Password)) {
842 $password = $Password;
844 $queries = array();
850 * Adds a user
851 * (Changes / copies a user, part II)
853 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
854 $sql_query = '';
855 if ($pred_username == 'any') {
856 $username = '';
858 switch ($pred_hostname) {
859 case 'any':
860 $hostname = '%';
861 break;
862 case 'localhost':
863 $hostname = 'localhost';
864 break;
865 case 'hosttable':
866 $hostname = '';
867 break;
868 case 'thishost':
869 $_user_name = PMA_DBI_fetch_value('SELECT USER()');
870 $hostname = substr($_user_name, (strrpos($_user_name, '@') + 1));
871 unset($_user_name);
872 break;
874 $sql = "SELECT '1' FROM `mysql`.`user`"
875 . " WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
876 . " AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
877 if (PMA_DBI_fetch_value($sql) == 1) {
878 $message = PMA_Message::error(__('The user %s already exists!'));
879 $message->addParam('[i]\'' . $username . '\'@\'' . $hostname . '\'[/i]');
880 $_REQUEST['adduser'] = true;
881 } else {
883 $create_user_real = 'CREATE USER \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
885 $real_sql_query =
886 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
887 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
888 if ($pred_password != 'none' && $pred_password != 'keep') {
889 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
890 $real_sql_query .= ' IDENTIFIED BY \'' . PMA_sqlAddslashes($pma_pw) . '\'';
891 if (isset($create_user_real)) {
892 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
893 $create_user_real .= ' IDENTIFIED BY \'' . PMA_sqlAddslashes($pma_pw) . '\'';
895 } else {
896 if ($pred_password == 'keep' && !empty($password)) {
897 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
898 if (isset($create_user_real)) {
899 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
902 $sql_query = $real_sql_query;
903 if (isset($create_user_real)) {
904 $create_user_show = $create_user_real;
908 * @todo similar code appears twice in this script
910 if ((isset($Grant_priv) && $Grant_priv == 'Y')
911 || (isset($max_questions) || isset($max_connections)
912 || isset($max_updates) || isset($max_user_connections))) {
913 $real_sql_query .= ' WITH';
914 $sql_query .= ' WITH';
915 if (isset($Grant_priv) && $Grant_priv == 'Y') {
916 $real_sql_query .= ' GRANT OPTION';
917 $sql_query .= ' GRANT OPTION';
919 if (isset($max_questions)) {
920 // avoid negative values
921 $max_questions = max(0, (int)$max_questions);
922 $real_sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
923 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
925 if (isset($max_connections)) {
926 $max_connections = max(0, (int)$max_connections);
927 $real_sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
928 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
930 if (isset($max_updates)) {
931 $max_updates = max(0, (int)$max_updates);
932 $real_sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
933 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
935 if (isset($max_user_connections)) {
936 $max_user_connections = max(0, (int)$max_user_connections);
937 $real_sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
938 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
941 if (isset($create_user_real)) {
942 $create_user_real .= ';';
943 $create_user_show .= ';';
945 $real_sql_query .= ';';
946 $sql_query .= ';';
947 if (empty($_REQUEST['change_copy'])) {
948 $_error = false;
950 if (isset($create_user_real)) {
951 if (! PMA_DBI_try_query($create_user_real)) {
952 $_error = true;
954 $sql_query = $create_user_show . $sql_query;
957 if ($_error || ! PMA_DBI_try_query($real_sql_query)) {
958 $_REQUEST['createdb'] = false;
959 $message = PMA_Message::rawError(PMA_DBI_getError());
960 } else {
961 $message = PMA_Message::success(__('You have added a new user.'));
964 switch (PMA_ifSetOr($_REQUEST['createdb'], '0')) {
965 case '1' :
966 // Create database with same name and grant all privileges
967 $q = 'CREATE DATABASE IF NOT EXISTS '
968 . PMA_backquote(PMA_sqlAddslashes($username)) . ';';
969 $sql_query .= $q;
970 if (! PMA_DBI_try_query($q)) {
971 $message = PMA_Message::rawError(PMA_DBI_getError());
972 break;
974 // this is needed in case tracking is on:
975 $GLOBALS['db'] = $username;
976 $GLOBALS['reload'] = TRUE;
977 PMA_reloadNavigation();
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 '2' :
988 // Grant all privileges on wildcard name (username\_%)
989 $q = 'GRANT ALL PRIVILEGES ON '
990 . PMA_backquote(PMA_sqlAddslashes($username) . '\_%') . '.* 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 '3' :
998 // Grant all privileges on the specified database to the new user
999 $q = 'GRANT ALL PRIVILEGES ON '
1000 . PMA_backquote(PMA_sqlAddslashes($dbname)) . '.* TO \''
1001 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1002 $sql_query .= $q;
1003 if (! PMA_DBI_try_query($q)) {
1004 $message = PMA_Message::rawError(PMA_DBI_getError());
1006 break;
1007 case '0' :
1008 default :
1009 break;
1011 } else {
1012 if (isset($create_user_real)) {
1013 $queries[] = $create_user_real;
1015 $queries[] = $real_sql_query;
1016 // we put the query containing the hidden password in
1017 // $queries_for_display, at the same position occupied
1018 // by the real query in $queries
1019 $tmp_count = count($queries);
1020 if (isset($create_user_real)) {
1021 $queries_for_display[$tmp_count - 2] = $create_user_show;
1023 $queries_for_display[$tmp_count - 1] = $sql_query;
1025 unset($res, $real_sql_query);
1031 * Changes / copies a user, part III
1033 if (isset($_REQUEST['change_copy'])) {
1034 $user_host_condition =
1035 ' WHERE `User`'
1036 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1037 .' AND `Host`'
1038 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\';';
1039 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1040 while ($row = PMA_DBI_fetch_assoc($res)) {
1041 $queries[] =
1042 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1043 .' ON ' . PMA_backquote($row['Db']) . '.*'
1044 .' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1045 . ($row['Grant_priv'] == 'Y' ? ' WITH GRANT OPTION;' : ';');
1047 PMA_DBI_free_result($res);
1048 $res = PMA_DBI_query(
1049 'SELECT `Db`, `Table_name`, `Table_priv`'
1050 .' FROM `mysql`.`tables_priv`' . $user_host_condition,
1051 $GLOBALS['userlink'], PMA_DBI_QUERY_STORE);
1052 while ($row = PMA_DBI_fetch_assoc($res)) {
1054 $res2 = PMA_DBI_QUERY(
1055 'SELECT `Column_name`, `Column_priv`'
1056 .' FROM `mysql`.`columns_priv`'
1057 .' WHERE `User`'
1058 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1059 .' AND `Host`'
1060 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\''
1061 .' AND `Db`'
1062 .' = \'' . PMA_sqlAddslashes($row['Db']) . "'"
1063 .' AND `Table_name`'
1064 .' = \'' . PMA_sqlAddslashes($row['Table_name']) . "'"
1065 .';',
1066 null, PMA_DBI_QUERY_STORE);
1068 $tmp_privs1 = PMA_extractPrivInfo($row);
1069 $tmp_privs2 = array(
1070 'Select' => array(),
1071 'Insert' => array(),
1072 'Update' => array(),
1073 'References' => array()
1076 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1077 $tmp_array = explode(',', $row2['Column_priv']);
1078 if (in_array('Select', $tmp_array)) {
1079 $tmp_privs2['Select'][] = $row2['Column_name'];
1081 if (in_array('Insert', $tmp_array)) {
1082 $tmp_privs2['Insert'][] = $row2['Column_name'];
1084 if (in_array('Update', $tmp_array)) {
1085 $tmp_privs2['Update'][] = $row2['Column_name'];
1087 if (in_array('References', $tmp_array)) {
1088 $tmp_privs2['References'][] = $row2['Column_name'];
1090 unset($tmp_array);
1092 if (count($tmp_privs2['Select']) > 0 && !in_array('SELECT', $tmp_privs1)) {
1093 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1095 if (count($tmp_privs2['Insert']) > 0 && !in_array('INSERT', $tmp_privs1)) {
1096 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1098 if (count($tmp_privs2['Update']) > 0 && !in_array('UPDATE', $tmp_privs1)) {
1099 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1101 if (count($tmp_privs2['References']) > 0 && !in_array('REFERENCES', $tmp_privs1)) {
1102 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1104 unset($tmp_privs2);
1105 $queries[] =
1106 'GRANT ' . join(', ', $tmp_privs1)
1107 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1108 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1109 . (in_array('Grant', explode(',', $row['Table_priv'])) ? ' WITH GRANT OPTION;' : ';');
1115 * Updates privileges
1117 if (!empty($update_privs)) {
1118 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, (isset($tablename) ? $tablename : ''));
1120 $sql_query0 =
1121 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1122 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1123 if (!isset($Grant_priv) || $Grant_priv != 'Y') {
1124 $sql_query1 =
1125 'REVOKE GRANT OPTION ON ' . $db_and_table
1126 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1127 } else {
1128 $sql_query1 = '';
1131 // Should not do a GRANT USAGE for a table-specific privilege, it
1132 // causes problems later (cannot revoke it)
1133 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1134 $sql_query2 =
1135 'GRANT ' . join(', ', PMA_extractPrivInfo())
1136 . ' ON ' . $db_and_table
1137 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
1140 * @todo similar code appears twice in this script
1142 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1143 || (! isset($dbname)
1144 && (isset($max_questions) || isset($max_connections)
1145 || isset($max_updates) || isset($max_user_connections))))
1147 $sql_query2 .= 'WITH';
1148 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1149 $sql_query2 .= ' GRANT OPTION';
1151 if (isset($max_questions)) {
1152 $max_questions = max(0, (int)$max_questions);
1153 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1155 if (isset($max_connections)) {
1156 $max_connections = max(0, (int)$max_connections);
1157 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1159 if (isset($max_updates)) {
1160 $max_updates = max(0, (int)$max_updates);
1161 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1163 if (isset($max_user_connections)) {
1164 $max_user_connections = max(0, (int)$max_user_connections);
1165 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1168 $sql_query2 .= ';';
1170 if (! PMA_DBI_try_query($sql_query0)) {
1171 // this query may fail, but this does not matter :o)
1172 $sql_query0 = '';
1174 if (isset($sql_query1) && !PMA_DBI_try_query($sql_query1)) {
1175 // this one may fail, too...
1176 $sql_query1 = '';
1178 if (isset($sql_query2)) {
1179 PMA_DBI_query($sql_query2);
1180 } else {
1181 $sql_query2 = '';
1183 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1184 $message = PMA_Message::success(__('You have updated the privileges for %s.'));
1185 $message->addParam('\'' . $username . '\'@\'' . $hostname . '\'');
1190 * Revokes Privileges
1192 if (isset($_REQUEST['revokeall'])) {
1193 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, isset($tablename) ? $tablename : '');
1195 $sql_query0 =
1196 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1197 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1198 $sql_query1 =
1199 'REVOKE GRANT OPTION ON ' . $db_and_table
1200 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1202 PMA_DBI_query($sql_query0);
1203 if (! PMA_DBI_try_query($sql_query1)) {
1204 // this one may fail, too...
1205 $sql_query1 = '';
1207 $sql_query = $sql_query0 . ' ' . $sql_query1;
1208 $message = PMA_Message::success(__('You have revoked the privileges for %s'));
1209 $message->addParam('\'' . $username . '\'@\'' . $hostname . '\'');
1210 if (! isset($tablename)) {
1211 unset($dbname);
1212 } else {
1213 unset($tablename);
1219 * Updates the password
1221 if (isset($_REQUEST['change_pw'])) {
1222 // similar logic in user_password.php
1223 $message = '';
1225 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1226 if ($pma_pw != $pma_pw2) {
1227 $message = PMA_Message::error(__('The passwords aren\'t the same!'));
1228 } elseif (empty($pma_pw) || empty($pma_pw2)) {
1229 $message = PMA_Message::error(__('The password is empty!'));
1231 } // end if
1233 // here $nopass could be == 1
1234 if (empty($message)) {
1236 $hashing_function = (!empty($pw_hash) && $pw_hash == 'old' ? 'OLD_' : '')
1237 . 'PASSWORD';
1239 // in $sql_query which will be displayed, hide the password
1240 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1241 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . PMA_sqlAddslashes($pma_pw) . '\')');
1242 PMA_DBI_try_query($local_query)
1243 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, FALSE, $err_url);
1244 $message = PMA_Message::success(__('The password for %s was changed successfully.'));
1245 $message->addParam('\'' . $username . '\'@\'' . $hostname . '\'');
1251 * Deletes users
1252 * (Changes / copies a user, part IV)
1255 if (isset($_REQUEST['delete']) || (isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1256 if (isset($_REQUEST['change_copy'])) {
1257 $selected_usr = array($old_username . '&amp;#27;' . $old_hostname);
1258 } else {
1259 $selected_usr = $_REQUEST['selected_usr'];
1260 $queries = array();
1262 foreach ($selected_usr as $each_user) {
1263 list($this_user, $this_host) = explode('&amp;#27;', $each_user);
1264 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1265 $queries[] = 'DROP USER \'' . PMA_sqlAddslashes($this_user) . '\'@\'' . PMA_sqlAddslashes($this_host) . '\';';
1267 if (isset($_REQUEST['drop_users_db'])) {
1268 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1269 $GLOBALS['reload'] = TRUE;
1270 PMA_reloadNavigation();
1273 if (empty($_REQUEST['change_copy'])) {
1274 if (empty($queries)) {
1275 $message = PMA_Message::error(__('No users selected for deleting!'));
1276 } else {
1277 if ($_REQUEST['mode'] == 3) {
1278 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1279 $queries[] = 'FLUSH PRIVILEGES;';
1281 $drop_user_error = '';
1282 foreach ($queries as $sql_query) {
1283 if ($sql_query{0} != '#') {
1284 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1285 $drop_user_error .= PMA_DBI_getError() . "\n";
1289 // tracking sets this, causing the deleted db to be shown in navi
1290 unset($GLOBALS['db']);
1292 $sql_query = join("\n", $queries);
1293 if (! empty($drop_user_error)) {
1294 $message = PMA_Message::rawError($drop_user_error);
1295 } else {
1296 $message = PMA_Message::success(__('The selected users have been deleted successfully.'));
1299 unset($queries);
1305 * Changes / copies a user, part V
1307 if (isset($_REQUEST['change_copy'])) {
1308 $tmp_count = 0;
1309 foreach ($queries as $sql_query) {
1310 if ($sql_query{0} != '#') {
1311 PMA_DBI_query($sql_query);
1313 // when there is a query containing a hidden password, take it
1314 // instead of the real query sent
1315 if (isset($queries_for_display[$tmp_count])) {
1316 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1318 $tmp_count++;
1320 $message = PMA_Message::success();
1321 $sql_query = join("\n", $queries);
1326 * Reloads the privilege tables into memory
1328 if (isset($_REQUEST['flush_privileges'])) {
1329 $sql_query = 'FLUSH PRIVILEGES;';
1330 PMA_DBI_query($sql_query);
1331 $message = PMA_Message::success(__('The privileges were reloaded successfully.'));
1336 * Displays the links
1338 if (isset($viewing_mode) && $viewing_mode == 'db') {
1339 $db = $checkprivs;
1340 $url_query .= '&amp;goto=db_operations.php';
1342 // Gets the database structure
1343 $sub_part = '_structure';
1344 require './libraries/db_info.inc.php';
1345 echo "\n";
1346 } else {
1347 require './libraries/server_links.inc.php';
1352 * defines some standard links
1354 $link_edit = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1355 . '&amp;username=%s'
1356 . '&amp;hostname=%s'
1357 . '&amp;dbname=%s'
1358 . '&amp;tablename=%s">'
1359 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1360 . '</a>';
1362 $link_revoke = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1363 . '&amp;username=%s'
1364 . '&amp;hostname=%s'
1365 . '&amp;dbname=%s'
1366 . '&amp;tablename=%s'
1367 . '&amp;revokeall=1">'
1368 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1369 . '</a>';
1371 $link_export = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1372 . '&amp;username=%s'
1373 . '&amp;hostname=%s'
1374 . '&amp;initial=%s'
1375 . '&amp;export=1">'
1376 . PMA_getIcon('b_tblexport.png', __('Export'))
1377 . '</a>';
1380 * Displays the page
1383 // export user definition
1384 if (isset($_REQUEST['export'])) {
1385 echo '<h2>' . __('User') . ' \'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'</h2>';
1386 echo '<textarea cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1387 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddslashes($username) . "'@'" . PMA_sqlAddslashes($hostname) . "'");
1388 foreach($grants as $one_grant) {
1389 echo $one_grant . ";\n\n";
1391 echo '</textarea>';
1392 unset($username, $hostname, $grants, $one_grant);
1395 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs))) {
1396 if (! isset($username)) {
1397 // No username is given --> display the overview
1398 echo '<h2>' . "\n"
1399 . PMA_getIcon('b_usrlist.png')
1400 . __('User overview') . "\n"
1401 . '</h2>' . "\n";
1403 $sql_query =
1404 'SELECT *,' .
1405 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1406 ' FROM `mysql`.`user`';
1408 $sql_query .= (isset($initial) ? PMA_RangeOfUsers($initial) : '');
1410 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1411 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1413 if (! $res) {
1414 // the query failed! This may have two reasons:
1415 // - the user does not have enough privileges
1416 // - the privilege tables use a structure of an earlier version.
1417 // so let's try a more simple query
1419 $sql_query = 'SELECT * FROM `mysql`.`user`';
1420 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1422 if (!$res) {
1423 PMA_Message::error(__('No Privileges'))->display();
1424 PMA_DBI_free_result($res);
1425 unset($res);
1426 } else {
1427 // This message is hardcoded because I will replace it by
1428 // a automatic repair feature soon.
1429 $raw = 'Your privilege table structure seems to be older than'
1430 . ' this MySQL version!<br />'
1431 . 'Please run the <tt>mysql_upgrade</tt> command'
1432 . '(<tt>mysql_fix_privilege_tables</tt> on older systems)'
1433 . ' that should be included in your MySQL server distribution'
1434 . ' to solve this problem!';
1435 PMA_Message::rawError($raw)->display();
1437 } else {
1439 // we also want users not in table `user` but in other table
1440 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1442 $tables_to_search_for_users = array(
1443 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1446 $db_rights_sqls = array();
1447 foreach ($tables_to_search_for_users as $table_search_in) {
1448 if (in_array($table_search_in, $tables)) {
1449 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ? PMA_RangeOfUsers($initial) : '');
1453 $user_defaults = array(
1454 'User' => '',
1455 'Host' => '%',
1456 'Password' => '?',
1457 'Grant_priv' => 'N',
1458 'privs' => array('USAGE'),
1461 // for all initials, even non A-Z
1462 $array_initials = array();
1463 // for the rights
1464 $db_rights = array();
1466 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1467 .' ORDER BY `User` ASC, `Host` ASC';
1469 $db_rights_result = PMA_DBI_query($db_rights_sql);
1471 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1472 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1473 $db_rights[$db_rights_row['User']][$db_rights_row['Host']] =
1474 $db_rights_row;
1476 PMA_DBI_free_result($db_rights_result);
1477 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1478 ksort($db_rights);
1481 * Displays the initials
1484 // initialize to FALSE the letters A-Z
1485 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++) {
1486 if (! isset($array_initials[chr($letter_counter + 64)])) {
1487 $array_initials[chr($letter_counter + 64)] = FALSE;
1491 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE);
1492 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1493 $array_initials[$tmp_initial] = TRUE;
1496 // Display the initials, which can be any characters, not
1497 // just letters. For letters A-Z, we add the non-used letters
1498 // as greyed out.
1500 uksort($array_initials, "strnatcasecmp");
1502 echo '<table cellspacing="5"><tr>';
1503 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1504 if ($initial_was_found) {
1505 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1506 } else {
1507 echo '<td>' . $tmp_initial . '</td>';
1510 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;showall=1">[' . __('Show all') . ']</a></td>' . "\n";
1511 echo '</tr></table>';
1514 * Display the user overview
1515 * (if less than 50 users, display them immediately)
1518 if (isset($initial) || isset($showall) || PMA_DBI_num_rows($res) < 50) {
1520 while ($row = PMA_DBI_fetch_assoc($res)) {
1521 $row['privs'] = PMA_extractPrivInfo($row, true);
1522 $db_rights[$row['User']][$row['Host']] = $row;
1524 @PMA_DBI_free_result($res);
1525 unset($res);
1527 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1528 . PMA_generate_common_hidden_inputs('', '')
1529 . ' <table id="tableuserrights" class="data">' . "\n"
1530 . ' <thead>' . "\n"
1531 . ' <tr><th></th>' . "\n"
1532 . ' <th>' . __('User') . '</th>' . "\n"
1533 . ' <th>' . __('Host') . '</th>' . "\n"
1534 . ' <th>' . __('Password') . '</th>' . "\n"
1535 . ' <th>' . __('Global privileges') . ' '
1536 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English ')) . '</th>' . "\n"
1537 . ' <th>' . __('Grant') . '</th>' . "\n"
1538 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1539 echo ' </tr>' . "\n";
1540 echo ' </thead>' . "\n";
1541 echo ' <tbody>' . "\n";
1542 $odd_row = true;
1543 $index_checkbox = -1;
1544 foreach ($db_rights as $user) {
1545 $index_checkbox++;
1546 ksort($user);
1547 foreach ($user as $host) {
1548 $index_checkbox++;
1549 echo ' <tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
1550 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1551 . $index_checkbox . '" value="'
1552 . htmlspecialchars($host['User'] . '&amp;#27;' . $host['Host'])
1553 . '"'
1554 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
1555 . ' /></td>' . "\n"
1556 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1557 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1558 echo ' <td>';
1559 switch ($host['Password']) {
1560 case 'Y':
1561 echo __('Yes');
1562 break;
1563 case 'N':
1564 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1565 break;
1566 // this happens if this is a definition not coming from mysql.user
1567 default:
1568 echo '--'; // in future version, replace by "not present"
1569 break;
1570 } // end switch
1571 echo '</td>' . "\n"
1572 . ' <td><tt>' . "\n"
1573 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1574 . ' </tt></td>' . "\n"
1575 . ' <td>' . ($host['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . '</td>' . "\n"
1576 . ' <td align="center">';
1577 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1578 echo '</td>';
1579 echo '<td align="center">';
1580 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ? $initial : ''));
1581 echo '</td>';
1582 echo '</tr>';
1583 $odd_row = ! $odd_row;
1587 unset($user, $host, $odd_row);
1588 echo ' </tbody></table>' . "\n"
1589 .'<img class="selectallarrow"'
1590 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1591 .' width="38" height="22"'
1592 .' alt="' . __('With selected:') . '" />' . "\n"
1593 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;checkall=1"'
1594 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1595 . __('Check All') . '</a>' . "\n"
1596 .'/' . "\n"
1597 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1598 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1599 . __('Uncheck All') . '</a>' . "\n";
1601 // add/delete user fieldset
1602 echo ' <fieldset id="fieldset_add_user">' . "\n"
1603 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1">' . "\n"
1604 . PMA_getIcon('b_usradd.png')
1605 . ' ' . __('Add a new User') . '</a>' . "\n"
1606 . ' </fieldset>' . "\n"
1607 . ' <fieldset id="fieldset_delete_user">'
1608 . ' <legend>' . "\n"
1609 . PMA_getIcon('b_usrdrop.png')
1610 . ' ' . __('Remove selected users') . '' . "\n"
1611 . ' </legend>' . "\n"
1612 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1613 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1614 . ' <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"
1615 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1616 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1617 . ' </label>' . "\n"
1618 . ' </fieldset>' . "\n"
1619 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1620 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" />' . "\n"
1621 . ' </fieldset>' . "\n"
1622 . '</form>' . "\n";
1623 } else {
1625 unset ($row);
1626 echo ' <fieldset id="fieldset_add_user">' . "\n"
1627 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1">' . "\n"
1628 . PMA_getIcon('b_usradd.png')
1629 . ' ' . __('Add a new User') . '</a>' . "\n"
1630 . ' </fieldset>' . "\n";
1631 } // end if (display overview)
1632 $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);
1633 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;flush_privileges=1">', false);
1634 $flushnote->addParam('</a>', false);
1635 $flushnote->display();
1639 } else {
1641 // A user was selected -> display the user's properties
1643 echo '<h2>' . "\n"
1644 . PMA_getIcon('b_usredit.png')
1645 . __('Edit Privileges') . ': '
1646 . __('User') ;
1648 if (isset($dbname)) {
1649 echo ' <i><a href="server_privileges.php?'
1650 . $GLOBALS['url_query'] . '&amp;username=' . urlencode($username)
1651 . '&amp;hostname=' . urlencode($hostname) . '&amp;dbname=&amp;tablename=">\''
1652 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1653 . '\'</a></i>' . "\n";
1654 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
1656 echo ' - ' . ($dbname_is_wildcard ? __('Databases') : __('Database') );
1657 if (isset($tablename)) {
1658 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
1659 . '&amp;username=' . urlencode($username) . '&amp;hostname=' . urlencode($hostname)
1660 . '&amp;dbname=' . $url_dbname . '&amp;tablename=">' . htmlspecialchars($dbname) . '</a></i>';
1661 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
1662 } else {
1663 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
1666 } else {
1667 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1668 . '\'</i>' . "\n";
1671 echo '</h2>' . "\n";
1674 $sql = "SELECT '1' FROM `mysql`.`user`"
1675 . " WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
1676 . " AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
1677 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
1678 unset($sql);
1679 if ($user_does_not_exists) {
1680 PMA_Message::warning(__('The selected user was not found in the privilege table.'))->display();
1681 PMA_displayLoginInformationFields();
1682 //require './libraries/footer.inc.php';
1685 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n";
1686 $_params = array(
1687 'username' => $username,
1688 'hostname' => $hostname,
1690 if (isset($dbname)) {
1691 $_params['dbname'] = $dbname;
1692 if (isset($tablename)) {
1693 $_params['tablename'] = $tablename;
1696 echo PMA_generate_common_hidden_inputs($_params);
1698 PMA_displayPrivTable(PMA_ifSetOr($dbname, '*', 'length'),
1699 PMA_ifSetOr($tablename, '*', 'length'));
1701 echo '</form>' . "\n";
1703 if (! isset($tablename) && empty($dbname_is_wildcard)) {
1705 // no table name was given, display all table specific rights
1706 // but only if $dbname contains no wildcards
1708 // table header
1709 echo '<form action="server_privileges.php" method="post">' . "\n"
1710 . PMA_generate_common_hidden_inputs('', '')
1711 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
1712 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1713 . '<fieldset>' . "\n"
1714 . '<legend>' . (! isset($dbname) ? __('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
1715 . '<table class="data">' . "\n"
1716 . '<thead>' . "\n"
1717 . '<tr><th>' . (! isset($dbname) ? __('Database') : __('Table')) . '</th>' . "\n"
1718 . ' <th>' . __('Privileges') . '</th>' . "\n"
1719 . ' <th>' . __('Grant') . '</th>' . "\n"
1720 . ' <th>' . (! isset($dbname) ? __('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
1721 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
1722 . '</tr>' . "\n"
1723 . '</thead>' . "\n"
1724 . '<tbody>' . "\n";
1726 $user_host_condition =
1727 ' WHERE `User`'
1728 . ' = \'' . PMA_sqlAddslashes($username) . "'"
1729 . ' AND `Host`'
1730 . ' = \'' . PMA_sqlAddslashes($hostname) . "'";
1732 // table body
1733 // get data
1735 // we also want privielgs for this user not in table `db` but in other table
1736 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1737 if (! isset($dbname)) {
1739 // no db name given, so we want all privs for the given user
1741 $tables_to_search_for_users = array(
1742 'tables_priv', 'columns_priv',
1745 $db_rights_sqls = array();
1746 foreach ($tables_to_search_for_users as $table_search_in) {
1747 if (in_array($table_search_in, $tables)) {
1748 $db_rights_sqls[] = '
1749 SELECT DISTINCT `Db`
1750 FROM `mysql`.' . PMA_backquote($table_search_in)
1751 . $user_host_condition;
1755 $user_defaults = array(
1756 'Db' => '',
1757 'Grant_priv' => 'N',
1758 'privs' => array('USAGE'),
1759 'Table_privs' => true,
1762 // for the rights
1763 $db_rights = array();
1765 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1766 .' ORDER BY `Db` ASC';
1768 $db_rights_result = PMA_DBI_query($db_rights_sql);
1770 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1771 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1772 // only Db names in the table `mysql`.`db` uses wildcards
1773 // as we are in the db specific rights display we want
1774 // all db names escaped, also from other sources
1775 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
1776 $db_rights_row['Db']);
1777 $db_rights[$db_rights_row['Db']] = $db_rights_row;
1780 PMA_DBI_free_result($db_rights_result);
1781 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1783 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
1784 $res = PMA_DBI_query($sql_query);
1785 $sql_query = '';
1787 while ($row = PMA_DBI_fetch_assoc($res)) {
1788 if (isset($db_rights[$row['Db']])) {
1789 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
1790 } else {
1791 $db_rights[$row['Db']] = $row;
1793 // there are db specific rights for this user
1794 // so we can drop this db rights
1795 $db_rights[$row['Db']]['can_delete'] = true;
1797 PMA_DBI_free_result($res);
1798 unset($row, $res);
1800 } else {
1802 // db name was given,
1803 // so we want all user specific rights for this db
1805 $user_host_condition .=
1806 ' AND `Db`'
1807 .' LIKE \'' . PMA_sqlAddslashes($dbname) . "'";
1809 $tables_to_search_for_users = array(
1810 'columns_priv',
1813 $db_rights_sqls = array();
1814 foreach ($tables_to_search_for_users as $table_search_in) {
1815 if (in_array($table_search_in, $tables)) {
1816 $db_rights_sqls[] = '
1817 SELECT DISTINCT `Table_name`
1818 FROM `mysql`.' . PMA_backquote($table_search_in)
1819 . $user_host_condition;
1823 $user_defaults = array(
1824 'Table_name' => '',
1825 'Grant_priv' => 'N',
1826 'privs' => array('USAGE'),
1827 'Column_priv' => true,
1830 // for the rights
1831 $db_rights = array();
1833 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1834 .' ORDER BY `Table_name` ASC';
1836 $db_rights_result = PMA_DBI_query($db_rights_sql);
1838 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1839 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1840 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
1842 PMA_DBI_free_result($db_rights_result);
1843 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1845 $sql_query =
1846 'SELECT `Table_name`,'
1847 .' `Table_priv`,'
1848 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
1849 .' AS \'Column_priv\''
1850 .' FROM `mysql`.`tables_priv`'
1851 . $user_host_condition
1852 .' ORDER BY `Table_name` ASC;';
1853 $res = PMA_DBI_query($sql_query);
1854 $sql_query = '';
1856 while ($row = PMA_DBI_fetch_assoc($res)) {
1857 if (isset($db_rights[$row['Table_name']])) {
1858 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
1859 } else {
1860 $db_rights[$row['Table_name']] = $row;
1863 PMA_DBI_free_result($res);
1864 unset($row, $res);
1866 ksort($db_rights);
1868 // display rows
1869 if (count($db_rights) < 1) {
1870 echo '<tr class="odd">' . "\n"
1871 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
1872 . '</tr>' . "\n";
1873 } else {
1874 $odd_row = true;
1875 $found_rows = array();
1876 //while ($row = PMA_DBI_fetch_assoc($res)) {
1877 foreach ($db_rights as $row) {
1878 $found_rows[] = (! isset($dbname)) ? $row['Db'] : $row['Table_name'];
1880 echo '<tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
1881 . ' <td>' . htmlspecialchars((! isset($dbname)) ? $row['Db'] : $row['Table_name']) . '</td>' . "\n"
1882 . ' <td><tt>' . "\n"
1883 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, TRUE)) . "\n"
1884 . ' </tt></td>' . "\n"
1885 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') || (isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ? __('Yes') : __('No')) . '</td>' . "\n"
1886 . ' <td>';
1887 if (! empty($row['Table_privs']) || ! empty ($row['Column_priv'])) {
1888 echo __('Yes');
1889 } else {
1890 echo __('No');
1892 echo '</td>' . "\n"
1893 . ' <td>';
1894 printf($link_edit, urlencode($username),
1895 urlencode($hostname),
1896 urlencode((! isset($dbname)) ? $row['Db'] : $dbname),
1897 urlencode((! isset($dbname)) ? '' : $row['Table_name']));
1898 echo '</td>' . "\n"
1899 . ' <td>';
1900 if (! empty($row['can_delete']) || isset($row['Table_name']) && strlen($row['Table_name'])) {
1901 printf($link_revoke, urlencode($username),
1902 urlencode($hostname),
1903 urlencode((! isset($dbname)) ? $row['Db'] : $dbname),
1904 urlencode((! isset($dbname)) ? '' : $row['Table_name']));
1906 echo '</td>' . "\n"
1907 . '</tr>' . "\n";
1908 $odd_row = ! $odd_row;
1909 } // end while
1911 unset($row);
1912 echo '</tbody>' . "\n"
1913 . '</table>' . "\n";
1915 if (! isset($dbname)) {
1917 // no database name was given, display select db
1919 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
1921 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
1922 if (!empty($pred_db_array)) {
1923 echo ' <select name="pred_dbname" onchange="this.form.submit();">' . "\n"
1924 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
1925 foreach ($pred_db_array as $current_db) {
1926 $current_db = PMA_escape_mysql_wildcards($current_db);
1927 // cannot use array_diff() once, outside of the loop,
1928 // because the list of databases has special characters
1929 // already escaped in $found_rows,
1930 // contrary to the output of SHOW DATABASES
1931 if (empty($found_rows) || ! in_array($current_db, $found_rows)) {
1932 echo ' <option value="' . htmlspecialchars($current_db) . '">'
1933 . htmlspecialchars($current_db) . '</option>' . "\n";
1936 echo ' </select>' . "\n";
1938 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
1939 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
1940 } else {
1941 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
1942 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
1943 if ($res = @PMA_DBI_try_query('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE)) {
1944 $pred_tbl_array = array();
1945 while ($row = PMA_DBI_fetch_row($res)) {
1946 if (!isset($found_rows) || !in_array($row[0], $found_rows)) {
1947 $pred_tbl_array[] = $row[0];
1950 PMA_DBI_free_result($res);
1951 unset($res, $row);
1952 if (!empty($pred_tbl_array)) {
1953 echo ' <select name="pred_tablename" onchange="this.form.submit();">' . "\n"
1954 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
1955 foreach ($pred_tbl_array as $current_table) {
1956 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
1958 echo ' </select>' . "\n";
1960 } else {
1961 unset($res);
1963 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
1965 echo '</fieldset>' . "\n";
1966 echo '<fieldset class="tblFooters">' . "\n"
1967 . ' <input type="submit" value="' . __('Go') . '" />'
1968 . '</fieldset>' . "\n"
1969 . '</form>' . "\n";
1973 // Provide a line with links to the relevant database and table
1974 if (isset($dbname) && empty($dbname_is_wildcard)) {
1975 echo '[ ' . __('Database')
1976 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
1977 . $GLOBALS['url_query'] . '&amp;db=' . $url_dbname . '&amp;reload=1">'
1978 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
1980 if (isset($tablename)) {
1981 echo ' [ ' . __('Table') . ' <a href="'
1982 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
1983 . '&amp;db=' . $url_dbname . '&amp;table=' . urlencode($tablename)
1984 . '&amp;reload=1">' . htmlspecialchars($tablename) . ': '
1985 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
1986 . "</a> ]\n";
1988 unset($url_dbname);
1991 if (! isset($dbname) && ! $user_does_not_exists) {
1992 require_once './libraries/display_change_password.lib.php';
1994 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
1995 . PMA_generate_common_hidden_inputs('', '')
1996 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
1997 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1998 . '<fieldset id="fieldset_change_copy_user">' . "\n"
1999 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
2000 PMA_displayLoginInformationFields('change');
2001 echo ' <fieldset>' . "\n"
2002 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2003 $choices = array(
2004 '4' => __('... keep the old one.'),
2005 '1' => __(' ... delete the old one from the user tables.'),
2006 '2' => __(' ... revoke all active privileges from the old one and delete it afterwards.'),
2007 '3' => __(' ... delete the old one from the user tables and reload the privileges afterwards.'));
2008 PMA_display_html_radio('mode', $choices, '4', true);
2009 unset($choices);
2011 echo ' </fieldset>' . "\n"
2012 . '</fieldset>' . "\n"
2013 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2014 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2015 . '</fieldset>' . "\n"
2016 . '</form>' . "\n";
2019 } elseif (isset($_REQUEST['adduser'])) {
2020 // Add a new user
2021 $GLOBALS['url_query'] .= '&amp;adduser=1';
2022 echo '<h2>' . "\n"
2023 . PMA_getIcon('b_usradd.png') . __('Add a new User') . "\n"
2024 . '</h2>' . "\n"
2025 . '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post" onsubmit="return checkAddUser(this);">' . "\n"
2026 . PMA_generate_common_hidden_inputs('', '');
2027 PMA_displayLoginInformationFields('new');
2028 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2029 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2031 $default_choice = 0;
2032 $choices = array(
2033 '0' => _pgettext('Create none database for user', 'None'),
2034 '1' => __('Create database with same name and grant all privileges'),
2035 '2' => __('Grant all privileges on wildcard name (username\\_%)'));
2037 if ( !empty($dbname) ) {
2038 $choices['3'] = sprintf( __('Grant all privileges on database &quot;%s&quot;'), htmlspecialchars($dbname));
2039 $default_choice = 3;
2040 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2043 // 4th parameter set to true to add line breaks
2044 // 5th parameter set to false to avoid htmlspecialchars() escaping in the label
2045 // since we have some HTML in some labels
2046 PMA_display_html_radio('createdb', $choices, $default_choice, true, false);
2047 unset($choices);
2048 unset($default_choice);
2050 echo '</fieldset>' . "\n";
2051 PMA_displayPrivTable('*', '*', FALSE);
2052 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2053 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2054 . ' </fieldset>' . "\n"
2055 . '</form>' . "\n";
2056 } else {
2057 // check the privileges for a particular database.
2058 echo '<table id="tablespecificuserrights" class="data">' . "\n"
2059 . '<caption class="tblHeaders">' . "\n"
2060 . PMA_getIcon('b_usrcheck.png')
2061 . ' ' . sprintf(__('Users having access to &quot;%s&quot;'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2062 . '</caption>' . "\n"
2063 . '<thead>' . "\n"
2064 . ' <tr><th>' . __('User') . '</th>' . "\n"
2065 . ' <th>' . __('Host') . '</th>' . "\n"
2066 . ' <th>' . __('Type') . '</th>' . "\n"
2067 . ' <th>' . __('Privileges') . '</th>' . "\n"
2068 . ' <th>' . __('Grant') . '</th>' . "\n"
2069 . ' <th>' . __('Action') . '</th>' . "\n"
2070 . ' </tr>' . "\n"
2071 . '</thead>' . "\n"
2072 . '<tbody>' . "\n";
2073 $odd_row = TRUE;
2074 unset($row, $row1, $row2);
2076 // now, we build the table...
2077 $list_of_privileges =
2078 '`User`, '
2079 . '`Host`, '
2080 . '`Select_priv`, '
2081 . '`Insert_priv`, '
2082 . '`Update_priv`, '
2083 . '`Delete_priv`, '
2084 . '`Create_priv`, '
2085 . '`Drop_priv`, '
2086 . '`Grant_priv`, '
2087 . '`Index_priv`, '
2088 . '`Alter_priv`, '
2089 . '`References_priv`, '
2090 . '`Create_tmp_table_priv`, '
2091 . '`Lock_tables_priv`, '
2092 . '`Create_view_priv`, '
2093 . '`Show_view_priv`, '
2094 . '`Create_routine_priv`, '
2095 . '`Alter_routine_priv`, '
2096 . '`Execute_priv`';
2098 $list_of_compared_privileges =
2099 '`Select_priv` = \'N\''
2100 . ' AND `Insert_priv` = \'N\''
2101 . ' AND `Update_priv` = \'N\''
2102 . ' AND `Delete_priv` = \'N\''
2103 . ' AND `Create_priv` = \'N\''
2104 . ' AND `Drop_priv` = \'N\''
2105 . ' AND `Grant_priv` = \'N\''
2106 . ' AND `References_priv` = \'N\''
2107 . ' AND `Create_tmp_table_priv` = \'N\''
2108 . ' AND `Lock_tables_priv` = \'N\''
2109 . ' AND `Create_view_priv` = \'N\''
2110 . ' AND `Show_view_priv` = \'N\''
2111 . ' AND `Create_routine_priv` = \'N\''
2112 . ' AND `Alter_routine_priv` = \'N\''
2113 . ' AND `Execute_priv` = \'N\'';
2115 if (PMA_MYSQL_INT_VERSION >= 50106) {
2116 $list_of_privileges .=
2117 ', `Event_priv`, '
2118 . '`Trigger_priv`';
2119 $list_of_compared_privileges .=
2120 ' AND `Event_priv` = \'N\''
2121 . ' AND `Trigger_priv` = \'N\'';
2124 $sql_query =
2125 '(SELECT ' . $list_of_privileges . ', `Db`'
2126 .' FROM `mysql`.`db`'
2127 .' WHERE \'' . PMA_sqlAddslashes($checkprivs) . "'"
2128 .' LIKE `Db`'
2129 .' AND NOT (' . $list_of_compared_privileges. ')) '
2130 .'UNION '
2131 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2132 .' FROM `mysql`.`user` '
2133 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2134 .' ORDER BY `User` ASC,'
2135 .' `Host` ASC,'
2136 .' `Db` ASC;';
2137 $res = PMA_DBI_query($sql_query);
2138 $row = PMA_DBI_fetch_assoc($res);
2139 if ($row) {
2140 $found = TRUE;
2143 if ($found) {
2144 while (TRUE) {
2145 // prepare the current user
2146 $current_privileges = array();
2147 $current_user = $row['User'];
2148 $current_host = $row['Host'];
2149 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2150 $current_privileges[] = $row;
2151 $row = PMA_DBI_fetch_assoc($res);
2153 echo ' <tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2154 . ' <td';
2155 if (count($current_privileges) > 1) {
2156 echo ' rowspan="' . count($current_privileges) . '"';
2158 echo '>' . (empty($current_user) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2159 . ' </td>' . "\n"
2160 . ' <td';
2161 if (count($current_privileges) > 1) {
2162 echo ' rowspan="' . count($current_privileges) . '"';
2164 echo '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2165 foreach ($current_privileges as $current) {
2166 echo ' <td>' . "\n"
2167 . ' ';
2168 if (!isset($current['Db']) || $current['Db'] == '*') {
2169 echo __('global');
2170 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2171 echo __('database-specific');
2172 } else {
2173 echo __('wildcard'), ': <tt>' . htmlspecialchars($current['Db']) . '</tt>';
2175 echo "\n"
2176 . ' </td>' . "\n"
2177 . ' <td>' . "\n"
2178 . ' <tt>' . "\n"
2179 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, TRUE)) . "\n"
2180 . ' </tt>' . "\n"
2181 . ' </td>' . "\n"
2182 . ' <td>' . "\n"
2183 . ' ' . ($current['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . "\n"
2184 . ' </td>' . "\n"
2185 . ' <td>' . "\n";
2186 printf($link_edit, urlencode($current_user),
2187 urlencode($current_host),
2188 urlencode(! isset($current['Db']) || $current['Db'] == '*' ? '' : $current['Db']),
2189 '');
2190 echo '</td>' . "\n"
2191 . ' </tr>' . "\n";
2193 if (empty($row) && empty($row1) && empty($row2)) {
2194 break;
2196 $odd_row = ! $odd_row;
2198 } else {
2199 echo ' <tr class="odd">' . "\n"
2200 . ' <td colspan="6">' . "\n"
2201 . ' ' . __('No user found.') . "\n"
2202 . ' </td>' . "\n"
2203 . ' </tr>' . "\n";
2205 echo '</tbody>' . "\n"
2206 . '</table>' . "\n";
2208 // Offer to create a new user for the current database
2209 echo '<fieldset id="fieldset_add_user">' . "\n"
2210 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1&amp;dbname=' . $checkprivs .'">' . "\n"
2211 . PMA_getIcon('b_usradd.png')
2212 . ' ' . __('Add a new User') . '</a>' . "\n"
2213 . '</fieldset>' . "\n";
2215 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2219 * Displays the footer
2221 echo "\n\n";
2222 require './libraries/footer.inc.php';