Always get full information here
[phpmyadmin.git] / server_privileges.php
blob00073e84fada437661a9b8a199aa369c75c3ff6d
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';
19 $_add_user_error = false;
21 require './libraries/server_common.inc.php';
23 if ($GLOBALS['cfg']['AjaxEnable']) {
24 $conditional_class = 'ajax';
25 } else {
26 $conditional_class = '';
29 /**
30 * Messages are built using the message name
32 $strPrivDescAllPrivileges = __('Includes all privileges except GRANT.');
33 $strPrivDescAlter = __('Allows altering the structure of existing tables.');
34 $strPrivDescAlterRoutine = __('Allows altering and dropping stored routines.');
35 $strPrivDescCreateDb = __('Allows creating new databases and tables.');
36 $strPrivDescCreateRoutine = __('Allows creating stored routines.');
37 $strPrivDescCreateTbl = __('Allows creating new tables.');
38 $strPrivDescCreateTmpTable = __('Allows creating temporary tables.');
39 $strPrivDescCreateUser = __('Allows creating, dropping and renaming user accounts.');
40 $strPrivDescCreateView = __('Allows creating new views.');
41 $strPrivDescDelete = __('Allows deleting data.');
42 $strPrivDescDropDb = __('Allows dropping databases and tables.');
43 $strPrivDescDropTbl = __('Allows dropping tables.');
44 $strPrivDescEvent = __('Allows to set up events for the event scheduler');
45 $strPrivDescExecute = __('Allows executing stored routines.');
46 $strPrivDescFile = __('Allows importing data from and exporting data into files.');
47 $strPrivDescGrant = __('Allows adding users and privileges without reloading the privilege tables.');
48 $strPrivDescIndex = __('Allows creating and dropping indexes.');
49 $strPrivDescInsert = __('Allows inserting and replacing data.');
50 $strPrivDescLockTables = __('Allows locking tables for the current thread.');
51 $strPrivDescMaxConnections = __('Limits the number of new connections the user may open per hour.');
52 $strPrivDescMaxQuestions = __('Limits the number of queries the user may send to the server per hour.');
53 $strPrivDescMaxUpdates = __('Limits the number of commands that change any table or database the user may execute per hour.');
54 $strPrivDescMaxUserConnections = __('Limits the number of simultaneous connections the user may have.');
55 $strPrivDescProcess = __('Allows viewing processes of all users');
56 $strPrivDescReferences = __('Has no effect in this MySQL version.');
57 $strPrivDescReload = __('Allows reloading server settings and flushing the server\'s caches.');
58 $strPrivDescReplClient = __('Allows the user to ask where the slaves / masters are.');
59 $strPrivDescReplSlave = __('Needed for the replication slaves.');
60 $strPrivDescSelect = __('Allows reading data.');
61 $strPrivDescShowDb = __('Gives access to the complete list of databases.');
62 $strPrivDescShowView = __('Allows performing SHOW CREATE VIEW queries.');
63 $strPrivDescShutdown = __('Allows shutting down the server.');
64 $strPrivDescSuper = __('Allows connecting, even if maximum number of connections is reached; required for most administrative operations like setting global variables or killing threads of other users.');
65 $strPrivDescTrigger = __('Allows creating and dropping triggers');
66 $strPrivDescUpdate = __('Allows changing data.');
67 $strPrivDescUsage = __('No privileges.');
69 /**
70 * Checks if a dropdown box has been used for selecting a database / table
72 if (PMA_isValid($_REQUEST['pred_tablename'])) {
73 $tablename = $_REQUEST['pred_tablename'];
74 unset($pred_tablename);
75 } elseif (PMA_isValid($_REQUEST['tablename'])) {
76 $tablename = $_REQUEST['tablename'];
77 } else {
78 unset($tablename);
81 if (PMA_isValid($_REQUEST['pred_dbname'])) {
82 $dbname = $_REQUEST['pred_dbname'];
83 unset($pred_dbname);
84 } elseif (PMA_isValid($_REQUEST['dbname'])) {
85 $dbname = $_REQUEST['dbname'];
86 } else {
87 unset($dbname);
88 unset($tablename);
91 if (isset($dbname)) {
92 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
93 if (isset($tablename)) {
94 $db_and_table .= PMA_backquote($tablename);
95 } else {
96 $db_and_table .= '*';
98 } else {
99 $db_and_table = '*.*';
102 // check if given $dbname is a wildcard or not
103 if (isset($dbname)) {
104 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
105 if (preg_match('/(?<!\\\\)(?:_|%)/i', $dbname)) {
106 $dbname_is_wildcard = true;
107 } else {
108 $dbname_is_wildcard = false;
113 * Checks if the user is allowed to do what he tries to...
115 if (!$is_superuser) {
116 require './libraries/server_links.inc.php';
117 echo '<h2>' . "\n"
118 . PMA_getIcon('b_usrlist.png')
119 . __('Privileges') . "\n"
120 . '</h2>' . "\n";
121 PMA_Message::error(__('No Privileges'))->display();
122 require './libraries/footer.inc.php';
125 $random_n = mt_rand(0,1000000); // a random number that will be appended to the id of the user forms
128 * Escapes wildcard in a database+table specification
129 * before using it in a GRANT statement.
131 * Escaping a wildcard character in a GRANT is only accepted at the global
132 * or database level, not at table level; this is why I remove
133 * the escaping character. Internally, in mysql.tables_priv.Db there are
134 * no escaping (for example test_db) but in mysql.db you'll see test\_db
135 * for a db-specific privilege.
137 * @param string $dbname Database name
138 * @param string $tablename Table name
139 * @return string the escaped (if necessary) database.table
141 function PMA_wildcardEscapeForGrant($dbname, $tablename) {
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, true) . "%'"
169 . " OR `User` LIKE '" . PMA_sqlAddSlashes(strtolower($initial), true) . "%'";
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(
190 'Select_priv',
191 'SELECT',
192 __('Allows reading data.')),
193 array(
194 'Insert_priv',
195 'INSERT',
196 __('Allows inserting and replacing data.')),
197 array(
198 'Update_priv',
199 'UPDATE',
200 __('Allows changing data.')),
201 array(
202 'Delete_priv',
203 'DELETE',
204 __('Allows deleting data.')),
205 array(
206 'Create_priv',
207 'CREATE',
208 __('Allows creating new databases and tables.')),
209 array(
210 'Drop_priv',
211 'DROP',
212 __('Allows dropping databases and tables.')),
213 array(
214 'Reload_priv',
215 'RELOAD',
216 __('Allows reloading server settings and flushing the server\'s caches.')),
217 array(
218 'Shutdown_priv',
219 'SHUTDOWN',
220 __('Allows shutting down the server.')),
221 array(
222 'Process_priv',
223 'PROCESS',
224 __('Allows viewing processes of all users')),
225 array(
226 'File_priv',
227 'FILE',
228 __('Allows importing data from and exporting data into files.')),
229 array(
230 'References_priv',
231 'REFERENCES',
232 __('Has no effect in this MySQL version.')),
233 array(
234 'Index_priv',
235 'INDEX',
236 __('Allows creating and dropping indexes.')),
237 array(
238 'Alter_priv',
239 'ALTER',
240 __('Allows altering the structure of existing tables.')),
241 array(
242 'Show_db_priv',
243 'SHOW DATABASES',
244 __('Gives access to the complete list of databases.')),
245 array(
246 'Super_priv',
247 'SUPER',
248 __('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.')),
249 array(
250 'Create_tmp_table_priv',
251 'CREATE TEMPORARY TABLES',
252 __('Allows creating temporary tables.')),
253 array(
254 'Lock_tables_priv',
255 'LOCK TABLES',
256 __('Allows locking tables for the current thread.')),
257 array(
258 'Repl_slave_priv',
259 'REPLICATION SLAVE',
260 __('Needed for the replication slaves.')),
261 array(
262 'Repl_client_priv',
263 'REPLICATION CLIENT',
264 __('Allows the user to ask where the slaves / masters are.')),
265 array(
266 'Create_view_priv',
267 'CREATE VIEW',
268 __('Allows creating new views.')),
269 array(
270 'Event_priv',
271 'EVENT',
272 __('Allows to set up events for the event scheduler')),
273 array(
274 'Trigger_priv',
275 'TRIGGER',
276 __('Allows creating and dropping triggers')),
277 // for table privs:
278 array(
279 'Create View_priv',
280 'CREATE VIEW',
281 __('Allows creating new views.')),
282 array(
283 'Show_view_priv',
284 'SHOW VIEW',
285 __('Allows performing SHOW CREATE VIEW queries.')),
286 // for table privs:
287 array(
288 'Show view_priv',
289 'SHOW VIEW',
290 __('Allows performing SHOW CREATE VIEW queries.')),
291 array(
292 'Create_routine_priv',
293 'CREATE ROUTINE',
294 __('Allows creating stored routines.')),
295 array(
296 'Alter_routine_priv',
297 'ALTER ROUTINE',
298 __('Allows altering and dropping stored routines.')),
299 array(
300 'Create_user_priv',
301 'CREATE USER',
302 __('Allows creating, dropping and renaming user accounts.')),
303 array(
304 'Execute_priv',
305 'EXECUTE',
306 __('Allows executing stored routines.')),
309 if (!empty($row) && isset($row['Table_priv'])) {
310 $row1 = PMA_DBI_fetch_single_row(
311 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
312 'ASSOC', $GLOBALS['userlink']);
313 $av_grants = explode('\',\'', substr($row1['Type'], 5, strlen($row1['Type']) - 7));
314 unset($row1);
315 $users_grants = explode(',', $row['Table_priv']);
316 foreach ($av_grants as $current_grant) {
317 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
319 unset($current_grant);
320 unset($av_grants);
321 unset($users_grants);
323 $privs = array();
324 $allPrivileges = true;
325 foreach ($grants as $current_grant) {
326 if ((!empty($row) && isset($row[$current_grant[0]]))
327 || (empty($row) && isset($GLOBALS[$current_grant[0]]))) {
328 if ((!empty($row) && $row[$current_grant[0]] == 'Y')
329 || (empty($row)
330 && ($GLOBALS[$current_grant[0]] == 'Y'
331 || (is_array($GLOBALS[$current_grant[0]])
332 && count($GLOBALS[$current_grant[0]]) == $GLOBALS['column_count']
333 && empty($GLOBALS[$current_grant[0] . '_none'])))))
335 if ($enableHTML) {
336 $privs[] = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
337 } else {
338 $privs[] = $current_grant[1];
340 } elseif (!empty($GLOBALS[$current_grant[0]])
341 && is_array($GLOBALS[$current_grant[0]])
342 && empty($GLOBALS[$current_grant[0] . '_none'])) {
343 if ($enableHTML) {
344 $priv_string = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
345 } else {
346 $priv_string = $current_grant[1];
348 $privs[] = $priv_string . ' (`' . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
349 } else {
350 $allPrivileges = false;
354 if (empty($privs)) {
355 if ($enableHTML) {
356 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
357 } else {
358 $privs[] = 'USAGE';
360 } elseif ($allPrivileges && (! isset($GLOBALS['grant_count']) || count($privs) == $GLOBALS['grant_count'])) {
361 if ($enableHTML) {
362 $privs = array('<dfn title="' . __('Includes all privileges except GRANT.') . '">ALL PRIVILEGES</dfn>');
363 } else {
364 $privs = array('ALL PRIVILEGES');
367 return $privs;
368 } // end of the 'PMA_extractPrivInfo()' function
371 * Displays on which column(s) a table-specific privilege is granted
373 function PMA_display_column_privs($columns, $row, $name_for_select,
374 $priv_for_header, $name, $name_for_dfn, $name_for_current)
376 echo ' <div class="item" id="div_item_' . $name . '">' . "\n"
377 . ' <label for="select_' . $name . '_priv">' . "\n"
378 . ' <tt><dfn title="' . $name_for_dfn . '">'
379 . $priv_for_header . '</dfn></tt>' . "\n"
380 . ' </label><br />' . "\n"
381 . ' <select id="select_' . $name . '_priv" name="'
382 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
384 foreach ($columns as $current_column => $current_column_privileges) {
385 echo ' <option value="' . htmlspecialchars($current_column) . '"';
386 if ($row[$name_for_select] == 'Y' || $current_column_privileges[$name_for_current]) {
387 echo ' selected="selected"';
389 echo '>' . htmlspecialchars($current_column) . '</option>' . "\n";
392 echo ' </select>' . "\n"
393 . ' <i>' . __('Or') . '</i>' . "\n"
394 . ' <label for="checkbox_' . $name_for_select
395 . '_none"><input type="checkbox"'
396 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
397 . ' name="' . $name_for_select . '_none" id="checkbox_'
398 . $name_for_select . '_none" title="' . _pgettext('None privileges', 'None') . '" />'
399 . _pgettext('None privileges', 'None') . '</label>' . "\n"
400 . ' </div>' . "\n";
401 } // end function
405 * Displays the privileges form table
407 * @param string $db the database
408 * @param string $table the table
409 * @param boolean $submit wheather to display the submit button or not
410 * @global array $cfg the phpMyAdmin configuration
411 * @global ressource $user_link the database connection
413 * @return void
415 function PMA_displayPrivTable($db = '*', $table = '*', $submit = true)
417 global $random_n;
419 if ($db == '*') {
420 $table = '*';
423 if (isset($GLOBALS['username'])) {
424 $username = $GLOBALS['username'];
425 $hostname = $GLOBALS['hostname'];
426 if ($db == '*') {
427 $sql_query =
428 "SELECT * FROM `mysql`.`user`"
429 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
430 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
431 } elseif ($table == '*') {
432 $sql_query =
433 "SELECT * FROM `mysql`.`db`"
434 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
435 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
436 ." AND '" . PMA_unescape_mysql_wildcards($db) . "'"
437 ." LIKE `Db`;";
438 } else {
439 $sql_query =
440 "SELECT `Table_priv`"
441 ." FROM `mysql`.`tables_priv`"
442 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
443 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
444 ." AND `Db` = '" . PMA_unescape_mysql_wildcards($db) . "'"
445 ." AND `Table_name` = '" . PMA_sqlAddSlashes($table) . "';";
447 $row = PMA_DBI_fetch_single_row($sql_query);
449 if (empty($row)) {
450 if ($table == '*') {
451 if ($db == '*') {
452 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
453 } elseif ($table == '*') {
454 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
456 $res = PMA_DBI_query($sql_query);
457 while ($row1 = PMA_DBI_fetch_row($res)) {
458 if (substr($row1[0], 0, 4) == 'max_') {
459 $row[$row1[0]] = 0;
460 } else {
461 $row[$row1[0]] = 'N';
464 PMA_DBI_free_result($res);
465 } else {
466 $row = array('Table_priv' => '');
469 if (isset($row['Table_priv'])) {
470 $row1 = PMA_DBI_fetch_single_row(
471 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
472 'ASSOC', $GLOBALS['userlink']);
473 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
474 // the View for Create is spelled with uppercase V
475 // the view for Show is spelled with lowercase v
476 // and there is a space between the words
478 $av_grants = explode('\',\'', substr($row1['Type'], strpos($row1['Type'], '(') + 2, strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3));
479 unset($row1);
480 $users_grants = explode(',', $row['Table_priv']);
482 foreach ($av_grants as $current_grant) {
483 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
485 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
487 // get collumns
488 $res = PMA_DBI_try_query('SHOW COLUMNS FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($db)) . '.' . PMA_backquote($table) . ';');
489 $columns = array();
490 if ($res) {
491 while ($row1 = PMA_DBI_fetch_row($res)) {
492 $columns[$row1[0]] = array(
493 'Select' => false,
494 'Insert' => false,
495 'Update' => false,
496 'References' => false
499 PMA_DBI_free_result($res);
501 unset($res, $row1);
503 // t a b l e - s p e c i f i c p r i v i l e g e s
504 if (! empty($columns)) {
505 $res = PMA_DBI_query(
506 'SELECT `Column_name`, `Column_priv`'
507 .' FROM `mysql`.`columns_priv`'
508 .' WHERE `User`'
509 .' = \'' . PMA_sqlAddSlashes($username) . "'"
510 .' AND `Host`'
511 .' = \'' . PMA_sqlAddSlashes($hostname) . "'"
512 .' AND `Db`'
513 .' = \'' . PMA_sqlAddSlashes(PMA_unescape_mysql_wildcards($db)) . "'"
514 .' AND `Table_name`'
515 .' = \'' . PMA_sqlAddSlashes($table) . '\';');
517 while ($row1 = PMA_DBI_fetch_row($res)) {
518 $row1[1] = explode(',', $row1[1]);
519 foreach ($row1[1] as $current) {
520 $columns[$row1[0]][$current] = true;
523 PMA_DBI_free_result($res);
524 unset($res, $row1, $current);
526 echo '<input type="hidden" name="grant_count" value="' . count($row) . '" />' . "\n"
527 . '<input type="hidden" name="column_count" value="' . count($columns) . '" />' . "\n"
528 . '<fieldset id="fieldset_user_priv">' . "\n"
529 . ' <legend>' . __('Table-specific privileges')
530 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English '))
531 . '</legend>' . "\n";
535 // privs that are attached to a specific column
536 PMA_display_column_privs($columns, $row, 'Select_priv',
537 'SELECT', 'select', __('Allows reading data.'), 'Select');
539 PMA_display_column_privs($columns, $row, 'Insert_priv',
540 'INSERT', 'insert', __('Allows inserting and replacing data.'), 'Insert');
542 PMA_display_column_privs($columns, $row, 'Update_priv',
543 'UPDATE', 'update', __('Allows changing data.'), 'Update');
545 PMA_display_column_privs($columns, $row, 'References_priv',
546 'REFERENCES', 'references', __('Has no effect in this MySQL version.'), 'References');
548 // privs that are not attached to a specific column
550 echo ' <div class="item">' . "\n";
551 foreach ($row as $current_grant => $current_grant_value) {
552 if (in_array(substr($current_grant, 0, (strlen($current_grant) - 5)),
553 array('Select', 'Insert', 'Update', 'References'))) {
554 continue;
556 // make a substitution to match the messages variables;
557 // also we must substitute the grant we get, because we can't generate
558 // a form variable containing blanks (those would get changed to
559 // an underscore when receiving the POST)
560 if ($current_grant == 'Create View_priv') {
561 $tmp_current_grant = 'CreateView_priv';
562 $current_grant = 'Create_view_priv';
563 } elseif ($current_grant == 'Show view_priv') {
564 $tmp_current_grant = 'ShowView_priv';
565 $current_grant = 'Show_view_priv';
566 } else {
567 $tmp_current_grant = $current_grant;
570 echo ' <div class="item">' . "\n"
571 . ' <input type="checkbox"'
572 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
573 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
574 . '" value="Y" '
575 . ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
576 . 'title="';
578 echo (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
579 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
580 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl']) . '"/>' . "\n";
582 echo ' <label for="checkbox_' . $current_grant
583 . '"><tt><dfn title="'
584 . (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
585 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
586 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl'])
587 . '">' . strtoupper(substr($current_grant, 0, strlen($current_grant) - 5)) . '</dfn></tt></label>' . "\n"
588 . ' </div>' . "\n";
589 } // end foreach ()
591 echo ' </div>' . "\n";
592 // for Safari 2.0.2
593 echo ' <div class="clearfloat"></div>' . "\n";
595 } else {
597 // g l o b a l o r d b - s p e c i f i c
599 $privTable_names = array(0 => __('Data'), 1 => __('Structure'), 2 => __('Administration'));
601 // d a t a
602 $privTable[0] = array(
603 array('Select', 'SELECT', __('Allows reading data.')),
604 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
605 array('Update', 'UPDATE', __('Allows changing data.')),
606 array('Delete', 'DELETE', __('Allows deleting data.'))
608 if ($db == '*') {
609 $privTable[0][] = array('File', 'FILE', __('Allows importing data from and exporting data into files.'));
612 // s t r u c t u r e
613 $privTable[1] = array(
614 array('Create', 'CREATE', ($table == '*' ? __('Allows creating new databases and tables.') : __('Allows creating new tables.'))),
615 array('Alter', 'ALTER', __('Allows altering the structure of existing tables.')),
616 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
617 array('Drop', 'DROP', ($table == '*' ? __('Allows dropping databases and tables.') : __('Allows dropping tables.'))),
618 array('Create_tmp_table', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
619 array('Show_view', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
620 array('Create_routine', 'CREATE ROUTINE', __('Allows creating stored routines.')),
621 array('Alter_routine', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
622 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
624 // this one is for a db-specific priv: Create_view_priv
625 if (isset($row['Create_view_priv'])) {
626 $privTable[1][] = array('Create_view', 'CREATE VIEW', __('Allows creating new views.'));
628 // this one is for a table-specific priv: Create View_priv
629 if (isset($row['Create View_priv'])) {
630 $privTable[1][] = array('Create View', 'CREATE VIEW', __('Allows creating new views.'));
632 if (isset($row['Event_priv'])) {
633 // MySQL 5.1.6
634 $privTable[1][] = array('Event', 'EVENT', __('Allows to set up events for the event scheduler'));
635 $privTable[1][] = array('Trigger', 'TRIGGER', __('Allows creating and dropping triggers'));
638 // a d m i n i s t r a t i o n
639 $privTable[2] = array(
640 array('Grant', 'GRANT', __('Allows adding users and privileges without reloading the privilege tables.')),
642 if ($db == '*') {
643 $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.'));
644 $privTable[2][] = array('Process', 'PROCESS', __('Allows viewing processes of all users'));
645 $privTable[2][] = array('Reload', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.'));
646 $privTable[2][] = array('Shutdown', 'SHUTDOWN', __('Allows shutting down the server.'));
647 $privTable[2][] = array('Show_db', 'SHOW DATABASES', __('Gives access to the complete list of databases.'));
649 $privTable[2][] = array('Lock_tables', 'LOCK TABLES', __('Allows locking tables for the current thread.'));
650 $privTable[2][] = array('References', 'REFERENCES', __('Has no effect in this MySQL version.'));
651 if ($db == '*') {
652 $privTable[2][] = array('Repl_client', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.'));
653 $privTable[2][] = array('Repl_slave', 'REPLICATION SLAVE', __('Needed for the replication slaves.'));
654 $privTable[2][] = array('Create_user', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.'));
656 echo '<input type="hidden" name="grant_count" value="'
657 . (count($privTable[0]) + count($privTable[1]) + count($privTable[2]) - (isset($row['Grant_priv']) ? 1 : 0))
658 . '" />' . "\n"
659 . '<fieldset id="fieldset_user_global_rights">' . "\n"
660 . ' <legend>' . "\n"
661 . ' '
662 . ($db == '*'
663 ? __('Global privileges')
664 : ($table == '*'
665 ? __('Database-specific privileges')
666 : __('Table-specific privileges'))) . "\n"
667 . ' (<a href="server_privileges.php?'
668 . $GLOBALS['url_query'] . '&amp;checkall=1" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', true); return false;">'
669 . __('Check All') . '</a> /' . "\n"
670 . ' <a href="server_privileges.php?'
671 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', false); return false;">'
672 . __('Uncheck All') . '</a>)' . "\n"
673 . ' </legend>' . "\n"
674 . ' <p><small><i>' . __(' Note: MySQL privilege names are expressed in English ') . '</i></small></p>' . "\n";
676 // Output the Global privilege tables with checkboxes
677 foreach ($privTable as $i => $table) {
678 echo ' <fieldset>' . "\n"
679 . ' <legend>' . __($privTable_names[$i]) . '</legend>' . "\n";
680 foreach ($table as $priv)
682 echo ' <div class="item">' . "\n"
683 . ' <input type="checkbox"'
684 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0] . '_priv"'
685 . ' value="Y" title="' . $priv[2] . '"'
686 . ((!empty($GLOBALS['checkall']) || $row[$priv[0] . '_priv'] == 'Y') ? ' checked="checked"' : '')
687 . '/>' . "\n"
688 . ' <label for="checkbox_' . $priv[0] . '_priv"><tt><dfn title="' . $priv[2] . '">'
689 . $priv[1] . '</dfn></tt></label>' . "\n"
690 . ' </div>' . "\n";
692 echo ' </fieldset>' . "\n";
695 // The "Resource limits" box is not displayed for db-specific privs
696 if ($db == '*') {
697 echo ' <fieldset>' . "\n"
698 . ' <legend>' . __('Resource limits') . '</legend>' . "\n"
699 . ' <p><small><i>' . __('Note: Setting these options to 0 (zero) removes the limit.') . '</i></small></p>' . "\n"
700 . ' <div class="item">' . "\n"
701 . ' <label for="text_max_questions"><tt><dfn title="'
702 . __('Limits the number of queries the user may send to the server per hour.') . '">MAX QUERIES PER HOUR</dfn></tt></label>' . "\n"
703 . ' <input type="text" name="max_questions" id="text_max_questions" value="'
704 . $row['max_questions'] . '" size="11" maxlength="11" title="' . __('Limits the number of queries the user may send to the server per hour.') . '" />' . "\n"
705 . ' </div>' . "\n"
706 . ' <div class="item">' . "\n"
707 . ' <label for="text_max_updates"><tt><dfn title="'
708 . __('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"
709 . ' <input type="text" name="max_updates" id="text_max_updates" value="'
710 . $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"
711 . ' </div>' . "\n"
712 . ' <div class="item">' . "\n"
713 . ' <label for="text_max_connections"><tt><dfn title="'
714 . __('Limits the number of new connections the user may open per hour.') . '">MAX CONNECTIONS PER HOUR</dfn></tt></label>' . "\n"
715 . ' <input type="text" name="max_connections" id="text_max_connections" value="'
716 . $row['max_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of new connections the user may open per hour.') . '" />' . "\n"
717 . ' </div>' . "\n"
718 . ' <div class="item">' . "\n"
719 . ' <label for="text_max_user_connections"><tt><dfn title="'
720 . __('Limits the number of simultaneous connections the user may have.') . '">MAX USER_CONNECTIONS</dfn></tt></label>' . "\n"
721 . ' <input type="text" name="max_user_connections" id="text_max_user_connections" value="'
722 . $row['max_user_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of simultaneous connections the user may have.') . '" />' . "\n"
723 . ' </div>' . "\n"
724 . ' </fieldset>' . "\n";
726 // for Safari 2.0.2
727 echo ' <div class="clearfloat"></div>' . "\n";
729 echo '</fieldset>' . "\n";
730 if ($submit) {
731 echo '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">' . "\n"
732 . ' <input type="submit" name="update_privs" value="' . __('Go') . '" />' . "\n"
733 . '</fieldset>' . "\n";
735 } // end of the 'PMA_displayPrivTable()' function
739 * Displays the fields used by the "new user" form as well as the
740 * "change login information / copy user" form.
742 * @param string $mode are we creating a new user or are we just
743 * changing one? (allowed values: 'new', 'change')
744 * @global array $cfg the phpMyAdmin configuration
745 * @global ressource $user_link the database connection
747 * @return void
749 function PMA_displayLoginInformationFields($mode = 'new')
751 // Get user/host name lengths
752 $fields_info = PMA_DBI_get_columns('mysql', 'user', true);
753 $username_length = 16;
754 $hostname_length = 41;
755 foreach ($fields_info as $val) {
756 if ($val['Field'] == 'User') {
757 strtok($val['Type'], '()');
758 $v = strtok('()');
759 if (is_int($v)) {
760 $username_length = $v;
762 } elseif ($val['Field'] == 'Host') {
763 strtok($val['Type'], '()');
764 $v = strtok('()');
765 if (is_int($v)) {
766 $hostname_length = $v;
770 unset($fields_info);
772 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
773 $GLOBALS['pred_username'] = 'any';
775 echo '<fieldset id="fieldset_add_user_login">' . "\n"
776 . '<legend>' . __('Login Information') . '</legend>' . "\n"
777 . '<div class="item">' . "\n"
778 . '<label for="select_pred_username">' . "\n"
779 . ' ' . __('User name') . ':' . "\n"
780 . '</label>' . "\n"
781 . '<span class="options">' . "\n"
782 . ' <select name="pred_username" id="select_pred_username" title="' . __('User name') . '"' . "\n"
783 . ' onchange="if (this.value == \'any\') { username.value = \'\'; } else if (this.value == \'userdefined\') { username.focus(); username.select(); }">' . "\n"
784 . ' <option value="any"' . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any') ? ' selected="selected"' : '') . '>' . __('Any user') . '</option>' . "\n"
785 . ' <option value="userdefined"' . ((! isset($GLOBALS['pred_username']) || $GLOBALS['pred_username'] == 'userdefined') ? ' selected="selected"' : '') . '>' . __('Use text field') . ':</option>' . "\n"
786 . ' </select>' . "\n"
787 . '</span>' . "\n"
788 . '<input type="text" name="username" maxlength="'
789 . $username_length . '" title="' . __('User name') . '"'
790 . (empty($GLOBALS['username'])
791 ? ''
792 : ' value="' . htmlspecialchars(isset($GLOBALS['new_username'])
793 ? $GLOBALS['new_username']
794 : $GLOBALS['username']) . '"')
795 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
796 . '</div>' . "\n"
797 . '<div class="item">' . "\n"
798 . '<label for="select_pred_hostname">' . "\n"
799 . ' ' . __('Host') . ':' . "\n"
800 . '</label>' . "\n"
801 . '<span class="options">' . "\n"
802 . ' <select name="pred_hostname" id="select_pred_hostname" title="' . __('Host') . '"' . "\n";
803 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
804 if (! empty($_current_user)) {
805 $thishost = str_replace("'", '', substr($_current_user, (strrpos($_current_user, '@') + 1)));
806 if ($thishost == 'localhost' || $thishost == '127.0.0.1') {
807 unset($thishost);
810 echo ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } else if (this.value == \'localhost\') { hostname.value = \'localhost\'; } '
811 . (empty($thishost) ? '' : 'else if (this.value == \'thishost\') { hostname.value = \'' . addslashes(htmlspecialchars($thishost)) . '\'; } ')
812 . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } else if (this.value == \'userdefined\') { hostname.focus(); hostname.select(); }">' . "\n";
813 unset($_current_user);
815 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
816 if (! isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
817 switch (strtolower($GLOBALS['hostname'])) {
818 case 'localhost':
819 case '127.0.0.1':
820 $GLOBALS['pred_hostname'] = 'localhost';
821 break;
822 case '%':
823 $GLOBALS['pred_hostname'] = 'any';
824 break;
825 default:
826 $GLOBALS['pred_hostname'] = 'userdefined';
827 break;
830 echo ' <option value="any"'
831 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
832 ? ' selected="selected"' : '') . '>' . __('Any host')
833 . '</option>' . "\n"
834 . ' <option value="localhost"'
835 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'localhost')
836 ? ' selected="selected"' : '') . '>' . __('Local')
837 . '</option>' . "\n";
838 if (!empty($thishost)) {
839 echo ' <option value="thishost"'
840 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'thishost')
841 ? ' selected="selected"' : '') . '>' . __('This Host')
842 . '</option>' . "\n";
844 unset($thishost);
845 echo ' <option value="hosttable"'
846 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'hosttable')
847 ? ' selected="selected"' : '') . '>' . __('Use Host Table')
848 . '</option>' . "\n"
849 . ' <option value="userdefined"'
850 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'userdefined')
851 ? ' selected="selected"' : '')
852 . '>' . __('Use text field') . ':</option>' . "\n"
853 . ' </select>' . "\n"
854 . '</span>' . "\n"
855 . '<input type="text" name="hostname" maxlength="'
856 . $hostname_length . '" value="'
857 . htmlspecialchars(isset($GLOBALS['hostname']) ? $GLOBALS['hostname'] : '')
858 . '" title="' . __('Host')
859 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
860 . PMA_showHint(__('When Host table is used, this field is ignored and values stored in Host table are used instead.'))
861 . '</div>' . "\n"
862 . '<div class="item">' . "\n"
863 . '<label for="select_pred_password">' . "\n"
864 . ' ' . __('Password') . ':' . "\n"
865 . '</label>' . "\n"
866 . '<span class="options">' . "\n"
867 . ' <select name="pred_password" id="select_pred_password" title="'
868 . __('Password') . '"' . "\n"
869 . ' onchange="if (this.value == \'none\') { pma_pw.value = \'\'; pma_pw2.value = \'\'; } else if (this.value == \'userdefined\') { pma_pw.focus(); pma_pw.select(); }">' . "\n"
870 . ($mode == 'change' ? ' <option value="keep" selected="selected">' . __('Do not change the password') . '</option>' . "\n" : '')
871 . ' <option value="none"';
872 if (isset($GLOBALS['username']) && $mode != 'change') {
873 echo ' selected="selected"';
875 echo '>' . __('No Password') . '</option>' . "\n"
876 . ' <option value="userdefined"' . (isset($GLOBALS['username']) ? '' : ' selected="selected"') . '>' . __('Use text field') . ':</option>' . "\n"
877 . ' </select>' . "\n"
878 . '</span>' . "\n"
879 . '<input type="password" id="text_pma_pw" name="pma_pw" title="' . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
880 . '</div>' . "\n"
881 . '<div class="item" id="div_element_before_generate_password">' . "\n"
882 . '<label for="text_pma_pw2">' . "\n"
883 . ' ' . __('Re-type') . ':' . "\n"
884 . '</label>' . "\n"
885 . '<span class="options">&nbsp;</span>' . "\n"
886 . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="' . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
887 . '</div>' . "\n"
888 // Generate password added here via jQuery
889 . '</fieldset>' . "\n";
890 } // end of the 'PMA_displayUserAndHostFields()' function
893 * Changes / copies a user, part I
895 if (isset($_REQUEST['change_copy'])) {
896 $user_host_condition =
897 ' WHERE `User`'
898 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
899 .' AND `Host`'
900 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
901 $row = PMA_DBI_fetch_single_row('SELECT * FROM `mysql`.`user` ' . $user_host_condition);
902 if (! $row) {
903 PMA_Message::notice(__('No user found.'))->display();
904 unset($_REQUEST['change_copy']);
905 } else {
906 extract($row, EXTR_OVERWRITE);
907 // Recent MySQL versions have the field "Password" in mysql.user,
908 // so the previous extract creates $Password but this script
909 // uses $password
910 if (! isset($password) && isset($Password)) {
911 $password = $Password;
913 $queries = array();
919 * Adds a user
920 * (Changes / copies a user, part II)
922 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
923 $sql_query = '';
924 if ($pred_username == 'any') {
925 $username = '';
927 switch ($pred_hostname) {
928 case 'any':
929 $hostname = '%';
930 break;
931 case 'localhost':
932 $hostname = 'localhost';
933 break;
934 case 'hosttable':
935 $hostname = '';
936 break;
937 case 'thishost':
938 $_user_name = PMA_DBI_fetch_value('SELECT USER()');
939 $hostname = substr($_user_name, (strrpos($_user_name, '@') + 1));
940 unset($_user_name);
941 break;
943 $sql = "SELECT '1' FROM `mysql`.`user`"
944 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
945 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
946 if (PMA_DBI_fetch_value($sql) == 1) {
947 $message = PMA_Message::error(__('The user %s already exists!'));
948 $message->addParam('[i]\'' . $username . '\'@\'' . $hostname . '\'[/i]');
949 $_REQUEST['adduser'] = true;
950 $_add_user_error = true;
951 } else {
953 $create_user_real = 'CREATE USER \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
955 $real_sql_query =
956 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
957 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
958 if ($pred_password != 'none' && $pred_password != 'keep') {
959 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
960 $real_sql_query .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
961 if (isset($create_user_real)) {
962 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
963 $create_user_real .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
965 } else {
966 if ($pred_password == 'keep' && !empty($password)) {
967 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
968 if (isset($create_user_real)) {
969 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
972 $sql_query = $real_sql_query;
973 if (isset($create_user_real)) {
974 $create_user_show = $create_user_real;
978 * @todo similar code appears twice in this script
980 if ((isset($Grant_priv) && $Grant_priv == 'Y')
981 || (isset($max_questions) || isset($max_connections)
982 || isset($max_updates) || isset($max_user_connections))) {
983 $real_sql_query .= ' WITH';
984 $sql_query .= ' WITH';
985 if (isset($Grant_priv) && $Grant_priv == 'Y') {
986 $real_sql_query .= ' GRANT OPTION';
987 $sql_query .= ' GRANT OPTION';
989 if (isset($max_questions)) {
990 // avoid negative values
991 $max_questions = max(0, (int)$max_questions);
992 $real_sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
993 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
995 if (isset($max_connections)) {
996 $max_connections = max(0, (int)$max_connections);
997 $real_sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
998 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1000 if (isset($max_updates)) {
1001 $max_updates = max(0, (int)$max_updates);
1002 $real_sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1003 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1005 if (isset($max_user_connections)) {
1006 $max_user_connections = max(0, (int)$max_user_connections);
1007 $real_sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1008 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1011 if (isset($create_user_real)) {
1012 $create_user_real .= ';';
1013 $create_user_show .= ';';
1015 $real_sql_query .= ';';
1016 $sql_query .= ';';
1017 if (empty($_REQUEST['change_copy'])) {
1018 $_error = false;
1020 if (isset($create_user_real)) {
1021 if (! PMA_DBI_try_query($create_user_real)) {
1022 $_error = true;
1024 $sql_query = $create_user_show . $sql_query;
1027 if ($_error || ! PMA_DBI_try_query($real_sql_query)) {
1028 $_REQUEST['createdb'] = false;
1029 $message = PMA_Message::rawError(PMA_DBI_getError());
1030 } else {
1031 $message = PMA_Message::success(__('You have added a new user.'));
1034 switch (PMA_ifSetOr($_REQUEST['createdb'], '0')) {
1035 case '1' :
1036 // Create database with same name and grant all privileges
1037 $q = 'CREATE DATABASE IF NOT EXISTS '
1038 . PMA_backquote(PMA_sqlAddSlashes($username)) . ';';
1039 $sql_query .= $q;
1040 if (! PMA_DBI_try_query($q)) {
1041 $message = PMA_Message::rawError(PMA_DBI_getError());
1042 break;
1047 * If we are not in an Ajax request, we can't reload navigation now
1049 if ($GLOBALS['is_ajax_request'] != true) {
1050 // this is needed in case tracking is on:
1051 $GLOBALS['db'] = $username;
1052 $GLOBALS['reload'] = true;
1053 PMA_reloadNavigation();
1056 $q = 'GRANT ALL PRIVILEGES ON '
1057 . PMA_backquote(PMA_sqlAddSlashes($username)) . '.* TO \''
1058 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1059 $sql_query .= $q;
1060 if (! PMA_DBI_try_query($q)) {
1061 $message = PMA_Message::rawError(PMA_DBI_getError());
1063 break;
1064 case '2' :
1065 // Grant all privileges on wildcard name (username\_%)
1066 $q = 'GRANT ALL PRIVILEGES ON '
1067 . PMA_backquote(PMA_sqlAddSlashes($username) . '\_%') . '.* TO \''
1068 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1069 $sql_query .= $q;
1070 if (! PMA_DBI_try_query($q)) {
1071 $message = PMA_Message::rawError(PMA_DBI_getError());
1073 break;
1074 case '3' :
1075 // Grant all privileges on the specified database to the new user
1076 $q = 'GRANT ALL PRIVILEGES ON '
1077 . PMA_backquote(PMA_sqlAddSlashes($dbname)) . '.* TO \''
1078 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1079 $sql_query .= $q;
1080 if (! PMA_DBI_try_query($q)) {
1081 $message = PMA_Message::rawError(PMA_DBI_getError());
1083 break;
1084 case '0' :
1085 default :
1086 break;
1088 } else {
1089 if (isset($create_user_real)) {
1090 $queries[] = $create_user_real;
1092 $queries[] = $real_sql_query;
1093 // we put the query containing the hidden password in
1094 // $queries_for_display, at the same position occupied
1095 // by the real query in $queries
1096 $tmp_count = count($queries);
1097 if (isset($create_user_real)) {
1098 $queries_for_display[$tmp_count - 2] = $create_user_show;
1100 $queries_for_display[$tmp_count - 1] = $sql_query;
1102 unset($res, $real_sql_query);
1108 * Changes / copies a user, part III
1110 if (isset($_REQUEST['change_copy'])) {
1111 $user_host_condition =
1112 ' WHERE `User`'
1113 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1114 .' AND `Host`'
1115 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
1116 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1117 while ($row = PMA_DBI_fetch_assoc($res)) {
1118 $queries[] =
1119 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1120 .' ON ' . PMA_backquote($row['Db']) . '.*'
1121 .' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1122 . ($row['Grant_priv'] == 'Y' ? ' WITH GRANT OPTION;' : ';');
1124 PMA_DBI_free_result($res);
1125 $res = PMA_DBI_query(
1126 'SELECT `Db`, `Table_name`, `Table_priv`'
1127 .' FROM `mysql`.`tables_priv`' . $user_host_condition,
1128 $GLOBALS['userlink'], PMA_DBI_QUERY_STORE);
1129 while ($row = PMA_DBI_fetch_assoc($res)) {
1131 $res2 = PMA_DBI_QUERY(
1132 'SELECT `Column_name`, `Column_priv`'
1133 .' FROM `mysql`.`columns_priv`'
1134 .' WHERE `User`'
1135 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1136 .' AND `Host`'
1137 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\''
1138 .' AND `Db`'
1139 .' = \'' . PMA_sqlAddSlashes($row['Db']) . "'"
1140 .' AND `Table_name`'
1141 .' = \'' . PMA_sqlAddSlashes($row['Table_name']) . "'"
1142 .';',
1143 null, PMA_DBI_QUERY_STORE);
1145 $tmp_privs1 = PMA_extractPrivInfo($row);
1146 $tmp_privs2 = array(
1147 'Select' => array(),
1148 'Insert' => array(),
1149 'Update' => array(),
1150 'References' => array()
1153 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1154 $tmp_array = explode(',', $row2['Column_priv']);
1155 if (in_array('Select', $tmp_array)) {
1156 $tmp_privs2['Select'][] = $row2['Column_name'];
1158 if (in_array('Insert', $tmp_array)) {
1159 $tmp_privs2['Insert'][] = $row2['Column_name'];
1161 if (in_array('Update', $tmp_array)) {
1162 $tmp_privs2['Update'][] = $row2['Column_name'];
1164 if (in_array('References', $tmp_array)) {
1165 $tmp_privs2['References'][] = $row2['Column_name'];
1167 unset($tmp_array);
1169 if (count($tmp_privs2['Select']) > 0 && !in_array('SELECT', $tmp_privs1)) {
1170 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1172 if (count($tmp_privs2['Insert']) > 0 && !in_array('INSERT', $tmp_privs1)) {
1173 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1175 if (count($tmp_privs2['Update']) > 0 && !in_array('UPDATE', $tmp_privs1)) {
1176 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1178 if (count($tmp_privs2['References']) > 0 && !in_array('REFERENCES', $tmp_privs1)) {
1179 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1181 unset($tmp_privs2);
1182 $queries[] =
1183 'GRANT ' . join(', ', $tmp_privs1)
1184 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1185 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1186 . (in_array('Grant', explode(',', $row['Table_priv'])) ? ' WITH GRANT OPTION;' : ';');
1192 * Updates privileges
1194 if (!empty($update_privs)) {
1195 $db_and_table = PMA_wildcardEscapeForGrant($dbname, (isset($tablename) ? $tablename : ''));
1197 $sql_query0 =
1198 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1199 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1200 if (! isset($Grant_priv) || $Grant_priv != 'Y') {
1201 $sql_query1 =
1202 'REVOKE GRANT OPTION ON ' . $db_and_table
1203 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1204 } else {
1205 $sql_query1 = '';
1208 // Should not do a GRANT USAGE for a table-specific privilege, it
1209 // causes problems later (cannot revoke it)
1210 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1211 $sql_query2 =
1212 'GRANT ' . join(', ', PMA_extractPrivInfo())
1213 . ' ON ' . $db_and_table
1214 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
1217 * @todo similar code appears twice in this script
1219 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1220 || (! isset($dbname)
1221 && (isset($max_questions) || isset($max_connections)
1222 || isset($max_updates) || isset($max_user_connections))))
1224 $sql_query2 .= 'WITH';
1225 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1226 $sql_query2 .= ' GRANT OPTION';
1228 if (isset($max_questions)) {
1229 $max_questions = max(0, (int)$max_questions);
1230 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1232 if (isset($max_connections)) {
1233 $max_connections = max(0, (int)$max_connections);
1234 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1236 if (isset($max_updates)) {
1237 $max_updates = max(0, (int)$max_updates);
1238 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1240 if (isset($max_user_connections)) {
1241 $max_user_connections = max(0, (int)$max_user_connections);
1242 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1245 $sql_query2 .= ';';
1247 if (! PMA_DBI_try_query($sql_query0)) {
1248 // This might fail when the executing user does not have ALL PRIVILEGES himself.
1249 // See https://sourceforge.net/tracker/index.php?func=detail&aid=3285929&group_id=23067&atid=377408
1250 $sql_query0 = '';
1252 if (isset($sql_query1) && !PMA_DBI_try_query($sql_query1)) {
1253 // this one may fail, too...
1254 $sql_query1 = '';
1256 if (isset($sql_query2)) {
1257 PMA_DBI_query($sql_query2);
1258 } else {
1259 $sql_query2 = '';
1261 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1262 $message = PMA_Message::success(__('You have updated the privileges for %s.'));
1263 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1268 * Revokes Privileges
1270 if (isset($_REQUEST['revokeall'])) {
1271 $db_and_table = PMA_wildcardEscapeForGrant($dbname, isset($tablename) ? $tablename : '');
1273 $sql_query0 =
1274 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1275 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1276 $sql_query1 =
1277 'REVOKE GRANT OPTION ON ' . $db_and_table
1278 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1280 PMA_DBI_query($sql_query0);
1281 if (! PMA_DBI_try_query($sql_query1)) {
1282 // this one may fail, too...
1283 $sql_query1 = '';
1285 $sql_query = $sql_query0 . ' ' . $sql_query1;
1286 $message = PMA_Message::success(__('You have revoked the privileges for %s'));
1287 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1288 if (! isset($tablename)) {
1289 unset($dbname);
1290 } else {
1291 unset($tablename);
1297 * Updates the password
1299 if (isset($_REQUEST['change_pw'])) {
1300 // similar logic in user_password.php
1301 $message = '';
1303 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1304 if ($pma_pw != $pma_pw2) {
1305 $message = PMA_Message::error(__('The passwords aren\'t the same!'));
1306 } elseif (empty($pma_pw) || empty($pma_pw2)) {
1307 $message = PMA_Message::error(__('The password is empty!'));
1309 } // end if
1311 // here $nopass could be == 1
1312 if (empty($message)) {
1314 $hashing_function = (!empty($pw_hash) && $pw_hash == 'old' ? 'OLD_' : '')
1315 . 'PASSWORD';
1317 // in $sql_query which will be displayed, hide the password
1318 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1319 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . PMA_sqlAddSlashes($pma_pw) . '\')');
1320 PMA_DBI_try_query($local_query)
1321 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, false, $err_url);
1322 $message = PMA_Message::success(__('The password for %s was changed successfully.'));
1323 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1329 * Deletes users
1330 * (Changes / copies a user, part IV)
1333 if (isset($_REQUEST['delete']) || (isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1334 if (isset($_REQUEST['change_copy'])) {
1335 $selected_usr = array($old_username . '&amp;#27;' . $old_hostname);
1336 } else {
1337 $selected_usr = $_REQUEST['selected_usr'];
1338 $queries = array();
1340 foreach ($selected_usr as $each_user) {
1341 list($this_user, $this_host) = explode('&amp;#27;', $each_user);
1342 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1343 $queries[] = 'DROP USER \'' . PMA_sqlAddSlashes($this_user) . '\'@\'' . PMA_sqlAddSlashes($this_host) . '\';';
1345 if (isset($_REQUEST['drop_users_db'])) {
1346 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1347 $GLOBALS['reload'] = true;
1349 if ($GLOBALS['is_ajax_request'] != true) {
1350 PMA_reloadNavigation();
1354 if (empty($_REQUEST['change_copy'])) {
1355 if (empty($queries)) {
1356 $message = PMA_Message::error(__('No users selected for deleting!'));
1357 } else {
1358 if ($_REQUEST['mode'] == 3) {
1359 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1360 $queries[] = 'FLUSH PRIVILEGES;';
1362 $drop_user_error = '';
1363 foreach ($queries as $sql_query) {
1364 if ($sql_query{0} != '#') {
1365 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1366 $drop_user_error .= PMA_DBI_getError() . "\n";
1370 // tracking sets this, causing the deleted db to be shown in navi
1371 unset($GLOBALS['db']);
1373 $sql_query = join("\n", $queries);
1374 if (! empty($drop_user_error)) {
1375 $message = PMA_Message::rawError($drop_user_error);
1376 } else {
1377 $message = PMA_Message::success(__('The selected users have been deleted successfully.'));
1380 unset($queries);
1386 * Changes / copies a user, part V
1388 if (isset($_REQUEST['change_copy'])) {
1389 $tmp_count = 0;
1390 foreach ($queries as $sql_query) {
1391 if ($sql_query{0} != '#') {
1392 PMA_DBI_query($sql_query);
1394 // when there is a query containing a hidden password, take it
1395 // instead of the real query sent
1396 if (isset($queries_for_display[$tmp_count])) {
1397 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1399 $tmp_count++;
1401 $message = PMA_Message::success();
1402 $sql_query = join("\n", $queries);
1407 * Reloads the privilege tables into memory
1409 if (isset($_REQUEST['flush_privileges'])) {
1410 $sql_query = 'FLUSH PRIVILEGES;';
1411 PMA_DBI_query($sql_query);
1412 $message = PMA_Message::success(__('The privileges were reloaded successfully.'));
1416 * defines some standard links
1418 $link_edit = '<a class="edit_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . $GLOBALS['url_query']
1419 . '&amp;username=%s'
1420 . '&amp;hostname=%s'
1421 . '&amp;dbname=%s'
1422 . '&amp;tablename=%s">'
1423 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1424 . '</a>';
1426 $link_revoke = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1427 . '&amp;username=%s'
1428 . '&amp;hostname=%s'
1429 . '&amp;dbname=%s'
1430 . '&amp;tablename=%s'
1431 . '&amp;revokeall=1">'
1432 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1433 . '</a>';
1435 $link_export = '<a class="export_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . $GLOBALS['url_query']
1436 . '&amp;username=%s'
1437 . '&amp;hostname=%s'
1438 . '&amp;initial=%s'
1439 . '&amp;export=1">'
1440 . PMA_getIcon('b_tblexport.png', __('Export'))
1441 . '</a>';
1444 * If we are in an Ajax request for Create User/Edit User/Revoke User/Flush Privileges,
1445 * show $message and exit.
1447 if ($GLOBALS['is_ajax_request'] && ! isset($_REQUEST['export']) && (! isset($_REQUEST['adduser']) || $_add_user_error) && ! isset($_REQUEST['initial']) && ! isset($_REQUEST['showall']) && ! isset($_REQUEST['edit_user_dialog']) && ! isset($_REQUEST['db_specific'])) {
1449 if (isset($sql_query)) {
1450 $extra_data['sql_query'] = PMA_showMessage(NULL, $sql_query);
1453 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
1455 * generate html on the fly for the new user that was just created.
1457 $new_user_string = '<tr>'."\n"
1458 .'<td> <input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_" value="' . htmlspecialchars($username) . '&amp;#27;' . htmlspecialchars($hostname) . '" /> </td>'."\n"
1459 .'<td><label for="checkbox_sel_users_">' . (empty($username) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($username) ) . '</label></td>' . "\n"
1460 .'<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
1461 $new_user_string .= '<td>';
1463 if (!empty($password) || isset($pma_pw)) {
1464 $new_user_string .= __('Yes');
1466 else {
1467 $new_user_string .= '<span style="color: #FF0000">' . __('No') . '</span>';
1470 $new_user_string .= '</td>'."\n";
1471 $new_user_string .= '<td><tt>' . join(', ', PMA_extractPrivInfo('', true)) . '</tt></td>'; //Fill in privileges here
1472 $new_user_string .= '<td>';
1474 if ((isset($Grant_priv) && $Grant_priv == 'Y')) {
1475 $new_user_string .= __('Yes');
1477 else {
1478 $new_user_string .= __('No');
1481 $new_user_string .='</td>';
1483 $new_user_string .= '<td>'.sprintf($link_edit, urlencode($username), urlencode($hostname), '', '' ).'</td>'."\n";
1484 $new_user_string .= '<td>'.sprintf($link_export, urlencode($username), urlencode($hostname), (isset($initial) ? $initial : '')).'</td>'."\n";
1486 $new_user_string .= '</tr>';
1488 $extra_data['new_user_string'] = $new_user_string;
1491 * Generate the string for this alphabet's initial, to update the user
1492 * pagination
1494 $new_user_initial = strtoupper(substr($username, 0, 1));
1495 $new_user_initial_string = '<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . $new_user_initial
1496 .'">' . $new_user_initial . '</a>';
1497 $extra_data['new_user_initial'] = $new_user_initial;
1498 $extra_data['new_user_initial_string'] = $new_user_initial_string;
1501 if (isset($update_privs)) {
1502 $extra_data['db_specific_privs'] = false;
1503 if (isset($dbname_is_wildcard)) {
1504 $extra_data['db_specific_privs'] = !$dbname_is_wildcard;
1506 $new_privileges = join(', ', PMA_extractPrivInfo('', true));
1508 $extra_data['new_privileges'] = $new_privileges;
1511 if ($message instanceof PMA_Message) {
1512 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
1517 * Displays the links
1519 if (isset($viewing_mode) && $viewing_mode == 'db') {
1520 $db = $checkprivs;
1521 $url_query .= '&amp;goto=db_operations.php';
1523 // Gets the database structure
1524 $sub_part = '_structure';
1525 require './libraries/db_info.inc.php';
1526 echo "\n";
1527 } else {
1528 require './libraries/server_links.inc.php';
1533 * Displays the page
1536 // export user definition
1537 if (isset($_REQUEST['export'])) {
1538 echo '<h2>' . __('User') . ' \'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'</h2>';
1539 echo '<textarea cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1540 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddSlashes($username) . "'@'" . PMA_sqlAddSlashes($hostname) . "'");
1541 foreach ($grants as $one_grant) {
1542 echo $one_grant . ";\n\n";
1544 echo '</textarea>';
1545 unset($username, $hostname, $grants, $one_grant);
1546 if ($GLOBALS['is_ajax_request']) {
1547 exit;
1551 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs))) {
1552 if (! isset($username)) {
1553 // No username is given --> display the overview
1554 echo '<h2>' . "\n"
1555 . PMA_getIcon('b_usrlist.png')
1556 . __('User overview') . "\n"
1557 . '</h2>' . "\n";
1559 $sql_query =
1560 'SELECT *,' .
1561 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1562 ' FROM `mysql`.`user`';
1564 $sql_query .= (isset($initial) ? PMA_rangeOfUsers($initial) : '');
1566 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1567 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1569 if (! $res) {
1570 // the query failed! This may have two reasons:
1571 // - the user does not have enough privileges
1572 // - the privilege tables use a structure of an earlier version.
1573 // so let's try a more simple query
1575 $sql_query = 'SELECT * FROM `mysql`.`user`';
1576 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1578 if (!$res) {
1579 PMA_Message::error(__('No Privileges'))->display();
1580 PMA_DBI_free_result($res);
1581 unset($res);
1582 } else {
1583 // This message is hardcoded because I will replace it by
1584 // a automatic repair feature soon.
1585 $raw = 'Your privilege table structure seems to be older than'
1586 . ' this MySQL version!<br />'
1587 . 'Please run the <tt>mysql_upgrade</tt> command'
1588 . '(<tt>mysql_fix_privilege_tables</tt> on older systems)'
1589 . ' that should be included in your MySQL server distribution'
1590 . ' to solve this problem!';
1591 PMA_Message::rawError($raw)->display();
1593 } else {
1595 // we also want users not in table `user` but in other table
1596 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1598 $tables_to_search_for_users = array(
1599 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1602 $db_rights_sqls = array();
1603 foreach ($tables_to_search_for_users as $table_search_in) {
1604 if (in_array($table_search_in, $tables)) {
1605 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ? PMA_rangeOfUsers($initial) : '');
1609 $user_defaults = array(
1610 'User' => '',
1611 'Host' => '%',
1612 'Password' => '?',
1613 'Grant_priv' => 'N',
1614 'privs' => array('USAGE'),
1617 // for all initials, even non A-Z
1618 $array_initials = array();
1619 // for the rights
1620 $db_rights = array();
1622 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1623 .' ORDER BY `User` ASC, `Host` ASC';
1625 $db_rights_result = PMA_DBI_query($db_rights_sql);
1627 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1628 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1629 $db_rights[$db_rights_row['User']][$db_rights_row['Host']] =
1630 $db_rights_row;
1632 PMA_DBI_free_result($db_rights_result);
1633 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1634 ksort($db_rights);
1637 * Displays the initials
1638 * In an Ajax request, we don't need to show this. Also not necassary if there is less than 20 privileges
1641 if ($GLOBALS['is_ajax_request'] != true && PMA_DBI_num_rows($res) > 20 ) {
1643 // initialize to false the letters A-Z
1644 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++) {
1645 if (! isset($array_initials[chr($letter_counter + 64)])) {
1646 $array_initials[chr($letter_counter + 64)] = false;
1650 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE);
1651 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1652 $array_initials[$tmp_initial] = true;
1655 // Display the initials, which can be any characters, not
1656 // just letters. For letters A-Z, we add the non-used letters
1657 // as greyed out.
1659 uksort($array_initials, "strnatcasecmp");
1661 echo '<table id="initials_table" class="' . $conditional_class . '" <cellspacing="5"><tr>';
1662 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1663 if ($initial_was_found) {
1664 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1665 } else {
1666 echo '<td>' . $tmp_initial . '</td>';
1669 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;showall=1" class="nowrap">[' . __('Show all') . ']</a></td>' . "\n";
1670 echo '</tr></table>';
1674 * Display the user overview
1675 * (if less than 50 users, display them immediately)
1678 if (isset($initial) || isset($showall) || PMA_DBI_num_rows($res) < 50) {
1680 while ($row = PMA_DBI_fetch_assoc($res)) {
1681 $row['privs'] = PMA_extractPrivInfo($row, true);
1682 $db_rights[$row['User']][$row['Host']] = $row;
1684 @PMA_DBI_free_result($res);
1685 unset($res);
1687 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1688 . PMA_generate_common_hidden_inputs('', '')
1689 . ' <table id="tableuserrights" class="data">' . "\n"
1690 . ' <thead>' . "\n"
1691 . ' <tr><th></th>' . "\n"
1692 . ' <th>' . __('User') . '</th>' . "\n"
1693 . ' <th>' . __('Host') . '</th>' . "\n"
1694 . ' <th>' . __('Password') . '</th>' . "\n"
1695 . ' <th>' . __('Global privileges') . ' '
1696 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English ')) . '</th>' . "\n"
1697 . ' <th>' . __('Grant') . '</th>' . "\n"
1698 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1699 echo ' </tr>' . "\n";
1700 echo ' </thead>' . "\n";
1701 echo ' <tbody>' . "\n";
1702 $odd_row = true;
1703 $index_checkbox = -1;
1704 foreach ($db_rights as $user) {
1705 $index_checkbox++;
1706 ksort($user);
1707 foreach ($user as $host) {
1708 $index_checkbox++;
1709 echo ' <tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
1710 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1711 . $index_checkbox . '" value="'
1712 . htmlspecialchars($host['User'] . '&amp;#27;' . $host['Host'])
1713 . '"'
1714 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
1715 . ' /></td>' . "\n"
1716 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1717 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1718 echo ' <td>';
1719 switch ($host['Password']) {
1720 case 'Y':
1721 echo __('Yes');
1722 break;
1723 case 'N':
1724 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1725 break;
1726 // this happens if this is a definition not coming from mysql.user
1727 default:
1728 echo '--'; // in future version, replace by "not present"
1729 break;
1730 } // end switch
1731 echo '</td>' . "\n"
1732 . ' <td><tt>' . "\n"
1733 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1734 . ' </tt></td>' . "\n"
1735 . ' <td>' . ($host['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . '</td>' . "\n"
1736 . ' <td align="center">';
1737 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1738 echo '</td>';
1739 echo '<td align="center">';
1740 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ? $initial : ''));
1741 echo '</td>';
1742 echo '</tr>';
1743 $odd_row = ! $odd_row;
1747 unset($user, $host, $odd_row);
1748 echo ' </tbody></table>' . "\n"
1749 .'<img class="selectallarrow"'
1750 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1751 .' width="38" height="22"'
1752 .' alt="' . __('With selected:') . '" />' . "\n"
1753 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;checkall=1"'
1754 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1755 . __('Check All') . '</a>' . "\n"
1756 .'/' . "\n"
1757 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1758 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1759 . __('Uncheck All') . '</a>' . "\n";
1761 // add/delete user fieldset
1762 echo ' <fieldset id="fieldset_add_user">' . "\n"
1763 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1764 . PMA_getIcon('b_usradd.png')
1765 . ' ' . __('Add user') . '</a>' . "\n"
1766 . ' </fieldset>' . "\n"
1767 . ' <fieldset id="fieldset_delete_user">'
1768 . ' <legend>' . "\n"
1769 . PMA_getIcon('b_usrdrop.png')
1770 . ' ' . __('Remove selected users') . '' . "\n"
1771 . ' </legend>' . "\n"
1772 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1773 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1774 . ' <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"
1775 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1776 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1777 . ' </label>' . "\n"
1778 . ' </fieldset>' . "\n"
1779 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1780 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" class="' . $conditional_class . '"/>' . "\n"
1781 . ' </fieldset>' . "\n"
1782 . '</form>' . "\n";
1783 } else {
1785 unset ($row);
1786 echo ' <fieldset id="fieldset_add_user">' . "\n"
1787 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1788 . PMA_getIcon('b_usradd.png')
1789 . ' ' . __('Add user') . '</a>' . "\n"
1790 . ' </fieldset>' . "\n";
1791 } // end if (display overview)
1793 if ($GLOBALS['is_ajax_request']) {
1794 exit;
1797 $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);
1798 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;flush_privileges=1" id="reload_privileges_anchor" class="' . $conditional_class . '">', false);
1799 $flushnote->addParam('</a>', false);
1800 $flushnote->display();
1804 } else {
1806 // A user was selected -> display the user's properties
1808 // In an Ajax request, prevent cached values from showing
1809 if ($GLOBALS['is_ajax_request'] == true) {
1810 header('Cache-Control: no-cache');
1813 echo '<h2>' . "\n"
1814 . PMA_getIcon('b_usredit.png')
1815 . __('Edit Privileges') . ': '
1816 . __('User') ;
1818 if (isset($dbname)) {
1819 echo ' <i><a href="server_privileges.php?'
1820 . $GLOBALS['url_query'] . '&amp;username=' . htmlspecialchars(urlencode($username))
1821 . '&amp;hostname=' . htmlspecialchars(urlencode($hostname)) . '&amp;dbname=&amp;tablename=">\''
1822 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1823 . '\'</a></i>' . "\n";
1824 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
1826 echo ' - ' . ($dbname_is_wildcard ? __('Databases') : __('Database') );
1827 if (isset($tablename)) {
1828 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
1829 . '&amp;username=' . htmlspecialchars(urlencode($username)) . '&amp;hostname=' . htmlspecialchars(urlencode($hostname))
1830 . '&amp;dbname=' . htmlspecialchars($url_dbname) . '&amp;tablename=">' . htmlspecialchars($dbname) . '</a></i>';
1831 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
1832 } else {
1833 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
1836 } else {
1837 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1838 . '\'</i>' . "\n";
1841 echo '</h2>' . "\n";
1844 $sql = "SELECT '1' FROM `mysql`.`user`"
1845 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
1846 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
1847 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
1848 unset($sql);
1849 if ($user_does_not_exists) {
1850 PMA_Message::error(__('The selected user was not found in the privilege table.'))->display();
1851 PMA_displayLoginInformationFields();
1852 //require './libraries/footer.inc.php';
1855 echo '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n";
1856 $_params = array(
1857 'username' => $username,
1858 'hostname' => $hostname,
1860 if (isset($dbname)) {
1861 $_params['dbname'] = $dbname;
1862 if (isset($tablename)) {
1863 $_params['tablename'] = $tablename;
1866 echo PMA_generate_common_hidden_inputs($_params);
1868 PMA_displayPrivTable(PMA_ifSetOr($dbname, '*', 'length'),
1869 PMA_ifSetOr($tablename, '*', 'length'));
1871 echo '</form>' . "\n";
1873 if (! isset($tablename) && empty($dbname_is_wildcard)) {
1875 // no table name was given, display all table specific rights
1876 // but only if $dbname contains no wildcards
1878 // table header
1879 echo '<form action="server_privileges.php" method="post">' . "\n"
1880 . PMA_generate_common_hidden_inputs('', '')
1881 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
1882 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1883 . '<fieldset>' . "\n"
1884 . '<legend>' . (! isset($dbname) ? __('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
1885 . '<table class="data">' . "\n"
1886 . '<thead>' . "\n"
1887 . '<tr><th>' . (! isset($dbname) ? __('Database') : __('Table')) . '</th>' . "\n"
1888 . ' <th>' . __('Privileges') . '</th>' . "\n"
1889 . ' <th>' . __('Grant') . '</th>' . "\n"
1890 . ' <th>' . (! isset($dbname) ? __('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
1891 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
1892 . '</tr>' . "\n"
1893 . '</thead>' . "\n"
1894 . '<tbody>' . "\n";
1896 $user_host_condition =
1897 ' WHERE `User`'
1898 . ' = \'' . PMA_sqlAddSlashes($username) . "'"
1899 . ' AND `Host`'
1900 . ' = \'' . PMA_sqlAddSlashes($hostname) . "'";
1902 // table body
1903 // get data
1905 // we also want privielgs for this user not in table `db` but in other table
1906 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1907 if (! isset($dbname)) {
1909 // no db name given, so we want all privs for the given user
1911 $tables_to_search_for_users = array(
1912 'tables_priv', 'columns_priv',
1915 $db_rights_sqls = array();
1916 foreach ($tables_to_search_for_users as $table_search_in) {
1917 if (in_array($table_search_in, $tables)) {
1918 $db_rights_sqls[] = '
1919 SELECT DISTINCT `Db`
1920 FROM `mysql`.' . PMA_backquote($table_search_in)
1921 . $user_host_condition;
1925 $user_defaults = array(
1926 'Db' => '',
1927 'Grant_priv' => 'N',
1928 'privs' => array('USAGE'),
1929 'Table_privs' => true,
1932 // for the rights
1933 $db_rights = array();
1935 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1936 .' ORDER BY `Db` ASC';
1938 $db_rights_result = PMA_DBI_query($db_rights_sql);
1940 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1941 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1942 // only Db names in the table `mysql`.`db` uses wildcards
1943 // as we are in the db specific rights display we want
1944 // all db names escaped, also from other sources
1945 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
1946 $db_rights_row['Db']);
1947 $db_rights[$db_rights_row['Db']] = $db_rights_row;
1950 PMA_DBI_free_result($db_rights_result);
1951 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1953 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
1954 $res = PMA_DBI_query($sql_query);
1955 $sql_query = '';
1957 while ($row = PMA_DBI_fetch_assoc($res)) {
1958 if (isset($db_rights[$row['Db']])) {
1959 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
1960 } else {
1961 $db_rights[$row['Db']] = $row;
1963 // there are db specific rights for this user
1964 // so we can drop this db rights
1965 $db_rights[$row['Db']]['can_delete'] = true;
1967 PMA_DBI_free_result($res);
1968 unset($row, $res);
1970 } else {
1972 // db name was given,
1973 // so we want all user specific rights for this db
1975 $user_host_condition .=
1976 ' AND `Db`'
1977 .' LIKE \'' . PMA_sqlAddSlashes($dbname, true) . "'";
1979 $tables_to_search_for_users = array(
1980 'columns_priv',
1983 $db_rights_sqls = array();
1984 foreach ($tables_to_search_for_users as $table_search_in) {
1985 if (in_array($table_search_in, $tables)) {
1986 $db_rights_sqls[] = '
1987 SELECT DISTINCT `Table_name`
1988 FROM `mysql`.' . PMA_backquote($table_search_in)
1989 . $user_host_condition;
1993 $user_defaults = array(
1994 'Table_name' => '',
1995 'Grant_priv' => 'N',
1996 'privs' => array('USAGE'),
1997 'Column_priv' => true,
2000 // for the rights
2001 $db_rights = array();
2003 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
2004 .' ORDER BY `Table_name` ASC';
2006 $db_rights_result = PMA_DBI_query($db_rights_sql);
2008 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
2009 $db_rights_row = array_merge($user_defaults, $db_rights_row);
2010 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
2012 PMA_DBI_free_result($db_rights_result);
2013 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
2015 $sql_query =
2016 'SELECT `Table_name`,'
2017 .' `Table_priv`,'
2018 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
2019 .' AS \'Column_priv\''
2020 .' FROM `mysql`.`tables_priv`'
2021 . $user_host_condition
2022 .' ORDER BY `Table_name` ASC;';
2023 $res = PMA_DBI_query($sql_query);
2024 $sql_query = '';
2026 while ($row = PMA_DBI_fetch_assoc($res)) {
2027 if (isset($db_rights[$row['Table_name']])) {
2028 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
2029 } else {
2030 $db_rights[$row['Table_name']] = $row;
2033 PMA_DBI_free_result($res);
2034 unset($row, $res);
2036 ksort($db_rights);
2038 // display rows
2039 if (count($db_rights) < 1) {
2040 echo '<tr class="odd">' . "\n"
2041 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
2042 . '</tr>' . "\n";
2043 } else {
2044 $odd_row = true;
2045 $found_rows = array();
2046 //while ($row = PMA_DBI_fetch_assoc($res)) {
2047 foreach ($db_rights as $row) {
2048 $found_rows[] = (! isset($dbname)) ? $row['Db'] : $row['Table_name'];
2050 echo '<tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2051 . ' <td>' . htmlspecialchars((! isset($dbname)) ? $row['Db'] : $row['Table_name']) . '</td>' . "\n"
2052 . ' <td><tt>' . "\n"
2053 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, true)) . "\n"
2054 . ' </tt></td>' . "\n"
2055 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') || (isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ? __('Yes') : __('No')) . '</td>' . "\n"
2056 . ' <td>';
2057 if (! empty($row['Table_privs']) || ! empty ($row['Column_priv'])) {
2058 echo __('Yes');
2059 } else {
2060 echo __('No');
2062 echo '</td>' . "\n"
2063 . ' <td>';
2064 printf($link_edit, htmlspecialchars(urlencode($username)),
2065 urlencode(htmlspecialchars($hostname)),
2066 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
2067 urlencode((! isset($dbname)) ? '' : $row['Table_name']));
2068 echo '</td>' . "\n"
2069 . ' <td>';
2070 if (! empty($row['can_delete']) || isset($row['Table_name']) && strlen($row['Table_name'])) {
2071 printf($link_revoke, htmlspecialchars(urlencode($username)),
2072 urlencode(htmlspecialchars($hostname)),
2073 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
2074 urlencode((! isset($dbname)) ? '' : $row['Table_name']));
2076 echo '</td>' . "\n"
2077 . '</tr>' . "\n";
2078 $odd_row = ! $odd_row;
2079 } // end while
2081 unset($row);
2082 echo '</tbody>' . "\n"
2083 . '</table>' . "\n";
2085 if (! isset($dbname)) {
2087 // no database name was given, display select db
2089 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
2091 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
2092 if (!empty($pred_db_array)) {
2093 echo ' <select name="pred_dbname" onchange="this.form.submit();">' . "\n"
2094 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2095 foreach ($pred_db_array as $current_db) {
2096 $current_db = PMA_escape_mysql_wildcards($current_db);
2097 // cannot use array_diff() once, outside of the loop,
2098 // because the list of databases has special characters
2099 // already escaped in $found_rows,
2100 // contrary to the output of SHOW DATABASES
2101 if (empty($found_rows) || ! in_array($current_db, $found_rows)) {
2102 echo ' <option value="' . htmlspecialchars($current_db) . '">'
2103 . htmlspecialchars($current_db) . '</option>' . "\n";
2106 echo ' </select>' . "\n";
2108 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
2109 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
2110 } else {
2111 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
2112 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
2113 if ($res = @PMA_DBI_try_query('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE)) {
2114 $pred_tbl_array = array();
2115 while ($row = PMA_DBI_fetch_row($res)) {
2116 if (! isset($found_rows) || !in_array($row[0], $found_rows)) {
2117 $pred_tbl_array[] = $row[0];
2120 PMA_DBI_free_result($res);
2121 unset($res, $row);
2122 if (!empty($pred_tbl_array)) {
2123 echo ' <select name="pred_tablename" onchange="this.form.submit();">' . "\n"
2124 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2125 foreach ($pred_tbl_array as $current_table) {
2126 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
2128 echo ' </select>' . "\n";
2130 } else {
2131 unset($res);
2133 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
2135 echo '</fieldset>' . "\n";
2136 echo '<fieldset class="tblFooters">' . "\n"
2137 . ' <input type="submit" value="' . __('Go') . '" />'
2138 . '</fieldset>' . "\n"
2139 . '</form>' . "\n";
2143 // Provide a line with links to the relevant database and table
2144 if (isset($dbname) && empty($dbname_is_wildcard)) {
2145 echo '[ ' . __('Database')
2146 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
2147 . $GLOBALS['url_query'] . '&amp;db=' . $url_dbname . '&amp;reload=1">'
2148 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
2150 if (isset($tablename)) {
2151 echo ' [ ' . __('Table') . ' <a href="'
2152 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
2153 . '&amp;db=' . $url_dbname . '&amp;table=' . htmlspecialchars(urlencode($tablename))
2154 . '&amp;reload=1">' . htmlspecialchars($tablename) . ': '
2155 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
2156 . "</a> ]\n";
2158 unset($url_dbname);
2161 if (! isset($dbname) && ! $user_does_not_exists) {
2162 require_once './libraries/display_change_password.lib.php';
2164 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
2165 . PMA_generate_common_hidden_inputs('', '')
2166 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
2167 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
2168 . '<fieldset id="fieldset_change_copy_user">' . "\n"
2169 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
2170 PMA_displayLoginInformationFields('change');
2171 echo ' <fieldset>' . "\n"
2172 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2173 $choices = array(
2174 '4' => __('... keep the old one.'),
2175 '1' => __(' ... delete the old one from the user tables.'),
2176 '2' => __(' ... revoke all active privileges from the old one and delete it afterwards.'),
2177 '3' => __(' ... delete the old one from the user tables and reload the privileges afterwards.'));
2178 PMA_display_html_radio('mode', $choices, '4', true);
2179 unset($choices);
2181 echo ' </fieldset>' . "\n"
2182 . '</fieldset>' . "\n"
2183 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2184 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2185 . '</fieldset>' . "\n"
2186 . '</form>' . "\n";
2189 } elseif (isset($_REQUEST['adduser'])) {
2191 // Add user
2192 $GLOBALS['url_query'] .= '&amp;adduser=1';
2193 echo '<h2>' . "\n"
2194 . PMA_getIcon('b_usradd.png') . __('Add user') . "\n"
2195 . '</h2>' . "\n"
2196 . '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n"
2197 . PMA_generate_common_hidden_inputs('', '');
2198 PMA_displayLoginInformationFields('new');
2199 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2200 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2202 $default_choice = 0;
2203 $choices = array(
2204 '0' => _pgettext('Create none database for user', 'None'),
2205 '1' => __('Create database with same name and grant all privileges'),
2206 '2' => __('Grant all privileges on wildcard name (username\\_%)'));
2208 if (! empty($dbname) ) {
2209 $choices['3'] = sprintf( __('Grant all privileges on database &quot;%s&quot;'), htmlspecialchars($dbname));
2210 $default_choice = 3;
2211 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2214 // 4th parameter set to true to add line breaks
2215 // 5th parameter set to false to avoid htmlspecialchars() escaping in the label
2216 // since we have some HTML in some labels
2217 PMA_display_html_radio('createdb', $choices, $default_choice, true, false);
2218 unset($choices);
2219 unset($default_choice);
2221 echo '</fieldset>' . "\n";
2222 PMA_displayPrivTable('*', '*', false);
2223 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2224 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2225 . ' </fieldset>' . "\n"
2226 . '</form>' . "\n";
2227 } else {
2228 // check the privileges for a particular database.
2229 $user_form = '<form id="usersForm"><table id="dbspecificuserrights" class="data">' . "\n"
2230 . '<caption class="tblHeaders">' . "\n"
2231 . PMA_getIcon('b_usrcheck.png')
2232 . ' ' . sprintf(__('Users having access to &quot;%s&quot;'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2233 . '</caption>' . "\n"
2234 . '<thead>' . "\n"
2235 . ' <tr><th>' . __('User') . '</th>' . "\n"
2236 . ' <th>' . __('Host') . '</th>' . "\n"
2237 . ' <th>' . __('Type') . '</th>' . "\n"
2238 . ' <th>' . __('Privileges') . '</th>' . "\n"
2239 . ' <th>' . __('Grant') . '</th>' . "\n"
2240 . ' <th>' . __('Action') . '</th>' . "\n"
2241 . ' </tr>' . "\n"
2242 . '</thead>' . "\n"
2243 . '<tbody>' . "\n";
2244 $odd_row = true;
2245 unset($row, $row1, $row2);
2247 // now, we build the table...
2248 $list_of_privileges =
2249 '`User`, '
2250 . '`Host`, '
2251 . '`Select_priv`, '
2252 . '`Insert_priv`, '
2253 . '`Update_priv`, '
2254 . '`Delete_priv`, '
2255 . '`Create_priv`, '
2256 . '`Drop_priv`, '
2257 . '`Grant_priv`, '
2258 . '`Index_priv`, '
2259 . '`Alter_priv`, '
2260 . '`References_priv`, '
2261 . '`Create_tmp_table_priv`, '
2262 . '`Lock_tables_priv`, '
2263 . '`Create_view_priv`, '
2264 . '`Show_view_priv`, '
2265 . '`Create_routine_priv`, '
2266 . '`Alter_routine_priv`, '
2267 . '`Execute_priv`';
2269 $list_of_compared_privileges =
2270 '`Select_priv` = \'N\''
2271 . ' AND `Insert_priv` = \'N\''
2272 . ' AND `Update_priv` = \'N\''
2273 . ' AND `Delete_priv` = \'N\''
2274 . ' AND `Create_priv` = \'N\''
2275 . ' AND `Drop_priv` = \'N\''
2276 . ' AND `Grant_priv` = \'N\''
2277 . ' AND `References_priv` = \'N\''
2278 . ' AND `Create_tmp_table_priv` = \'N\''
2279 . ' AND `Lock_tables_priv` = \'N\''
2280 . ' AND `Create_view_priv` = \'N\''
2281 . ' AND `Show_view_priv` = \'N\''
2282 . ' AND `Create_routine_priv` = \'N\''
2283 . ' AND `Alter_routine_priv` = \'N\''
2284 . ' AND `Execute_priv` = \'N\'';
2286 if (PMA_MYSQL_INT_VERSION >= 50106) {
2287 $list_of_privileges .=
2288 ', `Event_priv`, '
2289 . '`Trigger_priv`';
2290 $list_of_compared_privileges .=
2291 ' AND `Event_priv` = \'N\''
2292 . ' AND `Trigger_priv` = \'N\'';
2295 $sql_query =
2296 '(SELECT ' . $list_of_privileges . ', `Db`'
2297 .' FROM `mysql`.`db`'
2298 .' WHERE \'' . PMA_sqlAddSlashes($checkprivs) . "'"
2299 .' LIKE `Db`'
2300 .' AND NOT (' . $list_of_compared_privileges. ')) '
2301 .'UNION '
2302 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2303 .' FROM `mysql`.`user` '
2304 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2305 .' ORDER BY `User` ASC,'
2306 .' `Host` ASC,'
2307 .' `Db` ASC;';
2308 $res = PMA_DBI_query($sql_query);
2309 $row = PMA_DBI_fetch_assoc($res);
2310 if ($row) {
2311 $found = true;
2314 if ($found) {
2315 while (true) {
2316 // prepare the current user
2317 $current_privileges = array();
2318 $current_user = $row['User'];
2319 $current_host = $row['Host'];
2320 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2321 $current_privileges[] = $row;
2322 $row = PMA_DBI_fetch_assoc($res);
2324 $user_form .= ' <tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2325 . ' <td';
2326 if (count($current_privileges) > 1) {
2327 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2329 $user_form .= '>' . (empty($current_user) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2330 . ' </td>' . "\n"
2331 . ' <td';
2332 if (count($current_privileges) > 1) {
2333 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2335 $user_form .= '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2336 foreach ($current_privileges as $current) {
2337 $user_form .= ' <td>' . "\n"
2338 . ' ';
2339 if (! isset($current['Db']) || $current['Db'] == '*') {
2340 $user_form .= __('global');
2341 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2342 $user_form .= __('database-specific');
2343 } else {
2344 $user_form .= __('wildcard'). ': <tt>' . htmlspecialchars($current['Db']) . '</tt>';
2346 $user_form .= "\n"
2347 . ' </td>' . "\n"
2348 . ' <td>' . "\n"
2349 . ' <tt>' . "\n"
2350 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, true)) . "\n"
2351 . ' </tt>' . "\n"
2352 . ' </td>' . "\n"
2353 . ' <td>' . "\n"
2354 . ' ' . ($current['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . "\n"
2355 . ' </td>' . "\n"
2356 . ' <td>' . "\n";
2357 $user_form .= sprintf($link_edit, urlencode($current_user),
2358 urlencode($current_host),
2359 urlencode(! isset($current['Db']) || $current['Db'] == '*' ? '' : $current['Db']),
2360 '');
2361 $user_form .= '</td>' . "\n"
2362 . ' </tr>' . "\n";
2364 if (empty($row) && empty($row1) && empty($row2)) {
2365 break;
2367 $odd_row = ! $odd_row;
2369 } else {
2370 $user_form .= ' <tr class="odd">' . "\n"
2371 . ' <td colspan="6">' . "\n"
2372 . ' ' . __('No user found.') . "\n"
2373 . ' </td>' . "\n"
2374 . ' </tr>' . "\n";
2376 $user_form .= '</tbody>' . "\n"
2377 . '</table></form>' . "\n";
2379 if ($GLOBALS['is_ajax_request'] == true) {
2380 $extra_data['user_form'] = $user_form;
2381 $message = PMA_Message::success(__('User has been added.'));
2382 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
2383 }else{
2384 // Offer to create a new user for the current database
2385 $user_form .= '<fieldset id="fieldset_add_user">' . "\n"
2386 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1&amp;dbname=' . htmlspecialchars($checkprivs) .'" val="'.'checkprivs='.htmlspecialchars($checkprivs). '&'.$GLOBALS['url_query'] . '" class="'.$conditional_class.'" name="db_specific">' . "\n"
2387 . PMA_getIcon('b_usradd.png')
2388 . ' ' . __('Add user') . '</a>' . "\n"
2389 . '</fieldset>' . "\n";
2390 echo $user_form ;
2393 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2397 * Displays the footer
2399 echo "\n\n";
2400 require './libraries/footer.inc.php';