Translated using Weblate.
[phpmyadmin.git] / server_privileges.php
blob5f2bfca25718c935f743dec85022bf76e67226c1
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.16.custom.js';
19 $GLOBALS['js_include'][] = 'codemirror/lib/codemirror.js';
20 $GLOBALS['js_include'][] = 'codemirror/mode/mysql/mysql.js';
21 $_add_user_error = false;
23 require './libraries/server_common.inc.php';
25 if ($GLOBALS['cfg']['AjaxEnable']) {
26 $conditional_class = 'ajax';
27 } else {
28 $conditional_class = '';
31 /**
32 * Messages are built using the message name
34 $strPrivDescAllPrivileges = __('Includes all privileges except GRANT.');
35 $strPrivDescAlter = __('Allows altering the structure of existing tables.');
36 $strPrivDescAlterRoutine = __('Allows altering and dropping stored routines.');
37 $strPrivDescCreateDb = __('Allows creating new databases and tables.');
38 $strPrivDescCreateRoutine = __('Allows creating stored routines.');
39 $strPrivDescCreateTbl = __('Allows creating new tables.');
40 $strPrivDescCreateTmpTable = __('Allows creating temporary tables.');
41 $strPrivDescCreateUser = __('Allows creating, dropping and renaming user accounts.');
42 $strPrivDescCreateView = __('Allows creating new views.');
43 $strPrivDescDelete = __('Allows deleting data.');
44 $strPrivDescDropDb = __('Allows dropping databases and tables.');
45 $strPrivDescDropTbl = __('Allows dropping tables.');
46 $strPrivDescEvent = __('Allows to set up events for the event scheduler');
47 $strPrivDescExecute = __('Allows executing stored routines.');
48 $strPrivDescFile = __('Allows importing data from and exporting data into files.');
49 $strPrivDescGrant = __('Allows adding users and privileges without reloading the privilege tables.');
50 $strPrivDescIndex = __('Allows creating and dropping indexes.');
51 $strPrivDescInsert = __('Allows inserting and replacing data.');
52 $strPrivDescLockTables = __('Allows locking tables for the current thread.');
53 $strPrivDescMaxConnections = __('Limits the number of new connections the user may open per hour.');
54 $strPrivDescMaxQuestions = __('Limits the number of queries the user may send to the server per hour.');
55 $strPrivDescMaxUpdates = __('Limits the number of commands that change any table or database the user may execute per hour.');
56 $strPrivDescMaxUserConnections = __('Limits the number of simultaneous connections the user may have.');
57 $strPrivDescProcess = __('Allows viewing processes of all users');
58 $strPrivDescReferences = __('Has no effect in this MySQL version.');
59 $strPrivDescReload = __('Allows reloading server settings and flushing the server\'s caches.');
60 $strPrivDescReplClient = __('Allows the user to ask where the slaves / masters are.');
61 $strPrivDescReplSlave = __('Needed for the replication slaves.');
62 $strPrivDescSelect = __('Allows reading data.');
63 $strPrivDescShowDb = __('Gives access to the complete list of databases.');
64 $strPrivDescShowView = __('Allows performing SHOW CREATE VIEW queries.');
65 $strPrivDescShutdown = __('Allows shutting down the server.');
66 $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.');
67 $strPrivDescTrigger = __('Allows creating and dropping triggers');
68 $strPrivDescUpdate = __('Allows changing data.');
69 $strPrivDescUsage = __('No privileges.');
71 /**
72 * Checks if a dropdown box has been used for selecting a database / table
74 if (PMA_isValid($_REQUEST['pred_tablename'])) {
75 $tablename = $_REQUEST['pred_tablename'];
76 unset($pred_tablename);
77 } elseif (PMA_isValid($_REQUEST['tablename'])) {
78 $tablename = $_REQUEST['tablename'];
79 } else {
80 unset($tablename);
83 if (PMA_isValid($_REQUEST['pred_dbname'])) {
84 $dbname = $_REQUEST['pred_dbname'];
85 unset($pred_dbname);
86 } elseif (PMA_isValid($_REQUEST['dbname'])) {
87 $dbname = $_REQUEST['dbname'];
88 } else {
89 unset($dbname);
90 unset($tablename);
93 if (isset($dbname)) {
94 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
95 if (isset($tablename)) {
96 $db_and_table .= PMA_backquote($tablename);
97 } else {
98 $db_and_table .= '*';
100 } else {
101 $db_and_table = '*.*';
104 // check if given $dbname is a wildcard or not
105 if (isset($dbname)) {
106 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
107 if (preg_match('/(?<!\\\\)(?:_|%)/i', $dbname)) {
108 $dbname_is_wildcard = true;
109 } else {
110 $dbname_is_wildcard = false;
115 * Checks if the user is allowed to do what he tries to...
117 if (! $is_superuser) {
118 include './libraries/server_links.inc.php';
119 echo '<h2>' . "\n"
120 . PMA_getIcon('b_usrlist.png')
121 . __('Privileges') . "\n"
122 . '</h2>' . "\n";
123 PMA_Message::error(__('No Privileges'))->display();
124 include './libraries/footer.inc.php';
127 $random_n = mt_rand(0, 1000000); // a random number that will be appended to the id of the user forms
130 * Escapes wildcard in a database+table specification
131 * before using it in a GRANT statement.
133 * Escaping a wildcard character in a GRANT is only accepted at the global
134 * or database level, not at table level; this is why I remove
135 * the escaping character. Internally, in mysql.tables_priv.Db there are
136 * no escaping (for example test_db) but in mysql.db you'll see test\_db
137 * for a db-specific privilege.
139 * @param string $dbname Database name
140 * @param string $tablename Table name
142 * @return string the escaped (if necessary) database.table
144 function PMA_wildcardEscapeForGrant($dbname, $tablename)
147 if (! strlen($dbname)) {
148 $db_and_table = '*.*';
149 } else {
150 if (strlen($tablename)) {
151 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
152 $db_and_table .= PMA_backquote($tablename);
153 } else {
154 $db_and_table = PMA_backquote($dbname) . '.';
155 $db_and_table .= '*';
158 return $db_and_table;
162 * Generates a condition on the user name
164 * @param string $initial the user's initial
166 * @return string the generated condition
168 function PMA_rangeOfUsers($initial = '')
170 // strtolower() is used because the User field
171 // might be BINARY, so LIKE would be case sensitive
172 if (! empty($initial)) {
173 $ret = " WHERE `User` LIKE '" . PMA_sqlAddSlashes($initial, true) . "%'"
174 . " OR `User` LIKE '" . PMA_sqlAddSlashes(strtolower($initial), true) . "%'";
175 } else {
176 $ret = '';
178 return $ret;
179 } // end function
182 * Extracts the privilege information of a priv table row
184 * @param array $row the row
185 * @param boolean $enableHTML add <dfn> tag with tooltips
187 * @global resource $user_link the database connection
189 * @return array
191 function PMA_extractPrivInfo($row = '', $enableHTML = false)
193 $grants = array(
194 array(
195 'Select_priv',
196 'SELECT',
197 __('Allows reading data.')),
198 array(
199 'Insert_priv',
200 'INSERT',
201 __('Allows inserting and replacing data.')),
202 array(
203 'Update_priv',
204 'UPDATE',
205 __('Allows changing data.')),
206 array(
207 'Delete_priv',
208 'DELETE',
209 __('Allows deleting data.')),
210 array(
211 'Create_priv',
212 'CREATE',
213 __('Allows creating new databases and tables.')),
214 array(
215 'Drop_priv',
216 'DROP',
217 __('Allows dropping databases and tables.')),
218 array(
219 'Reload_priv',
220 'RELOAD',
221 __('Allows reloading server settings and flushing the server\'s caches.')),
222 array(
223 'Shutdown_priv',
224 'SHUTDOWN',
225 __('Allows shutting down the server.')),
226 array(
227 'Process_priv',
228 'PROCESS',
229 __('Allows viewing processes of all users')),
230 array(
231 'File_priv',
232 'FILE',
233 __('Allows importing data from and exporting data into files.')),
234 array(
235 'References_priv',
236 'REFERENCES',
237 __('Has no effect in this MySQL version.')),
238 array(
239 'Index_priv',
240 'INDEX',
241 __('Allows creating and dropping indexes.')),
242 array(
243 'Alter_priv',
244 'ALTER',
245 __('Allows altering the structure of existing tables.')),
246 array(
247 'Show_db_priv',
248 'SHOW DATABASES',
249 __('Gives access to the complete list of databases.')),
250 array(
251 'Super_priv',
252 'SUPER',
253 __('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.')),
254 array(
255 'Create_tmp_table_priv',
256 'CREATE TEMPORARY TABLES',
257 __('Allows creating temporary tables.')),
258 array(
259 'Lock_tables_priv',
260 'LOCK TABLES',
261 __('Allows locking tables for the current thread.')),
262 array(
263 'Repl_slave_priv',
264 'REPLICATION SLAVE',
265 __('Needed for the replication slaves.')),
266 array(
267 'Repl_client_priv',
268 'REPLICATION CLIENT',
269 __('Allows the user to ask where the slaves / masters are.')),
270 array(
271 'Create_view_priv',
272 'CREATE VIEW',
273 __('Allows creating new views.')),
274 array(
275 'Event_priv',
276 'EVENT',
277 __('Allows to set up events for the event scheduler')),
278 array(
279 'Trigger_priv',
280 'TRIGGER',
281 __('Allows creating and dropping triggers')),
282 // for table privs:
283 array(
284 'Create View_priv',
285 'CREATE VIEW',
286 __('Allows creating new views.')),
287 array(
288 'Show_view_priv',
289 'SHOW VIEW',
290 __('Allows performing SHOW CREATE VIEW queries.')),
291 // for table privs:
292 array(
293 'Show view_priv',
294 'SHOW VIEW',
295 __('Allows performing SHOW CREATE VIEW queries.')),
296 array(
297 'Create_routine_priv',
298 'CREATE ROUTINE',
299 __('Allows creating stored routines.')),
300 array(
301 'Alter_routine_priv',
302 'ALTER ROUTINE',
303 __('Allows altering and dropping stored routines.')),
304 array(
305 'Create_user_priv',
306 'CREATE USER',
307 __('Allows creating, dropping and renaming user accounts.')),
308 array(
309 'Execute_priv',
310 'EXECUTE',
311 __('Allows executing stored routines.')),
314 if (! empty($row) && isset($row['Table_priv'])) {
315 $row1 = PMA_DBI_fetch_single_row(
316 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
317 'ASSOC', $GLOBALS['userlink']
319 $av_grants = explode('\',\'', substr($row1['Type'], 5, strlen($row1['Type']) - 7));
320 unset($row1);
321 $users_grants = explode(',', $row['Table_priv']);
322 foreach ($av_grants as $current_grant) {
323 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
325 unset($current_grant);
326 unset($av_grants);
327 unset($users_grants);
329 $privs = array();
330 $allPrivileges = true;
331 foreach ($grants as $current_grant) {
332 if ((! empty($row) && isset($row[$current_grant[0]]))
333 || (empty($row) && isset($GLOBALS[$current_grant[0]]))
335 if ((! empty($row) && $row[$current_grant[0]] == 'Y')
336 || (empty($row)
337 && ($GLOBALS[$current_grant[0]] == 'Y'
338 || (is_array($GLOBALS[$current_grant[0]])
339 && count($GLOBALS[$current_grant[0]]) == $GLOBALS['column_count']
340 && empty($GLOBALS[$current_grant[0] . '_none']))))
342 if ($enableHTML) {
343 $privs[] = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
344 } else {
345 $privs[] = $current_grant[1];
347 } elseif (! empty($GLOBALS[$current_grant[0]])
348 && is_array($GLOBALS[$current_grant[0]])
349 && empty($GLOBALS[$current_grant[0] . '_none'])) {
350 if ($enableHTML) {
351 $priv_string = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
352 } else {
353 $priv_string = $current_grant[1];
355 $privs[] = $priv_string . ' (`' . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
356 } else {
357 $allPrivileges = false;
361 if (empty($privs)) {
362 if ($enableHTML) {
363 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
364 } else {
365 $privs[] = 'USAGE';
367 } elseif ($allPrivileges && (! isset($GLOBALS['grant_count']) || count($privs) == $GLOBALS['grant_count'])) {
368 if ($enableHTML) {
369 $privs = array('<dfn title="' . __('Includes all privileges except GRANT.') . '">ALL PRIVILEGES</dfn>');
370 } else {
371 $privs = array('ALL PRIVILEGES');
374 return $privs;
375 } // end of the 'PMA_extractPrivInfo()' function
378 * Displays on which column(s) a table-specific privilege is granted
380 function PMA_display_column_privs($columns, $row, $name_for_select,
381 $priv_for_header, $name, $name_for_dfn, $name_for_current)
383 echo ' <div class="item" id="div_item_' . $name . '">' . "\n"
384 . ' <label for="select_' . $name . '_priv">' . "\n"
385 . ' <tt><dfn title="' . $name_for_dfn . '">'
386 . $priv_for_header . '</dfn></tt>' . "\n"
387 . ' </label><br />' . "\n"
388 . ' <select id="select_' . $name . '_priv" name="'
389 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
391 foreach ($columns as $current_column => $current_column_privileges) {
392 echo ' <option value="' . htmlspecialchars($current_column) . '"';
393 if ($row[$name_for_select] == 'Y' || $current_column_privileges[$name_for_current]) {
394 echo ' selected="selected"';
396 echo '>' . htmlspecialchars($current_column) . '</option>' . "\n";
399 echo ' </select>' . "\n"
400 . ' <i>' . __('Or') . '</i>' . "\n"
401 . ' <label for="checkbox_' . $name_for_select
402 . '_none"><input type="checkbox"'
403 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
404 . ' name="' . $name_for_select . '_none" id="checkbox_'
405 . $name_for_select . '_none" title="' . _pgettext('None privileges', 'None') . '" />'
406 . _pgettext('None privileges', 'None') . '</label>' . "\n"
407 . ' </div>' . "\n";
408 } // end function
412 * Displays the privileges form table
414 * @param string $db the database
415 * @param string $table the table
416 * @param boolean $submit wheather to display the submit button or not
418 * @global array $cfg the phpMyAdmin configuration
419 * @global ressource $user_link the database connection
421 * @return void
423 function PMA_displayPrivTable($db = '*', $table = '*', $submit = true)
425 global $random_n;
427 if ($db == '*') {
428 $table = '*';
431 if (isset($GLOBALS['username'])) {
432 $username = $GLOBALS['username'];
433 $hostname = $GLOBALS['hostname'];
434 if ($db == '*') {
435 $sql_query = "SELECT * FROM `mysql`.`user`"
436 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
437 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
438 } elseif ($table == '*') {
439 $sql_query = "SELECT * FROM `mysql`.`db`"
440 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
441 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
442 ." AND '" . PMA_unescape_mysql_wildcards($db) . "'"
443 ." LIKE `Db`;";
444 } else {
445 $sql_query = "SELECT `Table_priv`"
446 ." FROM `mysql`.`tables_priv`"
447 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
448 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
449 ." AND `Db` = '" . PMA_unescape_mysql_wildcards($db) . "'"
450 ." AND `Table_name` = '" . PMA_sqlAddSlashes($table) . "';";
452 $row = PMA_DBI_fetch_single_row($sql_query);
454 if (empty($row)) {
455 if ($table == '*') {
456 if ($db == '*') {
457 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
458 } elseif ($table == '*') {
459 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
461 $res = PMA_DBI_query($sql_query);
462 while ($row1 = PMA_DBI_fetch_row($res)) {
463 if (substr($row1[0], 0, 4) == 'max_') {
464 $row[$row1[0]] = 0;
465 } else {
466 $row[$row1[0]] = 'N';
469 PMA_DBI_free_result($res);
470 } else {
471 $row = array('Table_priv' => '');
474 if (isset($row['Table_priv'])) {
475 $row1 = PMA_DBI_fetch_single_row(
476 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
477 'ASSOC', $GLOBALS['userlink']
479 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
480 // the View for Create is spelled with uppercase V
481 // the view for Show is spelled with lowercase v
482 // and there is a space between the words
484 $av_grants = explode('\',\'', substr($row1['Type'], strpos($row1['Type'], '(') + 2, strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3));
485 unset($row1);
486 $users_grants = explode(',', $row['Table_priv']);
488 foreach ($av_grants as $current_grant) {
489 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
491 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
493 // get collumns
494 $res = PMA_DBI_try_query('SHOW COLUMNS FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($db)) . '.' . PMA_backquote($table) . ';');
495 $columns = array();
496 if ($res) {
497 while ($row1 = PMA_DBI_fetch_row($res)) {
498 $columns[$row1[0]] = array(
499 'Select' => false,
500 'Insert' => false,
501 'Update' => false,
502 'References' => false
505 PMA_DBI_free_result($res);
507 unset($res, $row1);
509 // t a b l e - s p e c i f i c p r i v i l e g e s
510 if (! empty($columns)) {
511 $res = PMA_DBI_query(
512 'SELECT `Column_name`, `Column_priv`'
513 .' FROM `mysql`.`columns_priv`'
514 .' WHERE `User`'
515 .' = \'' . PMA_sqlAddSlashes($username) . "'"
516 .' AND `Host`'
517 .' = \'' . PMA_sqlAddSlashes($hostname) . "'"
518 .' AND `Db`'
519 .' = \'' . PMA_sqlAddSlashes(PMA_unescape_mysql_wildcards($db)) . "'"
520 .' AND `Table_name`'
521 .' = \'' . PMA_sqlAddSlashes($table) . '\';'
524 while ($row1 = PMA_DBI_fetch_row($res)) {
525 $row1[1] = explode(',', $row1[1]);
526 foreach ($row1[1] as $current) {
527 $columns[$row1[0]][$current] = true;
530 PMA_DBI_free_result($res);
531 unset($res, $row1, $current);
533 echo '<input type="hidden" name="grant_count" value="' . count($row) . '" />' . "\n"
534 . '<input type="hidden" name="column_count" value="' . count($columns) . '" />' . "\n"
535 . '<fieldset id="fieldset_user_priv">' . "\n"
536 . ' <legend>' . __('Table-specific privileges')
537 . PMA_showHint(__('Note: MySQL privilege names are expressed in English'))
538 . '</legend>' . "\n";
542 // privs that are attached to a specific column
543 PMA_display_column_privs(
544 $columns, $row, 'Select_priv', 'SELECT',
545 'select', __('Allows reading data.'), 'Select'
548 PMA_display_column_privs(
549 $columns, $row, 'Insert_priv', 'INSERT',
550 'insert', __('Allows inserting and replacing data.'), 'Insert'
553 PMA_display_column_privs(
554 $columns, $row, 'Update_priv', 'UPDATE',
555 'update', __('Allows changing data.'), 'Update'
558 PMA_display_column_privs(
559 $columns, $row, 'References_priv', 'REFERENCES', 'references',
560 __('Has no effect in this MySQL version.'), 'References'
563 // privs that are not attached to a specific column
565 echo ' <div class="item">' . "\n";
566 foreach ($row as $current_grant => $current_grant_value) {
567 if (in_array(substr($current_grant, 0, (strlen($current_grant) - 5)),
568 array('Select', 'Insert', 'Update', 'References'))) {
569 continue;
571 // make a substitution to match the messages variables;
572 // also we must substitute the grant we get, because we can't generate
573 // a form variable containing blanks (those would get changed to
574 // an underscore when receiving the POST)
575 if ($current_grant == 'Create View_priv') {
576 $tmp_current_grant = 'CreateView_priv';
577 $current_grant = 'Create_view_priv';
578 } elseif ($current_grant == 'Show view_priv') {
579 $tmp_current_grant = 'ShowView_priv';
580 $current_grant = 'Show_view_priv';
581 } else {
582 $tmp_current_grant = $current_grant;
585 echo ' <div class="item">' . "\n"
586 . ' <input type="checkbox"'
587 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
588 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
589 . '" value="Y" '
590 . ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
591 . 'title="';
593 echo (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
594 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
595 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl']) . '"/>' . "\n";
597 echo ' <label for="checkbox_' . $current_grant
598 . '"><tt><dfn title="'
599 . (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
600 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
601 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl'])
602 . '">' . strtoupper(substr($current_grant, 0, strlen($current_grant) - 5)) . '</dfn></tt></label>' . "\n"
603 . ' </div>' . "\n";
604 } // end foreach ()
606 echo ' </div>' . "\n";
607 // for Safari 2.0.2
608 echo ' <div class="clearfloat"></div>' . "\n";
610 } else {
612 // g l o b a l o r d b - s p e c i f i c
614 $privTable_names = array(0 => __('Data'), 1 => __('Structure'), 2 => __('Administration'));
616 // d a t a
617 $privTable[0] = array(
618 array('Select', 'SELECT', __('Allows reading data.')),
619 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
620 array('Update', 'UPDATE', __('Allows changing data.')),
621 array('Delete', 'DELETE', __('Allows deleting data.'))
623 if ($db == '*') {
624 $privTable[0][] = array('File', 'FILE', __('Allows importing data from and exporting data into files.'));
627 // s t r u c t u r e
628 $privTable[1] = array(
629 array('Create', 'CREATE', ($table == '*' ? __('Allows creating new databases and tables.') : __('Allows creating new tables.'))),
630 array('Alter', 'ALTER', __('Allows altering the structure of existing tables.')),
631 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
632 array('Drop', 'DROP', ($table == '*' ? __('Allows dropping databases and tables.') : __('Allows dropping tables.'))),
633 array('Create_tmp_table', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
634 array('Show_view', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
635 array('Create_routine', 'CREATE ROUTINE', __('Allows creating stored routines.')),
636 array('Alter_routine', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
637 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
639 // this one is for a db-specific priv: Create_view_priv
640 if (isset($row['Create_view_priv'])) {
641 $privTable[1][] = array('Create_view', 'CREATE VIEW', __('Allows creating new views.'));
643 // this one is for a table-specific priv: Create View_priv
644 if (isset($row['Create View_priv'])) {
645 $privTable[1][] = array('Create View', 'CREATE VIEW', __('Allows creating new views.'));
647 if (isset($row['Event_priv'])) {
648 // MySQL 5.1.6
649 $privTable[1][] = array('Event', 'EVENT', __('Allows to set up events for the event scheduler'));
650 $privTable[1][] = array('Trigger', 'TRIGGER', __('Allows creating and dropping triggers'));
653 // a d m i n i s t r a t i o n
654 $privTable[2] = array(
655 array('Grant', 'GRANT', __('Allows adding users and privileges without reloading the privilege tables.')),
657 if ($db == '*') {
658 $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.'));
659 $privTable[2][] = array('Process', 'PROCESS', __('Allows viewing processes of all users'));
660 $privTable[2][] = array('Reload', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.'));
661 $privTable[2][] = array('Shutdown', 'SHUTDOWN', __('Allows shutting down the server.'));
662 $privTable[2][] = array('Show_db', 'SHOW DATABASES', __('Gives access to the complete list of databases.'));
664 $privTable[2][] = array('Lock_tables', 'LOCK TABLES', __('Allows locking tables for the current thread.'));
665 $privTable[2][] = array('References', 'REFERENCES', __('Has no effect in this MySQL version.'));
666 if ($db == '*') {
667 $privTable[2][] = array('Repl_client', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.'));
668 $privTable[2][] = array('Repl_slave', 'REPLICATION SLAVE', __('Needed for the replication slaves.'));
669 $privTable[2][] = array('Create_user', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.'));
671 echo '<input type="hidden" name="grant_count" value="'
672 . (count($privTable[0]) + count($privTable[1]) + count($privTable[2]) - (isset($row['Grant_priv']) ? 1 : 0))
673 . '" />' . "\n"
674 . '<fieldset id="fieldset_user_global_rights">' . "\n"
675 . ' <legend>' . "\n"
676 . ' '
677 . ($db == '*'
678 ? __('Global privileges')
679 : ($table == '*'
680 ? __('Database-specific privileges')
681 : __('Table-specific privileges'))) . "\n"
682 . ' (<a href="server_privileges.php?'
683 . $GLOBALS['url_query'] . '&amp;checkall=1" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', true); return false;">'
684 . __('Check All') . '</a> /' . "\n"
685 . ' <a href="server_privileges.php?'
686 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', false); return false;">'
687 . __('Uncheck All') . '</a>)' . "\n"
688 . ' </legend>' . "\n"
689 . ' <p><small><i>' . __('Note: MySQL privilege names are expressed in English') . '</i></small></p>' . "\n";
691 // Output the Global privilege tables with checkboxes
692 foreach ($privTable as $i => $table) {
693 echo ' <fieldset>' . "\n"
694 . ' <legend>' . __($privTable_names[$i]) . '</legend>' . "\n";
695 foreach ($table as $priv) {
696 echo ' <div class="item">' . "\n"
697 . ' <input type="checkbox"'
698 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0] . '_priv"'
699 . ' value="Y" title="' . $priv[2] . '"'
700 . ((! empty($GLOBALS['checkall']) || $row[$priv[0] . '_priv'] == 'Y') ? ' checked="checked"' : '')
701 . '/>' . "\n"
702 . ' <label for="checkbox_' . $priv[0] . '_priv"><tt><dfn title="' . $priv[2] . '">'
703 . $priv[1] . '</dfn></tt></label>' . "\n"
704 . ' </div>' . "\n";
706 echo ' </fieldset>' . "\n";
709 // The "Resource limits" box is not displayed for db-specific privs
710 if ($db == '*') {
711 echo ' <fieldset>' . "\n"
712 . ' <legend>' . __('Resource limits') . '</legend>' . "\n"
713 . ' <p><small><i>' . __('Note: Setting these options to 0 (zero) removes the limit.') . '</i></small></p>' . "\n"
714 . ' <div class="item">' . "\n"
715 . ' <label for="text_max_questions"><tt><dfn title="'
716 . __('Limits the number of queries the user may send to the server per hour.') . '">MAX QUERIES PER HOUR</dfn></tt></label>' . "\n"
717 . ' <input type="text" name="max_questions" id="text_max_questions" value="'
718 . $row['max_questions'] . '" size="11" maxlength="11" title="' . __('Limits the number of queries the user may send to the server per hour.') . '" />' . "\n"
719 . ' </div>' . "\n"
720 . ' <div class="item">' . "\n"
721 . ' <label for="text_max_updates"><tt><dfn title="'
722 . __('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"
723 . ' <input type="text" name="max_updates" id="text_max_updates" value="'
724 . $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"
725 . ' </div>' . "\n"
726 . ' <div class="item">' . "\n"
727 . ' <label for="text_max_connections"><tt><dfn title="'
728 . __('Limits the number of new connections the user may open per hour.') . '">MAX CONNECTIONS PER HOUR</dfn></tt></label>' . "\n"
729 . ' <input type="text" name="max_connections" id="text_max_connections" value="'
730 . $row['max_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of new connections the user may open per hour.') . '" />' . "\n"
731 . ' </div>' . "\n"
732 . ' <div class="item">' . "\n"
733 . ' <label for="text_max_user_connections"><tt><dfn title="'
734 . __('Limits the number of simultaneous connections the user may have.') . '">MAX USER_CONNECTIONS</dfn></tt></label>' . "\n"
735 . ' <input type="text" name="max_user_connections" id="text_max_user_connections" value="'
736 . $row['max_user_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of simultaneous connections the user may have.') . '" />' . "\n"
737 . ' </div>' . "\n"
738 . ' </fieldset>' . "\n";
740 // for Safari 2.0.2
741 echo ' <div class="clearfloat"></div>' . "\n";
743 echo '</fieldset>' . "\n";
744 if ($submit) {
745 echo '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">' . "\n"
746 . ' <input type="submit" name="update_privs" value="' . __('Go') . '" />' . "\n"
747 . '</fieldset>' . "\n";
749 } // end of the 'PMA_displayPrivTable()' function
753 * Displays the fields used by the "new user" form as well as the
754 * "change login information / copy user" form.
756 * @param string $mode are we creating a new user or are we just
757 * changing one? (allowed values: 'new', 'change')
759 * @global array $cfg the phpMyAdmin configuration
760 * @global ressource $user_link the database connection
762 * @return void
764 function PMA_displayLoginInformationFields($mode = 'new')
766 // Get user/host name lengths
767 $fields_info = PMA_DBI_get_columns('mysql', 'user', null, true);
768 $username_length = 16;
769 $hostname_length = 41;
770 foreach ($fields_info as $val) {
771 if ($val['Field'] == 'User') {
772 strtok($val['Type'], '()');
773 $v = strtok('()');
774 if (is_int($v)) {
775 $username_length = $v;
777 } elseif ($val['Field'] == 'Host') {
778 strtok($val['Type'], '()');
779 $v = strtok('()');
780 if (is_int($v)) {
781 $hostname_length = $v;
785 unset($fields_info);
787 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
788 $GLOBALS['pred_username'] = 'any';
790 echo '<fieldset id="fieldset_add_user_login">' . "\n"
791 . '<legend>' . __('Login Information') . '</legend>' . "\n"
792 . '<div class="item">' . "\n"
793 . '<label for="select_pred_username">' . "\n"
794 . ' ' . __('User name') . ':' . "\n"
795 . '</label>' . "\n"
796 . '<span class="options">' . "\n"
797 . ' <select name="pred_username" id="select_pred_username" title="' . __('User name') . '"' . "\n"
798 . ' onchange="if (this.value == \'any\') { username.value = \'\'; } else if (this.value == \'userdefined\') { username.focus(); username.select(); }">' . "\n"
799 . ' <option value="any"' . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any') ? ' selected="selected"' : '') . '>' . __('Any user') . '</option>' . "\n"
800 . ' <option value="userdefined"' . ((! isset($GLOBALS['pred_username']) || $GLOBALS['pred_username'] == 'userdefined') ? ' selected="selected"' : '') . '>' . __('Use text field') . ':</option>' . "\n"
801 . ' </select>' . "\n"
802 . '</span>' . "\n"
803 . '<input type="text" name="username" maxlength="'
804 . $username_length . '" title="' . __('User name') . '"'
805 . (empty($GLOBALS['username'])
806 ? ''
807 : ' value="' . htmlspecialchars(isset($GLOBALS['new_username'])
808 ? $GLOBALS['new_username']
809 : $GLOBALS['username']) . '"')
810 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
811 . '</div>' . "\n"
812 . '<div class="item">' . "\n"
813 . '<label for="select_pred_hostname">' . "\n"
814 . ' ' . __('Host') . ':' . "\n"
815 . '</label>' . "\n"
816 . '<span class="options">' . "\n"
817 . ' <select name="pred_hostname" id="select_pred_hostname" title="' . __('Host') . '"' . "\n";
818 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
819 if (! empty($_current_user)) {
820 $thishost = str_replace("'", '', substr($_current_user, (strrpos($_current_user, '@') + 1)));
821 if ($thishost == 'localhost' || $thishost == '127.0.0.1') {
822 unset($thishost);
825 echo ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } else if (this.value == \'localhost\') { hostname.value = \'localhost\'; } '
826 . (empty($thishost) ? '' : 'else if (this.value == \'thishost\') { hostname.value = \'' . addslashes(htmlspecialchars($thishost)) . '\'; } ')
827 . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } else if (this.value == \'userdefined\') { hostname.focus(); hostname.select(); }">' . "\n";
828 unset($_current_user);
830 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
831 if (! isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
832 switch (strtolower($GLOBALS['hostname'])) {
833 case 'localhost':
834 case '127.0.0.1':
835 $GLOBALS['pred_hostname'] = 'localhost';
836 break;
837 case '%':
838 $GLOBALS['pred_hostname'] = 'any';
839 break;
840 default:
841 $GLOBALS['pred_hostname'] = 'userdefined';
842 break;
845 echo ' <option value="any"'
846 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
847 ? ' selected="selected"' : '') . '>' . __('Any host')
848 . '</option>' . "\n"
849 . ' <option value="localhost"'
850 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'localhost')
851 ? ' selected="selected"' : '') . '>' . __('Local')
852 . '</option>' . "\n";
853 if (! empty($thishost)) {
854 echo ' <option value="thishost"'
855 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'thishost')
856 ? ' selected="selected"' : '') . '>' . __('This Host')
857 . '</option>' . "\n";
859 unset($thishost);
860 echo ' <option value="hosttable"'
861 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'hosttable')
862 ? ' selected="selected"' : '') . '>' . __('Use Host Table')
863 . '</option>' . "\n"
864 . ' <option value="userdefined"'
865 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'userdefined')
866 ? ' selected="selected"' : '')
867 . '>' . __('Use text field') . ':</option>' . "\n"
868 . ' </select>' . "\n"
869 . '</span>' . "\n"
870 . '<input type="text" name="hostname" maxlength="'
871 . $hostname_length . '" value="'
872 . htmlspecialchars(isset($GLOBALS['hostname']) ? $GLOBALS['hostname'] : '')
873 . '" title="' . __('Host')
874 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
875 . PMA_showHint(__('When Host table is used, this field is ignored and values stored in Host table are used instead.'))
876 . '</div>' . "\n"
877 . '<div class="item">' . "\n"
878 . '<label for="select_pred_password">' . "\n"
879 . ' ' . __('Password') . ':' . "\n"
880 . '</label>' . "\n"
881 . '<span class="options">' . "\n"
882 . ' <select name="pred_password" id="select_pred_password" title="'
883 . __('Password') . '"' . "\n"
884 . ' onchange="if (this.value == \'none\') { pma_pw.value = \'\'; pma_pw2.value = \'\'; } else if (this.value == \'userdefined\') { pma_pw.focus(); pma_pw.select(); }">' . "\n"
885 . ($mode == 'change' ? ' <option value="keep" selected="selected">' . __('Do not change the password') . '</option>' . "\n" : '')
886 . ' <option value="none"';
887 if (isset($GLOBALS['username']) && $mode != 'change') {
888 echo ' selected="selected"';
890 echo '>' . __('No Password') . '</option>' . "\n"
891 . ' <option value="userdefined"' . (isset($GLOBALS['username']) ? '' : ' selected="selected"') . '>' . __('Use text field') . ':</option>' . "\n"
892 . ' </select>' . "\n"
893 . '</span>' . "\n"
894 . '<input type="password" id="text_pma_pw" name="pma_pw" title="' . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
895 . '</div>' . "\n"
896 . '<div class="item" id="div_element_before_generate_password">' . "\n"
897 . '<label for="text_pma_pw2">' . "\n"
898 . ' ' . __('Re-type') . ':' . "\n"
899 . '</label>' . "\n"
900 . '<span class="options">&nbsp;</span>' . "\n"
901 . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="' . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
902 . '</div>' . "\n"
903 // Generate password added here via jQuery
904 . '</fieldset>' . "\n";
905 } // end of the 'PMA_displayUserAndHostFields()' function
908 * Changes / copies a user, part I
910 if (isset($_REQUEST['change_copy'])) {
911 $user_host_condition = ' WHERE `User`'
912 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
913 .' AND `Host`'
914 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
915 $row = PMA_DBI_fetch_single_row('SELECT * FROM `mysql`.`user` ' . $user_host_condition);
916 if (! $row) {
917 PMA_Message::notice(__('No user found.'))->display();
918 unset($_REQUEST['change_copy']);
919 } else {
920 extract($row, EXTR_OVERWRITE);
921 // Recent MySQL versions have the field "Password" in mysql.user,
922 // so the previous extract creates $Password but this script
923 // uses $password
924 if (! isset($password) && isset($Password)) {
925 $password = $Password;
927 $queries = array();
933 * Adds a user
934 * (Changes / copies a user, part II)
936 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
937 $sql_query = '';
938 if ($pred_username == 'any') {
939 $username = '';
941 switch ($pred_hostname) {
942 case 'any':
943 $hostname = '%';
944 break;
945 case 'localhost':
946 $hostname = 'localhost';
947 break;
948 case 'hosttable':
949 $hostname = '';
950 break;
951 case 'thishost':
952 $_user_name = PMA_DBI_fetch_value('SELECT USER()');
953 $hostname = substr($_user_name, (strrpos($_user_name, '@') + 1));
954 unset($_user_name);
955 break;
957 $sql = "SELECT '1' FROM `mysql`.`user`"
958 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
959 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
960 if (PMA_DBI_fetch_value($sql) == 1) {
961 $message = PMA_Message::error(__('The user %s already exists!'));
962 $message->addParam('[i]\'' . $username . '\'@\'' . $hostname . '\'[/i]');
963 $_REQUEST['adduser'] = true;
964 $_add_user_error = true;
965 } else {
967 $create_user_real = 'CREATE USER \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
969 $real_sql_query = 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
970 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
971 if ($pred_password != 'none' && $pred_password != 'keep') {
972 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
973 $real_sql_query .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
974 if (isset($create_user_real)) {
975 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
976 $create_user_real .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
978 } else {
979 if ($pred_password == 'keep' && ! empty($password)) {
980 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
981 if (isset($create_user_real)) {
982 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
985 $sql_query = $real_sql_query;
986 if (isset($create_user_real)) {
987 $create_user_show = $create_user_real;
991 * @todo similar code appears twice in this script
993 if ((isset($Grant_priv) && $Grant_priv == 'Y')
994 || (isset($max_questions) || isset($max_connections)
995 || isset($max_updates) || isset($max_user_connections))
997 $real_sql_query .= ' WITH';
998 $sql_query .= ' WITH';
999 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1000 $real_sql_query .= ' GRANT OPTION';
1001 $sql_query .= ' GRANT OPTION';
1003 if (isset($max_questions)) {
1004 // avoid negative values
1005 $max_questions = max(0, (int)$max_questions);
1006 $real_sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1007 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1009 if (isset($max_connections)) {
1010 $max_connections = max(0, (int)$max_connections);
1011 $real_sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1012 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1014 if (isset($max_updates)) {
1015 $max_updates = max(0, (int)$max_updates);
1016 $real_sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1017 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1019 if (isset($max_user_connections)) {
1020 $max_user_connections = max(0, (int)$max_user_connections);
1021 $real_sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1022 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1025 if (isset($create_user_real)) {
1026 $create_user_real .= ';';
1027 $create_user_show .= ';';
1029 $real_sql_query .= ';';
1030 $sql_query .= ';';
1031 if (empty($_REQUEST['change_copy'])) {
1032 $_error = false;
1034 if (isset($create_user_real)) {
1035 if (! PMA_DBI_try_query($create_user_real)) {
1036 $_error = true;
1038 $sql_query = $create_user_show . $sql_query;
1041 if ($_error || ! PMA_DBI_try_query($real_sql_query)) {
1042 $_REQUEST['createdb'] = false;
1043 $message = PMA_Message::rawError(PMA_DBI_getError());
1044 } else {
1045 $message = PMA_Message::success(__('You have added a new user.'));
1048 switch (PMA_ifSetOr($_REQUEST['createdb'], '0')) {
1049 case '1' :
1050 // Create database with same name and grant all privileges
1051 $q = 'CREATE DATABASE IF NOT EXISTS '
1052 . PMA_backquote(PMA_sqlAddSlashes($username)) . ';';
1053 $sql_query .= $q;
1054 if (! PMA_DBI_try_query($q)) {
1055 $message = PMA_Message::rawError(PMA_DBI_getError());
1056 break;
1061 * If we are not in an Ajax request, we can't reload navigation now
1063 if ($GLOBALS['is_ajax_request'] != true) {
1064 // this is needed in case tracking is on:
1065 $GLOBALS['db'] = $username;
1066 $GLOBALS['reload'] = true;
1067 PMA_reloadNavigation();
1070 $q = 'GRANT ALL PRIVILEGES ON '
1071 . PMA_backquote(PMA_sqlAddSlashes($username)) . '.* TO \''
1072 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1073 $sql_query .= $q;
1074 if (! PMA_DBI_try_query($q)) {
1075 $message = PMA_Message::rawError(PMA_DBI_getError());
1077 break;
1078 case '2' :
1079 // Grant all privileges on wildcard name (username\_%)
1080 $q = 'GRANT ALL PRIVILEGES ON '
1081 . PMA_backquote(PMA_sqlAddSlashes($username) . '\_%') . '.* TO \''
1082 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1083 $sql_query .= $q;
1084 if (! PMA_DBI_try_query($q)) {
1085 $message = PMA_Message::rawError(PMA_DBI_getError());
1087 break;
1088 case '3' :
1089 // Grant all privileges on the specified database to the new user
1090 $q = 'GRANT ALL PRIVILEGES ON '
1091 . PMA_backquote(PMA_sqlAddSlashes($dbname)) . '.* TO \''
1092 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1093 $sql_query .= $q;
1094 if (! PMA_DBI_try_query($q)) {
1095 $message = PMA_Message::rawError(PMA_DBI_getError());
1097 break;
1098 case '0' :
1099 default :
1100 break;
1102 } else {
1103 if (isset($create_user_real)) {
1104 $queries[] = $create_user_real;
1106 $queries[] = $real_sql_query;
1107 // we put the query containing the hidden password in
1108 // $queries_for_display, at the same position occupied
1109 // by the real query in $queries
1110 $tmp_count = count($queries);
1111 if (isset($create_user_real)) {
1112 $queries_for_display[$tmp_count - 2] = $create_user_show;
1114 $queries_for_display[$tmp_count - 1] = $sql_query;
1116 unset($res, $real_sql_query);
1122 * Changes / copies a user, part III
1124 if (isset($_REQUEST['change_copy'])) {
1125 $user_host_condition = ' WHERE `User`'
1126 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1127 .' AND `Host`'
1128 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
1129 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1130 while ($row = PMA_DBI_fetch_assoc($res)) {
1131 $queries[] = 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1132 .' ON ' . PMA_backquote($row['Db']) . '.*'
1133 .' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1134 . ($row['Grant_priv'] == 'Y' ? ' WITH GRANT OPTION;' : ';');
1136 PMA_DBI_free_result($res);
1137 $res = PMA_DBI_query(
1138 'SELECT `Db`, `Table_name`, `Table_priv` FROM `mysql`.`tables_priv`' . $user_host_condition,
1139 $GLOBALS['userlink'],
1140 PMA_DBI_QUERY_STORE
1142 while ($row = PMA_DBI_fetch_assoc($res)) {
1144 $res2 = PMA_DBI_QUERY(
1145 'SELECT `Column_name`, `Column_priv`'
1146 .' FROM `mysql`.`columns_priv`'
1147 .' WHERE `User`'
1148 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1149 .' AND `Host`'
1150 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\''
1151 .' AND `Db`'
1152 .' = \'' . PMA_sqlAddSlashes($row['Db']) . "'"
1153 .' AND `Table_name`'
1154 .' = \'' . PMA_sqlAddSlashes($row['Table_name']) . "'"
1155 .';',
1156 null,
1157 PMA_DBI_QUERY_STORE
1160 $tmp_privs1 = PMA_extractPrivInfo($row);
1161 $tmp_privs2 = array(
1162 'Select' => array(),
1163 'Insert' => array(),
1164 'Update' => array(),
1165 'References' => array()
1168 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1169 $tmp_array = explode(',', $row2['Column_priv']);
1170 if (in_array('Select', $tmp_array)) {
1171 $tmp_privs2['Select'][] = $row2['Column_name'];
1173 if (in_array('Insert', $tmp_array)) {
1174 $tmp_privs2['Insert'][] = $row2['Column_name'];
1176 if (in_array('Update', $tmp_array)) {
1177 $tmp_privs2['Update'][] = $row2['Column_name'];
1179 if (in_array('References', $tmp_array)) {
1180 $tmp_privs2['References'][] = $row2['Column_name'];
1182 unset($tmp_array);
1184 if (count($tmp_privs2['Select']) > 0 && ! in_array('SELECT', $tmp_privs1)) {
1185 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1187 if (count($tmp_privs2['Insert']) > 0 && ! in_array('INSERT', $tmp_privs1)) {
1188 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1190 if (count($tmp_privs2['Update']) > 0 && ! in_array('UPDATE', $tmp_privs1)) {
1191 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1193 if (count($tmp_privs2['References']) > 0 && ! in_array('REFERENCES', $tmp_privs1)) {
1194 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1196 unset($tmp_privs2);
1197 $queries[] = 'GRANT ' . join(', ', $tmp_privs1)
1198 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1199 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1200 . (in_array('Grant', explode(',', $row['Table_priv'])) ? ' WITH GRANT OPTION;' : ';');
1206 * Updates privileges
1208 if (! empty($update_privs)) {
1209 $db_and_table = PMA_wildcardEscapeForGrant($dbname, (isset($tablename) ? $tablename : ''));
1211 $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1212 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1213 if (! isset($Grant_priv) || $Grant_priv != 'Y') {
1214 $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
1215 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1216 } else {
1217 $sql_query1 = '';
1220 // Should not do a GRANT USAGE for a table-specific privilege, it
1221 // causes problems later (cannot revoke it)
1222 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1223 $sql_query2 = 'GRANT ' . join(', ', PMA_extractPrivInfo())
1224 . ' ON ' . $db_and_table
1225 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
1228 * @todo similar code appears twice in this script
1230 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1231 || (! isset($dbname)
1232 && (isset($max_questions) || isset($max_connections)
1233 || isset($max_updates) || isset($max_user_connections)))
1235 $sql_query2 .= 'WITH';
1236 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1237 $sql_query2 .= ' GRANT OPTION';
1239 if (isset($max_questions)) {
1240 $max_questions = max(0, (int)$max_questions);
1241 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1243 if (isset($max_connections)) {
1244 $max_connections = max(0, (int)$max_connections);
1245 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1247 if (isset($max_updates)) {
1248 $max_updates = max(0, (int)$max_updates);
1249 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1251 if (isset($max_user_connections)) {
1252 $max_user_connections = max(0, (int)$max_user_connections);
1253 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1256 $sql_query2 .= ';';
1258 if (! PMA_DBI_try_query($sql_query0)) {
1259 // This might fail when the executing user does not have ALL PRIVILEGES himself.
1260 // See https://sourceforge.net/tracker/index.php?func=detail&aid=3285929&group_id=23067&atid=377408
1261 $sql_query0 = '';
1263 if (isset($sql_query1) && ! PMA_DBI_try_query($sql_query1)) {
1264 // this one may fail, too...
1265 $sql_query1 = '';
1267 if (isset($sql_query2)) {
1268 PMA_DBI_query($sql_query2);
1269 } else {
1270 $sql_query2 = '';
1272 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1273 $message = PMA_Message::success(__('You have updated the privileges for %s.'));
1274 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1279 * Revokes Privileges
1281 if (isset($_REQUEST['revokeall'])) {
1282 $db_and_table = PMA_wildcardEscapeForGrant($dbname, isset($tablename) ? $tablename : '');
1284 $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1285 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1286 $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
1287 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1289 PMA_DBI_query($sql_query0);
1290 if (! PMA_DBI_try_query($sql_query1)) {
1291 // this one may fail, too...
1292 $sql_query1 = '';
1294 $sql_query = $sql_query0 . ' ' . $sql_query1;
1295 $message = PMA_Message::success(__('You have revoked the privileges for %s'));
1296 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1297 if (! isset($tablename)) {
1298 unset($dbname);
1299 } else {
1300 unset($tablename);
1306 * Updates the password
1308 if (isset($_REQUEST['change_pw'])) {
1309 // similar logic in user_password.php
1310 $message = '';
1312 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1313 if ($pma_pw != $pma_pw2) {
1314 $message = PMA_Message::error(__('The passwords aren\'t the same!'));
1315 } elseif (empty($pma_pw) || empty($pma_pw2)) {
1316 $message = PMA_Message::error(__('The password is empty!'));
1318 } // end if
1320 // here $nopass could be == 1
1321 if (empty($message)) {
1323 $hashing_function = (! empty($pw_hash) && $pw_hash == 'old' ? 'OLD_' : '')
1324 . 'PASSWORD';
1326 // in $sql_query which will be displayed, hide the password
1327 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1328 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . PMA_sqlAddSlashes($pma_pw) . '\')');
1329 PMA_DBI_try_query($local_query)
1330 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, false, $err_url);
1331 $message = PMA_Message::success(__('The password for %s was changed successfully.'));
1332 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1338 * Deletes users
1339 * (Changes / copies a user, part IV)
1342 if (isset($_REQUEST['delete']) || (isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1343 if (isset($_REQUEST['change_copy'])) {
1344 $selected_usr = array($old_username . '&amp;#27;' . $old_hostname);
1345 } else {
1346 $selected_usr = $_REQUEST['selected_usr'];
1347 $queries = array();
1349 foreach ($selected_usr as $each_user) {
1350 list($this_user, $this_host) = explode('&amp;#27;', $each_user);
1351 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1352 $queries[] = 'DROP USER \'' . PMA_sqlAddSlashes($this_user) . '\'@\'' . PMA_sqlAddSlashes($this_host) . '\';';
1354 if (isset($_REQUEST['drop_users_db'])) {
1355 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1356 $GLOBALS['reload'] = true;
1358 if ($GLOBALS['is_ajax_request'] != true) {
1359 PMA_reloadNavigation();
1363 if (empty($_REQUEST['change_copy'])) {
1364 if (empty($queries)) {
1365 $message = PMA_Message::error(__('No users selected for deleting!'));
1366 } else {
1367 if ($_REQUEST['mode'] == 3) {
1368 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1369 $queries[] = 'FLUSH PRIVILEGES;';
1371 $drop_user_error = '';
1372 foreach ($queries as $sql_query) {
1373 if ($sql_query{0} != '#') {
1374 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1375 $drop_user_error .= PMA_DBI_getError() . "\n";
1379 // tracking sets this, causing the deleted db to be shown in navi
1380 unset($GLOBALS['db']);
1382 $sql_query = join("\n", $queries);
1383 if (! empty($drop_user_error)) {
1384 $message = PMA_Message::rawError($drop_user_error);
1385 } else {
1386 $message = PMA_Message::success(__('The selected users have been deleted successfully.'));
1389 unset($queries);
1395 * Changes / copies a user, part V
1397 if (isset($_REQUEST['change_copy'])) {
1398 $tmp_count = 0;
1399 foreach ($queries as $sql_query) {
1400 if ($sql_query{0} != '#') {
1401 PMA_DBI_query($sql_query);
1403 // when there is a query containing a hidden password, take it
1404 // instead of the real query sent
1405 if (isset($queries_for_display[$tmp_count])) {
1406 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1408 $tmp_count++;
1410 $message = PMA_Message::success();
1411 $sql_query = join("\n", $queries);
1416 * Reloads the privilege tables into memory
1418 if (isset($_REQUEST['flush_privileges'])) {
1419 $sql_query = 'FLUSH PRIVILEGES;';
1420 PMA_DBI_query($sql_query);
1421 $message = PMA_Message::success(__('The privileges were reloaded successfully.'));
1425 * defines some standard links
1427 $link_edit = '<a class="edit_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . str_replace('%', '%%', $GLOBALS['url_query'])
1428 . '&amp;username=%s'
1429 . '&amp;hostname=%s'
1430 . '&amp;dbname=%s'
1431 . '&amp;tablename=%s">'
1432 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1433 . '</a>';
1435 $link_revoke = '<a href="server_privileges.php?' . str_replace('%', '%%', $GLOBALS['url_query'])
1436 . '&amp;username=%s'
1437 . '&amp;hostname=%s'
1438 . '&amp;dbname=%s'
1439 . '&amp;tablename=%s'
1440 . '&amp;revokeall=1">'
1441 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1442 . '</a>';
1444 $link_export = '<a class="export_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . str_replace('%', '%%', $GLOBALS['url_query'])
1445 . '&amp;username=%s'
1446 . '&amp;hostname=%s'
1447 . '&amp;initial=%s'
1448 . '&amp;export=1">'
1449 . PMA_getIcon('b_tblexport.png', __('Export'))
1450 . '</a>';
1453 * If we are in an Ajax request for Create User/Edit User/Revoke User/
1454 * Flush Privileges, show $message and exit.
1456 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'])) {
1458 if (isset($sql_query)) {
1459 $extra_data['sql_query'] = PMA_showMessage(null, $sql_query);
1462 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
1464 * generate html on the fly for the new user that was just created.
1466 $new_user_string = '<tr>'."\n"
1467 .'<td> <input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_" value="' . htmlspecialchars($username) . '&amp;#27;' . htmlspecialchars($hostname) . '" /> </td>' . "\n"
1468 .'<td><label for="checkbox_sel_users_">' . (empty($username) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($username) ) . '</label></td>' . "\n"
1469 .'<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
1470 $new_user_string .= '<td>';
1472 if (! empty($password) || isset($pma_pw)) {
1473 $new_user_string .= __('Yes');
1474 } else {
1475 $new_user_string .= '<span style="color: #FF0000">' . __('No') . '</span>';
1478 $new_user_string .= '</td>'."\n";
1479 $new_user_string .= '<td><tt>' . join(', ', PMA_extractPrivInfo('', true)) . '</tt></td>'; //Fill in privileges here
1480 $new_user_string .= '<td>';
1482 if ((isset($Grant_priv) && $Grant_priv == 'Y')) {
1483 $new_user_string .= __('Yes');
1484 } else {
1485 $new_user_string .= __('No');
1488 $new_user_string .='</td>';
1490 $new_user_string .= '<td>' . sprintf($link_edit, urlencode($username), urlencode($hostname), '', '') . '</td>' . "\n";
1491 $new_user_string .= '<td>' . sprintf($link_export, urlencode($username), urlencode($hostname), (isset($initial) ? $initial : '')) . '</td>' . "\n";
1493 $new_user_string .= '</tr>';
1495 $extra_data['new_user_string'] = $new_user_string;
1498 * Generate the string for this alphabet's initial, to update the user
1499 * pagination
1501 $new_user_initial = strtoupper(substr($username, 0, 1));
1502 $new_user_initial_string = '<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . $new_user_initial
1503 .'">' . $new_user_initial . '</a>';
1504 $extra_data['new_user_initial'] = $new_user_initial;
1505 $extra_data['new_user_initial_string'] = $new_user_initial_string;
1508 if (isset($update_privs)) {
1509 $extra_data['db_specific_privs'] = false;
1510 if (isset($dbname_is_wildcard)) {
1511 $extra_data['db_specific_privs'] = ! $dbname_is_wildcard;
1513 $new_privileges = join(', ', PMA_extractPrivInfo('', true));
1515 $extra_data['new_privileges'] = $new_privileges;
1518 if ($message instanceof PMA_Message) {
1519 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
1524 * Displays the links
1526 if (isset($viewing_mode) && $viewing_mode == 'db') {
1527 $db = $checkprivs;
1528 $url_query .= '&amp;goto=db_operations.php';
1530 // Gets the database structure
1531 $sub_part = '_structure';
1532 include './libraries/db_info.inc.php';
1533 echo "\n";
1534 } else {
1535 include './libraries/server_links.inc.php';
1540 * Displays the page
1543 // export user definition
1544 if (isset($_REQUEST['export'])) {
1545 $title = __('User') . ' `' . htmlspecialchars($username) . '`@`' . htmlspecialchars($hostname) . '`';
1546 $response = '<textarea cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1547 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddSlashes($username) . "'@'" . PMA_sqlAddSlashes($hostname) . "'");
1548 foreach ($grants as $one_grant) {
1549 $response .= $one_grant . ";\n\n";
1551 $response .= '</textarea>';
1552 unset($username, $hostname, $grants, $one_grant);
1553 if ($GLOBALS['is_ajax_request']) {
1554 PMA_ajaxResponse($response, 1, array('title' => $title));
1555 } else {
1556 echo "<h2>$title</h2>$response";
1560 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs))) {
1561 if (! isset($username)) {
1562 // No username is given --> display the overview
1563 echo '<h2>' . "\n"
1564 . PMA_getIcon('b_usrlist.png')
1565 . __('Users overview') . "\n"
1566 . '</h2>' . "\n";
1568 $sql_query = 'SELECT *,' .
1569 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1570 ' FROM `mysql`.`user`';
1572 $sql_query .= (isset($initial) ? PMA_rangeOfUsers($initial) : '');
1574 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1575 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1577 if (! $res) {
1578 // the query failed! This may have two reasons:
1579 // - the user does not have enough privileges
1580 // - the privilege tables use a structure of an earlier version.
1581 // so let's try a more simple query
1583 $sql_query = 'SELECT * FROM `mysql`.`user`';
1584 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1586 if (! $res) {
1587 PMA_Message::error(__('No Privileges'))->display();
1588 PMA_DBI_free_result($res);
1589 unset($res);
1590 } else {
1591 // This message is hardcoded because I will replace it by
1592 // a automatic repair feature soon.
1593 $raw = 'Your privilege table structure seems to be older than'
1594 . ' this MySQL version!<br />'
1595 . 'Please run the <tt>mysql_upgrade</tt> command'
1596 . '(<tt>mysql_fix_privilege_tables</tt> on older systems)'
1597 . ' that should be included in your MySQL server distribution'
1598 . ' to solve this problem!';
1599 PMA_Message::rawError($raw)->display();
1601 } else {
1603 // we also want users not in table `user` but in other table
1604 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1606 $tables_to_search_for_users = array(
1607 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1610 $db_rights_sqls = array();
1611 foreach ($tables_to_search_for_users as $table_search_in) {
1612 if (in_array($table_search_in, $tables)) {
1613 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ? PMA_rangeOfUsers($initial) : '');
1617 $user_defaults = array(
1618 'User' => '',
1619 'Host' => '%',
1620 'Password' => '?',
1621 'Grant_priv' => 'N',
1622 'privs' => array('USAGE'),
1625 // for all initials, even non A-Z
1626 $array_initials = array();
1627 // for the rights
1628 $db_rights = array();
1630 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1631 .' ORDER BY `User` ASC, `Host` ASC';
1633 $db_rights_result = PMA_DBI_query($db_rights_sql);
1635 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1636 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1637 $db_rights[$db_rights_row['User']][$db_rights_row['Host']]
1638 = $db_rights_row;
1640 PMA_DBI_free_result($db_rights_result);
1641 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1642 ksort($db_rights);
1645 * Displays the initials
1646 * In an Ajax request, we don't need to show this.
1647 * Also not necassary if there is less than 20 privileges
1649 if ($GLOBALS['is_ajax_request'] != true && PMA_DBI_num_rows($res) > 20 ) {
1651 // initialize to false the letters A-Z
1652 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++) {
1653 if (! isset($array_initials[chr($letter_counter + 64)])) {
1654 $array_initials[chr($letter_counter + 64)] = false;
1658 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE);
1659 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1660 $array_initials[$tmp_initial] = true;
1663 // Display the initials, which can be any characters, not
1664 // just letters. For letters A-Z, we add the non-used letters
1665 // as greyed out.
1667 uksort($array_initials, "strnatcasecmp");
1669 echo '<table id="initials_table" class="' . $conditional_class . '" <cellspacing="5"><tr>';
1670 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1671 if ($initial_was_found) {
1672 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1673 } else {
1674 echo '<td>' . $tmp_initial . '</td>';
1677 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;showall=1" class="nowrap">[' . __('Show all') . ']</a></td>' . "\n";
1678 echo '</tr></table>';
1682 * Display the user overview
1683 * (if less than 50 users, display them immediately)
1686 if (isset($initial) || isset($showall) || PMA_DBI_num_rows($res) < 50) {
1688 while ($row = PMA_DBI_fetch_assoc($res)) {
1689 $row['privs'] = PMA_extractPrivInfo($row, true);
1690 $db_rights[$row['User']][$row['Host']] = $row;
1692 @PMA_DBI_free_result($res);
1693 unset($res);
1695 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1696 . PMA_generate_common_hidden_inputs('', '')
1697 . ' <table id="tableuserrights" class="data">' . "\n"
1698 . ' <thead>' . "\n"
1699 . ' <tr><th></th>' . "\n"
1700 . ' <th>' . __('User') . '</th>' . "\n"
1701 . ' <th>' . __('Host') . '</th>' . "\n"
1702 . ' <th>' . __('Password') . '</th>' . "\n"
1703 . ' <th>' . __('Global privileges') . ' '
1704 . PMA_showHint(__('Note: MySQL privilege names are expressed in English')) . '</th>' . "\n"
1705 . ' <th>' . __('Grant') . '</th>' . "\n"
1706 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1707 echo ' </tr>' . "\n";
1708 echo ' </thead>' . "\n";
1709 echo ' <tbody>' . "\n";
1710 $odd_row = true;
1711 $index_checkbox = -1;
1712 foreach ($db_rights as $user) {
1713 $index_checkbox++;
1714 ksort($user);
1715 foreach ($user as $host) {
1716 $index_checkbox++;
1717 echo ' <tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
1718 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1719 . $index_checkbox . '" value="'
1720 . htmlspecialchars($host['User'] . '&amp;#27;' . $host['Host'])
1721 . '"'
1722 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
1723 . ' /></td>' . "\n"
1724 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1725 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1726 echo ' <td>';
1727 switch ($host['Password']) {
1728 case 'Y':
1729 echo __('Yes');
1730 break;
1731 case 'N':
1732 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1733 break;
1734 // this happens if this is a definition not coming from mysql.user
1735 default:
1736 echo '--'; // in future version, replace by "not present"
1737 break;
1738 } // end switch
1739 echo '</td>' . "\n"
1740 . ' <td><tt>' . "\n"
1741 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1742 . ' </tt></td>' . "\n"
1743 . ' <td>' . ($host['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . '</td>' . "\n"
1744 . ' <td align="center">';
1745 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1746 echo '</td>';
1747 echo '<td align="center">';
1748 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ? $initial : ''));
1749 echo '</td>';
1750 echo '</tr>';
1751 $odd_row = ! $odd_row;
1755 unset($user, $host, $odd_row);
1756 echo ' </tbody></table>' . "\n"
1757 .'<img class="selectallarrow"'
1758 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1759 .' width="38" height="22"'
1760 .' alt="' . __('With selected:') . '" />' . "\n"
1761 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;checkall=1"'
1762 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1763 . __('Check All') . '</a>' . "\n"
1764 .'/' . "\n"
1765 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1766 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1767 . __('Uncheck All') . '</a>' . "\n";
1769 // add/delete user fieldset
1770 echo ' <fieldset id="fieldset_add_user">' . "\n"
1771 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1772 . PMA_getIcon('b_usradd.png')
1773 . ' ' . __('Add user') . '</a>' . "\n"
1774 . ' </fieldset>' . "\n"
1775 . ' <fieldset id="fieldset_delete_user">'
1776 . ' <legend>' . "\n"
1777 . PMA_getIcon('b_usrdrop.png')
1778 . ' ' . __('Remove selected users') . '' . "\n"
1779 . ' </legend>' . "\n"
1780 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1781 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1782 . ' <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"
1783 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1784 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1785 . ' </label>' . "\n"
1786 . ' </fieldset>' . "\n"
1787 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1788 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" class="' . $conditional_class . '"/>' . "\n"
1789 . ' </fieldset>' . "\n"
1790 . '</form>' . "\n";
1791 } else {
1793 unset ($row);
1794 echo ' <fieldset id="fieldset_add_user">' . "\n"
1795 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1796 . PMA_getIcon('b_usradd.png')
1797 . ' ' . __('Add user') . '</a>' . "\n"
1798 . ' </fieldset>' . "\n";
1799 } // end if (display overview)
1801 if ($GLOBALS['is_ajax_request']) {
1802 exit;
1805 $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);
1806 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;flush_privileges=1" id="reload_privileges_anchor" class="' . $conditional_class . '">', false);
1807 $flushnote->addParam('</a>', false);
1808 $flushnote->display();
1812 } else {
1814 // A user was selected -> display the user's properties
1816 // In an Ajax request, prevent cached values from showing
1817 if ($GLOBALS['is_ajax_request'] == true) {
1818 header('Cache-Control: no-cache');
1821 echo '<h2>' . "\n"
1822 . PMA_getIcon('b_usredit.png')
1823 . __('Edit Privileges') . ': '
1824 . __('User');
1826 if (isset($dbname)) {
1827 echo ' <i><a href="server_privileges.php?'
1828 . $GLOBALS['url_query'] . '&amp;username=' . htmlspecialchars(urlencode($username))
1829 . '&amp;hostname=' . htmlspecialchars(urlencode($hostname)) . '&amp;dbname=&amp;tablename=">\''
1830 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1831 . '\'</a></i>' . "\n";
1832 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
1834 echo ' - ' . ($dbname_is_wildcard ? __('Databases') : __('Database') );
1835 if (isset($tablename)) {
1836 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
1837 . '&amp;username=' . htmlspecialchars(urlencode($username)) . '&amp;hostname=' . htmlspecialchars(urlencode($hostname))
1838 . '&amp;dbname=' . htmlspecialchars($url_dbname) . '&amp;tablename=">' . htmlspecialchars($dbname) . '</a></i>';
1839 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
1840 } else {
1841 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
1844 } else {
1845 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1846 . '\'</i>' . "\n";
1849 echo '</h2>' . "\n";
1852 $sql = "SELECT '1' FROM `mysql`.`user`"
1853 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
1854 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
1855 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
1856 unset($sql);
1857 if ($user_does_not_exists) {
1858 PMA_Message::error(__('The selected user was not found in the privilege table.'))->display();
1859 PMA_displayLoginInformationFields();
1860 //require './libraries/footer.inc.php';
1863 echo '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n";
1864 $_params = array(
1865 'username' => $username,
1866 'hostname' => $hostname,
1868 if (isset($dbname)) {
1869 $_params['dbname'] = $dbname;
1870 if (isset($tablename)) {
1871 $_params['tablename'] = $tablename;
1874 echo PMA_generate_common_hidden_inputs($_params);
1876 PMA_displayPrivTable(
1877 PMA_ifSetOr($dbname, '*', 'length'),
1878 PMA_ifSetOr($tablename, '*', 'length')
1881 echo '</form>' . "\n";
1883 if (! isset($tablename) && empty($dbname_is_wildcard)) {
1885 // no table name was given, display all table specific rights
1886 // but only if $dbname contains no wildcards
1888 // table header
1889 echo '<form action="server_privileges.php" id="db_or_table_specific_priv" method="post">' . "\n"
1890 . PMA_generate_common_hidden_inputs('', '')
1891 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
1892 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1893 . '<fieldset>' . "\n"
1894 . '<legend>' . (! isset($dbname) ? __('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
1895 . '<table class="data">' . "\n"
1896 . '<thead>' . "\n"
1897 . '<tr><th>' . (! isset($dbname) ? __('Database') : __('Table')) . '</th>' . "\n"
1898 . ' <th>' . __('Privileges') . '</th>' . "\n"
1899 . ' <th>' . __('Grant') . '</th>' . "\n"
1900 . ' <th>' . (! isset($dbname) ? __('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
1901 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
1902 . '</tr>' . "\n"
1903 . '</thead>' . "\n"
1904 . '<tbody>' . "\n";
1906 $user_host_condition = ' WHERE `User`'
1907 . ' = \'' . PMA_sqlAddSlashes($username) . "'"
1908 . ' AND `Host`'
1909 . ' = \'' . PMA_sqlAddSlashes($hostname) . "'";
1911 // table body
1912 // get data
1914 // we also want privielgs for this user not in table `db` but in other table
1915 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1916 if (! isset($dbname)) {
1918 // no db name given, so we want all privs for the given user
1920 $tables_to_search_for_users = array(
1921 'tables_priv', 'columns_priv',
1924 $db_rights_sqls = array();
1925 foreach ($tables_to_search_for_users as $table_search_in) {
1926 if (in_array($table_search_in, $tables)) {
1927 $db_rights_sqls[] = '
1928 SELECT DISTINCT `Db`
1929 FROM `mysql`.' . PMA_backquote($table_search_in)
1930 . $user_host_condition;
1934 $user_defaults = array(
1935 'Db' => '',
1936 'Grant_priv' => 'N',
1937 'privs' => array('USAGE'),
1938 'Table_privs' => true,
1941 // for the rights
1942 $db_rights = array();
1944 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1945 .' ORDER BY `Db` ASC';
1947 $db_rights_result = PMA_DBI_query($db_rights_sql);
1949 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1950 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1951 // only Db names in the table `mysql`.`db` uses wildcards
1952 // as we are in the db specific rights display we want
1953 // all db names escaped, also from other sources
1954 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
1955 $db_rights_row['Db']
1957 $db_rights[$db_rights_row['Db']] = $db_rights_row;
1960 PMA_DBI_free_result($db_rights_result);
1961 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1963 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
1964 $res = PMA_DBI_query($sql_query);
1965 $sql_query = '';
1967 while ($row = PMA_DBI_fetch_assoc($res)) {
1968 if (isset($db_rights[$row['Db']])) {
1969 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
1970 } else {
1971 $db_rights[$row['Db']] = $row;
1973 // there are db specific rights for this user
1974 // so we can drop this db rights
1975 $db_rights[$row['Db']]['can_delete'] = true;
1977 PMA_DBI_free_result($res);
1978 unset($row, $res);
1980 } else {
1982 // db name was given,
1983 // so we want all user specific rights for this db
1985 $user_host_condition .=
1986 ' AND `Db`'
1987 .' LIKE \'' . PMA_sqlAddSlashes($dbname, true) . "'";
1989 $tables_to_search_for_users = array(
1990 'columns_priv',
1993 $db_rights_sqls = array();
1994 foreach ($tables_to_search_for_users as $table_search_in) {
1995 if (in_array($table_search_in, $tables)) {
1996 $db_rights_sqls[] = '
1997 SELECT DISTINCT `Table_name`
1998 FROM `mysql`.' . PMA_backquote($table_search_in)
1999 . $user_host_condition;
2003 $user_defaults = array(
2004 'Table_name' => '',
2005 'Grant_priv' => 'N',
2006 'privs' => array('USAGE'),
2007 'Column_priv' => true,
2010 // for the rights
2011 $db_rights = array();
2013 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
2014 .' ORDER BY `Table_name` ASC';
2016 $db_rights_result = PMA_DBI_query($db_rights_sql);
2018 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
2019 $db_rights_row = array_merge($user_defaults, $db_rights_row);
2020 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
2022 PMA_DBI_free_result($db_rights_result);
2023 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
2025 $sql_query = 'SELECT `Table_name`,'
2026 .' `Table_priv`,'
2027 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
2028 .' AS \'Column_priv\''
2029 .' FROM `mysql`.`tables_priv`'
2030 . $user_host_condition
2031 .' ORDER BY `Table_name` ASC;';
2032 $res = PMA_DBI_query($sql_query);
2033 $sql_query = '';
2035 while ($row = PMA_DBI_fetch_assoc($res)) {
2036 if (isset($db_rights[$row['Table_name']])) {
2037 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
2038 } else {
2039 $db_rights[$row['Table_name']] = $row;
2042 PMA_DBI_free_result($res);
2043 unset($row, $res);
2045 ksort($db_rights);
2047 // display rows
2048 if (count($db_rights) < 1) {
2049 echo '<tr class="odd">' . "\n"
2050 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
2051 . '</tr>' . "\n";
2052 } else {
2053 $odd_row = true;
2054 $found_rows = array();
2055 //while ($row = PMA_DBI_fetch_assoc($res)) {
2056 foreach ($db_rights as $row) {
2057 $found_rows[] = (! isset($dbname)) ? $row['Db'] : $row['Table_name'];
2059 echo '<tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2060 . ' <td>' . htmlspecialchars((! isset($dbname)) ? $row['Db'] : $row['Table_name']) . '</td>' . "\n"
2061 . ' <td><tt>' . "\n"
2062 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, true)) . "\n"
2063 . ' </tt></td>' . "\n"
2064 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') || (isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ? __('Yes') : __('No')) . '</td>' . "\n"
2065 . ' <td>';
2066 if (! empty($row['Table_privs']) || ! empty ($row['Column_priv'])) {
2067 echo __('Yes');
2068 } else {
2069 echo __('No');
2071 echo '</td>' . "\n"
2072 . ' <td>';
2073 printf(
2074 $link_edit,
2075 htmlspecialchars(urlencode($username)),
2076 urlencode(htmlspecialchars($hostname)),
2077 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
2078 urlencode((! isset($dbname)) ? '' : $row['Table_name'])
2080 echo '</td>' . "\n"
2081 . ' <td>';
2082 if (! empty($row['can_delete']) || isset($row['Table_name']) && strlen($row['Table_name'])) {
2083 printf(
2084 $link_revoke,
2085 htmlspecialchars(urlencode($username)),
2086 urlencode(htmlspecialchars($hostname)),
2087 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
2088 urlencode((! isset($dbname)) ? '' : $row['Table_name'])
2091 echo '</td>' . "\n"
2092 . '</tr>' . "\n";
2093 $odd_row = ! $odd_row;
2094 } // end while
2096 unset($row);
2097 echo '</tbody>' . "\n"
2098 . '</table>' . "\n";
2100 if (! isset($dbname)) {
2102 // no database name was given, display select db
2104 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
2106 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
2107 if (! empty($pred_db_array)) {
2108 echo ' <select name="pred_dbname" class="autosubmit">' . "\n"
2109 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2110 foreach ($pred_db_array as $current_db) {
2111 $current_db = PMA_escape_mysql_wildcards($current_db);
2112 // cannot use array_diff() once, outside of the loop,
2113 // because the list of databases has special characters
2114 // already escaped in $found_rows,
2115 // contrary to the output of SHOW DATABASES
2116 if (empty($found_rows) || ! in_array($current_db, $found_rows)) {
2117 echo ' <option value="' . htmlspecialchars($current_db) . '">'
2118 . htmlspecialchars($current_db) . '</option>' . "\n";
2121 echo ' </select>' . "\n";
2123 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
2124 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
2125 } else {
2126 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
2127 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
2128 if ($res = @PMA_DBI_try_query('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE)) {
2129 $pred_tbl_array = array();
2130 while ($row = PMA_DBI_fetch_row($res)) {
2131 if (! isset($found_rows) || ! in_array($row[0], $found_rows)) {
2132 $pred_tbl_array[] = $row[0];
2135 PMA_DBI_free_result($res);
2136 unset($res, $row);
2137 if (! empty($pred_tbl_array)) {
2138 echo ' <select name="pred_tablename" class="autosubmit">' . "\n"
2139 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2140 foreach ($pred_tbl_array as $current_table) {
2141 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
2143 echo ' </select>' . "\n";
2145 } else {
2146 unset($res);
2148 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
2150 echo '</fieldset>' . "\n";
2151 echo '<fieldset class="tblFooters">' . "\n"
2152 . ' <input type="submit" value="' . __('Go') . '" />'
2153 . '</fieldset>' . "\n"
2154 . '</form>' . "\n";
2158 // Provide a line with links to the relevant database and table
2159 if (isset($dbname) && empty($dbname_is_wildcard)) {
2160 echo '[ ' . __('Database')
2161 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
2162 . $GLOBALS['url_query'] . '&amp;db=' . $url_dbname . '&amp;reload=1">'
2163 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
2165 if (isset($tablename)) {
2166 echo ' [ ' . __('Table') . ' <a href="'
2167 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
2168 . '&amp;db=' . $url_dbname . '&amp;table=' . htmlspecialchars(urlencode($tablename))
2169 . '&amp;reload=1">' . htmlspecialchars($tablename) . ': '
2170 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
2171 . "</a> ]\n";
2173 unset($url_dbname);
2176 if (! isset($dbname) && ! $user_does_not_exists) {
2177 include_once './libraries/display_change_password.lib.php';
2179 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
2180 . PMA_generate_common_hidden_inputs('', '')
2181 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
2182 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
2183 . '<fieldset id="fieldset_change_copy_user">' . "\n"
2184 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
2185 PMA_displayLoginInformationFields('change');
2186 echo ' <fieldset>' . "\n"
2187 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2188 $choices = array(
2189 '4' => __('... keep the old one.'),
2190 '1' => __('... delete the old one from the user tables.'),
2191 '2' => __('... revoke all active privileges from the old one and delete it afterwards.'),
2192 '3' => __('... delete the old one from the user tables and reload the privileges afterwards.'));
2193 PMA_display_html_radio('mode', $choices, '4', true);
2194 unset($choices);
2196 echo ' </fieldset>' . "\n"
2197 . '</fieldset>' . "\n"
2198 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2199 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2200 . '</fieldset>' . "\n"
2201 . '</form>' . "\n";
2204 } elseif (isset($_REQUEST['adduser'])) {
2206 // Add user
2207 $GLOBALS['url_query'] .= '&amp;adduser=1';
2208 echo '<h2>' . "\n"
2209 . PMA_getIcon('b_usradd.png') . __('Add user') . "\n"
2210 . '</h2>' . "\n"
2211 . '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n"
2212 . PMA_generate_common_hidden_inputs('', '');
2213 PMA_displayLoginInformationFields('new');
2214 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2215 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2217 $default_choice = 0;
2218 $choices = array(
2219 '0' => _pgettext('Create none database for user', 'None'),
2220 '1' => __('Create database with same name and grant all privileges'),
2221 '2' => __('Grant all privileges on wildcard name (username\\_%)'));
2223 if (! empty($dbname) ) {
2224 $choices['3'] = sprintf(
2225 __('Grant all privileges on database &quot;%s&quot;'),
2226 htmlspecialchars($dbname)
2228 $default_choice = 3;
2229 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2232 // 4th parameter set to true to add line breaks
2233 // 5th parameter set to false to avoid htmlspecialchars() escaping in the label
2234 // since we have some HTML in some labels
2235 PMA_display_html_radio('createdb', $choices, $default_choice, true, false);
2236 unset($choices);
2237 unset($default_choice);
2239 echo '</fieldset>' . "\n";
2240 PMA_displayPrivTable('*', '*', false);
2241 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2242 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2243 . ' </fieldset>' . "\n"
2244 . '</form>' . "\n";
2245 } else {
2246 // check the privileges for a particular database.
2247 $user_form = '<form id="usersForm" action="server_privileges.php"><fieldset>' . "\n"
2248 . '<legend>' . "\n"
2249 . PMA_getIcon('b_usrcheck.png')
2250 . ' ' . sprintf(__('Users having access to &quot;%s&quot;'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2251 . '</legend>' . "\n"
2252 . '<table id="dbspecificuserrights" class="data">' . "\n"
2253 . '<thead>' . "\n"
2254 . ' <tr><th>' . __('User') . '</th>' . "\n"
2255 . ' <th>' . __('Host') . '</th>' . "\n"
2256 . ' <th>' . __('Type') . '</th>' . "\n"
2257 . ' <th>' . __('Privileges') . '</th>' . "\n"
2258 . ' <th>' . __('Grant') . '</th>' . "\n"
2259 . ' <th>' . __('Action') . '</th>' . "\n"
2260 . ' </tr>' . "\n"
2261 . '</thead>' . "\n"
2262 . '<tbody>' . "\n";
2263 $odd_row = true;
2264 unset($row, $row1, $row2);
2266 // now, we build the table...
2267 $list_of_privileges
2268 = '`User`, '
2269 . '`Host`, '
2270 . '`Select_priv`, '
2271 . '`Insert_priv`, '
2272 . '`Update_priv`, '
2273 . '`Delete_priv`, '
2274 . '`Create_priv`, '
2275 . '`Drop_priv`, '
2276 . '`Grant_priv`, '
2277 . '`Index_priv`, '
2278 . '`Alter_priv`, '
2279 . '`References_priv`, '
2280 . '`Create_tmp_table_priv`, '
2281 . '`Lock_tables_priv`, '
2282 . '`Create_view_priv`, '
2283 . '`Show_view_priv`, '
2284 . '`Create_routine_priv`, '
2285 . '`Alter_routine_priv`, '
2286 . '`Execute_priv`';
2288 $list_of_compared_privileges
2289 = '`Select_priv` = \'N\''
2290 . ' AND `Insert_priv` = \'N\''
2291 . ' AND `Update_priv` = \'N\''
2292 . ' AND `Delete_priv` = \'N\''
2293 . ' AND `Create_priv` = \'N\''
2294 . ' AND `Drop_priv` = \'N\''
2295 . ' AND `Grant_priv` = \'N\''
2296 . ' AND `References_priv` = \'N\''
2297 . ' AND `Create_tmp_table_priv` = \'N\''
2298 . ' AND `Lock_tables_priv` = \'N\''
2299 . ' AND `Create_view_priv` = \'N\''
2300 . ' AND `Show_view_priv` = \'N\''
2301 . ' AND `Create_routine_priv` = \'N\''
2302 . ' AND `Alter_routine_priv` = \'N\''
2303 . ' AND `Execute_priv` = \'N\'';
2305 if (PMA_MYSQL_INT_VERSION >= 50106) {
2306 $list_of_privileges .=
2307 ', `Event_priv`, '
2308 . '`Trigger_priv`';
2309 $list_of_compared_privileges .=
2310 ' AND `Event_priv` = \'N\''
2311 . ' AND `Trigger_priv` = \'N\'';
2314 $sql_query = '(SELECT ' . $list_of_privileges . ', `Db`'
2315 .' FROM `mysql`.`db`'
2316 .' WHERE \'' . PMA_sqlAddSlashes($checkprivs) . "'"
2317 .' LIKE `Db`'
2318 .' AND NOT (' . $list_of_compared_privileges. ')) '
2319 .'UNION '
2320 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2321 .' FROM `mysql`.`user` '
2322 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2323 .' ORDER BY `User` ASC,'
2324 .' `Host` ASC,'
2325 .' `Db` ASC;';
2326 $res = PMA_DBI_query($sql_query);
2327 $row = PMA_DBI_fetch_assoc($res);
2328 if ($row) {
2329 $found = true;
2332 if ($found) {
2333 while (true) {
2334 // prepare the current user
2335 $current_privileges = array();
2336 $current_user = $row['User'];
2337 $current_host = $row['Host'];
2338 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2339 $current_privileges[] = $row;
2340 $row = PMA_DBI_fetch_assoc($res);
2342 $user_form .= ' <tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2343 . ' <td';
2344 if (count($current_privileges) > 1) {
2345 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2347 $user_form .= '>' . (empty($current_user) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2348 . ' </td>' . "\n"
2349 . ' <td';
2350 if (count($current_privileges) > 1) {
2351 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2353 $user_form .= '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2354 for ($i = 0; $i < count($current_privileges); $i++) {
2355 $current = $current_privileges[$i];
2356 $user_form .= ' <td>' . "\n"
2357 . ' ';
2358 if (! isset($current['Db']) || $current['Db'] == '*') {
2359 $user_form .= __('global');
2360 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2361 $user_form .= __('database-specific');
2362 } else {
2363 $user_form .= __('wildcard'). ': <tt>' . htmlspecialchars($current['Db']) . '</tt>';
2365 $user_form .= "\n"
2366 . ' </td>' . "\n"
2367 . ' <td>' . "\n"
2368 . ' <tt>' . "\n"
2369 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, true)) . "\n"
2370 . ' </tt>' . "\n"
2371 . ' </td>' . "\n"
2372 . ' <td>' . "\n"
2373 . ' ' . ($current['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . "\n"
2374 . ' </td>' . "\n"
2375 . ' <td>' . "\n";
2376 $user_form .= sprintf(
2377 $link_edit,
2378 urlencode($current_user),
2379 urlencode($current_host),
2380 urlencode(! isset($current['Db']) || $current['Db'] == '*' ? '' : $current['Db']),
2383 $user_form .= '</td>' . "\n"
2384 . ' </tr>' . "\n";
2385 if (($i + 1) < count($current_privileges)) {
2386 $user_form .= '<tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">' . "\n";
2389 if (empty($row) && empty($row1) && empty($row2)) {
2390 break;
2392 $odd_row = ! $odd_row;
2394 } else {
2395 $user_form .= ' <tr class="odd">' . "\n"
2396 . ' <td colspan="6">' . "\n"
2397 . ' ' . __('No user found.') . "\n"
2398 . ' </td>' . "\n"
2399 . ' </tr>' . "\n";
2401 $user_form .= '</tbody>' . "\n"
2402 . '</table></fieldset></form>' . "\n";
2404 if ($GLOBALS['is_ajax_request'] == true) {
2405 $extra_data['user_form'] = $user_form;
2406 $message = PMA_Message::success(__('User has been added.'));
2407 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
2408 } else {
2409 // Offer to create a new user for the current database
2410 $user_form .= '<fieldset id="fieldset_add_user">' . "\n"
2411 . '<legend>' . __('New') . '</legend>' . "\n"
2412 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1&amp;dbname=' . htmlspecialchars($checkprivs) .'" rel="'.'checkprivs='.htmlspecialchars($checkprivs). '&amp;'.$GLOBALS['url_query'] . '" class="'.$conditional_class.'" name="db_specific">' . "\n"
2413 . PMA_getIcon('b_usradd.png')
2414 . ' ' . __('Add user') . '</a>' . "\n"
2415 . '</fieldset>' . "\n";
2416 echo $user_form ;
2419 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2423 * Displays the footer
2425 echo "\n\n";
2426 require './libraries/footer.inc.php';