Translated using Weblate.
[phpmyadmin.git] / server_privileges.php
blobef1db16827b973fc19570273915dce92430081df
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 * Sets globals from $_GET
35 $get_params = array(
36 'checkprivs',
37 'dbname',
38 'hostname',
39 'initial',
40 'tablename',
41 'username'
43 foreach ($get_params as $one_get_param) {
44 if (isset($_GET[$one_get_param])) {
45 $GLOBALS[$one_get_param] = $_GET[$one_get_param];
50 /**
51 * Messages are built using the message name
53 $strPrivDescAllPrivileges = __('Includes all privileges except GRANT.');
54 $strPrivDescAlter = __('Allows altering the structure of existing tables.');
55 $strPrivDescAlterRoutine = __('Allows altering and dropping stored routines.');
56 $strPrivDescCreateDb = __('Allows creating new databases and tables.');
57 $strPrivDescCreateRoutine = __('Allows creating stored routines.');
58 $strPrivDescCreateTbl = __('Allows creating new tables.');
59 $strPrivDescCreateTmpTable = __('Allows creating temporary tables.');
60 $strPrivDescCreateUser = __('Allows creating, dropping and renaming user accounts.');
61 $strPrivDescCreateView = __('Allows creating new views.');
62 $strPrivDescDelete = __('Allows deleting data.');
63 $strPrivDescDropDb = __('Allows dropping databases and tables.');
64 $strPrivDescDropTbl = __('Allows dropping tables.');
65 $strPrivDescEvent = __('Allows to set up events for the event scheduler');
66 $strPrivDescExecute = __('Allows executing stored routines.');
67 $strPrivDescFile = __('Allows importing data from and exporting data into files.');
68 $strPrivDescGrant = __('Allows adding users and privileges without reloading the privilege tables.');
69 $strPrivDescIndex = __('Allows creating and dropping indexes.');
70 $strPrivDescInsert = __('Allows inserting and replacing data.');
71 $strPrivDescLockTables = __('Allows locking tables for the current thread.');
72 $strPrivDescMaxConnections = __('Limits the number of new connections the user may open per hour.');
73 $strPrivDescMaxQuestions = __('Limits the number of queries the user may send to the server per hour.');
74 $strPrivDescMaxUpdates = __('Limits the number of commands that change any table or database the user may execute per hour.');
75 $strPrivDescMaxUserConnections = __('Limits the number of simultaneous connections the user may have.');
76 $strPrivDescProcess = __('Allows viewing processes of all users');
77 $strPrivDescReferences = __('Has no effect in this MySQL version.');
78 $strPrivDescReload = __('Allows reloading server settings and flushing the server\'s caches.');
79 $strPrivDescReplClient = __('Allows the user to ask where the slaves / masters are.');
80 $strPrivDescReplSlave = __('Needed for the replication slaves.');
81 $strPrivDescSelect = __('Allows reading data.');
82 $strPrivDescShowDb = __('Gives access to the complete list of databases.');
83 $strPrivDescShowView = __('Allows performing SHOW CREATE VIEW queries.');
84 $strPrivDescShutdown = __('Allows shutting down the server.');
85 $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.');
86 $strPrivDescTrigger = __('Allows creating and dropping triggers');
87 $strPrivDescUpdate = __('Allows changing data.');
88 $strPrivDescUsage = __('No privileges.');
90 /**
91 * Checks if a dropdown box has been used for selecting a database / table
93 if (PMA_isValid($_REQUEST['pred_tablename'])) {
94 $tablename = $_REQUEST['pred_tablename'];
95 unset($pred_tablename);
96 } elseif (PMA_isValid($_REQUEST['tablename'])) {
97 $tablename = $_REQUEST['tablename'];
98 } else {
99 unset($tablename);
102 if (PMA_isValid($_REQUEST['pred_dbname'])) {
103 $dbname = $_REQUEST['pred_dbname'];
104 unset($pred_dbname);
105 } elseif (PMA_isValid($_REQUEST['dbname'])) {
106 $dbname = $_REQUEST['dbname'];
107 } else {
108 unset($dbname);
109 unset($tablename);
112 if (isset($dbname)) {
113 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
114 if (isset($tablename)) {
115 $db_and_table .= PMA_backquote($tablename);
116 } else {
117 $db_and_table .= '*';
119 } else {
120 $db_and_table = '*.*';
123 // check if given $dbname is a wildcard or not
124 if (isset($dbname)) {
125 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
126 if (preg_match('/(?<!\\\\)(?:_|%)/i', $dbname)) {
127 $dbname_is_wildcard = true;
128 } else {
129 $dbname_is_wildcard = false;
134 * Checks if the user is allowed to do what he tries to...
136 if (! $is_superuser) {
137 include './libraries/server_links.inc.php';
138 echo '<h2>' . "\n"
139 . PMA_getIcon('b_usrlist.png')
140 . __('Privileges') . "\n"
141 . '</h2>' . "\n";
142 PMA_Message::error(__('No Privileges'))->display();
143 include './libraries/footer.inc.php';
146 $random_n = mt_rand(0, 1000000); // a random number that will be appended to the id of the user forms
149 * Escapes wildcard in a database+table specification
150 * before using it in a GRANT statement.
152 * Escaping a wildcard character in a GRANT is only accepted at the global
153 * or database level, not at table level; this is why I remove
154 * the escaping character. Internally, in mysql.tables_priv.Db there are
155 * no escaping (for example test_db) but in mysql.db you'll see test\_db
156 * for a db-specific privilege.
158 * @param string $dbname Database name
159 * @param string $tablename Table name
161 * @return string the escaped (if necessary) database.table
163 function PMA_wildcardEscapeForGrant($dbname, $tablename)
166 if (! strlen($dbname)) {
167 $db_and_table = '*.*';
168 } else {
169 if (strlen($tablename)) {
170 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
171 $db_and_table .= PMA_backquote($tablename);
172 } else {
173 $db_and_table = PMA_backquote($dbname) . '.';
174 $db_and_table .= '*';
177 return $db_and_table;
181 * Generates a condition on the user name
183 * @param string $initial the user's initial
185 * @return string the generated condition
187 function PMA_rangeOfUsers($initial = '')
189 // strtolower() is used because the User field
190 // might be BINARY, so LIKE would be case sensitive
191 if (! empty($initial)) {
192 $ret = " WHERE `User` LIKE '" . PMA_sqlAddSlashes($initial, true) . "%'"
193 . " OR `User` LIKE '" . PMA_sqlAddSlashes(strtolower($initial), true) . "%'";
194 } else {
195 $ret = '';
197 return $ret;
198 } // end function
201 * Extracts the privilege information of a priv table row
203 * @param array $row the row
204 * @param boolean $enableHTML add <dfn> tag with tooltips
206 * @global resource $user_link the database connection
208 * @return array
210 function PMA_extractPrivInfo($row = '', $enableHTML = false)
212 $grants = array(
213 array(
214 'Select_priv',
215 'SELECT',
216 __('Allows reading data.')),
217 array(
218 'Insert_priv',
219 'INSERT',
220 __('Allows inserting and replacing data.')),
221 array(
222 'Update_priv',
223 'UPDATE',
224 __('Allows changing data.')),
225 array(
226 'Delete_priv',
227 'DELETE',
228 __('Allows deleting data.')),
229 array(
230 'Create_priv',
231 'CREATE',
232 __('Allows creating new databases and tables.')),
233 array(
234 'Drop_priv',
235 'DROP',
236 __('Allows dropping databases and tables.')),
237 array(
238 'Reload_priv',
239 'RELOAD',
240 __('Allows reloading server settings and flushing the server\'s caches.')),
241 array(
242 'Shutdown_priv',
243 'SHUTDOWN',
244 __('Allows shutting down the server.')),
245 array(
246 'Process_priv',
247 'PROCESS',
248 __('Allows viewing processes of all users')),
249 array(
250 'File_priv',
251 'FILE',
252 __('Allows importing data from and exporting data into files.')),
253 array(
254 'References_priv',
255 'REFERENCES',
256 __('Has no effect in this MySQL version.')),
257 array(
258 'Index_priv',
259 'INDEX',
260 __('Allows creating and dropping indexes.')),
261 array(
262 'Alter_priv',
263 'ALTER',
264 __('Allows altering the structure of existing tables.')),
265 array(
266 'Show_db_priv',
267 'SHOW DATABASES',
268 __('Gives access to the complete list of databases.')),
269 array(
270 'Super_priv',
271 'SUPER',
272 __('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.')),
273 array(
274 'Create_tmp_table_priv',
275 'CREATE TEMPORARY TABLES',
276 __('Allows creating temporary tables.')),
277 array(
278 'Lock_tables_priv',
279 'LOCK TABLES',
280 __('Allows locking tables for the current thread.')),
281 array(
282 'Repl_slave_priv',
283 'REPLICATION SLAVE',
284 __('Needed for the replication slaves.')),
285 array(
286 'Repl_client_priv',
287 'REPLICATION CLIENT',
288 __('Allows the user to ask where the slaves / masters are.')),
289 array(
290 'Create_view_priv',
291 'CREATE VIEW',
292 __('Allows creating new views.')),
293 array(
294 'Event_priv',
295 'EVENT',
296 __('Allows to set up events for the event scheduler')),
297 array(
298 'Trigger_priv',
299 'TRIGGER',
300 __('Allows creating and dropping triggers')),
301 // for table privs:
302 array(
303 'Create View_priv',
304 'CREATE VIEW',
305 __('Allows creating new views.')),
306 array(
307 'Show_view_priv',
308 'SHOW VIEW',
309 __('Allows performing SHOW CREATE VIEW queries.')),
310 // for table privs:
311 array(
312 'Show view_priv',
313 'SHOW VIEW',
314 __('Allows performing SHOW CREATE VIEW queries.')),
315 array(
316 'Create_routine_priv',
317 'CREATE ROUTINE',
318 __('Allows creating stored routines.')),
319 array(
320 'Alter_routine_priv',
321 'ALTER ROUTINE',
322 __('Allows altering and dropping stored routines.')),
323 array(
324 'Create_user_priv',
325 'CREATE USER',
326 __('Allows creating, dropping and renaming user accounts.')),
327 array(
328 'Execute_priv',
329 'EXECUTE',
330 __('Allows executing stored routines.')),
333 if (! empty($row) && isset($row['Table_priv'])) {
334 $row1 = PMA_DBI_fetch_single_row(
335 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
336 'ASSOC', $GLOBALS['userlink']
338 $av_grants = explode('\',\'', substr($row1['Type'], 5, strlen($row1['Type']) - 7));
339 unset($row1);
340 $users_grants = explode(',', $row['Table_priv']);
341 foreach ($av_grants as $current_grant) {
342 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
344 unset($current_grant);
345 unset($av_grants);
346 unset($users_grants);
348 $privs = array();
349 $allPrivileges = true;
350 foreach ($grants as $current_grant) {
351 if ((! empty($row) && isset($row[$current_grant[0]]))
352 || (empty($row) && isset($GLOBALS[$current_grant[0]]))
354 if ((! empty($row) && $row[$current_grant[0]] == 'Y')
355 || (empty($row)
356 && ($GLOBALS[$current_grant[0]] == 'Y'
357 || (is_array($GLOBALS[$current_grant[0]])
358 && count($GLOBALS[$current_grant[0]]) == $GLOBALS['column_count']
359 && empty($GLOBALS[$current_grant[0] . '_none']))))
361 if ($enableHTML) {
362 $privs[] = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
363 } else {
364 $privs[] = $current_grant[1];
366 } elseif (! empty($GLOBALS[$current_grant[0]])
367 && is_array($GLOBALS[$current_grant[0]])
368 && empty($GLOBALS[$current_grant[0] . '_none'])) {
369 if ($enableHTML) {
370 $priv_string = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
371 } else {
372 $priv_string = $current_grant[1];
374 $privs[] = $priv_string . ' (`' . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
375 } else {
376 $allPrivileges = false;
380 if (empty($privs)) {
381 if ($enableHTML) {
382 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
383 } else {
384 $privs[] = 'USAGE';
386 } elseif ($allPrivileges && (! isset($GLOBALS['grant_count']) || count($privs) == $GLOBALS['grant_count'])) {
387 if ($enableHTML) {
388 $privs = array('<dfn title="' . __('Includes all privileges except GRANT.') . '">ALL PRIVILEGES</dfn>');
389 } else {
390 $privs = array('ALL PRIVILEGES');
393 return $privs;
394 } // end of the 'PMA_extractPrivInfo()' function
397 * Displays on which column(s) a table-specific privilege is granted
399 function PMA_display_column_privs($columns, $row, $name_for_select,
400 $priv_for_header, $name, $name_for_dfn, $name_for_current)
402 echo ' <div class="item" id="div_item_' . $name . '">' . "\n"
403 . ' <label for="select_' . $name . '_priv">' . "\n"
404 . ' <tt><dfn title="' . $name_for_dfn . '">'
405 . $priv_for_header . '</dfn></tt>' . "\n"
406 . ' </label><br />' . "\n"
407 . ' <select id="select_' . $name . '_priv" name="'
408 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
410 foreach ($columns as $current_column => $current_column_privileges) {
411 echo ' <option value="' . htmlspecialchars($current_column) . '"';
412 if ($row[$name_for_select] == 'Y' || $current_column_privileges[$name_for_current]) {
413 echo ' selected="selected"';
415 echo '>' . htmlspecialchars($current_column) . '</option>' . "\n";
418 echo ' </select>' . "\n"
419 . ' <i>' . __('Or') . '</i>' . "\n"
420 . ' <label for="checkbox_' . $name_for_select
421 . '_none"><input type="checkbox"'
422 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
423 . ' name="' . $name_for_select . '_none" id="checkbox_'
424 . $name_for_select . '_none" title="' . _pgettext('None privileges', 'None') . '" />'
425 . _pgettext('None privileges', 'None') . '</label>' . "\n"
426 . ' </div>' . "\n";
427 } // end function
431 * Displays the privileges form table
433 * @param string $db the database
434 * @param string $table the table
435 * @param boolean $submit wheather to display the submit button or not
437 * @global array $cfg the phpMyAdmin configuration
438 * @global ressource $user_link the database connection
440 * @return void
442 function PMA_displayPrivTable($db = '*', $table = '*', $submit = true)
444 global $random_n;
446 if ($db == '*') {
447 $table = '*';
450 if (isset($GLOBALS['username'])) {
451 $username = $GLOBALS['username'];
452 $hostname = $GLOBALS['hostname'];
453 if ($db == '*') {
454 $sql_query = "SELECT * FROM `mysql`.`user`"
455 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
456 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
457 } elseif ($table == '*') {
458 $sql_query = "SELECT * FROM `mysql`.`db`"
459 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
460 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
461 ." AND '" . PMA_unescape_mysql_wildcards($db) . "'"
462 ." LIKE `Db`;";
463 } else {
464 $sql_query = "SELECT `Table_priv`"
465 ." FROM `mysql`.`tables_priv`"
466 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
467 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
468 ." AND `Db` = '" . PMA_unescape_mysql_wildcards($db) . "'"
469 ." AND `Table_name` = '" . PMA_sqlAddSlashes($table) . "';";
471 $row = PMA_DBI_fetch_single_row($sql_query);
473 if (empty($row)) {
474 if ($table == '*') {
475 if ($db == '*') {
476 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
477 } elseif ($table == '*') {
478 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
480 $res = PMA_DBI_query($sql_query);
481 while ($row1 = PMA_DBI_fetch_row($res)) {
482 if (substr($row1[0], 0, 4) == 'max_') {
483 $row[$row1[0]] = 0;
484 } else {
485 $row[$row1[0]] = 'N';
488 PMA_DBI_free_result($res);
489 } else {
490 $row = array('Table_priv' => '');
493 if (isset($row['Table_priv'])) {
494 $row1 = PMA_DBI_fetch_single_row(
495 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
496 'ASSOC', $GLOBALS['userlink']
498 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
499 // the View for Create is spelled with uppercase V
500 // the view for Show is spelled with lowercase v
501 // and there is a space between the words
503 $av_grants = explode('\',\'', substr($row1['Type'], strpos($row1['Type'], '(') + 2, strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3));
504 unset($row1);
505 $users_grants = explode(',', $row['Table_priv']);
507 foreach ($av_grants as $current_grant) {
508 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
510 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
512 // get collumns
513 $res = PMA_DBI_try_query('SHOW COLUMNS FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($db)) . '.' . PMA_backquote($table) . ';');
514 $columns = array();
515 if ($res) {
516 while ($row1 = PMA_DBI_fetch_row($res)) {
517 $columns[$row1[0]] = array(
518 'Select' => false,
519 'Insert' => false,
520 'Update' => false,
521 'References' => false
524 PMA_DBI_free_result($res);
526 unset($res, $row1);
528 // t a b l e - s p e c i f i c p r i v i l e g e s
529 if (! empty($columns)) {
530 $res = PMA_DBI_query(
531 'SELECT `Column_name`, `Column_priv`'
532 .' FROM `mysql`.`columns_priv`'
533 .' WHERE `User`'
534 .' = \'' . PMA_sqlAddSlashes($username) . "'"
535 .' AND `Host`'
536 .' = \'' . PMA_sqlAddSlashes($hostname) . "'"
537 .' AND `Db`'
538 .' = \'' . PMA_sqlAddSlashes(PMA_unescape_mysql_wildcards($db)) . "'"
539 .' AND `Table_name`'
540 .' = \'' . PMA_sqlAddSlashes($table) . '\';'
543 while ($row1 = PMA_DBI_fetch_row($res)) {
544 $row1[1] = explode(',', $row1[1]);
545 foreach ($row1[1] as $current) {
546 $columns[$row1[0]][$current] = true;
549 PMA_DBI_free_result($res);
550 unset($res, $row1, $current);
552 echo '<input type="hidden" name="grant_count" value="' . count($row) . '" />' . "\n"
553 . '<input type="hidden" name="column_count" value="' . count($columns) . '" />' . "\n"
554 . '<fieldset id="fieldset_user_priv">' . "\n"
555 . ' <legend>' . __('Table-specific privileges')
556 . PMA_showHint(__('Note: MySQL privilege names are expressed in English'))
557 . '</legend>' . "\n";
561 // privs that are attached to a specific column
562 PMA_display_column_privs(
563 $columns, $row, 'Select_priv', 'SELECT',
564 'select', __('Allows reading data.'), 'Select'
567 PMA_display_column_privs(
568 $columns, $row, 'Insert_priv', 'INSERT',
569 'insert', __('Allows inserting and replacing data.'), 'Insert'
572 PMA_display_column_privs(
573 $columns, $row, 'Update_priv', 'UPDATE',
574 'update', __('Allows changing data.'), 'Update'
577 PMA_display_column_privs(
578 $columns, $row, 'References_priv', 'REFERENCES', 'references',
579 __('Has no effect in this MySQL version.'), 'References'
582 // privs that are not attached to a specific column
584 echo ' <div class="item">' . "\n";
585 foreach ($row as $current_grant => $current_grant_value) {
586 if (in_array(substr($current_grant, 0, (strlen($current_grant) - 5)),
587 array('Select', 'Insert', 'Update', 'References'))) {
588 continue;
590 // make a substitution to match the messages variables;
591 // also we must substitute the grant we get, because we can't generate
592 // a form variable containing blanks (those would get changed to
593 // an underscore when receiving the POST)
594 if ($current_grant == 'Create View_priv') {
595 $tmp_current_grant = 'CreateView_priv';
596 $current_grant = 'Create_view_priv';
597 } elseif ($current_grant == 'Show view_priv') {
598 $tmp_current_grant = 'ShowView_priv';
599 $current_grant = 'Show_view_priv';
600 } else {
601 $tmp_current_grant = $current_grant;
604 echo ' <div class="item">' . "\n"
605 . ' <input type="checkbox"'
606 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
607 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
608 . '" value="Y" '
609 . ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
610 . 'title="';
612 echo (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
613 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
614 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl']) . '"/>' . "\n";
616 echo ' <label for="checkbox_' . $current_grant
617 . '"><tt><dfn title="'
618 . (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
619 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
620 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl'])
621 . '">' . strtoupper(substr($current_grant, 0, strlen($current_grant) - 5)) . '</dfn></tt></label>' . "\n"
622 . ' </div>' . "\n";
623 } // end foreach ()
625 echo ' </div>' . "\n";
626 // for Safari 2.0.2
627 echo ' <div class="clearfloat"></div>' . "\n";
629 } else {
631 // g l o b a l o r d b - s p e c i f i c
633 $privTable_names = array(0 => __('Data'), 1 => __('Structure'), 2 => __('Administration'));
635 // d a t a
636 $privTable[0] = array(
637 array('Select', 'SELECT', __('Allows reading data.')),
638 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
639 array('Update', 'UPDATE', __('Allows changing data.')),
640 array('Delete', 'DELETE', __('Allows deleting data.'))
642 if ($db == '*') {
643 $privTable[0][] = array('File', 'FILE', __('Allows importing data from and exporting data into files.'));
646 // s t r u c t u r e
647 $privTable[1] = array(
648 array('Create', 'CREATE', ($table == '*' ? __('Allows creating new databases and tables.') : __('Allows creating new tables.'))),
649 array('Alter', 'ALTER', __('Allows altering the structure of existing tables.')),
650 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
651 array('Drop', 'DROP', ($table == '*' ? __('Allows dropping databases and tables.') : __('Allows dropping tables.'))),
652 array('Create_tmp_table', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
653 array('Show_view', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
654 array('Create_routine', 'CREATE ROUTINE', __('Allows creating stored routines.')),
655 array('Alter_routine', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
656 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
658 // this one is for a db-specific priv: Create_view_priv
659 if (isset($row['Create_view_priv'])) {
660 $privTable[1][] = array('Create_view', 'CREATE VIEW', __('Allows creating new views.'));
662 // this one is for a table-specific priv: Create View_priv
663 if (isset($row['Create View_priv'])) {
664 $privTable[1][] = array('Create View', 'CREATE VIEW', __('Allows creating new views.'));
666 if (isset($row['Event_priv'])) {
667 // MySQL 5.1.6
668 $privTable[1][] = array('Event', 'EVENT', __('Allows to set up events for the event scheduler'));
669 $privTable[1][] = array('Trigger', 'TRIGGER', __('Allows creating and dropping triggers'));
672 // a d m i n i s t r a t i o n
673 $privTable[2] = array(
674 array('Grant', 'GRANT', __('Allows adding users and privileges without reloading the privilege tables.')),
676 if ($db == '*') {
677 $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.'));
678 $privTable[2][] = array('Process', 'PROCESS', __('Allows viewing processes of all users'));
679 $privTable[2][] = array('Reload', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.'));
680 $privTable[2][] = array('Shutdown', 'SHUTDOWN', __('Allows shutting down the server.'));
681 $privTable[2][] = array('Show_db', 'SHOW DATABASES', __('Gives access to the complete list of databases.'));
683 $privTable[2][] = array('Lock_tables', 'LOCK TABLES', __('Allows locking tables for the current thread.'));
684 $privTable[2][] = array('References', 'REFERENCES', __('Has no effect in this MySQL version.'));
685 if ($db == '*') {
686 $privTable[2][] = array('Repl_client', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.'));
687 $privTable[2][] = array('Repl_slave', 'REPLICATION SLAVE', __('Needed for the replication slaves.'));
688 $privTable[2][] = array('Create_user', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.'));
690 echo '<input type="hidden" name="grant_count" value="'
691 . (count($privTable[0]) + count($privTable[1]) + count($privTable[2]) - (isset($row['Grant_priv']) ? 1 : 0))
692 . '" />' . "\n"
693 . '<fieldset id="fieldset_user_global_rights">' . "\n"
694 . ' <legend>' . "\n"
695 . ' '
696 . ($db == '*'
697 ? __('Global privileges')
698 : ($table == '*'
699 ? __('Database-specific privileges')
700 : __('Table-specific privileges'))) . "\n"
701 . ' (<a href="server_privileges.php?'
702 . $GLOBALS['url_query'] . '&amp;checkall=1" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', true); return false;">'
703 . __('Check All') . '</a> /' . "\n"
704 . ' <a href="server_privileges.php?'
705 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', false); return false;">'
706 . __('Uncheck All') . '</a>)' . "\n"
707 . ' </legend>' . "\n"
708 . ' <p><small><i>' . __('Note: MySQL privilege names are expressed in English') . '</i></small></p>' . "\n";
710 // Output the Global privilege tables with checkboxes
711 foreach ($privTable as $i => $table) {
712 echo ' <fieldset>' . "\n"
713 . ' <legend>' . __($privTable_names[$i]) . '</legend>' . "\n";
714 foreach ($table as $priv) {
715 echo ' <div class="item">' . "\n"
716 . ' <input type="checkbox"'
717 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0] . '_priv"'
718 . ' value="Y" title="' . $priv[2] . '"'
719 . ((! empty($GLOBALS['checkall']) || $row[$priv[0] . '_priv'] == 'Y') ? ' checked="checked"' : '')
720 . '/>' . "\n"
721 . ' <label for="checkbox_' . $priv[0] . '_priv"><tt><dfn title="' . $priv[2] . '">'
722 . $priv[1] . '</dfn></tt></label>' . "\n"
723 . ' </div>' . "\n";
725 echo ' </fieldset>' . "\n";
728 // The "Resource limits" box is not displayed for db-specific privs
729 if ($db == '*') {
730 echo ' <fieldset>' . "\n"
731 . ' <legend>' . __('Resource limits') . '</legend>' . "\n"
732 . ' <p><small><i>' . __('Note: Setting these options to 0 (zero) removes the limit.') . '</i></small></p>' . "\n"
733 . ' <div class="item">' . "\n"
734 . ' <label for="text_max_questions"><tt><dfn title="'
735 . __('Limits the number of queries the user may send to the server per hour.') . '">MAX QUERIES PER HOUR</dfn></tt></label>' . "\n"
736 . ' <input type="text" name="max_questions" id="text_max_questions" value="'
737 . $row['max_questions'] . '" size="11" maxlength="11" title="' . __('Limits the number of queries the user may send to the server per hour.') . '" />' . "\n"
738 . ' </div>' . "\n"
739 . ' <div class="item">' . "\n"
740 . ' <label for="text_max_updates"><tt><dfn title="'
741 . __('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"
742 . ' <input type="text" name="max_updates" id="text_max_updates" value="'
743 . $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"
744 . ' </div>' . "\n"
745 . ' <div class="item">' . "\n"
746 . ' <label for="text_max_connections"><tt><dfn title="'
747 . __('Limits the number of new connections the user may open per hour.') . '">MAX CONNECTIONS PER HOUR</dfn></tt></label>' . "\n"
748 . ' <input type="text" name="max_connections" id="text_max_connections" value="'
749 . $row['max_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of new connections the user may open per hour.') . '" />' . "\n"
750 . ' </div>' . "\n"
751 . ' <div class="item">' . "\n"
752 . ' <label for="text_max_user_connections"><tt><dfn title="'
753 . __('Limits the number of simultaneous connections the user may have.') . '">MAX USER_CONNECTIONS</dfn></tt></label>' . "\n"
754 . ' <input type="text" name="max_user_connections" id="text_max_user_connections" value="'
755 . $row['max_user_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of simultaneous connections the user may have.') . '" />' . "\n"
756 . ' </div>' . "\n"
757 . ' </fieldset>' . "\n";
759 // for Safari 2.0.2
760 echo ' <div class="clearfloat"></div>' . "\n";
762 echo '</fieldset>' . "\n";
763 if ($submit) {
764 echo '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">' . "\n"
765 . ' <input type="submit" name="update_privs" value="' . __('Go') . '" />' . "\n"
766 . '</fieldset>' . "\n";
768 } // end of the 'PMA_displayPrivTable()' function
772 * Displays the fields used by the "new user" form as well as the
773 * "change login information / copy user" form.
775 * @param string $mode are we creating a new user or are we just
776 * changing one? (allowed values: 'new', 'change')
778 * @global array $cfg the phpMyAdmin configuration
779 * @global ressource $user_link the database connection
781 * @return void
783 function PMA_displayLoginInformationFields($mode = 'new')
785 // Get user/host name lengths
786 $fields_info = PMA_DBI_get_columns('mysql', 'user', null, true);
787 $username_length = 16;
788 $hostname_length = 41;
789 foreach ($fields_info as $val) {
790 if ($val['Field'] == 'User') {
791 strtok($val['Type'], '()');
792 $v = strtok('()');
793 if (is_int($v)) {
794 $username_length = $v;
796 } elseif ($val['Field'] == 'Host') {
797 strtok($val['Type'], '()');
798 $v = strtok('()');
799 if (is_int($v)) {
800 $hostname_length = $v;
804 unset($fields_info);
806 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
807 $GLOBALS['pred_username'] = 'any';
809 echo '<fieldset id="fieldset_add_user_login">' . "\n"
810 . '<legend>' . __('Login Information') . '</legend>' . "\n"
811 . '<div class="item">' . "\n"
812 . '<label for="select_pred_username">' . "\n"
813 . ' ' . __('User name') . ':' . "\n"
814 . '</label>' . "\n"
815 . '<span class="options">' . "\n"
816 . ' <select name="pred_username" id="select_pred_username" title="' . __('User name') . '"' . "\n"
817 . ' onchange="if (this.value == \'any\') { username.value = \'\'; } else if (this.value == \'userdefined\') { username.focus(); username.select(); }">' . "\n"
818 . ' <option value="any"' . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any') ? ' selected="selected"' : '') . '>' . __('Any user') . '</option>' . "\n"
819 . ' <option value="userdefined"' . ((! isset($GLOBALS['pred_username']) || $GLOBALS['pred_username'] == 'userdefined') ? ' selected="selected"' : '') . '>' . __('Use text field') . ':</option>' . "\n"
820 . ' </select>' . "\n"
821 . '</span>' . "\n"
822 . '<input type="text" name="username" maxlength="'
823 . $username_length . '" title="' . __('User name') . '"'
824 . (empty($GLOBALS['username'])
825 ? ''
826 : ' value="' . htmlspecialchars(isset($GLOBALS['new_username'])
827 ? $GLOBALS['new_username']
828 : $GLOBALS['username']) . '"')
829 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
830 . '</div>' . "\n"
831 . '<div class="item">' . "\n"
832 . '<label for="select_pred_hostname">' . "\n"
833 . ' ' . __('Host') . ':' . "\n"
834 . '</label>' . "\n"
835 . '<span class="options">' . "\n"
836 . ' <select name="pred_hostname" id="select_pred_hostname" title="' . __('Host') . '"' . "\n";
837 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
838 if (! empty($_current_user)) {
839 $thishost = str_replace("'", '', substr($_current_user, (strrpos($_current_user, '@') + 1)));
840 if ($thishost == 'localhost' || $thishost == '127.0.0.1') {
841 unset($thishost);
844 echo ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } else if (this.value == \'localhost\') { hostname.value = \'localhost\'; } '
845 . (empty($thishost) ? '' : 'else if (this.value == \'thishost\') { hostname.value = \'' . addslashes(htmlspecialchars($thishost)) . '\'; } ')
846 . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } else if (this.value == \'userdefined\') { hostname.focus(); hostname.select(); }">' . "\n";
847 unset($_current_user);
849 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
850 if (! isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
851 switch (strtolower($GLOBALS['hostname'])) {
852 case 'localhost':
853 case '127.0.0.1':
854 $GLOBALS['pred_hostname'] = 'localhost';
855 break;
856 case '%':
857 $GLOBALS['pred_hostname'] = 'any';
858 break;
859 default:
860 $GLOBALS['pred_hostname'] = 'userdefined';
861 break;
864 echo ' <option value="any"'
865 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
866 ? ' selected="selected"' : '') . '>' . __('Any host')
867 . '</option>' . "\n"
868 . ' <option value="localhost"'
869 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'localhost')
870 ? ' selected="selected"' : '') . '>' . __('Local')
871 . '</option>' . "\n";
872 if (! empty($thishost)) {
873 echo ' <option value="thishost"'
874 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'thishost')
875 ? ' selected="selected"' : '') . '>' . __('This Host')
876 . '</option>' . "\n";
878 unset($thishost);
879 echo ' <option value="hosttable"'
880 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'hosttable')
881 ? ' selected="selected"' : '') . '>' . __('Use Host Table')
882 . '</option>' . "\n"
883 . ' <option value="userdefined"'
884 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'userdefined')
885 ? ' selected="selected"' : '')
886 . '>' . __('Use text field') . ':</option>' . "\n"
887 . ' </select>' . "\n"
888 . '</span>' . "\n"
889 . '<input type="text" name="hostname" maxlength="'
890 . $hostname_length . '" value="'
891 . htmlspecialchars(isset($GLOBALS['hostname']) ? $GLOBALS['hostname'] : '')
892 . '" title="' . __('Host')
893 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
894 . PMA_showHint(__('When Host table is used, this field is ignored and values stored in Host table are used instead.'))
895 . '</div>' . "\n"
896 . '<div class="item">' . "\n"
897 . '<label for="select_pred_password">' . "\n"
898 . ' ' . __('Password') . ':' . "\n"
899 . '</label>' . "\n"
900 . '<span class="options">' . "\n"
901 . ' <select name="pred_password" id="select_pred_password" title="'
902 . __('Password') . '"' . "\n"
903 . ' onchange="if (this.value == \'none\') { pma_pw.value = \'\'; pma_pw2.value = \'\'; } else if (this.value == \'userdefined\') { pma_pw.focus(); pma_pw.select(); }">' . "\n"
904 . ($mode == 'change' ? ' <option value="keep" selected="selected">' . __('Do not change the password') . '</option>' . "\n" : '')
905 . ' <option value="none"';
906 if (isset($GLOBALS['username']) && $mode != 'change') {
907 echo ' selected="selected"';
909 echo '>' . __('No Password') . '</option>' . "\n"
910 . ' <option value="userdefined"' . (isset($GLOBALS['username']) ? '' : ' selected="selected"') . '>' . __('Use text field') . ':</option>' . "\n"
911 . ' </select>' . "\n"
912 . '</span>' . "\n"
913 . '<input type="password" id="text_pma_pw" name="pma_pw" title="' . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
914 . '</div>' . "\n"
915 . '<div class="item" id="div_element_before_generate_password">' . "\n"
916 . '<label for="text_pma_pw2">' . "\n"
917 . ' ' . __('Re-type') . ':' . "\n"
918 . '</label>' . "\n"
919 . '<span class="options">&nbsp;</span>' . "\n"
920 . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="' . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
921 . '</div>' . "\n"
922 // Generate password added here via jQuery
923 . '</fieldset>' . "\n";
924 } // end of the 'PMA_displayUserAndHostFields()' function
928 * Returns all the grants for a certain user on a certain host
929 * Used in the export privileges for all users section
931 * @param string $user User name
932 * @param string $host Host name
934 * @return string containing all the grants text
936 function PMA_getGrants($user, $host) {
937 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddSlashes($user) . "'@'" . PMA_sqlAddSlashes($host) . "'");
938 $response = '';
939 foreach ($grants as $one_grant) {
940 $response .= $one_grant . ";\n\n";
942 return $response;
943 } // end of the 'PMA_getGrants()' function
946 * Changes / copies a user, part I
948 if (isset($_REQUEST['change_copy'])) {
949 $user_host_condition = ' WHERE `User`'
950 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
951 .' AND `Host`'
952 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
953 $row = PMA_DBI_fetch_single_row('SELECT * FROM `mysql`.`user` ' . $user_host_condition);
954 if (! $row) {
955 PMA_Message::notice(__('No user found.'))->display();
956 unset($_REQUEST['change_copy']);
957 } else {
958 extract($row, EXTR_OVERWRITE);
959 // Recent MySQL versions have the field "Password" in mysql.user,
960 // so the previous extract creates $Password but this script
961 // uses $password
962 if (! isset($password) && isset($Password)) {
963 $password = $Password;
965 $queries = array();
971 * Adds a user
972 * (Changes / copies a user, part II)
974 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
975 $sql_query = '';
976 if ($pred_username == 'any') {
977 $username = '';
979 switch ($pred_hostname) {
980 case 'any':
981 $hostname = '%';
982 break;
983 case 'localhost':
984 $hostname = 'localhost';
985 break;
986 case 'hosttable':
987 $hostname = '';
988 break;
989 case 'thishost':
990 $_user_name = PMA_DBI_fetch_value('SELECT USER()');
991 $hostname = substr($_user_name, (strrpos($_user_name, '@') + 1));
992 unset($_user_name);
993 break;
995 $sql = "SELECT '1' FROM `mysql`.`user`"
996 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
997 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
998 if (PMA_DBI_fetch_value($sql) == 1) {
999 $message = PMA_Message::error(__('The user %s already exists!'));
1000 $message->addParam('[i]\'' . $username . '\'@\'' . $hostname . '\'[/i]');
1001 $_REQUEST['adduser'] = true;
1002 $_add_user_error = true;
1003 } else {
1005 $create_user_real = 'CREATE USER \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
1007 $real_sql_query = 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
1008 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
1009 if ($pred_password != 'none' && $pred_password != 'keep') {
1010 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
1011 $real_sql_query .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
1012 if (isset($create_user_real)) {
1013 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
1014 $create_user_real .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
1016 } else {
1017 if ($pred_password == 'keep' && ! empty($password)) {
1018 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
1019 if (isset($create_user_real)) {
1020 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
1023 $sql_query = $real_sql_query;
1024 if (isset($create_user_real)) {
1025 $create_user_show = $create_user_real;
1029 * @todo similar code appears twice in this script
1031 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1032 || (isset($max_questions) || isset($max_connections)
1033 || isset($max_updates) || isset($max_user_connections))
1035 $real_sql_query .= ' WITH';
1036 $sql_query .= ' WITH';
1037 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1038 $real_sql_query .= ' GRANT OPTION';
1039 $sql_query .= ' GRANT OPTION';
1041 if (isset($max_questions)) {
1042 // avoid negative values
1043 $max_questions = max(0, (int)$max_questions);
1044 $real_sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1045 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1047 if (isset($max_connections)) {
1048 $max_connections = max(0, (int)$max_connections);
1049 $real_sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1050 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1052 if (isset($max_updates)) {
1053 $max_updates = max(0, (int)$max_updates);
1054 $real_sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1055 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1057 if (isset($max_user_connections)) {
1058 $max_user_connections = max(0, (int)$max_user_connections);
1059 $real_sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1060 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1063 if (isset($create_user_real)) {
1064 $create_user_real .= ';';
1065 $create_user_show .= ';';
1067 $real_sql_query .= ';';
1068 $sql_query .= ';';
1069 if (empty($_REQUEST['change_copy'])) {
1070 $_error = false;
1072 if (isset($create_user_real)) {
1073 if (! PMA_DBI_try_query($create_user_real)) {
1074 $_error = true;
1076 $sql_query = $create_user_show . $sql_query;
1079 if ($_error || ! PMA_DBI_try_query($real_sql_query)) {
1080 $_REQUEST['createdb-1']
1081 = $_REQUEST['createdb-2']
1082 = $_REQUEST['createdb-3'] = false;
1083 $message = PMA_Message::rawError(PMA_DBI_getError());
1084 } else {
1085 $message = PMA_Message::success(__('You have added a new user.'));
1088 if (isset($_REQUEST['createdb-1'])) {
1089 // Create database with same name and grant all privileges
1090 $q = 'CREATE DATABASE IF NOT EXISTS '
1091 . PMA_backquote(PMA_sqlAddSlashes($username)) . ';';
1092 $sql_query .= $q;
1093 if (! PMA_DBI_try_query($q)) {
1094 $message = PMA_Message::rawError(PMA_DBI_getError());
1095 break;
1100 * If we are not in an Ajax request, we can't reload navigation now
1102 if ($GLOBALS['is_ajax_request'] != true) {
1103 // this is needed in case tracking is on:
1104 $GLOBALS['db'] = $username;
1105 $GLOBALS['reload'] = true;
1106 PMA_reloadNavigation();
1109 $q = 'GRANT ALL PRIVILEGES ON '
1110 . PMA_backquote(PMA_sqlAddSlashes($username)) . '.* TO \''
1111 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1112 $sql_query .= $q;
1113 if (! PMA_DBI_try_query($q)) {
1114 $message = PMA_Message::rawError(PMA_DBI_getError());
1118 if (isset($_REQUEST['createdb-2'])) {
1119 // Grant all privileges on wildcard name (username\_%)
1120 $q = 'GRANT ALL PRIVILEGES ON '
1121 . PMA_backquote(PMA_sqlAddSlashes($username) . '\_%') . '.* TO \''
1122 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1123 $sql_query .= $q;
1124 if (! PMA_DBI_try_query($q)) {
1125 $message = PMA_Message::rawError(PMA_DBI_getError());
1129 if (isset($_REQUEST['createdb-3'])) {
1130 // Grant all privileges on the specified database to the new user
1131 $q = 'GRANT ALL PRIVILEGES ON '
1132 . PMA_backquote(PMA_sqlAddSlashes($dbname)) . '.* TO \''
1133 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1134 $sql_query .= $q;
1135 if (! PMA_DBI_try_query($q)) {
1136 $message = PMA_Message::rawError(PMA_DBI_getError());
1139 } else {
1140 if (isset($create_user_real)) {
1141 $queries[] = $create_user_real;
1143 $queries[] = $real_sql_query;
1144 // we put the query containing the hidden password in
1145 // $queries_for_display, at the same position occupied
1146 // by the real query in $queries
1147 $tmp_count = count($queries);
1148 if (isset($create_user_real)) {
1149 $queries_for_display[$tmp_count - 2] = $create_user_show;
1151 $queries_for_display[$tmp_count - 1] = $sql_query;
1153 unset($res, $real_sql_query);
1159 * Changes / copies a user, part III
1161 if (isset($_REQUEST['change_copy'])) {
1162 $user_host_condition = ' WHERE `User`'
1163 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1164 .' AND `Host`'
1165 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
1166 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1167 while ($row = PMA_DBI_fetch_assoc($res)) {
1168 $queries[] = 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1169 .' ON ' . PMA_backquote($row['Db']) . '.*'
1170 .' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1171 . ($row['Grant_priv'] == 'Y' ? ' WITH GRANT OPTION;' : ';');
1173 PMA_DBI_free_result($res);
1174 $res = PMA_DBI_query(
1175 'SELECT `Db`, `Table_name`, `Table_priv` FROM `mysql`.`tables_priv`' . $user_host_condition,
1176 $GLOBALS['userlink'],
1177 PMA_DBI_QUERY_STORE
1179 while ($row = PMA_DBI_fetch_assoc($res)) {
1181 $res2 = PMA_DBI_QUERY(
1182 'SELECT `Column_name`, `Column_priv`'
1183 .' FROM `mysql`.`columns_priv`'
1184 .' WHERE `User`'
1185 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1186 .' AND `Host`'
1187 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\''
1188 .' AND `Db`'
1189 .' = \'' . PMA_sqlAddSlashes($row['Db']) . "'"
1190 .' AND `Table_name`'
1191 .' = \'' . PMA_sqlAddSlashes($row['Table_name']) . "'"
1192 .';',
1193 null,
1194 PMA_DBI_QUERY_STORE
1197 $tmp_privs1 = PMA_extractPrivInfo($row);
1198 $tmp_privs2 = array(
1199 'Select' => array(),
1200 'Insert' => array(),
1201 'Update' => array(),
1202 'References' => array()
1205 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1206 $tmp_array = explode(',', $row2['Column_priv']);
1207 if (in_array('Select', $tmp_array)) {
1208 $tmp_privs2['Select'][] = $row2['Column_name'];
1210 if (in_array('Insert', $tmp_array)) {
1211 $tmp_privs2['Insert'][] = $row2['Column_name'];
1213 if (in_array('Update', $tmp_array)) {
1214 $tmp_privs2['Update'][] = $row2['Column_name'];
1216 if (in_array('References', $tmp_array)) {
1217 $tmp_privs2['References'][] = $row2['Column_name'];
1219 unset($tmp_array);
1221 if (count($tmp_privs2['Select']) > 0 && ! in_array('SELECT', $tmp_privs1)) {
1222 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1224 if (count($tmp_privs2['Insert']) > 0 && ! in_array('INSERT', $tmp_privs1)) {
1225 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1227 if (count($tmp_privs2['Update']) > 0 && ! in_array('UPDATE', $tmp_privs1)) {
1228 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1230 if (count($tmp_privs2['References']) > 0 && ! in_array('REFERENCES', $tmp_privs1)) {
1231 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1233 unset($tmp_privs2);
1234 $queries[] = 'GRANT ' . join(', ', $tmp_privs1)
1235 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1236 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1237 . (in_array('Grant', explode(',', $row['Table_priv'])) ? ' WITH GRANT OPTION;' : ';');
1243 * Updates privileges
1245 if (! empty($update_privs)) {
1246 $db_and_table = PMA_wildcardEscapeForGrant($dbname, (isset($tablename) ? $tablename : ''));
1248 $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1249 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1250 if (! isset($Grant_priv) || $Grant_priv != 'Y') {
1251 $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
1252 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1253 } else {
1254 $sql_query1 = '';
1257 // Should not do a GRANT USAGE for a table-specific privilege, it
1258 // causes problems later (cannot revoke it)
1259 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1260 $sql_query2 = 'GRANT ' . join(', ', PMA_extractPrivInfo())
1261 . ' ON ' . $db_and_table
1262 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
1265 * @todo similar code appears twice in this script
1267 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1268 || (! isset($dbname)
1269 && (isset($max_questions) || isset($max_connections)
1270 || isset($max_updates) || isset($max_user_connections)))
1272 $sql_query2 .= 'WITH';
1273 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1274 $sql_query2 .= ' GRANT OPTION';
1276 if (isset($max_questions)) {
1277 $max_questions = max(0, (int)$max_questions);
1278 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1280 if (isset($max_connections)) {
1281 $max_connections = max(0, (int)$max_connections);
1282 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1284 if (isset($max_updates)) {
1285 $max_updates = max(0, (int)$max_updates);
1286 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1288 if (isset($max_user_connections)) {
1289 $max_user_connections = max(0, (int)$max_user_connections);
1290 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1293 $sql_query2 .= ';';
1295 if (! PMA_DBI_try_query($sql_query0)) {
1296 // This might fail when the executing user does not have ALL PRIVILEGES himself.
1297 // See https://sourceforge.net/tracker/index.php?func=detail&aid=3285929&group_id=23067&atid=377408
1298 $sql_query0 = '';
1300 if (isset($sql_query1) && ! PMA_DBI_try_query($sql_query1)) {
1301 // this one may fail, too...
1302 $sql_query1 = '';
1304 if (isset($sql_query2)) {
1305 PMA_DBI_query($sql_query2);
1306 } else {
1307 $sql_query2 = '';
1309 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1310 $message = PMA_Message::success(__('You have updated the privileges for %s.'));
1311 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1316 * Revokes Privileges
1318 if (isset($_REQUEST['revokeall'])) {
1319 $db_and_table = PMA_wildcardEscapeForGrant($dbname, isset($tablename) ? $tablename : '');
1321 $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1322 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1323 $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
1324 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1326 PMA_DBI_query($sql_query0);
1327 if (! PMA_DBI_try_query($sql_query1)) {
1328 // this one may fail, too...
1329 $sql_query1 = '';
1331 $sql_query = $sql_query0 . ' ' . $sql_query1;
1332 $message = PMA_Message::success(__('You have revoked the privileges for %s'));
1333 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1334 if (! isset($tablename)) {
1335 unset($dbname);
1336 } else {
1337 unset($tablename);
1343 * Updates the password
1345 if (isset($_REQUEST['change_pw'])) {
1346 // similar logic in user_password.php
1347 $message = '';
1349 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1350 if ($pma_pw != $pma_pw2) {
1351 $message = PMA_Message::error(__('The passwords aren\'t the same!'));
1352 } elseif (empty($pma_pw) || empty($pma_pw2)) {
1353 $message = PMA_Message::error(__('The password is empty!'));
1355 } // end if
1357 // here $nopass could be == 1
1358 if (empty($message)) {
1360 $hashing_function = (! empty($pw_hash) && $pw_hash == 'old' ? 'OLD_' : '')
1361 . 'PASSWORD';
1363 // in $sql_query which will be displayed, hide the password
1364 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1365 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . PMA_sqlAddSlashes($pma_pw) . '\')');
1366 PMA_DBI_try_query($local_query)
1367 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, false, $err_url);
1368 $message = PMA_Message::success(__('The password for %s was changed successfully.'));
1369 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1375 * Deletes users
1376 * (Changes / copies a user, part IV)
1379 if (isset($_REQUEST['delete']) || (isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1380 if (isset($_REQUEST['change_copy'])) {
1381 $selected_usr = array($old_username . '&amp;#27;' . $old_hostname);
1382 } else {
1383 $selected_usr = $_REQUEST['selected_usr'];
1384 $queries = array();
1386 foreach ($selected_usr as $each_user) {
1387 list($this_user, $this_host) = explode('&amp;#27;', $each_user);
1388 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1389 $queries[] = 'DROP USER \'' . PMA_sqlAddSlashes($this_user) . '\'@\'' . PMA_sqlAddSlashes($this_host) . '\';';
1391 if (isset($_REQUEST['drop_users_db'])) {
1392 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1393 $GLOBALS['reload'] = true;
1395 if ($GLOBALS['is_ajax_request'] != true) {
1396 PMA_reloadNavigation();
1400 if (empty($_REQUEST['change_copy'])) {
1401 if (empty($queries)) {
1402 $message = PMA_Message::error(__('No users selected for deleting!'));
1403 } else {
1404 if ($_REQUEST['mode'] == 3) {
1405 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1406 $queries[] = 'FLUSH PRIVILEGES;';
1408 $drop_user_error = '';
1409 foreach ($queries as $sql_query) {
1410 if ($sql_query{0} != '#') {
1411 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1412 $drop_user_error .= PMA_DBI_getError() . "\n";
1416 // tracking sets this, causing the deleted db to be shown in navi
1417 unset($GLOBALS['db']);
1419 $sql_query = join("\n", $queries);
1420 if (! empty($drop_user_error)) {
1421 $message = PMA_Message::rawError($drop_user_error);
1422 } else {
1423 $message = PMA_Message::success(__('The selected users have been deleted successfully.'));
1426 unset($queries);
1432 * Changes / copies a user, part V
1434 if (isset($_REQUEST['change_copy'])) {
1435 $tmp_count = 0;
1436 foreach ($queries as $sql_query) {
1437 if ($sql_query{0} != '#') {
1438 PMA_DBI_query($sql_query);
1440 // when there is a query containing a hidden password, take it
1441 // instead of the real query sent
1442 if (isset($queries_for_display[$tmp_count])) {
1443 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1445 $tmp_count++;
1447 $message = PMA_Message::success();
1448 $sql_query = join("\n", $queries);
1453 * Reloads the privilege tables into memory
1455 if (isset($_REQUEST['flush_privileges'])) {
1456 $sql_query = 'FLUSH PRIVILEGES;';
1457 PMA_DBI_query($sql_query);
1458 $message = PMA_Message::success(__('The privileges were reloaded successfully.'));
1462 * defines some standard links
1464 $link_edit = '<a class="edit_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . str_replace('%', '%%', $GLOBALS['url_query'])
1465 . '&amp;username=%s'
1466 . '&amp;hostname=%s'
1467 . '&amp;dbname=%s'
1468 . '&amp;tablename=%s">'
1469 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1470 . '</a>';
1472 $link_revoke = '<a href="server_privileges.php?' . str_replace('%', '%%', $GLOBALS['url_query'])
1473 . '&amp;username=%s'
1474 . '&amp;hostname=%s'
1475 . '&amp;dbname=%s'
1476 . '&amp;tablename=%s'
1477 . '&amp;revokeall=1">'
1478 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1479 . '</a>';
1481 $link_export = '<a class="export_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . str_replace('%', '%%', $GLOBALS['url_query'])
1482 . '&amp;username=%s'
1483 . '&amp;hostname=%s'
1484 . '&amp;initial=%s'
1485 . '&amp;export=1">'
1486 . PMA_getIcon('b_tblexport.png', __('Export'))
1487 . '</a>';
1489 $link_export_all = '<a class="export_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . str_replace('%', '%%', $GLOBALS['url_query'])
1490 . '&amp;username=%s'
1491 . '&amp;hostname=%s'
1492 . '&amp;initial=%s'
1493 . '&amp;export=1">'
1494 . PMA_getIcon('b_tblexport.png', __('Export all'))
1495 . '</a>';
1498 * If we are in an Ajax request for Create User/Edit User/Revoke User/
1499 * Flush Privileges, show $message and exit.
1501 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'])) {
1503 if (isset($sql_query)) {
1504 $extra_data['sql_query'] = PMA_showMessage(null, $sql_query);
1507 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
1509 * generate html on the fly for the new user that was just created.
1511 $new_user_string = '<tr>'."\n"
1512 .'<td> <input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_" value="' . htmlspecialchars($username) . '&amp;#27;' . htmlspecialchars($hostname) . '" /> </td>' . "\n"
1513 .'<td><label for="checkbox_sel_users_">' . (empty($username) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($username) ) . '</label></td>' . "\n"
1514 .'<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
1515 $new_user_string .= '<td>';
1517 if (! empty($password) || isset($pma_pw)) {
1518 $new_user_string .= __('Yes');
1519 } else {
1520 $new_user_string .= '<span style="color: #FF0000">' . __('No') . '</span>';
1523 $new_user_string .= '</td>'."\n";
1524 $new_user_string .= '<td><tt>' . join(', ', PMA_extractPrivInfo('', true)) . '</tt></td>'; //Fill in privileges here
1525 $new_user_string .= '<td>';
1527 if ((isset($Grant_priv) && $Grant_priv == 'Y')) {
1528 $new_user_string .= __('Yes');
1529 } else {
1530 $new_user_string .= __('No');
1533 $new_user_string .='</td>';
1535 $new_user_string .= '<td>' . sprintf($link_edit, urlencode($username), urlencode($hostname), '', '') . '</td>' . "\n";
1536 $new_user_string .= '<td>' . sprintf($link_export, urlencode($username), urlencode($hostname), (isset($initial) ? $initial : '')) . '</td>' . "\n";
1538 $new_user_string .= '</tr>';
1540 $extra_data['new_user_string'] = $new_user_string;
1543 * Generate the string for this alphabet's initial, to update the user
1544 * pagination
1546 $new_user_initial = strtoupper(substr($username, 0, 1));
1547 $new_user_initial_string = '<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . $new_user_initial
1548 .'">' . $new_user_initial . '</a>';
1549 $extra_data['new_user_initial'] = $new_user_initial;
1550 $extra_data['new_user_initial_string'] = $new_user_initial_string;
1553 if (isset($update_privs)) {
1554 $extra_data['db_specific_privs'] = false;
1555 if (isset($dbname_is_wildcard)) {
1556 $extra_data['db_specific_privs'] = ! $dbname_is_wildcard;
1558 $new_privileges = join(', ', PMA_extractPrivInfo('', true));
1560 $extra_data['new_privileges'] = $new_privileges;
1563 if ($message instanceof PMA_Message) {
1564 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
1569 * Displays the links
1571 if (isset($viewing_mode) && $viewing_mode == 'db') {
1572 $db = $checkprivs;
1573 $url_query .= '&amp;goto=db_operations.php';
1575 // Gets the database structure
1576 $sub_part = '_structure';
1577 include './libraries/db_info.inc.php';
1578 echo "\n";
1579 } else {
1580 include './libraries/server_links.inc.php';
1585 * Displays the page
1588 // export user definition
1589 if (isset($_REQUEST['export'])) {
1590 $response = '<textarea cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1591 if ($username == '%') {
1592 // export privileges for all users
1593 $title = __('Privileges for all users');
1594 foreach ($_SESSION['user_host_pairs'] as $pair) {
1595 $response .= PMA_getGrants($pair['user'], $pair['host']);
1596 $response .= "\n";
1598 } else {
1599 // export privileges for a single user
1600 $title = __('User') . ' `' . htmlspecialchars($username) . '`@`' . htmlspecialchars($hostname) . '`';
1601 $response .= PMA_getGrants($username, $hostname);
1603 $response .= '</textarea>';
1604 unset($username, $hostname, $grants, $one_grant);
1605 if ($GLOBALS['is_ajax_request']) {
1606 PMA_ajaxResponse($response, 1, array('title' => $title));
1607 } else {
1608 echo "<h2>$title</h2>$response";
1612 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs))) {
1613 if (! isset($username)) {
1614 // No username is given --> display the overview
1615 echo '<h2>' . "\n"
1616 . PMA_getIcon('b_usrlist.png')
1617 . __('Users overview') . "\n"
1618 . '</h2>' . "\n";
1620 $sql_query = 'SELECT *,' .
1621 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1622 ' FROM `mysql`.`user`';
1624 $sql_query .= (isset($initial) ? PMA_rangeOfUsers($initial) : '');
1626 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1627 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1629 if (! $res) {
1630 // the query failed! This may have two reasons:
1631 // - the user does not have enough privileges
1632 // - the privilege tables use a structure of an earlier version.
1633 // so let's try a more simple query
1635 $sql_query = 'SELECT * FROM `mysql`.`user`';
1636 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1638 if (! $res) {
1639 PMA_Message::error(__('No Privileges'))->display();
1640 PMA_DBI_free_result($res);
1641 unset($res);
1642 } else {
1643 // This message is hardcoded because I will replace it by
1644 // a automatic repair feature soon.
1645 $raw = 'Your privilege table structure seems to be older than'
1646 . ' this MySQL version!<br />'
1647 . 'Please run the <tt>mysql_upgrade</tt> command'
1648 . '(<tt>mysql_fix_privilege_tables</tt> on older systems)'
1649 . ' that should be included in your MySQL server distribution'
1650 . ' to solve this problem!';
1651 PMA_Message::rawError($raw)->display();
1653 } else {
1655 // we also want users not in table `user` but in other table
1656 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1658 $tables_to_search_for_users = array(
1659 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1662 $db_rights_sqls = array();
1663 foreach ($tables_to_search_for_users as $table_search_in) {
1664 if (in_array($table_search_in, $tables)) {
1665 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ? PMA_rangeOfUsers($initial) : '');
1669 $user_defaults = array(
1670 'User' => '',
1671 'Host' => '%',
1672 'Password' => '?',
1673 'Grant_priv' => 'N',
1674 'privs' => array('USAGE'),
1677 // for all initials, even non A-Z
1678 $array_initials = array();
1679 // for the rights
1680 $db_rights = array();
1682 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1683 .' ORDER BY `User` ASC, `Host` ASC';
1685 $db_rights_result = PMA_DBI_query($db_rights_sql);
1687 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1688 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1689 $db_rights[$db_rights_row['User']][$db_rights_row['Host']]
1690 = $db_rights_row;
1692 PMA_DBI_free_result($db_rights_result);
1693 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1694 ksort($db_rights);
1697 * Displays the initials
1698 * In an Ajax request, we don't need to show this.
1699 * Also not necassary if there is less than 20 privileges
1701 if ($GLOBALS['is_ajax_request'] != true && PMA_DBI_num_rows($res) > 20 ) {
1703 // initialize to false the letters A-Z
1704 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++) {
1705 if (! isset($array_initials[chr($letter_counter + 64)])) {
1706 $array_initials[chr($letter_counter + 64)] = false;
1710 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE);
1711 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1712 $array_initials[$tmp_initial] = true;
1715 // Display the initials, which can be any characters, not
1716 // just letters. For letters A-Z, we add the non-used letters
1717 // as greyed out.
1719 uksort($array_initials, "strnatcasecmp");
1721 echo '<table id="initials_table" class="' . $conditional_class . '" <cellspacing="5"><tr>';
1722 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1723 if ($initial_was_found) {
1724 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1725 } else {
1726 echo '<td>' . $tmp_initial . '</td>';
1729 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;showall=1" class="nowrap">[' . __('Show all') . ']</a></td>' . "\n";
1730 echo '</tr></table>';
1734 * Display the user overview
1735 * (if less than 50 users, display them immediately)
1738 if (isset($initial) || isset($showall) || PMA_DBI_num_rows($res) < 50) {
1740 while ($row = PMA_DBI_fetch_assoc($res)) {
1741 $row['privs'] = PMA_extractPrivInfo($row, true);
1742 $db_rights[$row['User']][$row['Host']] = $row;
1744 @PMA_DBI_free_result($res);
1745 unset($res);
1747 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1748 . PMA_generate_common_hidden_inputs('', '')
1749 . ' <table id="tableuserrights" class="data">' . "\n"
1750 . ' <thead>' . "\n"
1751 . ' <tr><th></th>' . "\n"
1752 . ' <th>' . __('User') . '</th>' . "\n"
1753 . ' <th>' . __('Host') . '</th>' . "\n"
1754 . ' <th>' . __('Password') . '</th>' . "\n"
1755 . ' <th>' . __('Global privileges') . ' '
1756 . PMA_showHint(__('Note: MySQL privilege names are expressed in English')) . '</th>' . "\n"
1757 . ' <th>' . __('Grant') . '</th>' . "\n"
1758 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1759 echo ' </tr>' . "\n";
1760 echo ' </thead>' . "\n";
1761 echo ' <tbody>' . "\n";
1763 $_SESSION['user_host_pairs'] = array();
1764 $pair_count = 0;
1765 $odd_row = true;
1766 $index_checkbox = -1;
1767 foreach ($db_rights as $user) {
1768 $index_checkbox++;
1769 ksort($user);
1770 foreach ($user as $host) {
1771 $index_checkbox++;
1772 echo ' <tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
1773 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1774 . $index_checkbox . '" value="'
1775 . htmlspecialchars($host['User'] . '&amp;#27;' . $host['Host'])
1776 . '"'
1777 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
1778 . ' /></td>' . "\n"
1779 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1780 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1781 echo ' <td>';
1782 switch ($host['Password']) {
1783 case 'Y':
1784 echo __('Yes');
1785 break;
1786 case 'N':
1787 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1788 break;
1789 // this happens if this is a definition not coming from mysql.user
1790 default:
1791 echo '--'; // in future version, replace by "not present"
1792 break;
1793 } // end switch
1794 echo '</td>' . "\n"
1795 . ' <td><tt>' . "\n"
1796 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1797 . ' </tt></td>' . "\n"
1798 . ' <td>' . ($host['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . '</td>' . "\n"
1799 . ' <td align="center">';
1800 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1801 echo '</td>';
1802 echo '<td align="center">';
1803 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ? $initial : ''));
1804 echo '</td>';
1805 echo '</tr>';
1806 $odd_row = ! $odd_row;
1808 $_SESSION['user_host_pairs'][$pair_count]['user'] = $host['User'];
1809 $_SESSION['user_host_pairs'][$pair_count]['host'] = $host['Host'];
1810 $pair_count ++;
1814 unset($user, $host, $odd_row);
1815 echo ' </tbody></table>' . "\n"
1816 .'<div>'
1817 .'<div style="float:left;">'
1818 .'<img class="selectallarrow"'
1819 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1820 .' width="38" height="22"'
1821 .' alt="' . __('With selected:') . '" />' . "\n"
1822 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;checkall=1"'
1823 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1824 . __('Check All') . '</a>' . "\n"
1825 .'/' . "\n"
1826 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1827 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1828 . __('Uncheck All') . '</a>' . "\n"
1829 . '</div>'
1830 . '<div class="clear_both" style="clear:both"></div>'
1831 . '<div style="float:left; padding-left:10px;">';
1832 printf($link_export_all, urlencode('%'), urlencode('%'), (isset($initial) ? $initial : ''));
1833 echo '</div>'
1834 . '</div>'
1835 . '<div class="clear_both" style="clear:both"></div>'
1836 . '</div>';
1838 // add/delete user fieldset
1839 echo ' <fieldset id="fieldset_add_user">' . "\n"
1840 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1841 . PMA_getIcon('b_usradd.png')
1842 . ' ' . __('Add user') . '</a>' . "\n"
1843 . ' </fieldset>' . "\n"
1844 . ' <fieldset id="fieldset_delete_user">'
1845 . ' <legend>' . "\n"
1846 . PMA_getIcon('b_usrdrop.png')
1847 . ' ' . __('Remove selected users') . '' . "\n"
1848 . ' </legend>' . "\n"
1849 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1850 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1851 . ' <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"
1852 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1853 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1854 . ' </label>' . "\n"
1855 . ' </fieldset>' . "\n"
1856 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1857 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" class="' . $conditional_class . '"/>' . "\n"
1858 . ' </fieldset>' . "\n"
1859 . '</form>' . "\n";
1860 } else {
1862 unset ($row);
1863 echo ' <fieldset id="fieldset_add_user">' . "\n"
1864 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1865 . PMA_getIcon('b_usradd.png')
1866 . ' ' . __('Add user') . '</a>' . "\n"
1867 . ' </fieldset>' . "\n";
1868 } // end if (display overview)
1870 if ($GLOBALS['is_ajax_request']) {
1871 exit;
1874 $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);
1875 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;flush_privileges=1" id="reload_privileges_anchor" class="' . $conditional_class . '">', false);
1876 $flushnote->addParam('</a>', false);
1877 $flushnote->display();
1881 } else {
1883 // A user was selected -> display the user's properties
1885 // In an Ajax request, prevent cached values from showing
1886 if ($GLOBALS['is_ajax_request'] == true) {
1887 header('Cache-Control: no-cache');
1890 echo '<h2>' . "\n"
1891 . PMA_getIcon('b_usredit.png')
1892 . __('Edit Privileges') . ': '
1893 . __('User');
1895 if (isset($dbname)) {
1896 echo ' <i><a href="server_privileges.php?'
1897 . $GLOBALS['url_query'] . '&amp;username=' . htmlspecialchars(urlencode($username))
1898 . '&amp;hostname=' . htmlspecialchars(urlencode($hostname)) . '&amp;dbname=&amp;tablename=">\''
1899 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1900 . '\'</a></i>' . "\n";
1901 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
1903 echo ' - ' . ($dbname_is_wildcard ? __('Databases') : __('Database') );
1904 if (isset($tablename)) {
1905 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
1906 . '&amp;username=' . htmlspecialchars(urlencode($username)) . '&amp;hostname=' . htmlspecialchars(urlencode($hostname))
1907 . '&amp;dbname=' . htmlspecialchars($url_dbname) . '&amp;tablename=">' . htmlspecialchars($dbname) . '</a></i>';
1908 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
1909 } else {
1910 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
1913 } else {
1914 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1915 . '\'</i>' . "\n";
1918 echo '</h2>' . "\n";
1921 $sql = "SELECT '1' FROM `mysql`.`user`"
1922 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
1923 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
1924 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
1925 unset($sql);
1926 if ($user_does_not_exists) {
1927 PMA_Message::error(__('The selected user was not found in the privilege table.'))->display();
1928 PMA_displayLoginInformationFields();
1929 //require './libraries/footer.inc.php';
1932 echo '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n";
1933 $_params = array(
1934 'username' => $username,
1935 'hostname' => $hostname,
1937 if (isset($dbname)) {
1938 $_params['dbname'] = $dbname;
1939 if (isset($tablename)) {
1940 $_params['tablename'] = $tablename;
1943 echo PMA_generate_common_hidden_inputs($_params);
1945 PMA_displayPrivTable(
1946 PMA_ifSetOr($dbname, '*', 'length'),
1947 PMA_ifSetOr($tablename, '*', 'length')
1950 echo '</form>' . "\n";
1952 if (! isset($tablename) && empty($dbname_is_wildcard)) {
1954 // no table name was given, display all table specific rights
1955 // but only if $dbname contains no wildcards
1957 // table header
1958 echo '<form action="server_privileges.php" id="db_or_table_specific_priv" method="post">' . "\n"
1959 . PMA_generate_common_hidden_inputs('', '')
1960 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
1961 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1962 . '<fieldset>' . "\n"
1963 . '<legend>' . (! isset($dbname) ? __('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
1964 . '<table class="data">' . "\n"
1965 . '<thead>' . "\n"
1966 . '<tr><th>' . (! isset($dbname) ? __('Database') : __('Table')) . '</th>' . "\n"
1967 . ' <th>' . __('Privileges') . '</th>' . "\n"
1968 . ' <th>' . __('Grant') . '</th>' . "\n"
1969 . ' <th>' . (! isset($dbname) ? __('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
1970 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
1971 . '</tr>' . "\n"
1972 . '</thead>' . "\n"
1973 . '<tbody>' . "\n";
1975 $user_host_condition = ' WHERE `User`'
1976 . ' = \'' . PMA_sqlAddSlashes($username) . "'"
1977 . ' AND `Host`'
1978 . ' = \'' . PMA_sqlAddSlashes($hostname) . "'";
1980 // table body
1981 // get data
1983 // we also want privielgs for this user not in table `db` but in other table
1984 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1985 if (! isset($dbname)) {
1987 // no db name given, so we want all privs for the given user
1989 $tables_to_search_for_users = array(
1990 'tables_priv', '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 `Db`
1998 FROM `mysql`.' . PMA_backquote($table_search_in)
1999 . $user_host_condition;
2003 $user_defaults = array(
2004 'Db' => '',
2005 'Grant_priv' => 'N',
2006 'privs' => array('USAGE'),
2007 'Table_privs' => true,
2010 // for the rights
2011 $db_rights = array();
2013 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
2014 .' ORDER BY `Db` 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 // only Db names in the table `mysql`.`db` uses wildcards
2021 // as we are in the db specific rights display we want
2022 // all db names escaped, also from other sources
2023 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
2024 $db_rights_row['Db']
2026 $db_rights[$db_rights_row['Db']] = $db_rights_row;
2029 PMA_DBI_free_result($db_rights_result);
2030 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
2032 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
2033 $res = PMA_DBI_query($sql_query);
2034 $sql_query = '';
2036 while ($row = PMA_DBI_fetch_assoc($res)) {
2037 if (isset($db_rights[$row['Db']])) {
2038 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
2039 } else {
2040 $db_rights[$row['Db']] = $row;
2042 // there are db specific rights for this user
2043 // so we can drop this db rights
2044 $db_rights[$row['Db']]['can_delete'] = true;
2046 PMA_DBI_free_result($res);
2047 unset($row, $res);
2049 } else {
2051 // db name was given,
2052 // so we want all user specific rights for this db
2054 $user_host_condition .=
2055 ' AND `Db`'
2056 .' LIKE \'' . PMA_sqlAddSlashes($dbname, true) . "'";
2058 $tables_to_search_for_users = array(
2059 'columns_priv',
2062 $db_rights_sqls = array();
2063 foreach ($tables_to_search_for_users as $table_search_in) {
2064 if (in_array($table_search_in, $tables)) {
2065 $db_rights_sqls[] = '
2066 SELECT DISTINCT `Table_name`
2067 FROM `mysql`.' . PMA_backquote($table_search_in)
2068 . $user_host_condition;
2072 $user_defaults = array(
2073 'Table_name' => '',
2074 'Grant_priv' => 'N',
2075 'privs' => array('USAGE'),
2076 'Column_priv' => true,
2079 // for the rights
2080 $db_rights = array();
2082 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
2083 .' ORDER BY `Table_name` ASC';
2085 $db_rights_result = PMA_DBI_query($db_rights_sql);
2087 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
2088 $db_rights_row = array_merge($user_defaults, $db_rights_row);
2089 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
2091 PMA_DBI_free_result($db_rights_result);
2092 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
2094 $sql_query = 'SELECT `Table_name`,'
2095 .' `Table_priv`,'
2096 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
2097 .' AS \'Column_priv\''
2098 .' FROM `mysql`.`tables_priv`'
2099 . $user_host_condition
2100 .' ORDER BY `Table_name` ASC;';
2101 $res = PMA_DBI_query($sql_query);
2102 $sql_query = '';
2104 while ($row = PMA_DBI_fetch_assoc($res)) {
2105 if (isset($db_rights[$row['Table_name']])) {
2106 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
2107 } else {
2108 $db_rights[$row['Table_name']] = $row;
2111 PMA_DBI_free_result($res);
2112 unset($row, $res);
2114 ksort($db_rights);
2116 // display rows
2117 if (count($db_rights) < 1) {
2118 echo '<tr class="odd">' . "\n"
2119 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
2120 . '</tr>' . "\n";
2121 } else {
2122 $odd_row = true;
2123 $found_rows = array();
2124 //while ($row = PMA_DBI_fetch_assoc($res)) {
2125 foreach ($db_rights as $row) {
2126 $found_rows[] = (! isset($dbname)) ? $row['Db'] : $row['Table_name'];
2128 echo '<tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2129 . ' <td>' . htmlspecialchars((! isset($dbname)) ? $row['Db'] : $row['Table_name']) . '</td>' . "\n"
2130 . ' <td><tt>' . "\n"
2131 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, true)) . "\n"
2132 . ' </tt></td>' . "\n"
2133 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') || (isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ? __('Yes') : __('No')) . '</td>' . "\n"
2134 . ' <td>';
2135 if (! empty($row['Table_privs']) || ! empty ($row['Column_priv'])) {
2136 echo __('Yes');
2137 } else {
2138 echo __('No');
2140 echo '</td>' . "\n"
2141 . ' <td>';
2142 printf(
2143 $link_edit,
2144 htmlspecialchars(urlencode($username)),
2145 urlencode(htmlspecialchars($hostname)),
2146 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
2147 urlencode((! isset($dbname)) ? '' : $row['Table_name'])
2149 echo '</td>' . "\n"
2150 . ' <td>';
2151 if (! empty($row['can_delete']) || isset($row['Table_name']) && strlen($row['Table_name'])) {
2152 printf(
2153 $link_revoke,
2154 htmlspecialchars(urlencode($username)),
2155 urlencode(htmlspecialchars($hostname)),
2156 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
2157 urlencode((! isset($dbname)) ? '' : $row['Table_name'])
2160 echo '</td>' . "\n"
2161 . '</tr>' . "\n";
2162 $odd_row = ! $odd_row;
2163 } // end while
2165 unset($row);
2166 echo '</tbody>' . "\n"
2167 . '</table>' . "\n";
2169 if (! isset($dbname)) {
2171 // no database name was given, display select db
2173 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
2175 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
2176 if (! empty($pred_db_array)) {
2177 echo ' <select name="pred_dbname" class="autosubmit">' . "\n"
2178 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2179 foreach ($pred_db_array as $current_db) {
2180 $current_db = PMA_escape_mysql_wildcards($current_db);
2181 // cannot use array_diff() once, outside of the loop,
2182 // because the list of databases has special characters
2183 // already escaped in $found_rows,
2184 // contrary to the output of SHOW DATABASES
2185 if (empty($found_rows) || ! in_array($current_db, $found_rows)) {
2186 echo ' <option value="' . htmlspecialchars($current_db) . '">'
2187 . htmlspecialchars($current_db) . '</option>' . "\n";
2190 echo ' </select>' . "\n";
2192 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
2193 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
2194 } else {
2195 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
2196 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
2197 if ($res = @PMA_DBI_try_query('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE)) {
2198 $pred_tbl_array = array();
2199 while ($row = PMA_DBI_fetch_row($res)) {
2200 if (! isset($found_rows) || ! in_array($row[0], $found_rows)) {
2201 $pred_tbl_array[] = $row[0];
2204 PMA_DBI_free_result($res);
2205 unset($res, $row);
2206 if (! empty($pred_tbl_array)) {
2207 echo ' <select name="pred_tablename" class="autosubmit">' . "\n"
2208 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2209 foreach ($pred_tbl_array as $current_table) {
2210 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
2212 echo ' </select>' . "\n";
2214 } else {
2215 unset($res);
2217 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
2219 echo '</fieldset>' . "\n";
2220 echo '<fieldset class="tblFooters">' . "\n"
2221 . ' <input type="submit" value="' . __('Go') . '" />'
2222 . '</fieldset>' . "\n"
2223 . '</form>' . "\n";
2227 // Provide a line with links to the relevant database and table
2228 if (isset($dbname) && empty($dbname_is_wildcard)) {
2229 echo '[ ' . __('Database')
2230 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
2231 . $GLOBALS['url_query'] . '&amp;db=' . $url_dbname . '&amp;reload=1">'
2232 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
2234 if (isset($tablename)) {
2235 echo ' [ ' . __('Table') . ' <a href="'
2236 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
2237 . '&amp;db=' . $url_dbname . '&amp;table=' . htmlspecialchars(urlencode($tablename))
2238 . '&amp;reload=1">' . htmlspecialchars($tablename) . ': '
2239 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
2240 . "</a> ]\n";
2242 unset($url_dbname);
2245 if (! isset($dbname) && ! $user_does_not_exists) {
2246 include_once './libraries/display_change_password.lib.php';
2248 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
2249 . PMA_generate_common_hidden_inputs('', '')
2250 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
2251 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
2252 . '<fieldset id="fieldset_change_copy_user">' . "\n"
2253 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
2254 PMA_displayLoginInformationFields('change');
2255 echo ' <fieldset>' . "\n"
2256 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2257 $choices = array(
2258 '4' => __('... keep the old one.'),
2259 '1' => __('... delete the old one from the user tables.'),
2260 '2' => __('... revoke all active privileges from the old one and delete it afterwards.'),
2261 '3' => __('... delete the old one from the user tables and reload the privileges afterwards.'));
2262 PMA_display_html_radio('mode', $choices, '4', true);
2263 unset($choices);
2265 echo ' </fieldset>' . "\n"
2266 . '</fieldset>' . "\n"
2267 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2268 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2269 . '</fieldset>' . "\n"
2270 . '</form>' . "\n";
2273 } elseif (isset($_REQUEST['adduser'])) {
2275 // Add user
2276 $GLOBALS['url_query'] .= '&amp;adduser=1';
2277 echo '<h2>' . "\n"
2278 . PMA_getIcon('b_usradd.png') . __('Add user') . "\n"
2279 . '</h2>' . "\n"
2280 . '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n"
2281 . PMA_generate_common_hidden_inputs('', '');
2282 PMA_displayLoginInformationFields('new');
2283 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2284 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2286 PMA_display_html_checkbox('createdb-1', __('Create database with same name and grant all privileges'), false, false);
2287 echo '<br />' . "\n";
2288 PMA_display_html_checkbox('createdb-2', __('Grant all privileges on wildcard name (username\\_%)'), false, false);
2289 echo '<br />' . "\n";
2291 if (! empty($dbname) ) {
2292 PMA_display_html_checkbox('createdb-3', sprintf(__('Grant all privileges on database &quot;%s&quot;'), htmlspecialchars($dbname)), true, false);
2293 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2294 echo '<br />' . "\n";
2297 echo '</fieldset>' . "\n";
2298 PMA_displayPrivTable('*', '*', false);
2299 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2300 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2301 . ' </fieldset>' . "\n"
2302 . '</form>' . "\n";
2303 } else {
2304 // check the privileges for a particular database.
2305 $user_form = '<form id="usersForm" action="server_privileges.php"><fieldset>' . "\n"
2306 . '<legend>' . "\n"
2307 . PMA_getIcon('b_usrcheck.png')
2308 . ' ' . sprintf(__('Users having access to &quot;%s&quot;'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2309 . '</legend>' . "\n"
2310 . '<table id="dbspecificuserrights" class="data">' . "\n"
2311 . '<thead>' . "\n"
2312 . ' <tr><th>' . __('User') . '</th>' . "\n"
2313 . ' <th>' . __('Host') . '</th>' . "\n"
2314 . ' <th>' . __('Type') . '</th>' . "\n"
2315 . ' <th>' . __('Privileges') . '</th>' . "\n"
2316 . ' <th>' . __('Grant') . '</th>' . "\n"
2317 . ' <th>' . __('Action') . '</th>' . "\n"
2318 . ' </tr>' . "\n"
2319 . '</thead>' . "\n"
2320 . '<tbody>' . "\n";
2321 $odd_row = true;
2322 unset($row, $row1, $row2);
2324 // now, we build the table...
2325 $list_of_privileges
2326 = '`User`, '
2327 . '`Host`, '
2328 . '`Select_priv`, '
2329 . '`Insert_priv`, '
2330 . '`Update_priv`, '
2331 . '`Delete_priv`, '
2332 . '`Create_priv`, '
2333 . '`Drop_priv`, '
2334 . '`Grant_priv`, '
2335 . '`Index_priv`, '
2336 . '`Alter_priv`, '
2337 . '`References_priv`, '
2338 . '`Create_tmp_table_priv`, '
2339 . '`Lock_tables_priv`, '
2340 . '`Create_view_priv`, '
2341 . '`Show_view_priv`, '
2342 . '`Create_routine_priv`, '
2343 . '`Alter_routine_priv`, '
2344 . '`Execute_priv`';
2346 $list_of_compared_privileges
2347 = '`Select_priv` = \'N\''
2348 . ' AND `Insert_priv` = \'N\''
2349 . ' AND `Update_priv` = \'N\''
2350 . ' AND `Delete_priv` = \'N\''
2351 . ' AND `Create_priv` = \'N\''
2352 . ' AND `Drop_priv` = \'N\''
2353 . ' AND `Grant_priv` = \'N\''
2354 . ' AND `References_priv` = \'N\''
2355 . ' AND `Create_tmp_table_priv` = \'N\''
2356 . ' AND `Lock_tables_priv` = \'N\''
2357 . ' AND `Create_view_priv` = \'N\''
2358 . ' AND `Show_view_priv` = \'N\''
2359 . ' AND `Create_routine_priv` = \'N\''
2360 . ' AND `Alter_routine_priv` = \'N\''
2361 . ' AND `Execute_priv` = \'N\'';
2363 if (PMA_MYSQL_INT_VERSION >= 50106) {
2364 $list_of_privileges .=
2365 ', `Event_priv`, '
2366 . '`Trigger_priv`';
2367 $list_of_compared_privileges .=
2368 ' AND `Event_priv` = \'N\''
2369 . ' AND `Trigger_priv` = \'N\'';
2372 $sql_query = '(SELECT ' . $list_of_privileges . ', `Db`'
2373 .' FROM `mysql`.`db`'
2374 .' WHERE \'' . PMA_sqlAddSlashes($checkprivs) . "'"
2375 .' LIKE `Db`'
2376 .' AND NOT (' . $list_of_compared_privileges. ')) '
2377 .'UNION '
2378 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2379 .' FROM `mysql`.`user` '
2380 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2381 .' ORDER BY `User` ASC,'
2382 .' `Host` ASC,'
2383 .' `Db` ASC;';
2384 $res = PMA_DBI_query($sql_query);
2385 $row = PMA_DBI_fetch_assoc($res);
2386 if ($row) {
2387 $found = true;
2390 if ($found) {
2391 while (true) {
2392 // prepare the current user
2393 $current_privileges = array();
2394 $current_user = $row['User'];
2395 $current_host = $row['Host'];
2396 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2397 $current_privileges[] = $row;
2398 $row = PMA_DBI_fetch_assoc($res);
2400 $user_form .= ' <tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2401 . ' <td';
2402 if (count($current_privileges) > 1) {
2403 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2405 $user_form .= '>' . (empty($current_user) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2406 . ' </td>' . "\n"
2407 . ' <td';
2408 if (count($current_privileges) > 1) {
2409 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2411 $user_form .= '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2412 for ($i = 0; $i < count($current_privileges); $i++) {
2413 $current = $current_privileges[$i];
2414 $user_form .= ' <td>' . "\n"
2415 . ' ';
2416 if (! isset($current['Db']) || $current['Db'] == '*') {
2417 $user_form .= __('global');
2418 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2419 $user_form .= __('database-specific');
2420 } else {
2421 $user_form .= __('wildcard'). ': <tt>' . htmlspecialchars($current['Db']) . '</tt>';
2423 $user_form .= "\n"
2424 . ' </td>' . "\n"
2425 . ' <td>' . "\n"
2426 . ' <tt>' . "\n"
2427 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, true)) . "\n"
2428 . ' </tt>' . "\n"
2429 . ' </td>' . "\n"
2430 . ' <td>' . "\n"
2431 . ' ' . ($current['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . "\n"
2432 . ' </td>' . "\n"
2433 . ' <td>' . "\n";
2434 $user_form .= sprintf(
2435 $link_edit,
2436 urlencode($current_user),
2437 urlencode($current_host),
2438 urlencode(! isset($current['Db']) || $current['Db'] == '*' ? '' : $current['Db']),
2441 $user_form .= '</td>' . "\n"
2442 . ' </tr>' . "\n";
2443 if (($i + 1) < count($current_privileges)) {
2444 $user_form .= '<tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">' . "\n";
2447 if (empty($row) && empty($row1) && empty($row2)) {
2448 break;
2450 $odd_row = ! $odd_row;
2452 } else {
2453 $user_form .= ' <tr class="odd">' . "\n"
2454 . ' <td colspan="6">' . "\n"
2455 . ' ' . __('No user found.') . "\n"
2456 . ' </td>' . "\n"
2457 . ' </tr>' . "\n";
2459 $user_form .= '</tbody>' . "\n"
2460 . '</table></fieldset></form>' . "\n";
2462 if ($GLOBALS['is_ajax_request'] == true) {
2463 $extra_data['user_form'] = $user_form;
2464 $message = PMA_Message::success(__('User has been added.'));
2465 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
2466 } else {
2467 // Offer to create a new user for the current database
2468 $user_form .= '<fieldset id="fieldset_add_user">' . "\n"
2469 . '<legend>' . __('New') . '</legend>' . "\n"
2470 . ' <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"
2471 . PMA_getIcon('b_usradd.png')
2472 . ' ' . __('Add user') . '</a>' . "\n"
2473 . '</fieldset>' . "\n";
2474 echo $user_form ;
2477 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2481 * Displays the footer
2483 echo "\n\n";
2484 require './libraries/footer.inc.php';