Merge remote-tracking branch 'origin/QA_3_4'
[phpmyadmin.git] / server_privileges.php
blob2735de9fba743700d96b2a81b46f11449e997f2f
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
5 * @package phpMyAdmin
6 */
8 /**
11 require_once './libraries/common.inc.php';
13 /**
14 * Does the common work
16 $GLOBALS['js_include'][] = 'server_privileges.js';
17 $GLOBALS['js_include'][] = 'functions.js';
18 $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js';
19 $_add_user_error = false;
21 require './libraries/server_common.inc.php';
23 if ($GLOBALS['cfg']['AjaxEnable']) {
24 $conditional_class = 'ajax';
25 } else {
26 $conditional_class = '';
29 /**
30 * Messages are built using the message name
32 $strPrivDescAllPrivileges = __('Includes all privileges except GRANT.');
33 $strPrivDescAlter = __('Allows altering the structure of existing tables.');
34 $strPrivDescAlterRoutine = __('Allows altering and dropping stored routines.');
35 $strPrivDescCreateDb = __('Allows creating new databases and tables.');
36 $strPrivDescCreateRoutine = __('Allows creating stored routines.');
37 $strPrivDescCreateTbl = __('Allows creating new tables.');
38 $strPrivDescCreateTmpTable = __('Allows creating temporary tables.');
39 $strPrivDescCreateUser = __('Allows creating, dropping and renaming user accounts.');
40 $strPrivDescCreateView = __('Allows creating new views.');
41 $strPrivDescDelete = __('Allows deleting data.');
42 $strPrivDescDropDb = __('Allows dropping databases and tables.');
43 $strPrivDescDropTbl = __('Allows dropping tables.');
44 $strPrivDescEvent = __('Allows to set up events for the event scheduler');
45 $strPrivDescExecute = __('Allows executing stored routines.');
46 $strPrivDescFile = __('Allows importing data from and exporting data into files.');
47 $strPrivDescGrant = __('Allows adding users and privileges without reloading the privilege tables.');
48 $strPrivDescIndex = __('Allows creating and dropping indexes.');
49 $strPrivDescInsert = __('Allows inserting and replacing data.');
50 $strPrivDescLockTables = __('Allows locking tables for the current thread.');
51 $strPrivDescMaxConnections = __('Limits the number of new connections the user may open per hour.');
52 $strPrivDescMaxQuestions = __('Limits the number of queries the user may send to the server per hour.');
53 $strPrivDescMaxUpdates = __('Limits the number of commands that change any table or database the user may execute per hour.');
54 $strPrivDescMaxUserConnections = __('Limits the number of simultaneous connections the user may have.');
55 $strPrivDescProcess = __('Allows viewing processes of all users');
56 $strPrivDescReferences = __('Has no effect in this MySQL version.');
57 $strPrivDescReload = __('Allows reloading server settings and flushing the server\'s caches.');
58 $strPrivDescReplClient = __('Allows the user to ask where the slaves / masters are.');
59 $strPrivDescReplSlave = __('Needed for the replication slaves.');
60 $strPrivDescSelect = __('Allows reading data.');
61 $strPrivDescShowDb = __('Gives access to the complete list of databases.');
62 $strPrivDescShowView = __('Allows performing SHOW CREATE VIEW queries.');
63 $strPrivDescShutdown = __('Allows shutting down the server.');
64 $strPrivDescSuper = __('Allows connecting, even if maximum number of connections is reached; required for most administrative operations like setting global variables or killing threads of other users.');
65 $strPrivDescTrigger = __('Allows creating and dropping triggers');
66 $strPrivDescUpdate = __('Allows changing data.');
67 $strPrivDescUsage = __('No privileges.');
69 /**
70 * Checks if a dropdown box has been used for selecting a database / table
72 if (PMA_isValid($_REQUEST['pred_tablename'])) {
73 $tablename = $_REQUEST['pred_tablename'];
74 unset($pred_tablename);
75 } elseif (PMA_isValid($_REQUEST['tablename'])) {
76 $tablename = $_REQUEST['tablename'];
77 } else {
78 unset($tablename);
81 if (PMA_isValid($_REQUEST['pred_dbname'])) {
82 $dbname = $_REQUEST['pred_dbname'];
83 unset($pred_dbname);
84 } elseif (PMA_isValid($_REQUEST['dbname'])) {
85 $dbname = $_REQUEST['dbname'];
86 } else {
87 unset($dbname);
88 unset($tablename);
91 if (isset($dbname)) {
92 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
93 if (isset($tablename)) {
94 $db_and_table .= PMA_backquote($tablename);
95 } else {
96 $db_and_table .= '*';
98 } else {
99 $db_and_table = '*.*';
102 // check if given $dbname is a wildcard or not
103 if (isset($dbname)) {
104 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
105 if (preg_match('/(?<!\\\\)(?:_|%)/i', $dbname)) {
106 $dbname_is_wildcard = true;
107 } else {
108 $dbname_is_wildcard = false;
113 * Checks if the user is allowed to do what he tries to...
115 if (!$is_superuser) {
116 require './libraries/server_links.inc.php';
117 echo '<h2>' . "\n"
118 . PMA_getIcon('b_usrlist.png')
119 . __('Privileges') . "\n"
120 . '</h2>' . "\n";
121 PMA_Message::error(__('No Privileges'))->display();
122 require './libraries/footer.inc.php';
125 $random_n = mt_rand(0,1000000); // a random number that will be appended to the id of the user forms
128 * Escapes wildcard in a database+table specification
129 * before using it in a GRANT statement.
131 * Escaping a wildcard character in a GRANT is only accepted at the global
132 * or database level, not at table level; this is why I remove
133 * the escaping character. Internally, in mysql.tables_priv.Db there are
134 * no escaping (for example test_db) but in mysql.db you'll see test\_db
135 * for a db-specific privilege.
137 * @param string $dbname Database name
138 * @param string $tablename Table name
139 * @return string the escaped (if necessary) database.table
141 function PMA_wildcardEscapeForGrant($dbname, $tablename)
144 if (! strlen($dbname)) {
145 $db_and_table = '*.*';
146 } else {
147 if (strlen($tablename)) {
148 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
149 $db_and_table .= PMA_backquote($tablename);
150 } else {
151 $db_and_table = PMA_backquote($dbname) . '.';
152 $db_and_table .= '*';
155 return $db_and_table;
159 * Generates a condition on the user name
161 * @param string the user's initial
162 * @return string the generated condition
164 function PMA_rangeOfUsers($initial = '')
166 // strtolower() is used because the User field
167 // might be BINARY, so LIKE would be case sensitive
168 if (!empty($initial)) {
169 $ret = " WHERE `User` LIKE '" . PMA_sqlAddSlashes($initial, true) . "%'"
170 . " OR `User` LIKE '" . PMA_sqlAddSlashes(strtolower($initial), true) . "%'";
171 } else {
172 $ret = '';
174 return $ret;
175 } // end function
178 * Extracts the privilege information of a priv table row
180 * @param array $row the row
181 * @param boolean $enableHTML add <dfn> tag with tooltips
183 * @global resource $user_link the database connection
185 * @return array
187 function PMA_extractPrivInfo($row = '', $enableHTML = false)
189 $grants = array(
190 array(
191 'Select_priv',
192 'SELECT',
193 __('Allows reading data.')),
194 array(
195 'Insert_priv',
196 'INSERT',
197 __('Allows inserting and replacing data.')),
198 array(
199 'Update_priv',
200 'UPDATE',
201 __('Allows changing data.')),
202 array(
203 'Delete_priv',
204 'DELETE',
205 __('Allows deleting data.')),
206 array(
207 'Create_priv',
208 'CREATE',
209 __('Allows creating new databases and tables.')),
210 array(
211 'Drop_priv',
212 'DROP',
213 __('Allows dropping databases and tables.')),
214 array(
215 'Reload_priv',
216 'RELOAD',
217 __('Allows reloading server settings and flushing the server\'s caches.')),
218 array(
219 'Shutdown_priv',
220 'SHUTDOWN',
221 __('Allows shutting down the server.')),
222 array(
223 'Process_priv',
224 'PROCESS',
225 __('Allows viewing processes of all users')),
226 array(
227 'File_priv',
228 'FILE',
229 __('Allows importing data from and exporting data into files.')),
230 array(
231 'References_priv',
232 'REFERENCES',
233 __('Has no effect in this MySQL version.')),
234 array(
235 'Index_priv',
236 'INDEX',
237 __('Allows creating and dropping indexes.')),
238 array(
239 'Alter_priv',
240 'ALTER',
241 __('Allows altering the structure of existing tables.')),
242 array(
243 'Show_db_priv',
244 'SHOW DATABASES',
245 __('Gives access to the complete list of databases.')),
246 array(
247 'Super_priv',
248 'SUPER',
249 __('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.')),
250 array(
251 'Create_tmp_table_priv',
252 'CREATE TEMPORARY TABLES',
253 __('Allows creating temporary tables.')),
254 array(
255 'Lock_tables_priv',
256 'LOCK TABLES',
257 __('Allows locking tables for the current thread.')),
258 array(
259 'Repl_slave_priv',
260 'REPLICATION SLAVE',
261 __('Needed for the replication slaves.')),
262 array(
263 'Repl_client_priv',
264 'REPLICATION CLIENT',
265 __('Allows the user to ask where the slaves / masters are.')),
266 array(
267 'Create_view_priv',
268 'CREATE VIEW',
269 __('Allows creating new views.')),
270 array(
271 'Event_priv',
272 'EVENT',
273 __('Allows to set up events for the event scheduler')),
274 array(
275 'Trigger_priv',
276 'TRIGGER',
277 __('Allows creating and dropping triggers')),
278 // for table privs:
279 array(
280 'Create View_priv',
281 'CREATE VIEW',
282 __('Allows creating new views.')),
283 array(
284 'Show_view_priv',
285 'SHOW VIEW',
286 __('Allows performing SHOW CREATE VIEW queries.')),
287 // for table privs:
288 array(
289 'Show view_priv',
290 'SHOW VIEW',
291 __('Allows performing SHOW CREATE VIEW queries.')),
292 array(
293 'Create_routine_priv',
294 'CREATE ROUTINE',
295 __('Allows creating stored routines.')),
296 array(
297 'Alter_routine_priv',
298 'ALTER ROUTINE',
299 __('Allows altering and dropping stored routines.')),
300 array(
301 'Create_user_priv',
302 'CREATE USER',
303 __('Allows creating, dropping and renaming user accounts.')),
304 array(
305 'Execute_priv',
306 'EXECUTE',
307 __('Allows executing stored routines.')),
310 if (!empty($row) && isset($row['Table_priv'])) {
311 $row1 = PMA_DBI_fetch_single_row(
312 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
313 'ASSOC', $GLOBALS['userlink']);
314 $av_grants = explode('\',\'', substr($row1['Type'], 5, strlen($row1['Type']) - 7));
315 unset($row1);
316 $users_grants = explode(',', $row['Table_priv']);
317 foreach ($av_grants as $current_grant) {
318 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
320 unset($current_grant);
321 unset($av_grants);
322 unset($users_grants);
324 $privs = array();
325 $allPrivileges = true;
326 foreach ($grants as $current_grant) {
327 if ((!empty($row) && isset($row[$current_grant[0]]))
328 || (empty($row) && isset($GLOBALS[$current_grant[0]]))
330 if ((!empty($row) && $row[$current_grant[0]] == 'Y')
331 || (empty($row)
332 && ($GLOBALS[$current_grant[0]] == 'Y'
333 || (is_array($GLOBALS[$current_grant[0]])
334 && count($GLOBALS[$current_grant[0]]) == $GLOBALS['column_count']
335 && empty($GLOBALS[$current_grant[0] . '_none']))))
337 if ($enableHTML) {
338 $privs[] = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
339 } else {
340 $privs[] = $current_grant[1];
342 } elseif (!empty($GLOBALS[$current_grant[0]])
343 && is_array($GLOBALS[$current_grant[0]])
344 && empty($GLOBALS[$current_grant[0] . '_none'])) {
345 if ($enableHTML) {
346 $priv_string = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
347 } else {
348 $priv_string = $current_grant[1];
350 $privs[] = $priv_string . ' (`' . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
351 } else {
352 $allPrivileges = false;
356 if (empty($privs)) {
357 if ($enableHTML) {
358 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
359 } else {
360 $privs[] = 'USAGE';
362 } elseif ($allPrivileges && (! isset($GLOBALS['grant_count']) || count($privs) == $GLOBALS['grant_count'])) {
363 if ($enableHTML) {
364 $privs = array('<dfn title="' . __('Includes all privileges except GRANT.') . '">ALL PRIVILEGES</dfn>');
365 } else {
366 $privs = array('ALL PRIVILEGES');
369 return $privs;
370 } // end of the 'PMA_extractPrivInfo()' function
373 * Displays on which column(s) a table-specific privilege is granted
375 function PMA_display_column_privs($columns, $row, $name_for_select,
376 $priv_for_header, $name, $name_for_dfn, $name_for_current)
378 echo ' <div class="item" id="div_item_' . $name . '">' . "\n"
379 . ' <label for="select_' . $name . '_priv">' . "\n"
380 . ' <tt><dfn title="' . $name_for_dfn . '">'
381 . $priv_for_header . '</dfn></tt>' . "\n"
382 . ' </label><br />' . "\n"
383 . ' <select id="select_' . $name . '_priv" name="'
384 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
386 foreach ($columns as $current_column => $current_column_privileges) {
387 echo ' <option value="' . htmlspecialchars($current_column) . '"';
388 if ($row[$name_for_select] == 'Y' || $current_column_privileges[$name_for_current]) {
389 echo ' selected="selected"';
391 echo '>' . htmlspecialchars($current_column) . '</option>' . "\n";
394 echo ' </select>' . "\n"
395 . ' <i>' . __('Or') . '</i>' . "\n"
396 . ' <label for="checkbox_' . $name_for_select
397 . '_none"><input type="checkbox"'
398 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
399 . ' name="' . $name_for_select . '_none" id="checkbox_'
400 . $name_for_select . '_none" title="' . _pgettext('None privileges', 'None') . '" />'
401 . _pgettext('None privileges', 'None') . '</label>' . "\n"
402 . ' </div>' . "\n";
403 } // end function
407 * Displays the privileges form table
409 * @param string $db the database
410 * @param string $table the table
411 * @param boolean $submit wheather to display the submit button or not
412 * @global array $cfg the phpMyAdmin configuration
413 * @global ressource $user_link the database connection
415 * @return void
417 function PMA_displayPrivTable($db = '*', $table = '*', $submit = true)
419 global $random_n;
421 if ($db == '*') {
422 $table = '*';
425 if (isset($GLOBALS['username'])) {
426 $username = $GLOBALS['username'];
427 $hostname = $GLOBALS['hostname'];
428 if ($db == '*') {
429 $sql_query =
430 "SELECT * FROM `mysql`.`user`"
431 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
432 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
433 } elseif ($table == '*') {
434 $sql_query =
435 "SELECT * FROM `mysql`.`db`"
436 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
437 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
438 ." AND '" . PMA_unescape_mysql_wildcards($db) . "'"
439 ." LIKE `Db`;";
440 } else {
441 $sql_query =
442 "SELECT `Table_priv`"
443 ." FROM `mysql`.`tables_priv`"
444 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
445 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
446 ." AND `Db` = '" . PMA_unescape_mysql_wildcards($db) . "'"
447 ." AND `Table_name` = '" . PMA_sqlAddSlashes($table) . "';";
449 $row = PMA_DBI_fetch_single_row($sql_query);
451 if (empty($row)) {
452 if ($table == '*') {
453 if ($db == '*') {
454 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
455 } elseif ($table == '*') {
456 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
458 $res = PMA_DBI_query($sql_query);
459 while ($row1 = PMA_DBI_fetch_row($res)) {
460 if (substr($row1[0], 0, 4) == 'max_') {
461 $row[$row1[0]] = 0;
462 } else {
463 $row[$row1[0]] = 'N';
466 PMA_DBI_free_result($res);
467 } else {
468 $row = array('Table_priv' => '');
471 if (isset($row['Table_priv'])) {
472 $row1 = PMA_DBI_fetch_single_row(
473 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
474 'ASSOC', $GLOBALS['userlink']);
475 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
476 // the View for Create is spelled with uppercase V
477 // the view for Show is spelled with lowercase v
478 // and there is a space between the words
480 $av_grants = explode('\',\'', substr($row1['Type'], strpos($row1['Type'], '(') + 2, strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3));
481 unset($row1);
482 $users_grants = explode(',', $row['Table_priv']);
484 foreach ($av_grants as $current_grant) {
485 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
487 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
489 // get collumns
490 $res = PMA_DBI_try_query('SHOW COLUMNS FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($db)) . '.' . PMA_backquote($table) . ';');
491 $columns = array();
492 if ($res) {
493 while ($row1 = PMA_DBI_fetch_row($res)) {
494 $columns[$row1[0]] = array(
495 'Select' => false,
496 'Insert' => false,
497 'Update' => false,
498 'References' => false
501 PMA_DBI_free_result($res);
503 unset($res, $row1);
505 // t a b l e - s p e c i f i c p r i v i l e g e s
506 if (! empty($columns)) {
507 $res = PMA_DBI_query(
508 'SELECT `Column_name`, `Column_priv`'
509 .' FROM `mysql`.`columns_priv`'
510 .' WHERE `User`'
511 .' = \'' . PMA_sqlAddSlashes($username) . "'"
512 .' AND `Host`'
513 .' = \'' . PMA_sqlAddSlashes($hostname) . "'"
514 .' AND `Db`'
515 .' = \'' . PMA_sqlAddSlashes(PMA_unescape_mysql_wildcards($db)) . "'"
516 .' AND `Table_name`'
517 .' = \'' . PMA_sqlAddSlashes($table) . '\';');
519 while ($row1 = PMA_DBI_fetch_row($res)) {
520 $row1[1] = explode(',', $row1[1]);
521 foreach ($row1[1] as $current) {
522 $columns[$row1[0]][$current] = true;
525 PMA_DBI_free_result($res);
526 unset($res, $row1, $current);
528 echo '<input type="hidden" name="grant_count" value="' . count($row) . '" />' . "\n"
529 . '<input type="hidden" name="column_count" value="' . count($columns) . '" />' . "\n"
530 . '<fieldset id="fieldset_user_priv">' . "\n"
531 . ' <legend>' . __('Table-specific privileges')
532 . PMA_showHint(__('Note: MySQL privilege names are expressed in English'))
533 . '</legend>' . "\n";
537 // privs that are attached to a specific column
538 PMA_display_column_privs($columns, $row, 'Select_priv',
539 'SELECT', 'select', __('Allows reading data.'), 'Select');
541 PMA_display_column_privs($columns, $row, 'Insert_priv',
542 'INSERT', 'insert', __('Allows inserting and replacing data.'), 'Insert');
544 PMA_display_column_privs($columns, $row, 'Update_priv',
545 'UPDATE', 'update', __('Allows changing data.'), 'Update');
547 PMA_display_column_privs($columns, $row, 'References_priv',
548 'REFERENCES', 'references', __('Has no effect in this MySQL version.'), 'References');
550 // privs that are not attached to a specific column
552 echo ' <div class="item">' . "\n";
553 foreach ($row as $current_grant => $current_grant_value) {
554 if (in_array(substr($current_grant, 0, (strlen($current_grant) - 5)),
555 array('Select', 'Insert', 'Update', 'References'))) {
556 continue;
558 // make a substitution to match the messages variables;
559 // also we must substitute the grant we get, because we can't generate
560 // a form variable containing blanks (those would get changed to
561 // an underscore when receiving the POST)
562 if ($current_grant == 'Create View_priv') {
563 $tmp_current_grant = 'CreateView_priv';
564 $current_grant = 'Create_view_priv';
565 } elseif ($current_grant == 'Show view_priv') {
566 $tmp_current_grant = 'ShowView_priv';
567 $current_grant = 'Show_view_priv';
568 } else {
569 $tmp_current_grant = $current_grant;
572 echo ' <div class="item">' . "\n"
573 . ' <input type="checkbox"'
574 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
575 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
576 . '" value="Y" '
577 . ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
578 . 'title="';
580 echo (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
581 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
582 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl']) . '"/>' . "\n";
584 echo ' <label for="checkbox_' . $current_grant
585 . '"><tt><dfn title="'
586 . (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
587 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
588 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl'])
589 . '">' . strtoupper(substr($current_grant, 0, strlen($current_grant) - 5)) . '</dfn></tt></label>' . "\n"
590 . ' </div>' . "\n";
591 } // end foreach ()
593 echo ' </div>' . "\n";
594 // for Safari 2.0.2
595 echo ' <div class="clearfloat"></div>' . "\n";
597 } else {
599 // g l o b a l o r d b - s p e c i f i c
601 $privTable_names = array(0 => __('Data'), 1 => __('Structure'), 2 => __('Administration'));
603 // d a t a
604 $privTable[0] = array(
605 array('Select', 'SELECT', __('Allows reading data.')),
606 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
607 array('Update', 'UPDATE', __('Allows changing data.')),
608 array('Delete', 'DELETE', __('Allows deleting data.'))
610 if ($db == '*') {
611 $privTable[0][] = array('File', 'FILE', __('Allows importing data from and exporting data into files.'));
614 // s t r u c t u r e
615 $privTable[1] = array(
616 array('Create', 'CREATE', ($table == '*' ? __('Allows creating new databases and tables.') : __('Allows creating new tables.'))),
617 array('Alter', 'ALTER', __('Allows altering the structure of existing tables.')),
618 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
619 array('Drop', 'DROP', ($table == '*' ? __('Allows dropping databases and tables.') : __('Allows dropping tables.'))),
620 array('Create_tmp_table', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
621 array('Show_view', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
622 array('Create_routine', 'CREATE ROUTINE', __('Allows creating stored routines.')),
623 array('Alter_routine', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
624 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
626 // this one is for a db-specific priv: Create_view_priv
627 if (isset($row['Create_view_priv'])) {
628 $privTable[1][] = array('Create_view', 'CREATE VIEW', __('Allows creating new views.'));
630 // this one is for a table-specific priv: Create View_priv
631 if (isset($row['Create View_priv'])) {
632 $privTable[1][] = array('Create View', 'CREATE VIEW', __('Allows creating new views.'));
634 if (isset($row['Event_priv'])) {
635 // MySQL 5.1.6
636 $privTable[1][] = array('Event', 'EVENT', __('Allows to set up events for the event scheduler'));
637 $privTable[1][] = array('Trigger', 'TRIGGER', __('Allows creating and dropping triggers'));
640 // a d m i n i s t r a t i o n
641 $privTable[2] = array(
642 array('Grant', 'GRANT', __('Allows adding users and privileges without reloading the privilege tables.')),
644 if ($db == '*') {
645 $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.'));
646 $privTable[2][] = array('Process', 'PROCESS', __('Allows viewing processes of all users'));
647 $privTable[2][] = array('Reload', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.'));
648 $privTable[2][] = array('Shutdown', 'SHUTDOWN', __('Allows shutting down the server.'));
649 $privTable[2][] = array('Show_db', 'SHOW DATABASES', __('Gives access to the complete list of databases.'));
651 $privTable[2][] = array('Lock_tables', 'LOCK TABLES', __('Allows locking tables for the current thread.'));
652 $privTable[2][] = array('References', 'REFERENCES', __('Has no effect in this MySQL version.'));
653 if ($db == '*') {
654 $privTable[2][] = array('Repl_client', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.'));
655 $privTable[2][] = array('Repl_slave', 'REPLICATION SLAVE', __('Needed for the replication slaves.'));
656 $privTable[2][] = array('Create_user', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.'));
658 echo '<input type="hidden" name="grant_count" value="'
659 . (count($privTable[0]) + count($privTable[1]) + count($privTable[2]) - (isset($row['Grant_priv']) ? 1 : 0))
660 . '" />' . "\n"
661 . '<fieldset id="fieldset_user_global_rights">' . "\n"
662 . ' <legend>' . "\n"
663 . ' '
664 . ($db == '*'
665 ? __('Global privileges')
666 : ($table == '*'
667 ? __('Database-specific privileges')
668 : __('Table-specific privileges'))) . "\n"
669 . ' (<a href="server_privileges.php?'
670 . $GLOBALS['url_query'] . '&amp;checkall=1" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', true); return false;">'
671 . __('Check All') . '</a> /' . "\n"
672 . ' <a href="server_privileges.php?'
673 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', false); return false;">'
674 . __('Uncheck All') . '</a>)' . "\n"
675 . ' </legend>' . "\n"
676 . ' <p><small><i>' . __('Note: MySQL privilege names are expressed in English') . '</i></small></p>' . "\n";
678 // Output the Global privilege tables with checkboxes
679 foreach ($privTable as $i => $table) {
680 echo ' <fieldset>' . "\n"
681 . ' <legend>' . __($privTable_names[$i]) . '</legend>' . "\n";
682 foreach ($table as $priv) {
683 echo ' <div class="item">' . "\n"
684 . ' <input type="checkbox"'
685 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0] . '_priv"'
686 . ' value="Y" title="' . $priv[2] . '"'
687 . ((!empty($GLOBALS['checkall']) || $row[$priv[0] . '_priv'] == 'Y') ? ' checked="checked"' : '')
688 . '/>' . "\n"
689 . ' <label for="checkbox_' . $priv[0] . '_priv"><tt><dfn title="' . $priv[2] . '">'
690 . $priv[1] . '</dfn></tt></label>' . "\n"
691 . ' </div>' . "\n";
693 echo ' </fieldset>' . "\n";
696 // The "Resource limits" box is not displayed for db-specific privs
697 if ($db == '*') {
698 echo ' <fieldset>' . "\n"
699 . ' <legend>' . __('Resource limits') . '</legend>' . "\n"
700 . ' <p><small><i>' . __('Note: Setting these options to 0 (zero) removes the limit.') . '</i></small></p>' . "\n"
701 . ' <div class="item">' . "\n"
702 . ' <label for="text_max_questions"><tt><dfn title="'
703 . __('Limits the number of queries the user may send to the server per hour.') . '">MAX QUERIES PER HOUR</dfn></tt></label>' . "\n"
704 . ' <input type="text" name="max_questions" id="text_max_questions" value="'
705 . $row['max_questions'] . '" size="11" maxlength="11" title="' . __('Limits the number of queries the user may send to the server per hour.') . '" />' . "\n"
706 . ' </div>' . "\n"
707 . ' <div class="item">' . "\n"
708 . ' <label for="text_max_updates"><tt><dfn title="'
709 . __('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"
710 . ' <input type="text" name="max_updates" id="text_max_updates" value="'
711 . $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"
712 . ' </div>' . "\n"
713 . ' <div class="item">' . "\n"
714 . ' <label for="text_max_connections"><tt><dfn title="'
715 . __('Limits the number of new connections the user may open per hour.') . '">MAX CONNECTIONS PER HOUR</dfn></tt></label>' . "\n"
716 . ' <input type="text" name="max_connections" id="text_max_connections" value="'
717 . $row['max_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of new connections the user may open per hour.') . '" />' . "\n"
718 . ' </div>' . "\n"
719 . ' <div class="item">' . "\n"
720 . ' <label for="text_max_user_connections"><tt><dfn title="'
721 . __('Limits the number of simultaneous connections the user may have.') . '">MAX USER_CONNECTIONS</dfn></tt></label>' . "\n"
722 . ' <input type="text" name="max_user_connections" id="text_max_user_connections" value="'
723 . $row['max_user_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of simultaneous connections the user may have.') . '" />' . "\n"
724 . ' </div>' . "\n"
725 . ' </fieldset>' . "\n";
727 // for Safari 2.0.2
728 echo ' <div class="clearfloat"></div>' . "\n";
730 echo '</fieldset>' . "\n";
731 if ($submit) {
732 echo '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">' . "\n"
733 . ' <input type="submit" name="update_privs" value="' . __('Go') . '" />' . "\n"
734 . '</fieldset>' . "\n";
736 } // end of the 'PMA_displayPrivTable()' function
740 * Displays the fields used by the "new user" form as well as the
741 * "change login information / copy user" form.
743 * @param string $mode are we creating a new user or are we just
744 * changing one? (allowed values: 'new', 'change')
745 * @global array $cfg the phpMyAdmin configuration
746 * @global ressource $user_link the database connection
748 * @return void
750 function PMA_displayLoginInformationFields($mode = 'new')
752 // Get user/host name lengths
753 $fields_info = PMA_DBI_get_columns('mysql', 'user', null, true);
754 $username_length = 16;
755 $hostname_length = 41;
756 foreach ($fields_info as $val) {
757 if ($val['Field'] == 'User') {
758 strtok($val['Type'], '()');
759 $v = strtok('()');
760 if (is_int($v)) {
761 $username_length = $v;
763 } elseif ($val['Field'] == 'Host') {
764 strtok($val['Type'], '()');
765 $v = strtok('()');
766 if (is_int($v)) {
767 $hostname_length = $v;
771 unset($fields_info);
773 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
774 $GLOBALS['pred_username'] = 'any';
776 echo '<fieldset id="fieldset_add_user_login">' . "\n"
777 . '<legend>' . __('Login Information') . '</legend>' . "\n"
778 . '<div class="item">' . "\n"
779 . '<label for="select_pred_username">' . "\n"
780 . ' ' . __('User name') . ':' . "\n"
781 . '</label>' . "\n"
782 . '<span class="options">' . "\n"
783 . ' <select name="pred_username" id="select_pred_username" title="' . __('User name') . '"' . "\n"
784 . ' onchange="if (this.value == \'any\') { username.value = \'\'; } else if (this.value == \'userdefined\') { username.focus(); username.select(); }">' . "\n"
785 . ' <option value="any"' . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any') ? ' selected="selected"' : '') . '>' . __('Any user') . '</option>' . "\n"
786 . ' <option value="userdefined"' . ((! isset($GLOBALS['pred_username']) || $GLOBALS['pred_username'] == 'userdefined') ? ' selected="selected"' : '') . '>' . __('Use text field') . ':</option>' . "\n"
787 . ' </select>' . "\n"
788 . '</span>' . "\n"
789 . '<input type="text" name="username" maxlength="'
790 . $username_length . '" title="' . __('User name') . '"'
791 . (empty($GLOBALS['username'])
792 ? ''
793 : ' value="' . htmlspecialchars(isset($GLOBALS['new_username'])
794 ? $GLOBALS['new_username']
795 : $GLOBALS['username']) . '"')
796 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
797 . '</div>' . "\n"
798 . '<div class="item">' . "\n"
799 . '<label for="select_pred_hostname">' . "\n"
800 . ' ' . __('Host') . ':' . "\n"
801 . '</label>' . "\n"
802 . '<span class="options">' . "\n"
803 . ' <select name="pred_hostname" id="select_pred_hostname" title="' . __('Host') . '"' . "\n";
804 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
805 if (! empty($_current_user)) {
806 $thishost = str_replace("'", '', substr($_current_user, (strrpos($_current_user, '@') + 1)));
807 if ($thishost == 'localhost' || $thishost == '127.0.0.1') {
808 unset($thishost);
811 echo ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } else if (this.value == \'localhost\') { hostname.value = \'localhost\'; } '
812 . (empty($thishost) ? '' : 'else if (this.value == \'thishost\') { hostname.value = \'' . addslashes(htmlspecialchars($thishost)) . '\'; } ')
813 . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } else if (this.value == \'userdefined\') { hostname.focus(); hostname.select(); }">' . "\n";
814 unset($_current_user);
816 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
817 if (! isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
818 switch (strtolower($GLOBALS['hostname'])) {
819 case 'localhost':
820 case '127.0.0.1':
821 $GLOBALS['pred_hostname'] = 'localhost';
822 break;
823 case '%':
824 $GLOBALS['pred_hostname'] = 'any';
825 break;
826 default:
827 $GLOBALS['pred_hostname'] = 'userdefined';
828 break;
831 echo ' <option value="any"'
832 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
833 ? ' selected="selected"' : '') . '>' . __('Any host')
834 . '</option>' . "\n"
835 . ' <option value="localhost"'
836 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'localhost')
837 ? ' selected="selected"' : '') . '>' . __('Local')
838 . '</option>' . "\n";
839 if (!empty($thishost)) {
840 echo ' <option value="thishost"'
841 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'thishost')
842 ? ' selected="selected"' : '') . '>' . __('This Host')
843 . '</option>' . "\n";
845 unset($thishost);
846 echo ' <option value="hosttable"'
847 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'hosttable')
848 ? ' selected="selected"' : '') . '>' . __('Use Host Table')
849 . '</option>' . "\n"
850 . ' <option value="userdefined"'
851 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'userdefined')
852 ? ' selected="selected"' : '')
853 . '>' . __('Use text field') . ':</option>' . "\n"
854 . ' </select>' . "\n"
855 . '</span>' . "\n"
856 . '<input type="text" name="hostname" maxlength="'
857 . $hostname_length . '" value="'
858 . htmlspecialchars(isset($GLOBALS['hostname']) ? $GLOBALS['hostname'] : '')
859 . '" title="' . __('Host')
860 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
861 . PMA_showHint(__('When Host table is used, this field is ignored and values stored in Host table are used instead.'))
862 . '</div>' . "\n"
863 . '<div class="item">' . "\n"
864 . '<label for="select_pred_password">' . "\n"
865 . ' ' . __('Password') . ':' . "\n"
866 . '</label>' . "\n"
867 . '<span class="options">' . "\n"
868 . ' <select name="pred_password" id="select_pred_password" title="'
869 . __('Password') . '"' . "\n"
870 . ' onchange="if (this.value == \'none\') { pma_pw.value = \'\'; pma_pw2.value = \'\'; } else if (this.value == \'userdefined\') { pma_pw.focus(); pma_pw.select(); }">' . "\n"
871 . ($mode == 'change' ? ' <option value="keep" selected="selected">' . __('Do not change the password') . '</option>' . "\n" : '')
872 . ' <option value="none"';
873 if (isset($GLOBALS['username']) && $mode != 'change') {
874 echo ' selected="selected"';
876 echo '>' . __('No Password') . '</option>' . "\n"
877 . ' <option value="userdefined"' . (isset($GLOBALS['username']) ? '' : ' selected="selected"') . '>' . __('Use text field') . ':</option>' . "\n"
878 . ' </select>' . "\n"
879 . '</span>' . "\n"
880 . '<input type="password" id="text_pma_pw" name="pma_pw" title="' . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
881 . '</div>' . "\n"
882 . '<div class="item" id="div_element_before_generate_password">' . "\n"
883 . '<label for="text_pma_pw2">' . "\n"
884 . ' ' . __('Re-type') . ':' . "\n"
885 . '</label>' . "\n"
886 . '<span class="options">&nbsp;</span>' . "\n"
887 . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="' . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
888 . '</div>' . "\n"
889 // Generate password added here via jQuery
890 . '</fieldset>' . "\n";
891 } // end of the 'PMA_displayUserAndHostFields()' function
894 * Changes / copies a user, part I
896 if (isset($_REQUEST['change_copy'])) {
897 $user_host_condition =
898 ' WHERE `User`'
899 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
900 .' AND `Host`'
901 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
902 $row = PMA_DBI_fetch_single_row('SELECT * FROM `mysql`.`user` ' . $user_host_condition);
903 if (! $row) {
904 PMA_Message::notice(__('No user found.'))->display();
905 unset($_REQUEST['change_copy']);
906 } else {
907 extract($row, EXTR_OVERWRITE);
908 // Recent MySQL versions have the field "Password" in mysql.user,
909 // so the previous extract creates $Password but this script
910 // uses $password
911 if (! isset($password) && isset($Password)) {
912 $password = $Password;
914 $queries = array();
920 * Adds a user
921 * (Changes / copies a user, part II)
923 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
924 $sql_query = '';
925 if ($pred_username == 'any') {
926 $username = '';
928 switch ($pred_hostname) {
929 case 'any':
930 $hostname = '%';
931 break;
932 case 'localhost':
933 $hostname = 'localhost';
934 break;
935 case 'hosttable':
936 $hostname = '';
937 break;
938 case 'thishost':
939 $_user_name = PMA_DBI_fetch_value('SELECT USER()');
940 $hostname = substr($_user_name, (strrpos($_user_name, '@') + 1));
941 unset($_user_name);
942 break;
944 $sql = "SELECT '1' FROM `mysql`.`user`"
945 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
946 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
947 if (PMA_DBI_fetch_value($sql) == 1) {
948 $message = PMA_Message::error(__('The user %s already exists!'));
949 $message->addParam('[i]\'' . $username . '\'@\'' . $hostname . '\'[/i]');
950 $_REQUEST['adduser'] = true;
951 $_add_user_error = true;
952 } else {
954 $create_user_real = 'CREATE USER \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
956 $real_sql_query =
957 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
958 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
959 if ($pred_password != 'none' && $pred_password != 'keep') {
960 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
961 $real_sql_query .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
962 if (isset($create_user_real)) {
963 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
964 $create_user_real .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
966 } else {
967 if ($pred_password == 'keep' && !empty($password)) {
968 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
969 if (isset($create_user_real)) {
970 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
973 $sql_query = $real_sql_query;
974 if (isset($create_user_real)) {
975 $create_user_show = $create_user_real;
979 * @todo similar code appears twice in this script
981 if ((isset($Grant_priv) && $Grant_priv == 'Y')
982 || (isset($max_questions) || isset($max_connections)
983 || isset($max_updates) || isset($max_user_connections))) {
984 $real_sql_query .= ' WITH';
985 $sql_query .= ' WITH';
986 if (isset($Grant_priv) && $Grant_priv == 'Y') {
987 $real_sql_query .= ' GRANT OPTION';
988 $sql_query .= ' GRANT OPTION';
990 if (isset($max_questions)) {
991 // avoid negative values
992 $max_questions = max(0, (int)$max_questions);
993 $real_sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
994 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
996 if (isset($max_connections)) {
997 $max_connections = max(0, (int)$max_connections);
998 $real_sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
999 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1001 if (isset($max_updates)) {
1002 $max_updates = max(0, (int)$max_updates);
1003 $real_sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1004 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1006 if (isset($max_user_connections)) {
1007 $max_user_connections = max(0, (int)$max_user_connections);
1008 $real_sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1009 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1012 if (isset($create_user_real)) {
1013 $create_user_real .= ';';
1014 $create_user_show .= ';';
1016 $real_sql_query .= ';';
1017 $sql_query .= ';';
1018 if (empty($_REQUEST['change_copy'])) {
1019 $_error = false;
1021 if (isset($create_user_real)) {
1022 if (! PMA_DBI_try_query($create_user_real)) {
1023 $_error = true;
1025 $sql_query = $create_user_show . $sql_query;
1028 if ($_error || ! PMA_DBI_try_query($real_sql_query)) {
1029 $_REQUEST['createdb'] = false;
1030 $message = PMA_Message::rawError(PMA_DBI_getError());
1031 } else {
1032 $message = PMA_Message::success(__('You have added a new user.'));
1035 switch (PMA_ifSetOr($_REQUEST['createdb'], '0')) {
1036 case '1' :
1037 // Create database with same name and grant all privileges
1038 $q = 'CREATE DATABASE IF NOT EXISTS '
1039 . PMA_backquote(PMA_sqlAddSlashes($username)) . ';';
1040 $sql_query .= $q;
1041 if (! PMA_DBI_try_query($q)) {
1042 $message = PMA_Message::rawError(PMA_DBI_getError());
1043 break;
1048 * If we are not in an Ajax request, we can't reload navigation now
1050 if ($GLOBALS['is_ajax_request'] != true) {
1051 // this is needed in case tracking is on:
1052 $GLOBALS['db'] = $username;
1053 $GLOBALS['reload'] = true;
1054 PMA_reloadNavigation();
1057 $q = 'GRANT ALL PRIVILEGES ON '
1058 . PMA_backquote(PMA_sqlAddSlashes($username)) . '.* TO \''
1059 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1060 $sql_query .= $q;
1061 if (! PMA_DBI_try_query($q)) {
1062 $message = PMA_Message::rawError(PMA_DBI_getError());
1064 break;
1065 case '2' :
1066 // Grant all privileges on wildcard name (username\_%)
1067 $q = 'GRANT ALL PRIVILEGES ON '
1068 . PMA_backquote(PMA_sqlAddSlashes($username) . '\_%') . '.* TO \''
1069 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1070 $sql_query .= $q;
1071 if (! PMA_DBI_try_query($q)) {
1072 $message = PMA_Message::rawError(PMA_DBI_getError());
1074 break;
1075 case '3' :
1076 // Grant all privileges on the specified database to the new user
1077 $q = 'GRANT ALL PRIVILEGES ON '
1078 . PMA_backquote(PMA_sqlAddSlashes($dbname)) . '.* TO \''
1079 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1080 $sql_query .= $q;
1081 if (! PMA_DBI_try_query($q)) {
1082 $message = PMA_Message::rawError(PMA_DBI_getError());
1084 break;
1085 case '0' :
1086 default :
1087 break;
1089 } else {
1090 if (isset($create_user_real)) {
1091 $queries[] = $create_user_real;
1093 $queries[] = $real_sql_query;
1094 // we put the query containing the hidden password in
1095 // $queries_for_display, at the same position occupied
1096 // by the real query in $queries
1097 $tmp_count = count($queries);
1098 if (isset($create_user_real)) {
1099 $queries_for_display[$tmp_count - 2] = $create_user_show;
1101 $queries_for_display[$tmp_count - 1] = $sql_query;
1103 unset($res, $real_sql_query);
1109 * Changes / copies a user, part III
1111 if (isset($_REQUEST['change_copy'])) {
1112 $user_host_condition =
1113 ' WHERE `User`'
1114 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1115 .' AND `Host`'
1116 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
1117 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1118 while ($row = PMA_DBI_fetch_assoc($res)) {
1119 $queries[] =
1120 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1121 .' ON ' . PMA_backquote($row['Db']) . '.*'
1122 .' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1123 . ($row['Grant_priv'] == 'Y' ? ' WITH GRANT OPTION;' : ';');
1125 PMA_DBI_free_result($res);
1126 $res = PMA_DBI_query(
1127 'SELECT `Db`, `Table_name`, `Table_priv`'
1128 .' FROM `mysql`.`tables_priv`' . $user_host_condition,
1129 $GLOBALS['userlink'], PMA_DBI_QUERY_STORE);
1130 while ($row = PMA_DBI_fetch_assoc($res)) {
1132 $res2 = PMA_DBI_QUERY(
1133 'SELECT `Column_name`, `Column_priv`'
1134 .' FROM `mysql`.`columns_priv`'
1135 .' WHERE `User`'
1136 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1137 .' AND `Host`'
1138 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\''
1139 .' AND `Db`'
1140 .' = \'' . PMA_sqlAddSlashes($row['Db']) . "'"
1141 .' AND `Table_name`'
1142 .' = \'' . PMA_sqlAddSlashes($row['Table_name']) . "'"
1143 .';',
1144 null, PMA_DBI_QUERY_STORE);
1146 $tmp_privs1 = PMA_extractPrivInfo($row);
1147 $tmp_privs2 = array(
1148 'Select' => array(),
1149 'Insert' => array(),
1150 'Update' => array(),
1151 'References' => array()
1154 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1155 $tmp_array = explode(',', $row2['Column_priv']);
1156 if (in_array('Select', $tmp_array)) {
1157 $tmp_privs2['Select'][] = $row2['Column_name'];
1159 if (in_array('Insert', $tmp_array)) {
1160 $tmp_privs2['Insert'][] = $row2['Column_name'];
1162 if (in_array('Update', $tmp_array)) {
1163 $tmp_privs2['Update'][] = $row2['Column_name'];
1165 if (in_array('References', $tmp_array)) {
1166 $tmp_privs2['References'][] = $row2['Column_name'];
1168 unset($tmp_array);
1170 if (count($tmp_privs2['Select']) > 0 && !in_array('SELECT', $tmp_privs1)) {
1171 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1173 if (count($tmp_privs2['Insert']) > 0 && !in_array('INSERT', $tmp_privs1)) {
1174 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1176 if (count($tmp_privs2['Update']) > 0 && !in_array('UPDATE', $tmp_privs1)) {
1177 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1179 if (count($tmp_privs2['References']) > 0 && !in_array('REFERENCES', $tmp_privs1)) {
1180 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1182 unset($tmp_privs2);
1183 $queries[] =
1184 'GRANT ' . join(', ', $tmp_privs1)
1185 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1186 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1187 . (in_array('Grant', explode(',', $row['Table_priv'])) ? ' WITH GRANT OPTION;' : ';');
1193 * Updates privileges
1195 if (!empty($update_privs)) {
1196 $db_and_table = PMA_wildcardEscapeForGrant($dbname, (isset($tablename) ? $tablename : ''));
1198 $sql_query0 =
1199 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1200 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1201 if (! isset($Grant_priv) || $Grant_priv != 'Y') {
1202 $sql_query1 =
1203 'REVOKE GRANT OPTION ON ' . $db_and_table
1204 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1205 } else {
1206 $sql_query1 = '';
1209 // Should not do a GRANT USAGE for a table-specific privilege, it
1210 // causes problems later (cannot revoke it)
1211 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1212 $sql_query2 =
1213 'GRANT ' . join(', ', PMA_extractPrivInfo())
1214 . ' ON ' . $db_and_table
1215 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
1218 * @todo similar code appears twice in this script
1220 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1221 || (! isset($dbname)
1222 && (isset($max_questions) || isset($max_connections)
1223 || isset($max_updates) || isset($max_user_connections)))
1225 $sql_query2 .= 'WITH';
1226 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1227 $sql_query2 .= ' GRANT OPTION';
1229 if (isset($max_questions)) {
1230 $max_questions = max(0, (int)$max_questions);
1231 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1233 if (isset($max_connections)) {
1234 $max_connections = max(0, (int)$max_connections);
1235 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1237 if (isset($max_updates)) {
1238 $max_updates = max(0, (int)$max_updates);
1239 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1241 if (isset($max_user_connections)) {
1242 $max_user_connections = max(0, (int)$max_user_connections);
1243 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1246 $sql_query2 .= ';';
1248 if (! PMA_DBI_try_query($sql_query0)) {
1249 // This might fail when the executing user does not have ALL PRIVILEGES himself.
1250 // See https://sourceforge.net/tracker/index.php?func=detail&aid=3285929&group_id=23067&atid=377408
1251 $sql_query0 = '';
1253 if (isset($sql_query1) && !PMA_DBI_try_query($sql_query1)) {
1254 // this one may fail, too...
1255 $sql_query1 = '';
1257 if (isset($sql_query2)) {
1258 PMA_DBI_query($sql_query2);
1259 } else {
1260 $sql_query2 = '';
1262 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1263 $message = PMA_Message::success(__('You have updated the privileges for %s.'));
1264 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1269 * Revokes Privileges
1271 if (isset($_REQUEST['revokeall'])) {
1272 $db_and_table = PMA_wildcardEscapeForGrant($dbname, isset($tablename) ? $tablename : '');
1274 $sql_query0 =
1275 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1276 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1277 $sql_query1 =
1278 'REVOKE GRANT OPTION ON ' . $db_and_table
1279 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1281 PMA_DBI_query($sql_query0);
1282 if (! PMA_DBI_try_query($sql_query1)) {
1283 // this one may fail, too...
1284 $sql_query1 = '';
1286 $sql_query = $sql_query0 . ' ' . $sql_query1;
1287 $message = PMA_Message::success(__('You have revoked the privileges for %s'));
1288 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1289 if (! isset($tablename)) {
1290 unset($dbname);
1291 } else {
1292 unset($tablename);
1298 * Updates the password
1300 if (isset($_REQUEST['change_pw'])) {
1301 // similar logic in user_password.php
1302 $message = '';
1304 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1305 if ($pma_pw != $pma_pw2) {
1306 $message = PMA_Message::error(__('The passwords aren\'t the same!'));
1307 } elseif (empty($pma_pw) || empty($pma_pw2)) {
1308 $message = PMA_Message::error(__('The password is empty!'));
1310 } // end if
1312 // here $nopass could be == 1
1313 if (empty($message)) {
1315 $hashing_function = (!empty($pw_hash) && $pw_hash == 'old' ? 'OLD_' : '')
1316 . 'PASSWORD';
1318 // in $sql_query which will be displayed, hide the password
1319 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1320 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . PMA_sqlAddSlashes($pma_pw) . '\')');
1321 PMA_DBI_try_query($local_query)
1322 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, false, $err_url);
1323 $message = PMA_Message::success(__('The password for %s was changed successfully.'));
1324 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1330 * Deletes users
1331 * (Changes / copies a user, part IV)
1334 if (isset($_REQUEST['delete']) || (isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1335 if (isset($_REQUEST['change_copy'])) {
1336 $selected_usr = array($old_username . '&amp;#27;' . $old_hostname);
1337 } else {
1338 $selected_usr = $_REQUEST['selected_usr'];
1339 $queries = array();
1341 foreach ($selected_usr as $each_user) {
1342 list($this_user, $this_host) = explode('&amp;#27;', $each_user);
1343 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1344 $queries[] = 'DROP USER \'' . PMA_sqlAddSlashes($this_user) . '\'@\'' . PMA_sqlAddSlashes($this_host) . '\';';
1346 if (isset($_REQUEST['drop_users_db'])) {
1347 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1348 $GLOBALS['reload'] = true;
1350 if ($GLOBALS['is_ajax_request'] != true) {
1351 PMA_reloadNavigation();
1355 if (empty($_REQUEST['change_copy'])) {
1356 if (empty($queries)) {
1357 $message = PMA_Message::error(__('No users selected for deleting!'));
1358 } else {
1359 if ($_REQUEST['mode'] == 3) {
1360 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1361 $queries[] = 'FLUSH PRIVILEGES;';
1363 $drop_user_error = '';
1364 foreach ($queries as $sql_query) {
1365 if ($sql_query{0} != '#') {
1366 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1367 $drop_user_error .= PMA_DBI_getError() . "\n";
1371 // tracking sets this, causing the deleted db to be shown in navi
1372 unset($GLOBALS['db']);
1374 $sql_query = join("\n", $queries);
1375 if (! empty($drop_user_error)) {
1376 $message = PMA_Message::rawError($drop_user_error);
1377 } else {
1378 $message = PMA_Message::success(__('The selected users have been deleted successfully.'));
1381 unset($queries);
1387 * Changes / copies a user, part V
1389 if (isset($_REQUEST['change_copy'])) {
1390 $tmp_count = 0;
1391 foreach ($queries as $sql_query) {
1392 if ($sql_query{0} != '#') {
1393 PMA_DBI_query($sql_query);
1395 // when there is a query containing a hidden password, take it
1396 // instead of the real query sent
1397 if (isset($queries_for_display[$tmp_count])) {
1398 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1400 $tmp_count++;
1402 $message = PMA_Message::success();
1403 $sql_query = join("\n", $queries);
1408 * Reloads the privilege tables into memory
1410 if (isset($_REQUEST['flush_privileges'])) {
1411 $sql_query = 'FLUSH PRIVILEGES;';
1412 PMA_DBI_query($sql_query);
1413 $message = PMA_Message::success(__('The privileges were reloaded successfully.'));
1417 * defines some standard links
1419 $link_edit = '<a class="edit_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . str_replace($GLOBALS['url_query'], '%', '%%')
1420 . '&amp;username=%s'
1421 . '&amp;hostname=%s'
1422 . '&amp;dbname=%s'
1423 . '&amp;tablename=%s">'
1424 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1425 . '</a>';
1427 $link_revoke = '<a href="server_privileges.php?' . str_replace($GLOBALS['url_query'], '%', '%%')
1428 . '&amp;username=%s'
1429 . '&amp;hostname=%s'
1430 . '&amp;dbname=%s'
1431 . '&amp;tablename=%s'
1432 . '&amp;revokeall=1">'
1433 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1434 . '</a>';
1436 $link_export = '<a class="export_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . str_replace($GLOBALS['url_query'], '%', '%%')
1437 . '&amp;username=%s'
1438 . '&amp;hostname=%s'
1439 . '&amp;initial=%s'
1440 . '&amp;export=1">'
1441 . PMA_getIcon('b_tblexport.png', __('Export'))
1442 . '</a>';
1445 * If we are in an Ajax request for Create User/Edit User/Revoke User/Flush Privileges,
1446 * show $message and exit.
1448 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'])) {
1450 if (isset($sql_query)) {
1451 $extra_data['sql_query'] = PMA_showMessage(NULL, $sql_query);
1454 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
1456 * generate html on the fly for the new user that was just created.
1458 $new_user_string = '<tr>'."\n"
1459 .'<td> <input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_" value="' . htmlspecialchars($username) . '&amp;#27;' . htmlspecialchars($hostname) . '" /> </td>'."\n"
1460 .'<td><label for="checkbox_sel_users_">' . (empty($username) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($username) ) . '</label></td>' . "\n"
1461 .'<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
1462 $new_user_string .= '<td>';
1464 if (!empty($password) || isset($pma_pw)) {
1465 $new_user_string .= __('Yes');
1466 } else {
1467 $new_user_string .= '<span style="color: #FF0000">' . __('No') . '</span>';
1470 $new_user_string .= '</td>'."\n";
1471 $new_user_string .= '<td><tt>' . join(', ', PMA_extractPrivInfo('', true)) . '</tt></td>'; //Fill in privileges here
1472 $new_user_string .= '<td>';
1474 if ((isset($Grant_priv) && $Grant_priv == 'Y')) {
1475 $new_user_string .= __('Yes');
1476 } else {
1477 $new_user_string .= __('No');
1480 $new_user_string .='</td>';
1482 $new_user_string .= '<td>'.sprintf($link_edit, urlencode($username), urlencode($hostname), '', '' ).'</td>'."\n";
1483 $new_user_string .= '<td>'.sprintf($link_export, urlencode($username), urlencode($hostname), (isset($initial) ? $initial : '')).'</td>'."\n";
1485 $new_user_string .= '</tr>';
1487 $extra_data['new_user_string'] = $new_user_string;
1490 * Generate the string for this alphabet's initial, to update the user
1491 * pagination
1493 $new_user_initial = strtoupper(substr($username, 0, 1));
1494 $new_user_initial_string = '<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . $new_user_initial
1495 .'">' . $new_user_initial . '</a>';
1496 $extra_data['new_user_initial'] = $new_user_initial;
1497 $extra_data['new_user_initial_string'] = $new_user_initial_string;
1500 if (isset($update_privs)) {
1501 $extra_data['db_specific_privs'] = false;
1502 if (isset($dbname_is_wildcard)) {
1503 $extra_data['db_specific_privs'] = !$dbname_is_wildcard;
1505 $new_privileges = join(', ', PMA_extractPrivInfo('', true));
1507 $extra_data['new_privileges'] = $new_privileges;
1510 if ($message instanceof PMA_Message) {
1511 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
1516 * Displays the links
1518 if (isset($viewing_mode) && $viewing_mode == 'db') {
1519 $db = $checkprivs;
1520 $url_query .= '&amp;goto=db_operations.php';
1522 // Gets the database structure
1523 $sub_part = '_structure';
1524 require './libraries/db_info.inc.php';
1525 echo "\n";
1526 } else {
1527 require './libraries/server_links.inc.php';
1532 * Displays the page
1535 // export user definition
1536 if (isset($_REQUEST['export'])) {
1537 echo '<h2>' . __('User') . ' \'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'</h2>';
1538 echo '<textarea cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1539 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddSlashes($username) . "'@'" . PMA_sqlAddSlashes($hostname) . "'");
1540 foreach ($grants as $one_grant) {
1541 echo $one_grant . ";\n\n";
1543 echo '</textarea>';
1544 unset($username, $hostname, $grants, $one_grant);
1545 if ($GLOBALS['is_ajax_request']) {
1546 exit;
1550 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs))) {
1551 if (! isset($username)) {
1552 // No username is given --> display the overview
1553 echo '<h2>' . "\n"
1554 . PMA_getIcon('b_usrlist.png')
1555 . __('User overview') . "\n"
1556 . '</h2>' . "\n";
1558 $sql_query =
1559 'SELECT *,' .
1560 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1561 ' FROM `mysql`.`user`';
1563 $sql_query .= (isset($initial) ? PMA_rangeOfUsers($initial) : '');
1565 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1566 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1568 if (! $res) {
1569 // the query failed! This may have two reasons:
1570 // - the user does not have enough privileges
1571 // - the privilege tables use a structure of an earlier version.
1572 // so let's try a more simple query
1574 $sql_query = 'SELECT * FROM `mysql`.`user`';
1575 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1577 if (!$res) {
1578 PMA_Message::error(__('No Privileges'))->display();
1579 PMA_DBI_free_result($res);
1580 unset($res);
1581 } else {
1582 // This message is hardcoded because I will replace it by
1583 // a automatic repair feature soon.
1584 $raw = 'Your privilege table structure seems to be older than'
1585 . ' this MySQL version!<br />'
1586 . 'Please run the <tt>mysql_upgrade</tt> command'
1587 . '(<tt>mysql_fix_privilege_tables</tt> on older systems)'
1588 . ' that should be included in your MySQL server distribution'
1589 . ' to solve this problem!';
1590 PMA_Message::rawError($raw)->display();
1592 } else {
1594 // we also want users not in table `user` but in other table
1595 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1597 $tables_to_search_for_users = array(
1598 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1601 $db_rights_sqls = array();
1602 foreach ($tables_to_search_for_users as $table_search_in) {
1603 if (in_array($table_search_in, $tables)) {
1604 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ? PMA_rangeOfUsers($initial) : '');
1608 $user_defaults = array(
1609 'User' => '',
1610 'Host' => '%',
1611 'Password' => '?',
1612 'Grant_priv' => 'N',
1613 'privs' => array('USAGE'),
1616 // for all initials, even non A-Z
1617 $array_initials = array();
1618 // for the rights
1619 $db_rights = array();
1621 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1622 .' ORDER BY `User` ASC, `Host` ASC';
1624 $db_rights_result = PMA_DBI_query($db_rights_sql);
1626 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1627 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1628 $db_rights[$db_rights_row['User']][$db_rights_row['Host']] =
1629 $db_rights_row;
1631 PMA_DBI_free_result($db_rights_result);
1632 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1633 ksort($db_rights);
1636 * Displays the initials
1637 * In an Ajax request, we don't need to show this. Also not necassary if there is less than 20 privileges
1640 if ($GLOBALS['is_ajax_request'] != true && PMA_DBI_num_rows($res) > 20 ) {
1642 // initialize to false the letters A-Z
1643 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++) {
1644 if (! isset($array_initials[chr($letter_counter + 64)])) {
1645 $array_initials[chr($letter_counter + 64)] = false;
1649 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE);
1650 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1651 $array_initials[$tmp_initial] = true;
1654 // Display the initials, which can be any characters, not
1655 // just letters. For letters A-Z, we add the non-used letters
1656 // as greyed out.
1658 uksort($array_initials, "strnatcasecmp");
1660 echo '<table id="initials_table" class="' . $conditional_class . '" <cellspacing="5"><tr>';
1661 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1662 if ($initial_was_found) {
1663 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1664 } else {
1665 echo '<td>' . $tmp_initial . '</td>';
1668 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;showall=1" class="nowrap">[' . __('Show all') . ']</a></td>' . "\n";
1669 echo '</tr></table>';
1673 * Display the user overview
1674 * (if less than 50 users, display them immediately)
1677 if (isset($initial) || isset($showall) || PMA_DBI_num_rows($res) < 50) {
1679 while ($row = PMA_DBI_fetch_assoc($res)) {
1680 $row['privs'] = PMA_extractPrivInfo($row, true);
1681 $db_rights[$row['User']][$row['Host']] = $row;
1683 @PMA_DBI_free_result($res);
1684 unset($res);
1686 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1687 . PMA_generate_common_hidden_inputs('', '')
1688 . ' <table id="tableuserrights" class="data">' . "\n"
1689 . ' <thead>' . "\n"
1690 . ' <tr><th></th>' . "\n"
1691 . ' <th>' . __('User') . '</th>' . "\n"
1692 . ' <th>' . __('Host') . '</th>' . "\n"
1693 . ' <th>' . __('Password') . '</th>' . "\n"
1694 . ' <th>' . __('Global privileges') . ' '
1695 . PMA_showHint(__('Note: MySQL privilege names are expressed in English')) . '</th>' . "\n"
1696 . ' <th>' . __('Grant') . '</th>' . "\n"
1697 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1698 echo ' </tr>' . "\n";
1699 echo ' </thead>' . "\n";
1700 echo ' <tbody>' . "\n";
1701 $odd_row = true;
1702 $index_checkbox = -1;
1703 foreach ($db_rights as $user) {
1704 $index_checkbox++;
1705 ksort($user);
1706 foreach ($user as $host) {
1707 $index_checkbox++;
1708 echo ' <tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
1709 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1710 . $index_checkbox . '" value="'
1711 . htmlspecialchars($host['User'] . '&amp;#27;' . $host['Host'])
1712 . '"'
1713 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
1714 . ' /></td>' . "\n"
1715 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1716 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1717 echo ' <td>';
1718 switch ($host['Password']) {
1719 case 'Y':
1720 echo __('Yes');
1721 break;
1722 case 'N':
1723 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1724 break;
1725 // this happens if this is a definition not coming from mysql.user
1726 default:
1727 echo '--'; // in future version, replace by "not present"
1728 break;
1729 } // end switch
1730 echo '</td>' . "\n"
1731 . ' <td><tt>' . "\n"
1732 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1733 . ' </tt></td>' . "\n"
1734 . ' <td>' . ($host['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . '</td>' . "\n"
1735 . ' <td align="center">';
1736 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1737 echo '</td>';
1738 echo '<td align="center">';
1739 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ? $initial : ''));
1740 echo '</td>';
1741 echo '</tr>';
1742 $odd_row = ! $odd_row;
1746 unset($user, $host, $odd_row);
1747 echo ' </tbody></table>' . "\n"
1748 .'<img class="selectallarrow"'
1749 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1750 .' width="38" height="22"'
1751 .' alt="' . __('With selected:') . '" />' . "\n"
1752 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;checkall=1"'
1753 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1754 . __('Check All') . '</a>' . "\n"
1755 .'/' . "\n"
1756 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1757 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1758 . __('Uncheck All') . '</a>' . "\n";
1760 // add/delete user fieldset
1761 echo ' <fieldset id="fieldset_add_user">' . "\n"
1762 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1763 . PMA_getIcon('b_usradd.png')
1764 . ' ' . __('Add user') . '</a>' . "\n"
1765 . ' </fieldset>' . "\n"
1766 . ' <fieldset id="fieldset_delete_user">'
1767 . ' <legend>' . "\n"
1768 . PMA_getIcon('b_usrdrop.png')
1769 . ' ' . __('Remove selected users') . '' . "\n"
1770 . ' </legend>' . "\n"
1771 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1772 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1773 . ' <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"
1774 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1775 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1776 . ' </label>' . "\n"
1777 . ' </fieldset>' . "\n"
1778 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1779 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" class="' . $conditional_class . '"/>' . "\n"
1780 . ' </fieldset>' . "\n"
1781 . '</form>' . "\n";
1782 } else {
1784 unset ($row);
1785 echo ' <fieldset id="fieldset_add_user">' . "\n"
1786 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1787 . PMA_getIcon('b_usradd.png')
1788 . ' ' . __('Add user') . '</a>' . "\n"
1789 . ' </fieldset>' . "\n";
1790 } // end if (display overview)
1792 if ($GLOBALS['is_ajax_request']) {
1793 exit;
1796 $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);
1797 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;flush_privileges=1" id="reload_privileges_anchor" class="' . $conditional_class . '">', false);
1798 $flushnote->addParam('</a>', false);
1799 $flushnote->display();
1803 } else {
1805 // A user was selected -> display the user's properties
1807 // In an Ajax request, prevent cached values from showing
1808 if ($GLOBALS['is_ajax_request'] == true) {
1809 header('Cache-Control: no-cache');
1812 echo '<h2>' . "\n"
1813 . PMA_getIcon('b_usredit.png')
1814 . __('Edit Privileges') . ': '
1815 . __('User') ;
1817 if (isset($dbname)) {
1818 echo ' <i><a href="server_privileges.php?'
1819 . $GLOBALS['url_query'] . '&amp;username=' . htmlspecialchars(urlencode($username))
1820 . '&amp;hostname=' . htmlspecialchars(urlencode($hostname)) . '&amp;dbname=&amp;tablename=">\''
1821 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1822 . '\'</a></i>' . "\n";
1823 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
1825 echo ' - ' . ($dbname_is_wildcard ? __('Databases') : __('Database') );
1826 if (isset($tablename)) {
1827 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
1828 . '&amp;username=' . htmlspecialchars(urlencode($username)) . '&amp;hostname=' . htmlspecialchars(urlencode($hostname))
1829 . '&amp;dbname=' . htmlspecialchars($url_dbname) . '&amp;tablename=">' . htmlspecialchars($dbname) . '</a></i>';
1830 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
1831 } else {
1832 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
1835 } else {
1836 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1837 . '\'</i>' . "\n";
1840 echo '</h2>' . "\n";
1843 $sql = "SELECT '1' FROM `mysql`.`user`"
1844 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
1845 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
1846 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
1847 unset($sql);
1848 if ($user_does_not_exists) {
1849 PMA_Message::error(__('The selected user was not found in the privilege table.'))->display();
1850 PMA_displayLoginInformationFields();
1851 //require './libraries/footer.inc.php';
1854 echo '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n";
1855 $_params = array(
1856 'username' => $username,
1857 'hostname' => $hostname,
1859 if (isset($dbname)) {
1860 $_params['dbname'] = $dbname;
1861 if (isset($tablename)) {
1862 $_params['tablename'] = $tablename;
1865 echo PMA_generate_common_hidden_inputs($_params);
1867 PMA_displayPrivTable(PMA_ifSetOr($dbname, '*', 'length'),
1868 PMA_ifSetOr($tablename, '*', 'length'));
1870 echo '</form>' . "\n";
1872 if (! isset($tablename) && empty($dbname_is_wildcard)) {
1874 // no table name was given, display all table specific rights
1875 // but only if $dbname contains no wildcards
1877 // table header
1878 echo '<form action="server_privileges.php" method="post">' . "\n"
1879 . PMA_generate_common_hidden_inputs('', '')
1880 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
1881 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1882 . '<fieldset>' . "\n"
1883 . '<legend>' . (! isset($dbname) ? __('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
1884 . '<table class="data">' . "\n"
1885 . '<thead>' . "\n"
1886 . '<tr><th>' . (! isset($dbname) ? __('Database') : __('Table')) . '</th>' . "\n"
1887 . ' <th>' . __('Privileges') . '</th>' . "\n"
1888 . ' <th>' . __('Grant') . '</th>' . "\n"
1889 . ' <th>' . (! isset($dbname) ? __('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
1890 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
1891 . '</tr>' . "\n"
1892 . '</thead>' . "\n"
1893 . '<tbody>' . "\n";
1895 $user_host_condition =
1896 ' WHERE `User`'
1897 . ' = \'' . PMA_sqlAddSlashes($username) . "'"
1898 . ' AND `Host`'
1899 . ' = \'' . PMA_sqlAddSlashes($hostname) . "'";
1901 // table body
1902 // get data
1904 // we also want privielgs for this user not in table `db` but in other table
1905 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1906 if (! isset($dbname)) {
1908 // no db name given, so we want all privs for the given user
1910 $tables_to_search_for_users = array(
1911 'tables_priv', 'columns_priv',
1914 $db_rights_sqls = array();
1915 foreach ($tables_to_search_for_users as $table_search_in) {
1916 if (in_array($table_search_in, $tables)) {
1917 $db_rights_sqls[] = '
1918 SELECT DISTINCT `Db`
1919 FROM `mysql`.' . PMA_backquote($table_search_in)
1920 . $user_host_condition;
1924 $user_defaults = array(
1925 'Db' => '',
1926 'Grant_priv' => 'N',
1927 'privs' => array('USAGE'),
1928 'Table_privs' => true,
1931 // for the rights
1932 $db_rights = array();
1934 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1935 .' ORDER BY `Db` ASC';
1937 $db_rights_result = PMA_DBI_query($db_rights_sql);
1939 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1940 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1941 // only Db names in the table `mysql`.`db` uses wildcards
1942 // as we are in the db specific rights display we want
1943 // all db names escaped, also from other sources
1944 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
1945 $db_rights_row['Db']);
1946 $db_rights[$db_rights_row['Db']] = $db_rights_row;
1949 PMA_DBI_free_result($db_rights_result);
1950 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1952 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
1953 $res = PMA_DBI_query($sql_query);
1954 $sql_query = '';
1956 while ($row = PMA_DBI_fetch_assoc($res)) {
1957 if (isset($db_rights[$row['Db']])) {
1958 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
1959 } else {
1960 $db_rights[$row['Db']] = $row;
1962 // there are db specific rights for this user
1963 // so we can drop this db rights
1964 $db_rights[$row['Db']]['can_delete'] = true;
1966 PMA_DBI_free_result($res);
1967 unset($row, $res);
1969 } else {
1971 // db name was given,
1972 // so we want all user specific rights for this db
1974 $user_host_condition .=
1975 ' AND `Db`'
1976 .' LIKE \'' . PMA_sqlAddSlashes($dbname, true) . "'";
1978 $tables_to_search_for_users = array(
1979 'columns_priv',
1982 $db_rights_sqls = array();
1983 foreach ($tables_to_search_for_users as $table_search_in) {
1984 if (in_array($table_search_in, $tables)) {
1985 $db_rights_sqls[] = '
1986 SELECT DISTINCT `Table_name`
1987 FROM `mysql`.' . PMA_backquote($table_search_in)
1988 . $user_host_condition;
1992 $user_defaults = array(
1993 'Table_name' => '',
1994 'Grant_priv' => 'N',
1995 'privs' => array('USAGE'),
1996 'Column_priv' => true,
1999 // for the rights
2000 $db_rights = array();
2002 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
2003 .' ORDER BY `Table_name` ASC';
2005 $db_rights_result = PMA_DBI_query($db_rights_sql);
2007 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
2008 $db_rights_row = array_merge($user_defaults, $db_rights_row);
2009 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
2011 PMA_DBI_free_result($db_rights_result);
2012 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
2014 $sql_query =
2015 'SELECT `Table_name`,'
2016 .' `Table_priv`,'
2017 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
2018 .' AS \'Column_priv\''
2019 .' FROM `mysql`.`tables_priv`'
2020 . $user_host_condition
2021 .' ORDER BY `Table_name` ASC;';
2022 $res = PMA_DBI_query($sql_query);
2023 $sql_query = '';
2025 while ($row = PMA_DBI_fetch_assoc($res)) {
2026 if (isset($db_rights[$row['Table_name']])) {
2027 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
2028 } else {
2029 $db_rights[$row['Table_name']] = $row;
2032 PMA_DBI_free_result($res);
2033 unset($row, $res);
2035 ksort($db_rights);
2037 // display rows
2038 if (count($db_rights) < 1) {
2039 echo '<tr class="odd">' . "\n"
2040 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
2041 . '</tr>' . "\n";
2042 } else {
2043 $odd_row = true;
2044 $found_rows = array();
2045 //while ($row = PMA_DBI_fetch_assoc($res)) {
2046 foreach ($db_rights as $row) {
2047 $found_rows[] = (! isset($dbname)) ? $row['Db'] : $row['Table_name'];
2049 echo '<tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2050 . ' <td>' . htmlspecialchars((! isset($dbname)) ? $row['Db'] : $row['Table_name']) . '</td>' . "\n"
2051 . ' <td><tt>' . "\n"
2052 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, true)) . "\n"
2053 . ' </tt></td>' . "\n"
2054 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') || (isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ? __('Yes') : __('No')) . '</td>' . "\n"
2055 . ' <td>';
2056 if (! empty($row['Table_privs']) || ! empty ($row['Column_priv'])) {
2057 echo __('Yes');
2058 } else {
2059 echo __('No');
2061 echo '</td>' . "\n"
2062 . ' <td>';
2063 printf($link_edit, htmlspecialchars(urlencode($username)),
2064 urlencode(htmlspecialchars($hostname)),
2065 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
2066 urlencode((! isset($dbname)) ? '' : $row['Table_name']));
2067 echo '</td>' . "\n"
2068 . ' <td>';
2069 if (! empty($row['can_delete']) || isset($row['Table_name']) && strlen($row['Table_name'])) {
2070 printf($link_revoke, htmlspecialchars(urlencode($username)),
2071 urlencode(htmlspecialchars($hostname)),
2072 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
2073 urlencode((! isset($dbname)) ? '' : $row['Table_name']));
2075 echo '</td>' . "\n"
2076 . '</tr>' . "\n";
2077 $odd_row = ! $odd_row;
2078 } // end while
2080 unset($row);
2081 echo '</tbody>' . "\n"
2082 . '</table>' . "\n";
2084 if (! isset($dbname)) {
2086 // no database name was given, display select db
2088 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
2090 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
2091 if (!empty($pred_db_array)) {
2092 echo ' <select name="pred_dbname" class="autosubmit">' . "\n"
2093 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2094 foreach ($pred_db_array as $current_db) {
2095 $current_db = PMA_escape_mysql_wildcards($current_db);
2096 // cannot use array_diff() once, outside of the loop,
2097 // because the list of databases has special characters
2098 // already escaped in $found_rows,
2099 // contrary to the output of SHOW DATABASES
2100 if (empty($found_rows) || ! in_array($current_db, $found_rows)) {
2101 echo ' <option value="' . htmlspecialchars($current_db) . '">'
2102 . htmlspecialchars($current_db) . '</option>' . "\n";
2105 echo ' </select>' . "\n";
2107 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
2108 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
2109 } else {
2110 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
2111 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
2112 if ($res = @PMA_DBI_try_query('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE)) {
2113 $pred_tbl_array = array();
2114 while ($row = PMA_DBI_fetch_row($res)) {
2115 if (! isset($found_rows) || !in_array($row[0], $found_rows)) {
2116 $pred_tbl_array[] = $row[0];
2119 PMA_DBI_free_result($res);
2120 unset($res, $row);
2121 if (!empty($pred_tbl_array)) {
2122 echo ' <select name="pred_tablename" class="autosubmit">' . "\n"
2123 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2124 foreach ($pred_tbl_array as $current_table) {
2125 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
2127 echo ' </select>' . "\n";
2129 } else {
2130 unset($res);
2132 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
2134 echo '</fieldset>' . "\n";
2135 echo '<fieldset class="tblFooters">' . "\n"
2136 . ' <input type="submit" value="' . __('Go') . '" />'
2137 . '</fieldset>' . "\n"
2138 . '</form>' . "\n";
2142 // Provide a line with links to the relevant database and table
2143 if (isset($dbname) && empty($dbname_is_wildcard)) {
2144 echo '[ ' . __('Database')
2145 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
2146 . $GLOBALS['url_query'] . '&amp;db=' . $url_dbname . '&amp;reload=1">'
2147 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
2149 if (isset($tablename)) {
2150 echo ' [ ' . __('Table') . ' <a href="'
2151 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
2152 . '&amp;db=' . $url_dbname . '&amp;table=' . htmlspecialchars(urlencode($tablename))
2153 . '&amp;reload=1">' . htmlspecialchars($tablename) . ': '
2154 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
2155 . "</a> ]\n";
2157 unset($url_dbname);
2160 if (! isset($dbname) && ! $user_does_not_exists) {
2161 require_once './libraries/display_change_password.lib.php';
2163 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
2164 . PMA_generate_common_hidden_inputs('', '')
2165 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
2166 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
2167 . '<fieldset id="fieldset_change_copy_user">' . "\n"
2168 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
2169 PMA_displayLoginInformationFields('change');
2170 echo ' <fieldset>' . "\n"
2171 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2172 $choices = array(
2173 '4' => __('... keep the old one.'),
2174 '1' => __('... delete the old one from the user tables.'),
2175 '2' => __('... revoke all active privileges from the old one and delete it afterwards.'),
2176 '3' => __('... delete the old one from the user tables and reload the privileges afterwards.'));
2177 PMA_display_html_radio('mode', $choices, '4', true);
2178 unset($choices);
2180 echo ' </fieldset>' . "\n"
2181 . '</fieldset>' . "\n"
2182 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2183 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2184 . '</fieldset>' . "\n"
2185 . '</form>' . "\n";
2188 } elseif (isset($_REQUEST['adduser'])) {
2190 // Add user
2191 $GLOBALS['url_query'] .= '&amp;adduser=1';
2192 echo '<h2>' . "\n"
2193 . PMA_getIcon('b_usradd.png') . __('Add user') . "\n"
2194 . '</h2>' . "\n"
2195 . '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n"
2196 . PMA_generate_common_hidden_inputs('', '');
2197 PMA_displayLoginInformationFields('new');
2198 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2199 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2201 $default_choice = 0;
2202 $choices = array(
2203 '0' => _pgettext('Create none database for user', 'None'),
2204 '1' => __('Create database with same name and grant all privileges'),
2205 '2' => __('Grant all privileges on wildcard name (username\\_%)'));
2207 if (! empty($dbname) ) {
2208 $choices['3'] = sprintf( __('Grant all privileges on database &quot;%s&quot;'), htmlspecialchars($dbname));
2209 $default_choice = 3;
2210 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2213 // 4th parameter set to true to add line breaks
2214 // 5th parameter set to false to avoid htmlspecialchars() escaping in the label
2215 // since we have some HTML in some labels
2216 PMA_display_html_radio('createdb', $choices, $default_choice, true, false);
2217 unset($choices);
2218 unset($default_choice);
2220 echo '</fieldset>' . "\n";
2221 PMA_displayPrivTable('*', '*', false);
2222 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2223 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2224 . ' </fieldset>' . "\n"
2225 . '</form>' . "\n";
2226 } else {
2227 // check the privileges for a particular database.
2228 $user_form = '<form id="usersForm"><table id="dbspecificuserrights" class="data">' . "\n"
2229 . '<caption class="tblHeaders">' . "\n"
2230 . PMA_getIcon('b_usrcheck.png')
2231 . ' ' . sprintf(__('Users having access to &quot;%s&quot;'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2232 . '</caption>' . "\n"
2233 . '<thead>' . "\n"
2234 . ' <tr><th>' . __('User') . '</th>' . "\n"
2235 . ' <th>' . __('Host') . '</th>' . "\n"
2236 . ' <th>' . __('Type') . '</th>' . "\n"
2237 . ' <th>' . __('Privileges') . '</th>' . "\n"
2238 . ' <th>' . __('Grant') . '</th>' . "\n"
2239 . ' <th>' . __('Action') . '</th>' . "\n"
2240 . ' </tr>' . "\n"
2241 . '</thead>' . "\n"
2242 . '<tbody>' . "\n";
2243 $odd_row = true;
2244 unset($row, $row1, $row2);
2246 // now, we build the table...
2247 $list_of_privileges =
2248 '`User`, '
2249 . '`Host`, '
2250 . '`Select_priv`, '
2251 . '`Insert_priv`, '
2252 . '`Update_priv`, '
2253 . '`Delete_priv`, '
2254 . '`Create_priv`, '
2255 . '`Drop_priv`, '
2256 . '`Grant_priv`, '
2257 . '`Index_priv`, '
2258 . '`Alter_priv`, '
2259 . '`References_priv`, '
2260 . '`Create_tmp_table_priv`, '
2261 . '`Lock_tables_priv`, '
2262 . '`Create_view_priv`, '
2263 . '`Show_view_priv`, '
2264 . '`Create_routine_priv`, '
2265 . '`Alter_routine_priv`, '
2266 . '`Execute_priv`';
2268 $list_of_compared_privileges =
2269 '`Select_priv` = \'N\''
2270 . ' AND `Insert_priv` = \'N\''
2271 . ' AND `Update_priv` = \'N\''
2272 . ' AND `Delete_priv` = \'N\''
2273 . ' AND `Create_priv` = \'N\''
2274 . ' AND `Drop_priv` = \'N\''
2275 . ' AND `Grant_priv` = \'N\''
2276 . ' AND `References_priv` = \'N\''
2277 . ' AND `Create_tmp_table_priv` = \'N\''
2278 . ' AND `Lock_tables_priv` = \'N\''
2279 . ' AND `Create_view_priv` = \'N\''
2280 . ' AND `Show_view_priv` = \'N\''
2281 . ' AND `Create_routine_priv` = \'N\''
2282 . ' AND `Alter_routine_priv` = \'N\''
2283 . ' AND `Execute_priv` = \'N\'';
2285 if (PMA_MYSQL_INT_VERSION >= 50106) {
2286 $list_of_privileges .=
2287 ', `Event_priv`, '
2288 . '`Trigger_priv`';
2289 $list_of_compared_privileges .=
2290 ' AND `Event_priv` = \'N\''
2291 . ' AND `Trigger_priv` = \'N\'';
2294 $sql_query =
2295 '(SELECT ' . $list_of_privileges . ', `Db`'
2296 .' FROM `mysql`.`db`'
2297 .' WHERE \'' . PMA_sqlAddSlashes($checkprivs) . "'"
2298 .' LIKE `Db`'
2299 .' AND NOT (' . $list_of_compared_privileges. ')) '
2300 .'UNION '
2301 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2302 .' FROM `mysql`.`user` '
2303 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2304 .' ORDER BY `User` ASC,'
2305 .' `Host` ASC,'
2306 .' `Db` ASC;';
2307 $res = PMA_DBI_query($sql_query);
2308 $row = PMA_DBI_fetch_assoc($res);
2309 if ($row) {
2310 $found = true;
2313 if ($found) {
2314 while (true) {
2315 // prepare the current user
2316 $current_privileges = array();
2317 $current_user = $row['User'];
2318 $current_host = $row['Host'];
2319 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2320 $current_privileges[] = $row;
2321 $row = PMA_DBI_fetch_assoc($res);
2323 $user_form .= ' <tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2324 . ' <td';
2325 if (count($current_privileges) > 1) {
2326 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2328 $user_form .= '>' . (empty($current_user) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2329 . ' </td>' . "\n"
2330 . ' <td';
2331 if (count($current_privileges) > 1) {
2332 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2334 $user_form .= '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2335 foreach ($current_privileges as $current) {
2336 $user_form .= ' <td>' . "\n"
2337 . ' ';
2338 if (! isset($current['Db']) || $current['Db'] == '*') {
2339 $user_form .= __('global');
2340 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2341 $user_form .= __('database-specific');
2342 } else {
2343 $user_form .= __('wildcard'). ': <tt>' . htmlspecialchars($current['Db']) . '</tt>';
2345 $user_form .= "\n"
2346 . ' </td>' . "\n"
2347 . ' <td>' . "\n"
2348 . ' <tt>' . "\n"
2349 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, true)) . "\n"
2350 . ' </tt>' . "\n"
2351 . ' </td>' . "\n"
2352 . ' <td>' . "\n"
2353 . ' ' . ($current['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . "\n"
2354 . ' </td>' . "\n"
2355 . ' <td>' . "\n";
2356 $user_form .= sprintf(
2357 $link_edit,
2358 urlencode($current_user),
2359 urlencode($current_host),
2360 urlencode(! isset($current['Db']) || $current['Db'] == '*' ? '' : $current['Db']),
2361 '');
2362 $user_form .= '</td>' . "\n"
2363 . ' </tr>' . "\n";
2365 if (empty($row) && empty($row1) && empty($row2)) {
2366 break;
2368 $odd_row = ! $odd_row;
2370 } else {
2371 $user_form .= ' <tr class="odd">' . "\n"
2372 . ' <td colspan="6">' . "\n"
2373 . ' ' . __('No user found.') . "\n"
2374 . ' </td>' . "\n"
2375 . ' </tr>' . "\n";
2377 $user_form .= '</tbody>' . "\n"
2378 . '</table></form>' . "\n";
2380 if ($GLOBALS['is_ajax_request'] == true) {
2381 $extra_data['user_form'] = $user_form;
2382 $message = PMA_Message::success(__('User has been added.'));
2383 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
2384 } else {
2385 // Offer to create a new user for the current database
2386 $user_form .= '<fieldset id="fieldset_add_user">' . "\n"
2387 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1&amp;dbname=' . htmlspecialchars($checkprivs) .'" val="'.'checkprivs='.htmlspecialchars($checkprivs). '&'.$GLOBALS['url_query'] . '" class="'.$conditional_class.'" name="db_specific">' . "\n"
2388 . PMA_getIcon('b_usradd.png')
2389 . ' ' . __('Add user') . '</a>' . "\n"
2390 . '</fieldset>' . "\n";
2391 echo $user_form ;
2394 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2398 * Displays the footer
2400 echo "\n\n";
2401 require './libraries/footer.inc.php';