Merge branch 'QA_3_4'
[phpmyadmin/last10db.git] / server_privileges.php
blobdaf8a990ba0edb42964e9850b55061f3e48696fc
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
5 * @package phpMyAdmin
6 */
8 /**
11 require_once './libraries/common.inc.php';
13 /**
14 * Does the common work
16 $GLOBALS['js_include'][] = 'server_privileges.js';
17 $GLOBALS['js_include'][] = 'functions.js';
18 $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js';
20 require './libraries/server_common.inc.php';
22 if ($GLOBALS['cfg']['AjaxEnable']) {
23 $conditional_class = 'ajax';
24 } else {
25 $conditional_class = '';
28 /**
29 * Messages are built using the message name
31 $strPrivDescAllPrivileges = __('Includes all privileges except GRANT.');
32 $strPrivDescAlter = __('Allows altering the structure of existing tables.');
33 $strPrivDescAlterRoutine = __('Allows altering and dropping stored routines.');
34 $strPrivDescCreateDb = __('Allows creating new databases and tables.');
35 $strPrivDescCreateRoutine = __('Allows creating stored routines.');
36 $strPrivDescCreateTbl = __('Allows creating new tables.');
37 $strPrivDescCreateTmpTable = __('Allows creating temporary tables.');
38 $strPrivDescCreateUser = __('Allows creating, dropping and renaming user accounts.');
39 $strPrivDescCreateView = __('Allows creating new views.');
40 $strPrivDescDelete = __('Allows deleting data.');
41 $strPrivDescDropDb = __('Allows dropping databases and tables.');
42 $strPrivDescDropTbl = __('Allows dropping tables.');
43 $strPrivDescEvent = __('Allows to set up events for the event scheduler');
44 $strPrivDescExecute = __('Allows executing stored routines.');
45 $strPrivDescFile = __('Allows importing data from and exporting data into files.');
46 $strPrivDescGrant = __('Allows adding users and privileges without reloading the privilege tables.');
47 $strPrivDescIndex = __('Allows creating and dropping indexes.');
48 $strPrivDescInsert = __('Allows inserting and replacing data.');
49 $strPrivDescLockTables = __('Allows locking tables for the current thread.');
50 $strPrivDescMaxConnections = __('Limits the number of new connections the user may open per hour.');
51 $strPrivDescMaxQuestions = __('Limits the number of queries the user may send to the server per hour.');
52 $strPrivDescMaxUpdates = __('Limits the number of commands that change any table or database the user may execute per hour.');
53 $strPrivDescMaxUserConnections = __('Limits the number of simultaneous connections the user may have.');
54 $strPrivDescProcess = __('Allows viewing processes of all users');
55 $strPrivDescReferences = __('Has no effect in this MySQL version.');
56 $strPrivDescReload = __('Allows reloading server settings and flushing the server\'s caches.');
57 $strPrivDescReplClient = __('Allows the user to ask where the slaves / masters are.');
58 $strPrivDescReplSlave = __('Needed for the replication slaves.');
59 $strPrivDescSelect = __('Allows reading data.');
60 $strPrivDescShowDb = __('Gives access to the complete list of databases.');
61 $strPrivDescShowView = __('Allows performing SHOW CREATE VIEW queries.');
62 $strPrivDescShutdown = __('Allows shutting down the server.');
63 $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.');
64 $strPrivDescTrigger = __('Allows creating and dropping triggers');
65 $strPrivDescUpdate = __('Allows changing data.');
66 $strPrivDescUsage = __('No privileges.');
68 /**
69 * Checks if a dropdown box has been used for selecting a database / table
71 if (PMA_isValid($_REQUEST['pred_tablename'])) {
72 $tablename = $_REQUEST['pred_tablename'];
73 unset($pred_tablename);
74 } elseif (PMA_isValid($_REQUEST['tablename'])) {
75 $tablename = $_REQUEST['tablename'];
76 } else {
77 unset($tablename);
80 if (PMA_isValid($_REQUEST['pred_dbname'])) {
81 $dbname = $_REQUEST['pred_dbname'];
82 unset($pred_dbname);
83 } elseif (PMA_isValid($_REQUEST['dbname'])) {
84 $dbname = $_REQUEST['dbname'];
85 } else {
86 unset($dbname);
87 unset($tablename);
90 if (isset($dbname)) {
91 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
92 if (isset($tablename)) {
93 $db_and_table .= PMA_backquote($tablename);
94 } else {
95 $db_and_table .= '*';
97 } else {
98 $db_and_table = '*.*';
101 // check if given $dbname is a wildcard or not
102 if (isset($dbname)) {
103 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
104 if (preg_match('/(?<!\\\\)(?:_|%)/i', $dbname)) {
105 $dbname_is_wildcard = true;
106 } else {
107 $dbname_is_wildcard = false;
112 * Checks if the user is allowed to do what he tries to...
114 if (!$is_superuser) {
115 require './libraries/server_links.inc.php';
116 echo '<h2>' . "\n"
117 . PMA_getIcon('b_usrlist.png')
118 . __('Privileges') . "\n"
119 . '</h2>' . "\n";
120 PMA_Message::error(__('No Privileges'))->display();
121 require './libraries/footer.inc.php';
124 $random_n = mt_rand(0,1000000); // a random number that will be appended to the id of the user forms
127 * Escapes wildcard in a database+table specification
128 * before using it in a GRANT statement.
130 * Escaping a wildcard character in a GRANT is only accepted at the global
131 * or database level, not at table level; this is why I remove
132 * the escaping character. Internally, in mysql.tables_priv.Db there are
133 * no escaping (for example test_db) but in mysql.db you'll see test\_db
134 * for a db-specific privilege.
136 * @param string $db_and_table
137 * @param string $dbname
138 * @param string $tablename
139 * @return string the escaped (if necessary) $db_and_table
141 function PMA_WildcardEscapeForGrant($db_and_table, $dbname, $tablename) {
143 if (! strlen($dbname)) {
144 $db_and_table = '*.*';
145 } else {
146 if (strlen($tablename)) {
147 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
148 $db_and_table .= PMA_backquote($tablename);
149 } else {
150 $db_and_table = PMA_backquote($dbname) . '.';
151 $db_and_table .= '*';
154 return $db_and_table;
158 * Generates a condition on the user name
160 * @param string the user's initial
161 * @return string the generated condition
163 function PMA_RangeOfUsers($initial = '')
165 // strtolower() is used because the User field
166 // might be BINARY, so LIKE would be case sensitive
167 if (!empty($initial)) {
168 $ret = " WHERE `User` LIKE '" . PMA_sqlAddslashes($initial) . "%'"
169 . " OR `User` LIKE '" . PMA_sqlAddslashes(strtolower($initial)) . "%'";
170 } else {
171 $ret = '';
173 return $ret;
174 } // end function
177 * Extracts the privilege information of a priv table row
179 * @param array $row the row
180 * @param boolean $enableHTML add <dfn> tag with tooltips
182 * @global resource $user_link the database connection
184 * @return array
186 function PMA_extractPrivInfo($row = '', $enableHTML = FALSE)
188 $grants = array(
189 array('Select_priv', 'SELECT', __('Allows reading data.')),
190 array('Insert_priv', 'INSERT', __('Allows inserting and replacing data.')),
191 array('Update_priv', 'UPDATE', __('Allows changing data.')),
192 array('Delete_priv', 'DELETE', __('Allows deleting data.')),
193 array('Create_priv', 'CREATE', __('Allows creating new databases and tables.')),
194 array('Drop_priv', 'DROP', __('Allows dropping databases and tables.')),
195 array('Reload_priv', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.')),
196 array('Shutdown_priv', 'SHUTDOWN', __('Allows shutting down the server.')),
197 array('Process_priv', 'PROCESS', __('Allows viewing processes of all users')),
198 array('File_priv', 'FILE', __('Allows importing data from and exporting data into files.')),
199 array('References_priv', 'REFERENCES', __('Has no effect in this MySQL version.')),
200 array('Index_priv', 'INDEX', __('Allows creating and dropping indexes.')),
201 array('Alter_priv', 'ALTER', __('Allows altering the structure of existing tables.')),
202 array('Show_db_priv', 'SHOW DATABASES', __('Gives access to the complete list of databases.')),
203 array('Super_priv', 'SUPER', __('Allows connecting, even if maximum number of connections is reached; required for most administrative operations like setting global variables or killing threads of other users.')),
204 array('Create_tmp_table_priv', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
205 array('Lock_tables_priv', 'LOCK TABLES', __('Allows locking tables for the current thread.')),
206 array('Repl_slave_priv', 'REPLICATION SLAVE', __('Needed for the replication slaves.')),
207 array('Repl_client_priv', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.')),
208 array('Create_view_priv', 'CREATE VIEW', __('Allows creating new views.')),
209 array('Event_priv', 'EVENT', __('Allows to set up events for the event scheduler')),
210 array('Trigger_priv', 'TRIGGER', __('Allows creating and dropping triggers')),
211 // for table privs:
212 array('Create View_priv', 'CREATE VIEW', __('Allows creating new views.')),
213 array('Show_view_priv', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
214 // for table privs:
215 array('Show view_priv', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
216 array('Create_routine_priv', 'CREATE ROUTINE', __('Allows creating stored routines.')),
217 array('Alter_routine_priv', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
218 array('Create_user_priv', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.')),
219 array('Execute_priv', 'EXECUTE', __('Allows executing stored routines.')),
222 if (!empty($row) && isset($row['Table_priv'])) {
223 $row1 = PMA_DBI_fetch_single_row(
224 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
225 'ASSOC', $GLOBALS['userlink']);
226 $av_grants = explode('\',\'', substr($row1['Type'], 5, strlen($row1['Type']) - 7));
227 unset($row1);
228 $users_grants = explode(',', $row['Table_priv']);
229 foreach ($av_grants as $current_grant) {
230 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
232 unset($current_grant);
233 unset($av_grants);
234 unset($users_grants);
236 $privs = array();
237 $allPrivileges = TRUE;
238 foreach ($grants as $current_grant) {
239 if ((!empty($row) && isset($row[$current_grant[0]]))
240 || (empty($row) && isset($GLOBALS[$current_grant[0]]))) {
241 if ((!empty($row) && $row[$current_grant[0]] == 'Y')
242 || (empty($row)
243 && ($GLOBALS[$current_grant[0]] == 'Y'
244 || (is_array($GLOBALS[$current_grant[0]])
245 && count($GLOBALS[$current_grant[0]]) == $GLOBALS['column_count']
246 && empty($GLOBALS[$current_grant[0] . '_none'])))))
248 if ($enableHTML) {
249 $privs[] = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
250 } else {
251 $privs[] = $current_grant[1];
253 } elseif (!empty($GLOBALS[$current_grant[0]])
254 && is_array($GLOBALS[$current_grant[0]])
255 && empty($GLOBALS[$current_grant[0] . '_none'])) {
256 if ($enableHTML) {
257 $priv_string = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
258 } else {
259 $priv_string = $current_grant[1];
261 $privs[] = $priv_string . ' (`' . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
262 } else {
263 $allPrivileges = FALSE;
267 if (empty($privs)) {
268 if ($enableHTML) {
269 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
270 } else {
271 $privs[] = 'USAGE';
273 } elseif ($allPrivileges && (! isset($GLOBALS['grant_count']) || count($privs) == $GLOBALS['grant_count'])) {
274 if ($enableHTML) {
275 $privs = array('<dfn title="' . __('Includes all privileges except GRANT.') . '">ALL PRIVILEGES</dfn>');
276 } else {
277 $privs = array('ALL PRIVILEGES');
280 return $privs;
281 } // end of the 'PMA_extractPrivInfo()' function
284 * Displays on which column(s) a table-specific privilege is granted
286 function PMA_display_column_privs($columns, $row, $name_for_select,
287 $priv_for_header, $name, $name_for_dfn, $name_for_current)
289 echo ' <div class="item" id="div_item_' . $name . '">' . "\n"
290 . ' <label for="select_' . $name . '_priv">' . "\n"
291 . ' <tt><dfn title="' . $name_for_dfn . '">'
292 . $priv_for_header . '</dfn></tt>' . "\n"
293 . ' </label><br />' . "\n"
294 . ' <select id="select_' . $name . '_priv" name="'
295 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
297 foreach ($columns as $current_column => $current_column_privileges) {
298 echo ' <option value="' . htmlspecialchars($current_column) . '"';
299 if ($row[$name_for_select] == 'Y' || $current_column_privileges[$name_for_current]) {
300 echo ' selected="selected"';
302 echo '>' . htmlspecialchars($current_column) . '</option>' . "\n";
305 echo ' </select>' . "\n"
306 . ' <i>' . __('Or') . '</i>' . "\n"
307 . ' <label for="checkbox_' . $name_for_select
308 . '_none"><input type="checkbox"'
309 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
310 . ' name="' . $name_for_select . '_none" id="checkbox_'
311 . $name_for_select . '_none" title="' . _pgettext('None privileges', 'None') . '" />'
312 . _pgettext('None privileges', 'None') . '</label>' . "\n"
313 . ' </div>' . "\n";
314 } // end function
318 * Displays the privileges form table
320 * @param string $db the database
321 * @param string $table the table
322 * @param boolean $submit wheather to display the submit button or not
323 * @global array $cfg the phpMyAdmin configuration
324 * @global ressource $user_link the database connection
326 * @return void
328 function PMA_displayPrivTable($db = '*', $table = '*', $submit = TRUE)
330 global $random_n;
332 if ($db == '*') {
333 $table = '*';
336 if (isset($GLOBALS['username'])) {
337 $username = $GLOBALS['username'];
338 $hostname = $GLOBALS['hostname'];
339 if ($db == '*') {
340 $sql_query =
341 "SELECT * FROM `mysql`.`user`"
342 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
343 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
344 } elseif ($table == '*') {
345 $sql_query =
346 "SELECT * FROM `mysql`.`db`"
347 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
348 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "'"
349 ." AND '" . PMA_unescape_mysql_wildcards($db) . "'"
350 ." LIKE `Db`;";
351 } else {
352 $sql_query =
353 "SELECT `Table_priv`"
354 ." FROM `mysql`.`tables_priv`"
355 ." WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
356 ." AND `Host` = '" . PMA_sqlAddslashes($hostname) . "'"
357 ." AND `Db` = '" . PMA_unescape_mysql_wildcards($db) . "'"
358 ." AND `Table_name` = '" . PMA_sqlAddslashes($table) . "';";
360 $row = PMA_DBI_fetch_single_row($sql_query);
362 if (empty($row)) {
363 if ($table == '*') {
364 if ($db == '*') {
365 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
366 } elseif ($table == '*') {
367 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
369 $res = PMA_DBI_query($sql_query);
370 while ($row1 = PMA_DBI_fetch_row($res)) {
371 if (substr($row1[0], 0, 4) == 'max_') {
372 $row[$row1[0]] = 0;
373 } else {
374 $row[$row1[0]] = 'N';
377 PMA_DBI_free_result($res);
378 } else {
379 $row = array('Table_priv' => '');
382 if (isset($row['Table_priv'])) {
383 $row1 = PMA_DBI_fetch_single_row(
384 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
385 'ASSOC', $GLOBALS['userlink']);
386 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
387 // the View for Create is spelled with uppercase V
388 // the view for Show is spelled with lowercase v
389 // and there is a space between the words
391 $av_grants = explode('\',\'', substr($row1['Type'], strpos($row1['Type'], '(') + 2, strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3));
392 unset($row1);
393 $users_grants = explode(',', $row['Table_priv']);
395 foreach ($av_grants as $current_grant) {
396 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
398 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
400 // get collumns
401 $res = PMA_DBI_try_query('SHOW COLUMNS FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($db)) . '.' . PMA_backquote($table) . ';');
402 $columns = array();
403 if ($res) {
404 while ($row1 = PMA_DBI_fetch_row($res)) {
405 $columns[$row1[0]] = array(
406 'Select' => FALSE,
407 'Insert' => FALSE,
408 'Update' => FALSE,
409 'References' => FALSE
412 PMA_DBI_free_result($res);
414 unset($res, $row1);
416 // t a b l e - s p e c i f i c p r i v i l e g e s
417 if (! empty($columns)) {
418 $res = PMA_DBI_query(
419 'SELECT `Column_name`, `Column_priv`'
420 .' FROM `mysql`.`columns_priv`'
421 .' WHERE `User`'
422 .' = \'' . PMA_sqlAddslashes($username) . "'"
423 .' AND `Host`'
424 .' = \'' . PMA_sqlAddslashes($hostname) . "'"
425 .' AND `Db`'
426 .' = \'' . PMA_sqlAddslashes(PMA_unescape_mysql_wildcards($db)) . "'"
427 .' AND `Table_name`'
428 .' = \'' . PMA_sqlAddslashes($table) . '\';');
430 while ($row1 = PMA_DBI_fetch_row($res)) {
431 $row1[1] = explode(',', $row1[1]);
432 foreach ($row1[1] as $current) {
433 $columns[$row1[0]][$current] = TRUE;
436 PMA_DBI_free_result($res);
437 unset($res, $row1, $current);
439 echo '<input type="hidden" name="grant_count" value="' . count($row) . '" />' . "\n"
440 . '<input type="hidden" name="column_count" value="' . count($columns) . '" />' . "\n"
441 . '<fieldset id="fieldset_user_priv">' . "\n"
442 . ' <legend>' . __('Table-specific privileges')
443 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English '))
444 . '</legend>' . "\n";
448 // privs that are attached to a specific column
449 PMA_display_column_privs($columns, $row, 'Select_priv',
450 'SELECT', 'select', __('Allows reading data.'), 'Select');
452 PMA_display_column_privs($columns, $row, 'Insert_priv',
453 'INSERT', 'insert', __('Allows inserting and replacing data.'), 'Insert');
455 PMA_display_column_privs($columns, $row, 'Update_priv',
456 'UPDATE', 'update', __('Allows changing data.'), 'Update');
458 PMA_display_column_privs($columns, $row, 'References_priv',
459 'REFERENCES', 'references', __('Has no effect in this MySQL version.'), 'References');
461 // privs that are not attached to a specific column
463 echo ' <div class="item">' . "\n";
464 foreach ($row as $current_grant => $current_grant_value) {
465 if (in_array(substr($current_grant, 0, (strlen($current_grant) - 5)),
466 array('Select', 'Insert', 'Update', 'References'))) {
467 continue;
469 // make a substitution to match the messages variables;
470 // also we must substitute the grant we get, because we can't generate
471 // a form variable containing blanks (those would get changed to
472 // an underscore when receiving the POST)
473 if ($current_grant == 'Create View_priv') {
474 $tmp_current_grant = 'CreateView_priv';
475 $current_grant = 'Create_view_priv';
476 } elseif ($current_grant == 'Show view_priv') {
477 $tmp_current_grant = 'ShowView_priv';
478 $current_grant = 'Show_view_priv';
479 } else {
480 $tmp_current_grant = $current_grant;
483 echo ' <div class="item">' . "\n"
484 . ' <input type="checkbox"'
485 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
486 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
487 . '" value="Y" '
488 . ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
489 . 'title="';
491 echo (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
492 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
493 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl']) . '"/>' . "\n";
495 echo ' <label for="checkbox_' . $current_grant
496 . '"><tt><dfn title="'
497 . (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
498 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
499 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl'])
500 . '">' . strtoupper(substr($current_grant, 0, strlen($current_grant) - 5)) . '</dfn></tt></label>' . "\n"
501 . ' </div>' . "\n";
502 } // end foreach ()
504 echo ' </div>' . "\n";
505 // for Safari 2.0.2
506 echo ' <div class="clearfloat"></div>' . "\n";
508 } else {
510 // g l o b a l o r d b - s p e c i f i c
512 // d a t a
513 $privTable[0] = array(
514 array('Select', 'SELECT', __('Allows reading data.')),
515 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
516 array('Update', 'UPDATE', __('Allows changing data.')),
517 array('Delete', 'DELETE', __('Allows deleting data.'))
519 if ($db == '*') {
520 $privTable[0][] = array('File', 'FILE', __('Allows importing data from and exporting data into files.'));
523 // s t r u c t u r e
524 $privTable[1] = array(
525 array('Create', 'CREATE', ($table == '*' ? __('Allows creating new databases and tables.') : __('Allows creating new tables.'))),
526 array('Alter', 'ALTER', __('Allows altering the structure of existing tables.')),
527 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
528 array('Drop', 'DROP', ($table == '*' ? __('Allows dropping databases and tables.') : __('Allows dropping tables.'))),
529 array('Create_tmp_table', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
530 array('Show_view', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
531 array('Create_routine', 'CREATE ROUTINE', __('Allows creating stored routines.')),
532 array('Alter_routine', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
533 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
535 // this one is for a db-specific priv: Create_view_priv
536 if (isset($row['Create_view_priv'])) {
537 $privTable[1][] = array('Create_view', 'CREATE VIEW', __('Allows creating new views.'));
539 // this one is for a table-specific priv: Create View_priv
540 if (isset($row['Create View_priv'])) {
541 $privTable[1][] = array('Create View', 'CREATE VIEW', __('Allows creating new views.'));
543 if (isset($row['Event_priv'])) {
544 // MySQL 5.1.6
545 $privTable[1][] = array('Event', 'EVENT', __('Allows to set up events for the event scheduler'));
546 $privTable[1][] = array('Trigger', 'TRIGGER', __('Allows creating and dropping triggers'));
549 // a d m i n i s t r a t i o n
550 $privTable[2] = array(
551 array('Grant', 'GRANT', __('Allows adding users and privileges without reloading the privilege tables.')),
553 if ($db == '*') {
554 $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.'));
555 $privTable[2][] = array('Process', 'PROCESS', __('Allows viewing processes of all users'));
556 $privTable[2][] = array('Reload', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.'));
557 $privTable[2][] = array('Shutdown', 'SHUTDOWN', __('Allows shutting down the server.'));
558 $privTable[2][] = array('Show_db', 'SHOW DATABASES', __('Gives access to the complete list of databases.'));
560 $privTable[2][] = array('Lock_tables', 'LOCK TABLES', __('Allows locking tables for the current thread.'));
561 $privTable[2][] = array('References', 'REFERENCES', __('Has no effect in this MySQL version.'));
562 if ($db == '*') {
563 $privTable[2][] = array('Repl_client', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.'));
564 $privTable[2][] = array('Repl_slave', 'REPLICATION SLAVE', __('Needed for the replication slaves.'));
565 $privTable[2][] = array('Create_user', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.'));
567 echo '<input type="hidden" name="grant_count" value="'
568 . (count($privTable[0]) + count($privTable[1]) + count($privTable[2]) - (isset($row['Grant_priv']) ? 1 : 0))
569 . '" />' . "\n"
570 . '<fieldset id="fieldset_user_global_rights">' . "\n"
571 . ' <legend>' . "\n"
572 . ' '
573 . ($db == '*'
574 ? __('Global privileges')
575 : ($table == '*'
576 ? __('Database-specific privileges')
577 : __('Table-specific privileges'))) . "\n"
578 . ' (<a href="server_privileges.php?'
579 . $GLOBALS['url_query'] . '&amp;checkall=1" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', true); return false;">'
580 . __('Check All') . '</a> /' . "\n"
581 . ' <a href="server_privileges.php?'
582 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', false); return false;">'
583 . __('Uncheck All') . '</a>)' . "\n"
584 . ' </legend>' . "\n"
585 . ' <p><small><i>' . __(' Note: MySQL privilege names are expressed in English ') . '</i></small></p>' . "\n"
586 . ' <fieldset>' . "\n"
587 . ' <legend>' . __('Data') . '</legend>' . "\n";
588 foreach ($privTable[0] as $priv)
590 echo ' <div class="item">' . "\n"
591 . ' <input type="checkbox"'
592 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
593 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
594 . '_priv" value="Y" '
595 . ($row[$priv[0] . '_priv'] == 'Y' ? 'checked="checked" ' : '')
596 . 'title="' . $priv[2] . '"/>' . "\n"
597 . ' <label for="checkbox_' . $priv[0]
598 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
599 . '</dfn></tt></label>' . "\n"
600 . ' </div>' . "\n";
602 echo ' </fieldset>' . "\n"
603 . ' <fieldset>' . "\n"
604 . ' <legend>' . __('Structure') . '</legend>' . "\n";
605 foreach ($privTable[1] as $priv)
607 echo ' <div class="item">' . "\n"
608 . ' <input type="checkbox"'
609 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
610 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
611 . '_priv" value="Y" '
612 . ($row[$priv[0] . '_priv'] == 'Y' ? 'checked="checked" ' : '')
613 . 'title="' . $priv[2] . '"/>' . "\n"
614 . ' <label for="checkbox_' . $priv[0]
615 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
616 . '</dfn></tt></label>' . "\n"
617 . ' </div>' . "\n";
619 echo ' </fieldset>' . "\n"
620 . ' <fieldset>' . "\n"
621 . ' <legend>' . __('Administration') . '</legend>' . "\n";
622 foreach ($privTable[2] as $priv)
624 echo ' <div class="item">' . "\n"
625 . ' <input type="checkbox"'
626 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
627 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0]
628 . '_priv" value="Y" '
629 . ($row[$priv[0] . '_priv'] == 'Y' ? 'checked="checked" ' : '')
630 . 'title="' . $priv[2] . '"/>' . "\n"
631 . ' <label for="checkbox_' . $priv[0]
632 . '_priv"><tt><dfn title="' . $priv[2] . '">' . $priv[1]
633 . '</dfn></tt></label>' . "\n"
634 . ' </div>' . "\n";
637 echo ' </fieldset>' . "\n";
638 // The "Resource limits" box is not displayed for db-specific privs
639 if ($db == '*') {
640 echo ' <fieldset>' . "\n"
641 . ' <legend>' . __('Resource limits') . '</legend>' . "\n"
642 . ' <p><small><i>' . __('Note: Setting these options to 0 (zero) removes the limit.') . '</i></small></p>' . "\n"
643 . ' <div class="item">' . "\n"
644 . ' <label for="text_max_questions"><tt><dfn title="'
645 . __('Limits the number of queries the user may send to the server per hour.') . '">MAX QUERIES PER HOUR</dfn></tt></label>' . "\n"
646 . ' <input type="text" name="max_questions" id="text_max_questions" value="'
647 . $row['max_questions'] . '" size="11" maxlength="11" title="' . __('Limits the number of queries the user may send to the server per hour.') . '" />' . "\n"
648 . ' </div>' . "\n"
649 . ' <div class="item">' . "\n"
650 . ' <label for="text_max_updates"><tt><dfn title="'
651 . __('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"
652 . ' <input type="text" name="max_updates" id="text_max_updates" value="'
653 . $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"
654 . ' </div>' . "\n"
655 . ' <div class="item">' . "\n"
656 . ' <label for="text_max_connections"><tt><dfn title="'
657 . __('Limits the number of new connections the user may open per hour.') . '">MAX CONNECTIONS PER HOUR</dfn></tt></label>' . "\n"
658 . ' <input type="text" name="max_connections" id="text_max_connections" value="'
659 . $row['max_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of new connections the user may open per hour.') . '" />' . "\n"
660 . ' </div>' . "\n"
661 . ' <div class="item">' . "\n"
662 . ' <label for="text_max_user_connections"><tt><dfn title="'
663 . __('Limits the number of simultaneous connections the user may have.') . '">MAX USER_CONNECTIONS</dfn></tt></label>' . "\n"
664 . ' <input type="text" name="max_user_connections" id="text_max_user_connections" value="'
665 . $row['max_user_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of simultaneous connections the user may have.') . '" />' . "\n"
666 . ' </div>' . "\n"
667 . ' </fieldset>' . "\n";
669 // for Safari 2.0.2
670 echo ' <div class="clearfloat"></div>' . "\n";
672 echo '</fieldset>' . "\n";
673 if ($submit) {
674 echo '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">' . "\n"
675 . ' <input type="submit" name="update_privs" value="' . __('Go') . '" />' . "\n"
676 . '</fieldset>' . "\n";
678 } // end of the 'PMA_displayPrivTable()' function
682 * Displays the fields used by the "new user" form as well as the
683 * "change login information / copy user" form.
685 * @param string $mode are we creating a new user or are we just
686 * changing one? (allowed values: 'new', 'change')
687 * @global array $cfg the phpMyAdmin configuration
688 * @global ressource $user_link the database connection
690 * @return void
692 function PMA_displayLoginInformationFields($mode = 'new')
694 // Get user/host name lengths
695 $fields_info = PMA_DBI_get_fields('mysql', 'user');
696 $username_length = 16;
697 $hostname_length = 41;
698 foreach ($fields_info as $key => $val) {
699 if ($val['Field'] == 'User') {
700 strtok($val['Type'], '()');
701 $v = strtok('()');
702 if (is_int($v)) {
703 $username_length = $v;
705 } elseif ($val['Field'] == 'Host') {
706 strtok($val['Type'], '()');
707 $v = strtok('()');
708 if (is_int($v)) {
709 $hostname_length = $v;
713 unset($fields_info);
715 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
716 $GLOBALS['pred_username'] = 'any';
718 echo '<fieldset id="fieldset_add_user_login">' . "\n"
719 . '<legend>' . __('Login Information') . '</legend>' . "\n"
720 . '<div class="item">' . "\n"
721 . '<label for="select_pred_username">' . "\n"
722 . ' ' . __('User name') . ':' . "\n"
723 . '</label>' . "\n"
724 . '<span class="options">' . "\n"
725 . ' <select name="pred_username" id="select_pred_username" title="' . __('User name') . '"' . "\n"
726 . ' onchange="if (this.value == \'any\') { username.value = \'\'; } else if (this.value == \'userdefined\') { username.focus(); username.select(); }">' . "\n"
727 . ' <option value="any"' . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any') ? ' selected="selected"' : '') . '>' . __('Any user') . '</option>' . "\n"
728 . ' <option value="userdefined"' . ((! isset($GLOBALS['pred_username']) || $GLOBALS['pred_username'] == 'userdefined') ? ' selected="selected"' : '') . '>' . __('Use text field') . ':</option>' . "\n"
729 . ' </select>' . "\n"
730 . '</span>' . "\n"
731 . '<input type="text" name="username" maxlength="'
732 . $username_length . '" title="' . __('User name') . '"'
733 . (empty($GLOBALS['username'])
734 ? ''
735 : ' value="' . htmlspecialchars(isset($GLOBALS['new_username'])
736 ? $GLOBALS['new_username']
737 : $GLOBALS['username']) . '"')
738 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
739 . '</div>' . "\n"
740 . '<div class="item">' . "\n"
741 . '<label for="select_pred_hostname">' . "\n"
742 . ' ' . __('Host') . ':' . "\n"
743 . '</label>' . "\n"
744 . '<span class="options">' . "\n"
745 . ' <select name="pred_hostname" id="select_pred_hostname" title="' . __('Host') . '"' . "\n";
746 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
747 if (! empty($_current_user)) {
748 $thishost = str_replace("'", '', substr($_current_user, (strrpos($_current_user, '@') + 1)));
749 if ($thishost == 'localhost' || $thishost == '127.0.0.1') {
750 unset($thishost);
753 echo ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } else if (this.value == \'localhost\') { hostname.value = \'localhost\'; } '
754 . (empty($thishost) ? '' : 'else if (this.value == \'thishost\') { hostname.value = \'' . addslashes(htmlspecialchars($thishost)) . '\'; } ')
755 . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } else if (this.value == \'userdefined\') { hostname.focus(); hostname.select(); }">' . "\n";
756 unset($_current_user);
758 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
759 if (! isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
760 switch (strtolower($GLOBALS['hostname'])) {
761 case 'localhost':
762 case '127.0.0.1':
763 $GLOBALS['pred_hostname'] = 'localhost';
764 break;
765 case '%':
766 $GLOBALS['pred_hostname'] = 'any';
767 break;
768 default:
769 $GLOBALS['pred_hostname'] = 'userdefined';
770 break;
773 echo ' <option value="any"'
774 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
775 ? ' selected="selected"' : '') . '>' . __('Any host')
776 . '</option>' . "\n"
777 . ' <option value="localhost"'
778 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'localhost')
779 ? ' selected="selected"' : '') . '>' . __('Local')
780 . '</option>' . "\n";
781 if (!empty($thishost)) {
782 echo ' <option value="thishost"'
783 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'thishost')
784 ? ' selected="selected"' : '') . '>' . __('This Host')
785 . '</option>' . "\n";
787 unset($thishost);
788 echo ' <option value="hosttable"'
789 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'hosttable')
790 ? ' selected="selected"' : '') . '>' . __('Use Host Table')
791 . '</option>' . "\n"
792 . ' <option value="userdefined"'
793 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'userdefined')
794 ? ' selected="selected"' : '')
795 . '>' . __('Use text field') . ':</option>' . "\n"
796 . ' </select>' . "\n"
797 . '</span>' . "\n"
798 . '<input type="text" name="hostname" maxlength="'
799 . $hostname_length . '" value="'
800 . htmlspecialchars(isset($GLOBALS['hostname']) ? $GLOBALS['hostname'] : '')
801 . '" title="' . __('Host')
802 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
803 . PMA_showHint(__('When Host table is used, this field is ignored and values stored in Host table are used instead.'))
804 . '</div>' . "\n"
805 . '<div class="item">' . "\n"
806 . '<label for="select_pred_password">' . "\n"
807 . ' ' . __('Password') . ':' . "\n"
808 . '</label>' . "\n"
809 . '<span class="options">' . "\n"
810 . ' <select name="pred_password" id="select_pred_password" title="'
811 . __('Password') . '"' . "\n"
812 . ' onchange="if (this.value == \'none\') { pma_pw.value = \'\'; pma_pw2.value = \'\'; } else if (this.value == \'userdefined\') { pma_pw.focus(); pma_pw.select(); }">' . "\n"
813 . ($mode == 'change' ? ' <option value="keep" selected="selected">' . __('Do not change the password') . '</option>' . "\n" : '')
814 . ' <option value="none"';
815 if (isset($GLOBALS['username']) && $mode != 'change') {
816 echo ' selected="selected"';
818 echo '>' . __('No Password') . '</option>' . "\n"
819 . ' <option value="userdefined"' . (isset($GLOBALS['username']) ? '' : ' selected="selected"') . '>' . __('Use text field') . ':</option>' . "\n"
820 . ' </select>' . "\n"
821 . '</span>' . "\n"
822 . '<input type="password" id="text_pma_pw" name="pma_pw" title="' . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
823 . '</div>' . "\n"
824 . '<div class="item" id="div_element_before_generate_password">' . "\n"
825 . '<label for="text_pma_pw2">' . "\n"
826 . ' ' . __('Re-type') . ':' . "\n"
827 . '</label>' . "\n"
828 . '<span class="options">&nbsp;</span>' . "\n"
829 . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="' . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
830 . '</div>' . "\n"
831 // Generate password added here via jQuery
832 . '</fieldset>' . "\n";
833 } // end of the 'PMA_displayUserAndHostFields()' function
836 * Changes / copies a user, part I
838 if (isset($_REQUEST['change_copy'])) {
839 $user_host_condition =
840 ' WHERE `User`'
841 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
842 .' AND `Host`'
843 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\';';
844 $row = PMA_DBI_fetch_single_row('SELECT * FROM `mysql`.`user` ' . $user_host_condition);
845 if (! $row) {
846 PMA_Message::notice(__('No user found.'))->display();
847 unset($_REQUEST['change_copy']);
848 } else {
849 extract($row, EXTR_OVERWRITE);
850 // Recent MySQL versions have the field "Password" in mysql.user,
851 // so the previous extract creates $Password but this script
852 // uses $password
853 if (! isset($password) && isset($Password)) {
854 $password = $Password;
856 $queries = array();
862 * Adds a user
863 * (Changes / copies a user, part II)
865 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
866 $sql_query = '';
867 if ($pred_username == 'any') {
868 $username = '';
870 switch ($pred_hostname) {
871 case 'any':
872 $hostname = '%';
873 break;
874 case 'localhost':
875 $hostname = 'localhost';
876 break;
877 case 'hosttable':
878 $hostname = '';
879 break;
880 case 'thishost':
881 $_user_name = PMA_DBI_fetch_value('SELECT USER()');
882 $hostname = substr($_user_name, (strrpos($_user_name, '@') + 1));
883 unset($_user_name);
884 break;
886 $sql = "SELECT '1' FROM `mysql`.`user`"
887 . " WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
888 . " AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
889 if (PMA_DBI_fetch_value($sql) == 1) {
890 $message = PMA_Message::error(__('The user %s already exists!'));
891 $message->addParam('[i]\'' . $username . '\'@\'' . $hostname . '\'[/i]');
892 $_REQUEST['adduser'] = true;
893 $_add_user_error = true;
894 } else {
896 $create_user_real = 'CREATE USER \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
898 $real_sql_query =
899 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
900 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
901 if ($pred_password != 'none' && $pred_password != 'keep') {
902 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
903 $real_sql_query .= ' IDENTIFIED BY \'' . PMA_sqlAddslashes($pma_pw) . '\'';
904 if (isset($create_user_real)) {
905 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
906 $create_user_real .= ' IDENTIFIED BY \'' . PMA_sqlAddslashes($pma_pw) . '\'';
908 } else {
909 if ($pred_password == 'keep' && !empty($password)) {
910 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
911 if (isset($create_user_real)) {
912 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
915 $sql_query = $real_sql_query;
916 if (isset($create_user_real)) {
917 $create_user_show = $create_user_real;
921 * @todo similar code appears twice in this script
923 if ((isset($Grant_priv) && $Grant_priv == 'Y')
924 || (isset($max_questions) || isset($max_connections)
925 || isset($max_updates) || isset($max_user_connections))) {
926 $real_sql_query .= ' WITH';
927 $sql_query .= ' WITH';
928 if (isset($Grant_priv) && $Grant_priv == 'Y') {
929 $real_sql_query .= ' GRANT OPTION';
930 $sql_query .= ' GRANT OPTION';
932 if (isset($max_questions)) {
933 // avoid negative values
934 $max_questions = max(0, (int)$max_questions);
935 $real_sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
936 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
938 if (isset($max_connections)) {
939 $max_connections = max(0, (int)$max_connections);
940 $real_sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
941 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
943 if (isset($max_updates)) {
944 $max_updates = max(0, (int)$max_updates);
945 $real_sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
946 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
948 if (isset($max_user_connections)) {
949 $max_user_connections = max(0, (int)$max_user_connections);
950 $real_sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
951 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
954 if (isset($create_user_real)) {
955 $create_user_real .= ';';
956 $create_user_show .= ';';
958 $real_sql_query .= ';';
959 $sql_query .= ';';
960 if (empty($_REQUEST['change_copy'])) {
961 $_error = false;
963 if (isset($create_user_real)) {
964 if (! PMA_DBI_try_query($create_user_real)) {
965 $_error = true;
967 $sql_query = $create_user_show . $sql_query;
970 if ($_error || ! PMA_DBI_try_query($real_sql_query)) {
971 $_REQUEST['createdb'] = false;
972 $message = PMA_Message::rawError(PMA_DBI_getError());
973 } else {
974 $message = PMA_Message::success(__('You have added a new user.'));
977 switch (PMA_ifSetOr($_REQUEST['createdb'], '0')) {
978 case '1' :
979 // Create database with same name and grant all privileges
980 $q = 'CREATE DATABASE IF NOT EXISTS '
981 . PMA_backquote(PMA_sqlAddslashes($username)) . ';';
982 $sql_query .= $q;
983 if (! PMA_DBI_try_query($q)) {
984 $message = PMA_Message::rawError(PMA_DBI_getError());
985 break;
990 * If we are not in an Ajax request, we can't reload navigation now
992 if($GLOBALS['is_ajax_request'] != true) {
993 // this is needed in case tracking is on:
994 $GLOBALS['db'] = $username;
995 $GLOBALS['reload'] = TRUE;
996 PMA_reloadNavigation();
999 $q = 'GRANT ALL PRIVILEGES ON '
1000 . PMA_backquote(PMA_sqlAddslashes($username)) . '.* TO \''
1001 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1002 $sql_query .= $q;
1003 if (! PMA_DBI_try_query($q)) {
1004 $message = PMA_Message::rawError(PMA_DBI_getError());
1006 break;
1007 case '2' :
1008 // Grant all privileges on wildcard name (username\_%)
1009 $q = 'GRANT ALL PRIVILEGES ON '
1010 . PMA_backquote(PMA_sqlAddslashes($username) . '\_%') . '.* TO \''
1011 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1012 $sql_query .= $q;
1013 if (! PMA_DBI_try_query($q)) {
1014 $message = PMA_Message::rawError(PMA_DBI_getError());
1016 break;
1017 case '3' :
1018 // Grant all privileges on the specified database to the new user
1019 $q = 'GRANT ALL PRIVILEGES ON '
1020 . PMA_backquote(PMA_sqlAddslashes($dbname)) . '.* TO \''
1021 . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1022 $sql_query .= $q;
1023 if (! PMA_DBI_try_query($q)) {
1024 $message = PMA_Message::rawError(PMA_DBI_getError());
1026 break;
1027 case '0' :
1028 default :
1029 break;
1031 } else {
1032 if (isset($create_user_real)) {
1033 $queries[] = $create_user_real;
1035 $queries[] = $real_sql_query;
1036 // we put the query containing the hidden password in
1037 // $queries_for_display, at the same position occupied
1038 // by the real query in $queries
1039 $tmp_count = count($queries);
1040 if (isset($create_user_real)) {
1041 $queries_for_display[$tmp_count - 2] = $create_user_show;
1043 $queries_for_display[$tmp_count - 1] = $sql_query;
1045 unset($res, $real_sql_query);
1051 * Changes / copies a user, part III
1053 if (isset($_REQUEST['change_copy'])) {
1054 $user_host_condition =
1055 ' WHERE `User`'
1056 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1057 .' AND `Host`'
1058 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\';';
1059 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1060 while ($row = PMA_DBI_fetch_assoc($res)) {
1061 $queries[] =
1062 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1063 .' ON ' . PMA_backquote($row['Db']) . '.*'
1064 .' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1065 . ($row['Grant_priv'] == 'Y' ? ' WITH GRANT OPTION;' : ';');
1067 PMA_DBI_free_result($res);
1068 $res = PMA_DBI_query(
1069 'SELECT `Db`, `Table_name`, `Table_priv`'
1070 .' FROM `mysql`.`tables_priv`' . $user_host_condition,
1071 $GLOBALS['userlink'], PMA_DBI_QUERY_STORE);
1072 while ($row = PMA_DBI_fetch_assoc($res)) {
1074 $res2 = PMA_DBI_QUERY(
1075 'SELECT `Column_name`, `Column_priv`'
1076 .' FROM `mysql`.`columns_priv`'
1077 .' WHERE `User`'
1078 .' = \'' . PMA_sqlAddslashes($old_username) . "'"
1079 .' AND `Host`'
1080 .' = \'' . PMA_sqlAddslashes($old_hostname) . '\''
1081 .' AND `Db`'
1082 .' = \'' . PMA_sqlAddslashes($row['Db']) . "'"
1083 .' AND `Table_name`'
1084 .' = \'' . PMA_sqlAddslashes($row['Table_name']) . "'"
1085 .';',
1086 null, PMA_DBI_QUERY_STORE);
1088 $tmp_privs1 = PMA_extractPrivInfo($row);
1089 $tmp_privs2 = array(
1090 'Select' => array(),
1091 'Insert' => array(),
1092 'Update' => array(),
1093 'References' => array()
1096 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1097 $tmp_array = explode(',', $row2['Column_priv']);
1098 if (in_array('Select', $tmp_array)) {
1099 $tmp_privs2['Select'][] = $row2['Column_name'];
1101 if (in_array('Insert', $tmp_array)) {
1102 $tmp_privs2['Insert'][] = $row2['Column_name'];
1104 if (in_array('Update', $tmp_array)) {
1105 $tmp_privs2['Update'][] = $row2['Column_name'];
1107 if (in_array('References', $tmp_array)) {
1108 $tmp_privs2['References'][] = $row2['Column_name'];
1110 unset($tmp_array);
1112 if (count($tmp_privs2['Select']) > 0 && !in_array('SELECT', $tmp_privs1)) {
1113 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1115 if (count($tmp_privs2['Insert']) > 0 && !in_array('INSERT', $tmp_privs1)) {
1116 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1118 if (count($tmp_privs2['Update']) > 0 && !in_array('UPDATE', $tmp_privs1)) {
1119 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1121 if (count($tmp_privs2['References']) > 0 && !in_array('REFERENCES', $tmp_privs1)) {
1122 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1124 unset($tmp_privs2);
1125 $queries[] =
1126 'GRANT ' . join(', ', $tmp_privs1)
1127 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1128 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\''
1129 . (in_array('Grant', explode(',', $row['Table_priv'])) ? ' WITH GRANT OPTION;' : ';');
1135 * Updates privileges
1137 if (!empty($update_privs)) {
1138 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, (isset($tablename) ? $tablename : ''));
1140 $sql_query0 =
1141 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1142 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1143 if (! isset($Grant_priv) || $Grant_priv != 'Y') {
1144 $sql_query1 =
1145 'REVOKE GRANT OPTION ON ' . $db_and_table
1146 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1147 } else {
1148 $sql_query1 = '';
1151 // Should not do a GRANT USAGE for a table-specific privilege, it
1152 // causes problems later (cannot revoke it)
1153 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1154 $sql_query2 =
1155 'GRANT ' . join(', ', PMA_extractPrivInfo())
1156 . ' ON ' . $db_and_table
1157 . ' TO \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\'';
1160 * @todo similar code appears twice in this script
1162 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1163 || (! isset($dbname)
1164 && (isset($max_questions) || isset($max_connections)
1165 || isset($max_updates) || isset($max_user_connections))))
1167 $sql_query2 .= 'WITH';
1168 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1169 $sql_query2 .= ' GRANT OPTION';
1171 if (isset($max_questions)) {
1172 $max_questions = max(0, (int)$max_questions);
1173 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1175 if (isset($max_connections)) {
1176 $max_connections = max(0, (int)$max_connections);
1177 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1179 if (isset($max_updates)) {
1180 $max_updates = max(0, (int)$max_updates);
1181 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1183 if (isset($max_user_connections)) {
1184 $max_user_connections = max(0, (int)$max_user_connections);
1185 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1188 $sql_query2 .= ';';
1190 if (! PMA_DBI_query($sql_query0)) {
1191 // This might fail when the executing user does not have ALL PRIVILEGES himself.
1192 // See https://sourceforge.net/tracker/index.php?func=detail&aid=3285929&group_id=23067&atid=377408
1193 $sql_query0 = '';
1195 if (isset($sql_query1) && !PMA_DBI_try_query($sql_query1)) {
1196 // this one may fail, too...
1197 $sql_query1 = '';
1199 if (isset($sql_query2)) {
1200 PMA_DBI_query($sql_query2);
1201 } else {
1202 $sql_query2 = '';
1204 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1205 $message = PMA_Message::success(__('You have updated the privileges for %s.'));
1206 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1211 * Revokes Privileges
1213 if (isset($_REQUEST['revokeall'])) {
1214 $db_and_table = PMA_WildcardEscapeForGrant($db_and_table, $dbname, isset($tablename) ? $tablename : '');
1216 $sql_query0 =
1217 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1218 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1219 $sql_query1 =
1220 'REVOKE GRANT OPTION ON ' . $db_and_table
1221 . ' FROM \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\';';
1223 PMA_DBI_query($sql_query0);
1224 if (! PMA_DBI_try_query($sql_query1)) {
1225 // this one may fail, too...
1226 $sql_query1 = '';
1228 $sql_query = $sql_query0 . ' ' . $sql_query1;
1229 $message = PMA_Message::success(__('You have revoked the privileges for %s'));
1230 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1231 if (! isset($tablename)) {
1232 unset($dbname);
1233 } else {
1234 unset($tablename);
1240 * Updates the password
1242 if (isset($_REQUEST['change_pw'])) {
1243 // similar logic in user_password.php
1244 $message = '';
1246 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1247 if ($pma_pw != $pma_pw2) {
1248 $message = PMA_Message::error(__('The passwords aren\'t the same!'));
1249 } elseif (empty($pma_pw) || empty($pma_pw2)) {
1250 $message = PMA_Message::error(__('The password is empty!'));
1252 } // end if
1254 // here $nopass could be == 1
1255 if (empty($message)) {
1257 $hashing_function = (!empty($pw_hash) && $pw_hash == 'old' ? 'OLD_' : '')
1258 . 'PASSWORD';
1260 // in $sql_query which will be displayed, hide the password
1261 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1262 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddslashes($username) . '\'@\'' . PMA_sqlAddslashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . PMA_sqlAddslashes($pma_pw) . '\')');
1263 PMA_DBI_try_query($local_query)
1264 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, FALSE, $err_url);
1265 $message = PMA_Message::success(__('The password for %s was changed successfully.'));
1266 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1272 * Deletes users
1273 * (Changes / copies a user, part IV)
1276 if (isset($_REQUEST['delete']) || (isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1277 if (isset($_REQUEST['change_copy'])) {
1278 $selected_usr = array($old_username . '&amp;#27;' . $old_hostname);
1279 } else {
1280 $selected_usr = $_REQUEST['selected_usr'];
1281 $queries = array();
1283 foreach ($selected_usr as $each_user) {
1284 list($this_user, $this_host) = explode('&amp;#27;', $each_user);
1285 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1286 $queries[] = 'DROP USER \'' . PMA_sqlAddslashes($this_user) . '\'@\'' . PMA_sqlAddslashes($this_host) . '\';';
1288 if (isset($_REQUEST['drop_users_db'])) {
1289 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1290 $GLOBALS['reload'] = TRUE;
1292 if($GLOBALS['is_ajax_request'] != true) {
1293 PMA_reloadNavigation();
1297 if (empty($_REQUEST['change_copy'])) {
1298 if (empty($queries)) {
1299 $message = PMA_Message::error(__('No users selected for deleting!'));
1300 } else {
1301 if ($_REQUEST['mode'] == 3) {
1302 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1303 $queries[] = 'FLUSH PRIVILEGES;';
1305 $drop_user_error = '';
1306 foreach ($queries as $sql_query) {
1307 if ($sql_query{0} != '#') {
1308 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1309 $drop_user_error .= PMA_DBI_getError() . "\n";
1313 // tracking sets this, causing the deleted db to be shown in navi
1314 unset($GLOBALS['db']);
1316 $sql_query = join("\n", $queries);
1317 if (! empty($drop_user_error)) {
1318 $message = PMA_Message::rawError($drop_user_error);
1319 } else {
1320 $message = PMA_Message::success(__('The selected users have been deleted successfully.'));
1323 unset($queries);
1329 * Changes / copies a user, part V
1331 if (isset($_REQUEST['change_copy'])) {
1332 $tmp_count = 0;
1333 foreach ($queries as $sql_query) {
1334 if ($sql_query{0} != '#') {
1335 PMA_DBI_query($sql_query);
1337 // when there is a query containing a hidden password, take it
1338 // instead of the real query sent
1339 if (isset($queries_for_display[$tmp_count])) {
1340 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1342 $tmp_count++;
1344 $message = PMA_Message::success();
1345 $sql_query = join("\n", $queries);
1350 * Reloads the privilege tables into memory
1352 if (isset($_REQUEST['flush_privileges'])) {
1353 $sql_query = 'FLUSH PRIVILEGES;';
1354 PMA_DBI_query($sql_query);
1355 $message = PMA_Message::success(__('The privileges were reloaded successfully.'));
1359 * defines some standard links
1361 $link_edit = '<a class="edit_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . $GLOBALS['url_query']
1362 . '&amp;username=%s'
1363 . '&amp;hostname=%s'
1364 . '&amp;dbname=%s'
1365 . '&amp;tablename=%s">'
1366 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1367 . '</a>';
1369 $link_revoke = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1370 . '&amp;username=%s'
1371 . '&amp;hostname=%s'
1372 . '&amp;dbname=%s'
1373 . '&amp;tablename=%s'
1374 . '&amp;revokeall=1">'
1375 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1376 . '</a>';
1378 $link_export = '<a class="export_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . $GLOBALS['url_query']
1379 . '&amp;username=%s'
1380 . '&amp;hostname=%s'
1381 . '&amp;initial=%s'
1382 . '&amp;export=1">'
1383 . PMA_getIcon('b_tblexport.png', __('Export'))
1384 . '</a>';
1387 * If we are in an Ajax request for Create User/Edit User/Revoke User/Flush Privileges,
1388 * show $message and exit.
1390 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'])) {
1392 if(isset($sql_query)) {
1393 $extra_data['sql_query'] = PMA_showMessage(NULL, $sql_query);
1396 if(isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
1398 * generate html on the fly for the new user that was just created.
1400 $new_user_string = '<tr>'."\n"
1401 .'<td> <input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_" value="' . htmlspecialchars($username) . '&amp;#27;' . htmlspecialchars($hostname) . '" /> </td>'."\n"
1402 .'<td><label for="checkbox_sel_users_">' . (empty($username) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($username) ) . '</label></td>' . "\n"
1403 .'<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
1404 $new_user_string .= '<td>';
1406 if(!empty($password) || isset($pma_pw)) {
1407 $new_user_string .= __('Yes');
1409 else {
1410 $new_user_string .= '<span style="color: #FF0000">' . __('No') . '</span>';
1413 $new_user_string .= '</td>'."\n";
1414 $new_user_string .= '<td><tt>' . join(', ', PMA_extractPrivInfo('', true)) . '</tt></td>'; //Fill in privileges here
1415 $new_user_string .= '<td>';
1417 if((isset($Grant_priv) && $Grant_priv == 'Y')) {
1418 $new_user_string .= __('Yes');
1420 else {
1421 $new_user_string .= __('No');
1424 $new_user_string .='</td>';
1426 $new_user_string .= '<td>'.sprintf($link_edit, urlencode($username), urlencode($hostname), '', '' ).'</td>'."\n";
1427 $new_user_string .= '<td>'.sprintf($link_export, urlencode($username), urlencode($hostname), (isset($initial) ? $initial : '')).'</td>'."\n";
1429 $new_user_string .= '</tr>';
1431 $extra_data['new_user_string'] = $new_user_string;
1434 * Generate the string for this alphabet's initial, to update the user
1435 * pagination
1437 $new_user_initial = strtoupper(substr($username, 0, 1));
1438 $new_user_initial_string = '<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . $new_user_initial
1439 .'">' . $new_user_initial . '</a>';
1440 $extra_data['new_user_initial'] = $new_user_initial;
1441 $extra_data['new_user_initial_string'] = $new_user_initial_string;
1444 if(isset($update_privs)) {
1445 $extra_data['db_specific_privs'] = false;
1446 if (isset($dbname_is_wildcard)) {
1447 $extra_data['db_specific_privs'] = !$dbname_is_wildcard;
1449 $new_privileges = join(', ', PMA_extractPrivInfo('', true));
1451 $extra_data['new_privileges'] = $new_privileges;
1454 if ($message instanceof PMA_Message) {
1455 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
1460 * Displays the links
1462 if (isset($viewing_mode) && $viewing_mode == 'db') {
1463 $db = $checkprivs;
1464 $url_query .= '&amp;goto=db_operations.php';
1466 // Gets the database structure
1467 $sub_part = '_structure';
1468 require './libraries/db_info.inc.php';
1469 echo "\n";
1470 } else {
1471 require './libraries/server_links.inc.php';
1476 * Displays the page
1479 // export user definition
1480 if (isset($_REQUEST['export'])) {
1481 echo '<h2>' . __('User') . ' \'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'</h2>';
1482 echo '<textarea cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1483 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddslashes($username) . "'@'" . PMA_sqlAddslashes($hostname) . "'");
1484 foreach($grants as $one_grant) {
1485 echo $one_grant . ";\n\n";
1487 echo '</textarea>';
1488 unset($username, $hostname, $grants, $one_grant);
1489 if( $GLOBALS['is_ajax_request']) {
1490 exit;
1494 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs))) {
1495 if (! isset($username)) {
1496 // No username is given --> display the overview
1497 echo '<h2>' . "\n"
1498 . PMA_getIcon('b_usrlist.png')
1499 . __('User overview') . "\n"
1500 . '</h2>' . "\n";
1502 $sql_query =
1503 'SELECT *,' .
1504 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1505 ' FROM `mysql`.`user`';
1507 $sql_query .= (isset($initial) ? PMA_RangeOfUsers($initial) : '');
1509 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1510 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1512 if (! $res) {
1513 // the query failed! This may have two reasons:
1514 // - the user does not have enough privileges
1515 // - the privilege tables use a structure of an earlier version.
1516 // so let's try a more simple query
1518 $sql_query = 'SELECT * FROM `mysql`.`user`';
1519 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1521 if (!$res) {
1522 PMA_Message::error(__('No Privileges'))->display();
1523 PMA_DBI_free_result($res);
1524 unset($res);
1525 } else {
1526 // This message is hardcoded because I will replace it by
1527 // a automatic repair feature soon.
1528 $raw = 'Your privilege table structure seems to be older than'
1529 . ' this MySQL version!<br />'
1530 . 'Please run the <tt>mysql_upgrade</tt> command'
1531 . '(<tt>mysql_fix_privilege_tables</tt> on older systems)'
1532 . ' that should be included in your MySQL server distribution'
1533 . ' to solve this problem!';
1534 PMA_Message::rawError($raw)->display();
1536 } else {
1538 // we also want users not in table `user` but in other table
1539 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1541 $tables_to_search_for_users = array(
1542 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1545 $db_rights_sqls = array();
1546 foreach ($tables_to_search_for_users as $table_search_in) {
1547 if (in_array($table_search_in, $tables)) {
1548 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ? PMA_RangeOfUsers($initial) : '');
1552 $user_defaults = array(
1553 'User' => '',
1554 'Host' => '%',
1555 'Password' => '?',
1556 'Grant_priv' => 'N',
1557 'privs' => array('USAGE'),
1560 // for all initials, even non A-Z
1561 $array_initials = array();
1562 // for the rights
1563 $db_rights = array();
1565 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1566 .' ORDER BY `User` ASC, `Host` ASC';
1568 $db_rights_result = PMA_DBI_query($db_rights_sql);
1570 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1571 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1572 $db_rights[$db_rights_row['User']][$db_rights_row['Host']] =
1573 $db_rights_row;
1575 PMA_DBI_free_result($db_rights_result);
1576 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1577 ksort($db_rights);
1580 * Displays the initials
1581 * In an Ajax request, we don't need to show this
1584 if( $GLOBALS['is_ajax_request'] != true ) {
1586 // initialize to FALSE the letters A-Z
1587 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++) {
1588 if (! isset($array_initials[chr($letter_counter + 64)])) {
1589 $array_initials[chr($letter_counter + 64)] = FALSE;
1593 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE);
1594 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1595 $array_initials[$tmp_initial] = TRUE;
1598 // Display the initials, which can be any characters, not
1599 // just letters. For letters A-Z, we add the non-used letters
1600 // as greyed out.
1602 uksort($array_initials, "strnatcasecmp");
1604 echo '<table id="initials_table" class="' . $conditional_class . '" <cellspacing="5"><tr>';
1605 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1606 if ($initial_was_found) {
1607 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1608 } else {
1609 echo '<td>' . $tmp_initial . '</td>';
1612 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;showall=1">[' . __('Show all') . ']</a></td>' . "\n";
1613 echo '</tr></table>';
1617 * Display the user overview
1618 * (if less than 50 users, display them immediately)
1621 if (isset($initial) || isset($showall) || PMA_DBI_num_rows($res) < 50) {
1623 while ($row = PMA_DBI_fetch_assoc($res)) {
1624 $row['privs'] = PMA_extractPrivInfo($row, true);
1625 $db_rights[$row['User']][$row['Host']] = $row;
1627 @PMA_DBI_free_result($res);
1628 unset($res);
1630 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1631 . PMA_generate_common_hidden_inputs('', '')
1632 . ' <table id="tableuserrights" class="data">' . "\n"
1633 . ' <thead>' . "\n"
1634 . ' <tr><th></th>' . "\n"
1635 . ' <th>' . __('User') . '</th>' . "\n"
1636 . ' <th>' . __('Host') . '</th>' . "\n"
1637 . ' <th>' . __('Password') . '</th>' . "\n"
1638 . ' <th>' . __('Global privileges') . ' '
1639 . PMA_showHint(__(' Note: MySQL privilege names are expressed in English ')) . '</th>' . "\n"
1640 . ' <th>' . __('Grant') . '</th>' . "\n"
1641 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1642 echo ' </tr>' . "\n";
1643 echo ' </thead>' . "\n";
1644 echo ' <tbody>' . "\n";
1645 $odd_row = true;
1646 $index_checkbox = -1;
1647 foreach ($db_rights as $user) {
1648 $index_checkbox++;
1649 ksort($user);
1650 foreach ($user as $host) {
1651 $index_checkbox++;
1652 echo ' <tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
1653 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1654 . $index_checkbox . '" value="'
1655 . htmlspecialchars($host['User'] . '&amp;#27;' . $host['Host'])
1656 . '"'
1657 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
1658 . ' /></td>' . "\n"
1659 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1660 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1661 echo ' <td>';
1662 switch ($host['Password']) {
1663 case 'Y':
1664 echo __('Yes');
1665 break;
1666 case 'N':
1667 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1668 break;
1669 // this happens if this is a definition not coming from mysql.user
1670 default:
1671 echo '--'; // in future version, replace by "not present"
1672 break;
1673 } // end switch
1674 echo '</td>' . "\n"
1675 . ' <td><tt>' . "\n"
1676 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1677 . ' </tt></td>' . "\n"
1678 . ' <td>' . ($host['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . '</td>' . "\n"
1679 . ' <td align="center">';
1680 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1681 echo '</td>';
1682 echo '<td align="center">';
1683 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ? $initial : ''));
1684 echo '</td>';
1685 echo '</tr>';
1686 $odd_row = ! $odd_row;
1690 unset($user, $host, $odd_row);
1691 echo ' </tbody></table>' . "\n"
1692 .'<img class="selectallarrow"'
1693 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1694 .' width="38" height="22"'
1695 .' alt="' . __('With selected:') . '" />' . "\n"
1696 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;checkall=1"'
1697 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1698 . __('Check All') . '</a>' . "\n"
1699 .'/' . "\n"
1700 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1701 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1702 . __('Uncheck All') . '</a>' . "\n";
1704 // add/delete user fieldset
1705 echo ' <fieldset id="fieldset_add_user">' . "\n"
1706 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1707 . PMA_getIcon('b_usradd.png')
1708 . ' ' . __('Add a new User') . '</a>' . "\n"
1709 . ' </fieldset>' . "\n"
1710 . ' <fieldset id="fieldset_delete_user">'
1711 . ' <legend>' . "\n"
1712 . PMA_getIcon('b_usrdrop.png')
1713 . ' ' . __('Remove selected users') . '' . "\n"
1714 . ' </legend>' . "\n"
1715 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1716 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1717 . ' <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"
1718 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1719 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1720 . ' </label>' . "\n"
1721 . ' </fieldset>' . "\n"
1722 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1723 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" class="' . $conditional_class . '"/>' . "\n"
1724 . ' </fieldset>' . "\n"
1725 . '</form>' . "\n";
1726 } else {
1728 unset ($row);
1729 echo ' <fieldset id="fieldset_add_user">' . "\n"
1730 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1">' . "\n"
1731 . PMA_getIcon('b_usradd.png')
1732 . ' ' . __('Add a new User') . '</a>' . "\n"
1733 . ' </fieldset>' . "\n";
1734 } // end if (display overview)
1736 if( $GLOBALS['is_ajax_request'] ) {
1737 exit;
1740 $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);
1741 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;flush_privileges=1" id="reload_privileges_anchor" class="' . $conditional_class . '">', false);
1742 $flushnote->addParam('</a>', false);
1743 $flushnote->display();
1747 } else {
1749 // A user was selected -> display the user's properties
1751 // In an Ajax request, prevent cached values from showing
1752 if($GLOBALS['is_ajax_request'] == true) {
1753 header('Cache-Control: no-cache');
1756 echo '<h2>' . "\n"
1757 . PMA_getIcon('b_usredit.png')
1758 . __('Edit Privileges') . ': '
1759 . __('User') ;
1761 if (isset($dbname)) {
1762 echo ' <i><a href="server_privileges.php?'
1763 . $GLOBALS['url_query'] . '&amp;username=' . htmlspecialchars(urlencode($username))
1764 . '&amp;hostname=' . htmlspecialchars(urlencode($hostname)) . '&amp;dbname=&amp;tablename=">\''
1765 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1766 . '\'</a></i>' . "\n";
1767 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
1769 echo ' - ' . ($dbname_is_wildcard ? __('Databases') : __('Database') );
1770 if (isset($tablename)) {
1771 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
1772 . '&amp;username=' . htmlspecialchars(urlencode($username)) . '&amp;hostname=' . htmlspecialchars(urlencode($hostname))
1773 . '&amp;dbname=' . htmlspecialchars($url_dbname) . '&amp;tablename=">' . htmlspecialchars($dbname) . '</a></i>';
1774 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
1775 } else {
1776 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
1779 } else {
1780 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1781 . '\'</i>' . "\n";
1784 echo '</h2>' . "\n";
1787 $sql = "SELECT '1' FROM `mysql`.`user`"
1788 . " WHERE `User` = '" . PMA_sqlAddslashes($username) . "'"
1789 . " AND `Host` = '" . PMA_sqlAddslashes($hostname) . "';";
1790 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
1791 unset($sql);
1792 if ($user_does_not_exists) {
1793 PMA_Message::error(__('The selected user was not found in the privilege table.'))->display();
1794 PMA_displayLoginInformationFields();
1795 //require './libraries/footer.inc.php';
1798 echo '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n";
1799 $_params = array(
1800 'username' => $username,
1801 'hostname' => $hostname,
1803 if (isset($dbname)) {
1804 $_params['dbname'] = $dbname;
1805 if (isset($tablename)) {
1806 $_params['tablename'] = $tablename;
1809 echo PMA_generate_common_hidden_inputs($_params);
1811 PMA_displayPrivTable(PMA_ifSetOr($dbname, '*', 'length'),
1812 PMA_ifSetOr($tablename, '*', 'length'));
1814 echo '</form>' . "\n";
1816 if (! isset($tablename) && empty($dbname_is_wildcard)) {
1818 // no table name was given, display all table specific rights
1819 // but only if $dbname contains no wildcards
1821 // table header
1822 echo '<form action="server_privileges.php" method="post">' . "\n"
1823 . PMA_generate_common_hidden_inputs('', '')
1824 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
1825 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1826 . '<fieldset>' . "\n"
1827 . '<legend>' . (! isset($dbname) ? __('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
1828 . '<table class="data">' . "\n"
1829 . '<thead>' . "\n"
1830 . '<tr><th>' . (! isset($dbname) ? __('Database') : __('Table')) . '</th>' . "\n"
1831 . ' <th>' . __('Privileges') . '</th>' . "\n"
1832 . ' <th>' . __('Grant') . '</th>' . "\n"
1833 . ' <th>' . (! isset($dbname) ? __('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
1834 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
1835 . '</tr>' . "\n"
1836 . '</thead>' . "\n"
1837 . '<tbody>' . "\n";
1839 $user_host_condition =
1840 ' WHERE `User`'
1841 . ' = \'' . PMA_sqlAddslashes($username) . "'"
1842 . ' AND `Host`'
1843 . ' = \'' . PMA_sqlAddslashes($hostname) . "'";
1845 // table body
1846 // get data
1848 // we also want privielgs for this user not in table `db` but in other table
1849 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1850 if (! isset($dbname)) {
1852 // no db name given, so we want all privs for the given user
1854 $tables_to_search_for_users = array(
1855 'tables_priv', 'columns_priv',
1858 $db_rights_sqls = array();
1859 foreach ($tables_to_search_for_users as $table_search_in) {
1860 if (in_array($table_search_in, $tables)) {
1861 $db_rights_sqls[] = '
1862 SELECT DISTINCT `Db`
1863 FROM `mysql`.' . PMA_backquote($table_search_in)
1864 . $user_host_condition;
1868 $user_defaults = array(
1869 'Db' => '',
1870 'Grant_priv' => 'N',
1871 'privs' => array('USAGE'),
1872 'Table_privs' => true,
1875 // for the rights
1876 $db_rights = array();
1878 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1879 .' ORDER BY `Db` ASC';
1881 $db_rights_result = PMA_DBI_query($db_rights_sql);
1883 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1884 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1885 // only Db names in the table `mysql`.`db` uses wildcards
1886 // as we are in the db specific rights display we want
1887 // all db names escaped, also from other sources
1888 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
1889 $db_rights_row['Db']);
1890 $db_rights[$db_rights_row['Db']] = $db_rights_row;
1893 PMA_DBI_free_result($db_rights_result);
1894 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1896 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
1897 $res = PMA_DBI_query($sql_query);
1898 $sql_query = '';
1900 while ($row = PMA_DBI_fetch_assoc($res)) {
1901 if (isset($db_rights[$row['Db']])) {
1902 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
1903 } else {
1904 $db_rights[$row['Db']] = $row;
1906 // there are db specific rights for this user
1907 // so we can drop this db rights
1908 $db_rights[$row['Db']]['can_delete'] = true;
1910 PMA_DBI_free_result($res);
1911 unset($row, $res);
1913 } else {
1915 // db name was given,
1916 // so we want all user specific rights for this db
1918 $user_host_condition .=
1919 ' AND `Db`'
1920 .' LIKE \'' . PMA_sqlAddslashes($dbname) . "'";
1922 $tables_to_search_for_users = array(
1923 'columns_priv',
1926 $db_rights_sqls = array();
1927 foreach ($tables_to_search_for_users as $table_search_in) {
1928 if (in_array($table_search_in, $tables)) {
1929 $db_rights_sqls[] = '
1930 SELECT DISTINCT `Table_name`
1931 FROM `mysql`.' . PMA_backquote($table_search_in)
1932 . $user_host_condition;
1936 $user_defaults = array(
1937 'Table_name' => '',
1938 'Grant_priv' => 'N',
1939 'privs' => array('USAGE'),
1940 'Column_priv' => true,
1943 // for the rights
1944 $db_rights = array();
1946 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1947 .' ORDER BY `Table_name` ASC';
1949 $db_rights_result = PMA_DBI_query($db_rights_sql);
1951 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1952 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1953 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
1955 PMA_DBI_free_result($db_rights_result);
1956 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1958 $sql_query =
1959 'SELECT `Table_name`,'
1960 .' `Table_priv`,'
1961 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
1962 .' AS \'Column_priv\''
1963 .' FROM `mysql`.`tables_priv`'
1964 . $user_host_condition
1965 .' ORDER BY `Table_name` ASC;';
1966 $res = PMA_DBI_query($sql_query);
1967 $sql_query = '';
1969 while ($row = PMA_DBI_fetch_assoc($res)) {
1970 if (isset($db_rights[$row['Table_name']])) {
1971 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
1972 } else {
1973 $db_rights[$row['Table_name']] = $row;
1976 PMA_DBI_free_result($res);
1977 unset($row, $res);
1979 ksort($db_rights);
1981 // display rows
1982 if (count($db_rights) < 1) {
1983 echo '<tr class="odd">' . "\n"
1984 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
1985 . '</tr>' . "\n";
1986 } else {
1987 $odd_row = true;
1988 $found_rows = array();
1989 //while ($row = PMA_DBI_fetch_assoc($res)) {
1990 foreach ($db_rights as $row) {
1991 $found_rows[] = (! isset($dbname)) ? $row['Db'] : $row['Table_name'];
1993 echo '<tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
1994 . ' <td>' . htmlspecialchars((! isset($dbname)) ? $row['Db'] : $row['Table_name']) . '</td>' . "\n"
1995 . ' <td><tt>' . "\n"
1996 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, TRUE)) . "\n"
1997 . ' </tt></td>' . "\n"
1998 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') || (isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ? __('Yes') : __('No')) . '</td>' . "\n"
1999 . ' <td>';
2000 if (! empty($row['Table_privs']) || ! empty ($row['Column_priv'])) {
2001 echo __('Yes');
2002 } else {
2003 echo __('No');
2005 echo '</td>' . "\n"
2006 . ' <td>';
2007 printf($link_edit, htmlspecialchars(urlencode($username)),
2008 urlencode(htmlspecialchars($hostname)),
2009 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
2010 urlencode((! isset($dbname)) ? '' : $row['Table_name']));
2011 echo '</td>' . "\n"
2012 . ' <td>';
2013 if (! empty($row['can_delete']) || isset($row['Table_name']) && strlen($row['Table_name'])) {
2014 printf($link_revoke, htmlspecialchars(urlencode($username)),
2015 urlencode(htmlspecialchars($hostname)),
2016 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
2017 urlencode((! isset($dbname)) ? '' : $row['Table_name']));
2019 echo '</td>' . "\n"
2020 . '</tr>' . "\n";
2021 $odd_row = ! $odd_row;
2022 } // end while
2024 unset($row);
2025 echo '</tbody>' . "\n"
2026 . '</table>' . "\n";
2028 if (! isset($dbname)) {
2030 // no database name was given, display select db
2032 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
2034 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
2035 if (!empty($pred_db_array)) {
2036 echo ' <select name="pred_dbname" onchange="this.form.submit();">' . "\n"
2037 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2038 foreach ($pred_db_array as $current_db) {
2039 $current_db = PMA_escape_mysql_wildcards($current_db);
2040 // cannot use array_diff() once, outside of the loop,
2041 // because the list of databases has special characters
2042 // already escaped in $found_rows,
2043 // contrary to the output of SHOW DATABASES
2044 if (empty($found_rows) || ! in_array($current_db, $found_rows)) {
2045 echo ' <option value="' . htmlspecialchars($current_db) . '">'
2046 . htmlspecialchars($current_db) . '</option>' . "\n";
2049 echo ' </select>' . "\n";
2051 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
2052 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
2053 } else {
2054 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
2055 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
2056 if ($res = @PMA_DBI_try_query('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE)) {
2057 $pred_tbl_array = array();
2058 while ($row = PMA_DBI_fetch_row($res)) {
2059 if (! isset($found_rows) || !in_array($row[0], $found_rows)) {
2060 $pred_tbl_array[] = $row[0];
2063 PMA_DBI_free_result($res);
2064 unset($res, $row);
2065 if (!empty($pred_tbl_array)) {
2066 echo ' <select name="pred_tablename" onchange="this.form.submit();">' . "\n"
2067 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2068 foreach ($pred_tbl_array as $current_table) {
2069 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
2071 echo ' </select>' . "\n";
2073 } else {
2074 unset($res);
2076 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
2078 echo '</fieldset>' . "\n";
2079 echo '<fieldset class="tblFooters">' . "\n"
2080 . ' <input type="submit" value="' . __('Go') . '" />'
2081 . '</fieldset>' . "\n"
2082 . '</form>' . "\n";
2086 // Provide a line with links to the relevant database and table
2087 if (isset($dbname) && empty($dbname_is_wildcard)) {
2088 echo '[ ' . __('Database')
2089 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
2090 . $GLOBALS['url_query'] . '&amp;db=' . $url_dbname . '&amp;reload=1">'
2091 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
2093 if (isset($tablename)) {
2094 echo ' [ ' . __('Table') . ' <a href="'
2095 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
2096 . '&amp;db=' . $url_dbname . '&amp;table=' . htmlspecialchars(urlencode($tablename))
2097 . '&amp;reload=1">' . htmlspecialchars($tablename) . ': '
2098 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
2099 . "</a> ]\n";
2101 unset($url_dbname);
2104 if (! isset($dbname) && ! $user_does_not_exists) {
2105 require_once './libraries/display_change_password.lib.php';
2107 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
2108 . PMA_generate_common_hidden_inputs('', '')
2109 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
2110 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
2111 . '<fieldset id="fieldset_change_copy_user">' . "\n"
2112 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
2113 PMA_displayLoginInformationFields('change');
2114 echo ' <fieldset>' . "\n"
2115 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2116 $choices = array(
2117 '4' => __('... keep the old one.'),
2118 '1' => __(' ... delete the old one from the user tables.'),
2119 '2' => __(' ... revoke all active privileges from the old one and delete it afterwards.'),
2120 '3' => __(' ... delete the old one from the user tables and reload the privileges afterwards.'));
2121 PMA_display_html_radio('mode', $choices, '4', true);
2122 unset($choices);
2124 echo ' </fieldset>' . "\n"
2125 . '</fieldset>' . "\n"
2126 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2127 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2128 . '</fieldset>' . "\n"
2129 . '</form>' . "\n";
2132 } elseif (isset($_REQUEST['adduser'])) {
2134 // Add a new user
2135 $GLOBALS['url_query'] .= '&amp;adduser=1';
2136 echo '<h2>' . "\n"
2137 . PMA_getIcon('b_usradd.png') . __('Add a new User') . "\n"
2138 . '</h2>' . "\n"
2139 . '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n"
2140 . PMA_generate_common_hidden_inputs('', '');
2141 PMA_displayLoginInformationFields('new');
2142 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2143 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2145 $default_choice = 0;
2146 $choices = array(
2147 '0' => _pgettext('Create none database for user', 'None'),
2148 '1' => __('Create database with same name and grant all privileges'),
2149 '2' => __('Grant all privileges on wildcard name (username\\_%)'));
2151 if ( !empty($dbname) ) {
2152 $choices['3'] = sprintf( __('Grant all privileges on database &quot;%s&quot;'), htmlspecialchars($dbname));
2153 $default_choice = 3;
2154 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2157 // 4th parameter set to true to add line breaks
2158 // 5th parameter set to false to avoid htmlspecialchars() escaping in the label
2159 // since we have some HTML in some labels
2160 PMA_display_html_radio('createdb', $choices, $default_choice, true, false);
2161 unset($choices);
2162 unset($default_choice);
2164 echo '</fieldset>' . "\n";
2165 PMA_displayPrivTable('*', '*', FALSE);
2166 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2167 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2168 . ' </fieldset>' . "\n"
2169 . '</form>' . "\n";
2170 } else {
2171 // check the privileges for a particular database.
2172 echo '<form id="usersForm"><table id="dbspecificuserrights" class="data">' . "\n"
2173 . '<caption class="tblHeaders">' . "\n"
2174 . PMA_getIcon('b_usrcheck.png')
2175 . ' ' . sprintf(__('Users having access to &quot;%s&quot;'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2176 . '</caption>' . "\n"
2177 . '<thead>' . "\n"
2178 . ' <tr><th>' . __('User') . '</th>' . "\n"
2179 . ' <th>' . __('Host') . '</th>' . "\n"
2180 . ' <th>' . __('Type') . '</th>' . "\n"
2181 . ' <th>' . __('Privileges') . '</th>' . "\n"
2182 . ' <th>' . __('Grant') . '</th>' . "\n"
2183 . ' <th>' . __('Action') . '</th>' . "\n"
2184 . ' </tr>' . "\n"
2185 . '</thead>' . "\n"
2186 . '<tbody>' . "\n";
2187 $odd_row = TRUE;
2188 unset($row, $row1, $row2);
2190 // now, we build the table...
2191 $list_of_privileges =
2192 '`User`, '
2193 . '`Host`, '
2194 . '`Select_priv`, '
2195 . '`Insert_priv`, '
2196 . '`Update_priv`, '
2197 . '`Delete_priv`, '
2198 . '`Create_priv`, '
2199 . '`Drop_priv`, '
2200 . '`Grant_priv`, '
2201 . '`Index_priv`, '
2202 . '`Alter_priv`, '
2203 . '`References_priv`, '
2204 . '`Create_tmp_table_priv`, '
2205 . '`Lock_tables_priv`, '
2206 . '`Create_view_priv`, '
2207 . '`Show_view_priv`, '
2208 . '`Create_routine_priv`, '
2209 . '`Alter_routine_priv`, '
2210 . '`Execute_priv`';
2212 $list_of_compared_privileges =
2213 '`Select_priv` = \'N\''
2214 . ' AND `Insert_priv` = \'N\''
2215 . ' AND `Update_priv` = \'N\''
2216 . ' AND `Delete_priv` = \'N\''
2217 . ' AND `Create_priv` = \'N\''
2218 . ' AND `Drop_priv` = \'N\''
2219 . ' AND `Grant_priv` = \'N\''
2220 . ' AND `References_priv` = \'N\''
2221 . ' AND `Create_tmp_table_priv` = \'N\''
2222 . ' AND `Lock_tables_priv` = \'N\''
2223 . ' AND `Create_view_priv` = \'N\''
2224 . ' AND `Show_view_priv` = \'N\''
2225 . ' AND `Create_routine_priv` = \'N\''
2226 . ' AND `Alter_routine_priv` = \'N\''
2227 . ' AND `Execute_priv` = \'N\'';
2229 if (PMA_MYSQL_INT_VERSION >= 50106) {
2230 $list_of_privileges .=
2231 ', `Event_priv`, '
2232 . '`Trigger_priv`';
2233 $list_of_compared_privileges .=
2234 ' AND `Event_priv` = \'N\''
2235 . ' AND `Trigger_priv` = \'N\'';
2238 $sql_query =
2239 '(SELECT ' . $list_of_privileges . ', `Db`'
2240 .' FROM `mysql`.`db`'
2241 .' WHERE \'' . PMA_sqlAddslashes($checkprivs) . "'"
2242 .' LIKE `Db`'
2243 .' AND NOT (' . $list_of_compared_privileges. ')) '
2244 .'UNION '
2245 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2246 .' FROM `mysql`.`user` '
2247 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2248 .' ORDER BY `User` ASC,'
2249 .' `Host` ASC,'
2250 .' `Db` ASC;';
2251 $res = PMA_DBI_query($sql_query);
2252 $row = PMA_DBI_fetch_assoc($res);
2253 if ($row) {
2254 $found = TRUE;
2257 if ($found) {
2258 while (TRUE) {
2259 // prepare the current user
2260 $current_privileges = array();
2261 $current_user = $row['User'];
2262 $current_host = $row['Host'];
2263 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2264 $current_privileges[] = $row;
2265 $row = PMA_DBI_fetch_assoc($res);
2267 echo ' <tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2268 . ' <td';
2269 if (count($current_privileges) > 1) {
2270 echo ' rowspan="' . count($current_privileges) . '"';
2272 echo '>' . (empty($current_user) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2273 . ' </td>' . "\n"
2274 . ' <td';
2275 if (count($current_privileges) > 1) {
2276 echo ' rowspan="' . count($current_privileges) . '"';
2278 echo '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2279 foreach ($current_privileges as $current) {
2280 echo ' <td>' . "\n"
2281 . ' ';
2282 if (! isset($current['Db']) || $current['Db'] == '*') {
2283 echo __('global');
2284 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2285 echo __('database-specific');
2286 } else {
2287 echo __('wildcard'), ': <tt>' . htmlspecialchars($current['Db']) . '</tt>';
2289 echo "\n"
2290 . ' </td>' . "\n"
2291 . ' <td>' . "\n"
2292 . ' <tt>' . "\n"
2293 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, TRUE)) . "\n"
2294 . ' </tt>' . "\n"
2295 . ' </td>' . "\n"
2296 . ' <td>' . "\n"
2297 . ' ' . ($current['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . "\n"
2298 . ' </td>' . "\n"
2299 . ' <td>' . "\n";
2300 printf($link_edit, urlencode($current_user),
2301 urlencode($current_host),
2302 urlencode(! isset($current['Db']) || $current['Db'] == '*' ? '' : $current['Db']),
2303 '');
2304 echo '</td>' . "\n"
2305 . ' </tr>' . "\n";
2307 if (empty($row) && empty($row1) && empty($row2)) {
2308 break;
2310 $odd_row = ! $odd_row;
2312 } else {
2313 echo ' <tr class="odd">' . "\n"
2314 . ' <td colspan="6">' . "\n"
2315 . ' ' . __('No user found.') . "\n"
2316 . ' </td>' . "\n"
2317 . ' </tr>' . "\n";
2319 echo '</tbody>' . "\n"
2320 . '</table></form>' . "\n";
2322 // Offer to create a new user for the current database
2323 echo '<fieldset id="fieldset_add_user">' . "\n"
2324 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1&amp;dbname=' . htmlspecialchars($checkprivs) .'">' . "\n"
2325 . PMA_getIcon('b_usradd.png')
2326 . ' ' . __('Add a new User') . '</a>' . "\n"
2327 . '</fieldset>' . "\n";
2329 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2333 * Displays the footer
2335 echo "\n\n";
2336 require './libraries/footer.inc.php';