Better looking settings tabs in pmahomme
[phpmyadmin.git] / server_privileges.php
blobc1a1d835a99e575f365de1224761f7393f62c985
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 include './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 include './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
140 * @return string the escaped (if necessary) database.table
142 function PMA_wildcardEscapeForGrant($dbname, $tablename)
145 if (! strlen($dbname)) {
146 $db_and_table = '*.*';
147 } else {
148 if (strlen($tablename)) {
149 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
150 $db_and_table .= PMA_backquote($tablename);
151 } else {
152 $db_and_table = PMA_backquote($dbname) . '.';
153 $db_and_table .= '*';
156 return $db_and_table;
160 * Generates a condition on the user name
162 * @param string $initial the user's initial
164 * @return string the generated condition
166 function PMA_rangeOfUsers($initial = '')
168 // strtolower() is used because the User field
169 // might be BINARY, so LIKE would be case sensitive
170 if (! empty($initial)) {
171 $ret = " WHERE `User` LIKE '" . PMA_sqlAddSlashes($initial, true) . "%'"
172 . " OR `User` LIKE '" . PMA_sqlAddSlashes(strtolower($initial), true) . "%'";
173 } else {
174 $ret = '';
176 return $ret;
177 } // end function
180 * Extracts the privilege information of a priv table row
182 * @param array $row the row
183 * @param boolean $enableHTML add <dfn> tag with tooltips
185 * @global resource $user_link the database connection
187 * @return array
189 function PMA_extractPrivInfo($row = '', $enableHTML = false)
191 $grants = array(
192 array(
193 'Select_priv',
194 'SELECT',
195 __('Allows reading data.')),
196 array(
197 'Insert_priv',
198 'INSERT',
199 __('Allows inserting and replacing data.')),
200 array(
201 'Update_priv',
202 'UPDATE',
203 __('Allows changing data.')),
204 array(
205 'Delete_priv',
206 'DELETE',
207 __('Allows deleting data.')),
208 array(
209 'Create_priv',
210 'CREATE',
211 __('Allows creating new databases and tables.')),
212 array(
213 'Drop_priv',
214 'DROP',
215 __('Allows dropping databases and tables.')),
216 array(
217 'Reload_priv',
218 'RELOAD',
219 __('Allows reloading server settings and flushing the server\'s caches.')),
220 array(
221 'Shutdown_priv',
222 'SHUTDOWN',
223 __('Allows shutting down the server.')),
224 array(
225 'Process_priv',
226 'PROCESS',
227 __('Allows viewing processes of all users')),
228 array(
229 'File_priv',
230 'FILE',
231 __('Allows importing data from and exporting data into files.')),
232 array(
233 'References_priv',
234 'REFERENCES',
235 __('Has no effect in this MySQL version.')),
236 array(
237 'Index_priv',
238 'INDEX',
239 __('Allows creating and dropping indexes.')),
240 array(
241 'Alter_priv',
242 'ALTER',
243 __('Allows altering the structure of existing tables.')),
244 array(
245 'Show_db_priv',
246 'SHOW DATABASES',
247 __('Gives access to the complete list of databases.')),
248 array(
249 'Super_priv',
250 'SUPER',
251 __('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.')),
252 array(
253 'Create_tmp_table_priv',
254 'CREATE TEMPORARY TABLES',
255 __('Allows creating temporary tables.')),
256 array(
257 'Lock_tables_priv',
258 'LOCK TABLES',
259 __('Allows locking tables for the current thread.')),
260 array(
261 'Repl_slave_priv',
262 'REPLICATION SLAVE',
263 __('Needed for the replication slaves.')),
264 array(
265 'Repl_client_priv',
266 'REPLICATION CLIENT',
267 __('Allows the user to ask where the slaves / masters are.')),
268 array(
269 'Create_view_priv',
270 'CREATE VIEW',
271 __('Allows creating new views.')),
272 array(
273 'Event_priv',
274 'EVENT',
275 __('Allows to set up events for the event scheduler')),
276 array(
277 'Trigger_priv',
278 'TRIGGER',
279 __('Allows creating and dropping triggers')),
280 // for table privs:
281 array(
282 'Create View_priv',
283 'CREATE VIEW',
284 __('Allows creating new views.')),
285 array(
286 'Show_view_priv',
287 'SHOW VIEW',
288 __('Allows performing SHOW CREATE VIEW queries.')),
289 // for table privs:
290 array(
291 'Show view_priv',
292 'SHOW VIEW',
293 __('Allows performing SHOW CREATE VIEW queries.')),
294 array(
295 'Create_routine_priv',
296 'CREATE ROUTINE',
297 __('Allows creating stored routines.')),
298 array(
299 'Alter_routine_priv',
300 'ALTER ROUTINE',
301 __('Allows altering and dropping stored routines.')),
302 array(
303 'Create_user_priv',
304 'CREATE USER',
305 __('Allows creating, dropping and renaming user accounts.')),
306 array(
307 'Execute_priv',
308 'EXECUTE',
309 __('Allows executing stored routines.')),
312 if (! empty($row) && isset($row['Table_priv'])) {
313 $row1 = PMA_DBI_fetch_single_row(
314 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
315 'ASSOC', $GLOBALS['userlink']
317 $av_grants = explode('\',\'', substr($row1['Type'], 5, strlen($row1['Type']) - 7));
318 unset($row1);
319 $users_grants = explode(',', $row['Table_priv']);
320 foreach ($av_grants as $current_grant) {
321 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
323 unset($current_grant);
324 unset($av_grants);
325 unset($users_grants);
327 $privs = array();
328 $allPrivileges = true;
329 foreach ($grants as $current_grant) {
330 if ((! empty($row) && isset($row[$current_grant[0]]))
331 || (empty($row) && isset($GLOBALS[$current_grant[0]]))
333 if ((! empty($row) && $row[$current_grant[0]] == 'Y')
334 || (empty($row)
335 && ($GLOBALS[$current_grant[0]] == 'Y'
336 || (is_array($GLOBALS[$current_grant[0]])
337 && count($GLOBALS[$current_grant[0]]) == $GLOBALS['column_count']
338 && empty($GLOBALS[$current_grant[0] . '_none']))))
340 if ($enableHTML) {
341 $privs[] = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
342 } else {
343 $privs[] = $current_grant[1];
345 } elseif (! empty($GLOBALS[$current_grant[0]])
346 && is_array($GLOBALS[$current_grant[0]])
347 && empty($GLOBALS[$current_grant[0] . '_none'])) {
348 if ($enableHTML) {
349 $priv_string = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
350 } else {
351 $priv_string = $current_grant[1];
353 $privs[] = $priv_string . ' (`' . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
354 } else {
355 $allPrivileges = false;
359 if (empty($privs)) {
360 if ($enableHTML) {
361 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
362 } else {
363 $privs[] = 'USAGE';
365 } elseif ($allPrivileges && (! isset($GLOBALS['grant_count']) || count($privs) == $GLOBALS['grant_count'])) {
366 if ($enableHTML) {
367 $privs = array('<dfn title="' . __('Includes all privileges except GRANT.') . '">ALL PRIVILEGES</dfn>');
368 } else {
369 $privs = array('ALL PRIVILEGES');
372 return $privs;
373 } // end of the 'PMA_extractPrivInfo()' function
376 * Displays on which column(s) a table-specific privilege is granted
378 function PMA_display_column_privs($columns, $row, $name_for_select,
379 $priv_for_header, $name, $name_for_dfn, $name_for_current)
381 echo ' <div class="item" id="div_item_' . $name . '">' . "\n"
382 . ' <label for="select_' . $name . '_priv">' . "\n"
383 . ' <tt><dfn title="' . $name_for_dfn . '">'
384 . $priv_for_header . '</dfn></tt>' . "\n"
385 . ' </label><br />' . "\n"
386 . ' <select id="select_' . $name . '_priv" name="'
387 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
389 foreach ($columns as $current_column => $current_column_privileges) {
390 echo ' <option value="' . htmlspecialchars($current_column) . '"';
391 if ($row[$name_for_select] == 'Y' || $current_column_privileges[$name_for_current]) {
392 echo ' selected="selected"';
394 echo '>' . htmlspecialchars($current_column) . '</option>' . "\n";
397 echo ' </select>' . "\n"
398 . ' <i>' . __('Or') . '</i>' . "\n"
399 . ' <label for="checkbox_' . $name_for_select
400 . '_none"><input type="checkbox"'
401 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
402 . ' name="' . $name_for_select . '_none" id="checkbox_'
403 . $name_for_select . '_none" title="' . _pgettext('None privileges', 'None') . '" />'
404 . _pgettext('None privileges', 'None') . '</label>' . "\n"
405 . ' </div>' . "\n";
406 } // end function
410 * Displays the privileges form table
412 * @param string $db the database
413 * @param string $table the table
414 * @param boolean $submit wheather to display the submit button or not
416 * @global array $cfg the phpMyAdmin configuration
417 * @global ressource $user_link the database connection
419 * @return void
421 function PMA_displayPrivTable($db = '*', $table = '*', $submit = true)
423 global $random_n;
425 if ($db == '*') {
426 $table = '*';
429 if (isset($GLOBALS['username'])) {
430 $username = $GLOBALS['username'];
431 $hostname = $GLOBALS['hostname'];
432 if ($db == '*') {
433 $sql_query = "SELECT * FROM `mysql`.`user`"
434 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
435 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
436 } elseif ($table == '*') {
437 $sql_query = "SELECT * FROM `mysql`.`db`"
438 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
439 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
440 ." AND '" . PMA_unescape_mysql_wildcards($db) . "'"
441 ." LIKE `Db`;";
442 } else {
443 $sql_query = "SELECT `Table_priv`"
444 ." FROM `mysql`.`tables_priv`"
445 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
446 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
447 ." AND `Db` = '" . PMA_unescape_mysql_wildcards($db) . "'"
448 ." AND `Table_name` = '" . PMA_sqlAddSlashes($table) . "';";
450 $row = PMA_DBI_fetch_single_row($sql_query);
452 if (empty($row)) {
453 if ($table == '*') {
454 if ($db == '*') {
455 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
456 } elseif ($table == '*') {
457 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
459 $res = PMA_DBI_query($sql_query);
460 while ($row1 = PMA_DBI_fetch_row($res)) {
461 if (substr($row1[0], 0, 4) == 'max_') {
462 $row[$row1[0]] = 0;
463 } else {
464 $row[$row1[0]] = 'N';
467 PMA_DBI_free_result($res);
468 } else {
469 $row = array('Table_priv' => '');
472 if (isset($row['Table_priv'])) {
473 $row1 = PMA_DBI_fetch_single_row(
474 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
475 'ASSOC', $GLOBALS['userlink']
477 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
478 // the View for Create is spelled with uppercase V
479 // the view for Show is spelled with lowercase v
480 // and there is a space between the words
482 $av_grants = explode('\',\'', substr($row1['Type'], strpos($row1['Type'], '(') + 2, strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3));
483 unset($row1);
484 $users_grants = explode(',', $row['Table_priv']);
486 foreach ($av_grants as $current_grant) {
487 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
489 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
491 // get collumns
492 $res = PMA_DBI_try_query('SHOW COLUMNS FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($db)) . '.' . PMA_backquote($table) . ';');
493 $columns = array();
494 if ($res) {
495 while ($row1 = PMA_DBI_fetch_row($res)) {
496 $columns[$row1[0]] = array(
497 'Select' => false,
498 'Insert' => false,
499 'Update' => false,
500 'References' => false
503 PMA_DBI_free_result($res);
505 unset($res, $row1);
507 // t a b l e - s p e c i f i c p r i v i l e g e s
508 if (! empty($columns)) {
509 $res = PMA_DBI_query(
510 'SELECT `Column_name`, `Column_priv`'
511 .' FROM `mysql`.`columns_priv`'
512 .' WHERE `User`'
513 .' = \'' . PMA_sqlAddSlashes($username) . "'"
514 .' AND `Host`'
515 .' = \'' . PMA_sqlAddSlashes($hostname) . "'"
516 .' AND `Db`'
517 .' = \'' . PMA_sqlAddSlashes(PMA_unescape_mysql_wildcards($db)) . "'"
518 .' AND `Table_name`'
519 .' = \'' . PMA_sqlAddSlashes($table) . '\';'
522 while ($row1 = PMA_DBI_fetch_row($res)) {
523 $row1[1] = explode(',', $row1[1]);
524 foreach ($row1[1] as $current) {
525 $columns[$row1[0]][$current] = true;
528 PMA_DBI_free_result($res);
529 unset($res, $row1, $current);
531 echo '<input type="hidden" name="grant_count" value="' . count($row) . '" />' . "\n"
532 . '<input type="hidden" name="column_count" value="' . count($columns) . '" />' . "\n"
533 . '<fieldset id="fieldset_user_priv">' . "\n"
534 . ' <legend>' . __('Table-specific privileges')
535 . PMA_showHint(__('Note: MySQL privilege names are expressed in English'))
536 . '</legend>' . "\n";
540 // privs that are attached to a specific column
541 PMA_display_column_privs(
542 $columns, $row, 'Select_priv', 'SELECT',
543 'select', __('Allows reading data.'), 'Select'
546 PMA_display_column_privs(
547 $columns, $row, 'Insert_priv', 'INSERT',
548 'insert', __('Allows inserting and replacing data.'), 'Insert'
551 PMA_display_column_privs(
552 $columns, $row, 'Update_priv', 'UPDATE',
553 'update', __('Allows changing data.'), 'Update'
556 PMA_display_column_privs(
557 $columns, $row, 'References_priv', 'REFERENCES', 'references',
558 __('Has no effect in this MySQL version.'), 'References'
561 // privs that are not attached to a specific column
563 echo ' <div class="item">' . "\n";
564 foreach ($row as $current_grant => $current_grant_value) {
565 if (in_array(substr($current_grant, 0, (strlen($current_grant) - 5)),
566 array('Select', 'Insert', 'Update', 'References'))) {
567 continue;
569 // make a substitution to match the messages variables;
570 // also we must substitute the grant we get, because we can't generate
571 // a form variable containing blanks (those would get changed to
572 // an underscore when receiving the POST)
573 if ($current_grant == 'Create View_priv') {
574 $tmp_current_grant = 'CreateView_priv';
575 $current_grant = 'Create_view_priv';
576 } elseif ($current_grant == 'Show view_priv') {
577 $tmp_current_grant = 'ShowView_priv';
578 $current_grant = 'Show_view_priv';
579 } else {
580 $tmp_current_grant = $current_grant;
583 echo ' <div class="item">' . "\n"
584 . ' <input type="checkbox"'
585 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
586 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
587 . '" value="Y" '
588 . ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
589 . 'title="';
591 echo (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
592 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
593 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl']) . '"/>' . "\n";
595 echo ' <label for="checkbox_' . $current_grant
596 . '"><tt><dfn title="'
597 . (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
598 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
599 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl'])
600 . '">' . strtoupper(substr($current_grant, 0, strlen($current_grant) - 5)) . '</dfn></tt></label>' . "\n"
601 . ' </div>' . "\n";
602 } // end foreach ()
604 echo ' </div>' . "\n";
605 // for Safari 2.0.2
606 echo ' <div class="clearfloat"></div>' . "\n";
608 } else {
610 // g l o b a l o r d b - s p e c i f i c
612 $privTable_names = array(0 => __('Data'), 1 => __('Structure'), 2 => __('Administration'));
614 // d a t a
615 $privTable[0] = array(
616 array('Select', 'SELECT', __('Allows reading data.')),
617 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
618 array('Update', 'UPDATE', __('Allows changing data.')),
619 array('Delete', 'DELETE', __('Allows deleting data.'))
621 if ($db == '*') {
622 $privTable[0][] = array('File', 'FILE', __('Allows importing data from and exporting data into files.'));
625 // s t r u c t u r e
626 $privTable[1] = array(
627 array('Create', 'CREATE', ($table == '*' ? __('Allows creating new databases and tables.') : __('Allows creating new tables.'))),
628 array('Alter', 'ALTER', __('Allows altering the structure of existing tables.')),
629 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
630 array('Drop', 'DROP', ($table == '*' ? __('Allows dropping databases and tables.') : __('Allows dropping tables.'))),
631 array('Create_tmp_table', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
632 array('Show_view', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
633 array('Create_routine', 'CREATE ROUTINE', __('Allows creating stored routines.')),
634 array('Alter_routine', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
635 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
637 // this one is for a db-specific priv: Create_view_priv
638 if (isset($row['Create_view_priv'])) {
639 $privTable[1][] = array('Create_view', 'CREATE VIEW', __('Allows creating new views.'));
641 // this one is for a table-specific priv: Create View_priv
642 if (isset($row['Create View_priv'])) {
643 $privTable[1][] = array('Create View', 'CREATE VIEW', __('Allows creating new views.'));
645 if (isset($row['Event_priv'])) {
646 // MySQL 5.1.6
647 $privTable[1][] = array('Event', 'EVENT', __('Allows to set up events for the event scheduler'));
648 $privTable[1][] = array('Trigger', 'TRIGGER', __('Allows creating and dropping triggers'));
651 // a d m i n i s t r a t i o n
652 $privTable[2] = array(
653 array('Grant', 'GRANT', __('Allows adding users and privileges without reloading the privilege tables.')),
655 if ($db == '*') {
656 $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.'));
657 $privTable[2][] = array('Process', 'PROCESS', __('Allows viewing processes of all users'));
658 $privTable[2][] = array('Reload', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.'));
659 $privTable[2][] = array('Shutdown', 'SHUTDOWN', __('Allows shutting down the server.'));
660 $privTable[2][] = array('Show_db', 'SHOW DATABASES', __('Gives access to the complete list of databases.'));
662 $privTable[2][] = array('Lock_tables', 'LOCK TABLES', __('Allows locking tables for the current thread.'));
663 $privTable[2][] = array('References', 'REFERENCES', __('Has no effect in this MySQL version.'));
664 if ($db == '*') {
665 $privTable[2][] = array('Repl_client', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.'));
666 $privTable[2][] = array('Repl_slave', 'REPLICATION SLAVE', __('Needed for the replication slaves.'));
667 $privTable[2][] = array('Create_user', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.'));
669 echo '<input type="hidden" name="grant_count" value="'
670 . (count($privTable[0]) + count($privTable[1]) + count($privTable[2]) - (isset($row['Grant_priv']) ? 1 : 0))
671 . '" />' . "\n"
672 . '<fieldset id="fieldset_user_global_rights">' . "\n"
673 . ' <legend>' . "\n"
674 . ' '
675 . ($db == '*'
676 ? __('Global privileges')
677 : ($table == '*'
678 ? __('Database-specific privileges')
679 : __('Table-specific privileges'))) . "\n"
680 . ' (<a href="server_privileges.php?'
681 . $GLOBALS['url_query'] . '&amp;checkall=1" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', true); return false;">'
682 . __('Check All') . '</a> /' . "\n"
683 . ' <a href="server_privileges.php?'
684 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', false); return false;">'
685 . __('Uncheck All') . '</a>)' . "\n"
686 . ' </legend>' . "\n"
687 . ' <p><small><i>' . __('Note: MySQL privilege names are expressed in English') . '</i></small></p>' . "\n";
689 // Output the Global privilege tables with checkboxes
690 foreach ($privTable as $i => $table) {
691 echo ' <fieldset>' . "\n"
692 . ' <legend>' . __($privTable_names[$i]) . '</legend>' . "\n";
693 foreach ($table as $priv) {
694 echo ' <div class="item">' . "\n"
695 . ' <input type="checkbox"'
696 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0] . '_priv"'
697 . ' value="Y" title="' . $priv[2] . '"'
698 . ((! empty($GLOBALS['checkall']) || $row[$priv[0] . '_priv'] == 'Y') ? ' checked="checked"' : '')
699 . '/>' . "\n"
700 . ' <label for="checkbox_' . $priv[0] . '_priv"><tt><dfn title="' . $priv[2] . '">'
701 . $priv[1] . '</dfn></tt></label>' . "\n"
702 . ' </div>' . "\n";
704 echo ' </fieldset>' . "\n";
707 // The "Resource limits" box is not displayed for db-specific privs
708 if ($db == '*') {
709 echo ' <fieldset>' . "\n"
710 . ' <legend>' . __('Resource limits') . '</legend>' . "\n"
711 . ' <p><small><i>' . __('Note: Setting these options to 0 (zero) removes the limit.') . '</i></small></p>' . "\n"
712 . ' <div class="item">' . "\n"
713 . ' <label for="text_max_questions"><tt><dfn title="'
714 . __('Limits the number of queries the user may send to the server per hour.') . '">MAX QUERIES PER HOUR</dfn></tt></label>' . "\n"
715 . ' <input type="text" name="max_questions" id="text_max_questions" value="'
716 . $row['max_questions'] . '" size="11" maxlength="11" title="' . __('Limits the number of queries the user may send to the server per hour.') . '" />' . "\n"
717 . ' </div>' . "\n"
718 . ' <div class="item">' . "\n"
719 . ' <label for="text_max_updates"><tt><dfn title="'
720 . __('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"
721 . ' <input type="text" name="max_updates" id="text_max_updates" value="'
722 . $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"
723 . ' </div>' . "\n"
724 . ' <div class="item">' . "\n"
725 . ' <label for="text_max_connections"><tt><dfn title="'
726 . __('Limits the number of new connections the user may open per hour.') . '">MAX CONNECTIONS PER HOUR</dfn></tt></label>' . "\n"
727 . ' <input type="text" name="max_connections" id="text_max_connections" value="'
728 . $row['max_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of new connections the user may open per hour.') . '" />' . "\n"
729 . ' </div>' . "\n"
730 . ' <div class="item">' . "\n"
731 . ' <label for="text_max_user_connections"><tt><dfn title="'
732 . __('Limits the number of simultaneous connections the user may have.') . '">MAX USER_CONNECTIONS</dfn></tt></label>' . "\n"
733 . ' <input type="text" name="max_user_connections" id="text_max_user_connections" value="'
734 . $row['max_user_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of simultaneous connections the user may have.') . '" />' . "\n"
735 . ' </div>' . "\n"
736 . ' </fieldset>' . "\n";
738 // for Safari 2.0.2
739 echo ' <div class="clearfloat"></div>' . "\n";
741 echo '</fieldset>' . "\n";
742 if ($submit) {
743 echo '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">' . "\n"
744 . ' <input type="submit" name="update_privs" value="' . __('Go') . '" />' . "\n"
745 . '</fieldset>' . "\n";
747 } // end of the 'PMA_displayPrivTable()' function
751 * Displays the fields used by the "new user" form as well as the
752 * "change login information / copy user" form.
754 * @param string $mode are we creating a new user or are we just
755 * changing one? (allowed values: 'new', 'change')
757 * @global array $cfg the phpMyAdmin configuration
758 * @global ressource $user_link the database connection
760 * @return void
762 function PMA_displayLoginInformationFields($mode = 'new')
764 // Get user/host name lengths
765 $fields_info = PMA_DBI_get_columns('mysql', 'user', null, true);
766 $username_length = 16;
767 $hostname_length = 41;
768 foreach ($fields_info as $val) {
769 if ($val['Field'] == 'User') {
770 strtok($val['Type'], '()');
771 $v = strtok('()');
772 if (is_int($v)) {
773 $username_length = $v;
775 } elseif ($val['Field'] == 'Host') {
776 strtok($val['Type'], '()');
777 $v = strtok('()');
778 if (is_int($v)) {
779 $hostname_length = $v;
783 unset($fields_info);
785 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
786 $GLOBALS['pred_username'] = 'any';
788 echo '<fieldset id="fieldset_add_user_login">' . "\n"
789 . '<legend>' . __('Login Information') . '</legend>' . "\n"
790 . '<div class="item">' . "\n"
791 . '<label for="select_pred_username">' . "\n"
792 . ' ' . __('User name') . ':' . "\n"
793 . '</label>' . "\n"
794 . '<span class="options">' . "\n"
795 . ' <select name="pred_username" id="select_pred_username" title="' . __('User name') . '"' . "\n"
796 . ' onchange="if (this.value == \'any\') { username.value = \'\'; } else if (this.value == \'userdefined\') { username.focus(); username.select(); }">' . "\n"
797 . ' <option value="any"' . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any') ? ' selected="selected"' : '') . '>' . __('Any user') . '</option>' . "\n"
798 . ' <option value="userdefined"' . ((! isset($GLOBALS['pred_username']) || $GLOBALS['pred_username'] == 'userdefined') ? ' selected="selected"' : '') . '>' . __('Use text field') . ':</option>' . "\n"
799 . ' </select>' . "\n"
800 . '</span>' . "\n"
801 . '<input type="text" name="username" maxlength="'
802 . $username_length . '" title="' . __('User name') . '"'
803 . (empty($GLOBALS['username'])
804 ? ''
805 : ' value="' . htmlspecialchars(isset($GLOBALS['new_username'])
806 ? $GLOBALS['new_username']
807 : $GLOBALS['username']) . '"')
808 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
809 . '</div>' . "\n"
810 . '<div class="item">' . "\n"
811 . '<label for="select_pred_hostname">' . "\n"
812 . ' ' . __('Host') . ':' . "\n"
813 . '</label>' . "\n"
814 . '<span class="options">' . "\n"
815 . ' <select name="pred_hostname" id="select_pred_hostname" title="' . __('Host') . '"' . "\n";
816 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
817 if (! empty($_current_user)) {
818 $thishost = str_replace("'", '', substr($_current_user, (strrpos($_current_user, '@') + 1)));
819 if ($thishost == 'localhost' || $thishost == '127.0.0.1') {
820 unset($thishost);
823 echo ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } else if (this.value == \'localhost\') { hostname.value = \'localhost\'; } '
824 . (empty($thishost) ? '' : 'else if (this.value == \'thishost\') { hostname.value = \'' . addslashes(htmlspecialchars($thishost)) . '\'; } ')
825 . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } else if (this.value == \'userdefined\') { hostname.focus(); hostname.select(); }">' . "\n";
826 unset($_current_user);
828 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
829 if (! isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
830 switch (strtolower($GLOBALS['hostname'])) {
831 case 'localhost':
832 case '127.0.0.1':
833 $GLOBALS['pred_hostname'] = 'localhost';
834 break;
835 case '%':
836 $GLOBALS['pred_hostname'] = 'any';
837 break;
838 default:
839 $GLOBALS['pred_hostname'] = 'userdefined';
840 break;
843 echo ' <option value="any"'
844 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
845 ? ' selected="selected"' : '') . '>' . __('Any host')
846 . '</option>' . "\n"
847 . ' <option value="localhost"'
848 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'localhost')
849 ? ' selected="selected"' : '') . '>' . __('Local')
850 . '</option>' . "\n";
851 if (! empty($thishost)) {
852 echo ' <option value="thishost"'
853 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'thishost')
854 ? ' selected="selected"' : '') . '>' . __('This Host')
855 . '</option>' . "\n";
857 unset($thishost);
858 echo ' <option value="hosttable"'
859 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'hosttable')
860 ? ' selected="selected"' : '') . '>' . __('Use Host Table')
861 . '</option>' . "\n"
862 . ' <option value="userdefined"'
863 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'userdefined')
864 ? ' selected="selected"' : '')
865 . '>' . __('Use text field') . ':</option>' . "\n"
866 . ' </select>' . "\n"
867 . '</span>' . "\n"
868 . '<input type="text" name="hostname" maxlength="'
869 . $hostname_length . '" value="'
870 . htmlspecialchars(isset($GLOBALS['hostname']) ? $GLOBALS['hostname'] : '')
871 . '" title="' . __('Host')
872 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
873 . PMA_showHint(__('When Host table is used, this field is ignored and values stored in Host table are used instead.'))
874 . '</div>' . "\n"
875 . '<div class="item">' . "\n"
876 . '<label for="select_pred_password">' . "\n"
877 . ' ' . __('Password') . ':' . "\n"
878 . '</label>' . "\n"
879 . '<span class="options">' . "\n"
880 . ' <select name="pred_password" id="select_pred_password" title="'
881 . __('Password') . '"' . "\n"
882 . ' onchange="if (this.value == \'none\') { pma_pw.value = \'\'; pma_pw2.value = \'\'; } else if (this.value == \'userdefined\') { pma_pw.focus(); pma_pw.select(); }">' . "\n"
883 . ($mode == 'change' ? ' <option value="keep" selected="selected">' . __('Do not change the password') . '</option>' . "\n" : '')
884 . ' <option value="none"';
885 if (isset($GLOBALS['username']) && $mode != 'change') {
886 echo ' selected="selected"';
888 echo '>' . __('No Password') . '</option>' . "\n"
889 . ' <option value="userdefined"' . (isset($GLOBALS['username']) ? '' : ' selected="selected"') . '>' . __('Use text field') . ':</option>' . "\n"
890 . ' </select>' . "\n"
891 . '</span>' . "\n"
892 . '<input type="password" id="text_pma_pw" name="pma_pw" title="' . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
893 . '</div>' . "\n"
894 . '<div class="item" id="div_element_before_generate_password">' . "\n"
895 . '<label for="text_pma_pw2">' . "\n"
896 . ' ' . __('Re-type') . ':' . "\n"
897 . '</label>' . "\n"
898 . '<span class="options">&nbsp;</span>' . "\n"
899 . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="' . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
900 . '</div>' . "\n"
901 // Generate password added here via jQuery
902 . '</fieldset>' . "\n";
903 } // end of the 'PMA_displayUserAndHostFields()' function
906 * Changes / copies a user, part I
908 if (isset($_REQUEST['change_copy'])) {
909 $user_host_condition = ' WHERE `User`'
910 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
911 .' AND `Host`'
912 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
913 $row = PMA_DBI_fetch_single_row('SELECT * FROM `mysql`.`user` ' . $user_host_condition);
914 if (! $row) {
915 PMA_Message::notice(__('No user found.'))->display();
916 unset($_REQUEST['change_copy']);
917 } else {
918 extract($row, EXTR_OVERWRITE);
919 // Recent MySQL versions have the field "Password" in mysql.user,
920 // so the previous extract creates $Password but this script
921 // uses $password
922 if (! isset($password) && isset($Password)) {
923 $password = $Password;
925 $queries = array();
931 * Adds a user
932 * (Changes / copies a user, part II)
934 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
935 $sql_query = '';
936 if ($pred_username == 'any') {
937 $username = '';
939 switch ($pred_hostname) {
940 case 'any':
941 $hostname = '%';
942 break;
943 case 'localhost':
944 $hostname = 'localhost';
945 break;
946 case 'hosttable':
947 $hostname = '';
948 break;
949 case 'thishost':
950 $_user_name = PMA_DBI_fetch_value('SELECT USER()');
951 $hostname = substr($_user_name, (strrpos($_user_name, '@') + 1));
952 unset($_user_name);
953 break;
955 $sql = "SELECT '1' FROM `mysql`.`user`"
956 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
957 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
958 if (PMA_DBI_fetch_value($sql) == 1) {
959 $message = PMA_Message::error(__('The user %s already exists!'));
960 $message->addParam('[i]\'' . $username . '\'@\'' . $hostname . '\'[/i]');
961 $_REQUEST['adduser'] = true;
962 $_add_user_error = true;
963 } else {
965 $create_user_real = 'CREATE USER \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
967 $real_sql_query = 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
968 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
969 if ($pred_password != 'none' && $pred_password != 'keep') {
970 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
971 $real_sql_query .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
972 if (isset($create_user_real)) {
973 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
974 $create_user_real .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
976 } else {
977 if ($pred_password == 'keep' && ! empty($password)) {
978 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
979 if (isset($create_user_real)) {
980 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
983 $sql_query = $real_sql_query;
984 if (isset($create_user_real)) {
985 $create_user_show = $create_user_real;
989 * @todo similar code appears twice in this script
991 if ((isset($Grant_priv) && $Grant_priv == 'Y')
992 || (isset($max_questions) || isset($max_connections)
993 || isset($max_updates) || isset($max_user_connections))
995 $real_sql_query .= ' WITH';
996 $sql_query .= ' WITH';
997 if (isset($Grant_priv) && $Grant_priv == 'Y') {
998 $real_sql_query .= ' GRANT OPTION';
999 $sql_query .= ' GRANT OPTION';
1001 if (isset($max_questions)) {
1002 // avoid negative values
1003 $max_questions = max(0, (int)$max_questions);
1004 $real_sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1005 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1007 if (isset($max_connections)) {
1008 $max_connections = max(0, (int)$max_connections);
1009 $real_sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1010 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1012 if (isset($max_updates)) {
1013 $max_updates = max(0, (int)$max_updates);
1014 $real_sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1015 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1017 if (isset($max_user_connections)) {
1018 $max_user_connections = max(0, (int)$max_user_connections);
1019 $real_sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1020 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1023 if (isset($create_user_real)) {
1024 $create_user_real .= ';';
1025 $create_user_show .= ';';
1027 $real_sql_query .= ';';
1028 $sql_query .= ';';
1029 if (empty($_REQUEST['change_copy'])) {
1030 $_error = false;
1032 if (isset($create_user_real)) {
1033 if (! PMA_DBI_try_query($create_user_real)) {
1034 $_error = true;
1036 $sql_query = $create_user_show . $sql_query;
1039 if ($_error || ! PMA_DBI_try_query($real_sql_query)) {
1040 $_REQUEST['createdb'] = false;
1041 $message = PMA_Message::rawError(PMA_DBI_getError());
1042 } else {
1043 $message = PMA_Message::success(__('You have added a new user.'));
1046 switch (PMA_ifSetOr($_REQUEST['createdb'], '0')) {
1047 case '1' :
1048 // Create database with same name and grant all privileges
1049 $q = 'CREATE DATABASE IF NOT EXISTS '
1050 . PMA_backquote(PMA_sqlAddSlashes($username)) . ';';
1051 $sql_query .= $q;
1052 if (! PMA_DBI_try_query($q)) {
1053 $message = PMA_Message::rawError(PMA_DBI_getError());
1054 break;
1059 * If we are not in an Ajax request, we can't reload navigation now
1061 if ($GLOBALS['is_ajax_request'] != true) {
1062 // this is needed in case tracking is on:
1063 $GLOBALS['db'] = $username;
1064 $GLOBALS['reload'] = true;
1065 PMA_reloadNavigation();
1068 $q = 'GRANT ALL PRIVILEGES ON '
1069 . PMA_backquote(PMA_sqlAddSlashes($username)) . '.* TO \''
1070 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1071 $sql_query .= $q;
1072 if (! PMA_DBI_try_query($q)) {
1073 $message = PMA_Message::rawError(PMA_DBI_getError());
1075 break;
1076 case '2' :
1077 // Grant all privileges on wildcard name (username\_%)
1078 $q = 'GRANT ALL PRIVILEGES ON '
1079 . PMA_backquote(PMA_sqlAddSlashes($username) . '\_%') . '.* TO \''
1080 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1081 $sql_query .= $q;
1082 if (! PMA_DBI_try_query($q)) {
1083 $message = PMA_Message::rawError(PMA_DBI_getError());
1085 break;
1086 case '3' :
1087 // Grant all privileges on the specified database to the new user
1088 $q = 'GRANT ALL PRIVILEGES ON '
1089 . PMA_backquote(PMA_sqlAddSlashes($dbname)) . '.* TO \''
1090 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1091 $sql_query .= $q;
1092 if (! PMA_DBI_try_query($q)) {
1093 $message = PMA_Message::rawError(PMA_DBI_getError());
1095 break;
1096 case '0' :
1097 default :
1098 break;
1100 } else {
1101 if (isset($create_user_real)) {
1102 $queries[] = $create_user_real;
1104 $queries[] = $real_sql_query;
1105 // we put the query containing the hidden password in
1106 // $queries_for_display, at the same position occupied
1107 // by the real query in $queries
1108 $tmp_count = count($queries);
1109 if (isset($create_user_real)) {
1110 $queries_for_display[$tmp_count - 2] = $create_user_show;
1112 $queries_for_display[$tmp_count - 1] = $sql_query;
1114 unset($res, $real_sql_query);
1120 * Changes / copies a user, part III
1122 if (isset($_REQUEST['change_copy'])) {
1123 $user_host_condition = ' WHERE `User`'
1124 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1125 .' AND `Host`'
1126 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
1127 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1128 while ($row = PMA_DBI_fetch_assoc($res)) {
1129 $queries[] = 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1130 .' ON ' . PMA_backquote($row['Db']) . '.*'
1131 .' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1132 . ($row['Grant_priv'] == 'Y' ? ' WITH GRANT OPTION;' : ';');
1134 PMA_DBI_free_result($res);
1135 $res = PMA_DBI_query(
1136 'SELECT `Db`, `Table_name`, `Table_priv` FROM `mysql`.`tables_priv`' . $user_host_condition,
1137 $GLOBALS['userlink'],
1138 PMA_DBI_QUERY_STORE
1140 while ($row = PMA_DBI_fetch_assoc($res)) {
1142 $res2 = PMA_DBI_QUERY(
1143 'SELECT `Column_name`, `Column_priv`'
1144 .' FROM `mysql`.`columns_priv`'
1145 .' WHERE `User`'
1146 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1147 .' AND `Host`'
1148 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\''
1149 .' AND `Db`'
1150 .' = \'' . PMA_sqlAddSlashes($row['Db']) . "'"
1151 .' AND `Table_name`'
1152 .' = \'' . PMA_sqlAddSlashes($row['Table_name']) . "'"
1153 .';',
1154 null,
1155 PMA_DBI_QUERY_STORE
1158 $tmp_privs1 = PMA_extractPrivInfo($row);
1159 $tmp_privs2 = array(
1160 'Select' => array(),
1161 'Insert' => array(),
1162 'Update' => array(),
1163 'References' => array()
1166 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1167 $tmp_array = explode(',', $row2['Column_priv']);
1168 if (in_array('Select', $tmp_array)) {
1169 $tmp_privs2['Select'][] = $row2['Column_name'];
1171 if (in_array('Insert', $tmp_array)) {
1172 $tmp_privs2['Insert'][] = $row2['Column_name'];
1174 if (in_array('Update', $tmp_array)) {
1175 $tmp_privs2['Update'][] = $row2['Column_name'];
1177 if (in_array('References', $tmp_array)) {
1178 $tmp_privs2['References'][] = $row2['Column_name'];
1180 unset($tmp_array);
1182 if (count($tmp_privs2['Select']) > 0 && ! in_array('SELECT', $tmp_privs1)) {
1183 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1185 if (count($tmp_privs2['Insert']) > 0 && ! in_array('INSERT', $tmp_privs1)) {
1186 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1188 if (count($tmp_privs2['Update']) > 0 && ! in_array('UPDATE', $tmp_privs1)) {
1189 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1191 if (count($tmp_privs2['References']) > 0 && ! in_array('REFERENCES', $tmp_privs1)) {
1192 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1194 unset($tmp_privs2);
1195 $queries[] = 'GRANT ' . join(', ', $tmp_privs1)
1196 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1197 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1198 . (in_array('Grant', explode(',', $row['Table_priv'])) ? ' WITH GRANT OPTION;' : ';');
1204 * Updates privileges
1206 if (! empty($update_privs)) {
1207 $db_and_table = PMA_wildcardEscapeForGrant($dbname, (isset($tablename) ? $tablename : ''));
1209 $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1210 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1211 if (! isset($Grant_priv) || $Grant_priv != 'Y') {
1212 $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
1213 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1214 } else {
1215 $sql_query1 = '';
1218 // Should not do a GRANT USAGE for a table-specific privilege, it
1219 // causes problems later (cannot revoke it)
1220 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1221 $sql_query2 = 'GRANT ' . join(', ', PMA_extractPrivInfo())
1222 . ' ON ' . $db_and_table
1223 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
1226 * @todo similar code appears twice in this script
1228 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1229 || (! isset($dbname)
1230 && (isset($max_questions) || isset($max_connections)
1231 || isset($max_updates) || isset($max_user_connections)))
1233 $sql_query2 .= 'WITH';
1234 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1235 $sql_query2 .= ' GRANT OPTION';
1237 if (isset($max_questions)) {
1238 $max_questions = max(0, (int)$max_questions);
1239 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1241 if (isset($max_connections)) {
1242 $max_connections = max(0, (int)$max_connections);
1243 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1245 if (isset($max_updates)) {
1246 $max_updates = max(0, (int)$max_updates);
1247 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1249 if (isset($max_user_connections)) {
1250 $max_user_connections = max(0, (int)$max_user_connections);
1251 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1254 $sql_query2 .= ';';
1256 if (! PMA_DBI_try_query($sql_query0)) {
1257 // This might fail when the executing user does not have ALL PRIVILEGES himself.
1258 // See https://sourceforge.net/tracker/index.php?func=detail&aid=3285929&group_id=23067&atid=377408
1259 $sql_query0 = '';
1261 if (isset($sql_query1) && ! PMA_DBI_try_query($sql_query1)) {
1262 // this one may fail, too...
1263 $sql_query1 = '';
1265 if (isset($sql_query2)) {
1266 PMA_DBI_query($sql_query2);
1267 } else {
1268 $sql_query2 = '';
1270 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1271 $message = PMA_Message::success(__('You have updated the privileges for %s.'));
1272 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1277 * Revokes Privileges
1279 if (isset($_REQUEST['revokeall'])) {
1280 $db_and_table = PMA_wildcardEscapeForGrant($dbname, isset($tablename) ? $tablename : '');
1282 $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1283 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1284 $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
1285 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1287 PMA_DBI_query($sql_query0);
1288 if (! PMA_DBI_try_query($sql_query1)) {
1289 // this one may fail, too...
1290 $sql_query1 = '';
1292 $sql_query = $sql_query0 . ' ' . $sql_query1;
1293 $message = PMA_Message::success(__('You have revoked the privileges for %s'));
1294 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1295 if (! isset($tablename)) {
1296 unset($dbname);
1297 } else {
1298 unset($tablename);
1304 * Updates the password
1306 if (isset($_REQUEST['change_pw'])) {
1307 // similar logic in user_password.php
1308 $message = '';
1310 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1311 if ($pma_pw != $pma_pw2) {
1312 $message = PMA_Message::error(__('The passwords aren\'t the same!'));
1313 } elseif (empty($pma_pw) || empty($pma_pw2)) {
1314 $message = PMA_Message::error(__('The password is empty!'));
1316 } // end if
1318 // here $nopass could be == 1
1319 if (empty($message)) {
1321 $hashing_function = (! empty($pw_hash) && $pw_hash == 'old' ? 'OLD_' : '')
1322 . 'PASSWORD';
1324 // in $sql_query which will be displayed, hide the password
1325 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1326 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . PMA_sqlAddSlashes($pma_pw) . '\')');
1327 PMA_DBI_try_query($local_query)
1328 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, false, $err_url);
1329 $message = PMA_Message::success(__('The password for %s was changed successfully.'));
1330 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1336 * Deletes users
1337 * (Changes / copies a user, part IV)
1340 if (isset($_REQUEST['delete']) || (isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1341 if (isset($_REQUEST['change_copy'])) {
1342 $selected_usr = array($old_username . '&amp;#27;' . $old_hostname);
1343 } else {
1344 $selected_usr = $_REQUEST['selected_usr'];
1345 $queries = array();
1347 foreach ($selected_usr as $each_user) {
1348 list($this_user, $this_host) = explode('&amp;#27;', $each_user);
1349 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1350 $queries[] = 'DROP USER \'' . PMA_sqlAddSlashes($this_user) . '\'@\'' . PMA_sqlAddSlashes($this_host) . '\';';
1352 if (isset($_REQUEST['drop_users_db'])) {
1353 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1354 $GLOBALS['reload'] = true;
1356 if ($GLOBALS['is_ajax_request'] != true) {
1357 PMA_reloadNavigation();
1361 if (empty($_REQUEST['change_copy'])) {
1362 if (empty($queries)) {
1363 $message = PMA_Message::error(__('No users selected for deleting!'));
1364 } else {
1365 if ($_REQUEST['mode'] == 3) {
1366 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1367 $queries[] = 'FLUSH PRIVILEGES;';
1369 $drop_user_error = '';
1370 foreach ($queries as $sql_query) {
1371 if ($sql_query{0} != '#') {
1372 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1373 $drop_user_error .= PMA_DBI_getError() . "\n";
1377 // tracking sets this, causing the deleted db to be shown in navi
1378 unset($GLOBALS['db']);
1380 $sql_query = join("\n", $queries);
1381 if (! empty($drop_user_error)) {
1382 $message = PMA_Message::rawError($drop_user_error);
1383 } else {
1384 $message = PMA_Message::success(__('The selected users have been deleted successfully.'));
1387 unset($queries);
1393 * Changes / copies a user, part V
1395 if (isset($_REQUEST['change_copy'])) {
1396 $tmp_count = 0;
1397 foreach ($queries as $sql_query) {
1398 if ($sql_query{0} != '#') {
1399 PMA_DBI_query($sql_query);
1401 // when there is a query containing a hidden password, take it
1402 // instead of the real query sent
1403 if (isset($queries_for_display[$tmp_count])) {
1404 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1406 $tmp_count++;
1408 $message = PMA_Message::success();
1409 $sql_query = join("\n", $queries);
1414 * Reloads the privilege tables into memory
1416 if (isset($_REQUEST['flush_privileges'])) {
1417 $sql_query = 'FLUSH PRIVILEGES;';
1418 PMA_DBI_query($sql_query);
1419 $message = PMA_Message::success(__('The privileges were reloaded successfully.'));
1423 * defines some standard links
1425 $link_edit = '<a class="edit_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . str_replace($GLOBALS['url_query'], '%', '%%')
1426 . '&amp;username=%s'
1427 . '&amp;hostname=%s'
1428 . '&amp;dbname=%s'
1429 . '&amp;tablename=%s">'
1430 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1431 . '</a>';
1433 $link_revoke = '<a href="server_privileges.php?' . str_replace($GLOBALS['url_query'], '%', '%%')
1434 . '&amp;username=%s'
1435 . '&amp;hostname=%s'
1436 . '&amp;dbname=%s'
1437 . '&amp;tablename=%s'
1438 . '&amp;revokeall=1">'
1439 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1440 . '</a>';
1442 $link_export = '<a class="export_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . str_replace($GLOBALS['url_query'], '%', '%%')
1443 . '&amp;username=%s'
1444 . '&amp;hostname=%s'
1445 . '&amp;initial=%s'
1446 . '&amp;export=1">'
1447 . PMA_getIcon('b_tblexport.png', __('Export'))
1448 . '</a>';
1451 * If we are in an Ajax request for Create User/Edit User/Revoke User/
1452 * Flush Privileges, show $message and exit.
1454 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'])) {
1456 if (isset($sql_query)) {
1457 $extra_data['sql_query'] = PMA_showMessage(null, $sql_query);
1460 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
1462 * generate html on the fly for the new user that was just created.
1464 $new_user_string = '<tr>'."\n"
1465 .'<td> <input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_" value="' . htmlspecialchars($username) . '&amp;#27;' . htmlspecialchars($hostname) . '" /> </td>' . "\n"
1466 .'<td><label for="checkbox_sel_users_">' . (empty($username) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($username) ) . '</label></td>' . "\n"
1467 .'<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
1468 $new_user_string .= '<td>';
1470 if (! empty($password) || isset($pma_pw)) {
1471 $new_user_string .= __('Yes');
1472 } else {
1473 $new_user_string .= '<span style="color: #FF0000">' . __('No') . '</span>';
1476 $new_user_string .= '</td>'."\n";
1477 $new_user_string .= '<td><tt>' . join(', ', PMA_extractPrivInfo('', true)) . '</tt></td>'; //Fill in privileges here
1478 $new_user_string .= '<td>';
1480 if ((isset($Grant_priv) && $Grant_priv == 'Y')) {
1481 $new_user_string .= __('Yes');
1482 } else {
1483 $new_user_string .= __('No');
1486 $new_user_string .='</td>';
1488 $new_user_string .= '<td>' . sprintf($link_edit, urlencode($username), urlencode($hostname), '', '') . '</td>' . "\n";
1489 $new_user_string .= '<td>' . sprintf($link_export, urlencode($username), urlencode($hostname), (isset($initial) ? $initial : '')) . '</td>' . "\n";
1491 $new_user_string .= '</tr>';
1493 $extra_data['new_user_string'] = $new_user_string;
1496 * Generate the string for this alphabet's initial, to update the user
1497 * pagination
1499 $new_user_initial = strtoupper(substr($username, 0, 1));
1500 $new_user_initial_string = '<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . $new_user_initial
1501 .'">' . $new_user_initial . '</a>';
1502 $extra_data['new_user_initial'] = $new_user_initial;
1503 $extra_data['new_user_initial_string'] = $new_user_initial_string;
1506 if (isset($update_privs)) {
1507 $extra_data['db_specific_privs'] = false;
1508 if (isset($dbname_is_wildcard)) {
1509 $extra_data['db_specific_privs'] = ! $dbname_is_wildcard;
1511 $new_privileges = join(', ', PMA_extractPrivInfo('', true));
1513 $extra_data['new_privileges'] = $new_privileges;
1516 if ($message instanceof PMA_Message) {
1517 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
1522 * Displays the links
1524 if (isset($viewing_mode) && $viewing_mode == 'db') {
1525 $db = $checkprivs;
1526 $url_query .= '&amp;goto=db_operations.php';
1528 // Gets the database structure
1529 $sub_part = '_structure';
1530 include './libraries/db_info.inc.php';
1531 echo "\n";
1532 } else {
1533 include './libraries/server_links.inc.php';
1538 * Displays the page
1541 // export user definition
1542 if (isset($_REQUEST['export'])) {
1543 echo '<h2>' . __('User') . ' \'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'</h2>';
1544 echo '<textarea cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1545 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddSlashes($username) . "'@'" . PMA_sqlAddSlashes($hostname) . "'");
1546 foreach ($grants as $one_grant) {
1547 echo $one_grant . ";\n\n";
1549 echo '</textarea>';
1550 unset($username, $hostname, $grants, $one_grant);
1551 if ($GLOBALS['is_ajax_request']) {
1552 exit;
1556 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs))) {
1557 if (! isset($username)) {
1558 // No username is given --> display the overview
1559 echo '<h2>' . "\n"
1560 . PMA_getIcon('b_usrlist.png')
1561 . __('User overview') . "\n"
1562 . '</h2>' . "\n";
1564 $sql_query = 'SELECT *,' .
1565 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1566 ' FROM `mysql`.`user`';
1568 $sql_query .= (isset($initial) ? PMA_rangeOfUsers($initial) : '');
1570 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1571 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1573 if (! $res) {
1574 // the query failed! This may have two reasons:
1575 // - the user does not have enough privileges
1576 // - the privilege tables use a structure of an earlier version.
1577 // so let's try a more simple query
1579 $sql_query = 'SELECT * FROM `mysql`.`user`';
1580 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1582 if (! $res) {
1583 PMA_Message::error(__('No Privileges'))->display();
1584 PMA_DBI_free_result($res);
1585 unset($res);
1586 } else {
1587 // This message is hardcoded because I will replace it by
1588 // a automatic repair feature soon.
1589 $raw = 'Your privilege table structure seems to be older than'
1590 . ' this MySQL version!<br />'
1591 . 'Please run the <tt>mysql_upgrade</tt> command'
1592 . '(<tt>mysql_fix_privilege_tables</tt> on older systems)'
1593 . ' that should be included in your MySQL server distribution'
1594 . ' to solve this problem!';
1595 PMA_Message::rawError($raw)->display();
1597 } else {
1599 // we also want users not in table `user` but in other table
1600 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1602 $tables_to_search_for_users = array(
1603 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1606 $db_rights_sqls = array();
1607 foreach ($tables_to_search_for_users as $table_search_in) {
1608 if (in_array($table_search_in, $tables)) {
1609 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ? PMA_rangeOfUsers($initial) : '');
1613 $user_defaults = array(
1614 'User' => '',
1615 'Host' => '%',
1616 'Password' => '?',
1617 'Grant_priv' => 'N',
1618 'privs' => array('USAGE'),
1621 // for all initials, even non A-Z
1622 $array_initials = array();
1623 // for the rights
1624 $db_rights = array();
1626 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1627 .' ORDER BY `User` ASC, `Host` ASC';
1629 $db_rights_result = PMA_DBI_query($db_rights_sql);
1631 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1632 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1633 $db_rights[$db_rights_row['User']][$db_rights_row['Host']] =
1634 $db_rights_row;
1636 PMA_DBI_free_result($db_rights_result);
1637 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1638 ksort($db_rights);
1641 * Displays the initials
1642 * In an Ajax request, we don't need to show this.
1643 * Also not necassary if there is less than 20 privileges
1645 if ($GLOBALS['is_ajax_request'] != true && PMA_DBI_num_rows($res) > 20 ) {
1647 // initialize to false the letters A-Z
1648 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++) {
1649 if (! isset($array_initials[chr($letter_counter + 64)])) {
1650 $array_initials[chr($letter_counter + 64)] = false;
1654 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE);
1655 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1656 $array_initials[$tmp_initial] = true;
1659 // Display the initials, which can be any characters, not
1660 // just letters. For letters A-Z, we add the non-used letters
1661 // as greyed out.
1663 uksort($array_initials, "strnatcasecmp");
1665 echo '<table id="initials_table" class="' . $conditional_class . '" <cellspacing="5"><tr>';
1666 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1667 if ($initial_was_found) {
1668 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1669 } else {
1670 echo '<td>' . $tmp_initial . '</td>';
1673 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;showall=1" class="nowrap">[' . __('Show all') . ']</a></td>' . "\n";
1674 echo '</tr></table>';
1678 * Display the user overview
1679 * (if less than 50 users, display them immediately)
1682 if (isset($initial) || isset($showall) || PMA_DBI_num_rows($res) < 50) {
1684 while ($row = PMA_DBI_fetch_assoc($res)) {
1685 $row['privs'] = PMA_extractPrivInfo($row, true);
1686 $db_rights[$row['User']][$row['Host']] = $row;
1688 @PMA_DBI_free_result($res);
1689 unset($res);
1691 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1692 . PMA_generate_common_hidden_inputs('', '')
1693 . ' <table id="tableuserrights" class="data">' . "\n"
1694 . ' <thead>' . "\n"
1695 . ' <tr><th></th>' . "\n"
1696 . ' <th>' . __('User') . '</th>' . "\n"
1697 . ' <th>' . __('Host') . '</th>' . "\n"
1698 . ' <th>' . __('Password') . '</th>' . "\n"
1699 . ' <th>' . __('Global privileges') . ' '
1700 . PMA_showHint(__('Note: MySQL privilege names are expressed in English')) . '</th>' . "\n"
1701 . ' <th>' . __('Grant') . '</th>' . "\n"
1702 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1703 echo ' </tr>' . "\n";
1704 echo ' </thead>' . "\n";
1705 echo ' <tbody>' . "\n";
1706 $odd_row = true;
1707 $index_checkbox = -1;
1708 foreach ($db_rights as $user) {
1709 $index_checkbox++;
1710 ksort($user);
1711 foreach ($user as $host) {
1712 $index_checkbox++;
1713 echo ' <tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
1714 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1715 . $index_checkbox . '" value="'
1716 . htmlspecialchars($host['User'] . '&amp;#27;' . $host['Host'])
1717 . '"'
1718 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
1719 . ' /></td>' . "\n"
1720 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1721 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1722 echo ' <td>';
1723 switch ($host['Password']) {
1724 case 'Y':
1725 echo __('Yes');
1726 break;
1727 case 'N':
1728 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1729 break;
1730 // this happens if this is a definition not coming from mysql.user
1731 default:
1732 echo '--'; // in future version, replace by "not present"
1733 break;
1734 } // end switch
1735 echo '</td>' . "\n"
1736 . ' <td><tt>' . "\n"
1737 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1738 . ' </tt></td>' . "\n"
1739 . ' <td>' . ($host['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . '</td>' . "\n"
1740 . ' <td align="center">';
1741 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1742 echo '</td>';
1743 echo '<td align="center">';
1744 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ? $initial : ''));
1745 echo '</td>';
1746 echo '</tr>';
1747 $odd_row = ! $odd_row;
1751 unset($user, $host, $odd_row);
1752 echo ' </tbody></table>' . "\n"
1753 .'<img class="selectallarrow"'
1754 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1755 .' width="38" height="22"'
1756 .' alt="' . __('With selected:') . '" />' . "\n"
1757 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;checkall=1"'
1758 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1759 . __('Check All') . '</a>' . "\n"
1760 .'/' . "\n"
1761 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1762 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1763 . __('Uncheck All') . '</a>' . "\n";
1765 // add/delete user fieldset
1766 echo ' <fieldset id="fieldset_add_user">' . "\n"
1767 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1768 . PMA_getIcon('b_usradd.png')
1769 . ' ' . __('Add user') . '</a>' . "\n"
1770 . ' </fieldset>' . "\n"
1771 . ' <fieldset id="fieldset_delete_user">'
1772 . ' <legend>' . "\n"
1773 . PMA_getIcon('b_usrdrop.png')
1774 . ' ' . __('Remove selected users') . '' . "\n"
1775 . ' </legend>' . "\n"
1776 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1777 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1778 . ' <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"
1779 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1780 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1781 . ' </label>' . "\n"
1782 . ' </fieldset>' . "\n"
1783 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1784 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" class="' . $conditional_class . '"/>' . "\n"
1785 . ' </fieldset>' . "\n"
1786 . '</form>' . "\n";
1787 } else {
1789 unset ($row);
1790 echo ' <fieldset id="fieldset_add_user">' . "\n"
1791 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1792 . PMA_getIcon('b_usradd.png')
1793 . ' ' . __('Add user') . '</a>' . "\n"
1794 . ' </fieldset>' . "\n";
1795 } // end if (display overview)
1797 if ($GLOBALS['is_ajax_request']) {
1798 exit;
1801 $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);
1802 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;flush_privileges=1" id="reload_privileges_anchor" class="' . $conditional_class . '">', false);
1803 $flushnote->addParam('</a>', false);
1804 $flushnote->display();
1808 } else {
1810 // A user was selected -> display the user's properties
1812 // In an Ajax request, prevent cached values from showing
1813 if ($GLOBALS['is_ajax_request'] == true) {
1814 header('Cache-Control: no-cache');
1817 echo '<h2>' . "\n"
1818 . PMA_getIcon('b_usredit.png')
1819 . __('Edit Privileges') . ': '
1820 . __('User');
1822 if (isset($dbname)) {
1823 echo ' <i><a href="server_privileges.php?'
1824 . $GLOBALS['url_query'] . '&amp;username=' . htmlspecialchars(urlencode($username))
1825 . '&amp;hostname=' . htmlspecialchars(urlencode($hostname)) . '&amp;dbname=&amp;tablename=">\''
1826 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1827 . '\'</a></i>' . "\n";
1828 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
1830 echo ' - ' . ($dbname_is_wildcard ? __('Databases') : __('Database') );
1831 if (isset($tablename)) {
1832 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
1833 . '&amp;username=' . htmlspecialchars(urlencode($username)) . '&amp;hostname=' . htmlspecialchars(urlencode($hostname))
1834 . '&amp;dbname=' . htmlspecialchars($url_dbname) . '&amp;tablename=">' . htmlspecialchars($dbname) . '</a></i>';
1835 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
1836 } else {
1837 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
1840 } else {
1841 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1842 . '\'</i>' . "\n";
1845 echo '</h2>' . "\n";
1848 $sql = "SELECT '1' FROM `mysql`.`user`"
1849 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
1850 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
1851 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
1852 unset($sql);
1853 if ($user_does_not_exists) {
1854 PMA_Message::error(__('The selected user was not found in the privilege table.'))->display();
1855 PMA_displayLoginInformationFields();
1856 //require './libraries/footer.inc.php';
1859 echo '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n";
1860 $_params = array(
1861 'username' => $username,
1862 'hostname' => $hostname,
1864 if (isset($dbname)) {
1865 $_params['dbname'] = $dbname;
1866 if (isset($tablename)) {
1867 $_params['tablename'] = $tablename;
1870 echo PMA_generate_common_hidden_inputs($_params);
1872 PMA_displayPrivTable(
1873 PMA_ifSetOr($dbname, '*', 'length'),
1874 PMA_ifSetOr($tablename, '*', 'length')
1877 echo '</form>' . "\n";
1879 if (! isset($tablename) && empty($dbname_is_wildcard)) {
1881 // no table name was given, display all table specific rights
1882 // but only if $dbname contains no wildcards
1884 // table header
1885 echo '<form action="server_privileges.php" id="db_or_table_specific_priv" method="post">' . "\n"
1886 . PMA_generate_common_hidden_inputs('', '')
1887 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
1888 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1889 . '<fieldset>' . "\n"
1890 . '<legend>' . (! isset($dbname) ? __('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
1891 . '<table class="data">' . "\n"
1892 . '<thead>' . "\n"
1893 . '<tr><th>' . (! isset($dbname) ? __('Database') : __('Table')) . '</th>' . "\n"
1894 . ' <th>' . __('Privileges') . '</th>' . "\n"
1895 . ' <th>' . __('Grant') . '</th>' . "\n"
1896 . ' <th>' . (! isset($dbname) ? __('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
1897 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
1898 . '</tr>' . "\n"
1899 . '</thead>' . "\n"
1900 . '<tbody>' . "\n";
1902 $user_host_condition = ' WHERE `User`'
1903 . ' = \'' . PMA_sqlAddSlashes($username) . "'"
1904 . ' AND `Host`'
1905 . ' = \'' . PMA_sqlAddSlashes($hostname) . "'";
1907 // table body
1908 // get data
1910 // we also want privielgs for this user not in table `db` but in other table
1911 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1912 if (! isset($dbname)) {
1914 // no db name given, so we want all privs for the given user
1916 $tables_to_search_for_users = array(
1917 'tables_priv', 'columns_priv',
1920 $db_rights_sqls = array();
1921 foreach ($tables_to_search_for_users as $table_search_in) {
1922 if (in_array($table_search_in, $tables)) {
1923 $db_rights_sqls[] = '
1924 SELECT DISTINCT `Db`
1925 FROM `mysql`.' . PMA_backquote($table_search_in)
1926 . $user_host_condition;
1930 $user_defaults = array(
1931 'Db' => '',
1932 'Grant_priv' => 'N',
1933 'privs' => array('USAGE'),
1934 'Table_privs' => true,
1937 // for the rights
1938 $db_rights = array();
1940 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1941 .' ORDER BY `Db` ASC';
1943 $db_rights_result = PMA_DBI_query($db_rights_sql);
1945 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1946 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1947 // only Db names in the table `mysql`.`db` uses wildcards
1948 // as we are in the db specific rights display we want
1949 // all db names escaped, also from other sources
1950 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
1951 $db_rights_row['Db']
1953 $db_rights[$db_rights_row['Db']] = $db_rights_row;
1956 PMA_DBI_free_result($db_rights_result);
1957 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1959 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
1960 $res = PMA_DBI_query($sql_query);
1961 $sql_query = '';
1963 while ($row = PMA_DBI_fetch_assoc($res)) {
1964 if (isset($db_rights[$row['Db']])) {
1965 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
1966 } else {
1967 $db_rights[$row['Db']] = $row;
1969 // there are db specific rights for this user
1970 // so we can drop this db rights
1971 $db_rights[$row['Db']]['can_delete'] = true;
1973 PMA_DBI_free_result($res);
1974 unset($row, $res);
1976 } else {
1978 // db name was given,
1979 // so we want all user specific rights for this db
1981 $user_host_condition .=
1982 ' AND `Db`'
1983 .' LIKE \'' . PMA_sqlAddSlashes($dbname, true) . "'";
1985 $tables_to_search_for_users = array(
1986 'columns_priv',
1989 $db_rights_sqls = array();
1990 foreach ($tables_to_search_for_users as $table_search_in) {
1991 if (in_array($table_search_in, $tables)) {
1992 $db_rights_sqls[] = '
1993 SELECT DISTINCT `Table_name`
1994 FROM `mysql`.' . PMA_backquote($table_search_in)
1995 . $user_host_condition;
1999 $user_defaults = array(
2000 'Table_name' => '',
2001 'Grant_priv' => 'N',
2002 'privs' => array('USAGE'),
2003 'Column_priv' => true,
2006 // for the rights
2007 $db_rights = array();
2009 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
2010 .' ORDER BY `Table_name` ASC';
2012 $db_rights_result = PMA_DBI_query($db_rights_sql);
2014 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
2015 $db_rights_row = array_merge($user_defaults, $db_rights_row);
2016 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
2018 PMA_DBI_free_result($db_rights_result);
2019 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
2021 $sql_query = 'SELECT `Table_name`,'
2022 .' `Table_priv`,'
2023 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
2024 .' AS \'Column_priv\''
2025 .' FROM `mysql`.`tables_priv`'
2026 . $user_host_condition
2027 .' ORDER BY `Table_name` ASC;';
2028 $res = PMA_DBI_query($sql_query);
2029 $sql_query = '';
2031 while ($row = PMA_DBI_fetch_assoc($res)) {
2032 if (isset($db_rights[$row['Table_name']])) {
2033 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
2034 } else {
2035 $db_rights[$row['Table_name']] = $row;
2038 PMA_DBI_free_result($res);
2039 unset($row, $res);
2041 ksort($db_rights);
2043 // display rows
2044 if (count($db_rights) < 1) {
2045 echo '<tr class="odd">' . "\n"
2046 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
2047 . '</tr>' . "\n";
2048 } else {
2049 $odd_row = true;
2050 $found_rows = array();
2051 //while ($row = PMA_DBI_fetch_assoc($res)) {
2052 foreach ($db_rights as $row) {
2053 $found_rows[] = (! isset($dbname)) ? $row['Db'] : $row['Table_name'];
2055 echo '<tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2056 . ' <td>' . htmlspecialchars((! isset($dbname)) ? $row['Db'] : $row['Table_name']) . '</td>' . "\n"
2057 . ' <td><tt>' . "\n"
2058 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, true)) . "\n"
2059 . ' </tt></td>' . "\n"
2060 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') || (isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ? __('Yes') : __('No')) . '</td>' . "\n"
2061 . ' <td>';
2062 if (! empty($row['Table_privs']) || ! empty ($row['Column_priv'])) {
2063 echo __('Yes');
2064 } else {
2065 echo __('No');
2067 echo '</td>' . "\n"
2068 . ' <td>';
2069 printf(
2070 $link_edit,
2071 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 . ' <td>';
2078 if (! empty($row['can_delete']) || isset($row['Table_name']) && strlen($row['Table_name'])) {
2079 printf(
2080 $link_revoke,
2081 htmlspecialchars(urlencode($username)),
2082 urlencode(htmlspecialchars($hostname)),
2083 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
2084 urlencode((! isset($dbname)) ? '' : $row['Table_name'])
2087 echo '</td>' . "\n"
2088 . '</tr>' . "\n";
2089 $odd_row = ! $odd_row;
2090 } // end while
2092 unset($row);
2093 echo '</tbody>' . "\n"
2094 . '</table>' . "\n";
2096 if (! isset($dbname)) {
2098 // no database name was given, display select db
2100 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
2102 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
2103 if (! empty($pred_db_array)) {
2104 echo ' <select name="pred_dbname" class="autosubmit">' . "\n"
2105 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2106 foreach ($pred_db_array as $current_db) {
2107 $current_db = PMA_escape_mysql_wildcards($current_db);
2108 // cannot use array_diff() once, outside of the loop,
2109 // because the list of databases has special characters
2110 // already escaped in $found_rows,
2111 // contrary to the output of SHOW DATABASES
2112 if (empty($found_rows) || ! in_array($current_db, $found_rows)) {
2113 echo ' <option value="' . htmlspecialchars($current_db) . '">'
2114 . htmlspecialchars($current_db) . '</option>' . "\n";
2117 echo ' </select>' . "\n";
2119 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
2120 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
2121 } else {
2122 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
2123 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
2124 if ($res = @PMA_DBI_try_query('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE)) {
2125 $pred_tbl_array = array();
2126 while ($row = PMA_DBI_fetch_row($res)) {
2127 if (! isset($found_rows) || ! in_array($row[0], $found_rows)) {
2128 $pred_tbl_array[] = $row[0];
2131 PMA_DBI_free_result($res);
2132 unset($res, $row);
2133 if (! empty($pred_tbl_array)) {
2134 echo ' <select name="pred_tablename" class="autosubmit">' . "\n"
2135 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2136 foreach ($pred_tbl_array as $current_table) {
2137 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
2139 echo ' </select>' . "\n";
2141 } else {
2142 unset($res);
2144 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
2146 echo '</fieldset>' . "\n";
2147 echo '<fieldset class="tblFooters">' . "\n"
2148 . ' <input type="submit" value="' . __('Go') . '" />'
2149 . '</fieldset>' . "\n"
2150 . '</form>' . "\n";
2154 // Provide a line with links to the relevant database and table
2155 if (isset($dbname) && empty($dbname_is_wildcard)) {
2156 echo '[ ' . __('Database')
2157 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
2158 . $GLOBALS['url_query'] . '&amp;db=' . $url_dbname . '&amp;reload=1">'
2159 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
2161 if (isset($tablename)) {
2162 echo ' [ ' . __('Table') . ' <a href="'
2163 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
2164 . '&amp;db=' . $url_dbname . '&amp;table=' . htmlspecialchars(urlencode($tablename))
2165 . '&amp;reload=1">' . htmlspecialchars($tablename) . ': '
2166 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
2167 . "</a> ]\n";
2169 unset($url_dbname);
2172 if (! isset($dbname) && ! $user_does_not_exists) {
2173 include_once './libraries/display_change_password.lib.php';
2175 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
2176 . PMA_generate_common_hidden_inputs('', '')
2177 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
2178 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
2179 . '<fieldset id="fieldset_change_copy_user">' . "\n"
2180 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
2181 PMA_displayLoginInformationFields('change');
2182 echo ' <fieldset>' . "\n"
2183 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2184 $choices = array(
2185 '4' => __('... keep the old one.'),
2186 '1' => __('... delete the old one from the user tables.'),
2187 '2' => __('... revoke all active privileges from the old one and delete it afterwards.'),
2188 '3' => __('... delete the old one from the user tables and reload the privileges afterwards.'));
2189 PMA_display_html_radio('mode', $choices, '4', true);
2190 unset($choices);
2192 echo ' </fieldset>' . "\n"
2193 . '</fieldset>' . "\n"
2194 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2195 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2196 . '</fieldset>' . "\n"
2197 . '</form>' . "\n";
2200 } elseif (isset($_REQUEST['adduser'])) {
2202 // Add user
2203 $GLOBALS['url_query'] .= '&amp;adduser=1';
2204 echo '<h2>' . "\n"
2205 . PMA_getIcon('b_usradd.png') . __('Add user') . "\n"
2206 . '</h2>' . "\n"
2207 . '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n"
2208 . PMA_generate_common_hidden_inputs('', '');
2209 PMA_displayLoginInformationFields('new');
2210 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2211 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2213 $default_choice = 0;
2214 $choices = array(
2215 '0' => _pgettext('Create none database for user', 'None'),
2216 '1' => __('Create database with same name and grant all privileges'),
2217 '2' => __('Grant all privileges on wildcard name (username\\_%)'));
2219 if (! empty($dbname) ) {
2220 $choices['3'] = sprintf(
2221 __('Grant all privileges on database &quot;%s&quot;'),
2222 htmlspecialchars($dbname)
2224 $default_choice = 3;
2225 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2228 // 4th parameter set to true to add line breaks
2229 // 5th parameter set to false to avoid htmlspecialchars() escaping in the label
2230 // since we have some HTML in some labels
2231 PMA_display_html_radio('createdb', $choices, $default_choice, true, false);
2232 unset($choices);
2233 unset($default_choice);
2235 echo '</fieldset>' . "\n";
2236 PMA_displayPrivTable('*', '*', false);
2237 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2238 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2239 . ' </fieldset>' . "\n"
2240 . '</form>' . "\n";
2241 } else {
2242 // check the privileges for a particular database.
2243 $user_form = '<form id="usersForm"><table id="dbspecificuserrights" class="data">' . "\n"
2244 . '<caption class="tblHeaders">' . "\n"
2245 . PMA_getIcon('b_usrcheck.png')
2246 . ' ' . sprintf(__('Users having access to &quot;%s&quot;'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2247 . '</caption>' . "\n"
2248 . '<thead>' . "\n"
2249 . ' <tr><th>' . __('User') . '</th>' . "\n"
2250 . ' <th>' . __('Host') . '</th>' . "\n"
2251 . ' <th>' . __('Type') . '</th>' . "\n"
2252 . ' <th>' . __('Privileges') . '</th>' . "\n"
2253 . ' <th>' . __('Grant') . '</th>' . "\n"
2254 . ' <th>' . __('Action') . '</th>' . "\n"
2255 . ' </tr>' . "\n"
2256 . '</thead>' . "\n"
2257 . '<tbody>' . "\n";
2258 $odd_row = true;
2259 unset($row, $row1, $row2);
2261 // now, we build the table...
2262 $list_of_privileges =
2263 '`User`, '
2264 . '`Host`, '
2265 . '`Select_priv`, '
2266 . '`Insert_priv`, '
2267 . '`Update_priv`, '
2268 . '`Delete_priv`, '
2269 . '`Create_priv`, '
2270 . '`Drop_priv`, '
2271 . '`Grant_priv`, '
2272 . '`Index_priv`, '
2273 . '`Alter_priv`, '
2274 . '`References_priv`, '
2275 . '`Create_tmp_table_priv`, '
2276 . '`Lock_tables_priv`, '
2277 . '`Create_view_priv`, '
2278 . '`Show_view_priv`, '
2279 . '`Create_routine_priv`, '
2280 . '`Alter_routine_priv`, '
2281 . '`Execute_priv`';
2283 $list_of_compared_privileges =
2284 '`Select_priv` = \'N\''
2285 . ' AND `Insert_priv` = \'N\''
2286 . ' AND `Update_priv` = \'N\''
2287 . ' AND `Delete_priv` = \'N\''
2288 . ' AND `Create_priv` = \'N\''
2289 . ' AND `Drop_priv` = \'N\''
2290 . ' AND `Grant_priv` = \'N\''
2291 . ' AND `References_priv` = \'N\''
2292 . ' AND `Create_tmp_table_priv` = \'N\''
2293 . ' AND `Lock_tables_priv` = \'N\''
2294 . ' AND `Create_view_priv` = \'N\''
2295 . ' AND `Show_view_priv` = \'N\''
2296 . ' AND `Create_routine_priv` = \'N\''
2297 . ' AND `Alter_routine_priv` = \'N\''
2298 . ' AND `Execute_priv` = \'N\'';
2300 if (PMA_MYSQL_INT_VERSION >= 50106) {
2301 $list_of_privileges .=
2302 ', `Event_priv`, '
2303 . '`Trigger_priv`';
2304 $list_of_compared_privileges .=
2305 ' AND `Event_priv` = \'N\''
2306 . ' AND `Trigger_priv` = \'N\'';
2309 $sql_query = '(SELECT ' . $list_of_privileges . ', `Db`'
2310 .' FROM `mysql`.`db`'
2311 .' WHERE \'' . PMA_sqlAddSlashes($checkprivs) . "'"
2312 .' LIKE `Db`'
2313 .' AND NOT (' . $list_of_compared_privileges. ')) '
2314 .'UNION '
2315 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2316 .' FROM `mysql`.`user` '
2317 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2318 .' ORDER BY `User` ASC,'
2319 .' `Host` ASC,'
2320 .' `Db` ASC;';
2321 $res = PMA_DBI_query($sql_query);
2322 $row = PMA_DBI_fetch_assoc($res);
2323 if ($row) {
2324 $found = true;
2327 if ($found) {
2328 while (true) {
2329 // prepare the current user
2330 $current_privileges = array();
2331 $current_user = $row['User'];
2332 $current_host = $row['Host'];
2333 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2334 $current_privileges[] = $row;
2335 $row = PMA_DBI_fetch_assoc($res);
2337 $user_form .= ' <tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2338 . ' <td';
2339 if (count($current_privileges) > 1) {
2340 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2342 $user_form .= '>' . (empty($current_user) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2343 . ' </td>' . "\n"
2344 . ' <td';
2345 if (count($current_privileges) > 1) {
2346 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2348 $user_form .= '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2349 foreach ($current_privileges as $current) {
2350 $user_form .= ' <td>' . "\n"
2351 . ' ';
2352 if (! isset($current['Db']) || $current['Db'] == '*') {
2353 $user_form .= __('global');
2354 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2355 $user_form .= __('database-specific');
2356 } else {
2357 $user_form .= __('wildcard'). ': <tt>' . htmlspecialchars($current['Db']) . '</tt>';
2359 $user_form .= "\n"
2360 . ' </td>' . "\n"
2361 . ' <td>' . "\n"
2362 . ' <tt>' . "\n"
2363 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, true)) . "\n"
2364 . ' </tt>' . "\n"
2365 . ' </td>' . "\n"
2366 . ' <td>' . "\n"
2367 . ' ' . ($current['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . "\n"
2368 . ' </td>' . "\n"
2369 . ' <td>' . "\n";
2370 $user_form .= sprintf(
2371 $link_edit,
2372 urlencode($current_user),
2373 urlencode($current_host),
2374 urlencode(! isset($current['Db']) || $current['Db'] == '*' ? '' : $current['Db']),
2377 $user_form .= '</td>' . "\n"
2378 . ' </tr>' . "\n";
2380 if (empty($row) && empty($row1) && empty($row2)) {
2381 break;
2383 $odd_row = ! $odd_row;
2385 } else {
2386 $user_form .= ' <tr class="odd">' . "\n"
2387 . ' <td colspan="6">' . "\n"
2388 . ' ' . __('No user found.') . "\n"
2389 . ' </td>' . "\n"
2390 . ' </tr>' . "\n";
2392 $user_form .= '</tbody>' . "\n"
2393 . '</table></form>' . "\n";
2395 if ($GLOBALS['is_ajax_request'] == true) {
2396 $extra_data['user_form'] = $user_form;
2397 $message = PMA_Message::success(__('User has been added.'));
2398 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
2399 } else {
2400 // Offer to create a new user for the current database
2401 $user_form .= '<fieldset id="fieldset_add_user">' . "\n"
2402 . ' <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"
2403 . PMA_getIcon('b_usradd.png')
2404 . ' ' . __('Add user') . '</a>' . "\n"
2405 . '</fieldset>' . "\n";
2406 echo $user_form ;
2409 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2413 * Displays the footer
2415 echo "\n\n";
2416 require './libraries/footer.inc.php';